Skip to content
Snippets Groups Projects
webrtc.js 4.51 KiB
Newer Older
lazorfuzz's avatar
lazorfuzz committed
import util from 'util';
import mockconsole from 'mockconsole';
import LocalMedia from './localmedia';
lazorfuzz's avatar
lazorfuzz committed
import Peer from './peer';
import webrtcSupport from './webrtcsupport';

class WebRTC extends LocalMedia {
lazorfuzz's avatar
lazorfuzz committed
  constructor(opts) {
lazorfuzz's avatar
lazorfuzz committed
    const self = this;
    const options = opts || {};
    const config = this.config = {
      debug: false,
      peerConnectionConfig: {
lazorfuzz's avatar
lazorfuzz committed
      },
      peerConnectionConstraints: {
lazorfuzz's avatar
lazorfuzz committed
      },
      receiveMedia: {
        offerToReceiveAudio: 1,
        offerToReceiveVideo: 1,
lazorfuzz's avatar
lazorfuzz committed
      },
      enableDataChannels: true,
lazorfuzz's avatar
lazorfuzz committed
    };
    let item;

    this.logger = ((() => {
      // we assume that if you're in debug mode and you didn't
      // pass in a logger, you actually want to log as much as
      // possible.
lazorfuzz's avatar
lazorfuzz committed
      if (opts.debug) {
        return opts.logger || console;
      }
      // or we'll use your logger which should have its own logic
      // for output. Or we'll return the no-op.
lazorfuzz's avatar
lazorfuzz committed
      return opts.logger || mockconsole;
    })());

lazorfuzz's avatar
lazorfuzz committed
    for (item in options) {
      if (options.hasOwnProperty(item)) {
        this.config[item] = options[item];
      }
    }

lazorfuzz's avatar
lazorfuzz committed
    if (!webrtcSupport.support) {
      this.logger.error('Your browser doesn\'t seem to support WebRTC');
    }

    // where we'll store our peer connections
lazorfuzz's avatar
lazorfuzz committed
    this.peers = [];

    // call localMedia constructor
    // localMedia.call(this, this.config);
lazorfuzz's avatar
lazorfuzz committed

    this.on('speaking', () => {
      if (!self.hardMuted) {
        self.peers.forEach((peer) => {
          if (peer.enableDataChannels) {
            const dc = peer.getDataChannel('liowebrtc');
            if (dc.readyState !== 'open') return;
            dc.sendDirectlyToAll({ type: 'speaking' });
lazorfuzz's avatar
lazorfuzz committed
          }
        });
      }
    });
    this.on('stoppedSpeaking', () => {
      if (!self.hardMuted) {
        self.peers.forEach((peer) => {
          if (peer.enableDataChannels) {
            const dc = peer.getDataChannel('liowebrtc');
            if (dc.readyState !== 'open') return;
            dc.sendDirectlyToAll({ type: 'stoppedSpeaking' });
lazorfuzz's avatar
lazorfuzz committed
          }
        });
      }
    });
    this.on('volumeChange', (volume, treshold) => {
      if (!self.hardMuted) {
        self.peers.forEach((peer) => {
          if (peer.enableDataChannels) {
            const dc = peer.getDataChannel('liowebrtc');
            if (dc.readyState !== 'open') return;
            dc.sendDirectlyToAll({ type: 'payload', volume });
lazorfuzz's avatar
lazorfuzz committed
          }
        });
      }
    });

    // log events in debug mode
lazorfuzz's avatar
lazorfuzz committed
    if (this.config.debug) {
      this.on('*', (event, val1, val2) => {
        let logger;
        // if you didn't pass in a logger and you explicitly turning on debug
        // we're just going to assume you're wanting log output with console
lazorfuzz's avatar
lazorfuzz committed
        if (self.config.logger === mockconsole) {
          logger = console;
        } else {
          logger = self.logger;
        }
        logger.log('event:', event, val1, val2);
      });
    }
  }

  createPeer(opts) {
    let peer;
    opts.parent = this;
    peer = new Peer(opts);
    this.peers.push(peer);
    return peer;
  }

  // removes peers
  removePeers(id, type) {
    this.getPeers(id, type).forEach((peer) => {
      peer.end();
    });
  }

  // fetches all Peer objects by session id and/or type
  getPeers(sessionId, type) {
    return this.peers.filter(peer => (!sessionId || peer.id === sessionId) && (!type || peer.type === type));
lazorfuzz's avatar
lazorfuzz committed
  }

  getPeerById(id) {
    return this.peers.filter(p => p.id === id)[0];
  }

  getPeerByNick(nick) {
    return this.peers.filter(p => p.nick === nick)[0];
  }

lazorfuzz's avatar
lazorfuzz committed
  // sends message to all
  sendToAll(message, payload) {
    this.peers.forEach((peer) => {
      peer.send(message, payload);
    });
  }

  // sends message to all using a datachannel
  // only sends to anyone who has an open datachannel
lazorfuzz's avatar
lazorfuzz committed
  sendDirectlyToAll(message, payload, channel, shout) {
    const msgId = `${Date.now()}_${Math.random() * 1000000}`;
lazorfuzz's avatar
lazorfuzz committed
    this.peers.forEach((peer) => {
      if (peer.enableDataChannels) {
lazorfuzz's avatar
lazorfuzz committed
        peer.sendDirectly(message, payload, channel, shout, msgId);
lazorfuzz's avatar
lazorfuzz committed
      }
    });
  }
lazorfuzz's avatar
lazorfuzz committed
  shout(messageType, payload) {
lazorfuzz's avatar
lazorfuzz committed
    this.sendDirectlyToAll(messageType, payload, 'liowebrtc', true);
lazorfuzz's avatar
lazorfuzz committed
  whisper(peer, messageType, payload) {
    peer.sendDirectly(messageType, payload);
  }

  broadcast(messageType, payload) {
    this.sendToAll('signalData', { type: messageType, payload });

  transmit(peer, messageType, payload) {
    peer.send('signalData', { type: messageType, payload });
  }
lazorfuzz's avatar
lazorfuzz committed
}

export default WebRTC;