async run()

in src/task/JoinAndReceiveIndexTask.ts [43:163]


  async run(): Promise<void> {
    const indexFrame = await new Promise<SdkIndexFrame>((resolve, reject) => {
      const context = this.context;
      context.turnCredentials = null;
      class IndexFrameInterceptor implements SignalingClientObserver, TaskCanceler {
        constructor(private signalingClient: SignalingClient) {}

        cancel(): void {
          this.signalingClient.removeObserver(this);
          reject(new Error(`JoinAndReceiveIndexTask got canceled while waiting for SdkIndexFrame`));
        }

        handleSignalingClientEvent(event: SignalingClientEvent): void {
          if (event.type === SignalingClientEventType.WebSocketClosed) {
            let message = `The signaling connection was closed with code ${event.closeCode} and reason: ${event.closeReason}`;
            context.logger.warn(message);

            let statusCode: MeetingSessionStatusCode = MeetingSessionStatusCode.SignalingBadRequest;
            if (event.closeCode === 4410) {
              message = 'The meeting already ended.';
              context.logger.warn(message);
              statusCode = MeetingSessionStatusCode.MeetingEnded;
            } else if (event.closeCode >= 4500 && event.closeCode < 4600) {
              statusCode = MeetingSessionStatusCode.SignalingInternalServerError;
            }
            context.audioVideoController.handleMeetingSessionStatus(
              new MeetingSessionStatus(statusCode),
              new Error(message)
            );
            return;
          }
          if (event.type !== SignalingClientEventType.ReceivedSignalFrame) {
            return;
          }
          if (event.message.type === SdkSignalFrame.Type.JOIN_ACK) {
            // @ts-ignore: force cast to SdkJoinAckFrame
            const joinAckFrame: SdkJoinAckFrame = event.message.joinack;
            if (!joinAckFrame) {
              // This should realistically never happen
              context.audioVideoController.handleMeetingSessionStatus(
                new MeetingSessionStatus(MeetingSessionStatusCode.SignalingRequestFailed),
                new Error(`Join ACK message did not include expected frame`)
              );
              return;
            }
            if (joinAckFrame.videoSubscriptionLimit) {
              context.videoSubscriptionLimit = joinAckFrame.videoSubscriptionLimit;
            }

            context.serverSupportsCompression = joinAckFrame.wantsCompressedSdp;
            if (
              joinAckFrame.defaultServerSideNetworkAdaption !== undefined &&
              joinAckFrame.defaultServerSideNetworkAdaption !== ServerSideNetworkAdaption.Default &&
              context.videoDownlinkBandwidthPolicy.setServerSideNetworkAdaption !== undefined
            ) {
              const defaultServerSideNetworkAdaption: SdkServerSideNetworkAdaption =
                joinAckFrame.defaultServerSideNetworkAdaption;
              context.logger.info(
                `Overriding server side network adaption value to ${defaultServerSideNetworkAdaption}`
              );
              context.videoDownlinkBandwidthPolicy.setServerSideNetworkAdaption(
                convertServerSideNetworkAdaptionEnumFromSignaled(defaultServerSideNetworkAdaption)
              );
            }
            if (joinAckFrame && joinAckFrame.turnCredentials) {
              context.turnCredentials = new MeetingSessionTURNCredentials();
              context.turnCredentials.username = joinAckFrame.turnCredentials.username;
              context.turnCredentials.password = joinAckFrame.turnCredentials.password;
              context.turnCredentials.ttl = joinAckFrame.turnCredentials.ttl;
              context.turnCredentials.uris = joinAckFrame.turnCredentials.uris
                .map((uri: string): string => {
                  return context.meetingSessionConfiguration.urls.urlRewriter(uri);
                })
                .filter((uri: string) => {
                  return !!uri;
                });
            } else {
              context.logger.error('missing TURN credentials in JoinAckFrame');
            }
            return;
          }
          if (event.message.type !== SdkSignalFrame.Type.INDEX) {
            return;
          }
          this.signalingClient.removeObserver(this);
          // @ts-ignore: force cast to SdkIndexFrame
          const indexFrame: SdkIndexFrame = event.message.index;
          resolve(indexFrame);
        }
      }
      const interceptor = new IndexFrameInterceptor(this.context.signalingClient);
      this.context.signalingClient.registerObserver(interceptor);
      this.taskCanceler = interceptor;

      // reset SDP compression state
      this.context.previousSdpAnswerAsString = '';
      this.context.previousSdpOffer = null;
      this.context.serverSupportsCompression = false;

      const join = new SignalingClientJoin(
        this.context.meetingSessionConfiguration.applicationMetadata
      );
      if (
        this.context.videoDownlinkBandwidthPolicy.getServerSideNetworkAdaption !== undefined &&
        this.context.videoDownlinkBandwidthPolicy.supportedServerSideNetworkAdaptions !== undefined
      ) {
        join.serverSideNetworkAdaption = this.context.videoDownlinkBandwidthPolicy.getServerSideNetworkAdaption();
        join.supportedServerSideNetworkAdaptions = this.context.videoDownlinkBandwidthPolicy.supportedServerSideNetworkAdaptions();
      }
      if (this.context.videoDownlinkBandwidthPolicy.wantsAllTemporalLayersInIndex !== undefined) {
        join.wantsAllTemporalLayersInIndex = this.context.videoDownlinkBandwidthPolicy.wantsAllTemporalLayersInIndex();
      }
      join.disablePeriodicKeyframeRequestOnContentSender = this.context.meetingSessionConfiguration.disablePeriodicKeyframeRequestOnContentSender;
      this.context.signalingClient.join(join);
    });
    this.context.logger.info(`received first index ${JSON.stringify(indexFrame)}`);
    // We currently don't bother ingesting this into the same places as `ReceiveVideoStreamIndexTask` as we synchronously attempt a first subscribe
    // after this task completes and the state isn't quite in the right place to make it work without some refactoring. However that
    // means that we will always have an initial subscribe without any received videos.
    this.context.indexFrame = indexFrame;
  }