@libp2p/circuit-relay-v2 2.1.4 → 2.1.5-3bc9769b8

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 (63) hide show
  1. package/dist/index.min.js +4 -4
  2. package/dist/src/constants.d.ts +0 -5
  3. package/dist/src/constants.d.ts.map +1 -1
  4. package/dist/src/constants.js +0 -5
  5. package/dist/src/constants.js.map +1 -1
  6. package/dist/src/errors.d.ts +22 -0
  7. package/dist/src/errors.d.ts.map +1 -1
  8. package/dist/src/errors.js +22 -0
  9. package/dist/src/errors.js.map +1 -1
  10. package/dist/src/index.d.ts +16 -1
  11. package/dist/src/index.d.ts.map +1 -1
  12. package/dist/src/index.js.map +1 -1
  13. package/dist/src/pb/index.d.ts +12 -1
  14. package/dist/src/pb/index.d.ts.map +1 -1
  15. package/dist/src/pb/index.js +78 -2
  16. package/dist/src/pb/index.js.map +1 -1
  17. package/dist/src/server/index.d.ts.map +1 -1
  18. package/dist/src/server/index.js +19 -10
  19. package/dist/src/server/index.js.map +1 -1
  20. package/dist/src/server/reservation-store.d.ts +5 -9
  21. package/dist/src/server/reservation-store.d.ts.map +1 -1
  22. package/dist/src/server/reservation-store.js +32 -33
  23. package/dist/src/server/reservation-store.js.map +1 -1
  24. package/dist/src/server/reservation-voucher.d.ts +1 -1
  25. package/dist/src/transport/discovery.d.ts +1 -0
  26. package/dist/src/transport/discovery.d.ts.map +1 -1
  27. package/dist/src/transport/discovery.js +38 -8
  28. package/dist/src/transport/discovery.js.map +1 -1
  29. package/dist/src/transport/index.d.ts +0 -6
  30. package/dist/src/transport/index.d.ts.map +1 -1
  31. package/dist/src/transport/index.js.map +1 -1
  32. package/dist/src/transport/listener.d.ts +3 -0
  33. package/dist/src/transport/listener.d.ts.map +1 -1
  34. package/dist/src/transport/listener.js +57 -27
  35. package/dist/src/transport/listener.js.map +1 -1
  36. package/dist/src/transport/reservation-store.d.ts +37 -14
  37. package/dist/src/transport/reservation-store.d.ts.map +1 -1
  38. package/dist/src/transport/reservation-store.js +144 -74
  39. package/dist/src/transport/reservation-store.js.map +1 -1
  40. package/dist/src/transport/transport.d.ts +2 -13
  41. package/dist/src/transport/transport.d.ts.map +1 -1
  42. package/dist/src/transport/transport.js +30 -54
  43. package/dist/src/transport/transport.js.map +1 -1
  44. package/dist/src/utils.d.ts +10 -1
  45. package/dist/src/utils.d.ts.map +1 -1
  46. package/dist/src/utils.js +22 -8
  47. package/dist/src/utils.js.map +1 -1
  48. package/package.json +14 -12
  49. package/src/constants.ts +0 -7
  50. package/src/errors.ts +25 -0
  51. package/src/index.ts +19 -1
  52. package/src/pb/index.proto +20 -1
  53. package/src/pb/index.ts +99 -3
  54. package/src/server/index.ts +21 -11
  55. package/src/server/reservation-store.ts +38 -42
  56. package/src/server/reservation-voucher.ts +2 -2
  57. package/src/transport/discovery.ts +47 -9
  58. package/src/transport/index.ts +0 -7
  59. package/src/transport/listener.ts +75 -35
  60. package/src/transport/reservation-store.ts +209 -95
  61. package/src/transport/transport.ts +34 -76
  62. package/src/utils.ts +29 -8
  63. package/dist/typedoc-urls.json +0 -23
@@ -2,14 +2,14 @@ import { DialError, InvalidMessageError, serviceCapabilities, serviceDependencie
2
2
  import { peerFilter } from '@libp2p/peer-collections'
3
3
  import { peerIdFromMultihash, peerIdFromString } from '@libp2p/peer-id'
4
4
  import { streamToMaConnection } from '@libp2p/utils/stream-to-ma-conn'
5
- import * as mafmt from '@multiformats/mafmt'
6
5
  import { multiaddr } from '@multiformats/multiaddr'
6
+ import { Circuit } from '@multiformats/multiaddr-matcher'
7
7
  import { pbStream } from 'it-protobuf-stream'
8
8
  import * as Digest from 'multiformats/hashes/digest'
9
9
  import { CustomProgressEvent } from 'progress-events'
10
10
  import { CIRCUIT_PROTO_CODE, DEFAULT_DISCOVERY_FILTER_ERROR_RATE, DEFAULT_DISCOVERY_FILTER_SIZE, MAX_CONNECTIONS, RELAY_V2_HOP_CODEC, RELAY_V2_STOP_CODEC } from '../constants.js'
11
11
  import { StopMessage, HopMessage, Status } from '../pb/index.js'
12
- import { LimitTracker } from '../utils.js'
12
+ import { CircuitListen, CircuitSearch, LimitTracker } from '../utils.js'
13
13
  import { RelayDiscovery } from './discovery.js'
14
14
  import { createListener } from './listener.js'
15
15
  import { ReservationStore } from './reservation-store.js'
@@ -17,7 +17,7 @@ import type { CircuitRelayTransportComponents, CircuitRelayTransportInit } from
17
17
  import type { Transport, CreateListenerOptions, Listener, Upgrader, ComponentLogger, Logger, Connection, Stream, ConnectionGater, PeerId, PeerStore, OutboundConnectionUpgradeEvents, DialTransportOptions, OpenConnectionProgressEvents } from '@libp2p/interface'
18
18
  import type { AddressManager, ConnectionManager, IncomingStreamData, Registrar, TransportManager } from '@libp2p/interface-internal'
19
19
  import type { Multiaddr } from '@multiformats/multiaddr'
20
- import type { ProgressEvent, ProgressOptions } from 'progress-events'
20
+ import type { ProgressEvent } from 'progress-events'
21
21
 
22
22
  const isValidStop = (request: StopMessage): request is Required<StopMessage> => {
23
23
  if (request.peer == null) {
@@ -33,16 +33,6 @@ const isValidStop = (request: StopMessage): request is Required<StopMessage> =>
33
33
  return true
34
34
  }
35
35
 
36
- interface ConnectOptions extends ProgressOptions<CircuitRelayDialEvents> {
37
- stream: Stream
38
- connection: Connection
39
- destinationPeer: PeerId
40
- destinationAddr: Multiaddr
41
- relayAddr: Multiaddr
42
- ma: Multiaddr
43
- disconnectOnFailure: boolean
44
- }
45
-
46
36
  const defaults = {
47
37
  maxInboundStopStreams: MAX_CONNECTIONS,
48
38
  maxOutboundStopStreams: MAX_CONNECTIONS,
@@ -91,28 +81,23 @@ export class CircuitRelayTransport implements Transport<CircuitRelayDialEvents>
91
81
  this.maxOutboundStopStreams = init.maxOutboundStopStreams ?? defaults.maxOutboundStopStreams
92
82
  this.stopTimeout = init.stopTimeout ?? defaults.stopTimeout
93
83
 
94
- const discoverRelays = init.discoverRelays ?? 0
95
-
96
- if (discoverRelays > 0) {
97
- this.discovery = new RelayDiscovery(components, {
98
- filter: init.discoveryFilter ?? peerFilter(DEFAULT_DISCOVERY_FILTER_SIZE, DEFAULT_DISCOVERY_FILTER_ERROR_RATE)
99
- })
100
- this.discovery.addEventListener('relay:discover', (evt) => {
101
- this.reservationStore.addRelay(evt.detail, 'discovered')
102
- .catch(err => {
84
+ this.discovery = new RelayDiscovery(components, {
85
+ filter: init.discoveryFilter ?? peerFilter(DEFAULT_DISCOVERY_FILTER_SIZE, DEFAULT_DISCOVERY_FILTER_ERROR_RATE)
86
+ })
87
+ this.discovery.addEventListener('relay:discover', (evt) => {
88
+ this.reservationStore.addRelay(evt.detail, 'discovered')
89
+ .catch(err => {
90
+ if (err.name !== 'HadEnoughRelaysError' && err.name !== 'RelayQueueFullError') {
103
91
  this.log.error('could not add discovered relay %p', evt.detail, err)
104
- })
105
- })
106
- }
107
-
92
+ }
93
+ })
94
+ })
108
95
  this.reservationStore = new ReservationStore(components, init)
109
96
  this.reservationStore.addEventListener('relay:not-enough-relays', () => {
110
97
  this.discovery?.startDiscovery()
111
98
  })
112
- this.reservationStore.addEventListener('relay:created-reservation', () => {
113
- if (this.reservationStore.reservationCount() >= discoverRelays) {
114
- this.discovery?.stopDiscovery()
115
- }
99
+ this.reservationStore.addEventListener('relay:found-enough-relays', () => {
100
+ this.discovery?.stopDiscovery()
116
101
  })
117
102
 
118
103
  this.started = false
@@ -184,15 +169,14 @@ export class CircuitRelayTransport implements Transport<CircuitRelayDialEvents>
184
169
  const destinationId = destinationAddr.getPeerId()
185
170
 
186
171
  if (relayId == null || destinationId == null) {
187
- const errMsg = `Circuit relay dial to ${ma.toString()} failed as address did not have peer ids`
188
- this.log.error(errMsg)
189
- throw new DialError(errMsg)
172
+ const errMsg = `ircuit relay dial to ${ma.toString()} failed as address did not have both relay and destination PeerIDs`
173
+ this.log.error(`c${errMsg}`)
174
+ throw new DialError(`C${errMsg}`)
190
175
  }
191
176
 
192
177
  const relayPeer = peerIdFromString(relayId)
193
178
  const destinationPeer = peerIdFromString(destinationId)
194
179
 
195
- let disconnectOnFailure = false
196
180
  const relayConnections = this.connectionManager.getConnections(relayPeer)
197
181
  let relayConnection = relayConnections[0]
198
182
 
@@ -203,7 +187,6 @@ export class CircuitRelayTransport implements Transport<CircuitRelayDialEvents>
203
187
 
204
188
  options.onProgress?.(new CustomProgressEvent('circuit-relay:open-connection'))
205
189
  relayConnection = await this.connectionManager.openConnection(relayPeer, options)
206
- disconnectOnFailure = true
207
190
  } else {
208
191
  options.onProgress?.(new CustomProgressEvent('circuit-relay:reuse-connection'))
209
192
  }
@@ -212,52 +195,22 @@ export class CircuitRelayTransport implements Transport<CircuitRelayDialEvents>
212
195
 
213
196
  try {
214
197
  options.onProgress?.(new CustomProgressEvent('circuit-relay:open-hop-stream'))
215
- stream = await relayConnection.newStream(RELAY_V2_HOP_CODEC)
216
-
217
- return await this.connectV2({
218
- stream,
219
- connection: relayConnection,
220
- destinationPeer,
221
- destinationAddr,
222
- relayAddr,
223
- ma,
224
- disconnectOnFailure,
225
- onProgress: options.onProgress
226
- })
227
- } catch (err: any) {
228
- this.log.error('circuit relay dial to destination %p via relay %p failed', destinationPeer, relayPeer, err)
198
+ stream = await relayConnection.newStream(RELAY_V2_HOP_CODEC, options)
229
199
 
230
- if (stream != null) {
231
- stream.abort(err)
232
- }
233
- disconnectOnFailure && await relayConnection.close()
234
- throw err
235
- }
236
- }
237
-
238
- async connectV2 (
239
- {
240
- stream, connection, destinationPeer,
241
- destinationAddr, relayAddr, ma,
242
- disconnectOnFailure,
243
- onProgress
244
- }: ConnectOptions
245
- ): Promise<Connection> {
246
- try {
247
200
  const pbstr = pbStream(stream)
248
201
  const hopstr = pbstr.pb(HopMessage)
249
202
 
250
- onProgress?.(new CustomProgressEvent('circuit-relay:write-connect-message'))
203
+ options.onProgress?.(new CustomProgressEvent('circuit-relay:write-connect-message'))
251
204
  await hopstr.write({
252
205
  type: HopMessage.Type.CONNECT,
253
206
  peer: {
254
207
  id: destinationPeer.toMultihash().bytes,
255
208
  addrs: [multiaddr(destinationAddr).bytes]
256
209
  }
257
- })
210
+ }, options)
258
211
 
259
- onProgress?.(new CustomProgressEvent('circuit-relay:read-connect-response'))
260
- const status = await hopstr.read()
212
+ options.onProgress?.(new CustomProgressEvent('circuit-relay:read-connect-response'))
213
+ const status = await hopstr.read(options)
261
214
 
262
215
  if (status.status !== Status.OK) {
263
216
  throw new InvalidMessageError(`failed to connect via relay with status ${status?.status?.toString() ?? 'undefined'}`)
@@ -277,12 +230,13 @@ export class CircuitRelayTransport implements Transport<CircuitRelayDialEvents>
277
230
  this.log('new outbound relayed connection %a', maConn.remoteAddr)
278
231
 
279
232
  return await this.upgrader.upgradeOutbound(maConn, {
280
- limits: limits.getLimits(),
281
- onProgress
233
+ ...options,
234
+ limits: limits.getLimits()
282
235
  })
283
236
  } catch (err: any) {
284
- this.log.error(`Circuit relay dial to destination ${destinationPeer.toString()} via relay ${connection.remotePeer.toString()} failed`, err)
285
- disconnectOnFailure && await connection.close()
237
+ this.log.error('circuit relay dial to destination %p via relay %p failed', destinationPeer, relayPeer, err)
238
+ stream?.abort(err)
239
+
286
240
  throw err
287
241
  }
288
242
  }
@@ -305,7 +259,7 @@ export class CircuitRelayTransport implements Transport<CircuitRelayDialEvents>
305
259
  multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]
306
260
 
307
261
  return multiaddrs.filter((ma) => {
308
- return mafmt.Circuit.matches(ma)
262
+ return CircuitListen.exactMatch(ma) || CircuitSearch.exactMatch(ma)
309
263
  })
310
264
  }
311
265
 
@@ -313,7 +267,11 @@ export class CircuitRelayTransport implements Transport<CircuitRelayDialEvents>
313
267
  * Filter check for all Multiaddrs that this transport can dial
314
268
  */
315
269
  dialFilter (multiaddrs: Multiaddr[]): Multiaddr[] {
316
- return this.listenFilter(multiaddrs)
270
+ multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]
271
+
272
+ return multiaddrs.filter((ma) => {
273
+ return Circuit.exactMatch(ma)
274
+ })
317
275
  }
318
276
 
319
277
  /**
package/src/utils.ts CHANGED
@@ -1,7 +1,10 @@
1
+ import { P2P } from '@multiformats/multiaddr-matcher'
2
+ import { fmt, literal, and } from '@multiformats/multiaddr-matcher/utils'
1
3
  import { anySignal } from 'any-signal'
2
4
  import { CID } from 'multiformats/cid'
3
5
  import { sha256 } from 'multiformats/hashes/sha2'
4
6
  import { DurationLimitError, TransferLimitError } from './errors.js'
7
+ import type { RelayReservation } from './index.js'
5
8
  import type { Limit } from './pb/index.js'
6
9
  import type { ConnectionLimits, LoggerOptions, Stream } from '@libp2p/interface'
7
10
  import type { Source } from 'it-stream-types'
@@ -34,16 +37,18 @@ async function * countStreamBytes (source: Source<Uint8Array | Uint8ArrayList>,
34
37
  }
35
38
  }
36
39
 
37
- export function createLimitedRelay (src: Stream, dst: Stream, abortSignal: AbortSignal, limit: Limit | undefined, options: LoggerOptions): void {
40
+ export function createLimitedRelay (src: Stream, dst: Stream, abortSignal: AbortSignal, reservation: RelayReservation, options: LoggerOptions): void {
38
41
  function abortStreams (err: Error): void {
39
42
  src.abort(err)
40
43
  dst.abort(err)
41
44
  }
42
45
 
43
- const signals = [abortSignal]
46
+ // combine shutdown signal and reservation expiry signal
47
+ const signals = [abortSignal, reservation.signal]
44
48
 
45
- if (limit?.duration != null) {
46
- signals.push(AbortSignal.timeout(limit.duration))
49
+ if (reservation.limit?.duration != null) {
50
+ options.log('limiting relayed connection duration to %dms', reservation.limit.duration)
51
+ signals.push(AbortSignal.timeout(reservation.limit.duration))
47
52
  }
48
53
 
49
54
  const signal = anySignal(signals)
@@ -53,15 +58,16 @@ export function createLimitedRelay (src: Stream, dst: Stream, abortSignal: Abort
53
58
 
54
59
  let dataLimit: { remaining: bigint } | undefined
55
60
 
56
- if (limit?.data != null) {
61
+ if (reservation.limit?.data != null) {
57
62
  dataLimit = {
58
- remaining: limit.data
63
+ remaining: reservation.limit.data
59
64
  }
60
65
  }
61
66
 
62
67
  queueMicrotask(() => {
63
68
  const onAbort = (): void => {
64
- dst.abort(new DurationLimitError(`duration limit of ${limit?.duration} ms exceeded`))
69
+ options.log('relayed connection reached time limit')
70
+ dst.abort(new DurationLimitError(`duration limit of ${reservation.limit?.duration} ms exceeded`))
65
71
  }
66
72
 
67
73
  signal.addEventListener('abort', onAbort, { once: true })
@@ -83,7 +89,8 @@ export function createLimitedRelay (src: Stream, dst: Stream, abortSignal: Abort
83
89
 
84
90
  queueMicrotask(() => {
85
91
  const onAbort = (): void => {
86
- src.abort(new DurationLimitError(`duration limit of ${limit?.duration} ms exceeded`))
92
+ options.log('relayed connection reached time limit')
93
+ src.abort(new DurationLimitError(`duration limit of ${reservation.limit?.duration} ms exceeded`))
87
94
  }
88
95
 
89
96
  signal.addEventListener('abort', onAbort, { once: true })
@@ -185,3 +192,17 @@ export class LimitTracker {
185
192
  return output
186
193
  }
187
194
  }
195
+
196
+ /**
197
+ * A custom matcher that tells us to listen on a particular relay
198
+ */
199
+ export const CircuitListen = fmt(
200
+ and(P2P.matchers[0], literal('p2p-circuit'))
201
+ )
202
+
203
+ /**
204
+ * A custom matcher that tells us to discover available relays
205
+ */
206
+ export const CircuitSearch = fmt(
207
+ literal('p2p-circuit')
208
+ )
@@ -1,23 +0,0 @@
1
- {
2
- "codec": "https://libp2p.github.io/js-libp2p/functions/_libp2p_circuit_relay_v2.Limit.codec.html",
3
- "decode": "https://libp2p.github.io/js-libp2p/functions/_libp2p_circuit_relay_v2.Limit.decode.html",
4
- "encode": "https://libp2p.github.io/js-libp2p/functions/_libp2p_circuit_relay_v2.Limit.encode.html",
5
- "CircuitRelayServerComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.CircuitRelayServerComponents.html",
6
- "CircuitRelayServerInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.CircuitRelayServerInit.html",
7
- "CircuitRelayService": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.CircuitRelayService.html",
8
- ".:CircuitRelayService": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.CircuitRelayService.html",
9
- "CircuitRelayServiceEvents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.CircuitRelayServiceEvents.html",
10
- ".:CircuitRelayServiceEvents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.CircuitRelayServiceEvents.html",
11
- "CircuitRelayTransportComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.CircuitRelayTransportComponents.html",
12
- "CircuitRelayTransportInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.CircuitRelayTransportInit.html",
13
- "Limit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.Limit-1.html",
14
- "RelayDiscoveryComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.RelayDiscoveryComponents.html",
15
- "RelayReservation": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.RelayReservation.html",
16
- ".:RelayReservation": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.RelayReservation.html",
17
- "ServerReservationStoreInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.ServerReservationStoreInit.html",
18
- "TransportReservationStoreInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_circuit_relay_v2.TransportReservationStoreInit.html",
19
- "RELAY_V2_HOP_CODEC": "https://libp2p.github.io/js-libp2p/variables/_libp2p_circuit_relay_v2.RELAY_V2_HOP_CODEC.html",
20
- "RELAY_V2_STOP_CODEC": "https://libp2p.github.io/js-libp2p/variables/_libp2p_circuit_relay_v2.RELAY_V2_STOP_CODEC.html",
21
- "circuitRelayServer": "https://libp2p.github.io/js-libp2p/functions/_libp2p_circuit_relay_v2.circuitRelayServer.html",
22
- "circuitRelayTransport": "https://libp2p.github.io/js-libp2p/functions/_libp2p_circuit_relay_v2.circuitRelayTransport.html"
23
- }