@libp2p/circuit-relay-v2 1.0.24 → 1.0.25-44791342

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 (47) hide show
  1. package/dist/index.min.js +5 -5
  2. package/dist/src/constants.d.ts +13 -12
  3. package/dist/src/constants.d.ts.map +1 -1
  4. package/dist/src/constants.js +13 -12
  5. package/dist/src/constants.js.map +1 -1
  6. package/dist/src/pb/index.d.ts +7 -7
  7. package/dist/src/pb/index.d.ts.map +1 -1
  8. package/dist/src/pb/index.js +94 -52
  9. package/dist/src/pb/index.js.map +1 -1
  10. package/dist/src/server/index.d.ts +1 -7
  11. package/dist/src/server/index.d.ts.map +1 -1
  12. package/dist/src/server/index.js +10 -19
  13. package/dist/src/server/index.js.map +1 -1
  14. package/dist/src/server/reservation-store.d.ts +2 -3
  15. package/dist/src/server/reservation-store.d.ts.map +1 -1
  16. package/dist/src/server/reservation-store.js.map +1 -1
  17. package/dist/src/transport/discovery.d.ts +15 -10
  18. package/dist/src/transport/discovery.d.ts.map +1 -1
  19. package/dist/src/transport/discovery.js +103 -51
  20. package/dist/src/transport/discovery.js.map +1 -1
  21. package/dist/src/transport/index.d.ts +27 -18
  22. package/dist/src/transport/index.d.ts.map +1 -1
  23. package/dist/src/transport/index.js +0 -3
  24. package/dist/src/transport/index.js.map +1 -1
  25. package/dist/src/transport/reservation-store.d.ts +7 -3
  26. package/dist/src/transport/reservation-store.d.ts.map +1 -1
  27. package/dist/src/transport/reservation-store.js +37 -13
  28. package/dist/src/transport/reservation-store.js.map +1 -1
  29. package/dist/src/transport/transport.d.ts +0 -1
  30. package/dist/src/transport/transport.d.ts.map +1 -1
  31. package/dist/src/transport/transport.js +20 -19
  32. package/dist/src/transport/transport.js.map +1 -1
  33. package/package.json +12 -13
  34. package/src/constants.ts +16 -15
  35. package/src/pb/index.ts +96 -53
  36. package/src/server/index.ts +11 -29
  37. package/src/server/reservation-store.ts +2 -4
  38. package/src/transport/discovery.ts +121 -56
  39. package/src/transport/index.ts +28 -18
  40. package/src/transport/reservation-store.ts +45 -13
  41. package/src/transport/transport.ts +21 -21
  42. package/dist/src/server/advert-service.d.ts +0 -44
  43. package/dist/src/server/advert-service.d.ts.map +0 -1
  44. package/dist/src/server/advert-service.js +0 -72
  45. package/dist/src/server/advert-service.js.map +0 -1
  46. package/dist/typedoc-urls.json +0 -12
  47. package/src/server/advert-service.ts +0 -107
package/src/pb/index.ts CHANGED
@@ -4,8 +4,8 @@
4
4
  /* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
5
5
  /* eslint-disable @typescript-eslint/no-empty-interface */
6
6
 
7
- import { enumeration, encodeMessage, decodeMessage, message } from 'protons-runtime'
8
- import type { Codec } from 'protons-runtime'
7
+ import { type Codec, CodeError, decodeMessage, type DecodeOptions, encodeMessage, enumeration, message } from 'protons-runtime'
8
+ import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc'
9
9
  import type { Uint8ArrayList } from 'uint8arraylist'
10
10
 
11
11
  export interface HopMessage {
@@ -72,7 +72,7 @@ export namespace HopMessage {
72
72
  if (opts.lengthDelimited !== false) {
73
73
  w.ldelim()
74
74
  }
75
- }, (reader, length) => {
75
+ }, (reader, length, opts = {}) => {
76
76
  const obj: any = {}
77
77
 
78
78
  const end = length == null ? reader.len : reader.pos + length
@@ -81,24 +81,36 @@ export namespace HopMessage {
81
81
  const tag = reader.uint32()
82
82
 
83
83
  switch (tag >>> 3) {
84
- case 1:
84
+ case 1: {
85
85
  obj.type = HopMessage.Type.codec().decode(reader)
86
86
  break
87
- case 2:
88
- obj.peer = Peer.codec().decode(reader, reader.uint32())
87
+ }
88
+ case 2: {
89
+ obj.peer = Peer.codec().decode(reader, reader.uint32(), {
90
+ limits: opts.limits?.peer
91
+ })
89
92
  break
90
- case 3:
91
- obj.reservation = Reservation.codec().decode(reader, reader.uint32())
93
+ }
94
+ case 3: {
95
+ obj.reservation = Reservation.codec().decode(reader, reader.uint32(), {
96
+ limits: opts.limits?.reservation
97
+ })
92
98
  break
93
- case 4:
94
- obj.limit = Limit.codec().decode(reader, reader.uint32())
99
+ }
100
+ case 4: {
101
+ obj.limit = Limit.codec().decode(reader, reader.uint32(), {
102
+ limits: opts.limits?.limit
103
+ })
95
104
  break
96
- case 5:
105
+ }
106
+ case 5: {
97
107
  obj.status = Status.codec().decode(reader)
98
108
  break
99
- default:
109
+ }
110
+ default: {
100
111
  reader.skipType(tag & 7)
101
112
  break
113
+ }
102
114
  }
103
115
  }
104
116
 
@@ -113,8 +125,8 @@ export namespace HopMessage {
113
125
  return encodeMessage(obj, HopMessage.codec())
114
126
  }
115
127
 
116
- export const decode = (buf: Uint8Array | Uint8ArrayList): HopMessage => {
117
- return decodeMessage(buf, HopMessage.codec())
128
+ export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<HopMessage>): HopMessage => {
129
+ return decodeMessage(buf, HopMessage.codec(), opts)
118
130
  }
119
131
  }
120
132
 
@@ -174,7 +186,7 @@ export namespace StopMessage {
174
186
  if (opts.lengthDelimited !== false) {
175
187
  w.ldelim()
176
188
  }
177
- }, (reader, length) => {
189
+ }, (reader, length, opts = {}) => {
178
190
  const obj: any = {}
179
191
 
180
192
  const end = length == null ? reader.len : reader.pos + length
@@ -183,21 +195,30 @@ export namespace StopMessage {
183
195
  const tag = reader.uint32()
184
196
 
185
197
  switch (tag >>> 3) {
186
- case 1:
198
+ case 1: {
187
199
  obj.type = StopMessage.Type.codec().decode(reader)
188
200
  break
189
- case 2:
190
- obj.peer = Peer.codec().decode(reader, reader.uint32())
201
+ }
202
+ case 2: {
203
+ obj.peer = Peer.codec().decode(reader, reader.uint32(), {
204
+ limits: opts.limits?.peer
205
+ })
191
206
  break
192
- case 3:
193
- obj.limit = Limit.codec().decode(reader, reader.uint32())
207
+ }
208
+ case 3: {
209
+ obj.limit = Limit.codec().decode(reader, reader.uint32(), {
210
+ limits: opts.limits?.limit
211
+ })
194
212
  break
195
- case 4:
213
+ }
214
+ case 4: {
196
215
  obj.status = Status.codec().decode(reader)
197
216
  break
198
- default:
217
+ }
218
+ default: {
199
219
  reader.skipType(tag & 7)
200
220
  break
221
+ }
201
222
  }
202
223
  }
203
224
 
@@ -212,8 +233,8 @@ export namespace StopMessage {
212
233
  return encodeMessage(obj, StopMessage.codec())
213
234
  }
214
235
 
215
- export const decode = (buf: Uint8Array | Uint8ArrayList): StopMessage => {
216
- return decodeMessage(buf, StopMessage.codec())
236
+ export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<StopMessage>): StopMessage => {
237
+ return decodeMessage(buf, StopMessage.codec(), opts)
217
238
  }
218
239
  }
219
240
 
@@ -247,9 +268,9 @@ export namespace Peer {
247
268
  if (opts.lengthDelimited !== false) {
248
269
  w.ldelim()
249
270
  }
250
- }, (reader, length) => {
271
+ }, (reader, length, opts = {}) => {
251
272
  const obj: any = {
252
- id: new Uint8Array(0),
273
+ id: uint8ArrayAlloc(0),
253
274
  addrs: []
254
275
  }
255
276
 
@@ -259,15 +280,22 @@ export namespace Peer {
259
280
  const tag = reader.uint32()
260
281
 
261
282
  switch (tag >>> 3) {
262
- case 1:
283
+ case 1: {
263
284
  obj.id = reader.bytes()
264
285
  break
265
- case 2:
286
+ }
287
+ case 2: {
288
+ if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) {
289
+ throw new CodeError('decode error - map field "addrs" had too many elements', 'ERR_MAX_LENGTH')
290
+ }
291
+
266
292
  obj.addrs.push(reader.bytes())
267
293
  break
268
- default:
294
+ }
295
+ default: {
269
296
  reader.skipType(tag & 7)
270
297
  break
298
+ }
271
299
  }
272
300
  }
273
301
 
@@ -282,8 +310,8 @@ export namespace Peer {
282
310
  return encodeMessage(obj, Peer.codec())
283
311
  }
284
312
 
285
- export const decode = (buf: Uint8Array | Uint8ArrayList): Peer => {
286
- return decodeMessage(buf, Peer.codec())
313
+ export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<Peer>): Peer => {
314
+ return decodeMessage(buf, Peer.codec(), opts)
287
315
  }
288
316
  }
289
317
 
@@ -323,7 +351,7 @@ export namespace Reservation {
323
351
  if (opts.lengthDelimited !== false) {
324
352
  w.ldelim()
325
353
  }
326
- }, (reader, length) => {
354
+ }, (reader, length, opts = {}) => {
327
355
  const obj: any = {
328
356
  expire: 0n,
329
357
  addrs: []
@@ -335,18 +363,26 @@ export namespace Reservation {
335
363
  const tag = reader.uint32()
336
364
 
337
365
  switch (tag >>> 3) {
338
- case 1:
366
+ case 1: {
339
367
  obj.expire = reader.uint64()
340
368
  break
341
- case 2:
369
+ }
370
+ case 2: {
371
+ if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) {
372
+ throw new CodeError('decode error - map field "addrs" had too many elements', 'ERR_MAX_LENGTH')
373
+ }
374
+
342
375
  obj.addrs.push(reader.bytes())
343
376
  break
344
- case 3:
377
+ }
378
+ case 3: {
345
379
  obj.voucher = reader.bytes()
346
380
  break
347
- default:
381
+ }
382
+ default: {
348
383
  reader.skipType(tag & 7)
349
384
  break
385
+ }
350
386
  }
351
387
  }
352
388
 
@@ -361,8 +397,8 @@ export namespace Reservation {
361
397
  return encodeMessage(obj, Reservation.codec())
362
398
  }
363
399
 
364
- export const decode = (buf: Uint8Array | Uint8ArrayList): Reservation => {
365
- return decodeMessage(buf, Reservation.codec())
400
+ export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<Reservation>): Reservation => {
401
+ return decodeMessage(buf, Reservation.codec(), opts)
366
402
  }
367
403
  }
368
404
 
@@ -394,7 +430,7 @@ export namespace Limit {
394
430
  if (opts.lengthDelimited !== false) {
395
431
  w.ldelim()
396
432
  }
397
- }, (reader, length) => {
433
+ }, (reader, length, opts = {}) => {
398
434
  const obj: any = {}
399
435
 
400
436
  const end = length == null ? reader.len : reader.pos + length
@@ -403,15 +439,18 @@ export namespace Limit {
403
439
  const tag = reader.uint32()
404
440
 
405
441
  switch (tag >>> 3) {
406
- case 1:
442
+ case 1: {
407
443
  obj.duration = reader.uint32()
408
444
  break
409
- case 2:
445
+ }
446
+ case 2: {
410
447
  obj.data = reader.uint64()
411
448
  break
412
- default:
449
+ }
450
+ default: {
413
451
  reader.skipType(tag & 7)
414
452
  break
453
+ }
415
454
  }
416
455
  }
417
456
 
@@ -426,8 +465,8 @@ export namespace Limit {
426
465
  return encodeMessage(obj, Limit.codec())
427
466
  }
428
467
 
429
- export const decode = (buf: Uint8Array | Uint8ArrayList): Limit => {
430
- return decodeMessage(buf, Limit.codec())
468
+ export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<Limit>): Limit => {
469
+ return decodeMessage(buf, Limit.codec(), opts)
431
470
  }
432
471
  }
433
472
 
@@ -494,10 +533,10 @@ export namespace ReservationVoucher {
494
533
  if (opts.lengthDelimited !== false) {
495
534
  w.ldelim()
496
535
  }
497
- }, (reader, length) => {
536
+ }, (reader, length, opts = {}) => {
498
537
  const obj: any = {
499
- relay: new Uint8Array(0),
500
- peer: new Uint8Array(0),
538
+ relay: uint8ArrayAlloc(0),
539
+ peer: uint8ArrayAlloc(0),
501
540
  expiration: 0n
502
541
  }
503
542
 
@@ -507,18 +546,22 @@ export namespace ReservationVoucher {
507
546
  const tag = reader.uint32()
508
547
 
509
548
  switch (tag >>> 3) {
510
- case 1:
549
+ case 1: {
511
550
  obj.relay = reader.bytes()
512
551
  break
513
- case 2:
552
+ }
553
+ case 2: {
514
554
  obj.peer = reader.bytes()
515
555
  break
516
- case 3:
556
+ }
557
+ case 3: {
517
558
  obj.expiration = reader.uint64()
518
559
  break
519
- default:
560
+ }
561
+ default: {
520
562
  reader.skipType(tag & 7)
521
563
  break
564
+ }
522
565
  }
523
566
  }
524
567
 
@@ -533,7 +576,7 @@ export namespace ReservationVoucher {
533
576
  return encodeMessage(obj, ReservationVoucher.codec())
534
577
  }
535
578
 
536
- export const decode = (buf: Uint8Array | Uint8ArrayList): ReservationVoucher => {
537
- return decodeMessage(buf, ReservationVoucher.codec())
579
+ export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<ReservationVoucher>): ReservationVoucher => {
580
+ return decodeMessage(buf, ReservationVoucher.codec(), opts)
538
581
  }
539
582
  }
@@ -14,7 +14,6 @@ import {
14
14
  } from '../constants.js'
15
15
  import { HopMessage, type Reservation, Status, StopMessage } from '../pb/index.js'
16
16
  import { createLimitedRelay } from '../utils.js'
17
- import { AdvertService, type AdvertServiceComponents, type AdvertServiceInit } from './advert-service.js'
18
17
  import { ReservationStore, type ReservationStoreInit } from './reservation-store.js'
19
18
  import { ReservationVoucherRecord } from './reservation-voucher.js'
20
19
  import type { CircuitRelayService, RelayReservation } from '../index.js'
@@ -31,12 +30,6 @@ export interface CircuitRelayServerInit {
31
30
  */
32
31
  hopTimeout?: number
33
32
 
34
- /**
35
- * If true, advertise this service via libp2p content routing to allow
36
- * peers to locate us on the network (default: false)
37
- */
38
- advertise?: boolean | AdvertServiceInit
39
-
40
33
  /**
41
34
  * Configuration of reservations
42
35
  */
@@ -70,7 +63,7 @@ export interface StopOptions {
70
63
  request: StopMessage
71
64
  }
72
65
 
73
- export interface CircuitRelayServerComponents extends AdvertServiceComponents {
66
+ export interface CircuitRelayServerComponents {
74
67
  registrar: Registrar
75
68
  peerStore: PeerStore
76
69
  addressManager: AddressManager
@@ -98,7 +91,6 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
98
91
  private readonly connectionManager: ConnectionManager
99
92
  private readonly connectionGater: ConnectionGater
100
93
  private readonly reservationStore: ReservationStore
101
- private readonly advertService: AdvertService | undefined
102
94
  private started: boolean
103
95
  private readonly hopTimeout: number
104
96
  private readonly shutdownController: AbortController
@@ -122,24 +114,13 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
122
114
  this.connectionGater = components.connectionGater
123
115
  this.started = false
124
116
  this.hopTimeout = init?.hopTimeout ?? DEFAULT_HOP_TIMEOUT
125
- this.shutdownController = new AbortController()
126
117
  this.maxInboundHopStreams = init.maxInboundHopStreams
127
118
  this.maxOutboundHopStreams = init.maxOutboundHopStreams
128
119
  this.maxOutboundStopStreams = init.maxOutboundStopStreams ?? defaults.maxOutboundStopStreams
120
+ this.reservationStore = new ReservationStore(init.reservations)
129
121
 
122
+ this.shutdownController = new AbortController()
130
123
  setMaxListeners(Infinity, this.shutdownController.signal)
131
-
132
- if (init.advertise != null && init.advertise !== false) {
133
- this.advertService = new AdvertService(components, init.advertise === true ? undefined : init.advertise)
134
- this.advertService.addEventListener('advert:success', () => {
135
- this.safeDispatchEvent('relay:advert:success', {})
136
- })
137
- this.advertService.addEventListener('advert:error', (evt) => {
138
- this.safeDispatchEvent('relay:advert:error', { detail: evt.detail })
139
- })
140
- }
141
-
142
- this.reservationStore = new ReservationStore(init.reservations)
143
124
  }
144
125
 
145
126
  isStarted (): boolean {
@@ -154,9 +135,6 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
154
135
  return
155
136
  }
156
137
 
157
- // Advertise service if HOP enabled and advertising enabled
158
- this.advertService?.start()
159
-
160
138
  await this.registrar.handle(RELAY_V2_HOP_CODEC, (data) => {
161
139
  void this.onHop(data).catch(err => {
162
140
  this.log.error(err)
@@ -176,7 +154,6 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
176
154
  * Stop Relay service
177
155
  */
178
156
  async stop (): Promise<void> {
179
- this.advertService?.stop()
180
157
  this.reservationStore.stop()
181
158
  this.shutdownController.abort()
182
159
  await this.registrar.unhandle(RELAY_V2_HOP_CODEC)
@@ -359,6 +336,7 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
359
336
  return
360
337
  }
361
338
 
339
+ const limit = this.reservationStore.get(dstPeer)?.limit
362
340
  const destinationConnection = connections[0]
363
341
 
364
342
  const destinationStream = await this.stopHop({
@@ -368,7 +346,8 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
368
346
  peer: {
369
347
  id: connection.remotePeer.toBytes(),
370
348
  addrs: []
371
- }
349
+ },
350
+ limit
372
351
  }
373
352
  })
374
353
 
@@ -378,11 +357,14 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
378
357
  return
379
358
  }
380
359
 
381
- await hopstr.write({ type: HopMessage.Type.STATUS, status: Status.OK })
360
+ await hopstr.write({
361
+ type: HopMessage.Type.STATUS,
362
+ status: Status.OK,
363
+ limit
364
+ })
382
365
  const sourceStream = stream.unwrap()
383
366
 
384
367
  this.log('connection from %p to %p established - merging streams', connection.remotePeer, dstPeer)
385
- const limit = this.reservationStore.get(dstPeer)?.limit
386
368
  // Short circuit the two streams to create the relayed connection
387
369
  createLimitedRelay(sourceStream, destinationStream, this.shutdownController.signal, limit, {
388
370
  log: this.log
@@ -2,7 +2,7 @@ import { PeerMap } from '@libp2p/peer-collections'
2
2
  import { DEFAULT_DATA_LIMIT, DEFAULT_DURATION_LIMIT, DEFAULT_MAX_RESERVATION_CLEAR_INTERVAL, DEFAULT_MAX_RESERVATION_STORE_SIZE, DEFAULT_MAX_RESERVATION_TTL } from '../constants.js'
3
3
  import { type Limit, Status } from '../pb/index.js'
4
4
  import type { RelayReservation } from '../index.js'
5
- import type { RecursivePartial, PeerId, Startable } from '@libp2p/interface'
5
+ import type { PeerId, Startable } from '@libp2p/interface'
6
6
  import type { Multiaddr } from '@multiformats/multiaddr'
7
7
 
8
8
  export type ReservationStatus = Status.OK | Status.PERMISSION_DENIED | Status.RESERVATION_REFUSED
@@ -34,8 +34,6 @@ export interface ReservationStoreInit {
34
34
  defaultDataLimit?: bigint
35
35
  }
36
36
 
37
- export type ReservationStoreOptions = RecursivePartial<ReservationStoreInit>
38
-
39
37
  export class ReservationStore implements Startable {
40
38
  public readonly reservations = new PeerMap<RelayReservation>()
41
39
  private _started = false
@@ -47,7 +45,7 @@ export class ReservationStore implements Startable {
47
45
  private readonly defaultDurationLimit: number
48
46
  private readonly defaultDataLimit: bigint
49
47
 
50
- constructor (options: ReservationStoreOptions = {}) {
48
+ constructor (options: ReservationStoreInit = {}) {
51
49
  this.maxReservations = options.maxReservations ?? DEFAULT_MAX_RESERVATION_STORE_SIZE
52
50
  this.reservationClearInterval = options.reservationClearInterval ?? DEFAULT_MAX_RESERVATION_CLEAR_INTERVAL
53
51
  this.applyDefaultLimit = options.applyDefaultLimit !== false