@libp2p/websockets 9.2.19-8484de8a2 → 9.2.19-87bc8d4fb
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/dist/index.min.js +1 -1
- package/dist/index.min.js.map +4 -4
- package/dist/src/index.d.ts +0 -19
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +27 -24
- package/dist/src/index.js.map +1 -1
- package/dist/src/listener.d.ts +1 -5
- package/dist/src/listener.d.ts.map +1 -1
- package/dist/src/listener.js +28 -23
- package/dist/src/listener.js.map +1 -1
- package/dist/src/socket-to-conn.d.ts +11 -0
- package/dist/src/socket-to-conn.d.ts.map +1 -0
- package/dist/src/socket-to-conn.js +88 -0
- package/dist/src/socket-to-conn.js.map +1 -0
- package/package.json +13 -14
- package/src/index.ts +30 -44
- package/src/listener.ts +30 -25
- package/src/socket-to-conn.ts +114 -0
- package/dist/src/utils.d.ts +0 -7
- package/dist/src/utils.d.ts.map +0 -1
- package/dist/src/utils.js +0 -30
- package/dist/src/utils.js.map +0 -1
- package/dist/src/websocket-to-conn.d.ts +0 -9
- package/dist/src/websocket-to-conn.d.ts.map +0 -1
- package/dist/src/websocket-to-conn.js +0 -83
- package/dist/src/websocket-to-conn.js.map +0 -1
- package/src/utils.ts +0 -36
- package/src/websocket-to-conn.ts +0 -108
package/src/index.ts
CHANGED
|
@@ -25,14 +25,17 @@
|
|
|
25
25
|
|
|
26
26
|
import { transportSymbol, serviceCapabilities, ConnectionFailedError } from '@libp2p/interface'
|
|
27
27
|
import { multiaddrToUri as toUri } from '@multiformats/multiaddr-to-uri'
|
|
28
|
-
import {
|
|
28
|
+
import { connect } from 'it-ws/client'
|
|
29
|
+
import pDefer from 'p-defer'
|
|
29
30
|
import { CustomProgressEvent } from 'progress-events'
|
|
31
|
+
import { raceSignal } from 'race-signal'
|
|
30
32
|
import * as filters from './filters.js'
|
|
31
33
|
import { createListener } from './listener.js'
|
|
32
|
-
import {
|
|
34
|
+
import { socketToMaConn } from './socket-to-conn.js'
|
|
33
35
|
import type { Transport, MultiaddrFilter, CreateListenerOptions, DialTransportOptions, Listener, AbortOptions, ComponentLogger, Logger, Connection, OutboundConnectionUpgradeEvents, Metrics, CounterGroup, Libp2pEvents } from '@libp2p/interface'
|
|
34
36
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
35
37
|
import type { WebSocketOptions } from 'it-ws/client'
|
|
38
|
+
import type { DuplexWebSocket } from 'it-ws/duplex'
|
|
36
39
|
import type { TypedEventTarget } from 'main-event'
|
|
37
40
|
import type http from 'node:http'
|
|
38
41
|
import type https from 'node:https'
|
|
@@ -47,8 +50,6 @@ export interface WebSocketsInit extends AbortOptions, WebSocketOptions {
|
|
|
47
50
|
|
|
48
51
|
/**
|
|
49
52
|
* Options used to create WebSockets
|
|
50
|
-
*
|
|
51
|
-
* @deprecated This option will be removed in a future release
|
|
52
53
|
*/
|
|
53
54
|
websocket?: ClientOptions
|
|
54
55
|
|
|
@@ -69,25 +70,6 @@ export interface WebSocketsInit extends AbortOptions, WebSocketOptions {
|
|
|
69
70
|
* @deprecated Use the `connectionManager.inboundUpgradeTimeout` libp2p config key instead
|
|
70
71
|
*/
|
|
71
72
|
inboundConnectionUpgradeTimeout?: number
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* How large the outgoing [bufferedAmount](https://websockets.spec.whatwg.org/#dom-websocket-bufferedamount)
|
|
75
|
-
* property of incoming and outgoing websockets is allowed to get in bytes.
|
|
76
|
-
*
|
|
77
|
-
* If this limit is exceeded, backpressure will be applied to the writer.
|
|
78
|
-
*
|
|
79
|
-
* @default 4_194_304
|
|
80
|
-
*/
|
|
81
|
-
maxBufferedAmount?: number
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* If the [bufferedAmount](https://websockets.spec.whatwg.org/#dom-websocket-bufferedamount)
|
|
85
|
-
* property of a WebSocket exceeds `maxBufferedAmount`, poll the field every
|
|
86
|
-
* this number of ms to see if the socket can accept new data.
|
|
87
|
-
*
|
|
88
|
-
* @default 500
|
|
89
|
-
*/
|
|
90
|
-
bufferedAmountPollInterval?: number
|
|
91
73
|
}
|
|
92
74
|
|
|
93
75
|
export interface WebSocketsComponents {
|
|
@@ -139,14 +121,10 @@ class WebSockets implements Transport<WebSocketsDialEvents> {
|
|
|
139
121
|
this.log('dialing %s', ma)
|
|
140
122
|
options = options ?? {}
|
|
141
123
|
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
metrics: this.metrics?.dialerEvents
|
|
146
|
-
direction: 'outbound',
|
|
147
|
-
log: this.components.logger.forComponent('libp2p:websockets:connection'),
|
|
148
|
-
maxBufferedAmount: this.init.maxBufferedAmount,
|
|
149
|
-
bufferedAmountPollInterval: this.init.bufferedAmountPollInterval
|
|
124
|
+
const socket = await this._connect(ma, options)
|
|
125
|
+
const maConn = socketToMaConn(socket, ma, {
|
|
126
|
+
logger: this.logger,
|
|
127
|
+
metrics: this.metrics?.dialerEvents
|
|
150
128
|
})
|
|
151
129
|
this.log('new outbound connection %s', maConn.remoteAddr)
|
|
152
130
|
|
|
@@ -155,35 +133,43 @@ class WebSockets implements Transport<WebSocketsDialEvents> {
|
|
|
155
133
|
return conn
|
|
156
134
|
}
|
|
157
135
|
|
|
158
|
-
async _connect (ma: Multiaddr, options: DialTransportOptions<WebSocketsDialEvents>): Promise<
|
|
136
|
+
async _connect (ma: Multiaddr, options: DialTransportOptions<WebSocketsDialEvents>): Promise<DuplexWebSocket> {
|
|
159
137
|
options?.signal?.throwIfAborted()
|
|
160
138
|
|
|
161
|
-
const
|
|
162
|
-
this.log('
|
|
163
|
-
|
|
164
|
-
|
|
139
|
+
const cOpts = ma.toOptions()
|
|
140
|
+
this.log('dialing %s:%s', cOpts.host, cOpts.port)
|
|
141
|
+
|
|
142
|
+
const errorPromise = pDefer()
|
|
143
|
+
const rawSocket = connect(toUri(ma), this.init)
|
|
144
|
+
rawSocket.socket.addEventListener('error', () => {
|
|
145
|
+
// the WebSocket.ErrorEvent type doesn't actually give us any useful
|
|
146
|
+
// information about what happened
|
|
147
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/error_event
|
|
148
|
+
const err = new ConnectionFailedError(`Could not connect to ${ma.toString()}`)
|
|
149
|
+
this.log.error('connection error:', err)
|
|
150
|
+
this.metrics?.dialerEvents.increment({ error: true })
|
|
151
|
+
errorPromise.reject(err)
|
|
152
|
+
})
|
|
165
153
|
|
|
166
154
|
try {
|
|
167
155
|
options.onProgress?.(new CustomProgressEvent('websockets:open-connection'))
|
|
168
|
-
await
|
|
156
|
+
await raceSignal(Promise.race([rawSocket.connected(), errorPromise.promise]), options.signal)
|
|
169
157
|
} catch (err: any) {
|
|
170
158
|
if (options.signal?.aborted) {
|
|
171
159
|
this.metrics?.dialerEvents.increment({ abort: true })
|
|
172
|
-
throw new ConnectionFailedError(`Could not connect to ${uri}`)
|
|
173
|
-
} else {
|
|
174
|
-
this.metrics?.dialerEvents.increment({ error: true })
|
|
175
160
|
}
|
|
176
161
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
162
|
+
rawSocket.close()
|
|
163
|
+
.catch(err => {
|
|
164
|
+
this.log.error('error closing raw socket', err)
|
|
165
|
+
})
|
|
180
166
|
|
|
181
167
|
throw err
|
|
182
168
|
}
|
|
183
169
|
|
|
184
170
|
this.log('connected %s', ma)
|
|
185
171
|
this.metrics?.dialerEvents.increment({ connect: true })
|
|
186
|
-
return
|
|
172
|
+
return rawSocket
|
|
187
173
|
}
|
|
188
174
|
|
|
189
175
|
/**
|
package/src/listener.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import http from 'node:http'
|
|
2
2
|
import https from 'node:https'
|
|
3
3
|
import net from 'node:net'
|
|
4
|
-
import {
|
|
4
|
+
import { getThinWaistAddresses } from '@libp2p/utils/get-thin-waist-addresses'
|
|
5
|
+
import { ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils/ip-port-to-multiaddr'
|
|
5
6
|
import { multiaddr } from '@multiformats/multiaddr'
|
|
6
7
|
import { WebSockets, WebSocketsSecure } from '@multiformats/multiaddr-matcher'
|
|
8
|
+
import duplex from 'it-ws/duplex'
|
|
7
9
|
import { TypedEventEmitter, setMaxListeners } from 'main-event'
|
|
8
10
|
import { pEvent } from 'p-event'
|
|
9
11
|
import * as ws from 'ws'
|
|
10
|
-
import {
|
|
11
|
-
import { webSocketToMaConn } from './websocket-to-conn.js'
|
|
12
|
+
import { socketToMaConn } from './socket-to-conn.js'
|
|
12
13
|
import type { ComponentLogger, Logger, Listener, ListenerEvents, CreateListenerOptions, CounterGroup, MetricGroup, Metrics, TLSCertificate, Libp2pEvents, Upgrader, MultiaddrConnection } from '@libp2p/interface'
|
|
13
14
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
15
|
+
import type { DuplexWebSocket } from 'it-ws/duplex'
|
|
14
16
|
import type { TypedEventTarget } from 'main-event'
|
|
15
17
|
import type { EventEmitter } from 'node:events'
|
|
16
18
|
import type { Server } from 'node:http'
|
|
@@ -29,8 +31,6 @@ export interface WebSocketListenerInit extends CreateListenerOptions {
|
|
|
29
31
|
key?: string
|
|
30
32
|
http?: http.ServerOptions
|
|
31
33
|
https?: http.ServerOptions
|
|
32
|
-
maxBufferedAmount?: number
|
|
33
|
-
bufferedAmountPollInterval?: number
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export interface WebSocketListenerMetrics {
|
|
@@ -40,8 +40,8 @@ export interface WebSocketListenerMetrics {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export class WebSocketListener extends TypedEventEmitter<ListenerEvents> implements Listener {
|
|
43
|
-
private components: WebSocketListenerComponents
|
|
44
43
|
private readonly log: Logger
|
|
44
|
+
private readonly logger: ComponentLogger
|
|
45
45
|
private readonly server: net.Server
|
|
46
46
|
private readonly wsServer: ws.WebSocketServer
|
|
47
47
|
private readonly metrics: WebSocketListenerMetrics
|
|
@@ -54,19 +54,15 @@ export class WebSocketListener extends TypedEventEmitter<ListenerEvents> impleme
|
|
|
54
54
|
private https?: https.Server
|
|
55
55
|
private addr?: string
|
|
56
56
|
private listeningMultiaddr?: Multiaddr
|
|
57
|
-
private maxBufferedAmount?: number
|
|
58
|
-
private bufferedAmountPollInterval?: number
|
|
59
57
|
|
|
60
58
|
constructor (components: WebSocketListenerComponents, init: WebSocketListenerInit) {
|
|
61
59
|
super()
|
|
62
60
|
|
|
63
|
-
this.components = components
|
|
64
61
|
this.log = components.logger.forComponent('libp2p:websockets:listener')
|
|
62
|
+
this.logger = components.logger
|
|
65
63
|
this.upgrader = init.upgrader
|
|
66
64
|
this.httpOptions = init.http
|
|
67
65
|
this.httpsOptions = init.https ?? init.http
|
|
68
|
-
this.maxBufferedAmount = init.maxBufferedAmount
|
|
69
|
-
this.bufferedAmountPollInterval = init.bufferedAmountPollInterval
|
|
70
66
|
this.sockets = new Set()
|
|
71
67
|
this.shutdownController = new AbortController()
|
|
72
68
|
setMaxListeners(Infinity, this.shutdownController.signal)
|
|
@@ -175,7 +171,6 @@ export class WebSocketListener extends TypedEventEmitter<ListenerEvents> impleme
|
|
|
175
171
|
|
|
176
172
|
onWsServerConnection (socket: ws.WebSocket, req: http.IncomingMessage): void {
|
|
177
173
|
let addr: string | ws.AddressInfo | null
|
|
178
|
-
socket.binaryType = 'arraybuffer'
|
|
179
174
|
|
|
180
175
|
try {
|
|
181
176
|
addr = this.server.address()
|
|
@@ -194,18 +189,22 @@ export class WebSocketListener extends TypedEventEmitter<ListenerEvents> impleme
|
|
|
194
189
|
return
|
|
195
190
|
}
|
|
196
191
|
|
|
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
|
+
|
|
197
201
|
let maConn: MultiaddrConnection
|
|
198
202
|
|
|
199
203
|
try {
|
|
200
|
-
maConn =
|
|
201
|
-
|
|
202
|
-
remoteAddr: toMultiaddr(req.socket.remoteAddress ?? '0.0.0.0', req.socket.remotePort ?? 0).encapsulate('/ws'),
|
|
204
|
+
maConn = socketToMaConn(stream, toMultiaddr(stream.remoteAddress ?? '', stream.remotePort ?? 0), {
|
|
205
|
+
logger: this.logger,
|
|
203
206
|
metrics: this.metrics?.events,
|
|
204
|
-
metricPrefix: `${this.addr}
|
|
205
|
-
direction: 'inbound',
|
|
206
|
-
log: this.components.logger.forComponent('libp2p:websockets:connection'),
|
|
207
|
-
maxBufferedAmount: this.maxBufferedAmount,
|
|
208
|
-
bufferedAmountPollInterval: this.bufferedAmountPollInterval
|
|
207
|
+
metricPrefix: `${this.addr} `
|
|
209
208
|
})
|
|
210
209
|
} catch (err: any) {
|
|
211
210
|
this.log.error('inbound connection failed', err)
|
|
@@ -223,7 +222,11 @@ export class WebSocketListener extends TypedEventEmitter<ListenerEvents> impleme
|
|
|
223
222
|
this.log.error('inbound connection failed to upgrade - %e', err)
|
|
224
223
|
this.metrics.errors?.increment({ [`${this.addr} inbound_upgrade`]: true })
|
|
225
224
|
|
|
226
|
-
maConn.close()
|
|
225
|
+
await maConn.close()
|
|
226
|
+
.catch(err => {
|
|
227
|
+
this.log.error('inbound connection failed to close after upgrade failed', err)
|
|
228
|
+
this.metrics.errors?.increment({ [`${this.addr} inbound_closing_failed`]: true })
|
|
229
|
+
})
|
|
227
230
|
})
|
|
228
231
|
}
|
|
229
232
|
|
|
@@ -246,12 +249,12 @@ export class WebSocketListener extends TypedEventEmitter<ListenerEvents> impleme
|
|
|
246
249
|
this.https.addListener('tlsClientError', this.onTLSClientError.bind(this))
|
|
247
250
|
}
|
|
248
251
|
|
|
249
|
-
const
|
|
250
|
-
this.addr = `${
|
|
252
|
+
const options = ma.toOptions()
|
|
253
|
+
this.addr = `${options.host}:${options.port}`
|
|
251
254
|
|
|
252
255
|
this.server.listen({
|
|
253
|
-
...
|
|
254
|
-
ipv6Only:
|
|
256
|
+
...options,
|
|
257
|
+
ipv6Only: options.family === 6
|
|
255
258
|
})
|
|
256
259
|
|
|
257
260
|
await new Promise<void>((resolve, reject) => {
|
|
@@ -333,7 +336,9 @@ export class WebSocketListener extends TypedEventEmitter<ListenerEvents> impleme
|
|
|
333
336
|
|
|
334
337
|
await Promise.all([
|
|
335
338
|
pEvent(this.server, 'close'),
|
|
339
|
+
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
336
340
|
this.http == null ? null : pEvent(this.http, 'close'),
|
|
341
|
+
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
337
342
|
this.https == null ? null : pEvent(this.https, 'close'),
|
|
338
343
|
pEvent(this.wsServer, 'close')
|
|
339
344
|
])
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { AbortError, ConnectionFailedError } from '@libp2p/interface'
|
|
2
|
+
import { CLOSE_TIMEOUT } from './constants.js'
|
|
3
|
+
import type { AbortOptions, ComponentLogger, CounterGroup, MultiaddrConnection } from '@libp2p/interface'
|
|
4
|
+
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
5
|
+
import type { DuplexWebSocket } from 'it-ws/duplex'
|
|
6
|
+
|
|
7
|
+
export interface SocketToConnOptions {
|
|
8
|
+
localAddr?: Multiaddr
|
|
9
|
+
logger: ComponentLogger
|
|
10
|
+
metrics?: CounterGroup
|
|
11
|
+
metricPrefix?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Convert a stream into a MultiaddrConnection
|
|
15
|
+
// https://github.com/libp2p/interface-transport#multiaddrconnection
|
|
16
|
+
export function socketToMaConn (stream: DuplexWebSocket, remoteAddr: Multiaddr, options: SocketToConnOptions): MultiaddrConnection {
|
|
17
|
+
const metrics = options.metrics
|
|
18
|
+
const metricPrefix = options.metricPrefix ?? ''
|
|
19
|
+
|
|
20
|
+
const maConn: MultiaddrConnection = {
|
|
21
|
+
log: options.logger.forComponent('libp2p:websockets:connection'),
|
|
22
|
+
|
|
23
|
+
async sink (source) {
|
|
24
|
+
try {
|
|
25
|
+
await stream.sink((async function * () {
|
|
26
|
+
for await (const buf of source) {
|
|
27
|
+
if (buf instanceof Uint8Array) {
|
|
28
|
+
yield buf
|
|
29
|
+
} else {
|
|
30
|
+
yield buf.subarray()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
})())
|
|
34
|
+
} catch (err: any) {
|
|
35
|
+
if (err.type !== 'aborted') {
|
|
36
|
+
maConn.log.error(err)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
source: stream.source,
|
|
42
|
+
|
|
43
|
+
remoteAddr,
|
|
44
|
+
|
|
45
|
+
timeline: { open: Date.now() },
|
|
46
|
+
|
|
47
|
+
async close (options: AbortOptions = {}) {
|
|
48
|
+
const start = Date.now()
|
|
49
|
+
|
|
50
|
+
if (options.signal == null) {
|
|
51
|
+
const signal = AbortSignal.timeout(CLOSE_TIMEOUT)
|
|
52
|
+
|
|
53
|
+
options = {
|
|
54
|
+
...options,
|
|
55
|
+
signal
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const listener = (): void => {
|
|
60
|
+
const { host, port } = maConn.remoteAddr.toOptions()
|
|
61
|
+
maConn.log('timeout closing stream to %s:%s after %dms, destroying it manually',
|
|
62
|
+
host, port, Date.now() - start)
|
|
63
|
+
|
|
64
|
+
this.abort(new AbortError('Socket close timeout'))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
options.signal?.addEventListener('abort', listener)
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
await stream.close()
|
|
71
|
+
} catch (err: any) {
|
|
72
|
+
maConn.log.error('error closing WebSocket gracefully - %e', err)
|
|
73
|
+
this.abort(err)
|
|
74
|
+
} finally {
|
|
75
|
+
options.signal?.removeEventListener('abort', listener)
|
|
76
|
+
maConn.timeline.close = Date.now()
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
abort (err: Error): void {
|
|
81
|
+
maConn.log.error('destroying WebSocket after error - %e', err)
|
|
82
|
+
stream.destroy()
|
|
83
|
+
maConn.timeline.close = Date.now()
|
|
84
|
+
|
|
85
|
+
// ws WebSocket.terminate does not accept an Error arg to emit an 'error'
|
|
86
|
+
// event on destroy like other node streams so we can't update a metric
|
|
87
|
+
// with an event listener
|
|
88
|
+
// https://github.com/websockets/ws/issues/1752#issuecomment-622380981
|
|
89
|
+
metrics?.increment({ [`${metricPrefix}error`]: true })
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// track local vs remote closing
|
|
94
|
+
let closedLocally = false
|
|
95
|
+
const close = stream.socket.close.bind(stream.socket)
|
|
96
|
+
stream.socket.close = (...args) => {
|
|
97
|
+
closedLocally = true
|
|
98
|
+
return close(...args)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
stream.socket.addEventListener('close', (evt) => {
|
|
102
|
+
maConn.log('closed %s, code %d, reason "%s", wasClean %s', closedLocally ? 'locally' : 'by remote', evt.code, evt.reason, evt.wasClean)
|
|
103
|
+
|
|
104
|
+
if (!evt.wasClean) {
|
|
105
|
+
maConn.abort(new ConnectionFailedError(`${closedLocally ? 'Local' : 'Remote'} did not close WebSocket cleanly`))
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
metrics?.increment({ [`${metricPrefix}close`]: true })
|
|
110
|
+
maConn.timeline.close = Date.now()
|
|
111
|
+
}, { once: true })
|
|
112
|
+
|
|
113
|
+
return maConn
|
|
114
|
+
}
|
package/dist/src/utils.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { WebSocket as WSSWebSocket } from 'ws';
|
|
2
|
-
/**
|
|
3
|
-
* Adds properties/methods to a `WebSocket` instance from the `ws` module to be
|
|
4
|
-
* compatible with the `globalThis.WebSocket` API
|
|
5
|
-
*/
|
|
6
|
-
export declare function toWebSocket(ws: WSSWebSocket): WebSocket;
|
|
7
|
-
//# sourceMappingURL=utils.d.ts.map
|
package/dist/src/utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,IAAI,YAAY,EAAE,MAAM,IAAI,CAAA;AAEnD;;;GAGG;AACH,wBAAgB,WAAW,CAAE,EAAE,EAAE,YAAY,GAAG,SAAS,CA6BxD"}
|
package/dist/src/utils.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Adds properties/methods to a `WebSocket` instance from the `ws` module to be
|
|
3
|
-
* compatible with the `globalThis.WebSocket` API
|
|
4
|
-
*/
|
|
5
|
-
export function toWebSocket(ws) {
|
|
6
|
-
Object.defineProperty(ws, 'url', {
|
|
7
|
-
value: '',
|
|
8
|
-
writable: false
|
|
9
|
-
});
|
|
10
|
-
// @ts-expect-error not a WS/WebSocket method
|
|
11
|
-
ws.dispatchEvent = (evt) => {
|
|
12
|
-
if (evt.type === 'close') {
|
|
13
|
-
ws.emit('close');
|
|
14
|
-
}
|
|
15
|
-
if (evt.type === 'open') {
|
|
16
|
-
ws.emit('open');
|
|
17
|
-
}
|
|
18
|
-
if (evt.type === 'message') {
|
|
19
|
-
const m = evt;
|
|
20
|
-
ws.emit('data', m.data);
|
|
21
|
-
}
|
|
22
|
-
if (evt.type === 'error') {
|
|
23
|
-
ws.emit('error', new Error('An error occurred'));
|
|
24
|
-
}
|
|
25
|
-
ws.emit(evt.type, evt);
|
|
26
|
-
};
|
|
27
|
-
// @ts-expect-error ws is now WebSocket
|
|
28
|
-
return ws;
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=utils.js.map
|
package/dist/src/utils.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAE,EAAgB;IAC3C,MAAM,CAAC,cAAc,CAAC,EAAE,EAAE,KAAK,EAAE;QAC/B,KAAK,EAAE,EAAE;QACT,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAA;IAEF,6CAA6C;IAC7C,EAAE,CAAC,aAAa,GAAG,CAAC,GAAU,EAAE,EAAE;QAChC,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACzB,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAClB,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxB,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACjB,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,GAAmB,CAAA;YAC7B,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;QACzB,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACzB,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAA;QAClD,CAAC;QACD,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACxB,CAAC,CAAA;IAED,uCAAuC;IACvC,OAAO,EAAE,CAAA;AACX,CAAC"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { MultiaddrConnection } from '@libp2p/interface';
|
|
2
|
-
import type { AbstractMultiaddrConnectionInit } from '@libp2p/utils';
|
|
3
|
-
export interface WebSocketMultiaddrConnectionInit extends Omit<AbstractMultiaddrConnectionInit, 'name'> {
|
|
4
|
-
websocket: WebSocket;
|
|
5
|
-
maxBufferedAmount?: number;
|
|
6
|
-
bufferedAmountPollInterval?: number;
|
|
7
|
-
}
|
|
8
|
-
export declare function webSocketToMaConn(init: WebSocketMultiaddrConnectionInit): MultiaddrConnection;
|
|
9
|
-
//# sourceMappingURL=websocket-to-conn.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-to-conn.d.ts","sourceRoot":"","sources":["../../src/websocket-to-conn.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC1E,OAAO,KAAK,EAAE,+BAA+B,EAA6B,MAAM,eAAe,CAAA;AAK/F,MAAM,WAAW,gCAAiC,SAAQ,IAAI,CAAC,+BAA+B,EAAE,MAAM,CAAC;IACrG,SAAS,EAAE,SAAS,CAAA;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,0BAA0B,CAAC,EAAE,MAAM,CAAA;CACpC;AA4FD,wBAAgB,iBAAiB,CAAE,IAAI,EAAE,gCAAgC,GAAG,mBAAmB,CAE9F"}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { AbstractMultiaddrConnection, repeatingTask } from '@libp2p/utils';
|
|
2
|
-
import { Uint8ArrayList } from 'uint8arraylist';
|
|
3
|
-
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
|
|
4
|
-
const DEFAULT_MAX_BUFFERED_AMOUNT = 1024 * 1024 * 4;
|
|
5
|
-
const DEFAULT_BUFFERED_AMOUNT_POLL_INTERVAL = 10;
|
|
6
|
-
class WebSocketMultiaddrConnection extends AbstractMultiaddrConnection {
|
|
7
|
-
websocket;
|
|
8
|
-
maxBufferedAmount;
|
|
9
|
-
checkBufferedAmountTask;
|
|
10
|
-
constructor(init) {
|
|
11
|
-
super(init);
|
|
12
|
-
this.websocket = init.websocket;
|
|
13
|
-
this.maxBufferedAmount = init.maxBufferedAmount ?? DEFAULT_MAX_BUFFERED_AMOUNT;
|
|
14
|
-
this.checkBufferedAmountTask = repeatingTask(this.checkBufferedAmount.bind(this), init.bufferedAmountPollInterval ?? DEFAULT_BUFFERED_AMOUNT_POLL_INTERVAL);
|
|
15
|
-
this.websocket.addEventListener('close', (evt) => {
|
|
16
|
-
this.log('closed - code %d, reason "%s", wasClean %s', evt.code, evt.reason, evt.wasClean);
|
|
17
|
-
this.checkBufferedAmountTask.stop();
|
|
18
|
-
if (!evt.wasClean) {
|
|
19
|
-
this.onRemoteReset();
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
this.onTransportClosed();
|
|
23
|
-
}, { once: true });
|
|
24
|
-
this.websocket.addEventListener('message', (evt) => {
|
|
25
|
-
try {
|
|
26
|
-
let buf;
|
|
27
|
-
if (typeof evt.data === 'string') {
|
|
28
|
-
buf = uint8ArrayFromString(evt.data);
|
|
29
|
-
}
|
|
30
|
-
else if (evt.data instanceof ArrayBuffer) {
|
|
31
|
-
buf = new Uint8Array(evt.data, 0, evt.data.byteLength);
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
this.abort(new Error('Incorrect binary type'));
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
this.onData(buf);
|
|
38
|
-
}
|
|
39
|
-
catch (err) {
|
|
40
|
-
this.log.error('error receiving data - %e', err);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
sendData(data) {
|
|
45
|
-
for (const buf of data) {
|
|
46
|
-
this.websocket.send(buf);
|
|
47
|
-
}
|
|
48
|
-
const canSendMore = this.websocket.bufferedAmount < this.maxBufferedAmount;
|
|
49
|
-
if (!canSendMore) {
|
|
50
|
-
this.checkBufferedAmountTask.start();
|
|
51
|
-
}
|
|
52
|
-
return {
|
|
53
|
-
sentBytes: data.byteLength,
|
|
54
|
-
canSendMore
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
sendReset() {
|
|
58
|
-
this.websocket.close(1006); // abnormal closure
|
|
59
|
-
}
|
|
60
|
-
async sendClose(options) {
|
|
61
|
-
this.websocket.close();
|
|
62
|
-
options?.signal?.throwIfAborted();
|
|
63
|
-
}
|
|
64
|
-
sendPause() {
|
|
65
|
-
// read backpressure is not supported
|
|
66
|
-
}
|
|
67
|
-
sendResume() {
|
|
68
|
-
// read backpressure is not supported
|
|
69
|
-
}
|
|
70
|
-
checkBufferedAmount() {
|
|
71
|
-
this.log('buffered amount now %d', this.websocket.bufferedAmount);
|
|
72
|
-
if (this.websocket.bufferedAmount === 0) {
|
|
73
|
-
this.checkBufferedAmountTask.stop();
|
|
74
|
-
this.safeDispatchEvent('drain');
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
// Convert a stream into a MultiaddrConnection
|
|
79
|
-
// https://github.com/libp2p/interface-transport#multiaddrconnection
|
|
80
|
-
export function webSocketToMaConn(init) {
|
|
81
|
-
return new WebSocketMultiaddrConnection(init);
|
|
82
|
-
}
|
|
83
|
-
//# sourceMappingURL=websocket-to-conn.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-to-conn.js","sourceRoot":"","sources":["../../src/websocket-to-conn.ts"],"names":[],"mappings":"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"}
|
package/src/utils.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { WebSocket as WSSWebSocket } from 'ws'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Adds properties/methods to a `WebSocket` instance from the `ws` module to be
|
|
5
|
-
* compatible with the `globalThis.WebSocket` API
|
|
6
|
-
*/
|
|
7
|
-
export function toWebSocket (ws: WSSWebSocket): WebSocket {
|
|
8
|
-
Object.defineProperty(ws, 'url', {
|
|
9
|
-
value: '',
|
|
10
|
-
writable: false
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
// @ts-expect-error not a WS/WebSocket method
|
|
14
|
-
ws.dispatchEvent = (evt: Event) => {
|
|
15
|
-
if (evt.type === 'close') {
|
|
16
|
-
ws.emit('close')
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (evt.type === 'open') {
|
|
20
|
-
ws.emit('open')
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (evt.type === 'message') {
|
|
24
|
-
const m = evt as MessageEvent
|
|
25
|
-
ws.emit('data', m.data)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (evt.type === 'error') {
|
|
29
|
-
ws.emit('error', new Error('An error occurred'))
|
|
30
|
-
}
|
|
31
|
-
ws.emit(evt.type, evt)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// @ts-expect-error ws is now WebSocket
|
|
35
|
-
return ws
|
|
36
|
-
}
|