Initial commit
[yaffs-website] / node_modules / websocket-driver / lib / websocket / driver / server.js
1 'use strict';
2
3 var util       = require('util'),
4     HttpParser = require('../http_parser'),
5     Base       = require('./base'),
6     Draft75    = require('./draft75'),
7     Draft76    = require('./draft76'),
8     Hybi       = require('./hybi');
9
10 var Server = function(options) {
11   Base.call(this, null, null, options);
12   this._http = new HttpParser('request');
13 };
14 util.inherits(Server, Base);
15
16 var instance = {
17   EVENTS: ['open', 'message', 'error', 'close'],
18
19   _bindEventListeners: function() {
20     this.messages.on('error', function() {});
21     this.on('error', function() {});
22   },
23
24   parse: function(chunk) {
25     if (this._delegate) return this._delegate.parse(chunk);
26
27     this._http.parse(chunk);
28     if (!this._http.isComplete()) return;
29
30     this.method  = this._http.method;
31     this.url     = this._http.url;
32     this.headers = this._http.headers;
33     this.body    = this._http.body;
34
35     var self = this;
36     this._delegate = Server.http(this, this._options);
37     this._delegate.messages = this.messages;
38     this._delegate.io = this.io;
39     this._open();
40
41     this.EVENTS.forEach(function(event) {
42       this._delegate.on(event, function(e) { self.emit(event, e) });
43     }, this);
44
45     this.protocol = this._delegate.protocol;
46     this.version  = this._delegate.version;
47
48     this.parse(this._http.body);
49     this.emit('connect', new Base.ConnectEvent());
50   },
51
52   _open: function() {
53     this.__queue.forEach(function(msg) {
54       this._delegate[msg[0]].apply(this._delegate, msg[1]);
55     }, this);
56     this.__queue = [];
57   }
58 };
59
60 ['addExtension', 'setHeader', 'start', 'frame', 'text', 'binary', 'ping', 'close'].forEach(function(method) {
61   instance[method] = function() {
62     if (this._delegate) {
63       return this._delegate[method].apply(this._delegate, arguments);
64     } else {
65       this.__queue.push([method, arguments]);
66       return true;
67     }
68   };
69 });
70
71 for (var key in instance)
72   Server.prototype[key] = instance[key];
73
74 Server.isSecureRequest = function(request) {
75   if (request.connection && request.connection.authorized !== undefined) return true;
76   if (request.socket && request.socket.secure) return true;
77
78   var headers = request.headers;
79   if (!headers) return false;
80   if (headers['https'] === 'on') return true;
81   if (headers['x-forwarded-ssl'] === 'on') return true;
82   if (headers['x-forwarded-scheme'] === 'https') return true;
83   if (headers['x-forwarded-proto'] === 'https') return true;
84
85   return false;
86 };
87
88 Server.determineUrl = function(request) {
89   var scheme = this.isSecureRequest(request) ? 'wss:' : 'ws:';
90   return scheme + '//' + request.headers.host + request.url;
91 };
92
93 Server.http = function(request, options) {
94   options = options || {};
95   if (options.requireMasking === undefined) options.requireMasking = true;
96
97   var headers = request.headers,
98       url     = this.determineUrl(request);
99
100   if (headers['sec-websocket-version'])
101     return new Hybi(request, url, options);
102   else if (headers['sec-websocket-key1'])
103     return new Draft76(request, url, options);
104   else
105     return new Draft75(request, url, options);
106 };
107
108 module.exports = Server;