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

Sign up to get free protection for your applications and to get access to all the features.
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