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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
|
//SERVER
var WebSocketServer = require('ws').Server
var iolog = function() {};
for (var i = 0; i < process.argv.length; i++) {
var arg = process.argv[i];
if (arg === "-debug") {
iolog = function(msg) {
console.log(msg);
};
console.log('Debug mode on!');
}
}
// Used for callback publish and subscribe
if (typeof rtc === "undefined") {
var rtc = {};
}
//Array to store connections
rtc.sockets = [];
rtc.rooms = {};
rtc.users = {};
rtc.encryption = {};
rtc.browser = {};
rtc.browserVer = {};
// Holds callbacks for certain events.
rtc._events = {};
rtc.on = function(eventName, callback) {
rtc._events[eventName] = rtc._events[eventName] || [];
rtc._events[eventName].push(callback);
};
rtc.fire = function(eventName, _) {
var events = rtc._events[eventName];
var args = Array.prototype.slice.call(arguments, 1);
if (!events) {
return;
}
for (var i = 0, len = events.length; i < len; i++) {
events[i].apply(null, args);
}
};
module.exports.listen = function(server) {
var manager;
if (typeof server === 'number') {
manager = new WebSocketServer({
port: server
});
} else {
manager = new WebSocketServer({
server: server
});
}
manager.rtc = rtc;
attachEvents(manager);
return manager;
};
function attachEvents(manager) {
manager.on('connection', function(socket) {
iolog('connect');
socket.id = id();
iolog('new socket got id: ' + socket.id);
rtc.sockets.push(socket);
socket.on('message', function(msg) {
var json = JSON.parse(msg);
rtc.fire(json.eventName, json.data, socket);
});
socket.on('close', function() {
iolog('close');
// find socket to remove
var i = rtc.sockets.indexOf(socket);
// remove socket
rtc.sockets.splice(i, 1);
// remove from rooms and send remove_peer_connected to all sockets in room
for (var key in rtc.rooms) {
var room = rtc.rooms[key];
var exist = room.indexOf(socket.id);
if (exist !== -1) {
room.splice(room.indexOf(socket.id), 1);
for (var j = 0; j < room.length; j++) {
console.log(room[j]);
var soc = rtc.getSocket(room[j]);
soc.send(JSON.stringify({
"eventName": "remove_peer_connected",
"data": {
"socketId": socket.id
}
}), function(error) {
if (error) {
console.log(error);
}
});
}
//also remove from username list
var userList = rtc.users[key];
delete userList[socket.id];
break;
}
}
// we are leaved the room so lets notify about that
rtc.fire('room_leave', room, socket.id);
// call the disconnect callback
rtc.fire('disconnect', rtc);
});
// call the connect callback
rtc.fire('connect', rtc);
});
// manages the built-in room functionality
rtc.on('join_room', function(data, socket) {
iolog('join_room');
if (data.room == 0){
return;
}
var connectionsId = [];
var usersId = [];
var roomList = rtc.rooms[data.room] || [];
var userList = rtc.users[data.room] || {};
roomList.push(socket.id);
rtc.rooms[data.room] = roomList;
userList[socket.id] = data.username;
rtc.users[data.room] = userList;
for (var i = 0; i < roomList.length; i++) {
var id = roomList[i];
if (id == socket.id) {
continue;
} else {
connectionsId.push(id);
var soc = rtc.getSocket(id);
// inform the peers that they have a new peer
if (soc) {
soc.send(JSON.stringify({
"eventName": "new_peer_connected",
"data":{
"socketId": socket.id,
"username": data.username
}
}), function(error) {
if (error) {
console.log(error);
}
});
}
}
}
// send new peer a list of all prior peers
socket.send(JSON.stringify({
"eventName": "get_peers",
"data": {
"connections": connectionsId,
"usernames": userList,
"you": socket.id
}
}), function(error) {
if (error) {
console.log(error);
}
});
});
//Receive ICE candidates and send to the correct socket
rtc.on('send_ice_candidate', function(data, socket) {
iolog('send_ice_candidate');
var soc = rtc.getSocket(data.socketId);
if (soc) {
soc.send(JSON.stringify({
"eventName": "receive_ice_candidate",
"data": {
"label": data.label,
"candidate": data.candidate,
"socketId": socket.id
}
}), function(error) {
if (error) {
console.log(error);
}
});
// call the 'recieve ICE candidate' callback
rtc.fire('receive ice candidate', rtc);
}
});
//Receive offer and send to correct socket
rtc.on('send_offer', function(data, socket) {
iolog('send_offer');
var soc = rtc.getSocket(data.socketId);
if (soc) {
soc.send(JSON.stringify({
"eventName": "receive_offer",
"data": {
"sdp": data.sdp,
"socketId": socket.id
}
}), function(error) {
if (error) {
console.log(error);
}
});
}
// call the 'send offer' callback
rtc.fire('send offer', rtc);
});
//Receive answer and send to correct socket
rtc.on('send_answer', function(data, socket) {
iolog('send_answer');
var soc = rtc.getSocket( data.socketId);
if (soc) {
soc.send(JSON.stringify({
"eventName": "receive_answer",
"data" : {
"sdp": data.sdp,
"socketId": socket.id
}
}), function(error) {
if (error) {
console.log(error);
}
});
rtc.fire('send answer', rtc);
}
});
}
// generate a 4 digit hex code randomly
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
// make a REALLY COMPLICATED AND RANDOM id, kudos to dennis
function id() {
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}
rtc.getSocket = function(id) {
var connections = rtc.sockets;
if (!connections) {
// TODO: Or error, or customize
return;
}
for (var i = 0; i < connections.length; i++) {
var socket = connections[i];
if (id === socket.id) {
return socket;
}
}
};
|