@decentnetwork/peer 0.1.144 → 0.1.146
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/compat/express.d.ts +1 -0
- package/dist/compat/express.js +11 -2
- package/dist/peer.js +64 -5
- package/package.json +1 -1
package/dist/compat/express.d.ts
CHANGED
package/dist/compat/express.js
CHANGED
|
@@ -12,8 +12,13 @@ export class LegacyExpressClient {
|
|
|
12
12
|
#selfAddress;
|
|
13
13
|
#currNode = 0;
|
|
14
14
|
#callbacks;
|
|
15
|
+
// Own gate, and env-only until now — so in a browser this client was mute
|
|
16
|
+
// whatever the peer's debug setting was. That is why a stalled pull looked
|
|
17
|
+
// identical to a pull that never ran.
|
|
15
18
|
#debug = process.env.DECENT_DEBUG === "1";
|
|
16
19
|
constructor(opts) {
|
|
20
|
+
if (opts.debug)
|
|
21
|
+
this.#debug = true;
|
|
17
22
|
this.#selfKeyPair = opts.selfKeyPair;
|
|
18
23
|
this.#selfUserId = opts.selfUserId;
|
|
19
24
|
this.#selfAddress = opts.selfAddress;
|
|
@@ -63,8 +68,12 @@ export class LegacyExpressClient {
|
|
|
63
68
|
try {
|
|
64
69
|
body = await this.#http(node, "GET", encodeURIComponent(this.#selfUserId));
|
|
65
70
|
}
|
|
66
|
-
catch {
|
|
67
|
-
|
|
71
|
+
catch (error) {
|
|
72
|
+
// Say so. Swallowing this made an unreachable relay indistinguishable
|
|
73
|
+
// from an empty inbox, and offline mail piled up on the server with
|
|
74
|
+
// nothing anywhere reporting why.
|
|
75
|
+
this.#debugLog(`pull from ${node.host}:${node.port} failed: ${error?.message ?? error}`);
|
|
76
|
+
continue;
|
|
68
77
|
}
|
|
69
78
|
const messages = parseExpressResponseFrames(body);
|
|
70
79
|
if (messages.length === 0) {
|
package/dist/peer.js
CHANGED
|
@@ -598,6 +598,7 @@ export class Peer {
|
|
|
598
598
|
selfKeyPair: this.#keyPair,
|
|
599
599
|
selfUserId: this.userid(),
|
|
600
600
|
selfAddress: this.address(),
|
|
601
|
+
debug: this.#debug,
|
|
601
602
|
callbacks: {
|
|
602
603
|
onOfflineFriendRequest: (fromUserId, packet) => {
|
|
603
604
|
this.#emitOfflineFriendRequest(fromUserId, packet);
|
|
@@ -6873,6 +6874,41 @@ export class Peer {
|
|
|
6873
6874
|
async #sendThroughOnionPath(payloadForNodeD, nodeD, pathOffset = 0, forcedPath) {
|
|
6874
6875
|
const path = forcedPath === "direct" ? undefined : forcedPath ?? this.#selectOnionPath(nodeD, pathOffset);
|
|
6875
6876
|
if (!path) {
|
|
6877
|
+
// No 3-hop UDP path. "Direct" then meant a plain UDP send — which on a
|
|
6878
|
+
// host with no UDP (a browser, where dgram is a socket that drops) goes
|
|
6879
|
+
// straight into the void, silently, forever. Every announce and every
|
|
6880
|
+
// friend-request lookup died here.
|
|
6881
|
+
//
|
|
6882
|
+
// A RELAYED onion request needs only two hops: the relay is node A. So
|
|
6883
|
+
// try that before giving up, and only fall through to the UDP send when
|
|
6884
|
+
// there are no relays or not even two usable hops.
|
|
6885
|
+
if (this.#tcpRelays && this.#tcpRelays.connectedCount() > 0) {
|
|
6886
|
+
const hops = this.#selectTcpOnionHops(nodeD, pathOffset);
|
|
6887
|
+
if (hops) {
|
|
6888
|
+
try {
|
|
6889
|
+
const tcpPacket = createOnionRequest0Tcp({
|
|
6890
|
+
nodeBHost: hops.nodeB.host,
|
|
6891
|
+
nodeBPort: hops.nodeB.port,
|
|
6892
|
+
nodeBPublicKey: hops.nodeB.publicKey,
|
|
6893
|
+
nodeCHost: hops.nodeC.host,
|
|
6894
|
+
nodeCPort: hops.nodeC.port,
|
|
6895
|
+
nodeCPublicKey: hops.nodeC.publicKey,
|
|
6896
|
+
nodeDHost: nodeD.host,
|
|
6897
|
+
nodeDPort: nodeD.port,
|
|
6898
|
+
payloadForNodeD
|
|
6899
|
+
});
|
|
6900
|
+
const sent = this.#tcpRelays.sendOnionRequest(tcpPacket);
|
|
6901
|
+
if (sent > 0) {
|
|
6902
|
+
this.#diagTcpOnionSent += 1;
|
|
6903
|
+
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})`);
|
|
6904
|
+
return "direct";
|
|
6905
|
+
}
|
|
6906
|
+
}
|
|
6907
|
+
catch {
|
|
6908
|
+
/* malformed hop key — fall through to the UDP attempt */
|
|
6909
|
+
}
|
|
6910
|
+
}
|
|
6911
|
+
}
|
|
6876
6912
|
this.#debugLog(`no onion path for ${nodeD.host}:${nodeD.port}, sending direct`);
|
|
6877
6913
|
await this.#sendPacket(payloadForNodeD, nodeD);
|
|
6878
6914
|
return "direct";
|
|
@@ -6923,7 +6959,10 @@ export class Peer {
|
|
|
6923
6959
|
}
|
|
6924
6960
|
return path;
|
|
6925
6961
|
}
|
|
6926
|
-
|
|
6962
|
+
/** Ranked hop candidates for a path to nodeD. Shared by the 3-hop UDP
|
|
6963
|
+
* selector and the 2-hop TCP one — a relay stands in for node A, so a
|
|
6964
|
+
* relayed path needs one fewer usable node than a direct one. */
|
|
6965
|
+
#onionCandidatePool(nodeD) {
|
|
6927
6966
|
const nodeDId = `${nodeD.host}:${nodeD.port}`;
|
|
6928
6967
|
const candidates = [];
|
|
6929
6968
|
const bootstrapIds = new Set(this.#opts.bootstrapNodes.map((node) => `${node.host}:${node.port}`));
|
|
@@ -6972,13 +7011,33 @@ export class Peer {
|
|
|
6972
7011
|
// Ignore bad keys.
|
|
6973
7012
|
}
|
|
6974
7013
|
}
|
|
6975
|
-
if (candidates.length < 3) {
|
|
6976
|
-
return undefined;
|
|
6977
|
-
}
|
|
6978
7014
|
candidates.sort((a, b) => b.score - a.score);
|
|
6979
7015
|
const preferredRelays = candidates.filter((item) => isLikelyStableRelayPort(item.node.port));
|
|
6980
7016
|
const healthy = preferredRelays.filter((item) => item.score > -2);
|
|
6981
|
-
|
|
7017
|
+
return healthy.length >= 3 ? healthy : preferredRelays.length >= 3 ? preferredRelays : candidates;
|
|
7018
|
+
}
|
|
7019
|
+
/** Two hops (B and C) for a relayed onion request. The relay is node A, so
|
|
7020
|
+
* this succeeds on node sets too thin for a direct 3-hop path — which is
|
|
7021
|
+
* the browser's normal state, and where every request used to fall through
|
|
7022
|
+
* to a UDP send that goes nowhere. */
|
|
7023
|
+
#selectTcpOnionHops(nodeD, pathOffset = 0) {
|
|
7024
|
+
const pool = this.#onionCandidatePool(nodeD);
|
|
7025
|
+
if (pool.length < 2)
|
|
7026
|
+
return undefined;
|
|
7027
|
+
const i1 = pathOffset % pool.length;
|
|
7028
|
+
const i2 = (pathOffset + 1) % pool.length;
|
|
7029
|
+
if (i1 === i2)
|
|
7030
|
+
return undefined;
|
|
7031
|
+
const hop = (x) => ({
|
|
7032
|
+
node: x.node, host: x.node.host, port: x.node.port, publicKey: x.publicKey
|
|
7033
|
+
});
|
|
7034
|
+
return { nodeB: hop(pool[i1]), nodeC: hop(pool[i2]) };
|
|
7035
|
+
}
|
|
7036
|
+
#selectOnionPath(nodeD, pathOffset = 0) {
|
|
7037
|
+
const pool = this.#onionCandidatePool(nodeD);
|
|
7038
|
+
if (pool.length < 3) {
|
|
7039
|
+
return undefined;
|
|
7040
|
+
}
|
|
6982
7041
|
const count = pool.length;
|
|
6983
7042
|
const i0 = pathOffset % count;
|
|
6984
7043
|
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.146",
|
|
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",
|