Mercurial > hg > nodescore
comparison node_modules/socket.io/lib/index.js @ 77:cd921abc8887
added puredata trigger/OSC router
author | Rob Canning <rob@foo.net> |
---|---|
date | Tue, 15 Jul 2014 17:48:07 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
76:0ae87af84e2f | 77:cd921abc8887 |
---|---|
1 | |
2 /** | |
3 * Module dependencies. | |
4 */ | |
5 | |
6 var http = require('http'); | |
7 var read = require('fs').readFileSync; | |
8 var parse = require('url').parse; | |
9 var engine = require('engine.io'); | |
10 var client = require('socket.io-client'); | |
11 var clientVersion = require('socket.io-client/package').version; | |
12 var Client = require('./client'); | |
13 var Namespace = require('./namespace'); | |
14 var Adapter = require('socket.io-adapter'); | |
15 var debug = require('debug')('socket.io:server'); | |
16 var url = require('url'); | |
17 | |
18 /** | |
19 * Module exports. | |
20 */ | |
21 | |
22 module.exports = Server; | |
23 | |
24 /** | |
25 * Socket.IO client source. | |
26 */ | |
27 | |
28 var clientSource = read(require.resolve('socket.io-client/socket.io.js'), 'utf-8'); | |
29 | |
30 /** | |
31 * Server constructor. | |
32 * | |
33 * @param {http.Server|Number|Object} http server, port or options | |
34 * @param {Object} options | |
35 * @api public | |
36 */ | |
37 | |
38 function Server(srv, opts){ | |
39 if (!(this instanceof Server)) return new Server(srv, opts); | |
40 if ('object' == typeof srv && !srv.listen) { | |
41 opts = srv; | |
42 srv = null; | |
43 } | |
44 opts = opts || {}; | |
45 this.nsps = {}; | |
46 this.path(opts.path || '/socket.io'); | |
47 this.serveClient(false !== opts.serveClient); | |
48 this.adapter(opts.adapter || Adapter); | |
49 this.origins(opts.origins || '*:*'); | |
50 this.sockets = this.of('/'); | |
51 if (srv) this.attach(srv, opts); | |
52 } | |
53 | |
54 /** | |
55 * Server request verification function, that checks for allowed origins | |
56 * | |
57 * @param {http.IncomingMessage} request | |
58 * @param {Function} callback to be called with the result: `fn(err, success)` | |
59 */ | |
60 | |
61 Server.prototype.checkRequest = function(req, fn) { | |
62 var origin = req.headers.origin || req.headers.referer; | |
63 | |
64 // file:// URLs produce a null Origin which can't be authorized via echo-back | |
65 if ('null' == origin) origin = '*'; | |
66 | |
67 if (this._origins.indexOf('*:*') !== -1) return fn(null, true); | |
68 if (origin) { | |
69 try { | |
70 var parts = url.parse(origin); | |
71 parts.port = parts.port || 80; | |
72 var ok = | |
73 ~this._origins.indexOf(parts.hostname + ':' + parts.port) || | |
74 ~this._origins.indexOf(parts.hostname + ':*') || | |
75 ~this._origins.indexOf('*:' + parts.port); | |
76 return fn(null, !!ok); | |
77 } catch (ex) { | |
78 } | |
79 } | |
80 fn(null, false); | |
81 }; | |
82 | |
83 /** | |
84 * Sets/gets whether client code is being served. | |
85 * | |
86 * @param {Boolean} whether to serve client code | |
87 * @return {Server|Boolean} self when setting or value when getting | |
88 * @api public | |
89 */ | |
90 | |
91 Server.prototype.serveClient = function(v){ | |
92 if (!arguments.length) return this._serveClient; | |
93 this._serveClient = v; | |
94 return this; | |
95 }; | |
96 | |
97 /** | |
98 * Old settings for backwards compatibility | |
99 */ | |
100 | |
101 var oldSettings = { | |
102 "transports": "transports", | |
103 "heartbeat timeout": "pingTimeout", | |
104 "heartbeat interval": "pingInterval", | |
105 "destroy buffer size": "maxHttpBufferSize" | |
106 }; | |
107 | |
108 /** | |
109 * Backwards compatiblity. | |
110 * | |
111 * @api public | |
112 */ | |
113 | |
114 Server.prototype.set = function(key, val){ | |
115 if ('authorization' == key && val) { | |
116 this.use(function(socket, next) { | |
117 val(socket.request, function(err, authorized) { | |
118 if (err) return next(new Error(err)); | |
119 if (!authorized) return next(new Error('Not authorized')); | |
120 next(); | |
121 }); | |
122 }); | |
123 } else if ('origins' == key && val) { | |
124 this.origins(val); | |
125 } else if ('resource' == key) { | |
126 this.path(val); | |
127 } else if (oldSettings[key] && this.eio[oldSettings[key]]) { | |
128 this.eio[oldSettings[key]] = val; | |
129 } else { | |
130 console.error('Option %s is not valid. Please refer to the README.', key); | |
131 } | |
132 | |
133 return this; | |
134 }; | |
135 | |
136 /** | |
137 * Sets the client serving path. | |
138 * | |
139 * @param {String} pathname | |
140 * @return {Server|String} self when setting or value when getting | |
141 * @api public | |
142 */ | |
143 | |
144 Server.prototype.path = function(v){ | |
145 if (!arguments.length) return this._path; | |
146 this._path = v.replace(/\/$/, ''); | |
147 return this; | |
148 }; | |
149 | |
150 /** | |
151 * Sets the adapter for rooms. | |
152 * | |
153 * @param {Adapter} pathname | |
154 * @return {Server|Adapter} self when setting or value when getting | |
155 * @api public | |
156 */ | |
157 | |
158 Server.prototype.adapter = function(v){ | |
159 if (!arguments.length) return this._adapter; | |
160 this._adapter = v; | |
161 for (var i in this.nsps) { | |
162 if (this.nsps.hasOwnProperty(i)) { | |
163 this.nsps[i].initAdapter(); | |
164 } | |
165 } | |
166 return this; | |
167 }; | |
168 | |
169 /** | |
170 * Sets the allowed origins for requests. | |
171 * | |
172 * @param {String} origins | |
173 * @return {Server|Adapter} self when setting or value when getting | |
174 * @api public | |
175 */ | |
176 | |
177 Server.prototype.origins = function(v){ | |
178 if (!arguments.length) return this._origins; | |
179 | |
180 this._origins = v; | |
181 return this; | |
182 }; | |
183 | |
184 /** | |
185 * Attaches socket.io to a server or port. | |
186 * | |
187 * @param {http.Server|Number} server or port | |
188 * @param {Object} options passed to engine.io | |
189 * @return {Server} self | |
190 * @api public | |
191 */ | |
192 | |
193 Server.prototype.listen = | |
194 Server.prototype.attach = function(srv, opts){ | |
195 if ('function' == typeof srv) { | |
196 var msg = 'You are trying to attach socket.io to an express' + | |
197 'request handler function. Please pass a http.Server instance.'; | |
198 throw new Error(msg); | |
199 } | |
200 | |
201 // handle a port as a string | |
202 if (Number(srv) == srv) { | |
203 srv = Number(srv); | |
204 } | |
205 | |
206 if ('number' == typeof srv) { | |
207 debug('creating http server and binding to %d', srv); | |
208 var port = srv; | |
209 srv = http.Server(function(req, res){ | |
210 res.writeHead(404); | |
211 res.end(); | |
212 }); | |
213 srv.listen(port); | |
214 } | |
215 | |
216 // set engine.io path to `/socket.io` | |
217 opts = opts || {}; | |
218 opts.path = opts.path || '/socket.io'; | |
219 // set origins verification | |
220 opts.allowRequest = this.checkRequest.bind(this); | |
221 | |
222 // initialize engine | |
223 debug('creating engine.io instance with opts %j', opts); | |
224 this.eio = engine.attach(srv, opts); | |
225 | |
226 // attach static file serving | |
227 if (this._serveClient) this.attachServe(srv); | |
228 | |
229 // bind to engine events | |
230 this.bind(this.eio); | |
231 | |
232 return this; | |
233 }; | |
234 | |
235 /** | |
236 * Attaches the static file serving. | |
237 * | |
238 * @param {Function|http.Server} http server | |
239 * @api private | |
240 */ | |
241 | |
242 Server.prototype.attachServe = function(srv){ | |
243 debug('attaching client serving req handler'); | |
244 var url = this._path + '/socket.io.js'; | |
245 var evs = srv.listeners('request').slice(0); | |
246 var self = this; | |
247 srv.removeAllListeners('request'); | |
248 srv.on('request', function(req, res) { | |
249 if (0 == req.url.indexOf(url)) { | |
250 self.serve(req, res); | |
251 } else { | |
252 for (var i = 0; i < evs.length; i++) { | |
253 evs[i].call(srv, req, res); | |
254 } | |
255 } | |
256 }); | |
257 }; | |
258 | |
259 /** | |
260 * Handles a request serving `/socket.io.js` | |
261 * | |
262 * @param {http.Request} req | |
263 * @param {http.Response} res | |
264 * @api private | |
265 */ | |
266 | |
267 Server.prototype.serve = function(req, res){ | |
268 if (req.headers.etag) { | |
269 if (clientVersion == req.headers.etag) { | |
270 debug('serve client 304'); | |
271 res.writeHead(304); | |
272 res.end(); | |
273 return; | |
274 } | |
275 } | |
276 | |
277 debug('serve client source'); | |
278 res.setHeader('Content-Type', 'application/javascript'); | |
279 res.setHeader('ETag', clientVersion); | |
280 res.writeHead(200); | |
281 res.end(clientSource); | |
282 }; | |
283 | |
284 /** | |
285 * Binds socket.io to an engine.io instance. | |
286 * | |
287 * @param {engine.Server} engine.io (or compatible) server | |
288 * @return {Server} self | |
289 * @api public | |
290 */ | |
291 | |
292 Server.prototype.bind = function(engine){ | |
293 this.engine = engine; | |
294 this.engine.on('connection', this.onconnection.bind(this)); | |
295 return this; | |
296 }; | |
297 | |
298 /** | |
299 * Called with each incoming transport connection. | |
300 * | |
301 * @param {engine.Socket} socket | |
302 * @return {Server} self | |
303 * @api public | |
304 */ | |
305 | |
306 Server.prototype.onconnection = function(conn){ | |
307 debug('incoming connection with id %s', conn.id); | |
308 var client = new Client(this, conn); | |
309 client.connect('/'); | |
310 return this; | |
311 }; | |
312 | |
313 /** | |
314 * Looks up a namespace. | |
315 * | |
316 * @param {String} nsp name | |
317 * @param {Function} optional, nsp `connection` ev handler | |
318 * @api public | |
319 */ | |
320 | |
321 Server.prototype.of = function(name, fn){ | |
322 if (!this.nsps[name]) { | |
323 debug('initializing namespace %s', name); | |
324 var nsp = new Namespace(this, name); | |
325 this.nsps[name] = nsp; | |
326 } | |
327 if (fn) this.nsps[name].on('connect', fn); | |
328 return this.nsps[name]; | |
329 }; | |
330 | |
331 /** | |
332 * Expose main namespace (/). | |
333 */ | |
334 | |
335 ['on', 'to', 'in', 'use', 'emit', 'send', 'write'].forEach(function(fn){ | |
336 Server.prototype[fn] = function(){ | |
337 var nsp = this.sockets[fn]; | |
338 return nsp.apply(this.sockets, arguments); | |
339 }; | |
340 }); | |
341 | |
342 Namespace.flags.forEach(function(flag){ | |
343 Server.prototype.__defineGetter__(flag, function(name){ | |
344 this.flags.push(name); | |
345 return this; | |
346 }); | |
347 }); | |
348 | |
349 /** | |
350 * BC with `io.listen` | |
351 */ | |
352 | |
353 Server.listen = Server; |