-
Notifications
You must be signed in to change notification settings - Fork 56
Expand file tree
/
Copy pathserver.js
More file actions
126 lines (102 loc) · 2.39 KB
/
server.js
File metadata and controls
126 lines (102 loc) · 2.39 KB
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
/**
* Module dependencies.
*/
var protocols = require('./protocols')
, EventEmitter = require('events')
, url = require('url');
/**
* Module exports.
*/
module.exports = Server;
/**
* Constructor. HTTP Server agnostic.
*
* @param {Object} options
* @api public
*/
function Server (options) {
this.options = {
path: null
, clientTracking: true
};
for (var i in options) {
this.options[i] = options[i];
}
this.clients = [];
this.clientsCount = 0;
this.clientsNull = [];
}
/**
* Inherits from EventEmitter.
*/
Server.prototype.__proto__ = EventEmitter.prototype;
/**
* Handles a Request after `upgrade` event.
*
* @param {http.Request} request object
* @param {http.Stream} socket
* @param {Buffer} data stream head
* @return {Server} for chaining.
* @api public
*/
Server.prototype.handleUpgrade = function (req, socket, head) {
var self = this;
if (! this.checkRequest(req)) {
return this;
}
// attach the legacy `head` property to request
req.head = head;
var client = this.createClient(req);
client.on('open', function() {
if (self.options.clientTracking) {
var i = null;
if (self.clientsNull.length) {
i = self.clientsNull.shift();
self.clients[i] = client;
}
else {
i = self.clients.length;
self.clients.push(client);
}
self.clientsCount++;
client.on('close', function () {
self.clients[i] = null;
self.clientsNull.push(i);
self.clientsCount--;
});
}
self.emit('connection', client);
});
return this;
};
/**
* Checks whether the request path matches.
*
* @return {Bool}
* @api private
*/
Server.prototype.checkRequest = function (req) {
if (!(req.method == 'GET' &&
req.headers['upgrade'] &&
req.headers.upgrade.toLowerCase() == 'websocket')) {
// not a valid WebSocket upgrade
return false;
}
if (this.options.path) {
var u = url.parse(req.url);
if (u && u.pathname !== this.options.path) return false;
}
// no options.path => match all paths
return true;
};
/**
* Initializes a client for the request with appropriate protocol.
*
* @param {http.Request} request object
* @api private
*/
Server.prototype.createClient = function (req) {
var version = req.headers['sec-websocket-version']
, name = protocols[version] ? version : 'drafts'
return new protocols[name](req);
};