@libp2p/circuit-relay-v2 0.0.0-05b52d69c

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 (65) hide show
  1. package/LICENSE +4 -0
  2. package/README.md +69 -0
  3. package/dist/index.min.js +45 -0
  4. package/dist/src/constants.d.ts +55 -0
  5. package/dist/src/constants.d.ts.map +1 -0
  6. package/dist/src/constants.js +61 -0
  7. package/dist/src/constants.js.map +1 -0
  8. package/dist/src/index.d.ts +56 -0
  9. package/dist/src/index.d.ts.map +1 -0
  10. package/dist/src/index.js +39 -0
  11. package/dist/src/index.js.map +1 -0
  12. package/dist/src/pb/index.d.ts +93 -0
  13. package/dist/src/pb/index.d.ts.map +1 -0
  14. package/dist/src/pb/index.js +425 -0
  15. package/dist/src/pb/index.js.map +1 -0
  16. package/dist/src/server/advert-service.d.ts +46 -0
  17. package/dist/src/server/advert-service.d.ts.map +1 -0
  18. package/dist/src/server/advert-service.js +72 -0
  19. package/dist/src/server/advert-service.js.map +1 -0
  20. package/dist/src/server/index.d.ts +67 -0
  21. package/dist/src/server/index.d.ts.map +1 -0
  22. package/dist/src/server/index.js +313 -0
  23. package/dist/src/server/index.js.map +1 -0
  24. package/dist/src/server/reservation-store.d.ts +49 -0
  25. package/dist/src/server/reservation-store.d.ts.map +1 -0
  26. package/dist/src/server/reservation-store.js +65 -0
  27. package/dist/src/server/reservation-store.js.map +1 -0
  28. package/dist/src/server/reservation-voucher.d.ts +18 -0
  29. package/dist/src/server/reservation-voucher.d.ts.map +1 -0
  30. package/dist/src/server/reservation-voucher.js +36 -0
  31. package/dist/src/server/reservation-voucher.js.map +1 -0
  32. package/dist/src/transport/discovery.d.ts +48 -0
  33. package/dist/src/transport/discovery.d.ts.map +1 -0
  34. package/dist/src/transport/discovery.js +97 -0
  35. package/dist/src/transport/discovery.js.map +1 -0
  36. package/dist/src/transport/index.d.ts +58 -0
  37. package/dist/src/transport/index.d.ts.map +1 -0
  38. package/dist/src/transport/index.js +279 -0
  39. package/dist/src/transport/index.js.map +1 -0
  40. package/dist/src/transport/listener.d.ts +11 -0
  41. package/dist/src/transport/listener.d.ts.map +1 -0
  42. package/dist/src/transport/listener.js +66 -0
  43. package/dist/src/transport/listener.js.map +1 -0
  44. package/dist/src/transport/reservation-store.d.ts +74 -0
  45. package/dist/src/transport/reservation-store.d.ts.map +1 -0
  46. package/dist/src/transport/reservation-store.js +209 -0
  47. package/dist/src/transport/reservation-store.js.map +1 -0
  48. package/dist/src/utils.d.ts +14 -0
  49. package/dist/src/utils.d.ts.map +1 -0
  50. package/dist/src/utils.js +106 -0
  51. package/dist/src/utils.js.map +1 -0
  52. package/package.json +83 -0
  53. package/src/constants.ts +79 -0
  54. package/src/index.ts +64 -0
  55. package/src/pb/index.proto +67 -0
  56. package/src/pb/index.ts +539 -0
  57. package/src/server/advert-service.ts +109 -0
  58. package/src/server/index.ts +446 -0
  59. package/src/server/reservation-store.ts +116 -0
  60. package/src/server/reservation-voucher.ts +51 -0
  61. package/src/transport/discovery.ts +138 -0
  62. package/src/transport/index.ts +399 -0
  63. package/src/transport/listener.ts +98 -0
  64. package/src/transport/reservation-store.ts +312 -0
  65. package/src/utils.ts +134 -0
@@ -0,0 +1,539 @@
1
+ /* eslint-disable import/export */
2
+ /* eslint-disable complexity */
3
+ /* eslint-disable @typescript-eslint/no-namespace */
4
+ /* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
5
+ /* eslint-disable @typescript-eslint/no-empty-interface */
6
+
7
+ import { enumeration, encodeMessage, decodeMessage, message } from 'protons-runtime'
8
+ import type { Codec } from 'protons-runtime'
9
+ import type { Uint8ArrayList } from 'uint8arraylist'
10
+
11
+ export interface HopMessage {
12
+ type?: HopMessage.Type
13
+ peer?: Peer
14
+ reservation?: Reservation
15
+ limit?: Limit
16
+ status?: Status
17
+ }
18
+
19
+ export namespace HopMessage {
20
+ export enum Type {
21
+ RESERVE = 'RESERVE',
22
+ CONNECT = 'CONNECT',
23
+ STATUS = 'STATUS'
24
+ }
25
+
26
+ enum __TypeValues {
27
+ RESERVE = 0,
28
+ CONNECT = 1,
29
+ STATUS = 2
30
+ }
31
+
32
+ export namespace Type {
33
+ export const codec = (): Codec<Type> => {
34
+ return enumeration<Type>(__TypeValues)
35
+ }
36
+ }
37
+
38
+ let _codec: Codec<HopMessage>
39
+
40
+ export const codec = (): Codec<HopMessage> => {
41
+ if (_codec == null) {
42
+ _codec = message<HopMessage>((obj, w, opts = {}) => {
43
+ if (opts.lengthDelimited !== false) {
44
+ w.fork()
45
+ }
46
+
47
+ if (obj.type != null) {
48
+ w.uint32(8)
49
+ HopMessage.Type.codec().encode(obj.type, w)
50
+ }
51
+
52
+ if (obj.peer != null) {
53
+ w.uint32(18)
54
+ Peer.codec().encode(obj.peer, w)
55
+ }
56
+
57
+ if (obj.reservation != null) {
58
+ w.uint32(26)
59
+ Reservation.codec().encode(obj.reservation, w)
60
+ }
61
+
62
+ if (obj.limit != null) {
63
+ w.uint32(34)
64
+ Limit.codec().encode(obj.limit, w)
65
+ }
66
+
67
+ if (obj.status != null) {
68
+ w.uint32(40)
69
+ Status.codec().encode(obj.status, w)
70
+ }
71
+
72
+ if (opts.lengthDelimited !== false) {
73
+ w.ldelim()
74
+ }
75
+ }, (reader, length) => {
76
+ const obj: any = {}
77
+
78
+ const end = length == null ? reader.len : reader.pos + length
79
+
80
+ while (reader.pos < end) {
81
+ const tag = reader.uint32()
82
+
83
+ switch (tag >>> 3) {
84
+ case 1:
85
+ obj.type = HopMessage.Type.codec().decode(reader)
86
+ break
87
+ case 2:
88
+ obj.peer = Peer.codec().decode(reader, reader.uint32())
89
+ break
90
+ case 3:
91
+ obj.reservation = Reservation.codec().decode(reader, reader.uint32())
92
+ break
93
+ case 4:
94
+ obj.limit = Limit.codec().decode(reader, reader.uint32())
95
+ break
96
+ case 5:
97
+ obj.status = Status.codec().decode(reader)
98
+ break
99
+ default:
100
+ reader.skipType(tag & 7)
101
+ break
102
+ }
103
+ }
104
+
105
+ return obj
106
+ })
107
+ }
108
+
109
+ return _codec
110
+ }
111
+
112
+ export const encode = (obj: Partial<HopMessage>): Uint8Array => {
113
+ return encodeMessage(obj, HopMessage.codec())
114
+ }
115
+
116
+ export const decode = (buf: Uint8Array | Uint8ArrayList): HopMessage => {
117
+ return decodeMessage(buf, HopMessage.codec())
118
+ }
119
+ }
120
+
121
+ export interface StopMessage {
122
+ type?: StopMessage.Type
123
+ peer?: Peer
124
+ limit?: Limit
125
+ status?: Status
126
+ }
127
+
128
+ export namespace StopMessage {
129
+ export enum Type {
130
+ CONNECT = 'CONNECT',
131
+ STATUS = 'STATUS'
132
+ }
133
+
134
+ enum __TypeValues {
135
+ CONNECT = 0,
136
+ STATUS = 1
137
+ }
138
+
139
+ export namespace Type {
140
+ export const codec = (): Codec<Type> => {
141
+ return enumeration<Type>(__TypeValues)
142
+ }
143
+ }
144
+
145
+ let _codec: Codec<StopMessage>
146
+
147
+ export const codec = (): Codec<StopMessage> => {
148
+ if (_codec == null) {
149
+ _codec = message<StopMessage>((obj, w, opts = {}) => {
150
+ if (opts.lengthDelimited !== false) {
151
+ w.fork()
152
+ }
153
+
154
+ if (obj.type != null) {
155
+ w.uint32(8)
156
+ StopMessage.Type.codec().encode(obj.type, w)
157
+ }
158
+
159
+ if (obj.peer != null) {
160
+ w.uint32(18)
161
+ Peer.codec().encode(obj.peer, w)
162
+ }
163
+
164
+ if (obj.limit != null) {
165
+ w.uint32(26)
166
+ Limit.codec().encode(obj.limit, w)
167
+ }
168
+
169
+ if (obj.status != null) {
170
+ w.uint32(32)
171
+ Status.codec().encode(obj.status, w)
172
+ }
173
+
174
+ if (opts.lengthDelimited !== false) {
175
+ w.ldelim()
176
+ }
177
+ }, (reader, length) => {
178
+ const obj: any = {}
179
+
180
+ const end = length == null ? reader.len : reader.pos + length
181
+
182
+ while (reader.pos < end) {
183
+ const tag = reader.uint32()
184
+
185
+ switch (tag >>> 3) {
186
+ case 1:
187
+ obj.type = StopMessage.Type.codec().decode(reader)
188
+ break
189
+ case 2:
190
+ obj.peer = Peer.codec().decode(reader, reader.uint32())
191
+ break
192
+ case 3:
193
+ obj.limit = Limit.codec().decode(reader, reader.uint32())
194
+ break
195
+ case 4:
196
+ obj.status = Status.codec().decode(reader)
197
+ break
198
+ default:
199
+ reader.skipType(tag & 7)
200
+ break
201
+ }
202
+ }
203
+
204
+ return obj
205
+ })
206
+ }
207
+
208
+ return _codec
209
+ }
210
+
211
+ export const encode = (obj: Partial<StopMessage>): Uint8Array => {
212
+ return encodeMessage(obj, StopMessage.codec())
213
+ }
214
+
215
+ export const decode = (buf: Uint8Array | Uint8ArrayList): StopMessage => {
216
+ return decodeMessage(buf, StopMessage.codec())
217
+ }
218
+ }
219
+
220
+ export interface Peer {
221
+ id: Uint8Array
222
+ addrs: Uint8Array[]
223
+ }
224
+
225
+ export namespace Peer {
226
+ let _codec: Codec<Peer>
227
+
228
+ export const codec = (): Codec<Peer> => {
229
+ if (_codec == null) {
230
+ _codec = message<Peer>((obj, w, opts = {}) => {
231
+ if (opts.lengthDelimited !== false) {
232
+ w.fork()
233
+ }
234
+
235
+ if ((obj.id != null && obj.id.byteLength > 0)) {
236
+ w.uint32(10)
237
+ w.bytes(obj.id)
238
+ }
239
+
240
+ if (obj.addrs != null) {
241
+ for (const value of obj.addrs) {
242
+ w.uint32(18)
243
+ w.bytes(value)
244
+ }
245
+ }
246
+
247
+ if (opts.lengthDelimited !== false) {
248
+ w.ldelim()
249
+ }
250
+ }, (reader, length) => {
251
+ const obj: any = {
252
+ id: new Uint8Array(0),
253
+ addrs: []
254
+ }
255
+
256
+ const end = length == null ? reader.len : reader.pos + length
257
+
258
+ while (reader.pos < end) {
259
+ const tag = reader.uint32()
260
+
261
+ switch (tag >>> 3) {
262
+ case 1:
263
+ obj.id = reader.bytes()
264
+ break
265
+ case 2:
266
+ obj.addrs.push(reader.bytes())
267
+ break
268
+ default:
269
+ reader.skipType(tag & 7)
270
+ break
271
+ }
272
+ }
273
+
274
+ return obj
275
+ })
276
+ }
277
+
278
+ return _codec
279
+ }
280
+
281
+ export const encode = (obj: Partial<Peer>): Uint8Array => {
282
+ return encodeMessage(obj, Peer.codec())
283
+ }
284
+
285
+ export const decode = (buf: Uint8Array | Uint8ArrayList): Peer => {
286
+ return decodeMessage(buf, Peer.codec())
287
+ }
288
+ }
289
+
290
+ export interface Reservation {
291
+ expire: bigint
292
+ addrs: Uint8Array[]
293
+ voucher?: Uint8Array
294
+ }
295
+
296
+ export namespace Reservation {
297
+ let _codec: Codec<Reservation>
298
+
299
+ export const codec = (): Codec<Reservation> => {
300
+ if (_codec == null) {
301
+ _codec = message<Reservation>((obj, w, opts = {}) => {
302
+ if (opts.lengthDelimited !== false) {
303
+ w.fork()
304
+ }
305
+
306
+ if ((obj.expire != null && obj.expire !== 0n)) {
307
+ w.uint32(8)
308
+ w.uint64(obj.expire)
309
+ }
310
+
311
+ if (obj.addrs != null) {
312
+ for (const value of obj.addrs) {
313
+ w.uint32(18)
314
+ w.bytes(value)
315
+ }
316
+ }
317
+
318
+ if (obj.voucher != null) {
319
+ w.uint32(26)
320
+ w.bytes(obj.voucher)
321
+ }
322
+
323
+ if (opts.lengthDelimited !== false) {
324
+ w.ldelim()
325
+ }
326
+ }, (reader, length) => {
327
+ const obj: any = {
328
+ expire: 0n,
329
+ addrs: []
330
+ }
331
+
332
+ const end = length == null ? reader.len : reader.pos + length
333
+
334
+ while (reader.pos < end) {
335
+ const tag = reader.uint32()
336
+
337
+ switch (tag >>> 3) {
338
+ case 1:
339
+ obj.expire = reader.uint64()
340
+ break
341
+ case 2:
342
+ obj.addrs.push(reader.bytes())
343
+ break
344
+ case 3:
345
+ obj.voucher = reader.bytes()
346
+ break
347
+ default:
348
+ reader.skipType(tag & 7)
349
+ break
350
+ }
351
+ }
352
+
353
+ return obj
354
+ })
355
+ }
356
+
357
+ return _codec
358
+ }
359
+
360
+ export const encode = (obj: Partial<Reservation>): Uint8Array => {
361
+ return encodeMessage(obj, Reservation.codec())
362
+ }
363
+
364
+ export const decode = (buf: Uint8Array | Uint8ArrayList): Reservation => {
365
+ return decodeMessage(buf, Reservation.codec())
366
+ }
367
+ }
368
+
369
+ export interface Limit {
370
+ duration?: number
371
+ data?: bigint
372
+ }
373
+
374
+ export namespace Limit {
375
+ let _codec: Codec<Limit>
376
+
377
+ export const codec = (): Codec<Limit> => {
378
+ if (_codec == null) {
379
+ _codec = message<Limit>((obj, w, opts = {}) => {
380
+ if (opts.lengthDelimited !== false) {
381
+ w.fork()
382
+ }
383
+
384
+ if (obj.duration != null) {
385
+ w.uint32(8)
386
+ w.uint32(obj.duration)
387
+ }
388
+
389
+ if (obj.data != null) {
390
+ w.uint32(16)
391
+ w.uint64(obj.data)
392
+ }
393
+
394
+ if (opts.lengthDelimited !== false) {
395
+ w.ldelim()
396
+ }
397
+ }, (reader, length) => {
398
+ const obj: any = {}
399
+
400
+ const end = length == null ? reader.len : reader.pos + length
401
+
402
+ while (reader.pos < end) {
403
+ const tag = reader.uint32()
404
+
405
+ switch (tag >>> 3) {
406
+ case 1:
407
+ obj.duration = reader.uint32()
408
+ break
409
+ case 2:
410
+ obj.data = reader.uint64()
411
+ break
412
+ default:
413
+ reader.skipType(tag & 7)
414
+ break
415
+ }
416
+ }
417
+
418
+ return obj
419
+ })
420
+ }
421
+
422
+ return _codec
423
+ }
424
+
425
+ export const encode = (obj: Partial<Limit>): Uint8Array => {
426
+ return encodeMessage(obj, Limit.codec())
427
+ }
428
+
429
+ export const decode = (buf: Uint8Array | Uint8ArrayList): Limit => {
430
+ return decodeMessage(buf, Limit.codec())
431
+ }
432
+ }
433
+
434
+ export enum Status {
435
+ UNUSED = 'UNUSED',
436
+ OK = 'OK',
437
+ RESERVATION_REFUSED = 'RESERVATION_REFUSED',
438
+ RESOURCE_LIMIT_EXCEEDED = 'RESOURCE_LIMIT_EXCEEDED',
439
+ PERMISSION_DENIED = 'PERMISSION_DENIED',
440
+ CONNECTION_FAILED = 'CONNECTION_FAILED',
441
+ NO_RESERVATION = 'NO_RESERVATION',
442
+ MALFORMED_MESSAGE = 'MALFORMED_MESSAGE',
443
+ UNEXPECTED_MESSAGE = 'UNEXPECTED_MESSAGE'
444
+ }
445
+
446
+ enum __StatusValues {
447
+ UNUSED = 0,
448
+ OK = 100,
449
+ RESERVATION_REFUSED = 200,
450
+ RESOURCE_LIMIT_EXCEEDED = 201,
451
+ PERMISSION_DENIED = 202,
452
+ CONNECTION_FAILED = 203,
453
+ NO_RESERVATION = 204,
454
+ MALFORMED_MESSAGE = 400,
455
+ UNEXPECTED_MESSAGE = 401
456
+ }
457
+
458
+ export namespace Status {
459
+ export const codec = (): Codec<Status> => {
460
+ return enumeration<Status>(__StatusValues)
461
+ }
462
+ }
463
+ export interface ReservationVoucher {
464
+ relay: Uint8Array
465
+ peer: Uint8Array
466
+ expiration: bigint
467
+ }
468
+
469
+ export namespace ReservationVoucher {
470
+ let _codec: Codec<ReservationVoucher>
471
+
472
+ export const codec = (): Codec<ReservationVoucher> => {
473
+ if (_codec == null) {
474
+ _codec = message<ReservationVoucher>((obj, w, opts = {}) => {
475
+ if (opts.lengthDelimited !== false) {
476
+ w.fork()
477
+ }
478
+
479
+ if ((obj.relay != null && obj.relay.byteLength > 0)) {
480
+ w.uint32(10)
481
+ w.bytes(obj.relay)
482
+ }
483
+
484
+ if ((obj.peer != null && obj.peer.byteLength > 0)) {
485
+ w.uint32(18)
486
+ w.bytes(obj.peer)
487
+ }
488
+
489
+ if ((obj.expiration != null && obj.expiration !== 0n)) {
490
+ w.uint32(24)
491
+ w.uint64(obj.expiration)
492
+ }
493
+
494
+ if (opts.lengthDelimited !== false) {
495
+ w.ldelim()
496
+ }
497
+ }, (reader, length) => {
498
+ const obj: any = {
499
+ relay: new Uint8Array(0),
500
+ peer: new Uint8Array(0),
501
+ expiration: 0n
502
+ }
503
+
504
+ const end = length == null ? reader.len : reader.pos + length
505
+
506
+ while (reader.pos < end) {
507
+ const tag = reader.uint32()
508
+
509
+ switch (tag >>> 3) {
510
+ case 1:
511
+ obj.relay = reader.bytes()
512
+ break
513
+ case 2:
514
+ obj.peer = reader.bytes()
515
+ break
516
+ case 3:
517
+ obj.expiration = reader.uint64()
518
+ break
519
+ default:
520
+ reader.skipType(tag & 7)
521
+ break
522
+ }
523
+ }
524
+
525
+ return obj
526
+ })
527
+ }
528
+
529
+ return _codec
530
+ }
531
+
532
+ export const encode = (obj: Partial<ReservationVoucher>): Uint8Array => {
533
+ return encodeMessage(obj, ReservationVoucher.codec())
534
+ }
535
+
536
+ export const decode = (buf: Uint8Array | Uint8ArrayList): ReservationVoucher => {
537
+ return decodeMessage(buf, ReservationVoucher.codec())
538
+ }
539
+ }
@@ -0,0 +1,109 @@
1
+ import { TypedEventEmitter } from '@libp2p/interface/events'
2
+ import pRetry from 'p-retry'
3
+ import {
4
+ DEFAULT_ADVERT_BOOT_DELAY,
5
+ ERR_NO_ROUTERS_AVAILABLE,
6
+ RELAY_RENDEZVOUS_NS
7
+ } from '../constants.js'
8
+ import { namespaceToCid } from '../utils.js'
9
+ import type { ComponentLogger, Logger } from '@libp2p/interface'
10
+ import type { ContentRouting } from '@libp2p/interface/content-routing'
11
+ import type { Startable } from '@libp2p/interface/startable'
12
+
13
+ export interface AdvertServiceInit {
14
+ /**
15
+ * How long to wait after startup to begin advertising the service
16
+ * - if some configured content routers take a while to warm up (for
17
+ * example, the DHT needs some peers to be able to publish) this
18
+ * value should be high enough that they will have warmed up
19
+ */
20
+ bootDelay?: number
21
+ }
22
+
23
+ export interface AdvertServiceComponents {
24
+ contentRouting: ContentRouting
25
+ logger: ComponentLogger
26
+ }
27
+
28
+ export interface AdvertServiceEvents {
29
+ 'advert:success': CustomEvent<unknown>
30
+ 'advert:error': CustomEvent<Error>
31
+ }
32
+
33
+ export class AdvertService extends TypedEventEmitter<AdvertServiceEvents> implements Startable {
34
+ private readonly contentRouting: ContentRouting
35
+ private timeout?: any
36
+ private started: boolean
37
+ private readonly bootDelay: number
38
+ private readonly log: Logger
39
+
40
+ /**
41
+ * Creates an instance of Relay
42
+ */
43
+ constructor (components: AdvertServiceComponents, init?: AdvertServiceInit) {
44
+ super()
45
+
46
+ this.log = components.logger.forComponent('libp2p:circuit-relay:advert-service')
47
+ this.contentRouting = components.contentRouting
48
+ this.bootDelay = init?.bootDelay ?? DEFAULT_ADVERT_BOOT_DELAY
49
+ this.started = false
50
+ }
51
+
52
+ isStarted (): boolean {
53
+ return this.started
54
+ }
55
+
56
+ /**
57
+ * Start Relay service
58
+ */
59
+ start (): void {
60
+ if (this.started) {
61
+ return
62
+ }
63
+
64
+ // Advertise service if HOP enabled and advertising enabled
65
+ this.timeout = setTimeout(() => {
66
+ this._advertiseService().catch(err => {
67
+ this.log.error('could not advertise service', err)
68
+ })
69
+ }, this.bootDelay)
70
+
71
+ this.started = true
72
+ }
73
+
74
+ /**
75
+ * Stop Relay service
76
+ */
77
+ stop (): void {
78
+ try {
79
+ clearTimeout(this.timeout)
80
+ } catch (err) { }
81
+
82
+ this.started = false
83
+ }
84
+
85
+ /**
86
+ * Advertise hop relay service in the network.
87
+ */
88
+ async _advertiseService (): Promise<void> {
89
+ await pRetry(async () => {
90
+ try {
91
+ const cid = await namespaceToCid(RELAY_RENDEZVOUS_NS)
92
+ await this.contentRouting.provide(cid)
93
+
94
+ this.safeDispatchEvent('advert:success', { detail: undefined })
95
+ } catch (err: any) {
96
+ this.safeDispatchEvent('advert:error', { detail: err })
97
+
98
+ if (err.code === ERR_NO_ROUTERS_AVAILABLE) {
99
+ this.log.error('a content router, such as a DHT, must be provided in order to advertise the relay service', err)
100
+ this.stop()
101
+ return
102
+ }
103
+
104
+ this.log.error('could not advertise service', err)
105
+ throw err
106
+ }
107
+ })
108
+ }
109
+ }