1 | const Transport = require("../transport");
|
---|
2 | const debug = require("debug")("engine:ws");
|
---|
3 |
|
---|
4 | class WebSocket extends Transport {
|
---|
5 | /**
|
---|
6 | * WebSocket transport
|
---|
7 | *
|
---|
8 | * @param {http.IncomingMessage}
|
---|
9 | * @api public
|
---|
10 | */
|
---|
11 | constructor(req) {
|
---|
12 | super(req);
|
---|
13 | this.socket = req.websocket;
|
---|
14 | this.socket.on("message", this.onData.bind(this));
|
---|
15 | this.socket.once("close", this.onClose.bind(this));
|
---|
16 | this.socket.on("error", this.onError.bind(this));
|
---|
17 | this.socket.on("headers", headers => {
|
---|
18 | this.emit("headers", headers);
|
---|
19 | });
|
---|
20 | this.writable = true;
|
---|
21 | this.perMessageDeflate = null;
|
---|
22 | }
|
---|
23 |
|
---|
24 | /**
|
---|
25 | * Transport name
|
---|
26 | *
|
---|
27 | * @api public
|
---|
28 | */
|
---|
29 | get name() {
|
---|
30 | return "websocket";
|
---|
31 | }
|
---|
32 |
|
---|
33 | /**
|
---|
34 | * Advertise upgrade support.
|
---|
35 | *
|
---|
36 | * @api public
|
---|
37 | */
|
---|
38 | get handlesUpgrades() {
|
---|
39 | return true;
|
---|
40 | }
|
---|
41 |
|
---|
42 | /**
|
---|
43 | * Advertise framing support.
|
---|
44 | *
|
---|
45 | * @api public
|
---|
46 | */
|
---|
47 | get supportsFraming() {
|
---|
48 | return true;
|
---|
49 | }
|
---|
50 |
|
---|
51 | /**
|
---|
52 | * Processes the incoming data.
|
---|
53 | *
|
---|
54 | * @param {String} encoded packet
|
---|
55 | * @api private
|
---|
56 | */
|
---|
57 | onData(data) {
|
---|
58 | debug('received "%s"', data);
|
---|
59 | super.onData(data);
|
---|
60 | }
|
---|
61 |
|
---|
62 | /**
|
---|
63 | * Writes a packet payload.
|
---|
64 | *
|
---|
65 | * @param {Array} packets
|
---|
66 | * @api private
|
---|
67 | */
|
---|
68 | send(packets) {
|
---|
69 | var self = this;
|
---|
70 |
|
---|
71 | for (var i = 0; i < packets.length; i++) {
|
---|
72 | var packet = packets[i];
|
---|
73 | this.parser.encodePacket(packet, self.supportsBinary, send);
|
---|
74 | }
|
---|
75 |
|
---|
76 | function send(data) {
|
---|
77 | debug('writing "%s"', data);
|
---|
78 |
|
---|
79 | // always creates a new object since ws modifies it
|
---|
80 | var opts = {};
|
---|
81 | if (packet.options) {
|
---|
82 | opts.compress = packet.options.compress;
|
---|
83 | }
|
---|
84 |
|
---|
85 | if (self.perMessageDeflate) {
|
---|
86 | var len =
|
---|
87 | "string" === typeof data ? Buffer.byteLength(data) : data.length;
|
---|
88 | if (len < self.perMessageDeflate.threshold) {
|
---|
89 | opts.compress = false;
|
---|
90 | }
|
---|
91 | }
|
---|
92 |
|
---|
93 | self.writable = false;
|
---|
94 | self.socket.send(data, opts, onEnd);
|
---|
95 | }
|
---|
96 |
|
---|
97 | function onEnd(err) {
|
---|
98 | if (err) return self.onError("write error", err.stack);
|
---|
99 | self.writable = true;
|
---|
100 | self.emit("drain");
|
---|
101 | }
|
---|
102 | }
|
---|
103 |
|
---|
104 | /**
|
---|
105 | * Closes the transport.
|
---|
106 | *
|
---|
107 | * @api private
|
---|
108 | */
|
---|
109 | doClose(fn) {
|
---|
110 | debug("closing");
|
---|
111 | this.socket.close();
|
---|
112 | fn && fn();
|
---|
113 | }
|
---|
114 | }
|
---|
115 |
|
---|
116 | module.exports = WebSocket;
|
---|