annotate node_modules/socket.io/lib/socket.js @ 101:52e44ee1c791 tip master

enabled all scores in autostart script
author Rob Canning <rc@kiben.net>
date Tue, 21 Apr 2015 16:20:57 +0100
parents 0ae87af84e2f
children
rev   line source
rc-web@69 1
rc-web@69 2 /**
rc-web@69 3 * Module dependencies.
rc-web@69 4 */
rc-web@69 5
rob@76 6 var Emitter = require('events').EventEmitter;
rob@76 7 var parser = require('socket.io-parser');
rob@76 8 var url = require('url');
rob@76 9 var debug = require('debug')('socket.io:socket');
rob@76 10 var hasBin = require('has-binary-data');
rc-web@69 11
rc-web@69 12 /**
rob@76 13 * Module exports.
rc-web@69 14 */
rc-web@69 15
rob@76 16 module.exports = exports = Socket;
rc-web@69 17
rc-web@69 18 /**
rob@76 19 * Blacklisted events.
rc-web@69 20 *
rc-web@69 21 * @api public
rc-web@69 22 */
rc-web@69 23
rob@76 24 exports.events = [
rob@76 25 'error',
rob@76 26 'connect',
rob@76 27 'disconnect',
rob@76 28 'newListener',
rob@76 29 'removeListener'
rob@76 30 ];
rc-web@69 31
rc-web@69 32 /**
rob@76 33 * Flags.
rc-web@69 34 *
rc-web@69 35 * @api private
rc-web@69 36 */
rc-web@69 37
rob@76 38 var flags = [
rob@76 39 'json',
rob@76 40 'volatile',
rob@76 41 'broadcast'
rob@76 42 ];
rob@76 43
rob@76 44 /**
rob@76 45 * `EventEmitter#emit` reference.
rob@76 46 */
rob@76 47
rob@76 48 var emit = Emitter.prototype.emit;
rob@76 49
rob@76 50 /**
rob@76 51 * Interface to a `Client` for a given `Namespace`.
rob@76 52 *
rob@76 53 * @param {Namespace} nsp
rob@76 54 * @param {Client} client
rob@76 55 * @api public
rob@76 56 */
rob@76 57
rob@76 58 function Socket(nsp, client){
rob@76 59 this.nsp = nsp;
rob@76 60 this.server = nsp.server;
rob@76 61 this.adapter = this.nsp.adapter;
rob@76 62 this.id = client.id;
rob@76 63 this.request = client.request;
rob@76 64 this.client = client;
rob@76 65 this.conn = client.conn;
rob@76 66 this.rooms = [];
rob@76 67 this.acks = {};
rob@76 68 this.connected = true;
rob@76 69 this.disconnected = false;
rob@76 70 this.handshake = this.buildHandshake();
rob@76 71 }
rob@76 72
rob@76 73 /**
rob@76 74 * Inherits from `EventEmitter`.
rob@76 75 */
rob@76 76
rob@76 77 Socket.prototype.__proto__ = Emitter.prototype;
rob@76 78
rob@76 79 /**
rob@76 80 * Apply flags from `Socket`.
rob@76 81 */
rob@76 82
rob@76 83 flags.forEach(function(flag){
rob@76 84 Socket.prototype.__defineGetter__(flag, function(){
rob@76 85 this.flags = this.flags || {};
rob@76 86 this.flags[flag] = true;
rob@76 87 return this;
rob@76 88 });
rc-web@69 89 });
rc-web@69 90
rc-web@69 91 /**
rob@76 92 * `request` engine.io shorcut.
rob@76 93 *
rob@76 94 * @api public
rob@76 95 */
rob@76 96
rob@76 97 Socket.prototype.__defineGetter__('request', function(){
rob@76 98 return this.conn.request;
rob@76 99 });
rob@76 100
rob@76 101 /**
rob@76 102 * Builds the `handshake` BC object
rc-web@69 103 *
rc-web@69 104 * @api private
rc-web@69 105 */
rc-web@69 106
rob@76 107 Socket.prototype.buildHandshake = function(){
rob@76 108 return {
rob@76 109 headers: this.request.headers,
rob@76 110 time: (new Date) + '',
rob@76 111 address: this.request.connection.address(),
rob@76 112 xdomain: !!this.request.headers.origin,
rob@76 113 secure: !!this.request.connection.encrypted,
rob@76 114 issued: +(new Date),
rob@76 115 url: this.request.url,
rob@76 116 query: url.parse(this.request.url, true).query || {}
rob@76 117 };
rob@76 118 };
rc-web@69 119
rc-web@69 120 /**
rob@76 121 * Emits to this client.
rob@76 122 *
rob@76 123 * @return {Socket} self
rob@76 124 * @api public
rob@76 125 */
rob@76 126
rob@76 127 Socket.prototype.emit = function(ev){
rob@76 128 if (~exports.events.indexOf(ev)) {
rob@76 129 emit.apply(this, arguments);
rob@76 130 } else {
rob@76 131 var args = Array.prototype.slice.call(arguments);
rob@76 132 var packet = {};
rob@76 133 packet.type = hasBin(args) ? parser.BINARY_EVENT : parser.EVENT;
rob@76 134 packet.data = args;
rob@76 135
rob@76 136 // access last argument to see if it's an ACK callback
rob@76 137 if ('function' == typeof args[args.length - 1]) {
rob@76 138 if (this._rooms || (this.flags && this.flags.broadcast)) {
rob@76 139 throw new Error('Callbacks are not supported when broadcasting');
rob@76 140 }
rob@76 141
rob@76 142 debug('emitting packet with ack id %d', this.nsp.ids);
rob@76 143 this.acks[this.nsp.ids] = args.pop();
rob@76 144 packet.id = this.nsp.ids++;
rob@76 145 }
rob@76 146
rob@76 147 if (this._rooms || (this.flags && this.flags.broadcast)) {
rob@76 148 this.adapter.broadcast(packet, {
rob@76 149 except: [this.id],
rob@76 150 rooms: this._rooms,
rob@76 151 flags: this.flags
rob@76 152 });
rob@76 153 } else {
rob@76 154 // dispatch packet
rob@76 155 this.packet(packet);
rob@76 156 }
rob@76 157
rob@76 158 // reset flags
rob@76 159 delete this._rooms;
rob@76 160 delete this.flags;
rob@76 161 }
rob@76 162 return this;
rob@76 163 };
rob@76 164
rob@76 165 /**
rob@76 166 * Targets a room when broadcasting.
rob@76 167 *
rob@76 168 * @param {String} name
rob@76 169 * @return {Socket} self
rob@76 170 * @api public
rob@76 171 */
rob@76 172
rob@76 173 Socket.prototype.to =
rob@76 174 Socket.prototype.in = function(name){
rob@76 175 this._rooms = this._rooms || [];
rob@76 176 if (!~this._rooms.indexOf(name)) this._rooms.push(name);
rob@76 177 return this;
rob@76 178 };
rob@76 179
rob@76 180 /**
rob@76 181 * Sends a `message` event.
rob@76 182 *
rob@76 183 * @return {Socket} self
rob@76 184 * @api public
rob@76 185 */
rob@76 186
rob@76 187 Socket.prototype.send =
rob@76 188 Socket.prototype.write = function(){
rob@76 189 var args = Array.prototype.slice.call(arguments);
rob@76 190 args.unshift('message');
rob@76 191 this.emit.apply(this, args);
rob@76 192 return this;
rob@76 193 };
rob@76 194
rob@76 195 /**
rob@76 196 * Writes a packet.
rob@76 197 *
rob@76 198 * @param {Object} packet object
rob@76 199 * @api private
rob@76 200 */
rob@76 201
rob@76 202 Socket.prototype.packet = function(packet, preEncoded){
rob@76 203 packet.nsp = this.nsp.name;
rob@76 204 var volatile = this.flags && this.flags.volatile;
rob@76 205 this.client.packet(packet, preEncoded, volatile);
rob@76 206 };
rob@76 207
rob@76 208 /**
rob@76 209 * Joins a room.
rob@76 210 *
rob@76 211 * @param {String} room
rob@76 212 * @param {Function} optional, callback
rob@76 213 * @return {Socket} self
rob@76 214 * @api private
rob@76 215 */
rob@76 216
rob@76 217 Socket.prototype.join = function(room, fn){
rob@76 218 debug('joining room %s', room);
rob@76 219 var self = this;
rob@76 220 if (~this.rooms.indexOf(room)) return this;
rob@76 221 this.adapter.add(this.id, room, function(err){
rob@76 222 if (err) return fn && fn(err);
rob@76 223 debug('joined room %s', room);
rob@76 224 self.rooms.push(room);
rob@76 225 fn && fn(null);
rob@76 226 });
rob@76 227 return this;
rob@76 228 };
rob@76 229
rob@76 230 /**
rob@76 231 * Leaves a room.
rob@76 232 *
rob@76 233 * @param {String} room
rob@76 234 * @param {Function} optional, callback
rob@76 235 * @return {Socket} self
rob@76 236 * @api private
rob@76 237 */
rob@76 238
rob@76 239 Socket.prototype.leave = function(room, fn){
rob@76 240 debug('leave room %s', room);
rob@76 241 var self = this;
rob@76 242 this.adapter.del(this.id, room, function(err){
rob@76 243 if (err) return fn && fn(err);
rob@76 244 debug('left room %s', room);
rob@76 245 self.rooms.splice(self.rooms.indexOf(room, 1));
rob@76 246 fn && fn(null);
rob@76 247 });
rob@76 248 return this;
rob@76 249 };
rob@76 250
rob@76 251 /**
rob@76 252 * Leave all rooms.
rc-web@69 253 *
rc-web@69 254 * @api private
rc-web@69 255 */
rc-web@69 256
rob@76 257 Socket.prototype.leaveAll = function(){
rob@76 258 this.adapter.delAll(this.id);
rc-web@69 259 };
rc-web@69 260
rc-web@69 261 /**
rob@76 262 * Called by `Namespace` upon succesful
rob@76 263 * middleware execution (ie: authorization).
rc-web@69 264 *
rc-web@69 265 * @api private
rc-web@69 266 */
rc-web@69 267
rob@76 268 Socket.prototype.onconnect = function(){
rob@76 269 debug('socket connected - writing packet');
rob@76 270 this.join(this.id);
rob@76 271 this.packet({ type: parser.CONNECT });
rob@76 272 this.nsp.connected[this.id] = this;
rc-web@69 273 };
rc-web@69 274
rc-web@69 275 /**
rob@76 276 * Called with each packet. Called by `Client`.
rob@76 277 *
rob@76 278 * @param {Object} packet
rob@76 279 * @api private
rob@76 280 */
rob@76 281
rob@76 282 Socket.prototype.onpacket = function(packet){
rob@76 283 debug('got packet %j', packet);
rob@76 284 switch (packet.type) {
rob@76 285 case parser.EVENT:
rob@76 286 this.onevent(packet);
rob@76 287 break;
rob@76 288
rob@76 289 case parser.BINARY_EVENT:
rob@76 290 this.onevent(packet);
rob@76 291 break;
rob@76 292
rob@76 293 case parser.ACK:
rob@76 294 this.onack(packet);
rob@76 295 break;
rob@76 296
rob@76 297 case parser.BINARY_ACK:
rob@76 298 this.onack(packet);
rob@76 299 break;
rob@76 300
rob@76 301 case parser.DISCONNECT:
rob@76 302 this.ondisconnect();
rob@76 303 break;
rob@76 304
rob@76 305 case parser.ERROR:
rob@76 306 this.emit('error', packet.data);
rob@76 307 }
rob@76 308 };
rob@76 309
rob@76 310 /**
rob@76 311 * Called upon event packet.
rob@76 312 *
rob@76 313 * @param {Object} packet object
rob@76 314 * @api private
rob@76 315 */
rob@76 316
rob@76 317 Socket.prototype.onevent = function(packet){
rob@76 318 var args = packet.data || [];
rob@76 319 debug('emitting event %j', args);
rob@76 320
rob@76 321 if (null != packet.id) {
rob@76 322 debug('attaching ack callback to event');
rob@76 323 args.push(this.ack(packet.id));
rob@76 324 }
rob@76 325
rob@76 326 emit.apply(this, args);
rob@76 327 };
rob@76 328
rob@76 329 /**
rob@76 330 * Produces an ack callback to emit with an event.
rob@76 331 *
rob@76 332 * @param {Number} packet id
rob@76 333 * @api private
rob@76 334 */
rob@76 335
rob@76 336 Socket.prototype.ack = function(id){
rob@76 337 var self = this;
rob@76 338 var sent = false;
rob@76 339 return function(){
rob@76 340 // prevent double callbacks
rob@76 341 if (sent) return;
rob@76 342 var args = Array.prototype.slice.call(arguments);
rob@76 343 debug('sending ack %j', args);
rob@76 344
rob@76 345 var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK;
rob@76 346 self.packet({
rob@76 347 id: id,
rob@76 348 type: type,
rob@76 349 data: args
rob@76 350 });
rob@76 351 };
rob@76 352 };
rob@76 353
rob@76 354 /**
rob@76 355 * Called upon ack packet.
rc-web@69 356 *
rc-web@69 357 * @api private
rc-web@69 358 */
rc-web@69 359
rob@76 360 Socket.prototype.onack = function(packet){
rob@76 361 var ack = this.acks[packet.id];
rob@76 362 if ('function' == typeof ack) {
rob@76 363 debug('calling ack %s with %j', packet.id, packet.data);
rob@76 364 ack.apply(this, packet.data);
rob@76 365 delete this.acks[packet.id];
rob@76 366 } else {
rob@76 367 debug('bad ack %s', packet.id);
rc-web@69 368 }
rc-web@69 369 };
rc-web@69 370
rc-web@69 371 /**
rob@76 372 * Called upon client disconnect packet.
rc-web@69 373 *
rc-web@69 374 * @api private
rc-web@69 375 */
rc-web@69 376
rob@76 377 Socket.prototype.ondisconnect = function(){
rob@76 378 debug('got disconnect packet');
rob@76 379 this.onclose('client namespace disconnect');
rc-web@69 380 };
rc-web@69 381
rc-web@69 382 /**
rob@76 383 * Called upon closing. Called by `Client`.
rc-web@69 384 *
rob@76 385 * @param {String} reason
rc-web@69 386 * @api private
rc-web@69 387 */
rc-web@69 388
rob@76 389 Socket.prototype.onclose = function(reason){
rob@76 390 if (!this.connected) return this;
rob@76 391 debug('closing socket - reason %s', reason);
rob@76 392 this.leaveAll();
rob@76 393 this.nsp.remove(this);
rob@76 394 this.client.remove(this);
rob@76 395 this.connected = false;
rob@76 396 this.disconnected = true;
rob@76 397 delete this.nsp.connected[this.id];
rob@76 398 this.emit('disconnect', reason);
rc-web@69 399 };
rc-web@69 400
rc-web@69 401 /**
rob@76 402 * Produces an `error` packet.
rc-web@69 403 *
rob@76 404 * @param {Object} error object
rob@76 405 * @api private
rob@76 406 */
rob@76 407
rob@76 408 Socket.prototype.error = function(err){
rob@76 409 this.packet({ type: parser.ERROR, data: err });
rob@76 410 };
rob@76 411
rob@76 412 /**
rob@76 413 * Disconnects this client.
rob@76 414 *
rob@76 415 * @param {Boolean} if `true`, closes the underlying connection
rob@76 416 * @return {Socket} self
rc-web@69 417 * @api public
rc-web@69 418 */
rc-web@69 419
rob@76 420 Socket.prototype.disconnect = function(close){
rob@76 421 if (!this.connected) return this;
rob@76 422 if (close) {
rob@76 423 this.client.disconnect();
rob@76 424 } else {
rob@76 425 this.packet({ type: parser.DISCONNECT });
rob@76 426 this.onclose('server namespace disconnect');
rob@76 427 }
rc-web@69 428 return this;
rc-web@69 429 };