restructure realtime server for clarity (#780)

* restructure realtime server for clarity

* better indenting on signal.js

* don't need it because socketioconnection is being imported now
This commit is contained in:
Connor Turland 2016-10-18 20:29:21 -04:00 committed by GitHub
parent d8cd536a95
commit 139837e997
13 changed files with 387 additions and 4256 deletions

BIN
.env.swp

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -1,23 +0,0 @@
function SocketIoConnection(config) {
this.connection = io.connect(config.url, config.socketio);
}
SocketIoConnection.prototype.on = function (ev, fn) {
this.connection.on(ev, fn);
};
SocketIoConnection.prototype.emit = function () {
this.connection.emit.apply(this.connection, arguments);
};
SocketIoConnection.prototype.removeAllListeners = function () {
this.connection.removeAllListeners();
};
SocketIoConnection.prototype.getSessionid = function () {
return this.connection.socket.sessionid;
};
SocketIoConnection.prototype.disconnect = function () {
return this.connection.disconnect();
};

View file

@ -1,4 +1,4 @@
/* global Metamaps, $, SocketIoConnection */
/* global Metamaps, $ */
/*
* Metamaps.Realtime.js
@ -15,6 +15,7 @@
import _ from 'lodash'
import SimpleWebRTC from 'simplewebrtc'
import SocketIoConnection from 'simplewebrtc/socketioconnection'
import Active from '../Active'
import GlobalUI from '../GlobalUI'
@ -99,6 +100,7 @@ import {
leaveCall,
sendMapperInfo,
sendCoords,
createMessage,
dragTopic,
createTopic,
updateTopic,
@ -510,6 +512,7 @@ const sendables = [
['leaveCall',leaveCall],
['sendMapperInfo',sendMapperInfo],
['sendCoords',sendCoords],
['createMessage',createMessage],
['dragTopic',dragTopic],
['createTopic',createTopic],
['updateTopic',updateTopic],

View file

@ -40,7 +40,7 @@
"react-dom": "15.3.2",
"react-dropzone": "3.6.0",
"simplewebrtc": "2.2.0",
"socket.io": "0.9.12",
"socket.io": "1.3.7",
"underscore": "1.4.4",
"webpack": "1.13.2"
},

80
realtime/global.js Normal file
View file

@ -0,0 +1,80 @@
import {
// server sendable, client receivable
TOPIC_UPDATED,
TOPIC_DELETED,
SYNAPSE_UPDATED,
SYNAPSE_DELETED,
LIVE_MAPS_RECEIVED,
MAP_WENT_LIVE,
MAP_CEASED_LIVE,
MAP_UPDATED,
// server receivable, client sendable
REQUEST_LIVE_MAPS,
JOIN_MAP,
LEAVE_MAP,
UPDATE_TOPIC,
DELETE_TOPIC,
UPDATE_SYNAPSE,
DELETE_SYNAPSE,
UPDATE_MAP
} from '../frontend/src/Metamaps/Realtime/events'
const adjustAndBroadcast = (io, socket, state, event, data) => {
if (event === JOIN_MAP) {
if (!state.liveMaps[data.mapid]) {
state.liveMaps[data.mapid] = data.map // { name: '', desc: '', numTopics: '' }
state.liveMaps[data.mapid].mapper_count = 1
io.sockets.emit(MAP_WENT_LIVE, state.liveMaps[data.mapid])
}
else {
state.liveMaps[data.mapid].mapper_count++
}
}
else if (event === LEAVE_MAP) {
const mapid = socket.mapid
if (state.liveMaps[mapid] && state.liveMaps[mapid].mapper_count == 1) {
delete state.liveMaps[mapid]
io.sockets.emit(MAP_CEASED_LIVE, { id: mapid })
}
else if (state.liveMaps[mapid]) {
state.liveMaps[mapid].mapper_count--
}
}
}
module.exports = function (io, state) {
io.on('connection', function (socket) {
socket.on(REQUEST_LIVE_MAPS, function (activeUser) {
//constrain response to maps visible to user
var maps = Object.keys(state.liveMaps).map(function(key) { return state.liveMaps[key] })
socket.emit(LIVE_MAPS_RECEIVED, maps)
})
socket.on(JOIN_MAP, data => adjustAndBroadcast(io, socket, state, JOIN_MAP, data))
socket.on(LEAVE_MAP, () => adjustAndBroadcast(io, socket, state, LEAVE_MAP))
socket.on('disconnect', () => adjustAndBroadcast(io, socket, state, LEAVE_MAP))
socket.on(UPDATE_TOPIC, function (data) {
socket.broadcast.emit(TOPIC_UPDATED, data)
})
socket.on(DELETE_TOPIC, function (data) {
socket.broadcast.emit(TOPIC_DELETED, data)
})
socket.on(UPDATE_SYNAPSE, function (data) {
socket.broadcast.emit(SYNAPSE_UPDATED, data)
})
socket.on(DELETE_SYNAPSE, function (data) {
socket.broadcast.emit(SYNAPSE_DELETED, data)
})
socket.on(UPDATE_MAP, function (data) {
socket.broadcast.emit(MAP_UPDATED, data)
})
})
}

62
realtime/junto.js Normal file
View file

@ -0,0 +1,62 @@
import {
INVITED_TO_CALL,
INVITED_TO_JOIN,
CALL_ACCEPTED,
CALL_DENIED,
INVITE_DENIED,
CALL_IN_PROGRESS,
CALL_STARTED,
MAPPER_JOINED_CALL,
MAPPER_LEFT_CALL,
CHECK_FOR_CALL,
ACCEPT_CALL,
DENY_CALL,
DENY_INVITE,
INVITE_TO_JOIN,
INVITE_A_CALL,
JOIN_CALL,
LEAVE_CALL
} from '../frontend/src/Metamaps/Realtime/events'
const { mapRoom, userMapRoom } = require('./rooms')
module.exports = function (io, state) {
io.on('connection', function (socket) {
socket.on(CHECK_FOR_CALL, function (data) {
var callInProgress = Object.keys(io.nsps['/'].adapter.rooms[data.room] || {}).length
if (callInProgress) socket.emit(CALL_IN_PROGRESS)
})
socket.on(INVITE_A_CALL, function (data) {
socket.broadcast.in(userMapRoom(data.invited, data.mapid)).emit(INVITED_TO_CALL, data.inviter)
})
socket.on(INVITE_TO_JOIN, function (data) {
socket.broadcast.in(userMapRoom(data.invited, data.mapid)).emit(INVITED_TO_JOIN, data.inviter)
})
socket.on(ACCEPT_CALL, function (data) {
socket.broadcast.in(userMapRoom(data.inviter, data.mapid)).emit(CALL_ACCEPTED, data.invited)
socket.broadcast.in(mapRoom(data.mapid)).emit(CALL_STARTED)
})
socket.on(DENY_CALL, function (data) {
socket.broadcast.in(userMapRoom(data.inviter, data.mapid)).emit(CALL_DENIED, data.invited)
})
socket.on(DENY_INVITE, function (data) {
socket.broadcast.in(userMapRoom(data.inviter, data.mapid)).emit(INVITE_DENIED, data.invited)
})
socket.on(JOIN_CALL, function (data) {
socket.broadcast.in(mapRoom(data.mapid)).emit(MAPPER_JOINED_CALL, data.id)
})
socket.on(LEAVE_CALL, function (data) {
socket.broadcast.in(mapRoom(data.mapid)).emit(MAPPER_LEFT_CALL, data.id)
})
})
}

115
realtime/map.js Normal file
View file

@ -0,0 +1,115 @@
import {
MAPPER_LIST_UPDATED,
NEW_MAPPER,
LOST_MAPPER,
MESSAGE_CREATED,
TOPIC_DRAGGED,
TOPIC_CREATED,
TOPIC_REMOVED,
SYNAPSE_CREATED,
SYNAPSE_REMOVED,
PEER_COORDS_UPDATED,
JOIN_MAP,
LEAVE_MAP,
SEND_MAPPER_INFO,
SEND_COORDS,
CREATE_MESSAGE,
DRAG_TOPIC,
CREATE_TOPIC,
REMOVE_TOPIC,
CREATE_SYNAPSE,
REMOVE_SYNAPSE
} from '../frontend/src/Metamaps/Realtime/events'
const { mapRoom, userMapRoom } = require('./rooms')
module.exports = function (io, state) {
io.on('connection', function (socket) {
// this will ping everyone on a map that there's a person just joined the map
socket.on(JOIN_MAP, function (data) {
socket.mapid = data.mapid
socket.userid = data.userid
socket.username = data.username
socket.userimage = data.userimage
var newUser = {
userid: data.userid,
username: data.username,
userimage: data.userimage
}
socket.join(mapRoom(data.mapid))
socket.join(userMapRoom(data.userid, data.mapid))
socket.broadcast.in(mapRoom(data.mapid)).emit(NEW_MAPPER, newUser)
})
const leaveMap = () => {
var data = {
username: socket.username,
userid: socket.userid
}
socket.leave(mapRoom(socket.mapid))
socket.leave(userMapRoom(socket.userid, socket.mapid))
socket.broadcast.in(mapRoom(socket.mapid)).emit(LOST_MAPPER, data)
socket.mapid = null
}
socket.on(LEAVE_MAP, leaveMap)
socket.on('disconnect', leaveMap)
// this will ping a new person with awareness of who's already on the map
socket.on(SEND_MAPPER_INFO, function (data) {
var existingUser = {
userid: data.userid,
username: data.username,
userinconversation: data.userinconversation,
userimage: data.userimage
}
socket.broadcast.in(userMapRoom(data.userToNotify, data.mapid)).emit(MAPPER_LIST_UPDATED, existingUser)
})
socket.on(SEND_COORDS, function (data) {
var peer = {
userid: data.userid,
usercoords: data.usercoords
}
socket.broadcast.in(mapRoom(data.mapid)).emit(PEER_COORDS_UPDATED, peer)
})
socket.on(CREATE_MESSAGE, function (data) {
var mapId = data.mapid
delete data.mapid
socket.broadcast.in(mapRoom(mapId)).emit(MESSAGE_CREATED, data)
})
socket.on(DRAG_TOPIC, function (data) {
var mapId = data.mapid
delete data.mapid
socket.broadcast.in(mapRoom(mapId)).emit(TOPIC_DRAGGED, data)
})
socket.on(CREATE_TOPIC, function (data) {
var mapId = data.mapid
delete data.mapid
socket.broadcast.in(mapRoom(mapId)).emit(TOPIC_CREATED, data)
})
socket.on(REMOVE_TOPIC, function (data) {
var mapId = data.mapid
delete data.mapid
socket.broadcast.in(mapRoom(mapId)).emit(TOPIC_REMOVED, data)
})
socket.on(CREATE_SYNAPSE, function (data) {
var mapId = data.mapid
delete data.mapid
socket.broadcast.in(mapRoom(mapId)).emit(SYNAPSE_CREATED, data)
})
socket.on(REMOVE_SYNAPSE, function (data) {
var mapId = data.mapid
delete data.mapid
socket.broadcast.in(mapRoom(mapId)).emit(SYNAPSE_REMOVED, data)
})
})
}

View file

@ -1,267 +1,18 @@
var
io = require('socket.io').listen(5001),
signalServer = require('./signal'),
io = require('socket.io')(),
signalling = require('./signal'),
junto = require('./junto'),
map = require('./map'),
global = require('./global'),
stunservers = [{"url": "stun:stun.l.google.com:19302"}]
import {
// server sendable, client receivable
INVITED_TO_CALL,
INVITED_TO_JOIN,
CALL_ACCEPTED,
CALL_DENIED,
INVITE_DENIED,
CALL_IN_PROGRESS,
CALL_STARTED,
MAPPER_JOINED_CALL,
MAPPER_LEFT_CALL,
MAPPER_LIST_UPDATED,
NEW_MAPPER,
LOST_MAPPER,
MESSAGE_CREATED,
TOPIC_DRAGGED,
TOPIC_CREATED,
TOPIC_UPDATED,
TOPIC_REMOVED,
TOPIC_DELETED,
SYNAPSE_CREATED,
SYNAPSE_UPDATED,
SYNAPSE_REMOVED,
SYNAPSE_DELETED,
PEER_COORDS_UPDATED,
LIVE_MAPS_RECEIVED,
MAP_WENT_LIVE,
MAP_CEASED_LIVE,
MAP_UPDATED,
// server receivable, client sendable
REQUEST_LIVE_MAPS,
JOIN_MAP,
LEAVE_MAP,
CHECK_FOR_CALL,
ACCEPT_CALL,
DENY_CALL,
DENY_INVITE,
INVITE_TO_JOIN,
INVITE_A_CALL,
JOIN_CALL,
LEAVE_CALL,
REQUEST_MAPPER_INFO,
SEND_MAPPER_INFO,
SEND_COORDS,
CREATE_MESSAGE,
DRAG_TOPIC,
CREATE_TOPIC,
UPDATE_TOPIC,
REMOVE_TOPIC,
DELETE_TOPIC,
CREATE_SYNAPSE,
UPDATE_SYNAPSE,
REMOVE_SYNAPSE,
DELETE_SYNAPSE,
UPDATE_MAP
} from '../frontend/src/Metamaps/Realtime/events'
io.set('log', false)
function start() {
var livemaps = {}
signalServer(io, stunservers)
io.on('connection', function (socket) {
socket.on(REQUEST_LIVE_MAPS, function (activeUser) {
//constrain response to maps visible to user
var maps = Object.keys(livemaps).map(function(key) { return livemaps[key] })
socket.emit(LIVE_MAPS_RECEIVED, maps)
})
// this will ping a new person with awareness of who's already on the map
socket.on(SEND_MAPPER_INFO, function (data) {
var existingUser = {
userid: data.userid,
username: data.username,
userrealtime: data.userrealtime,
userinconversation: data.userinconversation,
userimage: data.userimage
var state = {
connectedPeople: {},
liveMaps: {}
}
//socket.broadcast.emit(data.userToNotify + '-' + data.mapid + '-UpdateMapperList', existingUser)
socket.broadcast.emit(MAPPER_LIST_UPDATED, existingUser)
})
signalling(io, stunservers, state)
junto(io, state)
map(io, state)
global(io, state)
io.listen(5001)
// as a new mapper check whether there's a call in progress to join
socket.on(CHECK_FOR_CALL, function (data) {
var socketsInRoom = io.sockets.clients(data.room)
//if (socketsInRoom.length) socket.emit('maps-' + data.mapid + '-callInProgress')
if (socketsInRoom.length) socket.emit(CALL_IN_PROGRESS)
})
// send the invitation to start a call
socket.on(INVITE_A_CALL, function (data) {
//socket.broadcast.emit(data.invited + '-' + data.mapid + '-invitedToCall', data.inviter)
socket.broadcast.emit(INVITED_TO_CALL, data.inviter)
})
// send an invitation to join a call in progress
socket.on(INVITE_TO_JOIN, function (data) {
//socket.broadcast.emit(data.invited + '-' + data.mapid + '-invitedToJoin', data.inviter)
socket.broadcast.emit(INVITED_TO_JOIN, data.inviter)
})
// send response back to the inviter
socket.on(ACCEPT_CALL, function (data) {
//socket.broadcast.emit(data.inviter + '-' + data.mapid + '-callAccepted', data.invited)
//socket.broadcast.emit('maps-' + data.mapid + '-callStarting')
socket.broadcast.emit(CALL_ACCEPTED, data.invited)
socket.broadcast.emit(CALL_STARTED)
})
socket.on(DENY_CALL, function (data) {
//socket.broadcast.emit(data.inviter + '-' + data.mapid + '-callDenied', data.invited)
socket.broadcast.emit(CALL_DENIED, data.invited)
})
socket.on(DENY_INVITE, function (data) {
//socket.broadcast.emit(data.inviter + '-' + data.mapid + '-inviteDenied', data.invited)
socket.broadcast.emit(INVITE_DENIED, data.invited)
})
socket.on(JOIN_CALL, function (data) {
//socket.broadcast.emit('maps-' + data.mapid + '-mapperJoinedCall', data.id)
socket.broadcast.emit(MAPPER_JOINED_CALL, data.id)
})
socket.on(LEAVE_CALL, function (data) {
//socket.broadcast.emit('maps-' + data.mapid + '-mapperLeftCall', data.id)
socket.broadcast.emit(MAPPER_LEFT_CALL, data.id)
})
// this will ping everyone on a map that there's a person just joined the map
socket.on(JOIN_MAP, function (data) {
if (!livemaps[data.mapid]) {
livemaps[data.mapid] = data.map // { name: '', desc: '', numTopics: '' }
livemaps[data.mapid].mapper_count = 1
io.sockets.emit(MAP_WENT_LIVE, livemaps[data.mapid])
}
else {
livemaps[data.mapid].mapper_count++
}
socket.set('mapid', data.mapid)
socket.set('userid', data.userid)
socket.set('username', data.username)
var newUser = {
userid: data.userid,
username: data.username,
userimage: data.userimage
}
//socket.broadcast.emit('maps-' + data.mapid + '-newmapper', newUser)
socket.broadcast.emit(NEW_MAPPER, newUser)
})
var end = function () {
var socketUserName, socketUserID
socket.get('userid', function (err, id) {
socketUserID = id
})
socket.get('username', function (err, name) {
socketUserName = name
})
var data = {
username: socketUserName,
userid: socketUserID
}
socket.get('mapid', function (err, mapid) {
if (livemaps[mapid] && livemaps[mapid].mapper_count == 1) {
delete livemaps[mapid]
io.sockets.emit(MAP_CEASED_LIVE, { id: mapid })
}
else if (livemaps[mapid]) {
livemaps[mapid].mapper_count--
}
// scope by map
socket.broadcast.emit(LOST_MAPPER, data)
})
}
// this will ping everyone on a map that there's a person just left the map
socket.on('disconnect', end)
socket.on(LEAVE_MAP, end)
socket.on(SEND_COORDS, function (data) {
var peer = {
userid: data.userid,
usercoords: data.usercoords
}
//socket.broadcast.emit('maps-' + data.mapid + '-updatePeerCoords', peer)
socket.broadcast.emit(PEER_COORDS_UPDATED, peer)
})
socket.on(DRAG_TOPIC, function (data) {
var mapId = data.mapid
delete data.mapid
//socket.broadcast.emit('maps-' + mapId + '-topicDrag', data)
socket.broadcast.emit(TOPIC_DRAGGED, data)
})
socket.on(CREATE_MESSAGE, function (data) {
var mapId = data.mapid
delete data.mapid
//socket.broadcast.emit('maps-' + mapId + '-newMessage', data)
socket.broadcast.emit(MESSAGE_CREATED, data)
})
socket.on(CREATE_TOPIC, function (data) {
var mapId = data.mapid
delete data.mapid
//socket.broadcast.emit('maps-' + mapId + '-newTopic', data)
socket.broadcast.emit(TOPIC_CREATED, data)
})
socket.on(UPDATE_TOPIC, function (data) {
socket.broadcast.emit(TOPIC_UPDATED, data)
})
socket.on(REMOVE_TOPIC, function (data) {
var mapId = data.mapid
delete data.mapid
//socket.broadcast.emit('maps-' + mapId + '-removeTopic', data)
socket.broadcast.emit(TOPIC_REMOVED, data)
})
socket.on(DELETE_TOPIC, function (data) {
socket.broadcast.emit(TOPIC_DELETED, data)
})
socket.on(CREATE_SYNAPSE, function (data) {
var mapId = data.mapid
delete data.mapid
//socket.broadcast.emit('maps-' + mapId + '-newSynapse', data)
socket.broadcast.emit(SYNAPSE_CREATED, data)
})
socket.on(UPDATE_SYNAPSE, function (data) {
socket.broadcast.emit(SYNAPSE_UPDATED, data)
})
socket.on(REMOVE_SYNAPSE, function (data) {
var mapId = data.mapid
delete data.mapid
//socket.broadcast.emit('maps-' + mapId + '-removeSynapse', data)
socket.broadcast.emit(SYNAPSE_REMOVED, data)
})
socket.on(DELETE_SYNAPSE, function (data) {
//socket.broadcast.emit('deleteSynapseFromServer', data)
socket.broadcast.emit(SYNAPSE_DELETED, data)
})
socket.on(UPDATE_MAP, function (data) {
socket.broadcast.emit(MAP_UPDATED, data)
})
})
}
start()

6
realtime/rooms.js Normal file
View file

@ -0,0 +1,6 @@
module.exports = {
mapRoom: mapId => `maps/${mapId}`,
userMapRoom: (mapperId, mapId) => `mappers/${mapperId}/maps/${mapId}`,
userRoom: mapperId => `mappers/${mapperId}`
}

View file

@ -1,20 +1,7 @@
var uuid = require('node-uuid');
var uuid = require('node-uuid')
module.exports = function(io, stunservers) {
var
activePeople = 0;
function describeRoom(name) {
var clients = io.sockets.clients(name);
var result = {
clients: {}
};
clients.forEach(function (client) {
result.clients[client.id] = client.resources;
});
return result;
}
// based off of https://github.com/andyet/signalmaster
// since it was updated to socket.io 1.3.7
function safeCb(cb) {
if (typeof cb === 'function') {
@ -24,88 +11,109 @@ module.exports = function(io, stunservers) {
}
}
io.sockets.on('connection', function (client) {
activePeople += 1;
module.exports = function(io, stunservers, state) {
client.resources = {
io.on('connection', function (socket) {
socket.resources = {
screen: false,
video: true,
audio: false
};
}
// pass a message to another id
client.on('message', function (details) {
if (!details) return;
socket.on('message', function (details) {
if (!details) return
var otherClient = io.sockets.sockets[details.to];
if (!otherClient) return;
var otherClient = io.to(details.to)
if (!otherClient) return
details.from = client.id;
otherClient.emit('message', details);
});
details.from = socket.id
otherClient.emit('message', details)
})
client.on('shareScreen', function () {
client.resources.screen = true;
});
socket.on('shareScreen', function () {
socket.resources.screen = true
})
client.on('unshareScreen', function (type) {
client.resources.screen = false;
removeFeed('screen');
});
socket.on('unshareScreen', function (type) {
socket.resources.screen = false
removeFeed('screen')
})
client.on('join', join);
socket.on('join', join)
function removeFeed(type) {
if (client.room) {
io.sockets.in(client.room).emit('remove', {
id: client.id,
if (socket.room) {
io.sockets.in(socket.room).emit('remove', {
id: socket.id,
type: type
});
})
if (!type) {
client.leave(client.room);
client.room = undefined;
socket.leave(socket.room)
socket.room = undefined
}
}
}
function join(name, cb) {
// sanity check
if (typeof name !== 'string') return;
if (typeof name !== 'string') return
// leave any existing rooms
removeFeed();
safeCb(cb)(null, describeRoom(name));
client.join(name);
client.room = name;
removeFeed()
safeCb(cb)(null, describeRoom(name))
socket.join(name)
socket.room = name
}
// we don't want to pass "leave" directly because the
// event type string of "socket end" gets passed too.
client.on('disconnect', function () {
removeFeed();
activePeople -= 1;
});
client.on('leave', function () {
removeFeed();
});
socket.on('disconnect', function () {
removeFeed()
})
socket.on('leave', function () {
removeFeed()
})
client.on('create', function (name, cb) {
socket.on('create', function (name, cb) {
if (arguments.length == 2) {
cb = (typeof cb == 'function') ? cb : function () {};
name = name || uuid();
cb = (typeof cb == 'function') ? cb : function () {}
name = name || uuid()
} else {
cb = name;
name = uuid();
cb = name
name = uuid()
}
// check if exists
if (io.sockets.clients(name).length) {
safeCb(cb)('taken');
var room = io.nsps['/'].adapter.rooms[name]
if (room && room.length) {
safeCb(cb)('taken')
} else {
join(name);
safeCb(cb)(null, name);
join(name)
safeCb(cb)(null, name)
}
});
})
// tell client about stun and turn servers and generate nonces
client.emit('stunservers', stunservers || []);
});
};
// support for logging full webrtc traces to stdout
// useful for large-scale error monitoring
socket.on('trace', function (data) {
console.log('trace', JSON.stringify(
[data.type, data.session, data.prefix, data.peer, data.time, data.value]
))
})
})
function describeRoom(name) {
var adapter = io.nsps['/'].adapter
var sockets = adapter.rooms[name] || {}
var result = {
clients: {}
}
Object.keys(sockets).forEach(function (id) {
result.clients[id] = adapter.nsp.connected[id].resources
})
return result
}
function socketsInRoom(name) {
return io.sockets.sockets(name).length
}
}