@statewalker/httpeers-libp2p 0.1.3 → 0.1.4
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/hub-link.d.ts +23 -0
- package/dist/hub-link.d.ts.map +1 -1
- package/dist/hub-link.js +34 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/src/hub-link.ts +40 -2
- package/src/index.ts +2 -0
package/dist/hub-link.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* so the same code runs in a page and under the Node tests.
|
|
7
7
|
*/
|
|
8
8
|
import type { Connection, Libp2p } from "@libp2p/interface";
|
|
9
|
+
import { type Multiaddr } from "@multiformats/multiaddr";
|
|
9
10
|
import { type RelaySupervisor } from "./reservation.js";
|
|
10
11
|
/**
|
|
11
12
|
* The address a member dials another member at: through their hub, with a
|
|
@@ -20,6 +21,28 @@ import { type RelaySupervisor } from "./reservation.js";
|
|
|
20
21
|
* connection it already holds to the hub.
|
|
21
22
|
*/
|
|
22
23
|
export declare function hubRoute(hubPeerId: string, peerId: string): string;
|
|
24
|
+
/** How many times `dialWebRTC` tries a WebRTC upgrade before giving up. */
|
|
25
|
+
export declare const WEBRTC_UPGRADE_ATTEMPTS = 3;
|
|
26
|
+
/**
|
|
27
|
+
* Dial a `/webrtc` address, trying the upgrade again when it fails.
|
|
28
|
+
*
|
|
29
|
+
* WHY. Under Node, WebRTC is libdatachannel (`node-datachannel`), and
|
|
30
|
+
* libdatachannel <= 0.24.5 can lose a race on the OFFERER: setting the remote
|
|
31
|
+
* answer hands it to the ICE agent before the answer's fingerprint is
|
|
32
|
+
* committed, ICE can complete at once (the answerer has been sending checks),
|
|
33
|
+
* and the DTLS handshake that follows finds no remote fingerprint to verify
|
|
34
|
+
* against -- `DTLS alert: unknown CA`, the peer connection fails, and
|
|
35
|
+
* libp2p's dial times out. It needs the threads to interleave badly, which a
|
|
36
|
+
* busy CPU makes common: the conformance suite lost it in most runs under
|
|
37
|
+
* load. Each attempt is an independent race, so one retry nearly always
|
|
38
|
+
* succeeds. Fixed upstream by libdatachannel 0235225 ("start DTLS after
|
|
39
|
+
* remote description"); drop the retry once node-datachannel ships it.
|
|
40
|
+
* Browsers implement WebRTC themselves and are not affected.
|
|
41
|
+
*
|
|
42
|
+
* A WebRTC path that cannot come up fails every attempt, and the caller's
|
|
43
|
+
* fallback (the relay circuit) runs as before.
|
|
44
|
+
*/
|
|
45
|
+
export declare function dialWebRTC(node: Libp2p, target: Multiaddr | Multiaddr[], attempts?: number): Promise<Connection>;
|
|
23
46
|
/**
|
|
24
47
|
* Reach the hub over WebRTC through the public relay, and keep ONLY the
|
|
25
48
|
* WebRTC connection.
|
package/dist/hub-link.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hub-link.d.ts","sourceRoot":"","sources":["../src/hub-link.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"hub-link.d.ts","sourceRoot":"","sources":["../src/hub-link.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,yBAAyB,CAAC;AAEpE,OAAO,EAAE,KAAK,eAAe,EAAkB,MAAM,kBAAkB,CAAC;AAExE;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,2EAA2E;AAC3E,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,GAAG,SAAS,EAAE,EAC/B,QAAQ,GAAE,MAAgC,GACzC,OAAO,CAAC,UAAU,CAAC,CAUrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhG;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,CAAC,CAErB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,qBAAqB,GAC7B,YAAY,GACZ,gBAAgB,GAChB,cAAc,GACd,UAAU,GACV,WAAW,GACX,OAAO,CAAC;AAEZ,uHAAuH;AACvH,qBAAa,mBAAoB,SAAQ,KAAK;IAE1C,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,oHAAoH;IACpH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAC9B,QAAQ,CAAC,OAAO,EAAE,qBAAqB;IAJzC,YACW,SAAS,EAAE,MAAM;IAC1B,oHAAoH;IAC3G,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,OAAO,EAAE,qBAAqB,EACvC,OAAO,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,EAI5B;CACF;AA2ED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAenF;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/E;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,2BAA2B,GAAG,eAAe,CAY1F"}
|
package/dist/hub-link.js
CHANGED
|
@@ -24,6 +24,39 @@ import { superviseRelay } from "./reservation.js";
|
|
|
24
24
|
export function hubRoute(hubPeerId, peerId) {
|
|
25
25
|
return `/p2p/${hubPeerId}/p2p-circuit/webrtc/p2p/${peerId}`;
|
|
26
26
|
}
|
|
27
|
+
/** How many times `dialWebRTC` tries a WebRTC upgrade before giving up. */
|
|
28
|
+
export const WEBRTC_UPGRADE_ATTEMPTS = 3;
|
|
29
|
+
/**
|
|
30
|
+
* Dial a `/webrtc` address, trying the upgrade again when it fails.
|
|
31
|
+
*
|
|
32
|
+
* WHY. Under Node, WebRTC is libdatachannel (`node-datachannel`), and
|
|
33
|
+
* libdatachannel <= 0.24.5 can lose a race on the OFFERER: setting the remote
|
|
34
|
+
* answer hands it to the ICE agent before the answer's fingerprint is
|
|
35
|
+
* committed, ICE can complete at once (the answerer has been sending checks),
|
|
36
|
+
* and the DTLS handshake that follows finds no remote fingerprint to verify
|
|
37
|
+
* against -- `DTLS alert: unknown CA`, the peer connection fails, and
|
|
38
|
+
* libp2p's dial times out. It needs the threads to interleave badly, which a
|
|
39
|
+
* busy CPU makes common: the conformance suite lost it in most runs under
|
|
40
|
+
* load. Each attempt is an independent race, so one retry nearly always
|
|
41
|
+
* succeeds. Fixed upstream by libdatachannel 0235225 ("start DTLS after
|
|
42
|
+
* remote description"); drop the retry once node-datachannel ships it.
|
|
43
|
+
* Browsers implement WebRTC themselves and are not affected.
|
|
44
|
+
*
|
|
45
|
+
* A WebRTC path that cannot come up fails every attempt, and the caller's
|
|
46
|
+
* fallback (the relay circuit) runs as before.
|
|
47
|
+
*/
|
|
48
|
+
export async function dialWebRTC(node, target, attempts = WEBRTC_UPGRADE_ATTEMPTS) {
|
|
49
|
+
let lastError;
|
|
50
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
51
|
+
try {
|
|
52
|
+
return await node.dial(target);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
lastError = err;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
throw lastError;
|
|
59
|
+
}
|
|
27
60
|
/**
|
|
28
61
|
* Reach the hub over WebRTC through the public relay, and keep ONLY the
|
|
29
62
|
* WebRTC connection.
|
|
@@ -37,7 +70,7 @@ export function hubRoute(hubPeerId, peerId) {
|
|
|
37
70
|
* prototype; the "connects two members directly" test fails without it.
|
|
38
71
|
*/
|
|
39
72
|
export async function reachHub(node, relayAddr, hubPeerId) {
|
|
40
|
-
await node
|
|
73
|
+
await dialWebRTC(node, multiaddr(`${relayAddr}/p2p-circuit/webrtc/p2p/${hubPeerId}`));
|
|
41
74
|
const limited = node.getConnections(peerIdFromString(hubPeerId)).filter((c) => c.limits != null);
|
|
42
75
|
await Promise.all(limited.map((c) => c.close()));
|
|
43
76
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
export { createDuplexMounts, DUPLEX_PROTOCOL, type DuplexContext, type DuplexHandler, type DuplexMounts, NO_MOUNT, type OpenDuplexInit, openDuplex, type PeerDuplex, type ServeDuplexInit, serveDuplex, } from "./duplex.js";
|
|
18
18
|
export { decodeHopAnswer, HOP_RESERVE_TIMEOUT_MS, HOP_STATUS_NAMES, HOP_STATUS_OK, type HopAnswer, RelayNotConnectedError, type RelayReservationGrant, RelayReservationRefusedError, requestRelayReservation, } from "./hop-reserve.js";
|
|
19
|
-
export { HubReservationError, type HubReservationRefusal, hubRoute, leaveRelay, reachHub, reachHubRelayed, reserveOnHub, type SuperviseHubReservationInit, superviseHubReservation, } from "./hub-link.js";
|
|
19
|
+
export { dialWebRTC, HubReservationError, type HubReservationRefusal, hubRoute, leaveRelay, reachHub, reachHubRelayed, reserveOnHub, type SuperviseHubReservationInit, superviseHubReservation, WEBRTC_UPGRADE_ATTEMPTS, } from "./hub-link.js";
|
|
20
20
|
export { HUB_MAX_RESERVATIONS, type HubRelayComponents, type HubRelayServiceInit, hubRelayService, type IsMember, membershipGater, releaseReservation, } from "./hub-relay.js";
|
|
21
21
|
export { type BytesStore, decodeKey, encodeKey, type GenerateKeyInit, generateKey, type IdentityStore, type IdentityStoreInit, identityStore, peerIdOf, type SignerLike, signerOf, } from "./identity.js";
|
|
22
22
|
export type { CallOnLimitedConnection } from "./link.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;GAOG;AACH,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,QAAQ,EACR,KAAK,cAAc,EACnB,UAAU,EACV,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,EACb,KAAK,SAAS,EACd,sBAAsB,EACtB,KAAK,qBAAqB,EAC1B,4BAA4B,EAC5B,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,mBAAmB,EACnB,KAAK,qBAAqB,EAC1B,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,KAAK,2BAA2B,EAChC,uBAAuB,GACxB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,eAAe,EACf,KAAK,QAAQ,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,KAAK,UAAU,EACf,SAAS,EACT,SAAS,EACT,KAAK,eAAe,EACpB,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,aAAa,EACb,QAAQ,EACR,KAAK,UAAU,EACf,QAAQ,GACT,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EACL,KAAK,YAAY,EACjB,YAAY,EACZ,2BAA2B,EAC3B,SAAS,EACT,uBAAuB,EACvB,uBAAuB,EACvB,yBAAyB,EACzB,yBAAyB,EACzB,4BAA4B,EAC5B,KAAK,QAAQ,EACb,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EACpB,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,KAAK,kBAAkB,EACvB,cAAc,EACd,KAAK,6BAA6B,EAClC,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,UAAU,EACV,YAAY,EACZ,wBAAwB,EACxB,mBAAmB,EACnB,QAAQ,EACR,KAAK,kBAAkB,EACvB,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;GAOG;AACH,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,QAAQ,EACR,KAAK,cAAc,EACnB,UAAU,EACV,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,EACb,KAAK,SAAS,EACd,sBAAsB,EACtB,KAAK,qBAAqB,EAC1B,4BAA4B,EAC5B,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,KAAK,qBAAqB,EAC1B,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,KAAK,2BAA2B,EAChC,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,eAAe,EACf,KAAK,QAAQ,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,KAAK,UAAU,EACf,SAAS,EACT,SAAS,EACT,KAAK,eAAe,EACpB,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,aAAa,EACb,QAAQ,EACR,KAAK,UAAU,EACf,QAAQ,GACT,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EACL,KAAK,YAAY,EACjB,YAAY,EACZ,2BAA2B,EAC3B,SAAS,EACT,uBAAuB,EACvB,uBAAuB,EACvB,yBAAyB,EACzB,yBAAyB,EACzB,4BAA4B,EAC5B,KAAK,QAAQ,EACb,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EACpB,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,KAAK,kBAAkB,EACvB,cAAc,EACd,KAAK,6BAA6B,EAClC,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,UAAU,EACV,YAAY,EACZ,wBAAwB,EACxB,mBAAmB,EACnB,QAAQ,EACR,KAAK,kBAAkB,EACvB,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
export { createDuplexMounts, DUPLEX_PROTOCOL, NO_MOUNT, openDuplex, serveDuplex, } from "./duplex.js";
|
|
18
18
|
export { decodeHopAnswer, HOP_RESERVE_TIMEOUT_MS, HOP_STATUS_NAMES, HOP_STATUS_OK, RelayNotConnectedError, RelayReservationRefusedError, requestRelayReservation, } from "./hop-reserve.js";
|
|
19
|
-
export { HubReservationError, hubRoute, leaveRelay, reachHub, reachHubRelayed, reserveOnHub, superviseHubReservation, } from "./hub-link.js";
|
|
19
|
+
export { dialWebRTC, HubReservationError, hubRoute, leaveRelay, reachHub, reachHubRelayed, reserveOnHub, superviseHubReservation, WEBRTC_UPGRADE_ATTEMPTS, } from "./hub-link.js";
|
|
20
20
|
export { HUB_MAX_RESERVATIONS, hubRelayService, membershipGater, releaseReservation, } from "./hub-relay.js";
|
|
21
21
|
export { decodeKey, encodeKey, generateKey, identityStore, peerIdOf, signerOf, } from "./identity.js";
|
|
22
22
|
export { lastPeerIdOf } from "./multiaddr-parts.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statewalker/httpeers-libp2p",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The transport: nodes, identity, and servePeer — the one place in the extraction that knows what libp2p is.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@multiformats/multiaddr": "^13.0.3",
|
|
49
49
|
"@statewalker/webrun-http-streams": "^0.2.2",
|
|
50
50
|
"@statewalker/webrun-streams": "^0.2.0",
|
|
51
|
-
"@statewalker/webrun-streams-libp2p": "^0.1.
|
|
51
|
+
"@statewalker/webrun-streams-libp2p": "^0.1.6",
|
|
52
52
|
"libp2p": "^3.3.11",
|
|
53
53
|
"@statewalker/httpeers-bridge": "^0.1.3",
|
|
54
54
|
"@statewalker/httpeers-core": "^0.1.2"
|
package/src/hub-link.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import type { Connection, Libp2p } from "@libp2p/interface";
|
|
10
10
|
import { peerIdFromString } from "@libp2p/peer-id";
|
|
11
|
-
import { multiaddr } from "@multiformats/multiaddr";
|
|
11
|
+
import { type Multiaddr, multiaddr } from "@multiformats/multiaddr";
|
|
12
12
|
import { lastPeerIdOf } from "./multiaddr-parts.js";
|
|
13
13
|
import { type RelaySupervisor, superviseRelay } from "./reservation.js";
|
|
14
14
|
|
|
@@ -28,6 +28,44 @@ export function hubRoute(hubPeerId: string, peerId: string): string {
|
|
|
28
28
|
return `/p2p/${hubPeerId}/p2p-circuit/webrtc/p2p/${peerId}`;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/** How many times `dialWebRTC` tries a WebRTC upgrade before giving up. */
|
|
32
|
+
export const WEBRTC_UPGRADE_ATTEMPTS = 3;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Dial a `/webrtc` address, trying the upgrade again when it fails.
|
|
36
|
+
*
|
|
37
|
+
* WHY. Under Node, WebRTC is libdatachannel (`node-datachannel`), and
|
|
38
|
+
* libdatachannel <= 0.24.5 can lose a race on the OFFERER: setting the remote
|
|
39
|
+
* answer hands it to the ICE agent before the answer's fingerprint is
|
|
40
|
+
* committed, ICE can complete at once (the answerer has been sending checks),
|
|
41
|
+
* and the DTLS handshake that follows finds no remote fingerprint to verify
|
|
42
|
+
* against -- `DTLS alert: unknown CA`, the peer connection fails, and
|
|
43
|
+
* libp2p's dial times out. It needs the threads to interleave badly, which a
|
|
44
|
+
* busy CPU makes common: the conformance suite lost it in most runs under
|
|
45
|
+
* load. Each attempt is an independent race, so one retry nearly always
|
|
46
|
+
* succeeds. Fixed upstream by libdatachannel 0235225 ("start DTLS after
|
|
47
|
+
* remote description"); drop the retry once node-datachannel ships it.
|
|
48
|
+
* Browsers implement WebRTC themselves and are not affected.
|
|
49
|
+
*
|
|
50
|
+
* A WebRTC path that cannot come up fails every attempt, and the caller's
|
|
51
|
+
* fallback (the relay circuit) runs as before.
|
|
52
|
+
*/
|
|
53
|
+
export async function dialWebRTC(
|
|
54
|
+
node: Libp2p,
|
|
55
|
+
target: Multiaddr | Multiaddr[],
|
|
56
|
+
attempts: number = WEBRTC_UPGRADE_ATTEMPTS,
|
|
57
|
+
): Promise<Connection> {
|
|
58
|
+
let lastError: unknown;
|
|
59
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
60
|
+
try {
|
|
61
|
+
return await node.dial(target);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
lastError = err;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
throw lastError;
|
|
67
|
+
}
|
|
68
|
+
|
|
31
69
|
/**
|
|
32
70
|
* Reach the hub over WebRTC through the public relay, and keep ONLY the
|
|
33
71
|
* WebRTC connection.
|
|
@@ -41,7 +79,7 @@ export function hubRoute(hubPeerId: string, peerId: string): string {
|
|
|
41
79
|
* prototype; the "connects two members directly" test fails without it.
|
|
42
80
|
*/
|
|
43
81
|
export async function reachHub(node: Libp2p, relayAddr: string, hubPeerId: string): Promise<void> {
|
|
44
|
-
await node
|
|
82
|
+
await dialWebRTC(node, multiaddr(`${relayAddr}/p2p-circuit/webrtc/p2p/${hubPeerId}`));
|
|
45
83
|
const limited = node.getConnections(peerIdFromString(hubPeerId)).filter((c) => c.limits != null);
|
|
46
84
|
await Promise.all(limited.map((c) => c.close()));
|
|
47
85
|
}
|
package/src/index.ts
CHANGED
|
@@ -40,6 +40,7 @@ export {
|
|
|
40
40
|
requestRelayReservation,
|
|
41
41
|
} from "./hop-reserve.js";
|
|
42
42
|
export {
|
|
43
|
+
dialWebRTC,
|
|
43
44
|
HubReservationError,
|
|
44
45
|
type HubReservationRefusal,
|
|
45
46
|
hubRoute,
|
|
@@ -49,6 +50,7 @@ export {
|
|
|
49
50
|
reserveOnHub,
|
|
50
51
|
type SuperviseHubReservationInit,
|
|
51
52
|
superviseHubReservation,
|
|
53
|
+
WEBRTC_UPGRADE_ATTEMPTS,
|
|
52
54
|
} from "./hub-link.js";
|
|
53
55
|
export {
|
|
54
56
|
HUB_MAX_RESERVATIONS,
|