-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
127 lines (98 loc) · 2.43 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
var WebSocketServer = require('ws').Server;
var JSONCodec = require('./jsoncodec');
var Promise = require('bluebird');
var NO_ACK = 0;
var INIT = 0;
var EVENT = 1;
var REPLY = 2;
var PING = 3;
var PONG = 4;
function WebRPCConn(ws) {
if (!(this instanceof WebRPCConn)) {
throw new Error('Please use the \'new\' operator.');
}
var self = this;
function send(type, name, data, ack) {
var event = self.codec.encode({
type: type,
name: name,
data: data,
ack: ack
});
ws.send(event);
}
function messageEvent(data) {
var message = self.codec.decode(data);
switch (message.type) {
case INIT:
// Reserved; not used for now.
break;
case EVENT:
var listener = self.listeners[message.name];
if (listener) {
if (message.ack !== NO_ACK) {
var ret = listener.apply(self, message.data);
Promise.resolve(ret).then(function then(value) {
send(REPLY, message.name, [value], message.ack);
});
} else {
listener.apply(self, message.data);
}
}
break;
case PING:
send(PONG);
break;
default:
break;
}
}
function disconnectEvent(e) {
if (self.ondisconnect) {
self.ondisconnect(e);
}
}
ws.on('message', messageEvent);
ws.on('close', disconnectEvent);
// Connection state
self.ws = ws;
self.codec = new JSONCodec();
// Callbacks.
self.ondisconnect = null;
self.listeners = {};
// Expose send.
self._send = send;
// Send init message. Currently not used.
send(INIT);
}
WebRPCConn.prototype.on = function on(name, listener) {
this.listeners[name] = listener;
};
WebRPCConn.prototype.emit = function emit() {
var name = arguments[0];
var params = Array.prototype.splice.call(arguments, 1);
this._send(EVENT, name, params, NO_ACK);
};
function WebRPCServer(options) {
if (!(this instanceof WebRPCServer)) {
throw new Error('Please use the \'new\' operator.');
}
var self = this;
var wss = new WebSocketServer(options);
function connectionEvent(ws) {
var conn = new WebRPCConn(ws);
if (self.onconnect) {
self.onconnect(conn);
}
}
wss.on('connection', connectionEvent);
// Server
self.wss = wss;
// Callbacks.
self.onconnect = null;
}
WebRPCServer.prototype.close = function close() {
return this.wss.close();
};
module.exports = WebRPCServer;
module.exports.WebRPCConn = WebRPCConn;