@decentnetwork/peer 0.1.61 → 0.1.62

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 +19 -15
  2. package/package.json +1 -1
package/dist/peer.js CHANGED
@@ -1636,22 +1636,18 @@ export class Peer {
1636
1636
  innerKind === PACKET_ID_FILE_SENDREQUEST ||
1637
1637
  innerKind === PACKET_ID_FILE_CONTROL ||
1638
1638
  innerKind === PACKET_ID_FILE_DATA;
1639
- if (!isSingleTransportKind && opened.packetNumber < (state.receiveBufferStart ?? 0)) {
1640
- continue;
1641
- }
1642
- state.peerBaseNonce[state.peerBaseNonce.length - 2] = packet[1];
1643
- state.peerBaseNonce[state.peerBaseNonce.length - 1] = packet[2];
1644
- incrementNonce(state.peerBaseNonce);
1639
+ // Confirm the transport path + liveness for EVERY decrypted packet —
1640
+ // INCLUDING a dual-send duplicate. Receiving over this transport proves
1641
+ // it works, so this MUST run BEFORE the dedup drop below. Otherwise the
1642
+ // duplicate UDP copy (the relay copy already advanced the buffer) is
1643
+ // dropped without ever marking the direct-UDP path live → lastUdpRecvMs
1644
+ // stays unset → udpFresh false → bulk data (files) never ride the LAN
1645
+ // even when LAN UDP is flowing both ways (the snoopy slow-file bug).
1645
1646
  state.lastPingRecvMs = Date.now();
1646
- // Same TCP-vs-UDP rule as the handshake handlers: don't poison
1647
- // the UDP send-back endpoint when this packet came in via TCP.
1648
1647
  if (this.#remoteIsTcp(remote)) {
1649
1648
  state.hasTcpRoute = true;
1650
1649
  }
1651
1650
  else if (viaRelay) {
1652
- // Arrived over the TURN relay. Track relay freshness separately;
1653
- // do NOT set state.remote (that's the direct endpoint). The relay
1654
- // address it came from is already in state.relayRemote.
1655
1651
  if (!state.lastRelayRecvMs) {
1656
1652
  this.#debugLog(`relay_confirmed friend=${friendId} via=${remote.address}:${remote.port} (TURN relay path live)`);
1657
1653
  }
@@ -1659,10 +1655,9 @@ export class Peer {
1659
1655
  }
1660
1656
  else {
1661
1657
  // Adopt the source as our send endpoint — but NEVER downgrade from a
1662
- // same-LAN (physical) path to a non-LAN source. A packet that loops in
1663
- // via the peer's public / Tailscale-exit endpoint must not knock us off
1664
- // the direct LAN path, which is strictly better. (This is the other
1665
- // half of the "use the physical LAN, not Tailscale" rule.)
1658
+ // same-LAN (physical) path to a non-LAN source (a hairpin packet via
1659
+ // the peer's public / Tailscale-exit endpoint must not knock us off
1660
+ // the direct LAN path, which is strictly better).
1666
1661
  const cur = state.remote?.host;
1667
1662
  const onSameLanAlready = !!cur && !cur.startsWith("tcp:") && isPrivateAddress(cur) && !isCgnatAddress(cur) &&
1668
1663
  getPhysicalLanSubnets().some((s) => isInIpv4Subnet(cur, s));
@@ -1676,6 +1671,15 @@ export class Peer {
1676
1671
  }
1677
1672
  state.lastUdpRecvMs = Date.now();
1678
1673
  }
1674
+ // De-duplicate: skip the DISPATCH + nonce advance for an already-seen
1675
+ // packet number. The transport confirmation above already ran, so a
1676
+ // duplicate still keeps the path fresh.
1677
+ if (!isSingleTransportKind && opened.packetNumber < (state.receiveBufferStart ?? 0)) {
1678
+ continue;
1679
+ }
1680
+ state.peerBaseNonce[state.peerBaseNonce.length - 2] = packet[1];
1681
+ state.peerBaseNonce[state.peerBaseNonce.length - 1] = packet[2];
1682
+ incrementNonce(state.peerBaseNonce);
1679
1683
  state.receiveBufferStart = Math.max(state.receiveBufferStart ?? 0, (opened.packetNumber + 1) >>> 0);
1680
1684
  const kind = opened.payload[0];
1681
1685
  const inner = opened.payload.slice(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.61",
3
+ "version": "0.1.62",
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",