-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
index.js
115 lines (105 loc) · 3.03 KB
/
index.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
'use strict'
const {
extractSocketDetails,
protocolDecoder
} = require('aedes-protocol-decoder')
const http = require('http')
const https = require('https')
const http2 = require('http2')
const net = require('net')
const tls = require('tls')
const WebSocket = require('ws')
const defaultOptions = {
ws: null,
customWSErrorHandler: () => {},
http: null,
https: null,
http2: null,
tls: null,
trustProxy: false,
serverFactory: null,
protocolDecoder: protocolDecoder,
extractSocketDetails: extractSocketDetails
}
const createServer = (aedes, options = {}) => {
if (!aedes || !aedes.handle) {
throw new Error('Missing aedes handler')
}
options = Object.assign({}, defaultOptions, options)
let server = null
if (options.serverFactory) {
server = options.serverFactory(aedes, options)
} else if (options.tls) {
server = tls.createServer(options.tls, (conn) => {
bindConnection(aedes, options, conn)
})
} else if (options.ws) {
if (options.https) {
if (options.http2) {
server = http2.createSecureServer({
...options.http2,
...options.https
})
} else {
server = https.createServer({
...(options.http || {}),
...options.https
})
}
} else {
if (options.http2) {
server = http2.createServer(options.http2)
} else {
server = http.createServer(options.http || {})
}
}
const ws = new WebSocket.Server({ server })
ws.on('error', options.customWSErrorHandler)
ws.on('connection', (conn, req) => {
const stream = WebSocket.createWebSocketStream(conn)
// the _socket object is needed in bindConnection to retrieve info from the stream
// before passing it to aedes.handle
stream._socket = conn._socket
bindConnection(aedes, options, stream, req)
})
} else {
server = net.createServer((conn) => {
bindConnection(aedes, options, conn)
})
}
return server
}
const bindConnection = (aedes, options, conn, req = {}) => {
if (options.trustProxy) {
extractConnectionDetails(aedes, options, conn, req)
} else {
req.connDetails = options.extractSocketDetails(conn.socket || conn)
aedes.handle(conn, req)
}
}
const extractConnectionDetails = (aedes, options, conn, req = {}) => {
const onReadable = () => {
// buffer should contain the whole proxy header if any
// see https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
const buffer = conn.read(null)
if (buffer) {
const protocol = options.protocolDecoder(conn, buffer, req)
req.connDetails = protocol
conn.removeListener('readable', onReadable)
conn.removeListener('error', onError)
conn.pause()
conn.unshift(protocol.data || buffer)
aedes.handle(conn, req)
}
}
const onError = (error) => {
conn.removeListener('readable', onReadable)
conn.removeListener('error', onError)
aedes.emit('error', error)
}
conn.on('readable', onReadable)
conn.on('error', onError)
}
module.exports = {
createServer
}