@decentnetwork/peer 0.1.58 → 0.1.60
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 +39 -2
- package/package.json +1 -1
package/dist/peer.js
CHANGED
|
@@ -90,6 +90,9 @@ const FRIEND_TIMEOUT_MS = readEnvInt("DECENT_FRIEND_TIMEOUT_MS", 32000);
|
|
|
90
90
|
const REHS_ACCEPT_COUNT = readEnvInt("DECENT_REHS_ACCEPT_COUNT", 4);
|
|
91
91
|
const REHS_ACCEPT_MS = readEnvInt("DECENT_REHS_ACCEPT_MS", 2500);
|
|
92
92
|
const REHS_WINDOW_MS = readEnvInt("DECENT_REHS_WINDOW_MS", 8000);
|
|
93
|
+
// Re-handshake when we keep receiving undecryptable crypto data from a known
|
|
94
|
+
// friend's endpoint (desynced sessions), rate-limited per friend.
|
|
95
|
+
const REINIT_ON_DESYNC_MS = readEnvInt("DECENT_REINIT_ON_DESYNC_MS", 2000);
|
|
93
96
|
// How long a relay path stays "confirmed" (carrying bulk data on its own, no
|
|
94
97
|
// tcp-relay fan-out) after the last packet received over it. The relay
|
|
95
98
|
// keepalive refreshes this every ~4s on a healthy path, so a generous window
|
|
@@ -1825,7 +1828,27 @@ export class Peer {
|
|
|
1825
1828
|
this.#debugVerboseLog(`unknown messenger packet kind ${kind} from ${friendId}`);
|
|
1826
1829
|
return;
|
|
1827
1830
|
}
|
|
1828
|
-
|
|
1831
|
+
// We received crypto data we can't decrypt from a KNOWN friend's endpoint:
|
|
1832
|
+
// our two sessions are desynced (different keys) and NEITHER side will
|
|
1833
|
+
// re-handshake on its own, because each believes it is still established
|
|
1834
|
+
// (the half-open breaker can't help — no handshakes are being exchanged).
|
|
1835
|
+
// Kick a fresh handshake so we re-converge. Rate-limited per friend so a
|
|
1836
|
+
// flood of undecryptable packets doesn't spam cookie requests.
|
|
1837
|
+
if (!this.#remoteIsTcp(remote) && !viaRelay) {
|
|
1838
|
+
for (const [fid, st] of this.#friendSessions.entries()) {
|
|
1839
|
+
const matches = (st.remote?.host === remote.address && st.remote?.port === remote.port) ||
|
|
1840
|
+
(st.endpointCandidates ?? []).some((c) => c.host === remote.address && c.port === remote.port);
|
|
1841
|
+
if (!matches)
|
|
1842
|
+
continue;
|
|
1843
|
+
if (Date.now() - (st.lastReinitMs ?? 0) > REINIT_ON_DESYNC_MS) {
|
|
1844
|
+
st.lastReinitMs = Date.now();
|
|
1845
|
+
this.#debugLog(`no-session-matched from ${remote.address}:${remote.port} (friend ${fid}) — desynced, re-initiating handshake`);
|
|
1846
|
+
void this.#initiateSession(fid).catch(() => undefined);
|
|
1847
|
+
}
|
|
1848
|
+
break;
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
this.#debugVerboseLog(`crypto data received from ${remote.address}:${remote.port} but no session matched`);
|
|
1829
1852
|
return;
|
|
1830
1853
|
}
|
|
1831
1854
|
if (packet[0] === NET_PACKET_ONION_DATA_RESPONSE && this.#announceDataKey) {
|
|
@@ -4034,8 +4057,22 @@ export class Peer {
|
|
|
4034
4057
|
const r = session.remote;
|
|
4035
4058
|
const remoteIsSameLan = !!r && isPrivateAddress(r.host) && !isCgnatAddress(r.host) &&
|
|
4036
4059
|
getPhysicalLanSubnets().some((s) => isInIpv4Subnet(r.host, s));
|
|
4037
|
-
if (!remoteIsSameLan)
|
|
4060
|
+
if (!remoteIsSameLan) {
|
|
4061
|
+
// If we ALREADY hold a same-LAN candidate for this peer (learned from
|
|
4062
|
+
// an earlier offer), switch the session onto it NOW — don't wait to
|
|
4063
|
+
// receive yet another offer at exactly the right moment. That delay is
|
|
4064
|
+
// what kept sessions stuck on the public/Tailscale-hairpin path after
|
|
4065
|
+
// the staggered restarts. Then send a keepalive over the LAN so the
|
|
4066
|
+
// peer learns our LAN source and replies over it; the downgrade guard
|
|
4067
|
+
// keeps us there once it sticks.
|
|
4068
|
+
const lanCand = (session.endpointCandidates ?? []).find((c) => isPrivateAddress(c.host) && !isCgnatAddress(c.host) &&
|
|
4069
|
+
getPhysicalLanSubnets().some((s) => isInIpv4Subnet(c.host, s)));
|
|
4070
|
+
if (lanCand) {
|
|
4071
|
+
session.remote = { host: lanCand.host, port: lanCand.port };
|
|
4072
|
+
void this.#sendMessengerPacket(friendId, PACKET_ID_ALIVE, new Uint8Array()).catch(() => undefined);
|
|
4073
|
+
}
|
|
4038
4074
|
void this.#sendUdpEndpointOffer(friendId).catch(() => undefined);
|
|
4075
|
+
}
|
|
4039
4076
|
}
|
|
4040
4077
|
}
|
|
4041
4078
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/peer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.60",
|
|
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",
|