87 lines
2.4 KiB
JavaScript
87 lines
2.4 KiB
JavaScript
var net = require('net'),
|
|
tls = require('tls');
|
|
|
|
var HybiParser = require('./hybi_parser'),
|
|
API = require('./api'),
|
|
Event = require('./api/event');
|
|
|
|
var Client = function(url, protocols, options) {
|
|
this.url = url;
|
|
this._uri = require('url').parse(url);
|
|
|
|
this.protocol = '';
|
|
this.readyState = API.CONNECTING;
|
|
this.bufferedAmount = 0;
|
|
|
|
var secure = (this._uri.protocol === 'wss:'),
|
|
self = this,
|
|
onConnect = function() { self._onConnect() },
|
|
tlsOptions = {};
|
|
|
|
if (options && options.verify === false) tlsOptions.rejectUnauthorized = false;
|
|
|
|
var connection = secure
|
|
? tls.connect(this._uri.port || 443, this._uri.hostname, tlsOptions, onConnect)
|
|
: net.createConnection(this._uri.port || 80, this._uri.hostname);
|
|
|
|
this._parser = new HybiParser(this, {masking: true, protocols: protocols});
|
|
this._stream = connection;
|
|
|
|
this._stream.setTimeout(0);
|
|
this._stream.setNoDelay(true);
|
|
|
|
if (!secure) connection.addListener('connect', onConnect);
|
|
|
|
connection.addListener('data', function(data) {
|
|
self._onData(data);
|
|
});
|
|
['close', 'end', 'error'].forEach(function(event) {
|
|
connection.addListener(event, function() { self.close(1006, '', false) });
|
|
});
|
|
};
|
|
|
|
Client.prototype._onConnect = function() {
|
|
this._handshake = this._parser.createHandshake(this._uri, this._stream);
|
|
this._message = [];
|
|
try {
|
|
this._stream.write(this._handshake.requestData(), 'binary');
|
|
} catch (e) {}
|
|
};
|
|
|
|
Client.prototype._onData = function(data) {
|
|
switch (this.readyState) {
|
|
case API.CONNECTING:
|
|
var bytes = this._handshake.parse(data);
|
|
for (var i = 0, n = bytes.length; i < n; i++)
|
|
this._message.push(bytes[i]);
|
|
|
|
if (!this._handshake.isComplete()) return;
|
|
|
|
if (this._handshake.isValid()) {
|
|
this.protocol = this._handshake.protocol || '';
|
|
this.readyState = API.OPEN;
|
|
var event = new Event('open');
|
|
event.initEvent('open', false, false);
|
|
this.dispatchEvent(event);
|
|
|
|
this._parser.parse(this._message);
|
|
|
|
} else {
|
|
this.readyState = API.CLOSED;
|
|
var event = new Event('close', {code: 1006, reason: ''});
|
|
event.initEvent('close', false, false);
|
|
this.dispatchEvent(event);
|
|
}
|
|
break;
|
|
|
|
case API.OPEN:
|
|
case API.CLOSING:
|
|
this._parser.parse(data);
|
|
}
|
|
};
|
|
|
|
for (var key in API) Client.prototype[key] = API[key];
|
|
|
|
module.exports = Client;
|
|
|