@decentnetwork/peer 0.1.57 → 0.1.58

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.
Files changed (2) hide show
  1. package/dist/peer.js +31 -5
  2. package/package.json +1 -1
package/dist/peer.js CHANGED
@@ -82,6 +82,14 @@ const FRIEND_PING_INTERVAL_MS = readEnvInt("DECENT_FRIEND_PING_INTERVAL_MS", 400
82
82
  // slow enough not to burn CPU on idle peers. Tunable via env.
83
83
  const FRIEND_CONNECTION_LOOP_MS = readEnvInt("DECENT_FRIEND_CONNECTION_LOOP_MS", 250);
84
84
  const FRIEND_TIMEOUT_MS = readEnvInt("DECENT_FRIEND_TIMEOUT_MS", 32000);
85
+ // Half-open breaker: if the peer proposes a NEW session key this many times over
86
+ // this long while our session looks "alive", accept it (the peer can't decrypt
87
+ // our current session — a desynced half-open session, observed as a flood of
88
+ // "no session matched"). Each handshake carries a fresh cookie so these are
89
+ // genuine attempts, not replays. Bounded so it never fires on a healthy session.
90
+ const REHS_ACCEPT_COUNT = readEnvInt("DECENT_REHS_ACCEPT_COUNT", 4);
91
+ const REHS_ACCEPT_MS = readEnvInt("DECENT_REHS_ACCEPT_MS", 2500);
92
+ const REHS_WINDOW_MS = readEnvInt("DECENT_REHS_WINDOW_MS", 8000);
85
93
  // How long a relay path stays "confirmed" (carrying bulk data on its own, no
86
94
  // tcp-relay fan-out) after the last packet received over it. The relay
87
95
  // keepalive refreshes this every ~4s on a healthy path, so a generous window
@@ -1436,12 +1444,30 @@ export class Peer {
1436
1444
  const lastAlive = state.lastPingRecvMs ?? state.sessionEstablishedAtMs;
1437
1445
  const currentSessionAlive = Date.now() - lastAlive < FRIEND_TIMEOUT_MS;
1438
1446
  if (sinceEstablished > 1000 && currentSessionAlive) {
1439
- // Verbose onlypeers retransmit handshakes aggressively, so
1440
- // this line fires dozens of times per minute on a stuck pair
1441
- // and drowns out signal. Visible with DECENT_DEBUG_VERBOSE=1.
1442
- this.#debugVerboseLog(`hs_recv ignored friend=${friendId} (new session pubkey on live established session, ${sinceEstablished}ms after establish)`);
1443
- return;
1447
+ // Half-open breaker. Our session looks alive but "alive" only means
1448
+ // WE are receiving (possibly only over the relay). If the peer KEEPS
1449
+ // proposing a new key, THEIR side can't decrypt our packets: a desynced
1450
+ // half-open session (observed snoopy↔mac on one LAN as 288k "no session
1451
+ // matched"). Rejecting forever deadlocks. So count sustained attempts
1452
+ // and, past the threshold, accept the new key to re-converge. Bounded
1453
+ // to sustained attempts so it never disturbs a healthy session.
1454
+ const now = Date.now();
1455
+ if (state.rehsFirstMs === undefined || now - (state.rehsLastMs ?? 0) > REHS_WINDOW_MS) {
1456
+ state.rehsFirstMs = now;
1457
+ state.rehsCount = 0;
1458
+ }
1459
+ state.rehsLastMs = now;
1460
+ state.rehsCount = (state.rehsCount ?? 0) + 1;
1461
+ const stuck = state.rehsCount >= REHS_ACCEPT_COUNT && now - state.rehsFirstMs >= REHS_ACCEPT_MS;
1462
+ if (!stuck) {
1463
+ this.#debugVerboseLog(`hs_recv ignored friend=${friendId} (new session pubkey on live session, attempt ${state.rehsCount}, ${sinceEstablished}ms after establish)`);
1464
+ return;
1465
+ }
1466
+ this.#debugLog(`hs_recv accepting re-handshake friend=${friendId} (half-open breaker: ${state.rehsCount} new-key attempts over ${now - state.rehsFirstMs}ms — peer can't decrypt our session)`);
1444
1467
  }
1468
+ // Converging on a fresh session — clear the breaker counter.
1469
+ state.rehsCount = 0;
1470
+ state.rehsFirstMs = undefined;
1445
1471
  this.#debugLog(`hs_recv accepting re-handshake friend=${friendId} (current session wedged/dead, ` +
1446
1472
  `lastPingRecv=${state.lastPingRecvMs ? Date.now() - state.lastPingRecvMs + "ms ago" : "never"})`);
1447
1473
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.57",
3
+ "version": "0.1.58",
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",