-
Notifications
You must be signed in to change notification settings - Fork 455
/
Copy pathminisocket.js
93 lines (86 loc) · 2.71 KB
/
minisocket.js
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
var crypto = require("crypto");
var KEY_SUFFIX = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
function hashWebSocketKey(key) {
var sha1 = crypto.createHash("sha1");
sha1.update(key + KEY_SUFFIX, "ascii");
return sha1.digest("base64");
}
/**
* Limitations: the current implementation does not
* care about what the client send:
* - we don't know `ws.close` only know `socket.closed` which is later so it has a latency
* - ping pong protocol
*/
// http://tools.ietf.org/html/rfc6455#section-5.2
var opcodes = {
TEXT: 1,
BINARY: 2,
CLOSE: 8,
PING: 9,
PONG: 10
};
/**
*
* @param {number} opcode
* @param {Buffer} payload
*/
function encodeMessage(opcode, payload) {
var buf; // Buffer type
var b1 = 0x80 | opcode;
// always send message as one frame (fin)
// second byte: maks and length part 1
// followed by 0, 2, or 8 additional bytes of continued length
var b2 = 0;
// server does not mask frames
var length = payload.length;
if (length < 126) {
buf = Buffer.allocUnsafe(payload.length + 2 + 0);
// zero extra bytes
b2 |= length;
buf.writeUInt8(b1, 0);
buf.writeUInt8(b2, 1);
payload.copy(buf, 2);
} else if (length < (1 << 16)) {
buf = Buffer.allocUnsafe(payload.length + 2 + 2);
// two bytes extra
b2 |= 126;
buf.writeUInt8(b1, 0);
buf.writeUInt8(b2, 1);
// add two byte length
buf.writeUInt16BE(length, 2);
payload.copy(buf, 4);
} else {
buf = Buffer.allocUnsafe(payload.length + 2 + 8);
// eight bytes extra
b2 |= 127;
buf.writeUInt8(b1, 0);
buf.writeUInt8(b2, 1);
// add eight byte length
// note: this implementation cannot handle lengths greater than 2^32
// the 32 bit length is prefixed with 0x0000
buf.writeUInt32BE(0, 2);
buf.writeUInt32BE(length, 6);
payload.copy(buf, 10);
}
return buf;
};
var upgradeHeader = 'HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nsec-websocket-accept: '
class MiniWebSocket {
constructor(req, socket, upgradeHead) {
this.socket = socket;
this.closed = false;
var self = this;
var key = hashWebSocketKey(req.headers["sec-websocket-key"])
// http://tools.ietf.org/html/rfc6455#section-4.2.2
socket.write( upgradeHeader + key + '\r\n\r\n');
socket.on("close", function (hadError) {
if (!self.closed) {
self.closed = true;
}
});
};
sendText(obj) {
this.socket.write(encodeMessage(opcodes.TEXT,Buffer.from(obj, "utf8")))
};
}
exports.MiniWebSocket = MiniWebSocket