| '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'], |
| |
| _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; |