UNPKG

4.47 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 * Sends a packet.
47 *
48 * @api private
49 */
50
51 SocketNamespace.prototype.packet = function (packet) {
52 packet.endpoint = this.name;
53 this.socket.packet(packet);
54 this.flags = {};
55 return this;
56 };
57
58 /**
59 * Sends a message
60 *
61 * @api public
62 */
63
64 SocketNamespace.prototype.send = function (data, fn) {
65 var packet = {
66 type: this.flags.json ? 'json' : 'message'
67 , data: data
68 };
69
70 if ('function' == typeof fn) {
71 packet.id = ++this.ackPackets;
72 packet.ack = true;
73 this.acks[packet.id] = fn;
74 }
75
76 return this.packet(packet);
77 };
78
79 /**
80 * Emits an event
81 *
82 * @api public
83 */
84
85 SocketNamespace.prototype.emit = function (name) {
86 var args = Array.prototype.slice.call(arguments, 1)
87 , lastArg = args[args.length - 1]
88 , packet = {
89 type: 'event'
90 , name: name
91 };
92
93 if ('function' == typeof lastArg) {
94 packet.id = ++this.ackPackets;
95 packet.ack = 'data';
96 this.acks[packet.id] = lastArg;
97 args = args.slice(0, args.length - 1);
98 }
99
100 packet.args = args;
101
102 return this.packet(packet);
103 };
104
105 /**
106 * Disconnects the namespace
107 *
108 * @api private
109 */
110
111 SocketNamespace.prototype.disconnect = function () {
112 if (this.name === '') {
113 this.socket.disconnect();
114 } else {
115 this.packet({ type: 'disconnect' });
116 this.$emit('disconnect');
117 }
118
119 return this;
120 };
121
122 /**
123 * Handles a packet
124 *
125 * @api private
126 */
127
128 SocketNamespace.prototype.onPacket = function (packet) {
129 var self = this;
130
131 function ack () {
132 self.packet({
133 type: 'ack'
134 , args: io.util.toArray(arguments)
135 , ackId: packet.id
136 });
137 };
138
139 switch (packet.type) {
140 case 'connect':
141 this.$emit('connect');
142 break;
143
144 case 'disconnect':
145 if (this.name === '') {
146 this.socket.onDisconnect(packet.reason || 'booted');
147 } else {
148 this.$emit('disconnect', packet.reason);
149 }
150 break;
151
152 case 'message':
153 case 'json':
154 var params = ['message', packet.data];
155
156 if (packet.ack == 'data') {
157 params.push(ack);
158 } else if (packet.ack) {
159 this.packet({ type: 'ack', ackId: packet.id });
160 }
161
162 this.$emit.apply(this, params);
163 break;
164
165 case 'event':
166 var params = [packet.name].concat(packet.args);
167
168 if (packet.ack == 'data')
169 params.push(ack);
170
171 this.$emit.apply(this, params);
172 break;
173
174 case 'ack':
175 if (this.acks[packet.ackId]) {
176 this.acks[packet.ackId].apply(this, packet.args);
177 delete this.acks[packet.ackId];
178 }
179 break;
180
181 case 'error':
182 if (packet.advice){
183 this.socket.onError(packet);
184 } else {
185 if (packet.reason == 'unauthorized') {
186 this.$emit('connect_failed', packet.reason);
187 } else {
188 this.$emit('error', packet.reason);
189 }
190 }
191 break;
192 }
193 };
194
195 /**
196 * Flag interface.
197 *
198 * @api private
199 */
200
201 function Flag (nsp, name) {
202 this.namespace = nsp;
203 this.name = name;
204 };
205
206 /**
207 * Send a message
208 *
209 * @api public
210 */
211
212 Flag.prototype.send = function () {
213 this.namespace.flags[this.name] = true;
214 this.namespace.send.apply(this.namespace, arguments);
215 };
216
217 /**
218 * Emit an event
219 *
220 * @api public
221 */
222
223 Flag.prototype.emit = function () {
224 this.namespace.flags[this.name] = true;
225 this.namespace.emit.apply(this.namespace, arguments);
226 };
227
228})(
229 'undefined' != typeof io ? io : module.exports
230 , 'undefined' != typeof io ? io : module.parent.exports
231);