-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathindex.js
164 lines (125 loc) · 4.04 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
var jsonparse = require('cog/jsonparse');
var EventEmitter = require('events').EventEmitter;
var FastMap = require('collections/fast-map');
var not = require('whisk/not');
/**
# rtc-switch
This is a processor layer for the rtc-switchboard that is capable of
talking with an rtc-signaller up to and including version 5.
## Example Usage
Plain old websockets:
<<< examples/ws-server.js
Using [socket.io](https://github.com/Automattic/socket.io):
<<< examples/socket-io.js
**/
module.exports = function(opts) {
var board = new EventEmitter();
var rooms = board.rooms = new FastMap();
var logger = (opts || {}).logger || console;
function connect() {
var peer = new EventEmitter();
var notMe = not(peer);
function process(data) {
var command;
var parts;
var target;
// emit the data for the board to process
board.emit('data', data, peer && peer.id, peer);
if (data.charAt(0) === '/') {
// initialise the command name
command = data.slice(1, data.indexOf('|', 1)).toLowerCase();
// get the payload
parts = data.slice(command.length + 2).split('|').map(jsonparse);
// if we have a to command, and no designated target
if (command === 'to') {
target = peer.room && peer.room.members.filter(function(member) {
return member.id === parts[0];
})[0];
// if the target is unknown, refuse to send
if (! target) {
logger.warn('got a to request for id "' + parts[0] + '" but cannot find target');
return false;
}
return target.emit('data', data);
}
if (! target) {
board.emit.apply(board, [command, data, peer].concat(parts));
if (peer.room) {
peer.room.members.filter(notMe).forEach(function(member) {
member.emit('data', data);
});
}
}
}
}
// add peer functions
peer.process = process;
peer.leave = board.emit.bind(board, 'leave', peer);
// trigger the peer connect
board.emit('peer:connect', peer);
return peer;
}
function createRoom(name) {
// create a simple room object
rooms.set(name, {
name: name,
members: []
});
board.emit('room:create', name);
return rooms.get(name);
}
function destroy() {
rooms.clear();
}
function emit(name, src) {
var args = [].slice.call(arguments);
return function(emitter) {
// never send messages to ourself
if (emitter === src) {
return;
}
return emitter.emit.apply(emitter, args);
};
}
function getOrCreateRoom(name) {
return rooms.get(name) || createRoom(name);
}
// handle announce messages
board.on('announce', function(payload, peer, sender, data) {
var targetRoom = data && data.room;
var room = targetRoom && getOrCreateRoom(targetRoom);
// if the peer is already in a room, then we need to remove them from
// that room
if (peer.room && peer.room.name !== targetRoom) {
board.emit('leave', peer, sender, data);
}
// tag the peer
peer.room = room;
peer.id = data.id;
// send through the announce
if (room) {
// add the peer to the room
room.members = room.members.filter(function(member) {
return member && peer && member.id && member.id !== peer.id;
}).concat([peer]);
// send the number of members back to the peer
peer.emit('data', '/roominfo|{"memberCount":' + room.members.length + '}');
}
});
board.on('leave', function(peer) {
if (peer.room) {
// remove the peer from the room
peer.room.members = peer.room.members.filter(not(peer));
// if we have no more members in the room, then destroy the room
if (peer.room.members.length === 0) {
board.emit('room:destroy', peer.room.name);
rooms.delete(peer.room.name);
}
peer.room = undefined;
}
board.emit('peer:disconnect', peer);
});
board.connect = connect;
board.destroy = destroy;
return board;
};