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