@libp2p/dcutr 0.0.0-97ab31c0c
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/LICENSE +4 -0
- package/README.md +88 -0
- package/dist/index.min.js +14 -0
- package/dist/src/dcutr.d.ts +44 -0
- package/dist/src/dcutr.d.ts.map +1 -0
- package/dist/src/dcutr.js +312 -0
- package/dist/src/dcutr.js.map +1 -0
- package/dist/src/index.d.ts +94 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +63 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/pb/message.d.ts +20 -0
- package/dist/src/pb/message.d.ts.map +1 -0
- package/dist/src/pb/message.js +77 -0
- package/dist/src/pb/message.js.map +1 -0
- package/dist/src/utils.d.ts +8 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +27 -0
- package/dist/src/utils.js.map +1 -0
- package/package.json +66 -0
- package/src/dcutr.ts +377 -0
- package/src/index.ts +104 -0
- package/src/pb/message.proto +12 -0
- package/src/pb/message.ts +96 -0
- package/src/utils.ts +33 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { CodeError, ERR_INVALID_MESSAGE } from '@libp2p/interface/errors';
|
|
2
|
+
import { multiaddr } from '@multiformats/multiaddr';
|
|
3
|
+
import delay from 'delay';
|
|
4
|
+
import { pbStream } from 'it-protobuf-stream';
|
|
5
|
+
import { HolePunch } from './pb/message.js';
|
|
6
|
+
import { isPublicAndDialable } from './utils.js';
|
|
7
|
+
import { multicodec } from './index.js';
|
|
8
|
+
// https://github.com/libp2p/specs/blob/master/relay/DCUtR.md#rpc-messages
|
|
9
|
+
const MAX_DCUTR_MESSAGE_SIZE = 1024 * 4;
|
|
10
|
+
// ensure the dial has a high priority to jump to the head of the dial queue
|
|
11
|
+
const DCUTR_DIAL_PRIORITY = 100;
|
|
12
|
+
const defaultValues = {
|
|
13
|
+
// https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/holepunch/holepuncher.go#L27
|
|
14
|
+
timeout: 5000,
|
|
15
|
+
// https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/holepunch/holepuncher.go#L28
|
|
16
|
+
retries: 3,
|
|
17
|
+
maxInboundStreams: 1,
|
|
18
|
+
maxOutboundStreams: 1
|
|
19
|
+
};
|
|
20
|
+
export class DefaultDCUtRService {
|
|
21
|
+
started;
|
|
22
|
+
timeout;
|
|
23
|
+
retries;
|
|
24
|
+
maxInboundStreams;
|
|
25
|
+
maxOutboundStreams;
|
|
26
|
+
peerStore;
|
|
27
|
+
registrar;
|
|
28
|
+
connectionManager;
|
|
29
|
+
addressManager;
|
|
30
|
+
transportManager;
|
|
31
|
+
topologyId;
|
|
32
|
+
log;
|
|
33
|
+
constructor(components, init) {
|
|
34
|
+
this.log = components.logger.forComponent('libp2p:dcutr');
|
|
35
|
+
this.started = false;
|
|
36
|
+
this.peerStore = components.peerStore;
|
|
37
|
+
this.registrar = components.registrar;
|
|
38
|
+
this.addressManager = components.addressManager;
|
|
39
|
+
this.connectionManager = components.connectionManager;
|
|
40
|
+
this.transportManager = components.transportManager;
|
|
41
|
+
this.timeout = init.timeout ?? defaultValues.timeout;
|
|
42
|
+
this.retries = init.retries ?? defaultValues.retries;
|
|
43
|
+
this.maxInboundStreams = init.maxInboundStreams ?? defaultValues.maxInboundStreams;
|
|
44
|
+
this.maxOutboundStreams = init.maxOutboundStreams ?? defaultValues.maxOutboundStreams;
|
|
45
|
+
}
|
|
46
|
+
isStarted() {
|
|
47
|
+
return this.started;
|
|
48
|
+
}
|
|
49
|
+
async start() {
|
|
50
|
+
if (this.started) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// register for notifications of when peers that support DCUtR connect
|
|
54
|
+
// nb. requires the identify service to be enabled
|
|
55
|
+
this.topologyId = await this.registrar.register(multicodec, {
|
|
56
|
+
notifyOnTransient: true,
|
|
57
|
+
onConnect: (peerId, connection) => {
|
|
58
|
+
if (!connection.transient) {
|
|
59
|
+
// the connection is already direct, no upgrade is required
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
// the inbound peer starts the connection upgrade
|
|
63
|
+
if (connection.direction !== 'inbound') {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.upgradeInbound(connection)
|
|
67
|
+
.catch(err => {
|
|
68
|
+
this.log.error('error during outgoing DCUtR attempt', err);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
await this.registrar.handle(multicodec, (data) => {
|
|
73
|
+
void this.handleIncomingUpgrade(data.stream, data.connection).catch(err => {
|
|
74
|
+
this.log.error('error during incoming DCUtR attempt', err);
|
|
75
|
+
data.stream.abort(err);
|
|
76
|
+
});
|
|
77
|
+
}, {
|
|
78
|
+
maxInboundStreams: this.maxInboundStreams,
|
|
79
|
+
maxOutboundStreams: this.maxOutboundStreams,
|
|
80
|
+
runOnTransientConnection: true
|
|
81
|
+
});
|
|
82
|
+
this.started = true;
|
|
83
|
+
}
|
|
84
|
+
async stop() {
|
|
85
|
+
await this.registrar.unhandle(multicodec);
|
|
86
|
+
if (this.topologyId != null) {
|
|
87
|
+
this.registrar.unregister(this.topologyId);
|
|
88
|
+
}
|
|
89
|
+
this.started = false;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Perform the inbound connection upgrade as B
|
|
93
|
+
*
|
|
94
|
+
* @see https://github.com/libp2p/specs/blob/master/relay/DCUtR.md#the-protocol
|
|
95
|
+
*/
|
|
96
|
+
async upgradeInbound(relayedConnection) {
|
|
97
|
+
// Upon observing the new connection, the inbound peer (here B) checks the
|
|
98
|
+
// addresses advertised by A via identify.
|
|
99
|
+
//
|
|
100
|
+
// If that set includes public addresses, then A may be reachable by a direct
|
|
101
|
+
// connection, in which case B attempts a unilateral connection upgrade by
|
|
102
|
+
// initiating a direct connection to A.
|
|
103
|
+
if (await this.attemptUnilateralConnectionUpgrade(relayedConnection)) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
let stream;
|
|
107
|
+
for (let i = 0; i < this.retries; i++) {
|
|
108
|
+
const options = {
|
|
109
|
+
signal: AbortSignal.timeout(this.timeout)
|
|
110
|
+
};
|
|
111
|
+
try {
|
|
112
|
+
// 1. B opens a stream to A using the /libp2p/dcutr protocol.
|
|
113
|
+
stream = await relayedConnection.newStream([multicodec], {
|
|
114
|
+
signal: options.signal,
|
|
115
|
+
runOnTransientConnection: true
|
|
116
|
+
});
|
|
117
|
+
const pb = pbStream(stream, {
|
|
118
|
+
maxDataLength: MAX_DCUTR_MESSAGE_SIZE
|
|
119
|
+
}).pb(HolePunch);
|
|
120
|
+
// 2. B sends to A a Connect message containing its observed (and
|
|
121
|
+
// possibly predicted) addresses from identify and starts a timer
|
|
122
|
+
// to measure RTT of the relay connection.
|
|
123
|
+
this.log('B sending connect to %p', relayedConnection.remotePeer);
|
|
124
|
+
const connectTimer = Date.now();
|
|
125
|
+
await pb.write({
|
|
126
|
+
type: HolePunch.Type.CONNECT,
|
|
127
|
+
observedAddresses: this.addressManager.getAddresses().map(ma => ma.bytes)
|
|
128
|
+
}, options);
|
|
129
|
+
this.log('B receiving connect from %p', relayedConnection.remotePeer);
|
|
130
|
+
// 4. Upon receiving the Connect, B sends a Sync message
|
|
131
|
+
const connect = await pb.read(options);
|
|
132
|
+
if (connect.type !== HolePunch.Type.CONNECT) {
|
|
133
|
+
this.log('A sent wrong message type');
|
|
134
|
+
throw new CodeError('DCUtR message type was incorrect', ERR_INVALID_MESSAGE);
|
|
135
|
+
}
|
|
136
|
+
const multiaddrs = this.getDialableMultiaddrs(connect.observedAddresses);
|
|
137
|
+
if (multiaddrs.length === 0) {
|
|
138
|
+
this.log('A did not have any dialable multiaddrs');
|
|
139
|
+
throw new CodeError('DCUtR connect message had no multiaddrs', ERR_INVALID_MESSAGE);
|
|
140
|
+
}
|
|
141
|
+
const rtt = Date.now() - connectTimer;
|
|
142
|
+
this.log('A sending sync, rtt %dms', rtt);
|
|
143
|
+
await pb.write({
|
|
144
|
+
type: HolePunch.Type.SYNC,
|
|
145
|
+
observedAddresses: []
|
|
146
|
+
}, options);
|
|
147
|
+
this.log('A waiting for half RTT');
|
|
148
|
+
// ..and starts a timer for half the RTT measured from the time between
|
|
149
|
+
// sending the initial Connect and receiving the response
|
|
150
|
+
await delay(rtt / 2);
|
|
151
|
+
// TODO: when we have a QUIC transport, the dial step is different - for
|
|
152
|
+
// now we only have tcp support
|
|
153
|
+
// https://github.com/libp2p/specs/blob/master/relay/DCUtR.md#the-protocol
|
|
154
|
+
this.log('B dialing', multiaddrs);
|
|
155
|
+
// Upon expiry of the timer, B dials the address to A.
|
|
156
|
+
const conn = await this.connectionManager.openConnection(multiaddrs, {
|
|
157
|
+
signal: options.signal,
|
|
158
|
+
priority: DCUTR_DIAL_PRIORITY
|
|
159
|
+
});
|
|
160
|
+
this.log('DCUtR to %p succeeded to address %a, closing relayed connection', relayedConnection.remotePeer, conn.remoteAddr);
|
|
161
|
+
await relayedConnection.close(options);
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
this.log.error('error while attempting DCUtR on attempt %d of %d', i + 1, this.retries, err);
|
|
166
|
+
stream?.abort(err);
|
|
167
|
+
if (i === this.retries) {
|
|
168
|
+
throw err;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
if (stream != null) {
|
|
173
|
+
await stream.close(options);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* This is performed when A has dialed B via a relay but A also has a public
|
|
180
|
+
* address that B can dial directly
|
|
181
|
+
*/
|
|
182
|
+
async attemptUnilateralConnectionUpgrade(relayedConnection) {
|
|
183
|
+
// Upon observing the new connection, the inbound peer (here B) checks the
|
|
184
|
+
// addresses advertised by A via identify.
|
|
185
|
+
const peerInfo = await this.peerStore.get(relayedConnection.remotePeer);
|
|
186
|
+
// If that set includes public addresses, then A may be reachable by a direct
|
|
187
|
+
// connection, in which case B attempts a unilateral connection upgrade by
|
|
188
|
+
// initiating a direct connection to A.
|
|
189
|
+
const publicAddresses = peerInfo.addresses
|
|
190
|
+
.map(address => {
|
|
191
|
+
const ma = address.multiaddr;
|
|
192
|
+
// ensure all multiaddrs have the peer id
|
|
193
|
+
if (ma.getPeerId() == null) {
|
|
194
|
+
return ma.encapsulate(`/p2p/${relayedConnection.remotePeer}`);
|
|
195
|
+
}
|
|
196
|
+
return ma;
|
|
197
|
+
})
|
|
198
|
+
.filter(ma => {
|
|
199
|
+
return isPublicAndDialable(ma, this.transportManager);
|
|
200
|
+
});
|
|
201
|
+
if (publicAddresses.length > 0) {
|
|
202
|
+
const signal = AbortSignal.timeout(this.timeout);
|
|
203
|
+
try {
|
|
204
|
+
this.log('attempting unilateral connection upgrade to %a', publicAddresses);
|
|
205
|
+
// force-dial the multiaddr(s), otherwise `connectionManager.openConnection`
|
|
206
|
+
// will return the existing relayed connection
|
|
207
|
+
const connection = await this.connectionManager.openConnection(publicAddresses, {
|
|
208
|
+
signal,
|
|
209
|
+
force: true
|
|
210
|
+
});
|
|
211
|
+
if (connection.transient) {
|
|
212
|
+
throw new Error('Could not open a new, non-transient, connection');
|
|
213
|
+
}
|
|
214
|
+
this.log('unilateral connection upgrade to %p succeeded via %a, closing relayed connection', relayedConnection.remotePeer, connection.remoteAddr);
|
|
215
|
+
await relayedConnection.close({
|
|
216
|
+
signal
|
|
217
|
+
});
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
this.log.error('unilateral connection upgrade to %p on addresses %a failed', relayedConnection.remotePeer, publicAddresses, err);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
this.log('peer %p has no public addresses, not attempting unilateral connection upgrade', relayedConnection.remotePeer);
|
|
226
|
+
}
|
|
227
|
+
// no public addresses or failed to dial public addresses
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Perform the connection upgrade as A
|
|
232
|
+
*
|
|
233
|
+
* @see https://github.com/libp2p/specs/blob/master/relay/DCUtR.md#the-protocol
|
|
234
|
+
*/
|
|
235
|
+
async handleIncomingUpgrade(stream, relayedConnection) {
|
|
236
|
+
const options = {
|
|
237
|
+
signal: AbortSignal.timeout(this.timeout)
|
|
238
|
+
};
|
|
239
|
+
try {
|
|
240
|
+
const pb = pbStream(stream, {
|
|
241
|
+
maxDataLength: MAX_DCUTR_MESSAGE_SIZE
|
|
242
|
+
}).pb(HolePunch);
|
|
243
|
+
this.log('A receiving connect');
|
|
244
|
+
// 3. Upon receiving the Connect, A responds back with a Connect message
|
|
245
|
+
// containing its observed (and possibly predicted) addresses.
|
|
246
|
+
const connect = await pb.read(options);
|
|
247
|
+
if (connect.type !== HolePunch.Type.CONNECT) {
|
|
248
|
+
this.log('B sent wrong message type');
|
|
249
|
+
throw new CodeError('DCUtR message type was incorrect', ERR_INVALID_MESSAGE);
|
|
250
|
+
}
|
|
251
|
+
if (connect.observedAddresses.length === 0) {
|
|
252
|
+
this.log('B sent no multiaddrs');
|
|
253
|
+
throw new CodeError('DCUtR connect message had no multiaddrs', ERR_INVALID_MESSAGE);
|
|
254
|
+
}
|
|
255
|
+
const multiaddrs = this.getDialableMultiaddrs(connect.observedAddresses);
|
|
256
|
+
if (multiaddrs.length === 0) {
|
|
257
|
+
this.log('B had no dialable multiaddrs');
|
|
258
|
+
throw new CodeError('DCUtR connect message had no dialable multiaddrs', ERR_INVALID_MESSAGE);
|
|
259
|
+
}
|
|
260
|
+
this.log('A sending connect');
|
|
261
|
+
await pb.write({
|
|
262
|
+
type: HolePunch.Type.CONNECT,
|
|
263
|
+
observedAddresses: this.addressManager.getAddresses().map(ma => ma.bytes)
|
|
264
|
+
});
|
|
265
|
+
this.log('A receiving sync');
|
|
266
|
+
const sync = await pb.read(options);
|
|
267
|
+
if (sync.type !== HolePunch.Type.SYNC) {
|
|
268
|
+
throw new CodeError('DCUtR message type was incorrect', ERR_INVALID_MESSAGE);
|
|
269
|
+
}
|
|
270
|
+
// TODO: when we have a QUIC transport, the dial step is different - for
|
|
271
|
+
// now we only have tcp support
|
|
272
|
+
// https://github.com/libp2p/specs/blob/master/relay/DCUtR.md#the-protocol
|
|
273
|
+
// Upon receiving the Sync, A immediately dials the address to B
|
|
274
|
+
this.log('A dialing', multiaddrs);
|
|
275
|
+
const connection = await this.connectionManager.openConnection(multiaddrs, {
|
|
276
|
+
signal: options.signal,
|
|
277
|
+
priority: DCUTR_DIAL_PRIORITY,
|
|
278
|
+
force: true
|
|
279
|
+
});
|
|
280
|
+
this.log('DCUtR to %p succeeded via %a, closing relayed connection', relayedConnection.remotePeer, connection.remoteAddr);
|
|
281
|
+
await relayedConnection.close(options);
|
|
282
|
+
}
|
|
283
|
+
catch (err) {
|
|
284
|
+
this.log.error('incoming DCUtR from %p failed', relayedConnection.remotePeer, err);
|
|
285
|
+
stream.abort(err);
|
|
286
|
+
}
|
|
287
|
+
finally {
|
|
288
|
+
await stream.close(options);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Takes the `addr` and converts it to a Multiaddr if possible
|
|
293
|
+
*/
|
|
294
|
+
getDialableMultiaddrs(addrs) {
|
|
295
|
+
const output = [];
|
|
296
|
+
for (const addr of addrs) {
|
|
297
|
+
if (addr == null || addr.length === 0) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
try {
|
|
301
|
+
const ma = multiaddr(addr);
|
|
302
|
+
if (!isPublicAndDialable(ma, this.transportManager)) {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
output.push(ma);
|
|
306
|
+
}
|
|
307
|
+
catch { }
|
|
308
|
+
}
|
|
309
|
+
return output;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
//# sourceMappingURL=dcutr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dcutr.js","sourceRoot":"","sources":["../../src/dcutr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* Direct Connection Upgrade through Relay (DCUtR) is a protocol that allows two
|
|
5
|
+
* nodes to connect to each other who would otherwise be prevented doing so due
|
|
6
|
+
* to being behind NATed connections or firewalls.
|
|
7
|
+
*
|
|
8
|
+
* The protocol involves making a relayed connection between the two peers and
|
|
9
|
+
* using the relay to synchronise connection timings so that they dial each other
|
|
10
|
+
* at precisely the same moment.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { createLibp2p } from 'libp2p'
|
|
16
|
+
* import { circuitRelayTransport } from 'libp2p/circuit-relay'
|
|
17
|
+
* import { tcp } from '@libp2p/tcp'
|
|
18
|
+
* import { identify } from '@libp2p/identify'
|
|
19
|
+
* import { dcutr } from '@libp2p/dcutr'
|
|
20
|
+
*
|
|
21
|
+
* const node = await createLibp2p({
|
|
22
|
+
* transports: [
|
|
23
|
+
* circuitRelayTransport(),
|
|
24
|
+
* tcp()
|
|
25
|
+
* ],
|
|
26
|
+
* services: {
|
|
27
|
+
* identify: identify(),
|
|
28
|
+
* dcutr: dcutr()
|
|
29
|
+
* }
|
|
30
|
+
* })
|
|
31
|
+
*
|
|
32
|
+
* // QmTarget is a peer that is behind a NAT, supports TCP and has a relay
|
|
33
|
+
* // reservation
|
|
34
|
+
* await node.dial('/ip4/.../p2p/QmRelay/p2p-circuit/p2p/QmTarget')
|
|
35
|
+
*
|
|
36
|
+
* // after a while the connection should automatically get upgraded to a
|
|
37
|
+
* // direct connection (e.g. non-transient)
|
|
38
|
+
* while (true) {
|
|
39
|
+
* const connections = node.getConnections()
|
|
40
|
+
*
|
|
41
|
+
* if (connections.find(conn => conn.transient === false)) {
|
|
42
|
+
* console.info('have direct connection')
|
|
43
|
+
* break
|
|
44
|
+
* } else {
|
|
45
|
+
* console.info('have relayed connection')
|
|
46
|
+
*
|
|
47
|
+
* // wait a few seconds to see if it's succeeded yet
|
|
48
|
+
* await new Promise((resolve) => {
|
|
49
|
+
* setTimeout(() => resolve(), 5000)
|
|
50
|
+
* })
|
|
51
|
+
* }
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
import type { ComponentLogger } from '@libp2p/interface';
|
|
56
|
+
import type { PeerStore } from '@libp2p/interface/peer-store';
|
|
57
|
+
import type { AddressManager } from '@libp2p/interface-internal/address-manager';
|
|
58
|
+
import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager';
|
|
59
|
+
import type { Registrar } from '@libp2p/interface-internal/registrar';
|
|
60
|
+
import type { TransportManager } from '@libp2p/interface-internal/transport-manager';
|
|
61
|
+
export interface DCUtRServiceInit {
|
|
62
|
+
/**
|
|
63
|
+
* How long we should wait for the connection upgrade to complete (default: 5s)
|
|
64
|
+
*/
|
|
65
|
+
timeout?: number;
|
|
66
|
+
/**
|
|
67
|
+
* How many times to retry the connection upgrade (default: 3)
|
|
68
|
+
*/
|
|
69
|
+
retries?: number;
|
|
70
|
+
/**
|
|
71
|
+
* How many simultaneous inbound DCUtR protocol streams to allow on each
|
|
72
|
+
* connection (default: 1)
|
|
73
|
+
*/
|
|
74
|
+
maxInboundStreams?: number;
|
|
75
|
+
/**
|
|
76
|
+
* How many simultaneous outbound DCUtR protocol streams to allow on each
|
|
77
|
+
* connection (default: 1)
|
|
78
|
+
*/
|
|
79
|
+
maxOutboundStreams?: number;
|
|
80
|
+
}
|
|
81
|
+
export interface DCUtRServiceComponents {
|
|
82
|
+
peerStore: PeerStore;
|
|
83
|
+
connectionManager: ConnectionManager;
|
|
84
|
+
registrar: Registrar;
|
|
85
|
+
addressManager: AddressManager;
|
|
86
|
+
transportManager: TransportManager;
|
|
87
|
+
logger: ComponentLogger;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The DCUtR protocol
|
|
91
|
+
*/
|
|
92
|
+
export declare const multicodec = "/libp2p/dcutr";
|
|
93
|
+
export declare function dcutr(init?: DCUtRServiceInit): (components: DCUtRServiceComponents) => unknown;
|
|
94
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAA;AAChF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAA;AACtF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAA;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAA;AAEpF,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAE1B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,SAAS,CAAA;IACpB,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,SAAS,EAAE,SAAS,CAAA;IACpB,cAAc,EAAE,cAAc,CAAA;IAC9B,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,MAAM,EAAE,eAAe,CAAA;CACxB;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,kBAAkB,CAAA;AAEzC,wBAAgB,KAAK,CAAE,IAAI,GAAE,gBAAqB,GAAG,CAAC,UAAU,EAAE,sBAAsB,KAAK,OAAO,CAEnG"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* Direct Connection Upgrade through Relay (DCUtR) is a protocol that allows two
|
|
5
|
+
* nodes to connect to each other who would otherwise be prevented doing so due
|
|
6
|
+
* to being behind NATed connections or firewalls.
|
|
7
|
+
*
|
|
8
|
+
* The protocol involves making a relayed connection between the two peers and
|
|
9
|
+
* using the relay to synchronise connection timings so that they dial each other
|
|
10
|
+
* at precisely the same moment.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { createLibp2p } from 'libp2p'
|
|
16
|
+
* import { circuitRelayTransport } from 'libp2p/circuit-relay'
|
|
17
|
+
* import { tcp } from '@libp2p/tcp'
|
|
18
|
+
* import { identify } from '@libp2p/identify'
|
|
19
|
+
* import { dcutr } from '@libp2p/dcutr'
|
|
20
|
+
*
|
|
21
|
+
* const node = await createLibp2p({
|
|
22
|
+
* transports: [
|
|
23
|
+
* circuitRelayTransport(),
|
|
24
|
+
* tcp()
|
|
25
|
+
* ],
|
|
26
|
+
* services: {
|
|
27
|
+
* identify: identify(),
|
|
28
|
+
* dcutr: dcutr()
|
|
29
|
+
* }
|
|
30
|
+
* })
|
|
31
|
+
*
|
|
32
|
+
* // QmTarget is a peer that is behind a NAT, supports TCP and has a relay
|
|
33
|
+
* // reservation
|
|
34
|
+
* await node.dial('/ip4/.../p2p/QmRelay/p2p-circuit/p2p/QmTarget')
|
|
35
|
+
*
|
|
36
|
+
* // after a while the connection should automatically get upgraded to a
|
|
37
|
+
* // direct connection (e.g. non-transient)
|
|
38
|
+
* while (true) {
|
|
39
|
+
* const connections = node.getConnections()
|
|
40
|
+
*
|
|
41
|
+
* if (connections.find(conn => conn.transient === false)) {
|
|
42
|
+
* console.info('have direct connection')
|
|
43
|
+
* break
|
|
44
|
+
* } else {
|
|
45
|
+
* console.info('have relayed connection')
|
|
46
|
+
*
|
|
47
|
+
* // wait a few seconds to see if it's succeeded yet
|
|
48
|
+
* await new Promise((resolve) => {
|
|
49
|
+
* setTimeout(() => resolve(), 5000)
|
|
50
|
+
* })
|
|
51
|
+
* }
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
import { DefaultDCUtRService } from './dcutr.js';
|
|
56
|
+
/**
|
|
57
|
+
* The DCUtR protocol
|
|
58
|
+
*/
|
|
59
|
+
export const multicodec = '/libp2p/dcutr';
|
|
60
|
+
export function dcutr(init = {}) {
|
|
61
|
+
return (components) => new DefaultDCUtRService(components, init);
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAyChD;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,eAAe,CAAA;AAEzC,MAAM,UAAU,KAAK,CAAE,OAAyB,EAAE;IAChD,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;AAClE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Codec } from 'protons-runtime';
|
|
2
|
+
import type { Uint8ArrayList } from 'uint8arraylist';
|
|
3
|
+
export interface HolePunch {
|
|
4
|
+
type?: HolePunch.Type;
|
|
5
|
+
observedAddresses: Uint8Array[];
|
|
6
|
+
}
|
|
7
|
+
export declare namespace HolePunch {
|
|
8
|
+
enum Type {
|
|
9
|
+
UNUSED = "UNUSED",
|
|
10
|
+
CONNECT = "CONNECT",
|
|
11
|
+
SYNC = "SYNC"
|
|
12
|
+
}
|
|
13
|
+
namespace Type {
|
|
14
|
+
const codec: () => Codec<Type>;
|
|
15
|
+
}
|
|
16
|
+
const codec: () => Codec<HolePunch>;
|
|
17
|
+
const encode: (obj: Partial<HolePunch>) => Uint8Array;
|
|
18
|
+
const decode: (buf: Uint8Array | Uint8ArrayList) => HolePunch;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../src/pb/message.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpD,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,SAAS,CAAC,IAAI,CAAA;IACrB,iBAAiB,EAAE,UAAU,EAAE,CAAA;CAChC;AAED,yBAAiB,SAAS,CAAC;IACzB,KAAY,IAAI;QACd,MAAM,WAAW;QACjB,OAAO,YAAY;QACnB,IAAI,SAAS;KACd;IAQD,UAAiB,IAAI,CAAC;QACb,MAAM,KAAK,QAAO,MAAM,IAAI,CAElC,CAAA;KACF;IAIM,MAAM,KAAK,QAAO,MAAM,SAAS,CAkDvC,CAAA;IAEM,MAAM,MAAM,QAAS,QAAQ,SAAS,CAAC,KAAG,UAEhD,CAAA;IAEM,MAAM,MAAM,QAAS,UAAU,GAAG,cAAc,KAAG,SAEzD,CAAA;CACF"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/* eslint-disable import/export */
|
|
2
|
+
/* eslint-disable complexity */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-namespace */
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
6
|
+
import { enumeration, encodeMessage, decodeMessage, message } from 'protons-runtime';
|
|
7
|
+
export var HolePunch;
|
|
8
|
+
(function (HolePunch) {
|
|
9
|
+
let Type;
|
|
10
|
+
(function (Type) {
|
|
11
|
+
Type["UNUSED"] = "UNUSED";
|
|
12
|
+
Type["CONNECT"] = "CONNECT";
|
|
13
|
+
Type["SYNC"] = "SYNC";
|
|
14
|
+
})(Type = HolePunch.Type || (HolePunch.Type = {}));
|
|
15
|
+
let __TypeValues;
|
|
16
|
+
(function (__TypeValues) {
|
|
17
|
+
__TypeValues[__TypeValues["UNUSED"] = 0] = "UNUSED";
|
|
18
|
+
__TypeValues[__TypeValues["CONNECT"] = 100] = "CONNECT";
|
|
19
|
+
__TypeValues[__TypeValues["SYNC"] = 300] = "SYNC";
|
|
20
|
+
})(__TypeValues || (__TypeValues = {}));
|
|
21
|
+
(function (Type) {
|
|
22
|
+
Type.codec = () => {
|
|
23
|
+
return enumeration(__TypeValues);
|
|
24
|
+
};
|
|
25
|
+
})(Type = HolePunch.Type || (HolePunch.Type = {}));
|
|
26
|
+
let _codec;
|
|
27
|
+
HolePunch.codec = () => {
|
|
28
|
+
if (_codec == null) {
|
|
29
|
+
_codec = message((obj, w, opts = {}) => {
|
|
30
|
+
if (opts.lengthDelimited !== false) {
|
|
31
|
+
w.fork();
|
|
32
|
+
}
|
|
33
|
+
if (obj.type != null) {
|
|
34
|
+
w.uint32(8);
|
|
35
|
+
HolePunch.Type.codec().encode(obj.type, w);
|
|
36
|
+
}
|
|
37
|
+
if (obj.observedAddresses != null) {
|
|
38
|
+
for (const value of obj.observedAddresses) {
|
|
39
|
+
w.uint32(18);
|
|
40
|
+
w.bytes(value);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (opts.lengthDelimited !== false) {
|
|
44
|
+
w.ldelim();
|
|
45
|
+
}
|
|
46
|
+
}, (reader, length) => {
|
|
47
|
+
const obj = {
|
|
48
|
+
observedAddresses: []
|
|
49
|
+
};
|
|
50
|
+
const end = length == null ? reader.len : reader.pos + length;
|
|
51
|
+
while (reader.pos < end) {
|
|
52
|
+
const tag = reader.uint32();
|
|
53
|
+
switch (tag >>> 3) {
|
|
54
|
+
case 1:
|
|
55
|
+
obj.type = HolePunch.Type.codec().decode(reader);
|
|
56
|
+
break;
|
|
57
|
+
case 2:
|
|
58
|
+
obj.observedAddresses.push(reader.bytes());
|
|
59
|
+
break;
|
|
60
|
+
default:
|
|
61
|
+
reader.skipType(tag & 7);
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return obj;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return _codec;
|
|
69
|
+
};
|
|
70
|
+
HolePunch.encode = (obj) => {
|
|
71
|
+
return encodeMessage(obj, HolePunch.codec());
|
|
72
|
+
};
|
|
73
|
+
HolePunch.decode = (buf) => {
|
|
74
|
+
return decodeMessage(buf, HolePunch.codec());
|
|
75
|
+
};
|
|
76
|
+
})(HolePunch || (HolePunch = {}));
|
|
77
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../../src/pb/message.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Multiaddr } from '@multiformats/multiaddr';
|
|
2
|
+
import type { TransportManager } from '@libp2p/interface-internal/src/transport-manager';
|
|
3
|
+
/**
|
|
4
|
+
* Returns true if the passed multiaddr is public, not relayed and we have a
|
|
5
|
+
* transport that can dial it
|
|
6
|
+
*/
|
|
7
|
+
export declare function isPublicAndDialable(ma: Multiaddr, transportManager: TransportManager): boolean;
|
|
8
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAGxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAA;AAExF;;;GAGG;AACH,wBAAgB,mBAAmB,CAAE,EAAE,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAuB/F"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {} from '@multiformats/multiaddr';
|
|
2
|
+
import { Circuit, IP, DNS } from '@multiformats/multiaddr-matcher';
|
|
3
|
+
import isPrivate from 'private-ip';
|
|
4
|
+
/**
|
|
5
|
+
* Returns true if the passed multiaddr is public, not relayed and we have a
|
|
6
|
+
* transport that can dial it
|
|
7
|
+
*/
|
|
8
|
+
export function isPublicAndDialable(ma, transportManager) {
|
|
9
|
+
// ignore circuit relay
|
|
10
|
+
if (Circuit.matches(ma)) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
const transport = transportManager.transportForMultiaddr(ma);
|
|
14
|
+
if (transport == null) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
// dns addresses are probably public?
|
|
18
|
+
if (DNS.matches(ma)) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
// ensure we have only IPv4/IPv6 addresses
|
|
22
|
+
if (!IP.matches(ma)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return isPrivate(ma.toOptions().host) === false;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,MAAM,yBAAyB,CAAA;AACxD,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAA;AAClE,OAAO,SAAS,MAAM,YAAY,CAAA;AAGlC;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAE,EAAa,EAAE,gBAAkC;IACpF,uBAAuB;IACvB,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;QACvB,OAAO,KAAK,CAAA;KACb;IAED,MAAM,SAAS,GAAG,gBAAgB,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAA;IAE5D,IAAI,SAAS,IAAI,IAAI,EAAE;QACrB,OAAO,KAAK,CAAA;KACb;IAED,qCAAqC;IACrC,IAAI,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;QACnB,OAAO,IAAI,CAAA;KACZ;IAED,0CAA0C;IAC1C,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;QACnB,OAAO,KAAK,CAAA;KACb;IAED,OAAO,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,CAAA;AACjD,CAAC"}
|