Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

New xhr transport based on socket.io

  • Loading branch information...
commit fe7fd92eaae6b66beeb799ddeaa187b7847e1b70 1 parent ef96f0a
@felixge authored
Showing with 186 additions and 132 deletions.
  1. +1 −0  benchmark.js
  2. +30 −132 transport/xhr_polling.js
  3. +155 −0 transport/xhr_polling_custom.js
View
1  benchmark.js
@@ -1,6 +1,7 @@
var options = require('commander');
var transports = {
'xhr-polling': require('./transport/xhr_polling'),
+ 'xhr-polling-custom': require('./transport/xhr_polling_custom'),
'websocket': require('./transport/websocket')
};
options
View
162 transport/xhr_polling.js
@@ -1,155 +1,53 @@
-var http = require('http');
-var querystring = require('querystring');
-var clients = [];
+var io = require('socket.io-client');
var EventEmitter = require('events').EventEmitter;
-var util = require('util');
+var util = require('util');
module.exports = XhrPolling;
util.inherits(XhrPolling, EventEmitter);
+
function XhrPolling() {
EventEmitter.call(this);
- this.port = null;
- this.host = null;
- this.connecting = false;
- this.connected = false;
- this.pollTimeout = 20 * 1000;
- this.connectionTimeout = 3 * 1000;
- this.sessionId = null;
- this.transport = 'xhr-polling';
-
- this._request = null;
- this._requestTimeout = null;
+ this.connection = null;
+ this.port = null;
+ this.host = null;
}
XhrPolling.create = function(port, host) {
- var instance = new this();
+ var instance = new this();
instance.port = port;
instance.host = host;
+
return instance;
-};
+}
XhrPolling.prototype.connect = function() {
- this.connecting = true;
- this.handshake();
-};
-
-XhrPolling.prototype.disconnect = function() {
- try {
- this._request.destroy();
- } catch (err) {
- this.emit('error', err);
- }
-};
-
-XhrPolling.prototype.handshake = function() {
var self = this;
- var timeout = setTimeout(function() {
- self.emit('error', new Error('Connection timeout'));
- }, this.connectionTimeout);
-
- this.request(function(err, response) {
- clearTimeout(timeout);
- if (err) return self.emit('error', err);
-
- self.connected = true;
- self.sessionId = response[0];
- self.poll();
- });
-};
-
-XhrPolling.prototype.poll = function() {
- var self = this;
- var timeout = setTimeout(function() {
- self.emit('error', new Error('Poll timeout'));
- }, this.pollTimeout);
-
- this.request(function(err, response) {
- clearTimeout(timeout);
- if (err) return self.emit('error', err);
-
- var type = response[0].replace(/\?[\d]+\?/, '');
-
- if (type === '7') {
- self.emit('error', new Error('Error: ' + JSON.stringify(response)));
- }
-
- // Connected
- if (type === '1') {
- self.connected = true;
- self.connecting = false;
- self.emit('connect');
- self.poll();
- return;
- }
+ io.transports = ['xhr-polling'];
+ this.connection = io.connect(
+ 'http://' + this.host + ':' + this.port,
+ {'force new connection': true}
+ );
- // Event (wtf, why does the regex above not fix this?)
- if (/5$/.test(type)) {
- try{
- var message = JSON.parse(response[3]);
- } catch (err) {
- self.emit(new Error('Could not parse response: ' + JSON.stringify(response)));
- return;
- }
+ this.connection
+ .on('connection', function() { self.emit('connection'); })
+ .on('chat.msg', function(msg) { self.emit('message', {args: [msg]}); })
+ .on('error', this.handleError.bind(this));
- self.emit('message', message);
- self.poll();
- return;
- }
-
- self.emit('error', new Error('Not implemented: ' + type + ': ' + JSON.stringify(response)));
- });
-};
-
-XhrPolling.prototype.request = function(endpoint, cb) {
- if (typeof endpoint === 'function') {
- cb = endpoint;
- endpoint = '';
- }
-
- var session = '';
- if (this.sessionId) {
- session = this.transport + '/' + this.sessionId;
- }
-
- var path = '/socket.io/1/' + session + endpoint;
- var options = {
- host: this.host,
- port: this.port,
- path: path,
- };
-
- var agent = http.getAgent(options.host, options.port)
- agent.maxSockets = 1000;
-
- this._request = http.get(options, this.handleResponse.bind(this, cb));
-
- var self = this;
- this._request.on('error', function(err) {
- self.emit('error', err);
- });
-};
-
-XhrPolling.prototype.handleResponse = function(cb, res) {
- var data = '';
- res.setEncoding('utf8');
- res
- .on('data', function(chunk) {
- data += chunk;
- })
- .on('end', function() {
- var message = [];
+ this.connection.socket.on('error', this.handleError.bind(this));
+}
- for (var i = 0; i < 3; i++) {
- var end = data.indexOf(':');
- message[i] = data.substr(0, end);
- data = data.substr(end + 1);
- }
+XhrPolling.prototype.handleError = function(error) {
+ var err = typeof error === 'string' ? new Error(error) : error;
+ this.emit('error', err);
+}
- message[3] = data;
+XhrPolling.prototype.send = function(message) {
+ this.connection.emit('chat.send', message);
+}
- cb(null, message);
- });
-};
+XhrPolling.prototype.disconnect = function() {
+ this.connection.disconnect();
+}
View
155 transport/xhr_polling_custom.js
@@ -0,0 +1,155 @@
+var http = require('http');
+var querystring = require('querystring');
+var clients = [];
+var EventEmitter = require('events').EventEmitter;
+var util = require('util');
+
+module.exports = XhrPolling;
+util.inherits(XhrPolling, EventEmitter);
+function XhrPolling() {
+ EventEmitter.call(this);
+
+ this.port = null;
+ this.host = null;
+ this.connecting = false;
+ this.connected = false;
+ this.pollTimeout = 20 * 1000;
+ this.connectionTimeout = 3 * 1000;
+ this.sessionId = null;
+ this.transport = 'xhr-polling';
+
+ this._request = null;
+ this._requestTimeout = null;
+}
+
+XhrPolling.create = function(port, host) {
+ var instance = new this();
+ instance.port = port;
+ instance.host = host;
+ return instance;
+};
+
+XhrPolling.prototype.connect = function() {
+ this.connecting = true;
+ this.handshake();
+};
+
+XhrPolling.prototype.disconnect = function() {
+ try {
+ this._request.destroy();
+ } catch (err) {
+ this.emit('error', err);
+ }
+};
+
+XhrPolling.prototype.handshake = function() {
+ var self = this;
+ var timeout = setTimeout(function() {
+ self.emit('error', new Error('Connection timeout'));
+ }, this.connectionTimeout);
+
+ this.request(function(err, response) {
+ clearTimeout(timeout);
+ if (err) return self.emit('error', err);
+
+ self.connected = true;
+ self.sessionId = response[0];
+ self.poll();
+ });
+};
+
+XhrPolling.prototype.poll = function() {
+ var self = this;
+ var timeout = setTimeout(function() {
+ self.emit('error', new Error('Poll timeout'));
+ }, this.pollTimeout);
+
+ this.request(function(err, response) {
+ clearTimeout(timeout);
+ if (err) return self.emit('error', err);
+
+ var type = response[0].replace(/\?[\d]+\?/, '');
+
+ if (type === '7') {
+ self.emit('error', new Error('Error: ' + JSON.stringify(response)));
+ }
+
+ // Connected
+ if (type === '1') {
+ self.connected = true;
+ self.connecting = false;
+ self.emit('connect');
+ self.poll();
+
+ return;
+ }
+
+ // Event (wtf, why does the regex above not fix this?)
+ if (/5$/.test(type)) {
+ try{
+ var message = JSON.parse(response[3]);
+ } catch (err) {
+ self.emit(new Error('Could not parse response: ' + JSON.stringify(response)));
+
+ return;
+ }
+
+ self.emit('message', message);
+ self.poll();
+ return;
+ }
+
+ self.emit('error', new Error('Not implemented: ' + type + ': ' + JSON.stringify(response)));
+ });
+};
+
+XhrPolling.prototype.request = function(endpoint, cb) {
+ if (typeof endpoint === 'function') {
+ cb = endpoint;
+ endpoint = '';
+ }
+
+ var session = '';
+ if (this.sessionId) {
+ session = this.transport + '/' + this.sessionId;
+ }
+
+ var path = '/socket.io/1/' + session + endpoint;
+ var options = {
+ host: this.host,
+ port: this.port,
+ path: path,
+ };
+
+ var agent = http.getAgent(options.host, options.port)
+ agent.maxSockets = 1000;
+
+ this._request = http.get(options, this.handleResponse.bind(this, cb));
+
+ var self = this;
+ this._request.on('error', function(err) {
+ self.emit('error', err);
+ });
+};
+
+XhrPolling.prototype.handleResponse = function(cb, res) {
+ var data = '';
+ res.setEncoding('utf8');
+ res
+ .on('data', function(chunk) {
+ data += chunk;
+ })
+ .on('end', function() {
+ var message = [];
+
+ for (var i = 0; i < 3; i++) {
+ var end = data.indexOf(':');
+ message[i] = data.substr(0, end);
+ data = data.substr(end + 1);
+ }
+
+ message[3] = data;
+
+ cb(null, message);
+ });
+};
Please sign in to comment.
Something went wrong with that request. Please try again.