twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

index.js (5421B)


      1 
      2 /**
      3  * Module dependencies.
      4  */
      5 
      6 var Emitter = require('events').EventEmitter;
      7 
      8 /**
      9  * Module exports.
     10  */
     11 
     12 module.exports = Adapter;
     13 
     14 /**
     15  * Memory adapter constructor.
     16  *
     17  * @param {Namespace} nsp
     18  * @api public
     19  */
     20 
     21 function Adapter(nsp){
     22   this.nsp = nsp;
     23   this.rooms = {};
     24   this.sids = {};
     25   this.encoder = nsp.server.encoder;
     26 }
     27 
     28 /**
     29  * Inherits from `EventEmitter`.
     30  */
     31 
     32 Adapter.prototype.__proto__ = Emitter.prototype;
     33 
     34 /**
     35  * Adds a socket to a room.
     36  *
     37  * @param {String} socket id
     38  * @param {String} room name
     39  * @param {Function} callback
     40  * @api public
     41  */
     42 
     43 Adapter.prototype.add = function(id, room, fn){
     44   return this.addAll(id, [ room ], fn);
     45 };
     46 
     47 /**
     48  * Adds a socket to a list of room.
     49  *
     50  * @param {String} socket id
     51  * @param {String} rooms
     52  * @param {Function} callback
     53  * @api public
     54  */
     55 
     56 Adapter.prototype.addAll = function(id, rooms, fn){
     57   for (var i = 0; i < rooms.length; i++) {
     58     var room = rooms[i];
     59     this.sids[id] = this.sids[id] || {};
     60     this.sids[id][room] = true;
     61     this.rooms[room] = this.rooms[room] || Room();
     62     this.rooms[room].add(id);
     63   }
     64   if (fn) process.nextTick(fn.bind(null, null));
     65 };
     66 
     67 /**
     68  * Removes a socket from a room.
     69  *
     70  * @param {String} socket id
     71  * @param {String} room name
     72  * @param {Function} callback
     73  * @api public
     74  */
     75 
     76 Adapter.prototype.del = function(id, room, fn){
     77   if (this.sids[id]) delete this.sids[id][room];
     78 
     79   if (this.rooms.hasOwnProperty(room)) {
     80     this.rooms[room].del(id);
     81     if (this.rooms[room].length === 0) delete this.rooms[room];
     82   }
     83 
     84   if (fn) process.nextTick(fn.bind(null, null));
     85 };
     86 
     87 /**
     88  * Removes a socket from all rooms it's joined.
     89  *
     90  * @param {String} socket id
     91  * @param {Function} callback
     92  * @api public
     93  */
     94 
     95 Adapter.prototype.delAll = function(id, fn){
     96   var rooms = this.sids[id];
     97   if (rooms) {
     98     for (var room in rooms) {
     99       if (this.rooms.hasOwnProperty(room)) {
    100         this.rooms[room].del(id);
    101         if (this.rooms[room].length === 0) delete this.rooms[room];
    102       }
    103     }
    104   }
    105   delete this.sids[id];
    106 
    107   if (fn) process.nextTick(fn.bind(null, null));
    108 };
    109 
    110 /**
    111  * Broadcasts a packet.
    112  *
    113  * Options:
    114  *  - `flags` {Object} flags for this packet
    115  *  - `except` {Array} sids that should be excluded
    116  *  - `rooms` {Array} list of rooms to broadcast to
    117  *
    118  * @param {Object} packet object
    119  * @api public
    120  */
    121 
    122 Adapter.prototype.broadcast = function(packet, opts){
    123   var rooms = opts.rooms || [];
    124   var except = opts.except || [];
    125   var flags = opts.flags || {};
    126   var packetOpts = {
    127     preEncoded: true,
    128     volatile: flags.volatile,
    129     compress: flags.compress
    130   };
    131   var ids = {};
    132   var self = this;
    133   var socket;
    134 
    135   packet.nsp = this.nsp.name;
    136   this.encoder.encode(packet, function(encodedPackets) {
    137     if (rooms.length) {
    138       for (var i = 0; i < rooms.length; i++) {
    139         var room = self.rooms[rooms[i]];
    140         if (!room) continue;
    141         var sockets = room.sockets;
    142         for (var id in sockets) {
    143           if (sockets.hasOwnProperty(id)) {
    144             if (ids[id] || ~except.indexOf(id)) continue;
    145             socket = self.nsp.connected[id];
    146             if (socket) {
    147               socket.packet(encodedPackets, packetOpts);
    148               ids[id] = true;
    149             }
    150           }
    151         }
    152       }
    153     } else {
    154       for (var id in self.sids) {
    155         if (self.sids.hasOwnProperty(id)) {
    156           if (~except.indexOf(id)) continue;
    157           socket = self.nsp.connected[id];
    158           if (socket) socket.packet(encodedPackets, packetOpts);
    159         }
    160       }
    161     }
    162   });
    163 };
    164 
    165 /**
    166  * Gets a list of clients by sid.
    167  *
    168  * @param {Array} explicit set of rooms to check.
    169  * @param {Function} callback
    170  * @api public
    171  */
    172 
    173 Adapter.prototype.clients = function(rooms, fn){
    174   if ('function' == typeof rooms){
    175     fn = rooms;
    176     rooms = null;
    177   }
    178 
    179   rooms = rooms || [];
    180 
    181   var ids = {};
    182   var sids = [];
    183   var socket;
    184 
    185   if (rooms.length) {
    186     for (var i = 0; i < rooms.length; i++) {
    187       var room = this.rooms[rooms[i]];
    188       if (!room) continue;
    189       var sockets = room.sockets;
    190       for (var id in sockets) {
    191         if (sockets.hasOwnProperty(id)) {
    192           if (ids[id]) continue;
    193           socket = this.nsp.connected[id];
    194           if (socket) {
    195             sids.push(id);
    196             ids[id] = true;
    197           }
    198         }
    199       }
    200     }
    201   } else {
    202     for (var id in this.sids) {
    203       if (this.sids.hasOwnProperty(id)) {
    204         socket = this.nsp.connected[id];
    205         if (socket) sids.push(id);
    206       }
    207     }
    208   }
    209 
    210   if (fn) process.nextTick(fn.bind(null, null, sids));
    211 };
    212 
    213 /**
    214  * Gets the list of rooms a given client has joined.
    215  *
    216  * @param {String} socket id
    217  * @param {Function} callback
    218  * @api public
    219  */
    220 Adapter.prototype.clientRooms = function(id, fn){
    221   var rooms = this.sids[id];
    222   if (fn) process.nextTick(fn.bind(null, null, rooms ? Object.keys(rooms) : null));
    223 };
    224 
    225 /**
    226 * Room constructor.
    227 *
    228 * @api private
    229 */
    230 
    231 function Room(){
    232   if (!(this instanceof Room)) return new Room();
    233   this.sockets = {};
    234   this.length = 0;
    235 }
    236 
    237 /**
    238  * Adds a socket to a room.
    239  *
    240  * @param {String} socket id
    241  * @api private
    242  */
    243 
    244 Room.prototype.add = function(id){
    245   if (!this.sockets.hasOwnProperty(id)) {
    246     this.sockets[id] = true;
    247     this.length++;
    248   }
    249 };
    250 
    251 /**
    252  * Removes a socket from a room.
    253  *
    254  * @param {String} socket id
    255  * @api private
    256  */
    257 
    258 Room.prototype.del = function(id){
    259   if (this.sockets.hasOwnProperty(id)) {
    260     delete this.sockets[id];
    261     this.length--;
    262   }
    263 };