diff --git a/lib/client.js b/lib/client.js index 32d179f971..5d5aa77940 100644 --- a/lib/client.js +++ b/lib/client.js @@ -163,6 +163,11 @@ Client.prototype.packet = function(packet, opts){ opts = opts || {}; var self = this; + if ('open' != this.conn.readyState) { + debug('ignoring packet write %j', packet); + return; + } + // this writes to the actual connection function writeToEngine(encodedPackets) { if (opts.volatile && !self.conn.transport.writable) return; @@ -171,15 +176,23 @@ Client.prototype.packet = function(packet, opts){ } } - if ('open' == this.conn.readyState) { + if (opts.loopback) { + debug('writing loopback packet %j', packet); + // handle loopback packets as though they came in off the wire. + if (opts.preEncoded) { // a broadcast pre-encodes a packet + for (var i = 0; i < packet.length; i++) { + this.decoder.add(packet[i]); + } + } else { // no broadcasting, no need to decode + this.ondecoded(packet); + } + } else { debug('writing packet %j', packet); if (!opts.preEncoded) { // not broadcasting, need to encode this.encoder.encode(packet, writeToEngine); // encode, then write results to engine } else { // a broadcast pre-encodes a packet writeToEngine(packet); } - } else { - debug('ignoring packet write %j', packet); } }; diff --git a/lib/namespace.js b/lib/namespace.js index 6d0ac17065..85b1090b18 100644 --- a/lib/namespace.js +++ b/lib/namespace.js @@ -30,6 +30,7 @@ exports.events = [ */ exports.flags = [ + 'loopback', 'json', 'volatile', 'local' diff --git a/lib/socket.js b/lib/socket.js index 9a96929728..59f48d3757 100644 --- a/lib/socket.js +++ b/lib/socket.js @@ -37,6 +37,7 @@ exports.events = [ */ var flags = [ + 'loopback', 'json', 'volatile', 'broadcast', @@ -155,6 +156,10 @@ Socket.prototype.emit = function(ev){ throw new Error('Callbacks are not supported when broadcasting'); } + if (this.flags.loopback) { + throw new Error('Callbacks are not supported when emitting loopback messages'); + } + debug('emitting packet with ack id %d', this.nsp.ids); this.acks[this.nsp.ids] = args.pop(); packet.id = this.nsp.ids++; @@ -311,7 +316,7 @@ Socket.prototype.onconnect = function(){ }; /** - * Called with each packet. Called by `Client`. + * Called with each packet. Called by `Client` and `emit` with `loopback` flag. * * @param {Object} packet * @api private diff --git a/test/socket.io.js b/test/socket.io.js index aec781455e..ac0c947562 100644 --- a/test/socket.io.js +++ b/test/socket.io.js @@ -677,7 +677,7 @@ describe('socket.io', function(){ }); }); }); - + it('should not reuse same-namespace connections', function(done){ var srv = http(); var sio = io(srv); @@ -837,6 +837,35 @@ describe('socket.io', function(){ }, 500); }); + it('should emit loopback messages locally', function(done) { + var srv = http(); + var sio = io(srv); + + var local_counter = 0; + var remote_counter = 0; + srv.listen(function(){ + sio.of('/chat').on('connection', function(s){ + setTimeout(function() { + sio.of('/chat').loopback.emit('ev', 'data'); + }, 50); + s.on('ev', function() { + local_counter++; + }); + }); + + var socket = client(srv, '/chat'); + socket.on('ev', function() { + remote_counter++; + }); + }); + + setTimeout(function() { + expect(local_counter).to.be(1); + expect(remote_counter).to.be(0); + done(); + }, 500); + }); + it('should emit volatile event', function(done) { var srv = http(); var sio = io(srv); @@ -1608,7 +1637,7 @@ describe('socket.io', function(){ }); }); }); - + it('should see query parameters sent from secondary namespace connections in handshake object', function(done){ var srv = http(); var sio = io(srv);