libp2p 0.42.2-593deefe → 0.42.2-5e63ee2d
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 +30 -30
- package/dist/src/address-manager/index.d.ts +1 -10
- package/dist/src/address-manager/index.d.ts.map +1 -1
- package/dist/src/address-manager/index.js +46 -29
- package/dist/src/address-manager/index.js.map +1 -1
- package/dist/src/autonat/constants.d.ts +4 -0
- package/dist/src/autonat/constants.d.ts.map +1 -0
- package/dist/src/autonat/constants.js +4 -0
- package/dist/src/autonat/constants.js.map +1 -0
- package/dist/src/autonat/index.d.ts +64 -0
- package/dist/src/autonat/index.d.ts.map +1 -0
- package/dist/src/autonat/index.js +417 -0
- package/dist/src/autonat/index.js.map +1 -0
- package/dist/src/autonat/pb/index.d.ts +57 -0
- package/dist/src/autonat/pb/index.d.ts.map +1 -0
- package/dist/src/autonat/pb/index.js +250 -0
- package/dist/src/autonat/pb/index.js.map +1 -0
- package/dist/src/circuit/constants.d.ts +29 -3
- package/dist/src/circuit/constants.d.ts.map +1 -1
- package/dist/src/circuit/constants.js +32 -5
- package/dist/src/circuit/constants.js.map +1 -1
- package/dist/src/circuit/index.d.ts +16 -61
- package/dist/src/circuit/index.d.ts.map +1 -1
- package/dist/src/circuit/index.js +2 -1
- package/dist/src/circuit/index.js.map +1 -1
- package/dist/src/circuit/server/advert-service.d.ts +43 -0
- package/dist/src/circuit/server/advert-service.d.ts.map +1 -0
- package/dist/src/circuit/server/advert-service.js +69 -0
- package/dist/src/circuit/server/advert-service.js.map +1 -0
- package/dist/src/circuit/server/index.d.ts +60 -0
- package/dist/src/circuit/server/index.d.ts.map +1 -0
- package/dist/src/circuit/server/index.js +287 -0
- package/dist/src/circuit/server/index.js.map +1 -0
- package/dist/src/circuit/{reservation-store.d.ts → server/reservation-store.d.ts} +17 -10
- package/dist/src/circuit/server/reservation-store.d.ts.map +1 -0
- package/dist/src/circuit/server/reservation-store.js +57 -0
- package/dist/src/circuit/server/reservation-store.js.map +1 -0
- package/dist/src/circuit/server/reservation-voucher.d.ts.map +1 -0
- package/dist/src/circuit/{reservation-voucher.js → server/reservation-voucher.js} +1 -1
- package/dist/src/circuit/server/reservation-voucher.js.map +1 -0
- package/dist/src/circuit/transport/discovery.d.ts +45 -0
- package/dist/src/circuit/transport/discovery.d.ts.map +1 -0
- package/dist/src/circuit/transport/discovery.js +82 -0
- package/dist/src/circuit/transport/discovery.js.map +1 -0
- package/dist/src/circuit/transport/index.d.ts +33 -0
- package/dist/src/circuit/transport/index.d.ts.map +1 -0
- package/dist/src/circuit/transport/index.js +225 -0
- package/dist/src/circuit/transport/index.js.map +1 -0
- package/dist/src/circuit/transport/listener.d.ts +9 -0
- package/dist/src/circuit/transport/listener.d.ts.map +1 -0
- package/dist/src/circuit/transport/listener.js +76 -0
- package/dist/src/circuit/transport/listener.js.map +1 -0
- package/dist/src/circuit/transport/reservation-store.d.ts +60 -0
- package/dist/src/circuit/transport/reservation-store.d.ts.map +1 -0
- package/dist/src/circuit/transport/reservation-store.js +165 -0
- package/dist/src/circuit/transport/reservation-store.js.map +1 -0
- package/dist/src/circuit/utils.d.ts +4 -2
- package/dist/src/circuit/utils.d.ts.map +1 -1
- package/dist/src/circuit/utils.js +75 -102
- package/dist/src/circuit/utils.js.map +1 -1
- package/dist/src/components.d.ts +2 -1
- package/dist/src/components.d.ts.map +1 -1
- package/dist/src/components.js.map +1 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +17 -20
- package/dist/src/config.js.map +1 -1
- package/dist/src/connection/index.d.ts +2 -2
- package/dist/src/connection/index.d.ts.map +1 -1
- package/dist/src/connection/index.js +1 -1
- package/dist/src/connection/index.js.map +1 -1
- package/dist/src/connection-manager/auto-dialler.d.ts +0 -4
- package/dist/src/connection-manager/auto-dialler.d.ts.map +1 -1
- package/dist/src/connection-manager/auto-dialler.js +0 -9
- package/dist/src/connection-manager/auto-dialler.js.map +1 -1
- package/dist/src/connection-manager/dialer/dial-request.js +1 -1
- package/dist/src/connection-manager/dialer/dial-request.js.map +1 -1
- package/dist/src/connection-manager/dialer/index.d.ts +2 -1
- package/dist/src/connection-manager/dialer/index.d.ts.map +1 -1
- package/dist/src/connection-manager/dialer/index.js +3 -3
- package/dist/src/connection-manager/dialer/index.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +0 -4
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +1 -1
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/connection-manager/latency-monitor.d.ts.map +1 -1
- package/dist/src/connection-manager/latency-monitor.js +1 -1
- package/dist/src/connection-manager/latency-monitor.js.map +1 -1
- package/dist/src/connection-manager/visibility-change-emitter.d.ts.map +1 -1
- package/dist/src/content-routing/index.d.ts +6 -4
- package/dist/src/content-routing/index.d.ts.map +1 -1
- package/dist/src/content-routing/index.js +1 -1
- package/dist/src/content-routing/index.js.map +1 -1
- package/dist/src/content-routing/utils.d.ts +3 -3
- package/dist/src/content-routing/utils.d.ts.map +1 -1
- package/dist/src/dht/dht-content-routing.d.ts +2 -1
- package/dist/src/dht/dht-content-routing.d.ts.map +1 -1
- package/dist/src/dht/dht-content-routing.js.map +1 -1
- package/dist/src/dht/dht-peer-routing.d.ts +3 -2
- package/dist/src/dht/dht-peer-routing.d.ts.map +1 -1
- package/dist/src/dht/dht-peer-routing.js.map +1 -1
- package/dist/src/dht/dummy-dht.d.ts +1 -1
- package/dist/src/dht/dummy-dht.d.ts.map +1 -1
- package/dist/src/fetch/index.d.ts.map +1 -1
- package/dist/src/identify/index.d.ts +3 -1
- package/dist/src/identify/index.d.ts.map +1 -1
- package/dist/src/identify/index.js +12 -7
- package/dist/src/identify/index.js.map +1 -1
- package/dist/src/index.d.ts +13 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/insecure/index.d.ts.map +1 -1
- package/dist/src/insecure/index.js.map +1 -1
- package/dist/src/libp2p.d.ts +6 -4
- package/dist/src/libp2p.d.ts.map +1 -1
- package/dist/src/libp2p.js +19 -28
- package/dist/src/libp2p.js.map +1 -1
- package/dist/src/nat-manager.d.ts.map +1 -1
- package/dist/src/nat-manager.js +3 -1
- package/dist/src/nat-manager.js.map +1 -1
- package/dist/src/peer-record-updater.d.ts.map +1 -1
- package/dist/src/peer-routing.d.ts.map +1 -1
- package/dist/src/ping/index.d.ts.map +1 -1
- package/dist/src/pnet/crypto.d.ts +1 -1
- package/dist/src/pnet/crypto.d.ts.map +1 -1
- package/dist/src/pnet/crypto.js +1 -1
- package/dist/src/pnet/crypto.js.map +1 -1
- package/dist/src/pnet/key-generator.d.ts.map +1 -1
- package/dist/src/registrar.d.ts.map +1 -1
- package/dist/src/transport-manager.d.ts.map +1 -1
- package/dist/src/transport-manager.js +1 -1
- package/dist/src/transport-manager.js.map +1 -1
- package/dist/src/upgrader.d.ts +2 -1
- package/dist/src/upgrader.d.ts.map +1 -1
- package/dist/src/upgrader.js +19 -14
- package/dist/src/upgrader.js.map +1 -1
- package/package.json +23 -18
- package/src/address-manager/index.ts +62 -35
- package/src/autonat/constants.ts +4 -0
- package/src/autonat/index.ts +567 -0
- package/src/autonat/pb/index.proto +35 -0
- package/src/autonat/pb/index.ts +320 -0
- package/src/circuit/constants.ts +40 -5
- package/src/circuit/index.ts +17 -67
- package/src/circuit/server/advert-service.ts +108 -0
- package/src/circuit/server/index.ts +421 -0
- package/src/circuit/server/reservation-store.ts +111 -0
- package/src/circuit/{reservation-voucher.ts → server/reservation-voucher.ts} +3 -3
- package/src/circuit/transport/discovery.ts +127 -0
- package/src/circuit/transport/index.ts +325 -0
- package/src/circuit/transport/listener.ts +99 -0
- package/src/circuit/transport/reservation-store.ts +249 -0
- package/src/circuit/utils.ts +78 -115
- package/src/components.ts +9 -8
- package/src/config.ts +17 -20
- package/src/connection/index.ts +7 -7
- package/src/connection-manager/auto-dialler.ts +4 -20
- package/src/connection-manager/dialer/dial-request.ts +1 -1
- package/src/connection-manager/dialer/index.ts +10 -9
- package/src/connection-manager/index.ts +14 -19
- package/src/connection-manager/latency-monitor.ts +9 -9
- package/src/connection-manager/visibility-change-emitter.ts +4 -4
- package/src/content-routing/index.ts +10 -8
- package/src/content-routing/utils.ts +3 -3
- package/src/dht/dht-content-routing.ts +3 -2
- package/src/dht/dht-peer-routing.ts +3 -2
- package/src/dht/dummy-dht.ts +1 -1
- package/src/fetch/index.ts +7 -7
- package/src/identify/index.ts +22 -17
- package/src/index.ts +14 -7
- package/src/insecure/index.ts +2 -1
- package/src/libp2p.ts +33 -41
- package/src/nat-manager.ts +9 -7
- package/src/peer-record-updater.ts +4 -4
- package/src/peer-routing.ts +4 -4
- package/src/ping/index.ts +4 -4
- package/src/pnet/crypto.ts +3 -3
- package/src/pnet/key-generator.ts +1 -1
- package/src/registrar.ts +8 -8
- package/src/transport-manager.ts +10 -10
- package/src/upgrader.ts +20 -19
- package/src/version.ts +1 -1
- package/dist/src/circuit/client.d.ts +0 -81
- package/dist/src/circuit/client.d.ts.map +0 -1
- package/dist/src/circuit/client.js +0 -285
- package/dist/src/circuit/client.js.map +0 -1
- package/dist/src/circuit/hop.d.ts +0 -23
- package/dist/src/circuit/hop.d.ts.map +0 -1
- package/dist/src/circuit/hop.js +0 -167
- package/dist/src/circuit/hop.js.map +0 -1
- package/dist/src/circuit/interfaces.d.ts +0 -27
- package/dist/src/circuit/interfaces.d.ts.map +0 -1
- package/dist/src/circuit/interfaces.js +0 -2
- package/dist/src/circuit/interfaces.js.map +0 -1
- package/dist/src/circuit/listener.d.ts +0 -9
- package/dist/src/circuit/listener.d.ts.map +0 -1
- package/dist/src/circuit/listener.js +0 -62
- package/dist/src/circuit/listener.js.map +0 -1
- package/dist/src/circuit/multicodec.d.ts +0 -3
- package/dist/src/circuit/multicodec.d.ts.map +0 -1
- package/dist/src/circuit/multicodec.js +0 -3
- package/dist/src/circuit/multicodec.js.map +0 -1
- package/dist/src/circuit/relay.d.ts +0 -34
- package/dist/src/circuit/relay.d.ts.map +0 -1
- package/dist/src/circuit/relay.js +0 -61
- package/dist/src/circuit/relay.js.map +0 -1
- package/dist/src/circuit/reservation-store.d.ts.map +0 -1
- package/dist/src/circuit/reservation-store.js +0 -59
- package/dist/src/circuit/reservation-store.js.map +0 -1
- package/dist/src/circuit/reservation-voucher.d.ts.map +0 -1
- package/dist/src/circuit/reservation-voucher.js.map +0 -1
- package/dist/src/circuit/stop.d.ts +0 -19
- package/dist/src/circuit/stop.d.ts.map +0 -1
- package/dist/src/circuit/stop.js +0 -67
- package/dist/src/circuit/stop.js.map +0 -1
- package/dist/src/circuit/transport.d.ts +0 -66
- package/dist/src/circuit/transport.d.ts.map +0 -1
- package/dist/src/circuit/transport.js +0 -238
- package/dist/src/circuit/transport.js.map +0 -1
- package/src/circuit/client.ts +0 -381
- package/src/circuit/hop.ts +0 -210
- package/src/circuit/interfaces.ts +0 -28
- package/src/circuit/listener.ts +0 -83
- package/src/circuit/multicodec.ts +0 -3
- package/src/circuit/relay.ts +0 -87
- package/src/circuit/reservation-store.ts +0 -106
- package/src/circuit/stop.ts +0 -92
- package/src/circuit/transport.ts +0 -313
- /package/dist/src/circuit/{reservation-voucher.d.ts → server/reservation-voucher.d.ts} +0 -0
package/src/circuit/client.ts
DELETED
|
@@ -1,381 +0,0 @@
|
|
|
1
|
-
import { logger } from '@libp2p/logger'
|
|
2
|
-
import { RELAY_V2_HOP_CODEC } from './multicodec.js'
|
|
3
|
-
import { getExpiration, namespaceToCid } from './utils.js'
|
|
4
|
-
import {
|
|
5
|
-
CIRCUIT_PROTO_CODE,
|
|
6
|
-
DEFAULT_MAX_RESERVATIONS,
|
|
7
|
-
RELAY_RENDEZVOUS_NS
|
|
8
|
-
} from './constants.js'
|
|
9
|
-
import type { PeerId } from '@libp2p/interface-peer-id'
|
|
10
|
-
import type { AddressSorter } from '@libp2p/interface-peer-store'
|
|
11
|
-
import type { Connection } from '@libp2p/interface-connection'
|
|
12
|
-
import sort from 'it-sort'
|
|
13
|
-
import all from 'it-all'
|
|
14
|
-
import { pipe } from 'it-pipe'
|
|
15
|
-
import { publicAddressesFirst } from '@libp2p/utils/address-sort'
|
|
16
|
-
import { reserve } from './hop.js'
|
|
17
|
-
import { EventEmitter, CustomEvent } from '@libp2p/interfaces/events'
|
|
18
|
-
import type { Startable } from '@libp2p/interfaces/startable'
|
|
19
|
-
import type { Components } from '../components.js'
|
|
20
|
-
import type { RelayReservationManagerConfig } from './index.js'
|
|
21
|
-
import { PeerSet, PeerMap, PeerList } from '@libp2p/peer-collections'
|
|
22
|
-
|
|
23
|
-
const log = logger('libp2p:circuit:client')
|
|
24
|
-
|
|
25
|
-
const noop = () => {}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* CircuitServiceInit initializes the circuit service using values
|
|
29
|
-
* from the provided config and an @type{AddressSorter}.
|
|
30
|
-
*/
|
|
31
|
-
export interface CircuitServiceInit extends RelayReservationManagerConfig {
|
|
32
|
-
/**
|
|
33
|
-
* Allows prioritizing addresses from the peerstore for dialing. The
|
|
34
|
-
* default behavior is to prioritise public addresses.
|
|
35
|
-
*/
|
|
36
|
-
addressSorter?: AddressSorter
|
|
37
|
-
/**
|
|
38
|
-
* A callback to invoke when an error occurs in the circuit service.
|
|
39
|
-
*/
|
|
40
|
-
onError?: (error: Error) => void
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface RelayReservationManagerEvents {
|
|
44
|
-
'relay:reservation': CustomEvent
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* ReservationManager automatically makes a circuit v2 reservation on any connected
|
|
49
|
-
* peers that support the circuit v2 HOP protocol.
|
|
50
|
-
*/
|
|
51
|
-
export class RelayReservationManager extends EventEmitter<RelayReservationManagerEvents> implements Startable {
|
|
52
|
-
private readonly components: Components
|
|
53
|
-
private readonly addressSorter: AddressSorter
|
|
54
|
-
private readonly maxReservations: number
|
|
55
|
-
private readonly relays: PeerSet
|
|
56
|
-
private readonly reservationMap: PeerMap<ReturnType<typeof setTimeout>>
|
|
57
|
-
private readonly onError: (error: Error) => void
|
|
58
|
-
private started: boolean
|
|
59
|
-
|
|
60
|
-
constructor (components: Components, init: CircuitServiceInit) {
|
|
61
|
-
super()
|
|
62
|
-
this.started = false
|
|
63
|
-
this.components = components
|
|
64
|
-
this.addressSorter = init.addressSorter ?? publicAddressesFirst
|
|
65
|
-
this.maxReservations = init.maxReservations ?? DEFAULT_MAX_RESERVATIONS
|
|
66
|
-
this.relays = new PeerSet()
|
|
67
|
-
this.reservationMap = new PeerMap()
|
|
68
|
-
this.onError = init.onError ?? noop
|
|
69
|
-
|
|
70
|
-
this._onProtocolChange = this._onProtocolChange.bind(this)
|
|
71
|
-
this._onPeerDisconnected = this._onPeerDisconnected.bind(this)
|
|
72
|
-
this._onPeerConnect = this._onPeerConnect.bind(this)
|
|
73
|
-
|
|
74
|
-
this.components.peerStore.addEventListener('change:protocols', (evt) => {
|
|
75
|
-
void this._onProtocolChange(evt.detail).catch(err => {
|
|
76
|
-
log.error('handling protocol change failed', err)
|
|
77
|
-
})
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
this.components.connectionManager.addEventListener('peer:disconnect', this._onPeerDisconnected)
|
|
81
|
-
this.components.connectionManager.addEventListener('peer:connect', this._onPeerConnect)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
isStarted () {
|
|
85
|
-
return this.started
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
start () {
|
|
89
|
-
void this._listenOnAvailableHopRelays().catch(err => { log.error('error listening on relays', err) })
|
|
90
|
-
this.started = true
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async stop () {
|
|
94
|
-
this.reservationMap.forEach((timer) => clearTimeout(timer))
|
|
95
|
-
this.reservationMap.clear()
|
|
96
|
-
this.relays.clear()
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Check if a peer supports the relay protocol.
|
|
101
|
-
* If the protocol is not supported, check if it was supported before and remove it as a listen relay.
|
|
102
|
-
* If the protocol is supported, check if the peer supports **HOP** and add it as a listener if
|
|
103
|
-
* inside the threshold.
|
|
104
|
-
*/
|
|
105
|
-
async _onProtocolChange ({ peerId, protocols }: {peerId: PeerId, protocols: string[]}) {
|
|
106
|
-
if (peerId.equals(this.components.peerId)) {
|
|
107
|
-
return
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Check if it has the protocol
|
|
111
|
-
const hasProtocol = protocols.includes(RELAY_V2_HOP_CODEC)
|
|
112
|
-
log.trace('Peer %p protocol change %p', peerId, this.components.peerId)
|
|
113
|
-
|
|
114
|
-
// If no protocol, check if we were keeping the peer before as a listenRelay
|
|
115
|
-
if (!hasProtocol) {
|
|
116
|
-
if (this.relays.has(peerId)) {
|
|
117
|
-
await this._removeListenRelay(peerId)
|
|
118
|
-
}
|
|
119
|
-
return
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (this.relays.has(peerId)) {
|
|
123
|
-
return
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// If protocol, check if can hop, store info in the metadataBook and listen on it
|
|
127
|
-
try {
|
|
128
|
-
const connections = this.components.connectionManager.getConnections(peerId)
|
|
129
|
-
|
|
130
|
-
// if no connections, try to listen on relay
|
|
131
|
-
if (connections.length === 0) {
|
|
132
|
-
void this._tryToListenOnRelay(peerId)
|
|
133
|
-
return
|
|
134
|
-
}
|
|
135
|
-
const connection = connections[0]
|
|
136
|
-
|
|
137
|
-
// Do not hop on a relayed connection
|
|
138
|
-
if (connection.remoteAddr.protoCodes().includes(CIRCUIT_PROTO_CODE)) {
|
|
139
|
-
log('relayed connection to %p will not be used to hop on', peerId)
|
|
140
|
-
return
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
await this._addListenRelay(connection, peerId)
|
|
144
|
-
} catch (err: any) {
|
|
145
|
-
log.error('could not add %p as relay', peerId)
|
|
146
|
-
this.onError(err)
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Handle case when peer connects. If we already have the peer in the protobook,
|
|
152
|
-
* we treat this event as an `onProtocolChange`.
|
|
153
|
-
*/
|
|
154
|
-
_onPeerConnect ({ detail: connection }: CustomEvent<Connection>) {
|
|
155
|
-
void this.components.peerStore.protoBook.get(connection.remotePeer)
|
|
156
|
-
.then((protocols) => {
|
|
157
|
-
void this._onProtocolChange({ peerId: connection.remotePeer, protocols })
|
|
158
|
-
.catch((err) => log.error('handling reconnect failed', err))
|
|
159
|
-
},
|
|
160
|
-
(err) => {
|
|
161
|
-
// this is not necessarily an error as we will only have the protocols stored
|
|
162
|
-
// in case of a reconnect
|
|
163
|
-
log.trace('could not fetch protocols for peer: %p', connection.remotePeer, err)
|
|
164
|
-
})
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Peer disconnects
|
|
169
|
-
*/
|
|
170
|
-
_onPeerDisconnected (evt: CustomEvent<Connection>) {
|
|
171
|
-
const connection = evt.detail
|
|
172
|
-
const peerId = connection.remotePeer
|
|
173
|
-
clearTimeout(this.reservationMap.get(peerId))
|
|
174
|
-
this.reservationMap.delete(peerId)
|
|
175
|
-
|
|
176
|
-
// Not listening on this relay
|
|
177
|
-
if (!this.relays.has(peerId)) {
|
|
178
|
-
return
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
this._removeListenRelay(peerId).catch(err => {
|
|
182
|
-
log.error(err)
|
|
183
|
-
})
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Attempt to listen on the given relay connection
|
|
188
|
-
*/
|
|
189
|
-
async _addListenRelay (connection: Connection, peerId: PeerId): Promise<void> {
|
|
190
|
-
log.trace('peerId %p is being added as relay', peerId)
|
|
191
|
-
try {
|
|
192
|
-
// Check if already enough relay reservations
|
|
193
|
-
if (this.relays.size >= this.maxReservations) {
|
|
194
|
-
return
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
await this.createOrRefreshReservation(peerId)
|
|
198
|
-
|
|
199
|
-
// Get peer known addresses and sort them with public addresses first
|
|
200
|
-
const remoteAddrs = await pipe(
|
|
201
|
-
await this.components.peerStore.addressBook.get(connection.remotePeer),
|
|
202
|
-
(source) => sort(source, this.addressSorter),
|
|
203
|
-
async (source) => await all(source)
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
// Attempt to listen on relay
|
|
207
|
-
const result = await Promise.all(
|
|
208
|
-
remoteAddrs.map(async addr => {
|
|
209
|
-
let multiaddr = addr.multiaddr
|
|
210
|
-
|
|
211
|
-
if (multiaddr.getPeerId() == null) {
|
|
212
|
-
multiaddr = multiaddr.encapsulate(`/p2p/${connection.remotePeer.toString()}`)
|
|
213
|
-
}
|
|
214
|
-
multiaddr = multiaddr.encapsulate('/p2p-circuit')
|
|
215
|
-
try {
|
|
216
|
-
// Announce multiaddrs will update on listen success by TransportManager event being triggered
|
|
217
|
-
await this.components.transportManager.listen([multiaddr])
|
|
218
|
-
return true
|
|
219
|
-
} catch (err: any) {
|
|
220
|
-
log.error('error listening on circuit address', multiaddr, err)
|
|
221
|
-
this.onError(err)
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
return false
|
|
225
|
-
})
|
|
226
|
-
)
|
|
227
|
-
|
|
228
|
-
if (result.includes(true)) {
|
|
229
|
-
this.relays.add(peerId)
|
|
230
|
-
}
|
|
231
|
-
} catch (err: any) {
|
|
232
|
-
this.relays.delete(peerId)
|
|
233
|
-
log.error('error adding relay for %p %s', peerId, err)
|
|
234
|
-
this.onError(err)
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Remove listen relay
|
|
240
|
-
*/
|
|
241
|
-
async _removeListenRelay (PeerId: PeerId) {
|
|
242
|
-
const recheck = this.relays.has(PeerId)
|
|
243
|
-
this.relays.delete(PeerId)
|
|
244
|
-
if (recheck) {
|
|
245
|
-
// TODO: this should be responsibility of the connMgr
|
|
246
|
-
await this._listenOnAvailableHopRelays(new PeerList([PeerId]))
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Try to listen on available hop relay connections.
|
|
252
|
-
* The following order will happen while we do not have enough relays.
|
|
253
|
-
* 1. Check the metadata store for known relays, try to listen on the ones we are already connected.
|
|
254
|
-
* 2. Dial and try to listen on the peers we know that support hop but are not connected.
|
|
255
|
-
* 3. Search the network.
|
|
256
|
-
*/
|
|
257
|
-
async _listenOnAvailableHopRelays (peersToIgnore: PeerList = new PeerList([])) {
|
|
258
|
-
// Check if already listening on enough relays
|
|
259
|
-
if (this.relays.size >= this.maxReservations) {
|
|
260
|
-
return
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const knownHopsToDial: PeerId[] = []
|
|
264
|
-
const peers = (await this.components.peerStore.all())
|
|
265
|
-
// filter by a list of peers supporting RELAY_V2_HOP and ones we are not listening on
|
|
266
|
-
.filter(({ id, protocols }) =>
|
|
267
|
-
protocols.includes(RELAY_V2_HOP_CODEC) && !this.relays.has(id) && !peersToIgnore.includes(id)
|
|
268
|
-
)
|
|
269
|
-
.map(({ id }) => {
|
|
270
|
-
const connections = this.components.connectionManager.getConnections(id)
|
|
271
|
-
if (connections.length === 0) {
|
|
272
|
-
knownHopsToDial.push(id)
|
|
273
|
-
return [id, null]
|
|
274
|
-
}
|
|
275
|
-
return [id, connections[0]]
|
|
276
|
-
})
|
|
277
|
-
.sort(() => Math.random() - 0.5)
|
|
278
|
-
|
|
279
|
-
// Check if we have known hop peers to use and attempt to listen on the already connected
|
|
280
|
-
for (const [id, conn] of peers) {
|
|
281
|
-
await this._addListenRelay(conn as Connection, id as PeerId)
|
|
282
|
-
|
|
283
|
-
// Check if already listening on enough relays
|
|
284
|
-
if (this.relays.size >= this.maxReservations) {
|
|
285
|
-
return
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Try to listen on known peers that are not connected
|
|
290
|
-
for (const peerId of knownHopsToDial) {
|
|
291
|
-
// Check if already listening on enough relays
|
|
292
|
-
if (this.relays.size >= this.maxReservations) {
|
|
293
|
-
return
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
await this._tryToListenOnRelay(peerId)
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// Try to find relays to hop on the network
|
|
300
|
-
try {
|
|
301
|
-
const cid = await namespaceToCid(RELAY_RENDEZVOUS_NS)
|
|
302
|
-
for await (const provider of this.components.contentRouting.findProviders(cid)) {
|
|
303
|
-
if (
|
|
304
|
-
provider.multiaddrs.length > 0 &&
|
|
305
|
-
!provider.id.equals(this.components.peerId)
|
|
306
|
-
) {
|
|
307
|
-
const peerId = provider.id
|
|
308
|
-
|
|
309
|
-
await this.components.peerStore.addressBook.add(peerId, provider.multiaddrs)
|
|
310
|
-
await this._tryToListenOnRelay(peerId)
|
|
311
|
-
|
|
312
|
-
// Check if already listening on enough relays
|
|
313
|
-
if (this.relays.size >= this.maxReservations) {
|
|
314
|
-
return
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
} catch (err: any) {
|
|
319
|
-
log.error('failed when finding relays on the network', err)
|
|
320
|
-
this.onError(err)
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
async _tryToListenOnRelay (peerId: PeerId) {
|
|
325
|
-
try {
|
|
326
|
-
if (peerId.equals(this.components.peerId)) {
|
|
327
|
-
log.trace('Skipping dialling self %p', peerId.toString())
|
|
328
|
-
return
|
|
329
|
-
}
|
|
330
|
-
const connection = await this.components.connectionManager.openConnection(peerId)
|
|
331
|
-
await this._addListenRelay(connection, peerId)
|
|
332
|
-
} catch (err: any) {
|
|
333
|
-
log.error('Could not connect and listen on relay %p', peerId, err)
|
|
334
|
-
this.onError(err)
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
private readonly createOrRefreshReservation = async (peerId: PeerId) => {
|
|
339
|
-
try {
|
|
340
|
-
const connections = this.components.connectionManager.getConnections(peerId)
|
|
341
|
-
|
|
342
|
-
if (connections.length === 0) {
|
|
343
|
-
throw new Error('No connections to peer')
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
const connection = connections[0]
|
|
347
|
-
|
|
348
|
-
const reservation = await reserve(connection)
|
|
349
|
-
|
|
350
|
-
const refreshReservation = this.createOrRefreshReservation
|
|
351
|
-
|
|
352
|
-
if (reservation != null) {
|
|
353
|
-
log('new reservation on %p', peerId)
|
|
354
|
-
|
|
355
|
-
// clear any previous timeouts
|
|
356
|
-
const previous = this.reservationMap.get(peerId)
|
|
357
|
-
if (previous != null) {
|
|
358
|
-
clearTimeout(previous)
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
const timeout = setTimeout(
|
|
362
|
-
(peerId: PeerId) => {
|
|
363
|
-
void refreshReservation(peerId).catch(err => {
|
|
364
|
-
log.error('error refreshing reservation for %p', peerId, err)
|
|
365
|
-
})
|
|
366
|
-
},
|
|
367
|
-
Math.max(getExpiration(reservation.expire) - 100, 0),
|
|
368
|
-
peerId
|
|
369
|
-
)
|
|
370
|
-
this.reservationMap.set(
|
|
371
|
-
peerId,
|
|
372
|
-
timeout
|
|
373
|
-
)
|
|
374
|
-
this.dispatchEvent(new CustomEvent<unknown>('relay:reservation'))
|
|
375
|
-
}
|
|
376
|
-
} catch (err: any) {
|
|
377
|
-
log.error(err)
|
|
378
|
-
await this._removeListenRelay(peerId)
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
}
|
package/src/circuit/hop.ts
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import type { PeerId } from '@libp2p/interface-peer-id'
|
|
2
|
-
import { RecordEnvelope } from '@libp2p/peer-record'
|
|
3
|
-
import { logger } from '@libp2p/logger'
|
|
4
|
-
import type { Connection, Stream } from '@libp2p/interface-connection'
|
|
5
|
-
import { HopMessage, Limit, Reservation, Status, StopMessage } from './pb/index.js'
|
|
6
|
-
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
7
|
-
import { multiaddr } from '@multiformats/multiaddr'
|
|
8
|
-
import type { Acl, ReservationStore } from './interfaces.js'
|
|
9
|
-
import { RELAY_V2_HOP_CODEC } from './multicodec.js'
|
|
10
|
-
import { stop } from './stop.js'
|
|
11
|
-
import { ReservationVoucherRecord } from './reservation-voucher.js'
|
|
12
|
-
import { peerIdFromBytes } from '@libp2p/peer-id'
|
|
13
|
-
import type { ConnectionManager } from '@libp2p/interface-connection-manager'
|
|
14
|
-
import type { ProtobufStream } from 'it-pb-stream'
|
|
15
|
-
import { pbStream } from 'it-pb-stream'
|
|
16
|
-
import { CIRCUIT_PROTO_CODE, RELAY_DESTINATION_TAG } from './constants.js'
|
|
17
|
-
import type { PeerStore } from '@libp2p/interface-peer-store'
|
|
18
|
-
import { createLimitedRelay } from './utils.js'
|
|
19
|
-
|
|
20
|
-
const log = logger('libp2p:circuit:v2:hop')
|
|
21
|
-
|
|
22
|
-
export interface HopProtocolOptions {
|
|
23
|
-
connection: Connection
|
|
24
|
-
request: HopMessage
|
|
25
|
-
stream: ProtobufStream<Stream>
|
|
26
|
-
relayPeer: PeerId
|
|
27
|
-
relayAddrs: Multiaddr[]
|
|
28
|
-
limit?: Limit
|
|
29
|
-
acl?: Acl
|
|
30
|
-
reservationStore: ReservationStore
|
|
31
|
-
connectionManager: ConnectionManager
|
|
32
|
-
peerStore: PeerStore
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export async function handleHopProtocol (options: HopProtocolOptions): Promise<void> {
|
|
36
|
-
const { stream, request } = options
|
|
37
|
-
log('received hop message')
|
|
38
|
-
switch (request.type) {
|
|
39
|
-
case HopMessage.Type.RESERVE: await handleReserve(options); break
|
|
40
|
-
case HopMessage.Type.CONNECT: await handleConnect(options); break
|
|
41
|
-
default: {
|
|
42
|
-
log.error('invalid hop request type %s via peer %s', options.request.type, options.connection.remotePeer)
|
|
43
|
-
stream.pb(HopMessage).write({ type: HopMessage.Type.STATUS, status: Status.UNEXPECTED_MESSAGE })
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function reserve (connection: Connection): Promise<Reservation> {
|
|
49
|
-
log('requesting reservation from %s', connection.remotePeer)
|
|
50
|
-
const stream = await connection.newStream([RELAY_V2_HOP_CODEC])
|
|
51
|
-
const pbstr = pbStream(stream)
|
|
52
|
-
const hopstr = pbstr.pb(HopMessage)
|
|
53
|
-
hopstr.write({ type: HopMessage.Type.RESERVE })
|
|
54
|
-
|
|
55
|
-
let response: HopMessage
|
|
56
|
-
try {
|
|
57
|
-
response = await hopstr.read()
|
|
58
|
-
} catch (err: any) {
|
|
59
|
-
log.error('error passing reserve message response from %s because', connection.remotePeer, err.message)
|
|
60
|
-
stream.close()
|
|
61
|
-
throw err
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (response.status === Status.OK && (response.reservation != null)) {
|
|
65
|
-
return response.reservation
|
|
66
|
-
}
|
|
67
|
-
const errMsg = `reservation failed with status ${response.status ?? 'undefined'}`
|
|
68
|
-
log.error(errMsg)
|
|
69
|
-
throw new Error(errMsg)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const isRelayAddr = (ma: Multiaddr): boolean => ma.protoCodes().includes(CIRCUIT_PROTO_CODE)
|
|
73
|
-
|
|
74
|
-
async function handleReserve ({ connection, stream: pbstr, relayPeer, relayAddrs, acl, reservationStore, peerStore }: HopProtocolOptions): Promise<void> {
|
|
75
|
-
const hopstr = pbstr.pb(HopMessage)
|
|
76
|
-
log('hop reserve request from %s', connection.remotePeer)
|
|
77
|
-
|
|
78
|
-
if (isRelayAddr(connection.remoteAddr)) {
|
|
79
|
-
log.error('relay reservation over circuit connection denied for peer: %p', connection.remotePeer)
|
|
80
|
-
hopstr.write({ type: HopMessage.Type.STATUS, status: Status.PERMISSION_DENIED })
|
|
81
|
-
return
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if ((await acl?.allowReserve?.(connection.remotePeer, connection.remoteAddr)) === false) {
|
|
85
|
-
log.error('acl denied reservation to %s', connection.remotePeer)
|
|
86
|
-
hopstr.write({ type: HopMessage.Type.STATUS, status: Status.PERMISSION_DENIED })
|
|
87
|
-
return
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const result = await reservationStore.reserve(connection.remotePeer, connection.remoteAddr)
|
|
91
|
-
|
|
92
|
-
if (result.status !== Status.OK) {
|
|
93
|
-
hopstr.write({ type: HopMessage.Type.STATUS, status: result.status })
|
|
94
|
-
return
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
try {
|
|
98
|
-
// tag relayed peer
|
|
99
|
-
// result.expire is non-null if `ReservationStore.reserve` returns with status == OK
|
|
100
|
-
if (result.expire != null) {
|
|
101
|
-
const ttl = new Date().getTime() - result.expire
|
|
102
|
-
await peerStore.tagPeer(relayPeer, RELAY_DESTINATION_TAG, { value: 1, ttl })
|
|
103
|
-
}
|
|
104
|
-
hopstr.write({
|
|
105
|
-
type: HopMessage.Type.STATUS,
|
|
106
|
-
status: Status.OK,
|
|
107
|
-
reservation: await makeReservation(relayAddrs, relayPeer, connection.remotePeer, BigInt(result.expire ?? 0)),
|
|
108
|
-
limit: (await reservationStore.get(relayPeer))?.limit
|
|
109
|
-
})
|
|
110
|
-
log('sent confirmation response to %s', connection.remotePeer)
|
|
111
|
-
} catch (err) {
|
|
112
|
-
log.error('failed to send confirmation response to %s', connection.remotePeer)
|
|
113
|
-
await reservationStore.removeReservation(connection.remotePeer)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
async function handleConnect (options: HopProtocolOptions): Promise<void> {
|
|
118
|
-
const { connection, stream, request, reservationStore, connectionManager, acl } = options
|
|
119
|
-
const hopstr = stream.pb(HopMessage)
|
|
120
|
-
|
|
121
|
-
log('hop connect request from %s', connection.remotePeer)
|
|
122
|
-
|
|
123
|
-
let dstPeer: PeerId
|
|
124
|
-
try {
|
|
125
|
-
if (request.peer == null) {
|
|
126
|
-
log.error('no peer info in hop connect request')
|
|
127
|
-
throw new Error('no peer info in request')
|
|
128
|
-
}
|
|
129
|
-
request.peer.addrs.forEach(multiaddr)
|
|
130
|
-
dstPeer = peerIdFromBytes(request.peer.id)
|
|
131
|
-
} catch (err) {
|
|
132
|
-
log.error('invalid hop connect request via peer %p %s', connection.remotePeer, err)
|
|
133
|
-
hopstr.write({ type: HopMessage.Type.STATUS, status: Status.MALFORMED_MESSAGE })
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (acl?.allowConnect !== undefined) {
|
|
138
|
-
const status = await acl.allowConnect(connection.remotePeer, connection.remoteAddr, dstPeer)
|
|
139
|
-
if (status !== Status.OK) {
|
|
140
|
-
log.error('hop connect denied for %s with status %s', connection.remotePeer, status)
|
|
141
|
-
hopstr.write({ type: HopMessage.Type.STATUS, status: status })
|
|
142
|
-
return
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (!await reservationStore.hasReservation(dstPeer)) {
|
|
147
|
-
log.error('hop connect denied for %s with status %s', connection.remotePeer, Status.NO_RESERVATION)
|
|
148
|
-
hopstr.write({ type: HopMessage.Type.STATUS, status: Status.NO_RESERVATION })
|
|
149
|
-
return
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const connections = connectionManager.getConnections(dstPeer)
|
|
153
|
-
if (connections.length === 0) {
|
|
154
|
-
log('hop connect denied for %s as there is no destination connection', connection.remotePeer)
|
|
155
|
-
hopstr.write({ type: HopMessage.Type.STATUS, status: Status.NO_RESERVATION })
|
|
156
|
-
return
|
|
157
|
-
}
|
|
158
|
-
const destinationConnection = connections[0]
|
|
159
|
-
log('hop connect request from %s to %s is valid', connection.remotePeer, dstPeer)
|
|
160
|
-
|
|
161
|
-
const destinationStream = await stop({
|
|
162
|
-
connection: destinationConnection,
|
|
163
|
-
request: {
|
|
164
|
-
type: StopMessage.Type.CONNECT,
|
|
165
|
-
peer: {
|
|
166
|
-
id: connection.remotePeer.toBytes(),
|
|
167
|
-
addrs: [multiaddr('/p2p/' + connection.remotePeer.toString()).bytes]
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
if (destinationStream == null) {
|
|
173
|
-
log.error('failed to open stream to destination peer %s', destinationConnection?.remotePeer)
|
|
174
|
-
hopstr.write({ type: HopMessage.Type.STATUS, status: Status.CONNECTION_FAILED })
|
|
175
|
-
return
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
hopstr.write({ type: HopMessage.Type.STATUS, status: Status.OK })
|
|
179
|
-
const sourceStream = stream.unwrap()
|
|
180
|
-
|
|
181
|
-
log('connection to destination established, short circuiting streams...')
|
|
182
|
-
const limit = (await reservationStore.get(dstPeer))?.limit
|
|
183
|
-
// Short circuit the two streams to create the relayed connection
|
|
184
|
-
return createLimitedRelay(sourceStream, destinationStream, limit)
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
async function makeReservation (
|
|
188
|
-
relayAddrs: Multiaddr[],
|
|
189
|
-
relayPeerId: PeerId,
|
|
190
|
-
remotePeer: PeerId,
|
|
191
|
-
expire: bigint
|
|
192
|
-
): Promise<Reservation> {
|
|
193
|
-
const addrs = []
|
|
194
|
-
|
|
195
|
-
for (const relayAddr of relayAddrs) {
|
|
196
|
-
addrs.push(relayAddr.bytes)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const voucher = await RecordEnvelope.seal(new ReservationVoucherRecord({
|
|
200
|
-
peer: remotePeer,
|
|
201
|
-
relay: relayPeerId,
|
|
202
|
-
expiration: Number(expire)
|
|
203
|
-
}), relayPeerId)
|
|
204
|
-
|
|
205
|
-
return {
|
|
206
|
-
addrs,
|
|
207
|
-
expire,
|
|
208
|
-
voucher: voucher.marshal()
|
|
209
|
-
}
|
|
210
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { PeerId } from '@libp2p/interface-peer-id'
|
|
2
|
-
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
3
|
-
import type { Limit, Status } from './pb/index.js'
|
|
4
|
-
|
|
5
|
-
export type ReservationStatus = Status.OK | Status.PERMISSION_DENIED | Status.RESERVATION_REFUSED
|
|
6
|
-
|
|
7
|
-
export interface Reservation {
|
|
8
|
-
addr: Multiaddr
|
|
9
|
-
expire: Date
|
|
10
|
-
limit?: Limit
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface ReservationStore {
|
|
14
|
-
reserve: (peer: PeerId, addr: Multiaddr, limit?: Limit) => {status: ReservationStatus, expire?: number}
|
|
15
|
-
removeReservation: (peer: PeerId) => void
|
|
16
|
-
hasReservation: (dst: PeerId) => boolean
|
|
17
|
-
get: (peer: PeerId) => Reservation | undefined
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export type AclStatus = Status.OK | Status.RESOURCE_LIMIT_EXCEEDED | Status.PERMISSION_DENIED
|
|
21
|
-
|
|
22
|
-
export interface Acl {
|
|
23
|
-
allowReserve: (peer: PeerId, addr: Multiaddr) => Promise<boolean>
|
|
24
|
-
/**
|
|
25
|
-
* Checks if connection should be allowed
|
|
26
|
-
*/
|
|
27
|
-
allowConnect: (src: PeerId, addr: Multiaddr, dst: PeerId) => Promise<AclStatus>
|
|
28
|
-
}
|
package/src/circuit/listener.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events'
|
|
2
|
-
import type { ConnectionManager } from '@libp2p/interface-connection-manager'
|
|
3
|
-
import type { PeerStore } from '@libp2p/interface-peer-store'
|
|
4
|
-
import type { Listener } from '@libp2p/interface-transport'
|
|
5
|
-
import { peerIdFromString } from '@libp2p/peer-id'
|
|
6
|
-
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
7
|
-
import { multiaddr } from '@multiformats/multiaddr'
|
|
8
|
-
|
|
9
|
-
export interface ListenerOptions {
|
|
10
|
-
peerStore: PeerStore
|
|
11
|
-
connectionManager: ConnectionManager
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function createListener (options: ListenerOptions): Listener {
|
|
15
|
-
const listeningAddrs = new Map()
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Add swarm handler and listen for incoming connections
|
|
19
|
-
*/
|
|
20
|
-
async function listen (addr: Multiaddr): Promise<void> {
|
|
21
|
-
const addrString = addr.toString().split('/p2p-circuit').find(a => a !== '')
|
|
22
|
-
const ma = multiaddr(addrString)
|
|
23
|
-
|
|
24
|
-
const relayPeerStr = ma.getPeerId()
|
|
25
|
-
|
|
26
|
-
if (relayPeerStr == null) {
|
|
27
|
-
throw new Error('Could not determine relay peer from multiaddr')
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const relayPeerId = peerIdFromString(relayPeerStr)
|
|
31
|
-
|
|
32
|
-
await options.peerStore.addressBook.add(relayPeerId, [ma])
|
|
33
|
-
|
|
34
|
-
const relayConn = await options.connectionManager.openConnection(relayPeerId)
|
|
35
|
-
const relayedAddr = relayConn.remoteAddr.encapsulate('/p2p-circuit')
|
|
36
|
-
|
|
37
|
-
listeningAddrs.set(relayConn.remotePeer.toString(), relayedAddr)
|
|
38
|
-
listener.dispatchEvent(new CustomEvent('listening'))
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Get fixed up multiaddrs
|
|
43
|
-
*
|
|
44
|
-
* NOTE: This method will grab the peers multiaddrs and expand them such that:
|
|
45
|
-
*
|
|
46
|
-
* a) If it's an existing /p2p-circuit address for a specific relay i.e.
|
|
47
|
-
* `/ip4/0.0.0.0/tcp/0/ipfs/QmRelay/p2p-circuit` this method will expand the
|
|
48
|
-
* address to `/ip4/0.0.0.0/tcp/0/ipfs/QmRelay/p2p-circuit/ipfs/QmPeer` where
|
|
49
|
-
* `QmPeer` is this peers id
|
|
50
|
-
* b) If it's not a /p2p-circuit address, it will encapsulate the address as a /p2p-circuit
|
|
51
|
-
* addr, such when dialing over a relay with this address, it will create the circuit using
|
|
52
|
-
* the encapsulated transport address. This is useful when for example, a peer should only
|
|
53
|
-
* be dialed over TCP rather than any other transport
|
|
54
|
-
*
|
|
55
|
-
* @returns {Multiaddr[]}
|
|
56
|
-
*/
|
|
57
|
-
function getAddrs () {
|
|
58
|
-
const addrs = []
|
|
59
|
-
for (const addr of listeningAddrs.values()) {
|
|
60
|
-
addrs.push(addr)
|
|
61
|
-
}
|
|
62
|
-
return addrs
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const listener: Listener = Object.assign(new EventEmitter(), {
|
|
66
|
-
close: async () => await Promise.resolve(),
|
|
67
|
-
listen,
|
|
68
|
-
getAddrs
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
// Remove listeningAddrs when a peer disconnects
|
|
72
|
-
options.connectionManager.addEventListener('peer:disconnect', (evt) => {
|
|
73
|
-
const { detail: connection } = evt
|
|
74
|
-
const deleted = listeningAddrs.delete(connection.remotePeer.toString())
|
|
75
|
-
|
|
76
|
-
if (deleted) {
|
|
77
|
-
// Announce listen addresses change
|
|
78
|
-
listener.dispatchEvent(new CustomEvent('close'))
|
|
79
|
-
}
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
return listener
|
|
83
|
-
}
|