@libp2p/tcp 8.0.13 → 9.0.0

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/listener.ts CHANGED
@@ -1,7 +1,5 @@
1
1
  import net from 'net'
2
- import { CodeError } from '@libp2p/interface/errors'
3
- import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events'
4
- import { logger } from '@libp2p/logger'
2
+ import { CodeError, TypedEventEmitter, CustomEvent } from '@libp2p/interface'
5
3
  import { CODE_P2P } from './constants.js'
6
4
  import { toMultiaddrConnection } from './socket-to-conn.js'
7
5
  import {
@@ -10,21 +8,17 @@ import {
10
8
  type NetConfig
11
9
  } from './utils.js'
12
10
  import type { TCPCreateListenerOptions } from './index.js'
13
- import type { MultiaddrConnection, Connection } from '@libp2p/interface/connection'
14
- import type { CounterGroup, MetricGroup, Metrics } from '@libp2p/interface/metrics'
15
- import type { Listener, ListenerEvents, Upgrader } from '@libp2p/interface/transport'
11
+ import type { ComponentLogger, Logger, LoggerOptions, MultiaddrConnection, Connection, CounterGroup, MetricGroup, Metrics, Listener, ListenerEvents, Upgrader } from '@libp2p/interface'
16
12
  import type { Multiaddr } from '@multiformats/multiaddr'
17
13
 
18
- const log = logger('libp2p:tcp:listener')
19
-
20
14
  /**
21
15
  * Attempts to close the given maConn. If a failure occurs, it will be logged
22
16
  */
23
- async function attemptClose (maConn: MultiaddrConnection): Promise<void> {
17
+ async function attemptClose (maConn: MultiaddrConnection, options: LoggerOptions): Promise<void> {
24
18
  try {
25
19
  await maConn.close()
26
20
  } catch (err) {
27
- log.error('an error occurred closing the connection', err)
21
+ options.log.error('an error occurred closing the connection', err)
28
22
  }
29
23
  }
30
24
 
@@ -45,6 +39,7 @@ interface Context extends TCPCreateListenerOptions {
45
39
  backlog?: number
46
40
  metrics?: Metrics
47
41
  closeServerOnMaxConnections?: CloseServerOnMaxConnectionsOpts
42
+ logger: ComponentLogger
48
43
  }
49
44
 
50
45
  export interface TCPListenerMetrics {
@@ -78,12 +73,15 @@ export class TCPListener extends TypedEventEmitter<ListenerEvents> implements Li
78
73
  private status: Status = { code: TCPListenerStatusCode.INACTIVE }
79
74
  private metrics?: TCPListenerMetrics
80
75
  private addr: string
76
+ private readonly log: Logger
81
77
 
82
78
  constructor (private readonly context: Context) {
83
79
  super()
84
80
 
85
81
  context.keepAlive = context.keepAlive ?? true
82
+ context.noDelay = context.noDelay ?? true
86
83
 
84
+ this.log = context.logger.forComponent('libp2p:tcp:listener')
87
85
  this.addr = 'unknown'
88
86
  this.server = net.createServer(context, this.onSocket.bind(this))
89
87
 
@@ -172,7 +170,7 @@ export class TCPListener extends TypedEventEmitter<ListenerEvents> implements Li
172
170
  }
173
171
  // Avoid uncaught errors caused by unstable connections
174
172
  socket.on('error', err => {
175
- log('socket error', err)
173
+ this.log('socket error', err)
176
174
  this.metrics?.events.increment({ [`${this.addr} error`]: true })
177
175
  })
178
176
 
@@ -183,19 +181,20 @@ export class TCPListener extends TypedEventEmitter<ListenerEvents> implements Li
183
181
  socketInactivityTimeout: this.context.socketInactivityTimeout,
184
182
  socketCloseTimeout: this.context.socketCloseTimeout,
185
183
  metrics: this.metrics?.events,
186
- metricPrefix: `${this.addr} `
184
+ metricPrefix: `${this.addr} `,
185
+ logger: this.context.logger
187
186
  })
188
187
  } catch (err) {
189
- log.error('inbound connection failed', err)
188
+ this.log.error('inbound connection failed', err)
190
189
  this.metrics?.errors.increment({ [`${this.addr} inbound_to_connection`]: true })
191
190
  return
192
191
  }
193
192
 
194
- log('new inbound connection %s', maConn.remoteAddr)
193
+ this.log('new inbound connection %s', maConn.remoteAddr)
195
194
  try {
196
195
  this.context.upgrader.upgradeInbound(maConn)
197
196
  .then((conn) => {
198
- log('inbound connection upgraded %s', maConn.remoteAddr)
197
+ this.log('inbound connection upgraded %s', maConn.remoteAddr)
199
198
  this.connections.add(maConn)
200
199
 
201
200
  socket.once('close', () => {
@@ -210,7 +209,7 @@ export class TCPListener extends TypedEventEmitter<ListenerEvents> implements Li
210
209
  // we can do. resume() will be called again every time a connection is dropped, which
211
210
  // acts as an eventual retry mechanism. onListenError allows the consumer act on this.
212
211
  this.resume().catch(e => {
213
- log.error('error attempting to listen server once connection count under limit', e)
212
+ this.log.error('error attempting to listen server once connection count under limit', e)
214
213
  this.context.closeServerOnMaxConnections?.onListenError?.(e as Error)
215
214
  })
216
215
  }
@@ -225,27 +224,31 @@ export class TCPListener extends TypedEventEmitter<ListenerEvents> implements Li
225
224
  this.connections.size >= this.context.closeServerOnMaxConnections.closeAbove
226
225
  ) {
227
226
  this.pause(false).catch(e => {
228
- log.error('error attempting to close server once connection count over limit', e)
227
+ this.log.error('error attempting to close server once connection count over limit', e)
229
228
  })
230
229
  }
231
230
 
232
231
  this.dispatchEvent(new CustomEvent<Connection>('connection', { detail: conn }))
233
232
  })
234
233
  .catch(async err => {
235
- log.error('inbound connection failed', err)
234
+ this.log.error('inbound connection failed', err)
236
235
  this.metrics?.errors.increment({ [`${this.addr} inbound_upgrade`]: true })
237
236
 
238
- await attemptClose(maConn)
237
+ await attemptClose(maConn, {
238
+ log: this.log
239
+ })
239
240
  })
240
241
  .catch(err => {
241
- log.error('closing inbound connection failed', err)
242
+ this.log.error('closing inbound connection failed', err)
242
243
  })
243
244
  } catch (err) {
244
- log.error('inbound connection failed', err)
245
+ this.log.error('inbound connection failed', err)
245
246
 
246
- attemptClose(maConn)
247
+ attemptClose(maConn, {
248
+ log: this.log
249
+ })
247
250
  .catch(err => {
248
- log.error('closing inbound connection failed', err)
251
+ this.log.error('closing inbound connection failed', err)
249
252
  this.metrics?.errors.increment({ [`${this.addr} inbound_closing_failed`]: true })
250
253
  })
251
254
  }
@@ -276,7 +279,7 @@ export class TCPListener extends TypedEventEmitter<ListenerEvents> implements Li
276
279
  addrs = addrs.concat(getMultiaddrs('ip6', address.address, address.port))
277
280
  }
278
281
  } catch (err) {
279
- log.error('could not turn %s:%s into multiaddr', address.address, address.port, err)
282
+ this.log.error('could not turn %s:%s into multiaddr', address.address, address.port, err)
280
283
  }
281
284
  }
282
285
 
@@ -310,9 +313,11 @@ export class TCPListener extends TypedEventEmitter<ListenerEvents> implements Li
310
313
  async close (): Promise<void> {
311
314
  // Close connections and server the same time to avoid any race condition
312
315
  await Promise.all([
313
- Promise.all(Array.from(this.connections.values()).map(async maConn => attemptClose(maConn))),
316
+ Promise.all(Array.from(this.connections.values()).map(async maConn => attemptClose(maConn, {
317
+ log: this.log
318
+ }))),
314
319
  this.pause(true).catch(e => {
315
- log.error('error attempting to close server once connection count over limit', e)
320
+ this.log.error('error attempting to close server once connection count over limit', e)
316
321
  })
317
322
  ])
318
323
  }
@@ -334,7 +339,7 @@ export class TCPListener extends TypedEventEmitter<ListenerEvents> implements Li
334
339
  })
335
340
 
336
341
  this.status = { ...this.status, code: TCPListenerStatusCode.ACTIVE }
337
- log('Listening on %s', this.server.address())
342
+ this.log('Listening on %s', this.server.address())
338
343
  }
339
344
 
340
345
  private async pause (permanent: boolean): Promise<void> {
@@ -347,7 +352,7 @@ export class TCPListener extends TypedEventEmitter<ListenerEvents> implements Li
347
352
  return
348
353
  }
349
354
 
350
- log('Closing server on %s', this.server.address())
355
+ this.log('Closing server on %s', this.server.address())
351
356
 
352
357
  // NodeJS implementation tracks listening status with `this._handle` property.
353
358
  // - Server.close() sets this._handle to null immediately. If this._handle is null, ERR_SERVER_NOT_RUNNING is thrown
@@ -1,17 +1,13 @@
1
- import { CodeError } from '@libp2p/interface/errors'
2
- import { logger } from '@libp2p/logger'
1
+ import { CodeError } from '@libp2p/interface'
3
2
  import { ipPortToMultiaddr as toMultiaddr } from '@libp2p/utils/ip-port-to-multiaddr'
4
3
  // @ts-expect-error no types
5
4
  import toIterable from 'stream-to-it'
6
5
  import { CLOSE_TIMEOUT, SOCKET_TIMEOUT } from './constants.js'
7
6
  import { multiaddrToNetConfig } from './utils.js'
8
- import type { MultiaddrConnection } from '@libp2p/interface/connection'
9
- import type { CounterGroup } from '@libp2p/interface/metrics'
7
+ import type { ComponentLogger, MultiaddrConnection, CounterGroup } from '@libp2p/interface'
10
8
  import type { AbortOptions, Multiaddr } from '@multiformats/multiaddr'
11
9
  import type { Socket } from 'net'
12
10
 
13
- const log = logger('libp2p:tcp:socket')
14
-
15
11
  interface ToConnectionOptions {
16
12
  listeningAddr?: Multiaddr
17
13
  remoteAddr?: Multiaddr
@@ -20,6 +16,7 @@ interface ToConnectionOptions {
20
16
  socketCloseTimeout?: number
21
17
  metrics?: CounterGroup
22
18
  metricPrefix?: string
19
+ logger: ComponentLogger
23
20
  }
24
21
 
25
22
  /**
@@ -27,6 +24,7 @@ interface ToConnectionOptions {
27
24
  * https://github.com/libp2p/interface-transport#multiaddrconnection
28
25
  */
29
26
  export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptions): MultiaddrConnection => {
27
+ const log = options.logger.forComponent('libp2p:tcp:socket')
30
28
  const metrics = options.metrics
31
29
  const metricPrefix = options.metricPrefix ?? ''
32
30
  const inactivityTimeout = options.socketInactivityTimeout ?? SOCKET_TIMEOUT
@@ -98,7 +96,15 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio
98
96
  const maConn: MultiaddrConnection = {
99
97
  async sink (source) {
100
98
  try {
101
- await sink(source)
99
+ await sink((async function * () {
100
+ for await (const buf of source) {
101
+ if (buf instanceof Uint8Array) {
102
+ yield buf
103
+ } else {
104
+ yield buf.subarray()
105
+ }
106
+ }
107
+ })())
102
108
  } catch (err: any) {
103
109
  // If aborted we can safely ignore
104
110
  if (err.type !== 'aborted') {
@@ -182,7 +188,9 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio
182
188
  log('%s socket abort due to error', lOptsStr, err)
183
189
 
184
190
  socket.destroy(err)
185
- }
191
+ },
192
+
193
+ log
186
194
  }
187
195
 
188
196
  return maConn
package/src/utils.ts CHANGED
@@ -22,7 +22,7 @@ export function multiaddrToNetConfig (addr: Multiaddr, config: NetConfig = {}):
22
22
  }
23
23
 
24
24
  // tcp listening
25
- return { ...addr.toOptions(), ...config }
25
+ return { ...config, ...addr.toOptions() }
26
26
  }
27
27
 
28
28
  export function getMultiaddrs (proto: 'ip4' | 'ip6', ip: string, port: number): Multiaddr[] {