peer-connection/helpers/refresh-connection/restartPeerConnection.js

import Skylink from '../../..';
import logger from '../../../logger';
import { PEER_CONNECTION_STATE } from '../../../constants';
import SkylinkSignalingServer from '../../../server-communication/signaling-server';
import messages from '../../../messages';
import sendRestartOfferMsg from './sendRestartOfferMsg';

/**
 * Function that sends restart message to the signaling server.
 * @param {String} peerId
 * @param {SkylinkState} roomState
 * @param {Object} options
 * @param {Object} options.bandwidth
 * @param {Object} options.googleXBandwidth
 * @return {Promise}
 * @memberOf PeerConnection.PeerConnectionHelpers
 */
const restartPeerConnection = (peerId, roomState, options) => {
  const state = Skylink.getSkylinkState(roomState.room.id);
  const { AdapterJS } = window;
  const {
    peerConnections, peerCustomConfigs, peerEndOfCandidatesCounter, room, user,
  } = state;
  const { doIceRestart, bwOptions } = options;
  const signaling = new SkylinkSignalingServer();
  const { PEER_CONNECTION } = messages;
  const errors = [];

  return new Promise((resolve) => {
    // reject with wrong peerId
    if (!peerConnections[peerId]) {
      logger.log.ERROR([peerId, null, null, PEER_CONNECTION.refresh_peerId_no_match]);
      errors.push(PEER_CONNECTION.refresh_peerId_no_match);
      return resolve([peerId, errors]);
    }

    const peerConnection = peerConnections[peerId];
    // refresh not supported in edge
    if (AdapterJS.webrtcDetectedBrowser === 'edge') {
      logger.log.WARN([peerId, 'RTCPeerConnection', null, PEER_CONNECTION.refresh_not_supported]);
      errors.push(PEER_CONNECTION.refresh_no_edge_support);
    }

    if (errors.length !== 0) {
      return resolve([peerId, errors]);
    }

    // Let's check if the signalingState is stable first.
    // In another galaxy or universe, where the local description gets dropped..
    // In the offerHandler or answerHandler, do the appropriate flags to ignore or drop "extra" descriptions
    if (peerConnection.signalingState === PEER_CONNECTION_STATE.STABLE) {
      logger.log.INFO([peerId, null, null, 'Sending restart message to signaling server ->'], {
        iceRestart: doIceRestart,
        options: bwOptions,
      });

      peerCustomConfigs[peerId] = peerCustomConfigs[peerId] || {};
      peerCustomConfigs[peerId].bandwidth = peerCustomConfigs[peerId].bandwidth || {};
      peerCustomConfigs[peerId].googleXBandwidth = peerCustomConfigs[peerId].googleXBandwidth || {};

      if (bwOptions.bandwidth && typeof bwOptions.bandwidth === 'object') {
        if (typeof bwOptions.bandwidth.audio === 'number') {
          peerCustomConfigs[peerId].bandwidth.audio = bwOptions.bandwidth.audio;
        }
        if (typeof bwOptions.bandwidth.video === 'number') {
          peerCustomConfigs[peerId].bandwidth.video = bwOptions.bandwidth.video;
        }
        if (typeof bwOptions.bandwidth.data === 'number') {
          peerCustomConfigs[peerId].bandwidth.data = bwOptions.bandwidth.data;
        }
      }

      if (bwOptions.googleXBandwidth && typeof bwOptions.googleXBandwidth === 'object') {
        if (typeof bwOptions.googleXBandwidth.min === 'number') {
          peerCustomConfigs[peerId].googleXBandwidth.min = bwOptions.googleXBandwidth.min;
        }
        if (typeof bwOptions.googleXBandwidth.max === 'number') {
          peerCustomConfigs[peerId].googleXBandwidth.max = bwOptions.googleXBandwidth.max;
        }
      }

      peerEndOfCandidatesCounter[peerId] = peerEndOfCandidatesCounter[peerId] || {};
      peerEndOfCandidatesCounter[peerId].len = 0;

      return resolve(sendRestartOfferMsg(state, peerId, doIceRestart));
    }

    // Checks if the local description is defined first
    const hasLocalDescription = peerConnection.localDescription && peerConnection.localDescription.sdp;
    // This is when the state is stable and re-handshaking is possible
    // This could be due to previous connection handshaking that is already done
    if (peerConnection.signalingState === PEER_CONNECTION_STATE.HAVE_LOCAL_OFFER && hasLocalDescription) {
      signaling.sendMessage({
        type: peerConnection.localDescription.type,
        sdp: peerConnection.localDescription.sdp,
        mid: user.sid,
        target: peerId,
        rid: room.id,
        restart: true,
      });
      return resolve(peerId);
    }

    const unableToRestartError = `Failed restarting as peer connection state is ${peerConnection.signalingState} and there is no localDescription set to connection. There could be a handshaking step error.`;
    logger.log.DEBUG([peerId, 'RTCPeerConnection', null, unableToRestartError], {
      localDescription: peerConnection.localDescription,
      remoteDescription: peerConnection.remoteDescription,
    });
    errors.push(unableToRestartError);

    resolve([peerId, errors]);

    return null;
  });
};

export default restartPeerConnection;