@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/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 { pEvent } from 'p-event'
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 { webSocketToMaConn } from './websocket-to-conn.js'
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 maConn = webSocketToMaConn({
143
- websocket: await this._connect(ma, options),
144
- remoteAddr: ma,
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<WebSocket> {
136
+ async _connect (ma: Multiaddr, options: DialTransportOptions<WebSocketsDialEvents>): Promise<DuplexWebSocket> {
159
137
  options?.signal?.throwIfAborted()
160
138
 
161
- const uri = toUri(ma)
162
- this.log('create websocket connection to %s', uri)
163
- const websocket = new WebSocket(uri)
164
- websocket.binaryType = 'arraybuffer'
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 pEvent(websocket, 'open', options)
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
- try {
178
- websocket.close()
179
- } catch {}
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 websocket
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 { getNetConfig, getThinWaistAddresses, ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils'
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 { toWebSocket } from './utils.ts'
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 = webSocketToMaConn({
201
- websocket: toWebSocket(socket),
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 config = getNetConfig(ma)
250
- this.addr = `${config.host}:${config.port}`
252
+ const options = ma.toOptions()
253
+ this.addr = `${options.host}:${options.port}`
251
254
 
252
255
  this.server.listen({
253
- ...config,
254
- ipv6Only: config.type === 'ip6'
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
+ }
@@ -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
@@ -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
@@ -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
- }