-
Notifications
You must be signed in to change notification settings - Fork 9
/
server.js
148 lines (120 loc) · 4.51 KB
/
server.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
// SSL Certificates
var fs = require('fs');
var options = {key: fs.readFileSync('certs/privatekey.pem').toString(),
cert: fs.readFileSync('certs/certificate.pem').toString(),
ca: [fs.readFileSync('certs/certrequest.csr').toString()]}
// Get AppFog port, or set 8080 as default one (dotCloud mandatory)
var port = process.env.VMC_APP_PORT || 8080
// HTTP server
function requestListener(req, res)
{
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('This is a DataChannel polyfill backend server. ')
res.write('You can get a copy of the source code at ')
res.end('<a href="https://github.com/piranna/DataChannel-polyfill">GitHub</a>')
}
var server = require('http').createServer(requestListener)
//var server = require('https').createServer(options, requestListener)
server.listen(port);
// DataChannel proxy server
var WebSocketServer = require('ws').Server
var wss = new WebSocketServer({server: server});
//Dict to store connections
wss.sockets = {}
wss.on('connection', function(socket)
{
// Forward raw message to the other peer
function onmessage_proxy(message)
{
this.peer.send(message.data)
};
// Handshake
socket.onmessage = function(message)
{
var args = JSON.parse(message.data)
var eventName = args[0]
var socketId = args[1]
var soc = wss.sockets[socketId]
switch(eventName)
{
case 'create': // socketId is the peer ID
if(soc)
{
// Both peers support native DataChannels
if(args[3] && soc.nativeSupport)
{
// Notify that both peers has native support
socket.send(JSON.stringify(['create.native']))
soc.send(JSON.stringify(['create.native']))
// Close both peers since they have native support
socket.close();
soc.close();
}
// At least one of the peers doesn't support DataChannels
else
{
// Register the new peer connection
socket.id = id()
wss.sockets[socket.id] = socket
// Send the other peer the request to connect
args[1] = socket.id
args.splice(3, 1)
soc.send(JSON.stringify(args))
}
}
// Second peer was not connected
// Send error message and close socket
else
{
socket.send(JSON.stringify(['create.error', socketId]))
socket.close();
}
break
case 'ready': // socketId is the UDT ID
if(soc)
{
// Link peers and update onmessage event to just forward
socket.peer = soc
soc.peer = socket
socket.onmessage = onmessage_proxy
soc.onmessage = onmessage_proxy
// Send 'ready' signal to the first peer and dettach it
soc.send(JSON.stringify(['ready']))
delete soc.id
delete wss.sockets[socketId]
}
// First peer was disconnected
// Send error message and close socket
else
{
socket.send(JSON.stringify(['ready.error', socketId]))
socket.close();
}
break
// Register peer signaling socket with this ID
case 'setId':
wss.sockets[socketId] = socket
wss.sockets[socketId].nativeSupport = args[2]
}
};
// Peer connection is closed, close the other end
socket.onclose = function()
{
// Sockets were connected, just close them
if(socket.peer != undefined)
socket.peer.close();
// Socket was not connected, remove it from sockets list
else
delete wss.sockets[socket.id]
};
})
// 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()
}