rc-web@69
|
1
|
rc-web@69
|
2 /*!
|
rc-web@69
|
3 * socket.io-node
|
rc-web@69
|
4 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
rc-web@69
|
5 * MIT Licensed
|
rc-web@69
|
6 */
|
rc-web@69
|
7
|
rc-web@69
|
8 /**
|
rc-web@69
|
9 * Module dependencies.
|
rc-web@69
|
10 */
|
rc-web@69
|
11
|
rc-web@69
|
12 var parser = require('./parser')
|
rc-web@69
|
13 , util = require('./util')
|
rc-web@69
|
14 , EventEmitter = process.EventEmitter
|
rc-web@69
|
15
|
rc-web@69
|
16 /**
|
rc-web@69
|
17 * Export the constructor.
|
rc-web@69
|
18 */
|
rc-web@69
|
19
|
rc-web@69
|
20 exports = module.exports = Socket;
|
rc-web@69
|
21
|
rc-web@69
|
22 /**
|
rc-web@69
|
23 * Default error event listener to prevent uncaught exceptions.
|
rc-web@69
|
24 */
|
rc-web@69
|
25
|
rc-web@69
|
26 var defaultError = function () {};
|
rc-web@69
|
27
|
rc-web@69
|
28 /**
|
rc-web@69
|
29 * Socket constructor.
|
rc-web@69
|
30 *
|
rc-web@69
|
31 * @param {Manager} manager instance
|
rc-web@69
|
32 * @param {String} session id
|
rc-web@69
|
33 * @param {Namespace} namespace the socket belongs to
|
rc-web@69
|
34 * @param {Boolean} whether the
|
rc-web@69
|
35 * @api public
|
rc-web@69
|
36 */
|
rc-web@69
|
37
|
rc-web@69
|
38 function Socket (manager, id, nsp, readable) {
|
rc-web@69
|
39 this.id = id;
|
rc-web@69
|
40 this.namespace = nsp;
|
rc-web@69
|
41 this.manager = manager;
|
rc-web@69
|
42 this.disconnected = false;
|
rc-web@69
|
43 this.ackPackets = 0;
|
rc-web@69
|
44 this.acks = {};
|
rc-web@69
|
45 this.setFlags();
|
rc-web@69
|
46 this.readable = readable;
|
rc-web@69
|
47 this.store = this.manager.store.client(this.id);
|
rc-web@69
|
48 this.on('error', defaultError);
|
rc-web@69
|
49 };
|
rc-web@69
|
50
|
rc-web@69
|
51 /**
|
rc-web@69
|
52 * Inherits from EventEmitter.
|
rc-web@69
|
53 */
|
rc-web@69
|
54
|
rc-web@69
|
55 Socket.prototype.__proto__ = EventEmitter.prototype;
|
rc-web@69
|
56
|
rc-web@69
|
57 /**
|
rc-web@69
|
58 * Accessor shortcut for the handshake data
|
rc-web@69
|
59 *
|
rc-web@69
|
60 * @api private
|
rc-web@69
|
61 */
|
rc-web@69
|
62
|
rc-web@69
|
63 Socket.prototype.__defineGetter__('handshake', function () {
|
rc-web@69
|
64 return this.manager.handshaken[this.id];
|
rc-web@69
|
65 });
|
rc-web@69
|
66
|
rc-web@69
|
67 /**
|
rc-web@69
|
68 * Accessor shortcut for the transport type
|
rc-web@69
|
69 *
|
rc-web@69
|
70 * @api private
|
rc-web@69
|
71 */
|
rc-web@69
|
72
|
rc-web@69
|
73 Socket.prototype.__defineGetter__('transport', function () {
|
rc-web@69
|
74 return this.manager.transports[this.id].name;
|
rc-web@69
|
75 });
|
rc-web@69
|
76
|
rc-web@69
|
77 /**
|
rc-web@69
|
78 * Accessor shortcut for the logger.
|
rc-web@69
|
79 *
|
rc-web@69
|
80 * @api private
|
rc-web@69
|
81 */
|
rc-web@69
|
82
|
rc-web@69
|
83 Socket.prototype.__defineGetter__('log', function () {
|
rc-web@69
|
84 return this.manager.log;
|
rc-web@69
|
85 });
|
rc-web@69
|
86
|
rc-web@69
|
87 /**
|
rc-web@69
|
88 * JSON message flag.
|
rc-web@69
|
89 *
|
rc-web@69
|
90 * @api public
|
rc-web@69
|
91 */
|
rc-web@69
|
92
|
rc-web@69
|
93 Socket.prototype.__defineGetter__('json', function () {
|
rc-web@69
|
94 this.flags.json = true;
|
rc-web@69
|
95 return this;
|
rc-web@69
|
96 });
|
rc-web@69
|
97
|
rc-web@69
|
98 /**
|
rc-web@69
|
99 * Volatile message flag.
|
rc-web@69
|
100 *
|
rc-web@69
|
101 * @api public
|
rc-web@69
|
102 */
|
rc-web@69
|
103
|
rc-web@69
|
104 Socket.prototype.__defineGetter__('volatile', function () {
|
rc-web@69
|
105 this.flags.volatile = true;
|
rc-web@69
|
106 return this;
|
rc-web@69
|
107 });
|
rc-web@69
|
108
|
rc-web@69
|
109 /**
|
rc-web@69
|
110 * Broadcast message flag.
|
rc-web@69
|
111 *
|
rc-web@69
|
112 * @api public
|
rc-web@69
|
113 */
|
rc-web@69
|
114
|
rc-web@69
|
115 Socket.prototype.__defineGetter__('broadcast', function () {
|
rc-web@69
|
116 this.flags.broadcast = true;
|
rc-web@69
|
117 return this;
|
rc-web@69
|
118 });
|
rc-web@69
|
119
|
rc-web@69
|
120 /**
|
rc-web@69
|
121 * Overrides the room to broadcast messages to (flag)
|
rc-web@69
|
122 *
|
rc-web@69
|
123 * @api public
|
rc-web@69
|
124 */
|
rc-web@69
|
125
|
rc-web@69
|
126 Socket.prototype.to = Socket.prototype.in = function (room) {
|
rc-web@69
|
127 this.flags.room = room;
|
rc-web@69
|
128 return this;
|
rc-web@69
|
129 };
|
rc-web@69
|
130
|
rc-web@69
|
131 /**
|
rc-web@69
|
132 * Resets flags
|
rc-web@69
|
133 *
|
rc-web@69
|
134 * @api private
|
rc-web@69
|
135 */
|
rc-web@69
|
136
|
rc-web@69
|
137 Socket.prototype.setFlags = function () {
|
rc-web@69
|
138 this.flags = {
|
rc-web@69
|
139 endpoint: this.namespace.name
|
rc-web@69
|
140 , room: ''
|
rc-web@69
|
141 };
|
rc-web@69
|
142 return this;
|
rc-web@69
|
143 };
|
rc-web@69
|
144
|
rc-web@69
|
145 /**
|
rc-web@69
|
146 * Triggered on disconnect
|
rc-web@69
|
147 *
|
rc-web@69
|
148 * @api private
|
rc-web@69
|
149 */
|
rc-web@69
|
150
|
rc-web@69
|
151 Socket.prototype.onDisconnect = function (reason) {
|
rc-web@69
|
152 if (!this.disconnected) {
|
rc-web@69
|
153 this.$emit('disconnect', reason);
|
rc-web@69
|
154 this.disconnected = true;
|
rc-web@69
|
155 }
|
rc-web@69
|
156 };
|
rc-web@69
|
157
|
rc-web@69
|
158 /**
|
rc-web@69
|
159 * Joins a user to a room.
|
rc-web@69
|
160 *
|
rc-web@69
|
161 * @api public
|
rc-web@69
|
162 */
|
rc-web@69
|
163
|
rc-web@69
|
164 Socket.prototype.join = function (name, fn) {
|
rc-web@69
|
165 var nsp = this.namespace.name
|
rc-web@69
|
166 , name = (nsp + '/') + name;
|
rc-web@69
|
167
|
rc-web@69
|
168 this.manager.onJoin(this.id, name);
|
rc-web@69
|
169 this.manager.store.publish('join', this.id, name);
|
rc-web@69
|
170
|
rc-web@69
|
171 if (fn) {
|
rc-web@69
|
172 this.log.warn('Client#join callback is deprecated');
|
rc-web@69
|
173 fn();
|
rc-web@69
|
174 }
|
rc-web@69
|
175
|
rc-web@69
|
176 return this;
|
rc-web@69
|
177 };
|
rc-web@69
|
178
|
rc-web@69
|
179 /**
|
rc-web@69
|
180 * Un-joins a user from a room.
|
rc-web@69
|
181 *
|
rc-web@69
|
182 * @api public
|
rc-web@69
|
183 */
|
rc-web@69
|
184
|
rc-web@69
|
185 Socket.prototype.leave = function (name, fn) {
|
rc-web@69
|
186 var nsp = this.namespace.name
|
rc-web@69
|
187 , name = (nsp + '/') + name;
|
rc-web@69
|
188
|
rc-web@69
|
189 this.manager.onLeave(this.id, name);
|
rc-web@69
|
190 this.manager.store.publish('leave', this.id, name);
|
rc-web@69
|
191
|
rc-web@69
|
192 if (fn) {
|
rc-web@69
|
193 this.log.warn('Client#leave callback is deprecated');
|
rc-web@69
|
194 fn();
|
rc-web@69
|
195 }
|
rc-web@69
|
196
|
rc-web@69
|
197 return this;
|
rc-web@69
|
198 };
|
rc-web@69
|
199
|
rc-web@69
|
200 /**
|
rc-web@69
|
201 * Transmits a packet.
|
rc-web@69
|
202 *
|
rc-web@69
|
203 * @api private
|
rc-web@69
|
204 */
|
rc-web@69
|
205
|
rc-web@69
|
206 Socket.prototype.packet = function (packet) {
|
rc-web@69
|
207 if (this.flags.broadcast) {
|
rc-web@69
|
208 this.log.debug('broadcasting packet');
|
rc-web@69
|
209 this.namespace.in(this.flags.room).except(this.id).packet(packet);
|
rc-web@69
|
210 } else {
|
rc-web@69
|
211 packet.endpoint = this.flags.endpoint;
|
rc-web@69
|
212 packet = parser.encodePacket(packet);
|
rc-web@69
|
213
|
rc-web@69
|
214 this.dispatch(packet, this.flags.volatile);
|
rc-web@69
|
215 }
|
rc-web@69
|
216
|
rc-web@69
|
217 this.setFlags();
|
rc-web@69
|
218
|
rc-web@69
|
219 return this;
|
rc-web@69
|
220 };
|
rc-web@69
|
221
|
rc-web@69
|
222 /**
|
rc-web@69
|
223 * Dispatches a packet
|
rc-web@69
|
224 *
|
rc-web@69
|
225 * @api private
|
rc-web@69
|
226 */
|
rc-web@69
|
227
|
rc-web@69
|
228 Socket.prototype.dispatch = function (packet, volatile) {
|
rc-web@69
|
229 if (this.manager.transports[this.id] && this.manager.transports[this.id].open) {
|
rc-web@69
|
230 this.manager.transports[this.id].onDispatch(packet, volatile);
|
rc-web@69
|
231 } else {
|
rc-web@69
|
232 if (!volatile) {
|
rc-web@69
|
233 this.manager.onClientDispatch(this.id, packet, volatile);
|
rc-web@69
|
234 }
|
rc-web@69
|
235
|
rc-web@69
|
236 this.manager.store.publish('dispatch:' + this.id, packet, volatile);
|
rc-web@69
|
237 }
|
rc-web@69
|
238 };
|
rc-web@69
|
239
|
rc-web@69
|
240 /**
|
rc-web@69
|
241 * Stores data for the client.
|
rc-web@69
|
242 *
|
rc-web@69
|
243 * @api public
|
rc-web@69
|
244 */
|
rc-web@69
|
245
|
rc-web@69
|
246 Socket.prototype.set = function (key, value, fn) {
|
rc-web@69
|
247 this.store.set(key, value, fn);
|
rc-web@69
|
248 return this;
|
rc-web@69
|
249 };
|
rc-web@69
|
250
|
rc-web@69
|
251 /**
|
rc-web@69
|
252 * Retrieves data for the client
|
rc-web@69
|
253 *
|
rc-web@69
|
254 * @api public
|
rc-web@69
|
255 */
|
rc-web@69
|
256
|
rc-web@69
|
257 Socket.prototype.get = function (key, fn) {
|
rc-web@69
|
258 this.store.get(key, fn);
|
rc-web@69
|
259 return this;
|
rc-web@69
|
260 };
|
rc-web@69
|
261
|
rc-web@69
|
262 /**
|
rc-web@69
|
263 * Checks data for the client
|
rc-web@69
|
264 *
|
rc-web@69
|
265 * @api public
|
rc-web@69
|
266 */
|
rc-web@69
|
267
|
rc-web@69
|
268 Socket.prototype.has = function (key, fn) {
|
rc-web@69
|
269 this.store.has(key, fn);
|
rc-web@69
|
270 return this;
|
rc-web@69
|
271 };
|
rc-web@69
|
272
|
rc-web@69
|
273 /**
|
rc-web@69
|
274 * Deletes data for the client
|
rc-web@69
|
275 *
|
rc-web@69
|
276 * @api public
|
rc-web@69
|
277 */
|
rc-web@69
|
278
|
rc-web@69
|
279 Socket.prototype.del = function (key, fn) {
|
rc-web@69
|
280 this.store.del(key, fn);
|
rc-web@69
|
281 return this;
|
rc-web@69
|
282 };
|
rc-web@69
|
283
|
rc-web@69
|
284 /**
|
rc-web@69
|
285 * Kicks client
|
rc-web@69
|
286 *
|
rc-web@69
|
287 * @api public
|
rc-web@69
|
288 */
|
rc-web@69
|
289
|
rc-web@69
|
290 Socket.prototype.disconnect = function () {
|
rc-web@69
|
291 if (!this.disconnected) {
|
rc-web@69
|
292 this.log.info('booting client');
|
rc-web@69
|
293
|
rc-web@69
|
294 if ('' === this.namespace.name) {
|
rc-web@69
|
295 if (this.manager.transports[this.id] && this.manager.transports[this.id].open) {
|
rc-web@69
|
296 this.manager.transports[this.id].onForcedDisconnect();
|
rc-web@69
|
297 } else {
|
rc-web@69
|
298 this.manager.onClientDisconnect(this.id);
|
rc-web@69
|
299 this.manager.store.publish('disconnect:' + this.id);
|
rc-web@69
|
300 }
|
rc-web@69
|
301 } else {
|
rc-web@69
|
302 this.packet({type: 'disconnect'});
|
rc-web@69
|
303 this.manager.onLeave(this.id, this.namespace.name);
|
rc-web@69
|
304 this.$emit('disconnect', 'booted');
|
rc-web@69
|
305 }
|
rc-web@69
|
306
|
rc-web@69
|
307 }
|
rc-web@69
|
308
|
rc-web@69
|
309 return this;
|
rc-web@69
|
310 };
|
rc-web@69
|
311
|
rc-web@69
|
312 /**
|
rc-web@69
|
313 * Send a message.
|
rc-web@69
|
314 *
|
rc-web@69
|
315 * @api public
|
rc-web@69
|
316 */
|
rc-web@69
|
317
|
rc-web@69
|
318 Socket.prototype.send = function (data, fn) {
|
rc-web@69
|
319 var packet = {
|
rc-web@69
|
320 type: this.flags.json ? 'json' : 'message'
|
rc-web@69
|
321 , data: data
|
rc-web@69
|
322 };
|
rc-web@69
|
323
|
rc-web@69
|
324 if (fn) {
|
rc-web@69
|
325 packet.id = ++this.ackPackets;
|
rc-web@69
|
326 packet.ack = true;
|
rc-web@69
|
327 this.acks[packet.id] = fn;
|
rc-web@69
|
328 }
|
rc-web@69
|
329
|
rc-web@69
|
330 return this.packet(packet);
|
rc-web@69
|
331 };
|
rc-web@69
|
332
|
rc-web@69
|
333 /**
|
rc-web@69
|
334 * Original emit function.
|
rc-web@69
|
335 *
|
rc-web@69
|
336 * @api private
|
rc-web@69
|
337 */
|
rc-web@69
|
338
|
rc-web@69
|
339 Socket.prototype.$emit = EventEmitter.prototype.emit;
|
rc-web@69
|
340
|
rc-web@69
|
341 /**
|
rc-web@69
|
342 * Emit override for custom events.
|
rc-web@69
|
343 *
|
rc-web@69
|
344 * @api public
|
rc-web@69
|
345 */
|
rc-web@69
|
346
|
rc-web@69
|
347 Socket.prototype.emit = function (ev) {
|
rc-web@69
|
348 if (ev == 'newListener') {
|
rc-web@69
|
349 return this.$emit.apply(this, arguments);
|
rc-web@69
|
350 }
|
rc-web@69
|
351
|
rc-web@69
|
352 var args = util.toArray(arguments).slice(1)
|
rc-web@69
|
353 , lastArg = args[args.length - 1]
|
rc-web@69
|
354 , packet = {
|
rc-web@69
|
355 type: 'event'
|
rc-web@69
|
356 , name: ev
|
rc-web@69
|
357 };
|
rc-web@69
|
358
|
rc-web@69
|
359 if ('function' == typeof lastArg) {
|
rc-web@69
|
360 packet.id = ++this.ackPackets;
|
rc-web@69
|
361 packet.ack = lastArg.length ? 'data' : true;
|
rc-web@69
|
362 this.acks[packet.id] = lastArg;
|
rc-web@69
|
363 args = args.slice(0, args.length - 1);
|
rc-web@69
|
364 }
|
rc-web@69
|
365
|
rc-web@69
|
366 packet.args = args;
|
rc-web@69
|
367
|
rc-web@69
|
368 return this.packet(packet);
|
rc-web@69
|
369 };
|