peer-connection/helpers/data-channel/sendP2PMessage.js

import Skylink from '../../../index';
import logger from '../../../logger';
import sendMessageToDataChannel from './sendMessageToDataChannel';
import { DC_PROTOCOL_TYPE, PEER_TYPE } from '../../../constants';
import { onIncomingMessage } from '../../../skylink-events';
import { dispatchEvent } from '../../../utils/skylinkEventManager';
import PeerData from '../../../peer-data';
import { getRoomStateByName } from '../../../utils/helpers';

/**
 * @param message
 * @param {String} targetPeerId
 * @param {SkylinkState} roomState
 * @returns {null}
 * @memberOf PeerConnection.PeerConnectionHelpers
 * @fires onIncomingMessage
 */
const sendP2PMessageForRoom = (roomState, message, targetPeerId) => {
  const initOptions = Skylink.getInitOptions();
  const {
    dataChannels,
    inRoom,
    user,
    hasMCU,
  } = roomState;

  let listOfPeers = Object.keys(dataChannels);
  let isPrivate = false;

  if (Array.isArray(targetPeerId) && targetPeerId.length) {
    listOfPeers = targetPeerId;
    isPrivate = true;
  } else if (targetPeerId && typeof targetPeerId === 'string') {
    listOfPeers = [targetPeerId];
    isPrivate = true;
  }

  if (!inRoom || !(user && user.sid)) {
    logger.log.ERROR('Unable to send message as User is not in Room. ->', message);
    return null;
  }

  if (!initOptions.enableDataChannel) {
    logger.log.ERROR('Unable to send message as User does not have DataChannel enabled. ->', message);
    return null;
  }

  // Loop out unwanted Peers
  for (let i = 0; i < listOfPeers.length; i += 1) {
    const peerId = listOfPeers[i];

    if (!dataChannels[peerId] && !hasMCU) {
      logger.log.ERROR([peerId, 'RTCDataChannel', null, 'Dropping of sending message to Peer as DataChannel connection does not exist.']);
      listOfPeers.splice(i, 1);
      i -= 1;
    } else if (peerId === PEER_TYPE.MCU) {
      listOfPeers.splice(i, 1);
      i -= 1;
    } else if (!hasMCU) {
      logger.log.DEBUG([peerId, 'RTCDataChannel', null, `Sending ${isPrivate ? 'private' : ''} P2P message to Peer.`]);

      sendMessageToDataChannel(roomState, peerId, {
        type: DC_PROTOCOL_TYPE.MESSAGE,
        isPrivate,
        sender: user.sid,
        target: targetPeerId ? peerId : null,
        data: message,
      }, 'main');
    }
  }

  if (listOfPeers.length === 0) {
    logger.log.WARN('Currently there are no Peers to send P2P message to.');
  }

  if (hasMCU) {
    logger.log.DEBUG([PEER_TYPE.MCU, 'RTCDataChannel', null, `Broadcasting ${isPrivate ? 'private' : ''} P2P message to Peers.`]);
    sendMessageToDataChannel(roomState, PEER_TYPE.MCU, {
      type: DC_PROTOCOL_TYPE.MESSAGE,
      isPrivate,
      sender: user.sid,
      target: listOfPeers,
      data: message,
    }, 'main');
  }

  if (targetPeerId || !hasMCU) {
    dispatchEvent(onIncomingMessage({
      room: roomState.room,
      message: {
        targetPeerId: targetPeerId || null,
        content: message,
        senderPeerId: user.sid,
        isDataChannel: true,
        isPrivate,
      },
      isSelf: true,
      peerId: user.sid,
      peerInfo: PeerData.getCurrentSessionInfo(roomState.room),
    }));
  }

  return null;
};

const sendP2PMessage = (roomName, message, targetPeerId) => {
  const roomState = getRoomStateByName(roomName);
  if (roomState) {
    sendP2PMessageForRoom(roomState, message, targetPeerId);
  } else {
    // Global P2P Message - Broadcast to all rooms
    const roomStates = Skylink.getSkylinkState();
    const roomKeys = Object.keys(roomStates);
    for (let i = 0; i < roomKeys.length; i += 1) {
      const state = roomStates[roomKeys[i]];
      sendP2PMessageForRoom(state, message, targetPeerId);
    }
  }
};


export default sendP2PMessage;