Blame view

node_modules/sockjs-client/lib/transport/websocket.js 2.66 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
  'use strict';
  
  var utils = require('../utils/event')
    , urlUtils = require('../utils/url')
    , inherits = require('inherits')
    , EventEmitter = require('events').EventEmitter
    , WebsocketDriver = require('./driver/websocket')
    ;
  
  var debug = function() {};
  if (process.env.NODE_ENV !== 'production') {
    debug = require('debug')('sockjs-client:websocket');
  }
  
  function WebSocketTransport(transUrl, ignore, options) {
    if (!WebSocketTransport.enabled()) {
      throw new Error('Transport created when disabled');
    }
  
    EventEmitter.call(this);
    debug('constructor', transUrl);
  
    var self = this;
    var url = urlUtils.addPath(transUrl, '/websocket');
    if (url.slice(0, 5) === 'https') {
      url = 'wss' + url.slice(5);
    } else {
      url = 'ws' + url.slice(4);
    }
    this.url = url;
  
    this.ws = new WebsocketDriver(this.url, [], options);
    this.ws.onmessage = function(e) {
      debug('message event', e.data);
      self.emit('message', e.data);
    };
    // Firefox has an interesting bug. If a websocket connection is
    // created after onunload, it stays alive even when user
    // navigates away from the page. In such situation let's lie -
    // let's not open the ws connection at all. See:
    // https://github.com/sockjs/sockjs-client/issues/28
    // https://bugzilla.mozilla.org/show_bug.cgi?id=696085
    this.unloadRef = utils.unloadAdd(function() {
      debug('unload');
      self.ws.close();
    });
    this.ws.onclose = function(e) {
      debug('close event', e.code, e.reason);
      self.emit('close', e.code, e.reason);
      self._cleanup();
    };
    this.ws.onerror = function(e) {
      debug('error event', e);
      self.emit('close', 1006, 'WebSocket connection broken');
      self._cleanup();
    };
  }
  
  inherits(WebSocketTransport, EventEmitter);
  
  WebSocketTransport.prototype.send = function(data) {
    var msg = '[' + data + ']';
    debug('send', msg);
    this.ws.send(msg);
  };
  
  WebSocketTransport.prototype.close = function() {
    debug('close');
    var ws = this.ws;
    this._cleanup();
    if (ws) {
      ws.close();
    }
  };
  
  WebSocketTransport.prototype._cleanup = function() {
    debug('_cleanup');
    var ws = this.ws;
    if (ws) {
      ws.onmessage = ws.onclose = ws.onerror = null;
    }
    utils.unloadDel(this.unloadRef);
    this.unloadRef = this.ws = null;
    this.removeAllListeners();
  };
  
  WebSocketTransport.enabled = function() {
    debug('enabled');
    return !!WebsocketDriver;
  };
  WebSocketTransport.transportName = 'websocket';
  
  // In theory, ws should require 1 round trip. But in chrome, this is
  // not very stable over SSL. Most likely a ws connection requires a
  // separate SSL connection, in which case 2 round trips are an
  // absolute minumum.
  WebSocketTransport.roundTrips = 2;
  
  module.exports = WebSocketTransport;