@libp2p/websockets 9.0.13-bc90b4fd5 → 9.0.13-d19974d93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.min.js +1 -1
- package/dist/src/index.d.ts +23 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/listener.d.ts +50 -5
- package/dist/src/listener.d.ts.map +1 -1
- package/dist/src/listener.js +294 -97
- package/dist/src/listener.js.map +1 -1
- package/package.json +14 -13
- package/src/index.ts +31 -7
- package/src/listener.ts +348 -110
- package/LICENSE +0 -4
package/src/listener.ts
CHANGED
|
@@ -1,145 +1,346 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import http from 'node:http'
|
|
2
|
+
import https from 'node:https'
|
|
3
|
+
import net from 'node:net'
|
|
4
|
+
import os from 'node:os'
|
|
5
|
+
import { TypedEventEmitter, setMaxListeners } from '@libp2p/interface'
|
|
3
6
|
import { ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils/ip-port-to-multiaddr'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
7
|
+
import { isLinkLocalIp } from '@libp2p/utils/link-local-ip'
|
|
8
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
9
|
+
import { WebSockets, WebSocketsSecure } from '@multiformats/multiaddr-matcher'
|
|
10
|
+
import duplex from 'it-ws/duplex'
|
|
11
|
+
import { pEvent } from 'p-event'
|
|
12
|
+
import * as ws from 'ws'
|
|
6
13
|
import { socketToMaConn } from './socket-to-conn.js'
|
|
7
|
-
import type { ComponentLogger, Logger, Listener, ListenerEvents, CreateListenerOptions, CounterGroup, MetricGroup, Metrics } from '@libp2p/interface'
|
|
14
|
+
import type { ComponentLogger, Logger, Listener, ListenerEvents, CreateListenerOptions, CounterGroup, MetricGroup, Metrics, TLSCertificate, TypedEventTarget, Libp2pEvents, Upgrader, MultiaddrConnection } from '@libp2p/interface'
|
|
8
15
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
9
|
-
import type { Server } from 'http'
|
|
10
16
|
import type { DuplexWebSocket } from 'it-ws/duplex'
|
|
11
|
-
import type {
|
|
17
|
+
import type { EventEmitter } from 'node:events'
|
|
18
|
+
import type { Server } from 'node:http'
|
|
19
|
+
import type { Duplex } from 'node:stream'
|
|
20
|
+
import type tls from 'node:tls'
|
|
12
21
|
|
|
13
22
|
export interface WebSocketListenerComponents {
|
|
14
23
|
logger: ComponentLogger
|
|
24
|
+
events: TypedEventTarget<Libp2pEvents>
|
|
15
25
|
metrics?: Metrics
|
|
16
26
|
}
|
|
17
27
|
|
|
18
28
|
export interface WebSocketListenerInit extends CreateListenerOptions {
|
|
19
29
|
server?: Server
|
|
30
|
+
inboundConnectionUpgradeTimeout?: number
|
|
31
|
+
cert?: string
|
|
32
|
+
key?: string
|
|
33
|
+
http?: http.ServerOptions
|
|
34
|
+
https?: http.ServerOptions
|
|
20
35
|
}
|
|
21
36
|
|
|
22
37
|
export interface WebSocketListenerMetrics {
|
|
23
|
-
status
|
|
24
|
-
errors
|
|
25
|
-
events
|
|
38
|
+
status?: MetricGroup
|
|
39
|
+
errors?: CounterGroup
|
|
40
|
+
events?: CounterGroup
|
|
26
41
|
}
|
|
27
42
|
|
|
28
|
-
class WebSocketListener extends TypedEventEmitter<ListenerEvents> implements Listener {
|
|
29
|
-
private readonly connections: Set<DuplexWebSocket>
|
|
30
|
-
private listeningMultiaddr?: Multiaddr
|
|
31
|
-
private readonly server: WebSocketServer
|
|
43
|
+
export class WebSocketListener extends TypedEventEmitter<ListenerEvents> implements Listener {
|
|
32
44
|
private readonly log: Logger
|
|
33
|
-
private
|
|
34
|
-
private
|
|
45
|
+
private readonly logger: ComponentLogger
|
|
46
|
+
private readonly server: net.Server
|
|
47
|
+
private readonly wsServer: ws.WebSocketServer
|
|
48
|
+
private readonly metrics: WebSocketListenerMetrics
|
|
49
|
+
private readonly sockets: Set<net.Socket>
|
|
50
|
+
private readonly upgrader: Upgrader
|
|
51
|
+
private readonly inboundConnectionUpgradeTimeout: number
|
|
52
|
+
private readonly httpOptions?: http.ServerOptions
|
|
53
|
+
private readonly httpsOptions?: https.ServerOptions
|
|
54
|
+
private http?: http.Server
|
|
55
|
+
private https?: https.Server
|
|
56
|
+
private addr?: string
|
|
57
|
+
private listeningMultiaddr?: Multiaddr
|
|
35
58
|
|
|
36
59
|
constructor (components: WebSocketListenerComponents, init: WebSocketListenerInit) {
|
|
37
60
|
super()
|
|
38
61
|
|
|
39
62
|
this.log = components.logger.forComponent('libp2p:websockets:listener')
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.
|
|
63
|
+
this.logger = components.logger
|
|
64
|
+
this.upgrader = init.upgrader
|
|
65
|
+
this.httpOptions = init.http
|
|
66
|
+
this.httpsOptions = init.https ?? init.http
|
|
67
|
+
this.inboundConnectionUpgradeTimeout = init.inboundConnectionUpgradeTimeout ?? 5000
|
|
68
|
+
this.sockets = new Set()
|
|
43
69
|
|
|
44
|
-
|
|
70
|
+
this.wsServer = new ws.WebSocketServer({
|
|
71
|
+
noServer: true
|
|
72
|
+
})
|
|
73
|
+
this.wsServer.addListener('connection', this.onWsServerConnection.bind(this))
|
|
45
74
|
|
|
46
|
-
|
|
75
|
+
components.metrics?.registerMetricGroup('libp2p_websockets_inbound_connections_total', {
|
|
76
|
+
label: 'address',
|
|
77
|
+
help: 'Current active connections in WebSocket listener',
|
|
78
|
+
calculate: () => {
|
|
79
|
+
if (this.addr == null) {
|
|
80
|
+
return {}
|
|
81
|
+
}
|
|
47
82
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
metrics: this.metrics?.events,
|
|
54
|
-
metricPrefix: `${this.addr} `
|
|
55
|
-
})
|
|
56
|
-
this.log('new inbound connection %s', maConn.remoteAddr)
|
|
83
|
+
return {
|
|
84
|
+
[this.addr]: this.sockets.size
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
})
|
|
57
88
|
|
|
58
|
-
|
|
89
|
+
this.metrics = {
|
|
90
|
+
status: components.metrics?.registerMetricGroup('libp2p_websockets_listener_status_info', {
|
|
91
|
+
label: 'address',
|
|
92
|
+
help: 'Current status of the WebSocket listener socket'
|
|
93
|
+
}),
|
|
94
|
+
errors: components.metrics?.registerMetricGroup('libp2p_websockets_listener_errors_total', {
|
|
95
|
+
label: 'address',
|
|
96
|
+
help: 'Total count of WebSocket listener errors by type'
|
|
97
|
+
}),
|
|
98
|
+
events: components.metrics?.registerMetricGroup('libp2p_websockets_listener_events_total', {
|
|
99
|
+
label: 'address',
|
|
100
|
+
help: 'Total count of WebSocket listener events by type'
|
|
101
|
+
})
|
|
102
|
+
}
|
|
59
103
|
|
|
60
|
-
|
|
61
|
-
|
|
104
|
+
this.server = net.createServer({
|
|
105
|
+
pauseOnConnect: true
|
|
106
|
+
}, (socket) => {
|
|
107
|
+
this.onSocketConnection(socket)
|
|
108
|
+
.catch(err => {
|
|
109
|
+
this.log.error('error handling socket - %e', err)
|
|
110
|
+
socket.destroy()
|
|
62
111
|
})
|
|
112
|
+
})
|
|
63
113
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
this.metrics?.errors.increment({ [`${this.addr} inbound_upgrade`]: true })
|
|
114
|
+
components.events.addEventListener('certificate:provision', this.onCertificateProvision.bind(this))
|
|
115
|
+
components.events.addEventListener('certificate:renew', this.onCertificateRenew.bind(this))
|
|
116
|
+
}
|
|
68
117
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
} catch (err) {
|
|
72
|
-
this.log.error('inbound connection failed to close after upgrade failed - %e', err)
|
|
73
|
-
this.metrics?.errors.increment({ [`${this.addr} inbound_closing_failed`]: true })
|
|
74
|
-
}
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
})
|
|
118
|
+
async onSocketConnection (socket: net.Socket): Promise<void> {
|
|
119
|
+
this.metrics.events?.increment({ [`${this.addr} connection`]: true })
|
|
78
120
|
|
|
79
|
-
|
|
80
|
-
if (metrics != null) {
|
|
81
|
-
const { host, port } = this.listeningMultiaddr?.toOptions() ?? {}
|
|
82
|
-
this.addr = `${host}:${port}`
|
|
83
|
-
|
|
84
|
-
metrics.registerMetricGroup('libp2p_websockets_inbound_connections_total', {
|
|
85
|
-
label: 'address',
|
|
86
|
-
help: 'Current active connections in WebSocket listener',
|
|
87
|
-
calculate: () => {
|
|
88
|
-
return {
|
|
89
|
-
[this.addr]: this.connections.size
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
})
|
|
121
|
+
let buffer = socket.read(1)
|
|
93
122
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
this.
|
|
123
|
+
if (buffer == null) {
|
|
124
|
+
await pEvent(socket, 'readable')
|
|
125
|
+
buffer = socket.read(1)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// determine if this is an HTTP(s) request
|
|
129
|
+
const byte = buffer[0]
|
|
130
|
+
let server: EventEmitter | undefined = this.http
|
|
131
|
+
|
|
132
|
+
// https://github.com/mscdex/httpolyglot/blob/1c6c4af65f4cf95a32c918d0fdcc532e0c095740/lib/index.js#L92
|
|
133
|
+
if (byte < 32 || byte >= 127) {
|
|
134
|
+
server = this.https
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (server == null) {
|
|
138
|
+
this.log.error('no appropriate listener configured for byte %d', byte)
|
|
139
|
+
socket.destroy()
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// store the socket so we can close it when the listener closes
|
|
144
|
+
this.sockets.add(socket)
|
|
145
|
+
|
|
146
|
+
socket.on('close', () => {
|
|
147
|
+
this.metrics.events?.increment({ [`${this.addr} close`]: true })
|
|
148
|
+
this.sockets.delete(socket)
|
|
110
149
|
})
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
this.
|
|
114
|
-
|
|
115
|
-
|
|
150
|
+
|
|
151
|
+
socket.on('error', (err) => {
|
|
152
|
+
this.log.error('socket error - %e', err)
|
|
153
|
+
this.metrics.events?.increment({ [`${this.addr} error`]: true })
|
|
154
|
+
socket.destroy()
|
|
116
155
|
})
|
|
117
|
-
|
|
118
|
-
|
|
156
|
+
|
|
157
|
+
socket.once('timeout', () => {
|
|
158
|
+
this.metrics.events?.increment({ [`${this.addr} timeout`]: true })
|
|
119
159
|
})
|
|
160
|
+
|
|
161
|
+
socket.once('end', () => {
|
|
162
|
+
this.metrics.events?.increment({ [`${this.addr} end`]: true })
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
// re-queue first data chunk
|
|
166
|
+
socket.unshift(buffer)
|
|
167
|
+
|
|
168
|
+
// hand the socket off to the appropriate server
|
|
169
|
+
server.emit('connection', socket)
|
|
120
170
|
}
|
|
121
171
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
172
|
+
onWsServerConnection (socket: ws.WebSocket, req: http.IncomingMessage): void {
|
|
173
|
+
let addr: string | ws.AddressInfo | null
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
addr = this.server.address()
|
|
177
|
+
|
|
178
|
+
if (typeof addr === 'string') {
|
|
179
|
+
throw new Error('Cannot listen on unix sockets')
|
|
180
|
+
}
|
|
126
181
|
|
|
127
|
-
|
|
128
|
-
|
|
182
|
+
if (addr == null) {
|
|
183
|
+
throw new Error('Server was closing or not running')
|
|
184
|
+
}
|
|
185
|
+
} catch (err: any) {
|
|
186
|
+
this.log.error('error obtaining remote socket address - %e', err)
|
|
187
|
+
req.destroy(err)
|
|
188
|
+
socket.close()
|
|
129
189
|
return
|
|
130
190
|
}
|
|
131
191
|
|
|
132
|
-
|
|
192
|
+
const stream: DuplexWebSocket = {
|
|
193
|
+
...duplex(socket, {
|
|
194
|
+
remoteAddress: req.socket.remoteAddress ?? '0.0.0.0',
|
|
195
|
+
remotePort: req.socket.remotePort ?? 0
|
|
196
|
+
}),
|
|
197
|
+
localAddress: addr.address,
|
|
198
|
+
localPort: addr.port
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
let maConn: MultiaddrConnection
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
maConn = socketToMaConn(stream, toMultiaddr(stream.remoteAddress ?? '', stream.remotePort ?? 0), {
|
|
205
|
+
logger: this.logger,
|
|
206
|
+
metrics: this.metrics?.events,
|
|
207
|
+
metricPrefix: `${this.addr} `
|
|
208
|
+
})
|
|
209
|
+
} catch (err: any) {
|
|
210
|
+
this.log.error('inbound connection failed', err)
|
|
211
|
+
this.metrics.errors?.increment({ [`${this.addr} inbound_to_connection`]: true })
|
|
212
|
+
socket.close()
|
|
213
|
+
return
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
this.log('new inbound connection %s', maConn.remoteAddr)
|
|
217
|
+
const signal = AbortSignal.timeout(this.inboundConnectionUpgradeTimeout)
|
|
218
|
+
setMaxListeners(Infinity, signal)
|
|
219
|
+
|
|
220
|
+
this.upgrader.upgradeInbound(maConn, {
|
|
221
|
+
signal
|
|
222
|
+
})
|
|
223
|
+
.catch(async err => {
|
|
224
|
+
this.log.error('inbound connection failed to upgrade - %e', err)
|
|
225
|
+
this.metrics.errors?.increment({ [`${this.addr} inbound_upgrade`]: true })
|
|
226
|
+
|
|
227
|
+
await maConn.close()
|
|
228
|
+
.catch(err => {
|
|
229
|
+
this.log.error('inbound connection failed to close after upgrade failed', err)
|
|
230
|
+
this.metrics.errors?.increment({ [`${this.addr} inbound_closing_failed`]: true })
|
|
231
|
+
})
|
|
232
|
+
})
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
onUpgrade (req: http.IncomingMessage, socket: Duplex, head: Buffer): void {
|
|
236
|
+
this.wsServer.handleUpgrade(req, socket, head, this.onWsServerConnection.bind(this))
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
onTLSClientError (err: Error, socket: tls.TLSSocket): void {
|
|
240
|
+
this.log.error('TLS client error - %e', err)
|
|
241
|
+
socket.destroy()
|
|
133
242
|
}
|
|
134
243
|
|
|
135
244
|
async listen (ma: Multiaddr): Promise<void> {
|
|
245
|
+
if (WebSockets.exactMatch(ma)) {
|
|
246
|
+
this.http = http.createServer(this.httpOptions ?? {}, this.httpRequestHandler.bind(this))
|
|
247
|
+
this.http.addListener('upgrade', this.onUpgrade.bind(this))
|
|
248
|
+
} else if (WebSocketsSecure.exactMatch(ma)) {
|
|
249
|
+
this.https = https.createServer(this.httpsOptions ?? {}, this.httpRequestHandler.bind(this))
|
|
250
|
+
this.https.addListener('upgrade', this.onUpgrade.bind(this))
|
|
251
|
+
this.https.addListener('tlsClientError', this.onTLSClientError.bind(this))
|
|
252
|
+
}
|
|
253
|
+
|
|
136
254
|
this.listeningMultiaddr = ma
|
|
255
|
+
const { host, port } = ma.toOptions()
|
|
256
|
+
this.addr = `${host}:${port}`
|
|
257
|
+
|
|
258
|
+
this.server.listen(port, host)
|
|
259
|
+
|
|
260
|
+
await new Promise<void>((resolve, reject) => {
|
|
261
|
+
const onListening = (): void => {
|
|
262
|
+
removeListeners()
|
|
263
|
+
resolve()
|
|
264
|
+
}
|
|
265
|
+
const onError = (err: Error): void => {
|
|
266
|
+
this.metrics.errors?.increment({ [`${this.addr} listen_error`]: true })
|
|
267
|
+
removeListeners()
|
|
268
|
+
reject(err)
|
|
269
|
+
}
|
|
270
|
+
const onDrop = (): void => {
|
|
271
|
+
this.metrics.events?.increment({ [`${this.addr} drop`]: true })
|
|
272
|
+
}
|
|
273
|
+
const removeListeners = (): void => {
|
|
274
|
+
this.server.removeListener('listening', onListening)
|
|
275
|
+
this.server.removeListener('error', onError)
|
|
276
|
+
this.server.removeListener('drop', onDrop)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
this.server.addListener('listening', onListening)
|
|
280
|
+
this.server.addListener('error', onError)
|
|
281
|
+
this.server.addListener('drop', onDrop)
|
|
282
|
+
})
|
|
137
283
|
|
|
138
|
-
|
|
284
|
+
this.safeDispatchEvent('listening')
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
onCertificateProvision (event: CustomEvent<TLSCertificate>): void {
|
|
288
|
+
if (this.https != null) {
|
|
289
|
+
this.log('auto-tls certificate found but already listening on https')
|
|
290
|
+
return
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
this.log('auto-tls certificate found, starting https server')
|
|
294
|
+
this.https = https.createServer({
|
|
295
|
+
...this.httpsOptions,
|
|
296
|
+
...event.detail
|
|
297
|
+
}, this.httpRequestHandler.bind(this))
|
|
298
|
+
this.https.addListener('upgrade', this.onUpgrade.bind(this))
|
|
299
|
+
this.https.addListener('tlsClientError', this.onTLSClientError.bind(this))
|
|
300
|
+
|
|
301
|
+
this.safeDispatchEvent('listening')
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
onCertificateRenew (event: CustomEvent<TLSCertificate>): void {
|
|
305
|
+
// stop accepting new connections
|
|
306
|
+
this.https?.close()
|
|
307
|
+
|
|
308
|
+
this.log('auto-tls certificate renewed, restarting https server')
|
|
309
|
+
this.https = https.createServer({
|
|
310
|
+
...this.httpsOptions,
|
|
311
|
+
...event.detail
|
|
312
|
+
}, this.httpRequestHandler.bind(this))
|
|
313
|
+
this.https.addListener('upgrade', this.onUpgrade.bind(this))
|
|
314
|
+
this.https.addListener('tlsClientError', this.onTLSClientError.bind(this))
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async close (): Promise<void> {
|
|
318
|
+
this.server.close()
|
|
319
|
+
this.http?.close()
|
|
320
|
+
this.https?.close()
|
|
321
|
+
this.wsServer.close()
|
|
322
|
+
|
|
323
|
+
// close all connections, must be done after closing the server to prevent
|
|
324
|
+
// race conditions where a new connection is accepted while we are closing
|
|
325
|
+
// the existing ones
|
|
326
|
+
this.http?.closeAllConnections()
|
|
327
|
+
this.https?.closeAllConnections()
|
|
328
|
+
|
|
329
|
+
;[...this.sockets].forEach(socket => {
|
|
330
|
+
socket.destroy()
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
await Promise.all([
|
|
334
|
+
pEvent(this.server, 'close'),
|
|
335
|
+
this.http == null ? null : pEvent(this.http, 'close'),
|
|
336
|
+
this.https == null ? null : pEvent(this.https, 'close'),
|
|
337
|
+
pEvent(this.wsServer, 'close')
|
|
338
|
+
])
|
|
339
|
+
|
|
340
|
+
this.safeDispatchEvent('close')
|
|
139
341
|
}
|
|
140
342
|
|
|
141
343
|
getAddrs (): Multiaddr[] {
|
|
142
|
-
const multiaddrs = []
|
|
143
344
|
const address = this.server.address()
|
|
144
345
|
|
|
145
346
|
if (address == null) {
|
|
@@ -154,38 +355,75 @@ class WebSocketListener extends TypedEventEmitter<ListenerEvents> implements Lis
|
|
|
154
355
|
throw new Error('Listener is not ready yet')
|
|
155
356
|
}
|
|
156
357
|
|
|
157
|
-
const
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
// Because TCP will only return the IPv6 version
|
|
161
|
-
// we need to capture from the passed multiaddr
|
|
162
|
-
if (protos.some(proto => proto.code === protocols('ip4').code)) {
|
|
163
|
-
const wsProto = protos.some(proto => proto.code === protocols('ws').code) ? '/ws' : '/wss'
|
|
164
|
-
let m = this.listeningMultiaddr.decapsulate('tcp')
|
|
165
|
-
m = m.encapsulate(`/tcp/${address.port}${wsProto}`)
|
|
166
|
-
if (ipfsId != null) {
|
|
167
|
-
m = m.encapsulate(`/p2p/${ipfsId}`)
|
|
168
|
-
}
|
|
358
|
+
const options = this.listeningMultiaddr.toOptions()
|
|
359
|
+
const multiaddrs: Multiaddr[] = []
|
|
169
360
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
Object.values(
|
|
361
|
+
if (options.family === 4) {
|
|
362
|
+
if (options.host === '0.0.0.0') {
|
|
363
|
+
Object.values(os.networkInterfaces()).forEach(niInfos => {
|
|
173
364
|
if (niInfos == null) {
|
|
174
365
|
return
|
|
175
366
|
}
|
|
176
367
|
|
|
177
368
|
niInfos.forEach(ni => {
|
|
178
369
|
if (ni.family === 'IPv4') {
|
|
179
|
-
multiaddrs.push(multiaddr(
|
|
370
|
+
multiaddrs.push(multiaddr(`/ip${options.family}/${ni.address}/${options.transport}/${address.port}`))
|
|
180
371
|
}
|
|
181
372
|
})
|
|
182
373
|
})
|
|
183
374
|
} else {
|
|
184
|
-
multiaddrs.push(
|
|
375
|
+
multiaddrs.push(multiaddr(`/ip${options.family}/${options.host}/${options.transport}/${address.port}`))
|
|
185
376
|
}
|
|
377
|
+
} else if (options.family === 6) {
|
|
378
|
+
if (options.host === '::') {
|
|
379
|
+
Object.values(os.networkInterfaces()).forEach(niInfos => {
|
|
380
|
+
if (niInfos == null) {
|
|
381
|
+
return
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
for (const ni of niInfos) {
|
|
385
|
+
if (ni.family !== 'IPv6') {
|
|
386
|
+
continue
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (isLinkLocalIp(ni.address)) {
|
|
390
|
+
continue
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
multiaddrs.push(multiaddr(`/ip${options.family}/${ni.address}/${options.transport}/${address.port}`))
|
|
394
|
+
}
|
|
395
|
+
})
|
|
396
|
+
} else {
|
|
397
|
+
multiaddrs.push(multiaddr(`/ip${options.family}/${options.host}/${options.transport}/${address.port}`))
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const insecureMultiaddrs: Multiaddr[] = []
|
|
402
|
+
|
|
403
|
+
if (this.http != null) {
|
|
404
|
+
multiaddrs.forEach(ma => {
|
|
405
|
+
insecureMultiaddrs.push(ma.encapsulate('/ws'))
|
|
406
|
+
})
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const secureMultiaddrs: Multiaddr[] = []
|
|
410
|
+
|
|
411
|
+
if (this.https != null) {
|
|
412
|
+
multiaddrs.forEach(ma => {
|
|
413
|
+
secureMultiaddrs.push(ma.encapsulate('/tls/ws'))
|
|
414
|
+
})
|
|
186
415
|
}
|
|
187
416
|
|
|
188
|
-
return
|
|
417
|
+
return [
|
|
418
|
+
...insecureMultiaddrs,
|
|
419
|
+
...secureMultiaddrs
|
|
420
|
+
]
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
private httpRequestHandler (req: http.IncomingMessage, res: http.ServerResponse): void {
|
|
424
|
+
res.writeHead(400)
|
|
425
|
+
res.write('Only WebSocket connections are supported')
|
|
426
|
+
res.end()
|
|
189
427
|
}
|
|
190
428
|
}
|
|
191
429
|
|
package/LICENSE
DELETED