@decentnetwork/peer 0.1.55 → 0.1.56

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 +34 -7
  2. package/package.json +1 -1
package/dist/peer.js CHANGED
@@ -1470,13 +1470,21 @@ export class Peer {
1470
1470
  this.#debugLog(`hs_recv friend=${friendId} initiated=${weInitiated ? 1 : 0} remote=${remote.address}:${remote.port}`);
1471
1471
  if (!wasEstablished) {
1472
1472
  this.#debugLog(`friend_connected friend=${friendId} remote=${remote.address}:${remote.port}`);
1473
- // If we only have a TCP-relay path, immediately tell the peer our
1474
- // public UDP endpoint so they can hole-punch don't wait for the
1475
- // 15s UDP-retry loop, which can miss a flapping relay session's
1476
- // short-lived establishment window. Both sides do this on every
1477
- // (re)establishment, so a brief tcp-relay window is enough to
1478
- // bootstrap the direct UDP path. See docs/UDP-DIRECT-PLAN.md.
1479
- if (state.hasTcpRoute && !state.remote) {
1473
+ // Send our UDP endpoint offer (public srflx + LAN host candidate)
1474
+ // whenever the current path isn't already a same-LAN direct one:
1475
+ // - relay-only sessions need it to bootstrap a direct UDP path; and
1476
+ // - sessions that came up over a PUBLIC UDP endpoint (internet
1477
+ // hairpin) when both peers are actually on the SAME LAN — without
1478
+ // the offer they never learn each other's 10.x/192.168.x address and
1479
+ // stay stuck on the public path, which a symmetric / hairpin NAT
1480
+ // breaks one-way (observed: two boxes on one LAN where each only saw
1481
+ // the other one-directionally). The peer's same-subnet filter drops
1482
+ // the LAN candidate when it doesn't apply, so offering is always safe.
1483
+ const r = state.remote;
1484
+ const remoteIsSameLan = !!r && isPrivateAddress(r.host) && !isCgnatAddress(r.host) &&
1485
+ getPhysicalLanSubnets().some((s) => isInIpv4Subnet(r.host, s));
1486
+ const haveLanToOffer = getPhysicalLanAddresses().some((ip) => isPrivateAddress(ip) && !isCgnatAddress(ip));
1487
+ if ((state.hasTcpRoute && !r) || (!remoteIsSameLan && haveLanToOffer)) {
1480
1488
  void this.#sendUdpEndpointOffer(friendId).catch(() => undefined);
1481
1489
  }
1482
1490
  }
@@ -3961,6 +3969,25 @@ export class Peer {
3961
3969
  if (!node.isTcp)
3962
3970
  void this.#sendDhtPing(node);
3963
3971
  }
3972
+ // 4. LAN-direct upgrade. Re-offer our endpoint (public srflx + LAN host
3973
+ // candidate) to any established friend whose current path is NOT already
3974
+ // a same-LAN address, as long as we have a LAN address to advertise. This
3975
+ // upgrades sessions that came up over a public UDP endpoint (internet
3976
+ // hairpin) to the direct LAN path even without a re-establish, and self-
3977
+ // stops once the path becomes same-LAN. The peer's same-subnet filter
3978
+ // drops the candidate when it doesn't apply, so this is always safe.
3979
+ const haveLan = getPhysicalLanAddresses().some((ip) => isPrivateAddress(ip) && !isCgnatAddress(ip));
3980
+ if (haveLan) {
3981
+ for (const [friendId, session] of this.#friendSessions.entries()) {
3982
+ if (!session.established)
3983
+ continue;
3984
+ const r = session.remote;
3985
+ const remoteIsSameLan = !!r && isPrivateAddress(r.host) && !isCgnatAddress(r.host) &&
3986
+ getPhysicalLanSubnets().some((s) => isInIpv4Subnet(r.host, s));
3987
+ if (!remoteIsSameLan)
3988
+ void this.#sendUdpEndpointOffer(friendId).catch(() => undefined);
3989
+ }
3990
+ }
3964
3991
  }
3965
3992
  /**
3966
3993
  * Send an onion DHT-PK announcement to a friend so they learn our DHT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.55",
3
+ "version": "0.1.56",
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",