You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.2 KiB
113 lines
3.2 KiB
4 weeks ago
|
'use strict';
|
||
|
|
||
|
var util = require('util'),
|
||
|
HttpParser = require('../http_parser'),
|
||
|
Base = require('./base'),
|
||
|
Draft75 = require('./draft75'),
|
||
|
Draft76 = require('./draft76'),
|
||
|
Hybi = require('./hybi');
|
||
|
|
||
|
var Server = function(options) {
|
||
|
Base.call(this, null, null, options);
|
||
|
this._http = new HttpParser('request');
|
||
|
};
|
||
|
util.inherits(Server, Base);
|
||
|
|
||
|
var instance = {
|
||
|
EVENTS: ['open', 'message', 'error', 'close', 'ping', 'pong'],
|
||
|
|
||
|
_bindEventListeners: function() {
|
||
|
this.messages.on('error', function() {});
|
||
|
this.on('error', function() {});
|
||
|
},
|
||
|
|
||
|
parse: function(chunk) {
|
||
|
if (this._delegate) return this._delegate.parse(chunk);
|
||
|
|
||
|
this._http.parse(chunk);
|
||
|
if (!this._http.isComplete()) return;
|
||
|
|
||
|
this.method = this._http.method;
|
||
|
this.url = this._http.url;
|
||
|
this.headers = this._http.headers;
|
||
|
this.body = this._http.body;
|
||
|
|
||
|
var self = this;
|
||
|
this._delegate = Server.http(this, this._options);
|
||
|
this._delegate.messages = this.messages;
|
||
|
this._delegate.io = this.io;
|
||
|
this._open();
|
||
|
|
||
|
this.EVENTS.forEach(function(event) {
|
||
|
this._delegate.on(event, function(e) { self.emit(event, e) });
|
||
|
}, this);
|
||
|
|
||
|
this.protocol = this._delegate.protocol;
|
||
|
this.version = this._delegate.version;
|
||
|
|
||
|
this.parse(this._http.body);
|
||
|
this.emit('connect', new Base.ConnectEvent());
|
||
|
},
|
||
|
|
||
|
_open: function() {
|
||
|
this.__queue.forEach(function(msg) {
|
||
|
this._delegate[msg[0]].apply(this._delegate, msg[1]);
|
||
|
}, this);
|
||
|
this.__queue = [];
|
||
|
}
|
||
|
};
|
||
|
|
||
|
['addExtension', 'setHeader', 'start', 'frame', 'text', 'binary', 'ping', 'close'].forEach(function(method) {
|
||
|
instance[method] = function() {
|
||
|
if (this._delegate) {
|
||
|
return this._delegate[method].apply(this._delegate, arguments);
|
||
|
} else {
|
||
|
this.__queue.push([method, arguments]);
|
||
|
return true;
|
||
|
}
|
||
|
};
|
||
|
});
|
||
|
|
||
|
for (var key in instance)
|
||
|
Server.prototype[key] = instance[key];
|
||
|
|
||
|
Server.isSecureRequest = function(request) {
|
||
|
if (request.connection && request.connection.authorized !== undefined) return true;
|
||
|
if (request.socket && request.socket.secure) return true;
|
||
|
|
||
|
var headers = request.headers;
|
||
|
if (!headers) return false;
|
||
|
if (headers['https'] === 'on') return true;
|
||
|
if (headers['x-forwarded-ssl'] === 'on') return true;
|
||
|
if (headers['x-forwarded-scheme'] === 'https') return true;
|
||
|
if (headers['x-forwarded-proto'] === 'https') return true;
|
||
|
|
||
|
return false;
|
||
|
};
|
||
|
|
||
|
Server.determineUrl = function(request) {
|
||
|
var scheme = this.isSecureRequest(request) ? 'wss:' : 'ws:';
|
||
|
return scheme + '//' + request.headers.host + request.url;
|
||
|
};
|
||
|
|
||
|
Server.http = function(request, options) {
|
||
|
options = options || {};
|
||
|
if (options.requireMasking === undefined) options.requireMasking = true;
|
||
|
|
||
|
var headers = request.headers,
|
||
|
version = headers['sec-websocket-version'],
|
||
|
key = headers['sec-websocket-key'],
|
||
|
key1 = headers['sec-websocket-key1'],
|
||
|
key2 = headers['sec-websocket-key2'],
|
||
|
url = this.determineUrl(request);
|
||
|
|
||
|
if (version || key)
|
||
|
return new Hybi(request, url, options);
|
||
|
else if (key1 || key2)
|
||
|
return new Draft76(request, url, options);
|
||
|
else
|
||
|
return new Draft75(request, url, options);
|
||
|
};
|
||
|
|
||
|
module.exports = Server;
|