@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,209 @@
1
+ import { TypedEventEmitter } from '@libp2p/interface/events';
2
+ import { PeerMap } from '@libp2p/peer-collections';
3
+ import { PeerJobQueue } from '@libp2p/utils/peer-job-queue';
4
+ import { multiaddr } from '@multiformats/multiaddr';
5
+ import { pbStream } from 'it-protobuf-stream';
6
+ import { DEFAULT_RESERVATION_CONCURRENCY, RELAY_TAG, RELAY_V2_HOP_CODEC } from '../constants.js';
7
+ import { HopMessage, Status } from '../pb/index.js';
8
+ import { getExpirationMilliseconds } from '../utils.js';
9
+ // allow refreshing a relay reservation if it will expire in the next 10 minutes
10
+ const REFRESH_WINDOW = (60 * 1000) * 10;
11
+ // try to refresh relay reservations 5 minutes before expiry
12
+ const REFRESH_TIMEOUT = (60 * 1000) * 5;
13
+ // minimum duration before which a reservation must not be refreshed
14
+ const REFRESH_TIMEOUT_MIN = 30 * 1000;
15
+ export class ReservationStore extends TypedEventEmitter {
16
+ peerId;
17
+ connectionManager;
18
+ transportManager;
19
+ peerStore;
20
+ events;
21
+ reserveQueue;
22
+ reservations;
23
+ maxDiscoveredRelays;
24
+ maxReservationQueueLength;
25
+ reservationCompletionTimeout;
26
+ started;
27
+ log;
28
+ constructor(components, init) {
29
+ super();
30
+ this.log = components.logger.forComponent('libp2p:circuit-relay:transport:reservation-store');
31
+ this.peerId = components.peerId;
32
+ this.connectionManager = components.connectionManager;
33
+ this.transportManager = components.transportManager;
34
+ this.peerStore = components.peerStore;
35
+ this.events = components.events;
36
+ this.reservations = new PeerMap();
37
+ this.maxDiscoveredRelays = init?.discoverRelays ?? 0;
38
+ this.maxReservationQueueLength = init?.maxReservationQueueLength ?? 100;
39
+ this.reservationCompletionTimeout = init?.reservationCompletionTimeout ?? 10000;
40
+ this.started = false;
41
+ // ensure we don't listen on multiple relays simultaneously
42
+ this.reserveQueue = new PeerJobQueue({
43
+ concurrency: init?.reservationConcurrency ?? DEFAULT_RESERVATION_CONCURRENCY
44
+ });
45
+ // When a peer disconnects, if we had a reservation on that peer
46
+ // remove the reservation and multiaddr and maybe trigger search
47
+ // for new relays
48
+ this.events.addEventListener('peer:disconnect', (evt) => {
49
+ this.#removeRelay(evt.detail);
50
+ });
51
+ }
52
+ isStarted() {
53
+ return this.started;
54
+ }
55
+ async start() {
56
+ this.started = true;
57
+ }
58
+ async stop() {
59
+ this.reserveQueue.clear();
60
+ this.reservations.forEach(({ timeout }) => {
61
+ clearTimeout(timeout);
62
+ });
63
+ this.reservations.clear();
64
+ this.started = false;
65
+ }
66
+ /**
67
+ * If the number of current relays is beneath the configured `maxReservations`
68
+ * value, and the passed peer id is not our own, and we have a non-relayed connection
69
+ * to the remote, and the remote peer speaks the hop protocol, try to reserve a slot
70
+ * on the remote peer
71
+ */
72
+ async addRelay(peerId, type) {
73
+ if (this.peerId.equals(peerId)) {
74
+ this.log('not trying to use self as relay');
75
+ return;
76
+ }
77
+ if (this.reserveQueue.size > this.maxReservationQueueLength) {
78
+ this.log('not adding relay as the queue is full');
79
+ return;
80
+ }
81
+ if (this.reserveQueue.hasJob(peerId)) {
82
+ this.log('relay peer is already in the reservation queue');
83
+ return;
84
+ }
85
+ this.log('add relay %p', peerId);
86
+ await this.reserveQueue.add(async () => {
87
+ try {
88
+ // allow refresh of an existing reservation if it is about to expire
89
+ const existingReservation = this.reservations.get(peerId);
90
+ if (existingReservation != null) {
91
+ if (getExpirationMilliseconds(existingReservation.reservation.expire) > REFRESH_WINDOW) {
92
+ this.log('already have reservation on relay peer %p and it expires in more than 10 minutes', peerId);
93
+ return;
94
+ }
95
+ clearTimeout(existingReservation.timeout);
96
+ this.reservations.delete(peerId);
97
+ }
98
+ if (type === 'discovered' && [...this.reservations.values()].reduce((acc, curr) => {
99
+ if (curr.type === 'discovered') {
100
+ acc++;
101
+ }
102
+ return acc;
103
+ }, 0) >= this.maxDiscoveredRelays) {
104
+ this.log('already have enough discovered relays');
105
+ return;
106
+ }
107
+ const signal = AbortSignal.timeout(this.reservationCompletionTimeout);
108
+ const connection = await this.connectionManager.openConnection(peerId, {
109
+ signal
110
+ });
111
+ if (connection.remoteAddr.protoNames().includes('p2p-circuit')) {
112
+ this.log('not creating reservation over relayed connection');
113
+ return;
114
+ }
115
+ const reservation = await this.#createReservation(connection, {
116
+ signal
117
+ });
118
+ this.log('created reservation on relay peer %p', peerId);
119
+ const expiration = getExpirationMilliseconds(reservation.expire);
120
+ // sets a lower bound on the timeout, and also don't let it go over
121
+ // 2^31 - 1 (setTimeout will only accept signed 32 bit integers)
122
+ const timeoutDuration = Math.min(Math.max(expiration - REFRESH_TIMEOUT, REFRESH_TIMEOUT_MIN), Math.pow(2, 31) - 1);
123
+ const timeout = setTimeout(() => {
124
+ this.addRelay(peerId, type).catch(err => {
125
+ this.log.error('could not refresh reservation to relay %p', peerId, err);
126
+ });
127
+ }, timeoutDuration);
128
+ // we've managed to create a reservation successfully
129
+ this.reservations.set(peerId, {
130
+ timeout,
131
+ reservation,
132
+ type
133
+ });
134
+ // ensure we don't close the connection to the relay
135
+ await this.peerStore.merge(peerId, {
136
+ tags: {
137
+ [RELAY_TAG]: {
138
+ value: 1,
139
+ ttl: expiration
140
+ }
141
+ }
142
+ });
143
+ // listen on multiaddr that only the circuit transport is listening for
144
+ await this.transportManager.listen([multiaddr(`/p2p/${peerId.toString()}/p2p-circuit`)]);
145
+ }
146
+ catch (err) {
147
+ this.log.error('could not reserve slot on %p', peerId, err);
148
+ // cancel the renewal timeout if it's been set
149
+ const reservation = this.reservations.get(peerId);
150
+ if (reservation != null) {
151
+ clearTimeout(reservation.timeout);
152
+ }
153
+ // if listening failed, remove the reservation
154
+ this.reservations.delete(peerId);
155
+ }
156
+ }, {
157
+ peerId
158
+ });
159
+ }
160
+ hasReservation(peerId) {
161
+ return this.reservations.has(peerId);
162
+ }
163
+ getReservation(peerId) {
164
+ return this.reservations.get(peerId)?.reservation;
165
+ }
166
+ async #createReservation(connection, options) {
167
+ options.signal?.throwIfAborted();
168
+ this.log('requesting reservation from %p', connection.remotePeer);
169
+ const stream = await connection.newStream(RELAY_V2_HOP_CODEC, options);
170
+ const pbstr = pbStream(stream);
171
+ const hopstr = pbstr.pb(HopMessage);
172
+ await hopstr.write({ type: HopMessage.Type.RESERVE }, options);
173
+ let response;
174
+ try {
175
+ response = await hopstr.read(options);
176
+ }
177
+ catch (err) {
178
+ this.log.error('error parsing reserve message response from %p because', connection.remotePeer, err);
179
+ throw err;
180
+ }
181
+ finally {
182
+ await stream.close();
183
+ }
184
+ if (response.status === Status.OK && (response.reservation != null)) {
185
+ return response.reservation;
186
+ }
187
+ const errMsg = `reservation failed with status ${response.status ?? 'undefined'}`;
188
+ this.log.error(errMsg);
189
+ throw new Error(errMsg);
190
+ }
191
+ /**
192
+ * Remove listen relay
193
+ */
194
+ #removeRelay(peerId) {
195
+ const existingReservation = this.reservations.get(peerId);
196
+ if (existingReservation == null) {
197
+ return;
198
+ }
199
+ this.log('connection to relay %p closed, removing reservation from local store', peerId);
200
+ clearTimeout(existingReservation.timeout);
201
+ this.reservations.delete(peerId);
202
+ this.safeDispatchEvent('relay:removed', { detail: peerId });
203
+ if (this.reservations.size < this.maxDiscoveredRelays) {
204
+ this.log('not enough relays %d/%d', this.reservations.size, this.maxDiscoveredRelays);
205
+ this.safeDispatchEvent('relay:not-enough-relays', {});
206
+ }
207
+ }
208
+ }
209
+ //# sourceMappingURL=reservation-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reservation-store.js","sourceRoot":"","sources":["../../../src/transport/reservation-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { CID } from 'multiformats/cid';
2
+ import type { Limit } from './pb/index.js';
3
+ import type { LoggerOptions } from '@libp2p/interface';
4
+ import type { Stream } from '@libp2p/interface/connection';
5
+ export declare function createLimitedRelay(src: Stream, dst: Stream, abortSignal: AbortSignal, limit: Limit | undefined, options: LoggerOptions): void;
6
+ /**
7
+ * Convert a namespace string into a cid
8
+ */
9
+ export declare function namespaceToCid(namespace: string): Promise<CID>;
10
+ /**
11
+ * returns number of ms between now and expiration time
12
+ */
13
+ export declare function getExpirationMilliseconds(expireTimeSeconds: bigint): number;
14
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAGtC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAA;AA+B1D,wBAAgB,kBAAkB,CAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CA0E9I;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAKrE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAE,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAM5E"}
@@ -0,0 +1,106 @@
1
+ import { CodeError } from '@libp2p/interface/errors';
2
+ import { anySignal } from 'any-signal';
3
+ import { CID } from 'multiformats/cid';
4
+ import { sha256 } from 'multiformats/hashes/sha2';
5
+ import { ERR_TRANSFER_LIMIT_EXCEEDED } from './constants.js';
6
+ async function* countStreamBytes(source, limit, options) {
7
+ const limitBytes = limit.remaining;
8
+ for await (const buf of source) {
9
+ const len = BigInt(buf.byteLength);
10
+ if ((limit.remaining - len) < 0) {
11
+ // this is a safe downcast since len is guarantee to be in the range for a number
12
+ const remaining = Number(limit.remaining);
13
+ limit.remaining = 0n;
14
+ try {
15
+ if (remaining !== 0) {
16
+ yield buf.subarray(0, remaining);
17
+ }
18
+ }
19
+ catch (err) {
20
+ options.log.error(err);
21
+ }
22
+ throw new CodeError(`data limit of ${limitBytes} bytes exceeded`, ERR_TRANSFER_LIMIT_EXCEEDED);
23
+ }
24
+ limit.remaining -= len;
25
+ yield buf;
26
+ }
27
+ }
28
+ export function createLimitedRelay(src, dst, abortSignal, limit, options) {
29
+ function abortStreams(err) {
30
+ src.abort(err);
31
+ dst.abort(err);
32
+ clearTimeout(timeout);
33
+ }
34
+ const abortController = new AbortController();
35
+ const signal = anySignal([abortSignal, abortController.signal]);
36
+ let timeout;
37
+ if (limit?.duration != null) {
38
+ timeout = setTimeout(() => {
39
+ abortController.abort();
40
+ }, limit.duration);
41
+ }
42
+ let srcDstFinished = false;
43
+ let dstSrcFinished = false;
44
+ let dataLimit;
45
+ if (limit?.data != null) {
46
+ dataLimit = {
47
+ remaining: limit.data
48
+ };
49
+ }
50
+ queueMicrotask(() => {
51
+ const onAbort = () => {
52
+ dst.abort(new CodeError(`duration limit of ${limit?.duration} ms exceeded`, ERR_TRANSFER_LIMIT_EXCEEDED));
53
+ };
54
+ signal.addEventListener('abort', onAbort, { once: true });
55
+ void dst.sink(dataLimit == null ? src.source : countStreamBytes(src.source, dataLimit, options))
56
+ .catch(err => {
57
+ options.log.error('error while relaying streams src -> dst', err);
58
+ abortStreams(err);
59
+ })
60
+ .finally(() => {
61
+ srcDstFinished = true;
62
+ if (dstSrcFinished) {
63
+ signal.removeEventListener('abort', onAbort);
64
+ signal.clear();
65
+ clearTimeout(timeout);
66
+ }
67
+ });
68
+ });
69
+ queueMicrotask(() => {
70
+ const onAbort = () => {
71
+ src.abort(new CodeError(`duration limit of ${limit?.duration} ms exceeded`, ERR_TRANSFER_LIMIT_EXCEEDED));
72
+ };
73
+ signal.addEventListener('abort', onAbort, { once: true });
74
+ void src.sink(dataLimit == null ? dst.source : countStreamBytes(dst.source, dataLimit, options))
75
+ .catch(err => {
76
+ options.log.error('error while relaying streams dst -> src', err);
77
+ abortStreams(err);
78
+ })
79
+ .finally(() => {
80
+ dstSrcFinished = true;
81
+ if (srcDstFinished) {
82
+ signal.removeEventListener('abort', onAbort);
83
+ signal.clear();
84
+ clearTimeout(timeout);
85
+ }
86
+ });
87
+ });
88
+ }
89
+ /**
90
+ * Convert a namespace string into a cid
91
+ */
92
+ export async function namespaceToCid(namespace) {
93
+ const bytes = new TextEncoder().encode(namespace);
94
+ const hash = await sha256.digest(bytes);
95
+ return CID.createV0(hash);
96
+ }
97
+ /**
98
+ * returns number of ms between now and expiration time
99
+ */
100
+ export function getExpirationMilliseconds(expireTimeSeconds) {
101
+ const expireTimeMillis = expireTimeSeconds * BigInt(1000);
102
+ const currentTime = new Date().getTime();
103
+ // downcast to number to use with setTimeout
104
+ return Number(expireTimeMillis - BigInt(currentTime));
105
+ }
106
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,83 @@
1
+ {
2
+ "name": "@libp2p/circuit-relay-v2",
3
+ "version": "0.0.0-05b52d69c",
4
+ "description": "Implementation of Circuit Relay v2",
5
+ "license": "Apache-2.0 OR MIT",
6
+ "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/transport-circuit-relay-v2#readme",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/libp2p/js-libp2p.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/libp2p/js-libp2p/issues"
13
+ },
14
+ "type": "module",
15
+ "types": "./dist/src/index.d.ts",
16
+ "files": [
17
+ "src",
18
+ "dist",
19
+ "!dist/test",
20
+ "!**/*.tsbuildinfo"
21
+ ],
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/src/index.d.ts",
25
+ "import": "./dist/src/index.js"
26
+ }
27
+ },
28
+ "eslintConfig": {
29
+ "extends": "ipfs",
30
+ "parserOptions": {
31
+ "project": true,
32
+ "sourceType": "module"
33
+ }
34
+ },
35
+ "scripts": {
36
+ "start": "node dist/src/main.js",
37
+ "build": "aegir build",
38
+ "test": "aegir test",
39
+ "clean": "aegir clean",
40
+ "generate": "protons ./src/pb/index.proto",
41
+ "lint": "aegir lint",
42
+ "test:chrome": "aegir test -t browser --cov",
43
+ "test:chrome-webworker": "aegir test -t webworker",
44
+ "test:firefox": "aegir test -t browser -- --browser firefox",
45
+ "test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
46
+ "test:node": "aegir test -t node --cov",
47
+ "dep-check": "aegir dep-check"
48
+ },
49
+ "dependencies": {
50
+ "@libp2p/interface": "0.1.6-05b52d69c",
51
+ "@libp2p/interface-internal": "0.1.9-05b52d69c",
52
+ "@libp2p/peer-collections": "4.0.8-05b52d69c",
53
+ "@libp2p/peer-id": "3.0.6-05b52d69c",
54
+ "@libp2p/peer-record": "6.0.9-05b52d69c",
55
+ "@libp2p/utils": "4.0.7-05b52d69c",
56
+ "@multiformats/mafmt": "^12.1.6",
57
+ "@multiformats/multiaddr": "^12.1.10",
58
+ "any-signal": "^4.1.1",
59
+ "delay": "^6.0.0",
60
+ "it-protobuf-stream": "^1.0.2",
61
+ "it-stream-types": "^2.0.1",
62
+ "multiformats": "^12.1.3",
63
+ "p-defer": "^4.0.0",
64
+ "p-retry": "^6.1.0",
65
+ "protons-runtime": "^5.0.0",
66
+ "uint8arraylist": "^2.4.3",
67
+ "uint8arrays": "^4.0.6"
68
+ },
69
+ "devDependencies": {
70
+ "@libp2p/interface-compliance-tests": "4.1.5-05b52d69c",
71
+ "@libp2p/logger": "3.1.0-05b52d69c",
72
+ "@libp2p/peer-id-factory": "3.0.8-05b52d69c",
73
+ "aegir": "^41.0.2",
74
+ "it-drain": "^3.0.3",
75
+ "it-pair": "^2.0.6",
76
+ "it-pushable": "^3.2.1",
77
+ "it-to-buffer": "^4.0.3",
78
+ "p-wait-for": "^5.0.2",
79
+ "protons": "^7.3.0",
80
+ "sinon": "^17.0.0",
81
+ "sinon-ts": "^2.0.0"
82
+ }
83
+ }
@@ -0,0 +1,79 @@
1
+ const second = 1000
2
+ const minute = 60 * second
3
+
4
+ /**
5
+ * Delay before HOP relay service is advertised on the network
6
+ */
7
+ export const ADVERTISE_BOOT_DELAY = 15 * minute
8
+
9
+ /**
10
+ * Delay Between HOP relay service advertisements on the network
11
+ */
12
+ export const ADVERTISE_TTL = 30 * minute
13
+
14
+ /**
15
+ * Multicodec code
16
+ */
17
+ export const CIRCUIT_PROTO_CODE = 290
18
+
19
+ /**
20
+ * Relay HOP relay service namespace for discovery
21
+ */
22
+ export const RELAY_RENDEZVOUS_NS = '/libp2p/relay'
23
+
24
+ /**
25
+ * The maximum number of relay reservations the relay server will accept
26
+ */
27
+ export const DEFAULT_MAX_RESERVATION_STORE_SIZE = 15
28
+
29
+ /**
30
+ * How often to check for reservation expiry
31
+ */
32
+ export const DEFAULT_MAX_RESERVATION_CLEAR_INTERVAL = 300 * second
33
+
34
+ /**
35
+ * How often to check for reservation expiry
36
+ */
37
+ export const DEFAULT_MAX_RESERVATION_TTL = 2 * 60 * minute
38
+
39
+ export const DEFAULT_RESERVATION_CONCURRENCY = 1
40
+
41
+ export const RELAY_SOURCE_TAG = 'circuit-relay-source'
42
+
43
+ export const RELAY_TAG = 'circuit-relay-relay'
44
+
45
+ // circuit v2 connection limits
46
+ // https://github.com/libp2p/go-libp2p/blob/master/p2p/protocol/circuitv2/relay/resources.go#L61-L66
47
+
48
+ // 2 min is the default connection duration
49
+ export const DEFAULT_DURATION_LIMIT = 2 * minute
50
+
51
+ // 128k is the default data limit
52
+ export const DEFAULT_DATA_LIMIT = BigInt(1 << 17)
53
+
54
+ /**
55
+ * The hop protocol
56
+ */
57
+ export const RELAY_V2_HOP_CODEC = '/libp2p/circuit/relay/0.2.0/hop'
58
+
59
+ /**
60
+ * the stop protocol
61
+ */
62
+ export const RELAY_V2_STOP_CODEC = '/libp2p/circuit/relay/0.2.0/stop'
63
+
64
+ /**
65
+ * Hop messages must be exchanged inside this timeout
66
+ */
67
+ export const DEFAULT_HOP_TIMEOUT = 30 * second
68
+
69
+ /**
70
+ * How long to wait before starting to advertise the relay service
71
+ */
72
+ export const DEFAULT_ADVERT_BOOT_DELAY = 30 * second
73
+
74
+ export const MAX_CONNECTIONS = 300
75
+
76
+ export const ERR_NO_ROUTERS_AVAILABLE = 'ERR_NO_ROUTERS_AVAILABLE'
77
+ export const ERR_RELAYED_DIAL = 'ERR_RELAYED_DIAL'
78
+ export const ERR_HOP_REQUEST_FAILED = 'ERR_HOP_REQUEST_FAILED'
79
+ export const ERR_TRANSFER_LIMIT_EXCEEDED = 'ERR_TRANSFER_LIMIT_EXCEEDED'
package/src/index.ts ADDED
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @packageDocumentation
3
+ *
4
+ * The `circuitRelayTransport` allows libp2p to dial and listen on [Circuit Relay](https://docs.libp2p.io/concepts/nat/circuit-relay/)
5
+ * addresses.
6
+ *
7
+ * @example
8
+ *
9
+ * ```typescript
10
+ * import { createLibp2p } from 'libp2p'
11
+ * import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'
12
+ *
13
+ * const node = await createLibp2p({
14
+ * transports: [
15
+ * circuitRelayTransport()
16
+ * ]
17
+ * })
18
+ * ```
19
+ *
20
+ * The `circuitRelayServer` function allows libp2p to function as a [Circuit Relay](https://docs.libp2p.io/concepts/nat/circuit-relay/)
21
+ * server. This will not work in browsers.
22
+ *
23
+ * @example
24
+ *
25
+ * ```typescript
26
+ * import { createLibp2p } from 'libp2p'
27
+ * import { circuitRelayServer } from '@libp2p/circuit-relay-v2'
28
+ *
29
+ * const node = await createLibp2p({
30
+ * services: [
31
+ * circuitRelay: circuitRelayServer()
32
+ * ]
33
+ * })
34
+ * ```
35
+ */
36
+
37
+ import type { Limit } from './pb/index.js'
38
+ import type { TypedEventEmitter } from '@libp2p/interface/events'
39
+ import type { PeerMap } from '@libp2p/peer-collections'
40
+ import type { Multiaddr } from '@multiformats/multiaddr'
41
+
42
+ export interface RelayReservation {
43
+ expire: Date
44
+ addr: Multiaddr
45
+ limit?: Limit
46
+ }
47
+
48
+ export interface CircuitRelayServiceEvents {
49
+ 'relay:reservation': CustomEvent<RelayReservation>
50
+ 'relay:advert:success': CustomEvent<unknown>
51
+ 'relay:advert:error': CustomEvent<Error>
52
+ }
53
+
54
+ export interface CircuitRelayService extends TypedEventEmitter<CircuitRelayServiceEvents> {
55
+ reservations: PeerMap<RelayReservation>
56
+ }
57
+
58
+ export { circuitRelayServer } from './server/index.js'
59
+ export { circuitRelayTransport } from './transport/index.js'
60
+
61
+ export {
62
+ RELAY_V2_HOP_CODEC,
63
+ RELAY_V2_STOP_CODEC
64
+ } from './constants.js'
@@ -0,0 +1,67 @@
1
+ syntax = "proto3";
2
+
3
+ message HopMessage {
4
+ enum Type {
5
+ RESERVE = 0;
6
+ CONNECT = 1;
7
+ STATUS = 2;
8
+ }
9
+
10
+ // the presence of this field is enforced at application level
11
+ optional Type type = 1;
12
+
13
+ optional Peer peer = 2;
14
+ optional Reservation reservation = 3;
15
+ optional Limit limit = 4;
16
+
17
+ optional Status status = 5;
18
+ }
19
+
20
+ message StopMessage {
21
+ enum Type {
22
+ CONNECT = 0;
23
+ STATUS = 1;
24
+ }
25
+
26
+ // the presence of this field is enforced at application level
27
+ optional Type type = 1;
28
+
29
+ optional Peer peer = 2;
30
+ optional Limit limit = 3;
31
+
32
+ optional Status status = 4;
33
+ }
34
+
35
+ message Peer {
36
+ bytes id = 1;
37
+ repeated bytes addrs = 2;
38
+ }
39
+
40
+ message Reservation {
41
+ uint64 expire = 1; // Unix expiration time (UTC)
42
+ repeated bytes addrs = 2; // relay addrs for reserving peer
43
+ optional bytes voucher = 3; // reservation voucher
44
+ }
45
+
46
+ message Limit {
47
+ optional uint32 duration = 1; // seconds
48
+ optional uint64 data = 2; // bytes
49
+ }
50
+
51
+ enum Status {
52
+ UNUSED = 0;
53
+ OK = 100;
54
+ RESERVATION_REFUSED = 200;
55
+ RESOURCE_LIMIT_EXCEEDED = 201;
56
+ PERMISSION_DENIED = 202;
57
+ CONNECTION_FAILED = 203;
58
+ NO_RESERVATION = 204;
59
+ MALFORMED_MESSAGE = 400;
60
+ UNEXPECTED_MESSAGE = 401;
61
+ }
62
+
63
+ message ReservationVoucher {
64
+ bytes relay = 1;
65
+ bytes peer = 2;
66
+ uint64 expiration = 3;
67
+ }