@decentnetwork/peer 0.1.144 → 0.1.145
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/peer.js +63 -5
- package/package.json +1 -1
package/dist/peer.js
CHANGED
|
@@ -6873,6 +6873,41 @@ export class Peer {
|
|
|
6873
6873
|
async #sendThroughOnionPath(payloadForNodeD, nodeD, pathOffset = 0, forcedPath) {
|
|
6874
6874
|
const path = forcedPath === "direct" ? undefined : forcedPath ?? this.#selectOnionPath(nodeD, pathOffset);
|
|
6875
6875
|
if (!path) {
|
|
6876
|
+
// No 3-hop UDP path. "Direct" then meant a plain UDP send — which on a
|
|
6877
|
+
// host with no UDP (a browser, where dgram is a socket that drops) goes
|
|
6878
|
+
// straight into the void, silently, forever. Every announce and every
|
|
6879
|
+
// friend-request lookup died here.
|
|
6880
|
+
//
|
|
6881
|
+
// A RELAYED onion request needs only two hops: the relay is node A. So
|
|
6882
|
+
// try that before giving up, and only fall through to the UDP send when
|
|
6883
|
+
// there are no relays or not even two usable hops.
|
|
6884
|
+
if (this.#tcpRelays && this.#tcpRelays.connectedCount() > 0) {
|
|
6885
|
+
const hops = this.#selectTcpOnionHops(nodeD, pathOffset);
|
|
6886
|
+
if (hops) {
|
|
6887
|
+
try {
|
|
6888
|
+
const tcpPacket = createOnionRequest0Tcp({
|
|
6889
|
+
nodeBHost: hops.nodeB.host,
|
|
6890
|
+
nodeBPort: hops.nodeB.port,
|
|
6891
|
+
nodeBPublicKey: hops.nodeB.publicKey,
|
|
6892
|
+
nodeCHost: hops.nodeC.host,
|
|
6893
|
+
nodeCPort: hops.nodeC.port,
|
|
6894
|
+
nodeCPublicKey: hops.nodeC.publicKey,
|
|
6895
|
+
nodeDHost: nodeD.host,
|
|
6896
|
+
nodeDPort: nodeD.port,
|
|
6897
|
+
payloadForNodeD
|
|
6898
|
+
});
|
|
6899
|
+
const sent = this.#tcpRelays.sendOnionRequest(tcpPacket);
|
|
6900
|
+
if (sent > 0) {
|
|
6901
|
+
this.#diagTcpOnionSent += 1;
|
|
6902
|
+
this.#debugLog(`no 3-hop path for ${nodeD.host}:${nodeD.port} — relayed 2-hop onion via ${sent} relay(s) (B=${hops.nodeB.host} C=${hops.nodeC.host})`);
|
|
6903
|
+
return "direct";
|
|
6904
|
+
}
|
|
6905
|
+
}
|
|
6906
|
+
catch {
|
|
6907
|
+
/* malformed hop key — fall through to the UDP attempt */
|
|
6908
|
+
}
|
|
6909
|
+
}
|
|
6910
|
+
}
|
|
6876
6911
|
this.#debugLog(`no onion path for ${nodeD.host}:${nodeD.port}, sending direct`);
|
|
6877
6912
|
await this.#sendPacket(payloadForNodeD, nodeD);
|
|
6878
6913
|
return "direct";
|
|
@@ -6923,7 +6958,10 @@ export class Peer {
|
|
|
6923
6958
|
}
|
|
6924
6959
|
return path;
|
|
6925
6960
|
}
|
|
6926
|
-
|
|
6961
|
+
/** Ranked hop candidates for a path to nodeD. Shared by the 3-hop UDP
|
|
6962
|
+
* selector and the 2-hop TCP one — a relay stands in for node A, so a
|
|
6963
|
+
* relayed path needs one fewer usable node than a direct one. */
|
|
6964
|
+
#onionCandidatePool(nodeD) {
|
|
6927
6965
|
const nodeDId = `${nodeD.host}:${nodeD.port}`;
|
|
6928
6966
|
const candidates = [];
|
|
6929
6967
|
const bootstrapIds = new Set(this.#opts.bootstrapNodes.map((node) => `${node.host}:${node.port}`));
|
|
@@ -6972,13 +7010,33 @@ export class Peer {
|
|
|
6972
7010
|
// Ignore bad keys.
|
|
6973
7011
|
}
|
|
6974
7012
|
}
|
|
6975
|
-
if (candidates.length < 3) {
|
|
6976
|
-
return undefined;
|
|
6977
|
-
}
|
|
6978
7013
|
candidates.sort((a, b) => b.score - a.score);
|
|
6979
7014
|
const preferredRelays = candidates.filter((item) => isLikelyStableRelayPort(item.node.port));
|
|
6980
7015
|
const healthy = preferredRelays.filter((item) => item.score > -2);
|
|
6981
|
-
|
|
7016
|
+
return healthy.length >= 3 ? healthy : preferredRelays.length >= 3 ? preferredRelays : candidates;
|
|
7017
|
+
}
|
|
7018
|
+
/** Two hops (B and C) for a relayed onion request. The relay is node A, so
|
|
7019
|
+
* this succeeds on node sets too thin for a direct 3-hop path — which is
|
|
7020
|
+
* the browser's normal state, and where every request used to fall through
|
|
7021
|
+
* to a UDP send that goes nowhere. */
|
|
7022
|
+
#selectTcpOnionHops(nodeD, pathOffset = 0) {
|
|
7023
|
+
const pool = this.#onionCandidatePool(nodeD);
|
|
7024
|
+
if (pool.length < 2)
|
|
7025
|
+
return undefined;
|
|
7026
|
+
const i1 = pathOffset % pool.length;
|
|
7027
|
+
const i2 = (pathOffset + 1) % pool.length;
|
|
7028
|
+
if (i1 === i2)
|
|
7029
|
+
return undefined;
|
|
7030
|
+
const hop = (x) => ({
|
|
7031
|
+
node: x.node, host: x.node.host, port: x.node.port, publicKey: x.publicKey
|
|
7032
|
+
});
|
|
7033
|
+
return { nodeB: hop(pool[i1]), nodeC: hop(pool[i2]) };
|
|
7034
|
+
}
|
|
7035
|
+
#selectOnionPath(nodeD, pathOffset = 0) {
|
|
7036
|
+
const pool = this.#onionCandidatePool(nodeD);
|
|
7037
|
+
if (pool.length < 3) {
|
|
7038
|
+
return undefined;
|
|
7039
|
+
}
|
|
6982
7040
|
const count = pool.length;
|
|
6983
7041
|
const i0 = pathOffset % count;
|
|
6984
7042
|
const i1 = (pathOffset + 1) % count;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/peer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.145",
|
|
4
4
|
"description": "Pure TypeScript port of Elastos Carrier (toxcore-derived) P2P messaging. DHT, onion routing, TCP relay, FlatBuffers app payloads, Express offline relay. Wire-compatible with iOS Beagle and the Carrier C SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|