@libp2p/websockets 9.2.19 → 10.0.0-55b7e5fea

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/src/index.ts CHANGED
@@ -24,35 +24,21 @@
24
24
  */
25
25
 
26
26
  import { transportSymbol, serviceCapabilities, ConnectionFailedError } from '@libp2p/interface'
27
+ import { WebSockets as WebSocketsMatcher, WebSocketsSecure } from '@multiformats/multiaddr-matcher'
27
28
  import { multiaddrToUri as toUri } from '@multiformats/multiaddr-to-uri'
28
- import { connect } from 'it-ws/client'
29
- import pDefer from 'p-defer'
29
+ import { pEvent } from 'p-event'
30
30
  import { CustomProgressEvent } from 'progress-events'
31
- import { raceSignal } from 'race-signal'
32
- import * as filters from './filters.js'
33
31
  import { createListener } from './listener.js'
34
- import { socketToMaConn } from './socket-to-conn.js'
35
- import type { Transport, MultiaddrFilter, CreateListenerOptions, DialTransportOptions, Listener, AbortOptions, ComponentLogger, Logger, Connection, OutboundConnectionUpgradeEvents, Metrics, CounterGroup, Libp2pEvents } from '@libp2p/interface'
32
+ import { webSocketToMaConn } from './websocket-to-conn.js'
33
+ import type { Transport, CreateListenerOptions, DialTransportOptions, Listener, AbortOptions, ComponentLogger, Logger, Connection, OutboundConnectionUpgradeEvents, Metrics, CounterGroup, Libp2pEvents } from '@libp2p/interface'
36
34
  import type { Multiaddr } from '@multiformats/multiaddr'
37
35
  import type { WebSocketOptions } from 'it-ws/client'
38
- import type { DuplexWebSocket } from 'it-ws/duplex'
39
36
  import type { TypedEventTarget } from 'main-event'
40
37
  import type http from 'node:http'
41
38
  import type https from 'node:https'
42
39
  import type { ProgressEvent } from 'progress-events'
43
- import type { ClientOptions } from 'ws'
44
40
 
45
41
  export interface WebSocketsInit extends AbortOptions, WebSocketOptions {
46
- /**
47
- * @deprecated Use a ConnectionGater instead
48
- */
49
- filter?: MultiaddrFilter
50
-
51
- /**
52
- * Options used to create WebSockets
53
- */
54
- websocket?: ClientOptions
55
-
56
42
  /**
57
43
  * Options used to create the HTTP server
58
44
  */
@@ -65,11 +51,23 @@ export interface WebSocketsInit extends AbortOptions, WebSocketOptions {
65
51
  https?: https.ServerOptions
66
52
 
67
53
  /**
68
- * Inbound connections must complete their upgrade within this many ms
54
+ * How large the outgoing [bufferedAmount](https://websockets.spec.whatwg.org/#dom-websocket-bufferedamount)
55
+ * property of incoming and outgoing websockets is allowed to get in bytes.
56
+ *
57
+ * If this limit is exceeded, backpressure will be applied to the writer.
58
+ *
59
+ * @default 4_194_304
60
+ */
61
+ maxBufferedAmount?: number
62
+
63
+ /**
64
+ * If the [bufferedAmount](https://websockets.spec.whatwg.org/#dom-websocket-bufferedamount)
65
+ * property of a WebSocket exceeds `maxBufferedAmount`, poll the field every
66
+ * this number of ms to see if the socket can accept new data.
69
67
  *
70
- * @deprecated Use the `connectionManager.inboundUpgradeTimeout` libp2p config key instead
68
+ * @default 500
71
69
  */
72
- inboundConnectionUpgradeTimeout?: number
70
+ bufferedAmountPollInterval?: number
73
71
  }
74
72
 
75
73
  export interface WebSocketsComponents {
@@ -121,10 +119,14 @@ class WebSockets implements Transport<WebSocketsDialEvents> {
121
119
  this.log('dialing %s', ma)
122
120
  options = options ?? {}
123
121
 
124
- const socket = await this._connect(ma, options)
125
- const maConn = socketToMaConn(socket, ma, {
126
- logger: this.logger,
127
- metrics: this.metrics?.dialerEvents
122
+ const maConn = webSocketToMaConn({
123
+ websocket: await this._connect(ma, options),
124
+ remoteAddr: ma,
125
+ metrics: this.metrics?.dialerEvents,
126
+ direction: 'outbound',
127
+ log: this.components.logger.forComponent('libp2p:websockets:connection'),
128
+ maxBufferedAmount: this.init.maxBufferedAmount,
129
+ bufferedAmountPollInterval: this.init.bufferedAmountPollInterval
128
130
  })
129
131
  this.log('new outbound connection %s', maConn.remoteAddr)
130
132
 
@@ -133,43 +135,35 @@ class WebSockets implements Transport<WebSocketsDialEvents> {
133
135
  return conn
134
136
  }
135
137
 
136
- async _connect (ma: Multiaddr, options: DialTransportOptions<WebSocketsDialEvents>): Promise<DuplexWebSocket> {
138
+ async _connect (ma: Multiaddr, options: DialTransportOptions<WebSocketsDialEvents>): Promise<WebSocket> {
137
139
  options?.signal?.throwIfAborted()
138
140
 
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
- })
141
+ const uri = toUri(ma)
142
+ this.log('create websocket connection to %s', uri)
143
+ const websocket = new WebSocket(uri)
144
+ websocket.binaryType = 'arraybuffer'
153
145
 
154
146
  try {
155
147
  options.onProgress?.(new CustomProgressEvent('websockets:open-connection'))
156
- await raceSignal(Promise.race([rawSocket.connected(), errorPromise.promise]), options.signal)
148
+ await pEvent(websocket, 'open', options)
157
149
  } catch (err: any) {
158
150
  if (options.signal?.aborted) {
159
151
  this.metrics?.dialerEvents.increment({ abort: true })
152
+ throw new ConnectionFailedError(`Could not connect to ${uri}`)
153
+ } else {
154
+ this.metrics?.dialerEvents.increment({ error: true })
160
155
  }
161
156
 
162
- rawSocket.close()
163
- .catch(err => {
164
- this.log.error('error closing raw socket', err)
165
- })
157
+ try {
158
+ websocket.close()
159
+ } catch {}
166
160
 
167
161
  throw err
168
162
  }
169
163
 
170
164
  this.log('connected %s', ma)
171
165
  this.metrics?.dialerEvents.increment({ connect: true })
172
- return rawSocket
166
+ return websocket
173
167
  }
174
168
 
175
169
  /**
@@ -188,24 +182,10 @@ class WebSockets implements Transport<WebSocketsDialEvents> {
188
182
  })
189
183
  }
190
184
 
191
- /**
192
- * Takes a list of `Multiaddr`s and returns only valid WebSockets addresses.
193
- * By default, in a browser environment only DNS+WSS multiaddr is accepted,
194
- * while in a Node.js environment DNS+{WS, WSS} multiaddrs are accepted.
195
- */
196
185
  listenFilter (multiaddrs: Multiaddr[]): Multiaddr[] {
197
- multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]
198
-
199
- if (this.init?.filter != null) {
200
- return this.init?.filter(multiaddrs)
201
- }
202
-
203
- return filters.all(multiaddrs)
186
+ return multiaddrs.filter(ma => WebSocketsMatcher.exactMatch(ma) || WebSocketsSecure.exactMatch(ma))
204
187
  }
205
188
 
206
- /**
207
- * Filter check for all Multiaddrs that this transport can dial
208
- */
209
189
  dialFilter (multiaddrs: Multiaddr[]): Multiaddr[] {
210
190
  return this.listenFilter(multiaddrs)
211
191
  }
package/src/listener.ts CHANGED
@@ -1,18 +1,16 @@
1
1
  import http from 'node:http'
2
2
  import https from 'node:https'
3
3
  import net from 'node:net'
4
- import { getThinWaistAddresses } from '@libp2p/utils/get-thin-waist-addresses'
5
- import { ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils/ip-port-to-multiaddr'
4
+ import { getNetConfig, getThinWaistAddresses, ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils'
6
5
  import { multiaddr } from '@multiformats/multiaddr'
7
6
  import { WebSockets, WebSocketsSecure } from '@multiformats/multiaddr-matcher'
8
- import duplex from 'it-ws/duplex'
9
7
  import { TypedEventEmitter, setMaxListeners } from 'main-event'
10
8
  import { pEvent } from 'p-event'
11
9
  import * as ws from 'ws'
12
- import { socketToMaConn } from './socket-to-conn.js'
10
+ import { toWebSocket } from './utils.ts'
11
+ import { webSocketToMaConn } from './websocket-to-conn.js'
13
12
  import type { ComponentLogger, Logger, Listener, ListenerEvents, CreateListenerOptions, CounterGroup, MetricGroup, Metrics, TLSCertificate, Libp2pEvents, Upgrader, MultiaddrConnection } from '@libp2p/interface'
14
13
  import type { Multiaddr } from '@multiformats/multiaddr'
15
- import type { DuplexWebSocket } from 'it-ws/duplex'
16
14
  import type { TypedEventTarget } from 'main-event'
17
15
  import type { EventEmitter } from 'node:events'
18
16
  import type { Server } from 'node:http'
@@ -31,6 +29,8 @@ export interface WebSocketListenerInit extends CreateListenerOptions {
31
29
  key?: string
32
30
  http?: http.ServerOptions
33
31
  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
43
44
  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,15 +54,19 @@ 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
57
59
 
58
60
  constructor (components: WebSocketListenerComponents, init: WebSocketListenerInit) {
59
61
  super()
60
62
 
63
+ this.components = components
61
64
  this.log = components.logger.forComponent('libp2p:websockets:listener')
62
- this.logger = components.logger
63
65
  this.upgrader = init.upgrader
64
66
  this.httpOptions = init.http
65
67
  this.httpsOptions = init.https ?? init.http
68
+ this.maxBufferedAmount = init.maxBufferedAmount
69
+ this.bufferedAmountPollInterval = init.bufferedAmountPollInterval
66
70
  this.sockets = new Set()
67
71
  this.shutdownController = new AbortController()
68
72
  setMaxListeners(Infinity, this.shutdownController.signal)
@@ -171,6 +175,7 @@ export class WebSocketListener extends TypedEventEmitter<ListenerEvents> impleme
171
175
 
172
176
  onWsServerConnection (socket: ws.WebSocket, req: http.IncomingMessage): void {
173
177
  let addr: string | ws.AddressInfo | null
178
+ socket.binaryType = 'arraybuffer'
174
179
 
175
180
  try {
176
181
  addr = this.server.address()
@@ -189,22 +194,18 @@ export class WebSocketListener extends TypedEventEmitter<ListenerEvents> impleme
189
194
  return
190
195
  }
191
196
 
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
197
  let maConn: MultiaddrConnection
202
198
 
203
199
  try {
204
- maConn = socketToMaConn(stream, toMultiaddr(stream.remoteAddress ?? '', stream.remotePort ?? 0), {
205
- logger: this.logger,
200
+ maConn = webSocketToMaConn({
201
+ websocket: toWebSocket(socket),
202
+ remoteAddr: toMultiaddr(req.socket.remoteAddress ?? '0.0.0.0', req.socket.remotePort ?? 0).encapsulate('/ws'),
206
203
  metrics: this.metrics?.events,
207
- metricPrefix: `${this.addr} `
204
+ metricPrefix: `${this.addr} `,
205
+ direction: 'inbound',
206
+ log: this.components.logger.forComponent('libp2p:websockets:connection'),
207
+ maxBufferedAmount: this.maxBufferedAmount,
208
+ bufferedAmountPollInterval: this.bufferedAmountPollInterval
208
209
  })
209
210
  } catch (err: any) {
210
211
  this.log.error('inbound connection failed', err)
@@ -222,11 +223,7 @@ export class WebSocketListener extends TypedEventEmitter<ListenerEvents> impleme
222
223
  this.log.error('inbound connection failed to upgrade - %e', err)
223
224
  this.metrics.errors?.increment({ [`${this.addr} inbound_upgrade`]: true })
224
225
 
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
- })
226
+ maConn.close()
230
227
  })
231
228
  }
232
229
 
@@ -249,12 +246,12 @@ export class WebSocketListener extends TypedEventEmitter<ListenerEvents> impleme
249
246
  this.https.addListener('tlsClientError', this.onTLSClientError.bind(this))
250
247
  }
251
248
 
252
- const options = ma.toOptions()
253
- this.addr = `${options.host}:${options.port}`
249
+ const config = getNetConfig(ma)
250
+ this.addr = `${config.host}:${config.port}`
254
251
 
255
252
  this.server.listen({
256
- ...options,
257
- ipv6Only: options.family === 6
253
+ ...config,
254
+ ipv6Only: config.type === 'ip6'
258
255
  })
259
256
 
260
257
  await new Promise<void>((resolve, reject) => {
@@ -334,12 +331,20 @@ export class WebSocketListener extends TypedEventEmitter<ListenerEvents> impleme
334
331
  // abort and in-flight connection upgrades
335
332
  this.shutdownController.abort()
336
333
 
337
- await Promise.all([
334
+ const events = [
338
335
  pEvent(this.server, 'close'),
339
- this.http == null ? null : pEvent(this.http, 'close'),
340
- this.https == null ? null : pEvent(this.https, 'close'),
341
336
  pEvent(this.wsServer, 'close')
342
- ])
337
+ ]
338
+
339
+ if (this.http != null) {
340
+ events.push(pEvent(this.http, 'close'))
341
+ }
342
+
343
+ if (this.https != null) {
344
+ events.push(pEvent(this.https, 'close'))
345
+ }
346
+
347
+ await Promise.all(events)
343
348
 
344
349
  this.safeDispatchEvent('close')
345
350
  }
package/src/utils.ts ADDED
@@ -0,0 +1,36 @@
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
+ }
@@ -0,0 +1,108 @@
1
+ import { AbstractMultiaddrConnection, repeatingTask } from '@libp2p/utils'
2
+ import { Uint8ArrayList } from 'uint8arraylist'
3
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
4
+ import type { AbortOptions, MultiaddrConnection } from '@libp2p/interface'
5
+ import type { AbstractMultiaddrConnectionInit, RepeatingTask, SendResult } from '@libp2p/utils'
6
+
7
+ const DEFAULT_MAX_BUFFERED_AMOUNT = 1024 * 1024 * 4
8
+ const DEFAULT_BUFFERED_AMOUNT_POLL_INTERVAL = 10
9
+
10
+ export interface WebSocketMultiaddrConnectionInit extends Omit<AbstractMultiaddrConnectionInit, 'name'> {
11
+ websocket: WebSocket
12
+ maxBufferedAmount?: number
13
+ bufferedAmountPollInterval?: number
14
+ }
15
+
16
+ class WebSocketMultiaddrConnection extends AbstractMultiaddrConnection {
17
+ private websocket: WebSocket
18
+ private maxBufferedAmount: number
19
+ private checkBufferedAmountTask: RepeatingTask
20
+
21
+ constructor (init: WebSocketMultiaddrConnectionInit) {
22
+ super(init)
23
+
24
+ this.websocket = init.websocket
25
+ this.maxBufferedAmount = init.maxBufferedAmount ?? DEFAULT_MAX_BUFFERED_AMOUNT
26
+ this.checkBufferedAmountTask = repeatingTask(this.checkBufferedAmount.bind(this), init.bufferedAmountPollInterval ?? DEFAULT_BUFFERED_AMOUNT_POLL_INTERVAL)
27
+
28
+ this.websocket.addEventListener('close', (evt) => {
29
+ this.log('closed - code %d, reason "%s", wasClean %s', evt.code, evt.reason, evt.wasClean)
30
+ this.checkBufferedAmountTask.stop()
31
+
32
+ if (!evt.wasClean) {
33
+ this.onRemoteReset()
34
+ return
35
+ }
36
+
37
+ this.onTransportClosed()
38
+ }, { once: true })
39
+
40
+ this.websocket.addEventListener('message', (evt) => {
41
+ try {
42
+ let buf: Uint8Array
43
+
44
+ if (typeof evt.data === 'string') {
45
+ buf = uint8ArrayFromString(evt.data)
46
+ } else if (evt.data instanceof ArrayBuffer) {
47
+ buf = new Uint8Array(evt.data, 0, evt.data.byteLength)
48
+ } else {
49
+ this.abort(new Error('Incorrect binary type'))
50
+ return
51
+ }
52
+
53
+ this.onData(buf)
54
+ } catch (err: any) {
55
+ this.log.error('error receiving data - %e', err)
56
+ }
57
+ })
58
+ }
59
+
60
+ sendData (data: Uint8ArrayList): SendResult {
61
+ for (const buf of data) {
62
+ this.websocket.send(buf)
63
+ }
64
+
65
+ const canSendMore = this.websocket.bufferedAmount < this.maxBufferedAmount
66
+
67
+ if (!canSendMore) {
68
+ this.checkBufferedAmountTask.start()
69
+ }
70
+
71
+ return {
72
+ sentBytes: data.byteLength,
73
+ canSendMore
74
+ }
75
+ }
76
+
77
+ sendReset (): void {
78
+ this.websocket.close(1006) // abnormal closure
79
+ }
80
+
81
+ async sendClose (options?: AbortOptions): Promise<void> {
82
+ this.websocket.close()
83
+ options?.signal?.throwIfAborted()
84
+ }
85
+
86
+ sendPause (): void {
87
+ // read backpressure is not supported
88
+ }
89
+
90
+ sendResume (): void {
91
+ // read backpressure is not supported
92
+ }
93
+
94
+ private checkBufferedAmount (): void {
95
+ this.log('buffered amount now %d', this.websocket.bufferedAmount)
96
+
97
+ if (this.websocket.bufferedAmount === 0) {
98
+ this.checkBufferedAmountTask.stop()
99
+ this.safeDispatchEvent('drain')
100
+ }
101
+ }
102
+ }
103
+
104
+ // Convert a stream into a MultiaddrConnection
105
+ // https://github.com/libp2p/interface-transport#multiaddrconnection
106
+ export function webSocketToMaConn (init: WebSocketMultiaddrConnectionInit): MultiaddrConnection {
107
+ return new WebSocketMultiaddrConnection(init)
108
+ }
@@ -1,18 +0,0 @@
1
- import type { Multiaddr } from '@multiformats/multiaddr';
2
- /**
3
- * @deprecated Configure this globally by passing a `connectionGater` to `createLibp2p` with a `denyDialMultiaddr` method that returns `false`
4
- */
5
- export declare function all(multiaddrs: Multiaddr[]): Multiaddr[];
6
- /**
7
- * @deprecated Configure this globally by passing a `connectionGater` to `createLibp2p`
8
- */
9
- export declare function wss(multiaddrs: Multiaddr[]): Multiaddr[];
10
- /**
11
- * @deprecated Configure this globally by passing a `connectionGater` to `createLibp2p`
12
- */
13
- export declare function dnsWss(multiaddrs: Multiaddr[]): Multiaddr[];
14
- /**
15
- * @deprecated Configure this globally by passing a `connectionGater` to `createLibp2p`
16
- */
17
- export declare function dnsWsOrWss(multiaddrs: Multiaddr[]): Multiaddr[];
18
- //# sourceMappingURL=filters.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../../src/filters.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD;;GAEG;AACH,wBAAgB,GAAG,CAAE,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAIzD;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAE,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAIzD;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAE,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAI5D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAE,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAIhE"}
@@ -1,34 +0,0 @@
1
- import { WebSocketsSecure, WebSockets, DNS } from '@multiformats/multiaddr-matcher';
2
- /**
3
- * @deprecated Configure this globally by passing a `connectionGater` to `createLibp2p` with a `denyDialMultiaddr` method that returns `false`
4
- */
5
- export function all(multiaddrs) {
6
- return multiaddrs.filter((ma) => {
7
- return WebSocketsSecure.exactMatch(ma) || WebSockets.exactMatch(ma);
8
- });
9
- }
10
- /**
11
- * @deprecated Configure this globally by passing a `connectionGater` to `createLibp2p`
12
- */
13
- export function wss(multiaddrs) {
14
- return multiaddrs.filter((ma) => {
15
- return WebSocketsSecure.exactMatch(ma);
16
- });
17
- }
18
- /**
19
- * @deprecated Configure this globally by passing a `connectionGater` to `createLibp2p`
20
- */
21
- export function dnsWss(multiaddrs) {
22
- return multiaddrs.filter((ma) => {
23
- return DNS.matches(ma) && WebSocketsSecure.exactMatch(ma);
24
- });
25
- }
26
- /**
27
- * @deprecated Configure this globally by passing a `connectionGater` to `createLibp2p`
28
- */
29
- export function dnsWsOrWss(multiaddrs) {
30
- return multiaddrs.filter((ma) => {
31
- return DNS.matches(ma) && (WebSocketsSecure.exactMatch(ma) || WebSockets.exactMatch(ma));
32
- });
33
- }
34
- //# sourceMappingURL=filters.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filters.js","sourceRoot":"","sources":["../../src/filters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAA;AAGnF;;GAEG;AACH,MAAM,UAAU,GAAG,CAAE,UAAuB;IAC1C,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;QAC9B,OAAO,gBAAgB,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IACrE,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,GAAG,CAAE,UAAuB;IAC1C,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;QAC9B,OAAO,gBAAgB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,MAAM,CAAE,UAAuB;IAC7C,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;QAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,gBAAgB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAE,UAAuB;IACjD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;QAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAA;IAC1F,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -1,11 +0,0 @@
1
- import type { ComponentLogger, CounterGroup, MultiaddrConnection } from '@libp2p/interface';
2
- import type { Multiaddr } from '@multiformats/multiaddr';
3
- import type { DuplexWebSocket } from 'it-ws/duplex';
4
- export interface SocketToConnOptions {
5
- localAddr?: Multiaddr;
6
- logger: ComponentLogger;
7
- metrics?: CounterGroup;
8
- metricPrefix?: string;
9
- }
10
- export declare function socketToMaConn(stream: DuplexWebSocket, remoteAddr: Multiaddr, options: SocketToConnOptions): MultiaddrConnection;
11
- //# sourceMappingURL=socket-to-conn.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"socket-to-conn.d.ts","sourceRoot":"","sources":["../../src/socket-to-conn.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,eAAe,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACzG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEnD,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,MAAM,EAAE,eAAe,CAAA;IACvB,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAID,wBAAgB,cAAc,CAAE,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,CAkGjI"}
@@ -1,88 +0,0 @@
1
- import { AbortError, ConnectionFailedError } from '@libp2p/interface';
2
- import { CLOSE_TIMEOUT } from './constants.js';
3
- // Convert a stream into a MultiaddrConnection
4
- // https://github.com/libp2p/interface-transport#multiaddrconnection
5
- export function socketToMaConn(stream, remoteAddr, options) {
6
- const metrics = options.metrics;
7
- const metricPrefix = options.metricPrefix ?? '';
8
- const maConn = {
9
- log: options.logger.forComponent('libp2p:websockets:connection'),
10
- async sink(source) {
11
- try {
12
- await stream.sink((async function* () {
13
- for await (const buf of source) {
14
- if (buf instanceof Uint8Array) {
15
- yield buf;
16
- }
17
- else {
18
- yield buf.subarray();
19
- }
20
- }
21
- })());
22
- }
23
- catch (err) {
24
- if (err.type !== 'aborted') {
25
- maConn.log.error(err);
26
- }
27
- }
28
- },
29
- source: stream.source,
30
- remoteAddr,
31
- timeline: { open: Date.now() },
32
- async close(options = {}) {
33
- const start = Date.now();
34
- if (options.signal == null) {
35
- const signal = AbortSignal.timeout(CLOSE_TIMEOUT);
36
- options = {
37
- ...options,
38
- signal
39
- };
40
- }
41
- const listener = () => {
42
- const { host, port } = maConn.remoteAddr.toOptions();
43
- maConn.log('timeout closing stream to %s:%s after %dms, destroying it manually', host, port, Date.now() - start);
44
- this.abort(new AbortError('Socket close timeout'));
45
- };
46
- options.signal?.addEventListener('abort', listener);
47
- try {
48
- await stream.close();
49
- }
50
- catch (err) {
51
- maConn.log.error('error closing WebSocket gracefully - %e', err);
52
- this.abort(err);
53
- }
54
- finally {
55
- options.signal?.removeEventListener('abort', listener);
56
- maConn.timeline.close = Date.now();
57
- }
58
- },
59
- abort(err) {
60
- maConn.log.error('destroying WebSocket after error - %e', err);
61
- stream.destroy();
62
- maConn.timeline.close = Date.now();
63
- // ws WebSocket.terminate does not accept an Error arg to emit an 'error'
64
- // event on destroy like other node streams so we can't update a metric
65
- // with an event listener
66
- // https://github.com/websockets/ws/issues/1752#issuecomment-622380981
67
- metrics?.increment({ [`${metricPrefix}error`]: true });
68
- }
69
- };
70
- // track local vs remote closing
71
- let closedLocally = false;
72
- const close = stream.socket.close.bind(stream.socket);
73
- stream.socket.close = (...args) => {
74
- closedLocally = true;
75
- return close(...args);
76
- };
77
- stream.socket.addEventListener('close', (evt) => {
78
- maConn.log('closed %s, code %d, reason "%s", wasClean %s', closedLocally ? 'locally' : 'by remote', evt.code, evt.reason, evt.wasClean);
79
- if (!evt.wasClean) {
80
- maConn.abort(new ConnectionFailedError(`${closedLocally ? 'Local' : 'Remote'} did not close WebSocket cleanly`));
81
- return;
82
- }
83
- metrics?.increment({ [`${metricPrefix}close`]: true });
84
- maConn.timeline.close = Date.now();
85
- }, { once: true });
86
- return maConn;
87
- }
88
- //# sourceMappingURL=socket-to-conn.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"socket-to-conn.js","sourceRoot":"","sources":["../../src/socket-to-conn.ts"],"names":[],"mappings":"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"}
@@ -1,20 +0,0 @@
1
- {
2
- "all": "https://libp2p.github.io/js-libp2p/functions/_libp2p_websockets.filters.all.html",
3
- "./filters:all": "https://libp2p.github.io/js-libp2p/functions/_libp2p_websockets.filters.all.html",
4
- "dnsWsOrWss": "https://libp2p.github.io/js-libp2p/functions/_libp2p_websockets.filters.dnsWsOrWss.html",
5
- "./filters:dnsWsOrWss": "https://libp2p.github.io/js-libp2p/functions/_libp2p_websockets.filters.dnsWsOrWss.html",
6
- "dnsWss": "https://libp2p.github.io/js-libp2p/functions/_libp2p_websockets.filters.dnsWss.html",
7
- "./filters:dnsWss": "https://libp2p.github.io/js-libp2p/functions/_libp2p_websockets.filters.dnsWss.html",
8
- "wss": "https://libp2p.github.io/js-libp2p/functions/_libp2p_websockets.filters.wss.html",
9
- "./filters:wss": "https://libp2p.github.io/js-libp2p/functions/_libp2p_websockets.filters.wss.html",
10
- "WebSocketsComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_websockets.index.WebSocketsComponents.html",
11
- ".:WebSocketsComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_websockets.index.WebSocketsComponents.html",
12
- "WebSocketsInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_websockets.index.WebSocketsInit.html",
13
- ".:WebSocketsInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_websockets.index.WebSocketsInit.html",
14
- "WebSocketsMetrics": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_websockets.index.WebSocketsMetrics.html",
15
- ".:WebSocketsMetrics": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_websockets.index.WebSocketsMetrics.html",
16
- "WebSocketsDialEvents": "https://libp2p.github.io/js-libp2p/types/_libp2p_websockets.index.WebSocketsDialEvents.html",
17
- ".:WebSocketsDialEvents": "https://libp2p.github.io/js-libp2p/types/_libp2p_websockets.index.WebSocketsDialEvents.html",
18
- "webSockets": "https://libp2p.github.io/js-libp2p/functions/_libp2p_websockets.index.webSockets.html",
19
- ".:webSockets": "https://libp2p.github.io/js-libp2p/functions/_libp2p_websockets.index.webSockets.html"
20
- }