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

/* eslint-disable prefer-promise-reject-errors */
import Skylink from '../../../index';
import MESSAGES from '../../../messages';
import logger from '../../../logger';
import PeerConnection from '../../index';
import {
  isEmptyArray, isAObj, isAString, isABoolean,
} from '../../../utils/helpers';
import buildRefreshConnectionResult from './buildRefreshConnectionResult';

const buildResult = (listOfPeers, refreshErrors, refreshSettings) => {
  const result = {};
  result.listOfPeers = listOfPeers;
  result.refreshErrors = refreshErrors;
  result.refreshSettings = refreshSettings;

  return result;
};

const buildPeerRefreshSettings = (listOfPeers, room, doIceRestart) => {
  const refreshSettings = [];

  Object.keys(listOfPeers).forEach((i) => {
    refreshSettings.push(buildRefreshConnectionResult(listOfPeers[i], room, doIceRestart));
  });

  return refreshSettings;
};

const buildPeerRefreshErrors = (peerId, errors) => {
  const peerRefreshError = {};
  peerRefreshError[peerId] = errors;

  return peerRefreshError;
};

const filterParams = (targetPeerId, iceRestart, options, peerConnections) => {
  let doIceRestart = false;
  let bwOptions = {};
  let listOfPeers = Object.keys(peerConnections);

  if (Array.isArray(targetPeerId)) {
    listOfPeers = targetPeerId;
  } else if (isAString(targetPeerId)) {
    listOfPeers = [targetPeerId];
  } else if (isABoolean(targetPeerId)) {
    doIceRestart = targetPeerId;
  } else if (targetPeerId && isAObj(targetPeerId)) {
    bwOptions = targetPeerId;
  }

  if (isABoolean(iceRestart)) {
    doIceRestart = iceRestart;
  } else if (iceRestart && isAObj(iceRestart)) {
    bwOptions = iceRestart;
  }

  if (options && isAObj(options)) {
    bwOptions = options;
  }

  return {
    listOfPeers,
    doIceRestart,
    bwOptions,
  };
};

/**
 * Function that refreshes Peer connections to update with the current streaming.
 * @param {SkylinkState} roomState
 * @param {String} targetPeerId
 * @param {boolean} iceRestart
 * @param {Object} options
 * @param {Object} options.andwidth
 * @param {Object} options.googleXBandwidth
 * @return {Promise}
 * @memberOf PeerConnection
 */
const refreshConnection = (roomState, targetPeerId, iceRestart, options) => new Promise((resolve, reject) => {
  if (!roomState) {
    reject(new Error(MESSAGES.ROOM_STATE.NO_ROOM_NAME));
  }

  const { peerConnections, hasMCU, room } = roomState;
  const initOptions = Skylink.getInitOptions();
  const { mcuUseRenegoRestart } = initOptions;
  const { PEER_CONNECTION } = MESSAGES;
  const params = filterParams(targetPeerId, iceRestart, options, peerConnections);
  const { listOfPeers, doIceRestart, bwOptions } = params;

  try {
    if (isEmptyArray(listOfPeers) && !(hasMCU && !mcuUseRenegoRestart)) {
      logger.log.ERROR(PEER_CONNECTION.refresh_no_peer_connection);
      reject({
        refreshErrors: { self: PEER_CONNECTION.refresh_no_peer_connection },
        listOfPeers,
      });
    }

    logger.log.INFO([null, 'PeerConnection', null, PEER_CONNECTION.refresh_start]);

    const refreshPeerConnectionPromises = PeerConnection.refreshPeerConnection(listOfPeers, roomState, doIceRestart, bwOptions);
    refreshPeerConnectionPromises
      .then((results) => {
        const mResults = hasMCU ? [results] : results;
        const refreshErrors = [];
        for (let i = 0; i < mResults.length; i += 1) {
          if (Array.isArray(mResults[i])) {
            const error = mResults[i];
            refreshErrors.push(buildPeerRefreshErrors(error[0], error[1]));
            logger.log.WARN([listOfPeers, 'PeerConnection', null, PEER_CONNECTION.refresh_peer_failed], error[0]);
          } else if (typeof mResults[i] === 'string') {
            logger.log.INFO([listOfPeers, 'PeerConnection', null, PEER_CONNECTION.refresh_peer_success], mResults[i]);
          }
        }

        if (refreshErrors.length === listOfPeers.length) {
          reject(buildResult(listOfPeers, refreshErrors, buildPeerRefreshSettings(listOfPeers, room, doIceRestart)));
        } else {
          resolve(buildResult(listOfPeers, refreshErrors, buildPeerRefreshSettings(listOfPeers, room, doIceRestart)));
        }
      })
      .catch(error => logger.log.ERROR([null, 'RTCPeerConnection', null, PEER_CONNECTION.refresh_failed], error))
      .finally(() => logger.log.INFO(PEER_CONNECTION.refresh_completed));
  } catch (error) {
    reject(error);
  }
});

export default refreshConnection;