@libp2p/circuit-relay-v2 3.2.23 → 3.2.24-8484de8a2
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.
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +4 -4
- package/dist/src/constants.d.ts +0 -4
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +0 -4
- package/dist/src/constants.js.map +1 -1
- package/dist/src/index.d.ts +170 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +12 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/server/index.d.ts +41 -45
- package/dist/src/server/index.d.ts.map +1 -1
- package/dist/src/server/index.js +30 -47
- package/dist/src/server/index.js.map +1 -1
- package/dist/src/server/reservation-store.d.ts +2 -36
- package/dist/src/server/reservation-store.d.ts.map +1 -1
- package/dist/src/server/reservation-store.js.map +1 -1
- package/dist/src/transport/discovery.d.ts +2 -17
- package/dist/src/transport/discovery.d.ts.map +1 -1
- package/dist/src/transport/discovery.js +2 -2
- package/dist/src/transport/discovery.js.map +1 -1
- package/dist/src/transport/index.d.ts +34 -42
- package/dist/src/transport/index.d.ts.map +1 -1
- package/dist/src/transport/index.js +291 -5
- package/dist/src/transport/index.js.map +1 -1
- package/dist/src/transport/reservation-store.d.ts +3 -37
- package/dist/src/transport/reservation-store.d.ts.map +1 -1
- package/dist/src/transport/reservation-store.js +4 -6
- package/dist/src/transport/reservation-store.js.map +1 -1
- package/dist/src/transport/stream-to-conn.d.ts +19 -0
- package/dist/src/transport/stream-to-conn.d.ts.map +1 -0
- package/dist/src/transport/stream-to-conn.js +60 -0
- package/dist/src/transport/stream-to-conn.js.map +1 -0
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +36 -59
- package/dist/src/utils.js.map +1 -1
- package/package.json +19 -24
- package/src/constants.ts +0 -5
- package/src/index.ts +207 -8
- package/src/server/index.ts +35 -100
- package/src/server/reservation-store.ts +2 -42
- package/src/transport/discovery.ts +4 -22
- package/src/transport/index.ts +338 -46
- package/src/transport/reservation-store.ts +8 -46
- package/src/transport/stream-to-conn.ts +91 -0
- package/src/utils.ts +37 -66
- package/dist/src/transport/transport.d.ts +0 -54
- package/dist/src/transport/transport.d.ts.map +0 -1
- package/dist/src/transport/transport.js +0 -314
- package/dist/src/transport/transport.js.map +0 -1
- package/dist/typedoc-urls.json +0 -23
- package/src/transport/transport.ts +0 -378
package/src/index.ts
CHANGED
@@ -40,7 +40,11 @@
|
|
40
40
|
*/
|
41
41
|
|
42
42
|
import { TypedEventEmitter } from 'main-event'
|
43
|
+
import { CircuitRelayServer } from './server/index.js'
|
44
|
+
import { CircuitRelayTransport } from './transport/index.ts'
|
43
45
|
import type { Limit } from './pb/index.js'
|
46
|
+
import type { ComponentLogger, ConnectionGater, Libp2pEvents, Metrics, PeerId, PeerStore, PrivateKey, TopologyFilter, Transport, TypedEventTarget, Upgrader } from '@libp2p/interface'
|
47
|
+
import type { AddressManager, ConnectionManager, RandomWalk, Registrar, TransportManager } from '@libp2p/interface-internal'
|
44
48
|
import type { PeerMap } from '@libp2p/peer-collections'
|
45
49
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
46
50
|
import type { RetimeableAbortSignal } from 'retimeable-signal'
|
@@ -80,15 +84,210 @@ export interface CircuitRelayService extends TypedEventEmitter<CircuitRelayServi
|
|
80
84
|
reservations: PeerMap<RelayReservation>
|
81
85
|
}
|
82
86
|
|
83
|
-
export { circuitRelayServer } from './server/index.js'
|
84
|
-
export type { CircuitRelayServerInit, CircuitRelayServerComponents } from './server/index.js'
|
85
|
-
export type { ReservationStoreInit as ServerReservationStoreInit } from './server/reservation-store.js'
|
86
|
-
export { circuitRelayTransport } from './transport/index.js'
|
87
|
-
export type { RelayDiscoveryComponents } from './transport/discovery.js'
|
88
|
-
export type { ReservationStoreInit as TransportReservationStoreInit } from './transport/reservation-store.js'
|
89
|
-
export type { CircuitRelayTransportInit, CircuitRelayTransportComponents } from './transport/index.js'
|
90
|
-
|
91
87
|
export {
|
92
88
|
RELAY_V2_HOP_CODEC,
|
93
89
|
RELAY_V2_STOP_CODEC
|
94
90
|
} from './constants.js'
|
91
|
+
|
92
|
+
export interface ServerReservationStoreInit {
|
93
|
+
/**
|
94
|
+
* maximum number of reservations allowed
|
95
|
+
*
|
96
|
+
* @default 15
|
97
|
+
*/
|
98
|
+
maxReservations?: number
|
99
|
+
|
100
|
+
/**
|
101
|
+
* interval after which stale reservations are cleared
|
102
|
+
*
|
103
|
+
* @default 300000
|
104
|
+
*/
|
105
|
+
reservationClearInterval?: number
|
106
|
+
|
107
|
+
/**
|
108
|
+
* apply default relay limits to a new reservation
|
109
|
+
*
|
110
|
+
* @default true
|
111
|
+
*/
|
112
|
+
applyDefaultLimit?: boolean
|
113
|
+
|
114
|
+
/**
|
115
|
+
* reservation ttl
|
116
|
+
*
|
117
|
+
* @default 7200000
|
118
|
+
*/
|
119
|
+
reservationTtl?: number
|
120
|
+
|
121
|
+
/**
|
122
|
+
* The maximum time a relayed connection can be open for
|
123
|
+
*/
|
124
|
+
defaultDurationLimit?: number
|
125
|
+
|
126
|
+
/**
|
127
|
+
* The maximum amount of data allowed to be transferred over a relayed connection
|
128
|
+
*/
|
129
|
+
defaultDataLimit?: bigint
|
130
|
+
}
|
131
|
+
|
132
|
+
export interface CircuitRelayServerComponents {
|
133
|
+
registrar: Registrar
|
134
|
+
peerStore: PeerStore
|
135
|
+
addressManager: AddressManager
|
136
|
+
peerId: PeerId
|
137
|
+
privateKey: PrivateKey
|
138
|
+
connectionManager: ConnectionManager
|
139
|
+
connectionGater: ConnectionGater
|
140
|
+
logger: ComponentLogger
|
141
|
+
metrics?: Metrics
|
142
|
+
}
|
143
|
+
|
144
|
+
export interface CircuitRelayServerInit {
|
145
|
+
/**
|
146
|
+
* Incoming hop requests must complete within this time in ms otherwise
|
147
|
+
* the stream will be reset
|
148
|
+
*
|
149
|
+
* @default 30000
|
150
|
+
*/
|
151
|
+
hopTimeout?: number
|
152
|
+
|
153
|
+
/**
|
154
|
+
* Configuration of reservations
|
155
|
+
*/
|
156
|
+
reservations?: ServerReservationStoreInit
|
157
|
+
|
158
|
+
/**
|
159
|
+
* The maximum number of simultaneous HOP inbound streams that can be open at once
|
160
|
+
*/
|
161
|
+
maxInboundHopStreams?: number
|
162
|
+
|
163
|
+
/**
|
164
|
+
* The maximum number of simultaneous HOP outbound streams that can be open at once
|
165
|
+
*/
|
166
|
+
maxOutboundHopStreams?: number
|
167
|
+
|
168
|
+
/**
|
169
|
+
* The maximum number of simultaneous STOP outbound streams that can be open at
|
170
|
+
* once.
|
171
|
+
*
|
172
|
+
* @default 300
|
173
|
+
*/
|
174
|
+
maxOutboundStopStreams?: number
|
175
|
+
}
|
176
|
+
|
177
|
+
export function circuitRelayServer (init: CircuitRelayServerInit = {}): (components: CircuitRelayServerComponents) => CircuitRelayService {
|
178
|
+
return (components) => {
|
179
|
+
return new CircuitRelayServer(components, init)
|
180
|
+
}
|
181
|
+
}
|
182
|
+
|
183
|
+
export interface RelayDiscoveryEvents {
|
184
|
+
'relay:discover': CustomEvent<PeerId>
|
185
|
+
}
|
186
|
+
|
187
|
+
export interface TransportReservationStoreComponents {
|
188
|
+
peerId: PeerId
|
189
|
+
connectionManager: ConnectionManager
|
190
|
+
peerStore: PeerStore
|
191
|
+
events: TypedEventTarget<Libp2pEvents>
|
192
|
+
logger: ComponentLogger
|
193
|
+
metrics?: Metrics
|
194
|
+
}
|
195
|
+
|
196
|
+
export interface TransportReservationStoreInit {
|
197
|
+
/**
|
198
|
+
* Multiple relays may be discovered simultaneously - to prevent listening
|
199
|
+
* on too many relays, this value controls how many to attempt to reserve a
|
200
|
+
* slot on at once. If set to more than one, we may end up listening on
|
201
|
+
* more relays than the `maxReservations` value, but on networks with poor
|
202
|
+
* connectivity the user may wish to attempt to reserve on multiple relays
|
203
|
+
* simultaneously.
|
204
|
+
*
|
205
|
+
* @default 1
|
206
|
+
*/
|
207
|
+
reservationConcurrency?: number
|
208
|
+
|
209
|
+
/**
|
210
|
+
* Limit the number of potential relays we will dial
|
211
|
+
*
|
212
|
+
* @default 100
|
213
|
+
*/
|
214
|
+
maxReservationQueueLength?: number
|
215
|
+
|
216
|
+
/**
|
217
|
+
* When creating a reservation it must complete within this number of ms
|
218
|
+
*
|
219
|
+
* @default 5000
|
220
|
+
*/
|
221
|
+
reservationCompletionTimeout?: number
|
222
|
+
}
|
223
|
+
|
224
|
+
export interface RelayDiscoveryComponents {
|
225
|
+
peerStore: PeerStore
|
226
|
+
connectionManager: ConnectionManager
|
227
|
+
transportManager: TransportManager
|
228
|
+
registrar: Registrar
|
229
|
+
logger: ComponentLogger
|
230
|
+
randomWalk: RandomWalk
|
231
|
+
events: TypedEventTarget<Libp2pEvents>
|
232
|
+
}
|
233
|
+
|
234
|
+
export interface RelayDiscoveryInit {
|
235
|
+
filter?: TopologyFilter
|
236
|
+
}
|
237
|
+
|
238
|
+
export interface CircuitRelayTransportComponents extends RelayDiscoveryComponents {
|
239
|
+
peerId: PeerId
|
240
|
+
upgrader: Upgrader
|
241
|
+
addressManager: AddressManager
|
242
|
+
connectionGater: ConnectionGater
|
243
|
+
}
|
244
|
+
|
245
|
+
/**
|
246
|
+
* RelayConfig configures the circuit v2 relay transport.
|
247
|
+
*/
|
248
|
+
export interface CircuitRelayTransportInit extends TransportReservationStoreInit {
|
249
|
+
/**
|
250
|
+
* An optional filter used to prevent duplicate attempts to reserve relay
|
251
|
+
* slots on the same peer
|
252
|
+
*/
|
253
|
+
discoveryFilter?: TopologyFilter
|
254
|
+
|
255
|
+
/**
|
256
|
+
* The maximum number of simultaneous STOP inbound streams that can be open at
|
257
|
+
* once - each inbound relayed connection uses a STOP stream
|
258
|
+
*
|
259
|
+
* @default 300
|
260
|
+
*/
|
261
|
+
maxInboundStopStreams?: number
|
262
|
+
|
263
|
+
/**
|
264
|
+
* The maximum number of simultaneous STOP outbound streams that can be open
|
265
|
+
* at once. If this transport is used along with the relay server these
|
266
|
+
* settings should be set to the same value
|
267
|
+
*
|
268
|
+
* @default 300
|
269
|
+
*/
|
270
|
+
maxOutboundStopStreams?: number
|
271
|
+
|
272
|
+
/**
|
273
|
+
* Incoming STOP requests (e.g. when a remote peer wants to dial us via a
|
274
|
+
* relay) must finish the initial protocol negotiation within this timeout in
|
275
|
+
* ms
|
276
|
+
*
|
277
|
+
* @deprecated Configure `connectionManager.inboundUpgradeTimeout` instead
|
278
|
+
*/
|
279
|
+
stopTimeout?: number
|
280
|
+
|
281
|
+
/**
|
282
|
+
* When creating a reservation it must complete within this number of ms
|
283
|
+
*
|
284
|
+
* @default 10_000
|
285
|
+
*/
|
286
|
+
reservationCompletionTimeout?: number
|
287
|
+
}
|
288
|
+
|
289
|
+
export function circuitRelayTransport (init: CircuitRelayTransportInit = {}): (components: CircuitRelayTransportComponents) => Transport {
|
290
|
+
return (components) => {
|
291
|
+
return new CircuitRelayTransport(components, init)
|
292
|
+
}
|
293
|
+
}
|
package/src/server/index.ts
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
import { publicKeyToProtobuf } from '@libp2p/crypto/keys'
|
2
2
|
import { peerIdFromMultihash } from '@libp2p/peer-id'
|
3
3
|
import { RecordEnvelope } from '@libp2p/peer-record'
|
4
|
+
import { pbStream } from '@libp2p/utils'
|
4
5
|
import { multiaddr } from '@multiformats/multiaddr'
|
5
|
-
import {
|
6
|
+
import { Circuit } from '@multiformats/multiaddr-matcher'
|
6
7
|
import { TypedEventEmitter, setMaxListeners } from 'main-event'
|
7
8
|
import * as Digest from 'multiformats/hashes/digest'
|
8
9
|
import {
|
9
|
-
CIRCUIT_PROTO_CODE,
|
10
10
|
DEFAULT_HOP_TIMEOUT,
|
11
11
|
KEEP_ALIVE_SOURCE_TAG,
|
12
12
|
MAX_CONNECTIONS,
|
@@ -18,49 +18,11 @@ import { HopMessage, Status, StopMessage } from '../pb/index.js'
|
|
18
18
|
import { createLimitedRelay } from '../utils.js'
|
19
19
|
import { ReservationStore } from './reservation-store.js'
|
20
20
|
import { ReservationVoucherRecord } from './reservation-voucher.js'
|
21
|
-
import type {
|
22
|
-
import type { CircuitRelayService, RelayReservation } from '../index.js'
|
21
|
+
import type { CircuitRelayServerComponents, CircuitRelayServerInit, CircuitRelayService, RelayReservation } from '../index.js'
|
23
22
|
import type { Reservation } from '../pb/index.js'
|
24
|
-
import type {
|
25
|
-
import type { AddressManager, ConnectionManager, Registrar } from '@libp2p/interface-internal'
|
23
|
+
import type { Logger, Connection, Stream, PeerId, Startable, AbortOptions } from '@libp2p/interface'
|
26
24
|
import type { PeerMap } from '@libp2p/peer-collections'
|
27
|
-
import type {
|
28
|
-
import type { ProtobufStream } from 'it-protobuf-stream'
|
29
|
-
|
30
|
-
const isRelayAddr = (ma: Multiaddr): boolean => ma.protoCodes().includes(CIRCUIT_PROTO_CODE)
|
31
|
-
|
32
|
-
export interface CircuitRelayServerInit {
|
33
|
-
/**
|
34
|
-
* Incoming hop requests must complete within this time in ms otherwise
|
35
|
-
* the stream will be reset
|
36
|
-
*
|
37
|
-
* @default 30000
|
38
|
-
*/
|
39
|
-
hopTimeout?: number
|
40
|
-
|
41
|
-
/**
|
42
|
-
* Configuration of reservations
|
43
|
-
*/
|
44
|
-
reservations?: ReservationStoreInit
|
45
|
-
|
46
|
-
/**
|
47
|
-
* The maximum number of simultaneous HOP inbound streams that can be open at once
|
48
|
-
*/
|
49
|
-
maxInboundHopStreams?: number
|
50
|
-
|
51
|
-
/**
|
52
|
-
* The maximum number of simultaneous HOP outbound streams that can be open at once
|
53
|
-
*/
|
54
|
-
maxOutboundHopStreams?: number
|
55
|
-
|
56
|
-
/**
|
57
|
-
* The maximum number of simultaneous STOP outbound streams that can be open at
|
58
|
-
* once.
|
59
|
-
*
|
60
|
-
* @default 300
|
61
|
-
*/
|
62
|
-
maxOutboundStopStreams?: number
|
63
|
-
}
|
25
|
+
import type { ProtobufStream } from '@libp2p/utils'
|
64
26
|
|
65
27
|
export interface HopProtocolOptions {
|
66
28
|
connection: Connection
|
@@ -73,18 +35,6 @@ export interface StopOptions {
|
|
73
35
|
request: StopMessage
|
74
36
|
}
|
75
37
|
|
76
|
-
export interface CircuitRelayServerComponents {
|
77
|
-
registrar: Registrar
|
78
|
-
peerStore: PeerStore
|
79
|
-
addressManager: AddressManager
|
80
|
-
peerId: PeerId
|
81
|
-
privateKey: PrivateKey
|
82
|
-
connectionManager: ConnectionManager
|
83
|
-
connectionGater: ConnectionGater
|
84
|
-
logger: ComponentLogger
|
85
|
-
metrics?: Metrics
|
86
|
-
}
|
87
|
-
|
88
38
|
export interface RelayServerEvents {
|
89
39
|
'relay:reservation': CustomEvent<RelayReservation>
|
90
40
|
'relay:advert:success': CustomEvent<unknown>
|
@@ -95,14 +45,8 @@ const defaults = {
|
|
95
45
|
maxOutboundStopStreams: MAX_CONNECTIONS
|
96
46
|
}
|
97
47
|
|
98
|
-
class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements Startable, CircuitRelayService {
|
99
|
-
private readonly
|
100
|
-
private readonly peerStore: PeerStore
|
101
|
-
private readonly addressManager: AddressManager
|
102
|
-
private readonly peerId: PeerId
|
103
|
-
private readonly privateKey: PrivateKey
|
104
|
-
private readonly connectionManager: ConnectionManager
|
105
|
-
private readonly connectionGater: ConnectionGater
|
48
|
+
export class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements Startable, CircuitRelayService {
|
49
|
+
private readonly components: CircuitRelayServerComponents
|
106
50
|
private readonly reservationStore: ReservationStore
|
107
51
|
private started: boolean
|
108
52
|
private readonly hopTimeout: number
|
@@ -119,13 +63,7 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
119
63
|
super()
|
120
64
|
|
121
65
|
this.log = components.logger.forComponent('libp2p:circuit-relay:server')
|
122
|
-
this.
|
123
|
-
this.peerStore = components.peerStore
|
124
|
-
this.addressManager = components.addressManager
|
125
|
-
this.peerId = components.peerId
|
126
|
-
this.privateKey = components.privateKey
|
127
|
-
this.connectionManager = components.connectionManager
|
128
|
-
this.connectionGater = components.connectionGater
|
66
|
+
this.components = components
|
129
67
|
this.started = false
|
130
68
|
this.hopTimeout = init?.hopTimeout ?? DEFAULT_HOP_TIMEOUT
|
131
69
|
this.maxInboundHopStreams = init.maxInboundHopStreams
|
@@ -135,6 +73,8 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
135
73
|
|
136
74
|
this.shutdownController = new AbortController()
|
137
75
|
setMaxListeners(Infinity, this.shutdownController.signal)
|
76
|
+
|
77
|
+
this.onHop = this.onHop.bind(this)
|
138
78
|
}
|
139
79
|
|
140
80
|
readonly [Symbol.toStringTag] = '@libp2p/circuit-relay-v2-server'
|
@@ -151,11 +91,7 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
151
91
|
return
|
152
92
|
}
|
153
93
|
|
154
|
-
await this.registrar.handle(RELAY_V2_HOP_CODEC,
|
155
|
-
void this.onHop(data).catch(err => {
|
156
|
-
this.log.error(err)
|
157
|
-
})
|
158
|
-
}, {
|
94
|
+
await this.components.registrar.handle(RELAY_V2_HOP_CODEC, this.onHop, {
|
159
95
|
maxInboundStreams: this.maxInboundHopStreams,
|
160
96
|
maxOutboundStreams: this.maxOutboundHopStreams,
|
161
97
|
runOnLimitedConnection: true
|
@@ -170,16 +106,19 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
170
106
|
async stop (): Promise<void> {
|
171
107
|
this.reservationStore.clear()
|
172
108
|
this.shutdownController.abort()
|
173
|
-
await this.registrar.unhandle(RELAY_V2_HOP_CODEC)
|
109
|
+
await this.components.registrar.unhandle(RELAY_V2_HOP_CODEC)
|
174
110
|
|
175
111
|
this.started = false
|
176
112
|
}
|
177
113
|
|
178
|
-
async onHop (
|
114
|
+
async onHop (stream: Stream, connection: Connection): Promise<void> {
|
179
115
|
this.log('received circuit v2 hop protocol stream from %p', connection.remotePeer)
|
180
116
|
|
117
|
+
const signal = AbortSignal.timeout(this.hopTimeout)
|
118
|
+
setMaxListeners(Infinity, signal)
|
119
|
+
|
181
120
|
const options = {
|
182
|
-
signal
|
121
|
+
signal
|
183
122
|
}
|
184
123
|
const pbstr = pbStream(stream)
|
185
124
|
|
@@ -223,13 +162,13 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
223
162
|
const hopstr = stream.pb(HopMessage)
|
224
163
|
this.log('hop reserve request from %p', connection.remotePeer)
|
225
164
|
|
226
|
-
if (
|
165
|
+
if (Circuit.exactMatch(connection.remoteAddr)) {
|
227
166
|
this.log.error('relay reservation over circuit connection denied for peer: %p', connection.remotePeer)
|
228
167
|
await hopstr.write({ type: HopMessage.Type.STATUS, status: Status.PERMISSION_DENIED }, options)
|
229
168
|
return
|
230
169
|
}
|
231
170
|
|
232
|
-
if ((await this.connectionGater.denyInboundRelayReservation?.(connection.remotePeer)) === true) {
|
171
|
+
if ((await this.components.connectionGater.denyInboundRelayReservation?.(connection.remotePeer)) === true) {
|
233
172
|
this.log.error('reservation for %p denied by connection gater', connection.remotePeer)
|
234
173
|
await hopstr.write({ type: HopMessage.Type.STATUS, status: Status.PERMISSION_DENIED }, options)
|
235
174
|
return
|
@@ -247,12 +186,12 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
247
186
|
// result.expire is non-null if `ReservationStore.reserve` returns with status == OK
|
248
187
|
if (result.expire != null) {
|
249
188
|
const ttl = (result.expire * 1000) - Date.now()
|
250
|
-
await this.peerStore.merge(connection.remotePeer, {
|
189
|
+
await this.components.peerStore.merge(connection.remotePeer, {
|
251
190
|
tags: {
|
252
191
|
[RELAY_SOURCE_TAG]: { value: 1, ttl },
|
253
192
|
[KEEP_ALIVE_SOURCE_TAG]: { value: 1, ttl }
|
254
193
|
}
|
255
|
-
})
|
194
|
+
}, options)
|
256
195
|
}
|
257
196
|
|
258
197
|
await hopstr.write({
|
@@ -262,17 +201,20 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
262
201
|
limit: this.reservationStore.get(connection.remotePeer)?.limit
|
263
202
|
}, options)
|
264
203
|
this.log('sent confirmation response to %s', connection.remotePeer)
|
204
|
+
|
205
|
+
// close writable end of stream
|
206
|
+
await hopstr.unwrap().unwrap().close(options)
|
265
207
|
} catch (err) {
|
266
208
|
this.log.error('failed to send confirmation response to %p - %e', connection.remotePeer, err)
|
267
209
|
this.reservationStore.removeReservation(connection.remotePeer)
|
268
210
|
|
269
211
|
try {
|
270
|
-
await this.peerStore.merge(connection.remotePeer, {
|
212
|
+
await this.components.peerStore.merge(connection.remotePeer, {
|
271
213
|
tags: {
|
272
214
|
[RELAY_SOURCE_TAG]: undefined,
|
273
215
|
[KEEP_ALIVE_SOURCE_TAG]: undefined
|
274
216
|
}
|
275
|
-
})
|
217
|
+
}, options)
|
276
218
|
} catch (err) {
|
277
219
|
this.log.error('failed to untag relay source peer %p - %e', connection.remotePeer, err)
|
278
220
|
}
|
@@ -285,7 +227,7 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
285
227
|
): Promise<Reservation> {
|
286
228
|
const addrs = []
|
287
229
|
|
288
|
-
for (const relayAddr of this.addressManager.getAddresses()) {
|
230
|
+
for (const relayAddr of this.components.addressManager.getAddresses()) {
|
289
231
|
if (relayAddr.toString().includes('/p2p-circuit')) {
|
290
232
|
continue
|
291
233
|
}
|
@@ -295,9 +237,9 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
295
237
|
|
296
238
|
const envelope = await RecordEnvelope.seal(new ReservationVoucherRecord({
|
297
239
|
peer: remotePeer,
|
298
|
-
relay: this.peerId,
|
240
|
+
relay: this.components.peerId,
|
299
241
|
expiration: expire
|
300
|
-
}), this.privateKey)
|
242
|
+
}), this.components.privateKey)
|
301
243
|
|
302
244
|
return {
|
303
245
|
addrs,
|
@@ -307,7 +249,7 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
307
249
|
payloadType: envelope.payloadType,
|
308
250
|
payload: {
|
309
251
|
peer: remotePeer.toMultihash().bytes,
|
310
|
-
relay: this.peerId.toMultihash().bytes,
|
252
|
+
relay: this.components.peerId.toMultihash().bytes,
|
311
253
|
expiration: expire
|
312
254
|
},
|
313
255
|
signature: envelope.signature
|
@@ -318,7 +260,7 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
318
260
|
async handleConnect ({ stream, request, connection }: HopProtocolOptions, options: AbortOptions): Promise<void> {
|
319
261
|
const hopstr = stream.pb(HopMessage)
|
320
262
|
|
321
|
-
if (
|
263
|
+
if (Circuit.matches(connection.remoteAddr)) {
|
322
264
|
this.log.error('relay reservation over circuit connection denied for peer: %p', connection.remotePeer)
|
323
265
|
await hopstr.write({ type: HopMessage.Type.STATUS, status: Status.PERMISSION_DENIED }, options)
|
324
266
|
return
|
@@ -350,13 +292,13 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
350
292
|
return
|
351
293
|
}
|
352
294
|
|
353
|
-
if ((await this.connectionGater.denyOutboundRelayedConnection?.(connection.remotePeer, dstPeer)) === true) {
|
295
|
+
if ((await this.components.connectionGater.denyOutboundRelayedConnection?.(connection.remotePeer, dstPeer)) === true) {
|
354
296
|
this.log.error('hop connect for %p to %p denied by connection gater', connection.remotePeer, dstPeer)
|
355
297
|
await hopstr.write({ type: HopMessage.Type.STATUS, status: Status.PERMISSION_DENIED }, options)
|
356
298
|
return
|
357
299
|
}
|
358
300
|
|
359
|
-
const connections = this.connectionManager.getConnections(dstPeer)
|
301
|
+
const connections = this.components.connectionManager.getConnections(dstPeer)
|
360
302
|
|
361
303
|
if (connections.length === 0) {
|
362
304
|
this.log('hop connect denied for destination peer %p not having a connection for %p as there is no destination connection', dstPeer, connection.remotePeer)
|
@@ -389,12 +331,11 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
389
331
|
status: Status.OK,
|
390
332
|
limit: reservation?.limit
|
391
333
|
}, options)
|
392
|
-
const sourceStream = stream.unwrap()
|
393
334
|
|
394
335
|
this.log('connection from %p to %p established - merging streams', connection.remotePeer, dstPeer)
|
395
336
|
|
396
337
|
// Short circuit the two streams to create the relayed connection
|
397
|
-
createLimitedRelay(
|
338
|
+
createLimitedRelay(stream.unwrap(), destinationStream, this.shutdownController.signal, reservation, {
|
398
339
|
log: this.log
|
399
340
|
})
|
400
341
|
}
|
@@ -404,7 +345,7 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
404
345
|
*/
|
405
346
|
async stopHop ({ connection, request }: StopOptions, options: AbortOptions): Promise<Stream | undefined> {
|
406
347
|
this.log('starting circuit relay v2 stop request to %s', connection.remotePeer)
|
407
|
-
const stream = await connection.newStream(
|
348
|
+
const stream = await connection.newStream(RELAY_V2_STOP_CODEC, {
|
408
349
|
maxOutboundStreams: this.maxOutboundStopStreams,
|
409
350
|
runOnLimitedConnection: true,
|
410
351
|
...options
|
@@ -439,9 +380,3 @@ class CircuitRelayServer extends TypedEventEmitter<RelayServerEvents> implements
|
|
439
380
|
return this.reservationStore.reservations
|
440
381
|
}
|
441
382
|
}
|
442
|
-
|
443
|
-
export function circuitRelayServer (init: CircuitRelayServerInit = {}): (components: CircuitRelayServerComponents) => CircuitRelayService {
|
444
|
-
return (components) => {
|
445
|
-
return new CircuitRelayServer(components, init)
|
446
|
-
}
|
447
|
-
}
|
@@ -2,7 +2,7 @@ import { trackedPeerMap } from '@libp2p/peer-collections'
|
|
2
2
|
import { retimeableSignal } from 'retimeable-signal'
|
3
3
|
import { DEFAULT_DATA_LIMIT, DEFAULT_DURATION_LIMIT, DEFAULT_MAX_RESERVATION_STORE_SIZE, DEFAULT_MAX_RESERVATION_TTL } from '../constants.js'
|
4
4
|
import { Status } from '../pb/index.js'
|
5
|
-
import type { RelayReservation } from '../index.js'
|
5
|
+
import type { RelayReservation, ServerReservationStoreInit } from '../index.js'
|
6
6
|
import type { Limit } from '../pb/index.js'
|
7
7
|
import type { ComponentLogger, Logger, Metrics, PeerId } from '@libp2p/interface'
|
8
8
|
import type { PeerMap } from '@libp2p/peer-collections'
|
@@ -15,46 +15,6 @@ export interface ReservationStoreComponents {
|
|
15
15
|
metrics?: Metrics
|
16
16
|
}
|
17
17
|
|
18
|
-
export interface ReservationStoreInit {
|
19
|
-
/**
|
20
|
-
* maximum number of reservations allowed
|
21
|
-
*
|
22
|
-
* @default 15
|
23
|
-
*/
|
24
|
-
maxReservations?: number
|
25
|
-
|
26
|
-
/**
|
27
|
-
* interval after which stale reservations are cleared
|
28
|
-
*
|
29
|
-
* @default 300000
|
30
|
-
*/
|
31
|
-
reservationClearInterval?: number
|
32
|
-
|
33
|
-
/**
|
34
|
-
* apply default relay limits to a new reservation
|
35
|
-
*
|
36
|
-
* @default true
|
37
|
-
*/
|
38
|
-
applyDefaultLimit?: boolean
|
39
|
-
|
40
|
-
/**
|
41
|
-
* reservation ttl
|
42
|
-
*
|
43
|
-
* @default 7200000
|
44
|
-
*/
|
45
|
-
reservationTtl?: number
|
46
|
-
|
47
|
-
/**
|
48
|
-
* The maximum time a relayed connection can be open for
|
49
|
-
*/
|
50
|
-
defaultDurationLimit?: number
|
51
|
-
|
52
|
-
/**
|
53
|
-
* The maximum amount of data allowed to be transferred over a relayed connection
|
54
|
-
*/
|
55
|
-
defaultDataLimit?: bigint
|
56
|
-
}
|
57
|
-
|
58
18
|
export class ReservationStore {
|
59
19
|
public readonly reservations: PeerMap<RelayReservation>
|
60
20
|
private readonly maxReservations: number
|
@@ -64,7 +24,7 @@ export class ReservationStore {
|
|
64
24
|
private readonly defaultDataLimit: bigint
|
65
25
|
private readonly log: Logger
|
66
26
|
|
67
|
-
constructor (components: ReservationStoreComponents, init:
|
27
|
+
constructor (components: ReservationStoreComponents, init: ServerReservationStoreInit = {}) {
|
68
28
|
this.log = components.logger.forComponent('libp2p:circuit-relay:server:reservation-store')
|
69
29
|
this.maxReservations = init.maxReservations ?? DEFAULT_MAX_RESERVATION_STORE_SIZE
|
70
30
|
this.applyDefaultLimit = init.applyDefaultLimit !== false
|
@@ -1,30 +1,12 @@
|
|
1
|
-
import { PeerQueue } from '@libp2p/utils
|
1
|
+
import { PeerQueue } from '@libp2p/utils'
|
2
2
|
import { anySignal } from 'any-signal'
|
3
3
|
import { TypedEventEmitter, setMaxListeners } from 'main-event'
|
4
4
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
5
5
|
import {
|
6
6
|
RELAY_V2_HOP_CODEC
|
7
7
|
} from '../constants.js'
|
8
|
-
import type {
|
9
|
-
import type {
|
10
|
-
|
11
|
-
export interface RelayDiscoveryEvents {
|
12
|
-
'relay:discover': CustomEvent<PeerId>
|
13
|
-
}
|
14
|
-
|
15
|
-
export interface RelayDiscoveryComponents {
|
16
|
-
peerStore: PeerStore
|
17
|
-
connectionManager: ConnectionManager
|
18
|
-
transportManager: TransportManager
|
19
|
-
registrar: Registrar
|
20
|
-
logger: ComponentLogger
|
21
|
-
randomWalk: RandomWalk
|
22
|
-
events: TypedEventTarget<Libp2pEvents>
|
23
|
-
}
|
24
|
-
|
25
|
-
export interface RelayDiscoveryInit {
|
26
|
-
filter?: TopologyFilter
|
27
|
-
}
|
8
|
+
import type { RelayDiscoveryComponents, RelayDiscoveryEvents, RelayDiscoveryInit } from '../index.ts'
|
9
|
+
import type { Logger, Peer, PeerId, PeerInfo, Startable, TopologyFilter } from '@libp2p/interface'
|
28
10
|
|
29
11
|
/**
|
30
12
|
* ReservationManager automatically makes a circuit v2 reservation on any connected
|
@@ -221,7 +203,7 @@ export class RelayDiscovery extends TypedEventEmitter<RelayDiscoveryEvents> impl
|
|
221
203
|
}
|
222
204
|
|
223
205
|
onPeer (evt: CustomEvent<PeerInfo>): void {
|
224
|
-
this.log.trace('maybe dialing discovered peer %p
|
206
|
+
this.log.trace('maybe dialing discovered peer %p', evt.detail.id)
|
225
207
|
|
226
208
|
this.maybeDialPeer(evt)
|
227
209
|
.catch(err => {
|