@decentnetwork/peer 0.1.131 → 0.1.132

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 +30 -0
  2. package/package.json +1 -1
package/dist/peer.js CHANGED
@@ -3585,6 +3585,36 @@ export class Peer {
3585
3585
  if (session.remote && friend.status !== "online") {
3586
3586
  this.#setFriendOnline(friendId, session.remote.host, session.remote.port);
3587
3587
  }
3588
+ // Self-heal a remote that was poisoned before we knew better.
3589
+ //
3590
+ // The adoption guards stop a bad endpoint getting IN, but a session
3591
+ // that already holds one never re-examines it — and session.remote is
3592
+ // sticky, so the daemon keeps addressing a host it cannot reach for as
3593
+ // long as the session lives. Seen between tokyo (Japan) and a laptop
3594
+ // at home: udpRemote stayed 10.0.0.245 across restarts with
3595
+ // lastUdpRecvMs null the whole time, while traffic limped along the
3596
+ // relay. Symptom is a link that is fast when it works and dead in
3597
+ // stretches, because only some paths reach the peer.
3598
+ //
3599
+ // The two conditions together are what make this safe: an address we
3600
+ // could never route to, AND no UDP ever received on this session. A
3601
+ // working same-LAN peer fails the first test; a peer we have actually
3602
+ // heard from fails the second.
3603
+ if (session.remote &&
3604
+ !session.remote.host.startsWith("tcp:") &&
3605
+ session.lastUdpRecvMs === undefined &&
3606
+ isPrivateAddress(session.remote.host) &&
3607
+ !isCgnatAddress(session.remote.host) &&
3608
+ !getPhysicalLanSubnets().some((sub) => isInIpv4Subnet(session.remote.host, sub))) {
3609
+ const dead = session.remote;
3610
+ this.#debugLog(`clearing unreachable remote ${dead.host}:${dead.port} for ${friendId} ` +
3611
+ `— private, off our LANs, and never received UDP from it`);
3612
+ session.remote = undefined;
3613
+ session.lanRemoteHost = undefined;
3614
+ // Drop it from the candidate list too, or the next sweep re-adopts
3615
+ // the same address and we are back where we started.
3616
+ session.endpointCandidates = (session.endpointCandidates ?? []).filter((c) => !(c.host === dead.host && c.port === dead.port));
3617
+ }
3588
3618
  // Phase 1.2: keep retrying UDP holepunch even after the session
3589
3619
  // is already "established" via TCP relay. The toxcore-derived
3590
3620
  // logic above stops trying once anybody is reachable, which is
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.131",
3
+ "version": "0.1.132",
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",