libp2p 0.37.3-e6f646e → 0.38.0-0e7096d

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.
Files changed (125) hide show
  1. package/README.md +0 -2
  2. package/dist/src/circuit/circuit/hop.d.ts +5 -3
  3. package/dist/src/circuit/circuit/hop.d.ts.map +1 -1
  4. package/dist/src/circuit/circuit/hop.js +8 -4
  5. package/dist/src/circuit/circuit/hop.js.map +1 -1
  6. package/dist/src/circuit/circuit/stop.d.ts +5 -3
  7. package/dist/src/circuit/circuit/stop.d.ts.map +1 -1
  8. package/dist/src/circuit/circuit/stop.js +4 -2
  9. package/dist/src/circuit/circuit/stop.js.map +1 -1
  10. package/dist/src/circuit/circuit/stream-handler.d.ts +2 -1
  11. package/dist/src/circuit/circuit/stream-handler.d.ts.map +1 -1
  12. package/dist/src/circuit/circuit/stream-handler.js +2 -2
  13. package/dist/src/circuit/circuit/stream-handler.js.map +1 -1
  14. package/dist/src/circuit/index.d.ts +2 -10
  15. package/dist/src/circuit/index.d.ts.map +1 -1
  16. package/dist/src/circuit/index.js.map +1 -1
  17. package/dist/src/circuit/pb/index.d.ts +5 -4
  18. package/dist/src/circuit/pb/index.d.ts.map +1 -1
  19. package/dist/src/circuit/pb/index.js +107 -11
  20. package/dist/src/circuit/pb/index.js.map +1 -1
  21. package/dist/src/circuit/transport.d.ts +3 -0
  22. package/dist/src/circuit/transport.d.ts.map +1 -1
  23. package/dist/src/circuit/transport.js +79 -57
  24. package/dist/src/circuit/transport.js.map +1 -1
  25. package/dist/src/config.d.ts.map +1 -1
  26. package/dist/src/config.js +19 -4
  27. package/dist/src/config.js.map +1 -1
  28. package/dist/src/connection-manager/dialer/auto-dialer.d.ts.map +1 -1
  29. package/dist/src/connection-manager/dialer/auto-dialer.js +6 -0
  30. package/dist/src/connection-manager/dialer/auto-dialer.js.map +1 -1
  31. package/dist/src/connection-manager/dialer/index.d.ts +4 -4
  32. package/dist/src/connection-manager/dialer/index.d.ts.map +1 -1
  33. package/dist/src/connection-manager/dialer/index.js +10 -10
  34. package/dist/src/connection-manager/dialer/index.js.map +1 -1
  35. package/dist/src/connection-manager/index.d.ts +8 -1
  36. package/dist/src/connection-manager/index.d.ts.map +1 -1
  37. package/dist/src/connection-manager/index.js +42 -16
  38. package/dist/src/connection-manager/index.js.map +1 -1
  39. package/dist/src/constants.d.ts +4 -0
  40. package/dist/src/constants.d.ts.map +1 -1
  41. package/dist/src/constants.js +4 -0
  42. package/dist/src/constants.js.map +1 -1
  43. package/dist/src/fetch/index.d.ts +4 -0
  44. package/dist/src/fetch/index.d.ts.map +1 -1
  45. package/dist/src/fetch/index.js +25 -6
  46. package/dist/src/fetch/index.js.map +1 -1
  47. package/dist/src/fetch/pb/proto.d.ts +4 -3
  48. package/dist/src/fetch/pb/proto.d.ts.map +1 -1
  49. package/dist/src/fetch/pb/proto.js +88 -8
  50. package/dist/src/fetch/pb/proto.js.map +1 -1
  51. package/dist/src/identify/index.d.ts +1 -1
  52. package/dist/src/identify/index.d.ts.map +1 -1
  53. package/dist/src/identify/index.js +35 -12
  54. package/dist/src/identify/index.js.map +1 -1
  55. package/dist/src/identify/pb/message.d.ts +2 -1
  56. package/dist/src/identify/pb/message.d.ts.map +1 -1
  57. package/dist/src/identify/pb/message.js +94 -10
  58. package/dist/src/identify/pb/message.js.map +1 -1
  59. package/dist/src/index.d.ts +1 -5
  60. package/dist/src/index.d.ts.map +1 -1
  61. package/dist/src/index.js.map +1 -1
  62. package/dist/src/insecure/index.d.ts.map +1 -1
  63. package/dist/src/insecure/index.js +7 -3
  64. package/dist/src/insecure/index.js.map +1 -1
  65. package/dist/src/insecure/pb/proto.d.ts +4 -3
  66. package/dist/src/insecure/pb/proto.d.ts.map +1 -1
  67. package/dist/src/insecure/pb/proto.js +89 -9
  68. package/dist/src/insecure/pb/proto.js.map +1 -1
  69. package/dist/src/keychain/index.d.ts +6 -1
  70. package/dist/src/keychain/index.d.ts.map +1 -1
  71. package/dist/src/keychain/index.js +19 -2
  72. package/dist/src/keychain/index.js.map +1 -1
  73. package/dist/src/libp2p.d.ts +0 -5
  74. package/dist/src/libp2p.d.ts.map +1 -1
  75. package/dist/src/libp2p.js +3 -17
  76. package/dist/src/libp2p.js.map +1 -1
  77. package/dist/src/metrics/index.d.ts +1 -2
  78. package/dist/src/metrics/index.d.ts.map +1 -1
  79. package/dist/src/metrics/index.js +3 -4
  80. package/dist/src/metrics/index.js.map +1 -1
  81. package/dist/src/ping/index.d.ts +4 -0
  82. package/dist/src/ping/index.d.ts.map +1 -1
  83. package/dist/src/ping/index.js +27 -8
  84. package/dist/src/ping/index.js.map +1 -1
  85. package/dist/src/pnet/index.d.ts.map +1 -1
  86. package/dist/src/pnet/index.js +2 -1
  87. package/dist/src/pnet/index.js.map +1 -1
  88. package/dist/src/registrar.d.ts +2 -2
  89. package/dist/src/registrar.d.ts.map +1 -1
  90. package/dist/src/registrar.js +2 -2
  91. package/dist/src/registrar.js.map +1 -1
  92. package/dist/src/upgrader.d.ts +6 -0
  93. package/dist/src/upgrader.d.ts.map +1 -1
  94. package/dist/src/upgrader.js +121 -75
  95. package/dist/src/upgrader.js.map +1 -1
  96. package/dist/src/version.d.ts.map +1 -1
  97. package/dist/src/version.js.map +1 -1
  98. package/package.json +48 -47
  99. package/src/circuit/README.md +2 -2
  100. package/src/circuit/circuit/hop.ts +18 -9
  101. package/src/circuit/circuit/stop.ts +9 -4
  102. package/src/circuit/circuit/stream-handler.ts +5 -4
  103. package/src/circuit/index.ts +2 -11
  104. package/src/circuit/pb/index.ts +133 -15
  105. package/src/circuit/transport.ts +87 -58
  106. package/src/config.ts +19 -4
  107. package/src/connection-manager/dialer/auto-dialer.ts +6 -0
  108. package/src/connection-manager/dialer/index.ts +10 -10
  109. package/src/connection-manager/index.ts +54 -19
  110. package/src/constants.ts +5 -0
  111. package/src/fetch/index.ts +34 -8
  112. package/src/fetch/pb/proto.ts +109 -11
  113. package/src/identify/index.ts +41 -19
  114. package/src/identify/pb/message.ts +111 -11
  115. package/src/index.ts +1 -6
  116. package/src/insecure/index.ts +8 -3
  117. package/src/insecure/pb/proto.ts +111 -12
  118. package/src/keychain/index.ts +27 -3
  119. package/src/libp2p.ts +3 -18
  120. package/src/metrics/index.ts +4 -7
  121. package/src/ping/index.ts +37 -11
  122. package/src/pnet/index.ts +2 -0
  123. package/src/registrar.ts +2 -2
  124. package/src/upgrader.ts +138 -78
  125. package/src/version.ts +1 -2
@@ -12,6 +12,8 @@ import { peerIdFromBytes } from '@libp2p/peer-id'
12
12
  import type { Duplex } from 'it-stream-types'
13
13
  import type { Circuit } from '../transport.js'
14
14
  import type { ConnectionManager } from '@libp2p/interface-connection-manager'
15
+ import type { AbortOptions } from '@libp2p/interfaces'
16
+ import type { Uint8ArrayList } from 'uint8arraylist'
15
17
 
16
18
  const log = logger('libp2p:circuit:hop')
17
19
 
@@ -23,7 +25,7 @@ export interface HopRequest {
23
25
  connectionManager: ConnectionManager
24
26
  }
25
27
 
26
- export async function handleHop (hopRequest: HopRequest) {
28
+ export async function handleHop (hopRequest: HopRequest): Promise<void> {
27
29
  const {
28
30
  connection,
29
31
  request,
@@ -83,7 +85,7 @@ export async function handleHop (hopRequest: HopRequest) {
83
85
  srcPeer: request.srcPeer
84
86
  }
85
87
 
86
- let destinationStream: Duplex<Uint8Array>
88
+ let destinationStream: Duplex<Uint8ArrayList>
87
89
  try {
88
90
  log('performing STOP request')
89
91
  const result = await stop({
@@ -118,7 +120,7 @@ export async function handleHop (hopRequest: HopRequest) {
118
120
  )
119
121
  }
120
122
 
121
- export interface HopConfig {
123
+ export interface HopConfig extends AbortOptions {
122
124
  connection: Connection
123
125
  request: CircuitPB
124
126
  }
@@ -127,14 +129,17 @@ export interface HopConfig {
127
129
  * Performs a HOP request to a relay peer, to request a connection to another
128
130
  * peer. A new, virtual, connection will be created between the two via the relay.
129
131
  */
130
- export async function hop (options: HopConfig): Promise<Duplex<Uint8Array>> {
132
+ export async function hop (options: HopConfig): Promise<Duplex<Uint8ArrayList, Uint8ArrayList | Uint8Array>> {
131
133
  const {
132
134
  connection,
133
- request
135
+ request,
136
+ signal
134
137
  } = options
135
138
 
136
139
  // Create a new stream to the relay
137
- const stream = await connection.newStream(RELAY_CODEC)
140
+ const stream = await connection.newStream(RELAY_CODEC, {
141
+ signal
142
+ })
138
143
  // Send the HOP request
139
144
  const streamHandler = new StreamHandler({ stream })
140
145
  streamHandler.write(request)
@@ -147,6 +152,7 @@ export async function hop (options: HopConfig): Promise<Duplex<Uint8Array>> {
147
152
 
148
153
  if (response.code === CircuitPB.Status.SUCCESS) {
149
154
  log('hop request was successful')
155
+
150
156
  return streamHandler.rest()
151
157
  }
152
158
 
@@ -156,7 +162,7 @@ export async function hop (options: HopConfig): Promise<Duplex<Uint8Array>> {
156
162
  throw errCode(new Error(`HOP request failed with code "${response.code ?? 'unknown'}"`), Errors.ERR_HOP_REQUEST_FAILED)
157
163
  }
158
164
 
159
- export interface CanHopOptions {
165
+ export interface CanHopOptions extends AbortOptions {
160
166
  connection: Connection
161
167
  }
162
168
 
@@ -165,11 +171,14 @@ export interface CanHopOptions {
165
171
  */
166
172
  export async function canHop (options: CanHopOptions) {
167
173
  const {
168
- connection
174
+ connection,
175
+ signal
169
176
  } = options
170
177
 
171
178
  // Create a new stream to the relay
172
- const stream = await connection.newStream(RELAY_CODEC)
179
+ const stream = await connection.newStream(RELAY_CODEC, {
180
+ signal
181
+ })
173
182
 
174
183
  // Send the HOP request
175
184
  const streamHandler = new StreamHandler({ stream })
@@ -5,6 +5,8 @@ import { StreamHandler } from './stream-handler.js'
5
5
  import { validateAddrs } from './utils.js'
6
6
  import type { Connection } from '@libp2p/interface-connection'
7
7
  import type { Duplex } from 'it-stream-types'
8
+ import type { AbortOptions } from '@libp2p/interfaces'
9
+ import type { Uint8ArrayList } from 'uint8arraylist'
8
10
 
9
11
  const log = logger('libp2p:circuit:stop')
10
12
 
@@ -17,7 +19,7 @@ export interface HandleStopOptions {
17
19
  /**
18
20
  * Handles incoming STOP requests
19
21
  */
20
- export function handleStop (options: HandleStopOptions): Duplex<Uint8Array> | undefined {
22
+ export function handleStop (options: HandleStopOptions): Duplex<Uint8ArrayList, Uint8ArrayList | Uint8Array> | undefined {
21
23
  const {
22
24
  connection,
23
25
  request,
@@ -42,7 +44,7 @@ export function handleStop (options: HandleStopOptions): Duplex<Uint8Array> | un
42
44
  return streamHandler.rest()
43
45
  }
44
46
 
45
- export interface StopOptions {
47
+ export interface StopOptions extends AbortOptions {
46
48
  connection: Connection
47
49
  request: CircuitPB
48
50
  }
@@ -53,10 +55,13 @@ export interface StopOptions {
53
55
  export async function stop (options: StopOptions) {
54
56
  const {
55
57
  connection,
56
- request
58
+ request,
59
+ signal
57
60
  } = options
58
61
 
59
- const stream = await connection.newStream([RELAY_CODEC])
62
+ const stream = await connection.newStream(RELAY_CODEC, {
63
+ signal
64
+ })
60
65
  log('starting stop request to %p', connection.remotePeer)
61
66
  const streamHandler = new StreamHandler({ stream })
62
67
 
@@ -4,6 +4,7 @@ import { Handshake, handshake } from 'it-handshake'
4
4
  import { CircuitRelay } from '../pb/index.js'
5
5
  import type { Stream } from '@libp2p/interface-connection'
6
6
  import type { Source } from 'it-stream-types'
7
+ import type { Uint8ArrayList } from 'uint8arraylist'
7
8
 
8
9
  const log = logger('libp2p:circuit:stream-handler')
9
10
 
@@ -21,8 +22,8 @@ export interface StreamHandlerOptions {
21
22
 
22
23
  export class StreamHandler {
23
24
  private readonly stream: Stream
24
- private readonly shake: Handshake
25
- private readonly decoder: Source<Uint8Array>
25
+ private readonly shake: Handshake<Uint8ArrayList | Uint8Array>
26
+ private readonly decoder: Source<Uint8ArrayList>
26
27
 
27
28
  constructor (options: StreamHandlerOptions) {
28
29
  const { stream, maxLength = 4096 } = options
@@ -40,7 +41,7 @@ export class StreamHandler {
40
41
  const msg = await this.decoder.next()
41
42
 
42
43
  if (msg.value != null) {
43
- const value = CircuitRelay.decode(msg.value.slice())
44
+ const value = CircuitRelay.decode(msg.value)
44
45
  log('read message type', value.type)
45
46
  return value
46
47
  }
@@ -55,7 +56,7 @@ export class StreamHandler {
55
56
  */
56
57
  write (msg: CircuitRelay) {
57
58
  log('write message type %s', msg.type)
58
- this.shake.write(lp.encode.single(CircuitRelay.encode(msg)).slice())
59
+ this.shake.write(lp.encode.single(CircuitRelay.encode(msg)))
59
60
  }
60
61
 
61
62
  /**
@@ -13,6 +13,7 @@ import {
13
13
  import type { AddressSorter } from '@libp2p/interface-peer-store'
14
14
  import type { Startable } from '@libp2p/interfaces/startable'
15
15
  import type { Components } from '@libp2p/components'
16
+ import type { RelayConfig } from '../index.js'
16
17
 
17
18
  const log = logger('libp2p:relay')
18
19
 
@@ -22,11 +23,6 @@ export interface RelayAdvertiseConfig {
22
23
  ttl?: number
23
24
  }
24
25
 
25
- export interface HopConfig {
26
- enabled?: boolean
27
- active?: boolean
28
- }
29
-
30
26
  export interface AutoRelayConfig {
31
27
  enabled?: boolean
32
28
 
@@ -36,13 +32,8 @@ export interface AutoRelayConfig {
36
32
  maxListeners: number
37
33
  }
38
34
 
39
- export interface RelayInit {
35
+ export interface RelayInit extends RelayConfig {
40
36
  addressSorter?: AddressSorter
41
- maxListeners?: number
42
- onError?: (error: Error, msg?: string) => void
43
- hop: HopConfig
44
- advertise: RelayAdvertiseConfig
45
- autoRelay: AutoRelayConfig
46
37
  }
47
38
 
48
39
  export class Relay implements Startable {
@@ -1,7 +1,8 @@
1
1
  /* eslint-disable import/export */
2
2
  /* eslint-disable @typescript-eslint/no-namespace */
3
3
 
4
- import { enumeration, encodeMessage, decodeMessage, message, bytes } from 'protons-runtime'
4
+ import { enumeration, encodeMessage, decodeMessage, message } from 'protons-runtime'
5
+ import type { Uint8ArrayList } from 'uint8arraylist'
5
6
  import type { Codec } from 'protons-runtime'
6
7
 
7
8
  export interface CircuitRelay {
@@ -52,7 +53,7 @@ export namespace CircuitRelay {
52
53
 
53
54
  export namespace Status {
54
55
  export const codec = () => {
55
- return enumeration<typeof Status>(__StatusValues)
56
+ return enumeration<Status>(__StatusValues)
56
57
  }
57
58
  }
58
59
 
@@ -72,7 +73,7 @@ export namespace CircuitRelay {
72
73
 
73
74
  export namespace Type {
74
75
  export const codec = () => {
75
- return enumeration<typeof Type>(__TypeValues)
76
+ return enumeration<Type>(__TypeValues)
76
77
  }
77
78
  }
78
79
 
@@ -82,36 +83,153 @@ export namespace CircuitRelay {
82
83
  }
83
84
 
84
85
  export namespace Peer {
86
+ let _codec: Codec<Peer>
87
+
85
88
  export const codec = (): Codec<Peer> => {
86
- return message<Peer>({
87
- 1: { name: 'id', codec: bytes },
88
- 2: { name: 'addrs', codec: bytes, repeats: true }
89
- })
89
+ if (_codec == null) {
90
+ _codec = message<Peer>((obj, writer, opts = {}) => {
91
+ if (opts.lengthDelimited !== false) {
92
+ writer.fork()
93
+ }
94
+
95
+ if (obj.id != null) {
96
+ writer.uint32(10)
97
+ writer.bytes(obj.id)
98
+ } else {
99
+ throw new Error('Protocol error: required field "id" was not found in object')
100
+ }
101
+
102
+ if (obj.addrs != null) {
103
+ for (const value of obj.addrs) {
104
+ writer.uint32(18)
105
+ writer.bytes(value)
106
+ }
107
+ } else {
108
+ throw new Error('Protocol error: required field "addrs" was not found in object')
109
+ }
110
+
111
+ if (opts.lengthDelimited !== false) {
112
+ writer.ldelim()
113
+ }
114
+ }, (reader, length) => {
115
+ const obj: any = {}
116
+
117
+ const end = length == null ? reader.len : reader.pos + length
118
+
119
+ while (reader.pos < end) {
120
+ const tag = reader.uint32()
121
+
122
+ switch (tag >>> 3) {
123
+ case 1:
124
+ obj.id = reader.bytes()
125
+ break
126
+ case 2:
127
+ obj.addrs = obj.addrs ?? []
128
+ obj.addrs.push(reader.bytes())
129
+ break
130
+ default:
131
+ reader.skipType(tag & 7)
132
+ break
133
+ }
134
+ }
135
+
136
+ obj.addrs = obj.addrs ?? []
137
+
138
+ if (obj.id == null) {
139
+ throw new Error('Protocol error: value for required field "id" was not found in protobuf')
140
+ }
141
+
142
+ if (obj.addrs == null) {
143
+ throw new Error('Protocol error: value for required field "addrs" was not found in protobuf')
144
+ }
145
+
146
+ return obj
147
+ })
148
+ }
149
+
150
+ return _codec
90
151
  }
91
152
 
92
153
  export const encode = (obj: Peer): Uint8Array => {
93
154
  return encodeMessage(obj, Peer.codec())
94
155
  }
95
156
 
96
- export const decode = (buf: Uint8Array): Peer => {
157
+ export const decode = (buf: Uint8Array | Uint8ArrayList): Peer => {
97
158
  return decodeMessage(buf, Peer.codec())
98
159
  }
99
160
  }
100
161
 
162
+ let _codec: Codec<CircuitRelay>
163
+
101
164
  export const codec = (): Codec<CircuitRelay> => {
102
- return message<CircuitRelay>({
103
- 1: { name: 'type', codec: CircuitRelay.Type.codec(), optional: true },
104
- 2: { name: 'srcPeer', codec: CircuitRelay.Peer.codec(), optional: true },
105
- 3: { name: 'dstPeer', codec: CircuitRelay.Peer.codec(), optional: true },
106
- 4: { name: 'code', codec: CircuitRelay.Status.codec(), optional: true }
107
- })
165
+ if (_codec == null) {
166
+ _codec = message<CircuitRelay>((obj, writer, opts = {}) => {
167
+ if (opts.lengthDelimited !== false) {
168
+ writer.fork()
169
+ }
170
+
171
+ if (obj.type != null) {
172
+ writer.uint32(8)
173
+ CircuitRelay.Type.codec().encode(obj.type, writer)
174
+ }
175
+
176
+ if (obj.srcPeer != null) {
177
+ writer.uint32(18)
178
+ CircuitRelay.Peer.codec().encode(obj.srcPeer, writer)
179
+ }
180
+
181
+ if (obj.dstPeer != null) {
182
+ writer.uint32(26)
183
+ CircuitRelay.Peer.codec().encode(obj.dstPeer, writer)
184
+ }
185
+
186
+ if (obj.code != null) {
187
+ writer.uint32(32)
188
+ CircuitRelay.Status.codec().encode(obj.code, writer)
189
+ }
190
+
191
+ if (opts.lengthDelimited !== false) {
192
+ writer.ldelim()
193
+ }
194
+ }, (reader, length) => {
195
+ const obj: any = {}
196
+
197
+ const end = length == null ? reader.len : reader.pos + length
198
+
199
+ while (reader.pos < end) {
200
+ const tag = reader.uint32()
201
+
202
+ switch (tag >>> 3) {
203
+ case 1:
204
+ obj.type = CircuitRelay.Type.codec().decode(reader)
205
+ break
206
+ case 2:
207
+ obj.srcPeer = CircuitRelay.Peer.codec().decode(reader, reader.uint32())
208
+ break
209
+ case 3:
210
+ obj.dstPeer = CircuitRelay.Peer.codec().decode(reader, reader.uint32())
211
+ break
212
+ case 4:
213
+ obj.code = CircuitRelay.Status.codec().decode(reader)
214
+ break
215
+ default:
216
+ reader.skipType(tag & 7)
217
+ break
218
+ }
219
+ }
220
+
221
+ return obj
222
+ })
223
+ }
224
+
225
+ return _codec
108
226
  }
109
227
 
110
228
  export const encode = (obj: CircuitRelay): Uint8Array => {
111
229
  return encodeMessage(obj, CircuitRelay.codec())
112
230
  }
113
231
 
114
- export const decode = (buf: Uint8Array): CircuitRelay => {
232
+ export const decode = (buf: Uint8Array | Uint8ArrayList): CircuitRelay => {
115
233
  return decodeMessage(buf, CircuitRelay.codec())
116
234
  }
117
235
  }
@@ -17,12 +17,23 @@ import type { AbortOptions } from '@libp2p/interfaces'
17
17
  import type { IncomingStreamData } from '@libp2p/interface-registrar'
18
18
  import type { Listener, Transport, CreateListenerOptions, ConnectionHandler } from '@libp2p/interface-transport'
19
19
  import type { Connection } from '@libp2p/interface-connection'
20
+ import type { RelayConfig } from '../index.js'
21
+ import { abortableDuplex } from 'abortable-iterator'
22
+ import { TimeoutController } from 'timeout-abort-controller'
23
+ import { setMaxListeners } from 'events'
24
+ import type { Uint8ArrayList } from 'uint8arraylist'
25
+ import type { Duplex } from 'it-stream-types'
20
26
 
21
27
  const log = logger('libp2p:circuit')
22
28
 
23
29
  export class Circuit implements Transport, Initializable {
24
30
  private handler?: ConnectionHandler
25
31
  private components: Components = new Components()
32
+ private readonly _init: RelayConfig
33
+
34
+ constructor (init: RelayConfig) {
35
+ this._init = init
36
+ }
26
37
 
27
38
  init (components: Components): void {
28
39
  this.components = components
@@ -54,49 +65,25 @@ export class Circuit implements Transport, Initializable {
54
65
 
55
66
  async _onProtocol (data: IncomingStreamData) {
56
67
  const { connection, stream } = data
57
- const streamHandler = new StreamHandler({ stream })
58
- const request = await streamHandler.read()
59
-
60
- if (request == null) {
61
- log('request was invalid, could not read from stream')
62
- streamHandler.write({
63
- type: CircuitPB.Type.STATUS,
64
- code: CircuitPB.Status.MALFORMED_MESSAGE
65
- })
66
- streamHandler.close()
67
- return
68
- }
68
+ const controller = new TimeoutController(this._init.hop.timeout)
69
69
 
70
- let virtualConnection
70
+ try {
71
+ // fails on node < 15.4
72
+ setMaxListeners?.(Infinity, controller.signal)
73
+ } catch {}
71
74
 
72
- switch (request.type) {
73
- case CircuitPB.Type.CAN_HOP: {
74
- log('received CAN_HOP request from %p', connection.remotePeer)
75
- await handleCanHop({ circuit: this, connection, streamHandler })
76
- break
77
- }
78
- case CircuitPB.Type.HOP: {
79
- log('received HOP request from %p', connection.remotePeer)
80
- virtualConnection = await handleHop({
81
- connection,
82
- request,
83
- streamHandler,
84
- circuit: this,
85
- connectionManager: this.components.getConnectionManager()
86
- })
87
- break
88
- }
89
- case CircuitPB.Type.STOP: {
90
- log('received STOP request from %p', connection.remotePeer)
91
- virtualConnection = await handleStop({
92
- connection,
93
- request,
94
- streamHandler
95
- })
96
- break
97
- }
98
- default: {
99
- log('Request of type %s not supported', request.type)
75
+ try {
76
+ const source = abortableDuplex(stream, controller.signal)
77
+ const streamHandler = new StreamHandler({
78
+ stream: {
79
+ ...stream,
80
+ ...source
81
+ }
82
+ })
83
+ const request = await streamHandler.read()
84
+
85
+ if (request == null) {
86
+ log('request was invalid, could not read from stream')
100
87
  streamHandler.write({
101
88
  type: CircuitPB.Type.STATUS,
102
89
  code: CircuitPB.Status.MALFORMED_MESSAGE
@@ -104,27 +91,68 @@ export class Circuit implements Transport, Initializable {
104
91
  streamHandler.close()
105
92
  return
106
93
  }
107
- }
108
94
 
109
- if (virtualConnection != null) {
110
- // @ts-expect-error dst peer will not be undefined
111
- const remoteAddr = new Multiaddr(request.dstPeer.addrs[0])
112
- // @ts-expect-error dst peer will not be undefined
113
- const localAddr = new Multiaddr(request.srcPeer.addrs[0])
114
- const maConn = streamToMaConnection({
115
- stream: virtualConnection,
116
- remoteAddr,
117
- localAddr
118
- })
119
- const type = request.type === CircuitPB.Type.HOP ? 'relay' : 'inbound'
120
- log('new %s connection %s', type, maConn.remoteAddr)
95
+ let virtualConnection: Duplex<Uint8ArrayList, Uint8ArrayList | Uint8Array> | undefined
96
+
97
+ switch (request.type) {
98
+ case CircuitPB.Type.CAN_HOP: {
99
+ log('received CAN_HOP request from %p', connection.remotePeer)
100
+ await handleCanHop({ circuit: this, connection, streamHandler })
101
+ break
102
+ }
103
+ case CircuitPB.Type.HOP: {
104
+ log('received HOP request from %p', connection.remotePeer)
105
+ await handleHop({
106
+ connection,
107
+ request,
108
+ streamHandler,
109
+ circuit: this,
110
+ connectionManager: this.components.getConnectionManager()
111
+ })
112
+ break
113
+ }
114
+ case CircuitPB.Type.STOP: {
115
+ log('received STOP request from %p', connection.remotePeer)
116
+ virtualConnection = await handleStop({
117
+ connection,
118
+ request,
119
+ streamHandler
120
+ })
121
+ break
122
+ }
123
+ default: {
124
+ log('Request of type %s not supported', request.type)
125
+ streamHandler.write({
126
+ type: CircuitPB.Type.STATUS,
127
+ code: CircuitPB.Status.MALFORMED_MESSAGE
128
+ })
129
+ streamHandler.close()
130
+ return
131
+ }
132
+ }
121
133
 
122
- const conn = await this.components.getUpgrader().upgradeInbound(maConn)
123
- log('%s connection %s upgraded', type, maConn.remoteAddr)
134
+ if (virtualConnection != null) {
135
+ const remoteAddr = connection.remoteAddr
136
+ .encapsulate('/p2p-circuit')
137
+ .encapsulate(new Multiaddr(request.dstPeer?.addrs[0]))
138
+ const localAddr = new Multiaddr(request.srcPeer?.addrs[0])
139
+ const maConn = streamToMaConnection({
140
+ stream: virtualConnection,
141
+ remoteAddr,
142
+ localAddr
143
+ })
144
+ const type = request.type === CircuitPB.Type.HOP ? 'relay' : 'inbound'
145
+ log('new %s connection %s', type, maConn.remoteAddr)
146
+
147
+ const conn = await this.components.getUpgrader().upgradeInbound(maConn)
148
+ log('%s connection %s upgraded', type, maConn.remoteAddr)
124
149
 
125
- if (this.handler != null) {
126
- this.handler(conn)
150
+ if (this.handler != null) {
151
+ this.handler(conn)
152
+ }
127
153
  }
154
+ } finally {
155
+ controller.clear()
128
156
  }
129
157
  }
130
158
 
@@ -160,6 +188,7 @@ export class Circuit implements Transport, Initializable {
160
188
 
161
189
  try {
162
190
  const virtualConnection = await hop({
191
+ ...options,
163
192
  connection: relayConnection,
164
193
  request: {
165
194
  type: CircuitPB.Type.HOP,
package/src/config.ts CHANGED
@@ -10,6 +10,7 @@ import type { Libp2pInit } from './index.js'
10
10
  import { codes, messages } from './errors.js'
11
11
  import errCode from 'err-code'
12
12
  import type { RecursivePartial } from '@libp2p/interfaces'
13
+ import { isNode, isBrowser, isWebWorker, isElectronMain, isElectronRenderer, isReactNative } from 'wherearewe'
13
14
 
14
15
  const DefaultConfig: Partial<Libp2pInit> = {
15
16
  addresses: {
@@ -26,6 +27,7 @@ const DefaultConfig: Partial<Libp2pInit> = {
26
27
  maxParallelDials: Constants.MAX_PARALLEL_DIALS,
27
28
  maxDialsPerPeer: Constants.MAX_PER_PEER_DIALS,
28
29
  dialTimeout: Constants.DIAL_TIMEOUT,
30
+ inboundUpgradeTimeout: Constants.INBOUND_UPGRADE_TIMEOUT,
29
31
  resolvers: {
30
32
  dnsaddr: dnsaddrResolver
31
33
  },
@@ -67,7 +69,8 @@ const DefaultConfig: Partial<Libp2pInit> = {
67
69
  },
68
70
  hop: {
69
71
  enabled: false,
70
- active: false
72
+ active: false,
73
+ timeout: 30000
71
74
  },
72
75
  autoRelay: {
73
76
  enabled: false,
@@ -79,7 +82,8 @@ const DefaultConfig: Partial<Libp2pInit> = {
79
82
  host: {
80
83
  agentVersion: AGENT_VERSION
81
84
  },
82
- timeout: 30000,
85
+ // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L48
86
+ timeout: 60000,
83
87
  maxInboundStreams: 1,
84
88
  maxOutboundStreams: 1,
85
89
  maxPushIncomingStreams: 1,
@@ -88,12 +92,14 @@ const DefaultConfig: Partial<Libp2pInit> = {
88
92
  ping: {
89
93
  protocolPrefix: 'ipfs',
90
94
  maxInboundStreams: 1,
91
- maxOutboundStreams: 1
95
+ maxOutboundStreams: 1,
96
+ timeout: 10000
92
97
  },
93
98
  fetch: {
94
99
  protocolPrefix: 'libp2p',
95
100
  maxInboundStreams: 1,
96
- maxOutboundStreams: 1
101
+ maxOutboundStreams: 1,
102
+ timeout: 10000
97
103
  }
98
104
  }
99
105
 
@@ -112,5 +118,14 @@ export function validateConfig (opts: RecursivePartial<Libp2pInit>): Libp2pInit
112
118
  throw errCode(new Error(messages.ERR_PROTECTOR_REQUIRED), codes.ERR_PROTECTOR_REQUIRED)
113
119
  }
114
120
 
121
+ // Append user agent version to default AGENT_VERSION depending on the environment
122
+ if (resultingOptions.identify.host.agentVersion === AGENT_VERSION) {
123
+ if (isNode || isElectronMain) {
124
+ resultingOptions.identify.host.agentVersion += ` UserAgent=${globalThis.process.version}`
125
+ } else if (isBrowser || isWebWorker || isElectronRenderer || isReactNative) {
126
+ resultingOptions.identify.host.agentVersion += ` UserAgent=${globalThis.navigator.userAgent}`
127
+ }
128
+ }
129
+
115
130
  return resultingOptions
116
131
  }
@@ -2,6 +2,7 @@ import type { PeerInfo } from '@libp2p/interface-peer-info'
2
2
  import { logger } from '@libp2p/logger'
3
3
  import type { Components } from '@libp2p/components'
4
4
  import { TimeoutController } from 'timeout-abort-controller'
5
+ import { setMaxListeners } from 'events'
5
6
 
6
7
  const log = logger('libp2p:dialer:auto-dialer')
7
8
 
@@ -44,6 +45,11 @@ export class AutoDialer {
44
45
 
45
46
  const controller = new TimeoutController(this.dialTimeout)
46
47
 
48
+ try {
49
+ // fails on node < 15.4
50
+ setMaxListeners?.(Infinity, controller.signal)
51
+ } catch {}
52
+
47
53
  void this.components.getConnectionManager().openConnection(peer.id, {
48
54
  signal: controller.signal
49
55
  })