UNPKG

4.74 kBJavaScriptView Raw
1/**
2 * socket.io
3 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
4 * MIT Licensed
5 */
6
7(function (exports, io) {
8
9 /**
10 * Expose constructor.
11 */
12
13 exports.SocketNamespace = SocketNamespace;
14
15 /**
16 * Socket namespace constructor.
17 *
18 * @constructor
19 * @api public
20 */
21
22 function SocketNamespace (socket, name) {
23 this.socket = socket;
24 this.name = name || '';
25 this.flags = {};
26 this.json = new Flag(this, 'json');
27 this.ackPackets = 0;
28 this.acks = {};
29 };
30
31 /**
32 * Apply EventEmitter mixin.
33 */
34
35 io.util.mixin(SocketNamespace, io.EventEmitter);
36
37 /**
38 * Copies emit since we override it
39 *
40 * @api private
41 */
42
43 SocketNamespace.prototype.$emit = io.EventEmitter.prototype.emit;
44
45 /**
46 * Creates a new namespace, by proxying the request to the socket. This
47 * allows us to use the synax as we do on the server.
48 *
49 * @api public
50 */
51
52 SocketNamespace.prototype.of = function () {
53 return this.socket.of.apply(this.socket, arguments);
54 };
55
56 /**
57 * Sends a packet.
58 *
59 * @api private
60 */
61
62 SocketNamespace.prototype.packet = function (packet) {
63 packet.endpoint = this.name;
64 this.socket.packet(packet);
65 this.flags = {};
66 return this;
67 };
68
69 /**
70 * Sends a message
71 *
72 * @api public
73 */
74
75 SocketNamespace.prototype.send = function (data, fn) {
76 var packet = {
77 type: this.flags.json ? 'json' : 'message'
78 , data: data
79 };
80
81 if ('function' == typeof fn) {
82 packet.id = ++this.ackPackets;
83 packet.ack = true;
84 this.acks[packet.id] = fn;
85 }
86
87 return this.packet(packet);
88 };
89
90 /**
91 * Emits an event
92 *
93 * @api public
94 */
95
96 SocketNamespace.prototype.emit = function (name) {
97 var args = Array.prototype.slice.call(arguments, 1)
98 , lastArg = args[args.length - 1]
99 , packet = {
100 type: 'event'
101 , name: name
102 };
103
104 if ('function' == typeof lastArg) {
105 packet.id = ++this.ackPackets;
106 packet.ack = 'data';
107 this.acks[packet.id] = lastArg;
108 args = args.slice(0, args.length - 1);
109 }
110
111 packet.args = args;
112
113 return this.packet(packet);
114 };
115
116 /**
117 * Disconnects the namespace
118 *
119 * @api private
120 */
121
122 SocketNamespace.prototype.disconnect = function () {
123 if (this.name === '') {
124 this.socket.disconnect();
125 } else {
126 this.packet({ type: 'disconnect' });
127 this.$emit('disconnect');
128 }
129
130 return this;
131 };
132
133 /**
134 * Handles a packet
135 *
136 * @api private
137 */
138
139 SocketNamespace.prototype.onPacket = function (packet) {
140 var self = this;
141
142 function ack () {
143 self.packet({
144 type: 'ack'
145 , args: io.util.toArray(arguments)
146 , ackId: packet.id
147 });
148 };
149
150 switch (packet.type) {
151 case 'connect':
152 this.$emit('connect');
153 break;
154
155 case 'disconnect':
156 if (this.name === '') {
157 this.socket.onDisconnect(packet.reason || 'booted');
158 } else {
159 this.$emit('disconnect', packet.reason);
160 }
161 break;
162
163 case 'message':
164 case 'json':
165 var params = ['message', packet.data];
166
167 if (packet.ack == 'data') {
168 params.push(ack);
169 } else if (packet.ack) {
170 this.packet({ type: 'ack', ackId: packet.id });
171 }
172
173 this.$emit.apply(this, params);
174 break;
175
176 case 'event':
177 var params = [packet.name].concat(packet.args);
178
179 if (packet.ack == 'data')
180 params.push(ack);
181
182 this.$emit.apply(this, params);
183 break;
184
185 case 'ack':
186 if (this.acks[packet.ackId]) {
187 this.acks[packet.ackId].apply(this, packet.args);
188 delete this.acks[packet.ackId];
189 }
190 break;
191
192 case 'error':
193 if (packet.advice){
194 this.socket.onError(packet);
195 } else {
196 if (packet.reason == 'unauthorized') {
197 this.$emit('connect_failed', packet.reason);
198 } else {
199 this.$emit('error', packet.reason);
200 }
201 }
202 break;
203 }
204 };
205
206 /**
207 * Flag interface.
208 *
209 * @api private
210 */
211
212 function Flag (nsp, name) {
213 this.namespace = nsp;
214 this.name = name;
215 };
216
217 /**
218 * Send a message
219 *
220 * @api public
221 */
222
223 Flag.prototype.send = function () {
224 this.namespace.flags[this.name] = true;
225 this.namespace.send.apply(this.namespace, arguments);
226 };
227
228 /**
229 * Emit an event
230 *
231 * @api public
232 */
233
234 Flag.prototype.emit = function () {
235 this.namespace.flags[this.name] = true;
236 this.namespace.emit.apply(this.namespace, arguments);
237 };
238
239})(
240 'undefined' != typeof io ? io : module.exports
241 , 'undefined' != typeof io ? io : module.parent.exports
242);