peer-calls/src/client/actions/PeerActions.js
2017-06-17 23:14:26 -04:00

129 lines
3.7 KiB
JavaScript

import * as NotifyActions from '../actions/NotifyActions.js'
import * as StreamActions from '../actions/StreamActions.js'
import * as constants from '../constants.js'
import Peer from 'simple-peer'
import _ from 'underscore'
import _debug from 'debug'
import { play, iceServers } from '../window.js'
const debug = _debug('peercalls')
class PeerHandler {
constructor ({ socket, user, stream, dispatch, getState }) {
this.socket = socket
this.user = user
this.stream = stream
this.dispatch = dispatch
this.getState = getState
}
handleError = err => {
const { dispatch, getState, user } = this
debug('peer: %s, error %s', user.id, err.stack)
dispatch(NotifyActions.error('A peer connection error occurred'))
const peer = getState().peers[user.id]
peer && peer.destroy()
dispatch(removePeer(user.id))
}
handleSignal = signal => {
const { socket, user } = this
debug('peer: %s, signal: %o', user.id, signal)
const payload = { userId: user.id, signal }
socket.emit('signal', payload)
}
handleConnect = () => {
const { dispatch, user } = this
debug('peer: %s, connect', user.id)
dispatch(NotifyActions.warning('Peer connection established'))
play()
}
handleStream = stream => {
const { user, dispatch } = this
debug('peer: %s, stream', user.id)
dispatch(StreamActions.addStream({
userId: user.id,
stream
}))
}
handleData = object => {
const { dispatch, user } = this
object = JSON.parse(new window.TextDecoder('utf-8').decode(object))
debug('peer: %s, message: %o', user.id, object)
const message = user.id + ': ' + object.message
dispatch(NotifyActions.info(message))
}
handleClose = () => {
const { dispatch, user } = this
debug('peer: %s, close', user.id)
dispatch(NotifyActions.error('Peer connection closed'))
dispatch(StreamActions.removeStream(user.id))
dispatch(removePeer(user.id))
}
}
/**
* @param {Object} options
* @param {Socket} options.socket
* @param {User} options.user
* @param {String} options.user.id
* @param {Boolean} [options.initiator=false]
* @param {MediaStream} [options.stream]
*/
export function createPeer ({ socket, user, initiator, stream }) {
return (dispatch, getState) => {
const userId = user.id
debug('create peer: %s, stream:', userId, stream)
dispatch(NotifyActions.warning('Connecting to peer...'))
const oldPeer = getState().peers[userId]
if (oldPeer) {
dispatch(NotifyActions.info('Cleaning up old connection...'))
oldPeer.destroy()
dispatch(removePeer(userId))
}
const peer = new Peer({
initiator: socket.id === initiator,
stream,
config: { iceServers }
})
const handler = new PeerHandler({
socket,
user,
stream,
dispatch,
getState
})
peer.once(constants.PEER_EVENT_ERROR, handler.handleError)
peer.once(constants.PEER_EVENT_CONNECT, handler.handleConnect)
peer.once(constants.PEER_EVENT_CLOSE, handler.handleClose)
peer.on(constants.PEER_EVENT_SIGNAL, handler.handleSignal)
peer.on(constants.PEER_EVENT_STREAM, handler.handleStream)
peer.on(constants.PEER_EVENT_DATA, handler.handleData)
dispatch(addPeer({ peer, userId }))
}
}
export const addPeer = ({ peer, userId }) => ({
type: constants.PEER_ADD,
payload: { peer, userId }
})
export const removePeer = userId => ({
type: constants.PEER_REMOVE,
payload: { userId }
})
export const destroyPeers = () => ({
type: constants.PEERS_DESTROY
})
export const sendMessage = message => (dispatch, getState) => {
message = JSON.stringify({ message })
const { peers } = getState()
_.each(peers, peer => peer.send(message))
}