@decentnetwork/peer 0.1.114 → 0.1.115

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 +36 -1
  2. package/package.json +1 -1
package/dist/peer.js CHANGED
@@ -1808,6 +1808,20 @@ export class Peer {
1808
1808
  if (!fromTcp) {
1809
1809
  this.#cacheFriendRemote(senderId, remote.address, remote.port, request.senderRealPublicKey, request.senderDhtPublicKey);
1810
1810
  }
1811
+ else if (request.senderDhtPublicKey && request.senderDhtPublicKey.length === 32) {
1812
+ // TCP arrival: skip the endpoint, but STILL learn the sender's DHT
1813
+ // key. Natives rotate it every app restart and the relay routes
1814
+ // CRYPTO_DATA by it — a relay-only native (its UDP unreachable to
1815
+ // us) otherwise kept its stale key here, every routed send went to
1816
+ // a key the relay didn't know, and the peer — never receiving our
1817
+ // data — re-keyed every 8s forever (the iPhone churn loop).
1818
+ const session = this.#friendSessions.get(senderId);
1819
+ if (session && !(session.friendDhtPublicKey && Buffer.from(session.friendDhtPublicKey).equals(Buffer.from(request.senderDhtPublicKey)))) {
1820
+ this.#debugLog(`dht_key_from_tcp_cookie friend=${senderId} new=${carrierIdFromPublicKey(request.senderDhtPublicKey)}`);
1821
+ session.friendDhtPublicKey = request.senderDhtPublicKey;
1822
+ }
1823
+ this.#learnFriendDhtKey(senderId, request.senderDhtPublicKey);
1824
+ }
1811
1825
  const response = createCookieResponse({
1812
1826
  request,
1813
1827
  receiverDhtSecretKey: this.#keyPair.secretKey,
@@ -2071,8 +2085,18 @@ export class Peer {
2071
2085
  else {
2072
2086
  if (!state.friendRealPublicKey)
2073
2087
  state.friendRealPublicKey = hs.senderRealPublicKey;
2074
- if (!state.friendDhtPublicKey)
2088
+ // ALWAYS take the handshake's DHT key, not only when empty: the
2089
+ // handshake authenticates the sender's real key, and natives rotate
2090
+ // their DHT key every restart. Keeping a stale key here sent every
2091
+ // relay-routed CRYPTO_DATA packet to a key the relay didn't know —
2092
+ // silent drop, peer re-keys every 8s (iPhone churn loop).
2093
+ if (hs.senderDhtPublicKey && hs.senderDhtPublicKey.length === 32 &&
2094
+ !(state.friendDhtPublicKey && Buffer.from(state.friendDhtPublicKey).equals(Buffer.from(hs.senderDhtPublicKey)))) {
2095
+ if (state.friendDhtPublicKey) {
2096
+ this.#debugLog(`dht_key_from_hs friend=${friendId} new=${carrierIdFromPublicKey(hs.senderDhtPublicKey)}`);
2097
+ }
2075
2098
  state.friendDhtPublicKey = hs.senderDhtPublicKey;
2099
+ }
2076
2100
  }
2077
2101
  if (hs.senderDhtPublicKey && hs.senderDhtPublicKey.length === 32) {
2078
2102
  this.#learnFriendDhtKey(friendId, hs.senderDhtPublicKey);
@@ -5512,6 +5536,17 @@ export class Peer {
5512
5536
  }
5513
5537
  if (!friendId)
5514
5538
  return;
5539
+ // If ANY established session already uses this DHT key, the key's owner
5540
+ // is known and it is not `friendId` — a shared own-host target (the
5541
+ // simulator) answers EVERY prober's probe, and without this check each
5542
+ // stranded friend in turn "adopted" the sim's key during its slot,
5543
+ // endlessly poisoning its own routing.
5544
+ for (const [fid, s] of this.#friendSessions) {
5545
+ if (fid === friendId || !s.established || !s.friendDhtPublicKey)
5546
+ continue;
5547
+ if (Buffer.from(s.friendDhtPublicKey).equals(Buffer.from(senderDhtPk)))
5548
+ return;
5549
+ }
5515
5550
  // The sender pk currently maps to a DIFFERENT friend. If that friend's
5516
5551
  // session is ESTABLISHED, the key genuinely belongs to them — don't
5517
5552
  // cross-wire. If it is NOT established, the mapping itself may be a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.114",
3
+ "version": "0.1.115",
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",