annotate node_modules/socket.io/lib/namespace.js @ 70:753414e075a0

danger stash pop
author tzara <rc-web@kiben.net>
date Sat, 26 Oct 2013 13:43:08 +0000
parents 333afcfd3f3a
children 0ae87af84e2f
rev   line source
rc-web@69 1 /**
rc-web@69 2 * Module dependencies.
rc-web@69 3 */
rc-web@69 4
rc-web@69 5 var Socket = require('./socket')
rc-web@69 6 , EventEmitter = process.EventEmitter
rc-web@69 7 , parser = require('./parser')
rc-web@69 8 , util = require('./util');
rc-web@69 9
rc-web@69 10 /**
rc-web@69 11 * Exports the constructor.
rc-web@69 12 */
rc-web@69 13
rc-web@69 14 exports = module.exports = SocketNamespace;
rc-web@69 15
rc-web@69 16 /**
rc-web@69 17 * Constructor.
rc-web@69 18 *
rc-web@69 19 * @api public.
rc-web@69 20 */
rc-web@69 21
rc-web@69 22 function SocketNamespace (mgr, name) {
rc-web@69 23 this.manager = mgr;
rc-web@69 24 this.name = name || '';
rc-web@69 25 this.sockets = {};
rc-web@69 26 this.auth = false;
rc-web@69 27 this.setFlags();
rc-web@69 28 };
rc-web@69 29
rc-web@69 30 /**
rc-web@69 31 * Inherits from EventEmitter.
rc-web@69 32 */
rc-web@69 33
rc-web@69 34 SocketNamespace.prototype.__proto__ = EventEmitter.prototype;
rc-web@69 35
rc-web@69 36 /**
rc-web@69 37 * Copies emit since we override it.
rc-web@69 38 *
rc-web@69 39 * @api private
rc-web@69 40 */
rc-web@69 41
rc-web@69 42 SocketNamespace.prototype.$emit = EventEmitter.prototype.emit;
rc-web@69 43
rc-web@69 44 /**
rc-web@69 45 * Retrieves all clients as Socket instances as an array.
rc-web@69 46 *
rc-web@69 47 * @api public
rc-web@69 48 */
rc-web@69 49
rc-web@69 50 SocketNamespace.prototype.clients = function (room) {
rc-web@69 51 var room = this.name + (room !== undefined ?
rc-web@69 52 '/' + room : '');
rc-web@69 53
rc-web@69 54 if (!this.manager.rooms[room]) {
rc-web@69 55 return [];
rc-web@69 56 }
rc-web@69 57
rc-web@69 58 return this.manager.rooms[room].map(function (id) {
rc-web@69 59 return this.socket(id);
rc-web@69 60 }, this);
rc-web@69 61 };
rc-web@69 62
rc-web@69 63 /**
rc-web@69 64 * Access logger interface.
rc-web@69 65 *
rc-web@69 66 * @api public
rc-web@69 67 */
rc-web@69 68
rc-web@69 69 SocketNamespace.prototype.__defineGetter__('log', function () {
rc-web@69 70 return this.manager.log;
rc-web@69 71 });
rc-web@69 72
rc-web@69 73 /**
rc-web@69 74 * Access store.
rc-web@69 75 *
rc-web@69 76 * @api public
rc-web@69 77 */
rc-web@69 78
rc-web@69 79 SocketNamespace.prototype.__defineGetter__('store', function () {
rc-web@69 80 return this.manager.store;
rc-web@69 81 });
rc-web@69 82
rc-web@69 83 /**
rc-web@69 84 * JSON message flag.
rc-web@69 85 *
rc-web@69 86 * @api public
rc-web@69 87 */
rc-web@69 88
rc-web@69 89 SocketNamespace.prototype.__defineGetter__('json', function () {
rc-web@69 90 this.flags.json = true;
rc-web@69 91 return this;
rc-web@69 92 });
rc-web@69 93
rc-web@69 94 /**
rc-web@69 95 * Volatile message flag.
rc-web@69 96 *
rc-web@69 97 * @api public
rc-web@69 98 */
rc-web@69 99
rc-web@69 100 SocketNamespace.prototype.__defineGetter__('volatile', function () {
rc-web@69 101 this.flags.volatile = true;
rc-web@69 102 return this;
rc-web@69 103 });
rc-web@69 104
rc-web@69 105 /**
rc-web@69 106 * Overrides the room to relay messages to (flag).
rc-web@69 107 *
rc-web@69 108 * @api public
rc-web@69 109 */
rc-web@69 110
rc-web@69 111 SocketNamespace.prototype.in = SocketNamespace.prototype.to = function (room) {
rc-web@69 112 this.flags.endpoint = this.name + (room ? '/' + room : '');
rc-web@69 113 return this;
rc-web@69 114 };
rc-web@69 115
rc-web@69 116 /**
rc-web@69 117 * Adds a session id we should prevent relaying messages to (flag).
rc-web@69 118 *
rc-web@69 119 * @api public
rc-web@69 120 */
rc-web@69 121
rc-web@69 122 SocketNamespace.prototype.except = function (id) {
rc-web@69 123 this.flags.exceptions.push(id);
rc-web@69 124 return this;
rc-web@69 125 };
rc-web@69 126
rc-web@69 127 /**
rc-web@69 128 * Sets the default flags.
rc-web@69 129 *
rc-web@69 130 * @api private
rc-web@69 131 */
rc-web@69 132
rc-web@69 133 SocketNamespace.prototype.setFlags = function () {
rc-web@69 134 this.flags = {
rc-web@69 135 endpoint: this.name
rc-web@69 136 , exceptions: []
rc-web@69 137 };
rc-web@69 138 return this;
rc-web@69 139 };
rc-web@69 140
rc-web@69 141 /**
rc-web@69 142 * Sends out a packet.
rc-web@69 143 *
rc-web@69 144 * @api private
rc-web@69 145 */
rc-web@69 146
rc-web@69 147 SocketNamespace.prototype.packet = function (packet) {
rc-web@69 148 packet.endpoint = this.name;
rc-web@69 149
rc-web@69 150 var store = this.store
rc-web@69 151 , log = this.log
rc-web@69 152 , volatile = this.flags.volatile
rc-web@69 153 , exceptions = this.flags.exceptions
rc-web@69 154 , packet = parser.encodePacket(packet);
rc-web@69 155
rc-web@69 156 this.manager.onDispatch(this.flags.endpoint, packet, volatile, exceptions);
rc-web@69 157 this.store.publish('dispatch', this.flags.endpoint, packet, volatile, exceptions);
rc-web@69 158
rc-web@69 159 this.setFlags();
rc-web@69 160
rc-web@69 161 return this;
rc-web@69 162 };
rc-web@69 163
rc-web@69 164 /**
rc-web@69 165 * Sends to everyone.
rc-web@69 166 *
rc-web@69 167 * @api public
rc-web@69 168 */
rc-web@69 169
rc-web@69 170 SocketNamespace.prototype.send = function (data) {
rc-web@69 171 return this.packet({
rc-web@69 172 type: this.flags.json ? 'json' : 'message'
rc-web@69 173 , data: data
rc-web@69 174 });
rc-web@69 175 };
rc-web@69 176
rc-web@69 177 /**
rc-web@69 178 * Emits to everyone (override).
rc-web@69 179 *
rc-web@69 180 * @api public
rc-web@69 181 */
rc-web@69 182
rc-web@69 183 SocketNamespace.prototype.emit = function (name) {
rc-web@69 184 if (name == 'newListener') {
rc-web@69 185 return this.$emit.apply(this, arguments);
rc-web@69 186 }
rc-web@69 187
rc-web@69 188 return this.packet({
rc-web@69 189 type: 'event'
rc-web@69 190 , name: name
rc-web@69 191 , args: util.toArray(arguments).slice(1)
rc-web@69 192 });
rc-web@69 193 };
rc-web@69 194
rc-web@69 195 /**
rc-web@69 196 * Retrieves or creates a write-only socket for a client, unless specified.
rc-web@69 197 *
rc-web@69 198 * @param {Boolean} whether the socket will be readable when initialized
rc-web@69 199 * @api public
rc-web@69 200 */
rc-web@69 201
rc-web@69 202 SocketNamespace.prototype.socket = function (sid, readable) {
rc-web@69 203 if (!this.sockets[sid]) {
rc-web@69 204 this.sockets[sid] = new Socket(this.manager, sid, this, readable);
rc-web@69 205 }
rc-web@69 206
rc-web@69 207 return this.sockets[sid];
rc-web@69 208 };
rc-web@69 209
rc-web@69 210 /**
rc-web@69 211 * Sets authorization for this namespace.
rc-web@69 212 *
rc-web@69 213 * @api public
rc-web@69 214 */
rc-web@69 215
rc-web@69 216 SocketNamespace.prototype.authorization = function (fn) {
rc-web@69 217 this.auth = fn;
rc-web@69 218 return this;
rc-web@69 219 };
rc-web@69 220
rc-web@69 221 /**
rc-web@69 222 * Called when a socket disconnects entirely.
rc-web@69 223 *
rc-web@69 224 * @api private
rc-web@69 225 */
rc-web@69 226
rc-web@69 227 SocketNamespace.prototype.handleDisconnect = function (sid, reason, raiseOnDisconnect) {
rc-web@69 228 if (this.sockets[sid] && this.sockets[sid].readable) {
rc-web@69 229 if (raiseOnDisconnect) this.sockets[sid].onDisconnect(reason);
rc-web@69 230 delete this.sockets[sid];
rc-web@69 231 }
rc-web@69 232 };
rc-web@69 233
rc-web@69 234 /**
rc-web@69 235 * Performs authentication.
rc-web@69 236 *
rc-web@69 237 * @param Object client request data
rc-web@69 238 * @api private
rc-web@69 239 */
rc-web@69 240
rc-web@69 241 SocketNamespace.prototype.authorize = function (data, fn) {
rc-web@69 242 if (this.auth) {
rc-web@69 243 var self = this;
rc-web@69 244
rc-web@69 245 this.auth.call(this, data, function (err, authorized) {
rc-web@69 246 self.log.debug('client ' +
rc-web@69 247 (authorized ? '' : 'un') + 'authorized for ' + self.name);
rc-web@69 248 fn(err, authorized);
rc-web@69 249 });
rc-web@69 250 } else {
rc-web@69 251 this.log.debug('client authorized for ' + this.name);
rc-web@69 252 fn(null, true);
rc-web@69 253 }
rc-web@69 254
rc-web@69 255 return this;
rc-web@69 256 };
rc-web@69 257
rc-web@69 258 /**
rc-web@69 259 * Handles a packet.
rc-web@69 260 *
rc-web@69 261 * @api private
rc-web@69 262 */
rc-web@69 263
rc-web@69 264 SocketNamespace.prototype.handlePacket = function (sessid, packet) {
rc-web@69 265 var socket = this.socket(sessid)
rc-web@69 266 , dataAck = packet.ack == 'data'
rc-web@69 267 , manager = this.manager
rc-web@69 268 , self = this;
rc-web@69 269
rc-web@69 270 function ack () {
rc-web@69 271 self.log.debug('sending data ack packet');
rc-web@69 272 socket.packet({
rc-web@69 273 type: 'ack'
rc-web@69 274 , args: util.toArray(arguments)
rc-web@69 275 , ackId: packet.id
rc-web@69 276 });
rc-web@69 277 };
rc-web@69 278
rc-web@69 279 function error (err) {
rc-web@69 280 self.log.warn('handshake error ' + err + ' for ' + self.name);
rc-web@69 281 socket.packet({ type: 'error', reason: err });
rc-web@69 282 };
rc-web@69 283
rc-web@69 284 function connect () {
rc-web@69 285 self.manager.onJoin(sessid, self.name);
rc-web@69 286 self.store.publish('join', sessid, self.name);
rc-web@69 287
rc-web@69 288 // packet echo
rc-web@69 289 socket.packet({ type: 'connect' });
rc-web@69 290
rc-web@69 291 // emit connection event
rc-web@69 292 self.$emit('connection', socket);
rc-web@69 293 };
rc-web@69 294
rc-web@69 295 switch (packet.type) {
rc-web@69 296 case 'connect':
rc-web@69 297 if (packet.endpoint == '') {
rc-web@69 298 connect();
rc-web@69 299 } else {
rc-web@69 300 var handshakeData = manager.handshaken[sessid];
rc-web@69 301
rc-web@69 302 this.authorize(handshakeData, function (err, authorized, newData) {
rc-web@69 303 if (err) return error(err);
rc-web@69 304
rc-web@69 305 if (authorized) {
rc-web@69 306 manager.onHandshake(sessid, newData || handshakeData);
rc-web@69 307 self.store.publish('handshake', sessid, newData || handshakeData);
rc-web@69 308 connect();
rc-web@69 309 } else {
rc-web@69 310 error('unauthorized');
rc-web@69 311 }
rc-web@69 312 });
rc-web@69 313 }
rc-web@69 314 break;
rc-web@69 315
rc-web@69 316 case 'ack':
rc-web@69 317 if (socket.acks[packet.ackId]) {
rc-web@69 318 socket.acks[packet.ackId].apply(socket, packet.args);
rc-web@69 319 } else {
rc-web@69 320 this.log.info('unknown ack packet');
rc-web@69 321 }
rc-web@69 322 break;
rc-web@69 323
rc-web@69 324 case 'event':
rc-web@69 325 // check if the emitted event is not blacklisted
rc-web@69 326 if (-~manager.get('blacklist').indexOf(packet.name)) {
rc-web@69 327 this.log.debug('ignoring blacklisted event `' + packet.name + '`');
rc-web@69 328 } else {
rc-web@69 329 var params = [packet.name].concat(packet.args);
rc-web@69 330
rc-web@69 331 if (dataAck) {
rc-web@69 332 params.push(ack);
rc-web@69 333 }
rc-web@69 334
rc-web@69 335 socket.$emit.apply(socket, params);
rc-web@69 336 }
rc-web@69 337 break;
rc-web@69 338
rc-web@69 339 case 'disconnect':
rc-web@69 340 this.manager.onLeave(sessid, this.name);
rc-web@69 341 this.store.publish('leave', sessid, this.name);
rc-web@69 342
rc-web@69 343 socket.$emit('disconnect', packet.reason || 'packet');
rc-web@69 344 break;
rc-web@69 345
rc-web@69 346 case 'json':
rc-web@69 347 case 'message':
rc-web@69 348 var params = ['message', packet.data];
rc-web@69 349
rc-web@69 350 if (dataAck)
rc-web@69 351 params.push(ack);
rc-web@69 352
rc-web@69 353 socket.$emit.apply(socket, params);
rc-web@69 354 };
rc-web@69 355 };