Blame view

node_modules/websocket-driver/lib/websocket/driver/server.js 3.02 KB
aaac7fed   liuqimichale   add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  '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,
        url     = this.determineUrl(request);
  
    if (headers['sec-websocket-version'])
      return new Hybi(request, url, options);
    else if (headers['sec-websocket-key1'])
      return new Draft76(request, url, options);
    else
      return new Draft75(request, url, options);
  };
  
  module.exports = Server;