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.
112 lines
3.2 KiB
112 lines
3.2 KiB
'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;
|
|
|