@decentnetwork/peer 0.1.50 → 0.1.52

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.
package/dist/peer.js CHANGED
@@ -193,6 +193,11 @@ export class Peer {
193
193
  #persistSeq = 0; // makes atomic friend-store temp filenames unique per write
194
194
  #cookieSymmetricKey;
195
195
  #friendSessions = new Map();
196
+ /** source "ip:port" → friendId, so an inbound crypto-data packet is decrypted
197
+ * against the right session FIRST instead of scanning every friend (O(N) nacl
198
+ * ops/packet starved high-rate CCTV forwarding). Self-correcting: stale
199
+ * entries just miss and fall back to the scan. */
200
+ #cryptoEndpointIndex = new Map();
196
201
  #express;
197
202
  #expressPollTimer;
198
203
  /**
@@ -1549,8 +1554,17 @@ export class Peer {
1549
1554
  return;
1550
1555
  }
1551
1556
  if (packet[0] === NET_PACKET_CRYPTO_DATA) {
1552
- for (const [friendId, state] of this.#friendSessions.entries()) {
1553
- if (!state.sessionSharedKey || !state.peerBaseNonce) {
1557
+ // Demux by source endpoint: try the session last seen here FIRST so a
1558
+ // high-rate stream (CCTV) isn't decrypted against every friend session
1559
+ // (O(friends) nacl ops per packet, which starved forwarding). Falls back
1560
+ // to scanning all sessions for a new/changed endpoint, then caches the
1561
+ // match. A stale hint just misses and falls through harmlessly.
1562
+ const epKey = `${remote.address}:${remote.port}`;
1563
+ const hinted = this.#cryptoEndpointIndex.get(epKey);
1564
+ const ids = hinted !== undefined ? [hinted, ...this.#friendSessions.keys()] : this.#friendSessions.keys();
1565
+ for (const friendId of ids) {
1566
+ const state = this.#friendSessions.get(friendId);
1567
+ if (!state || !state.sessionSharedKey || !state.peerBaseNonce) {
1554
1568
  continue;
1555
1569
  }
1556
1570
  const opened = openCryptoDataPacket(packet, {
@@ -1560,6 +1574,11 @@ export class Peer {
1560
1574
  if (!opened) {
1561
1575
  continue;
1562
1576
  }
1577
+ if (hinted !== friendId) {
1578
+ if (this.#cryptoEndpointIndex.size > 4096)
1579
+ this.#cryptoEndpointIndex.clear();
1580
+ this.#cryptoEndpointIndex.set(epKey, friendId);
1581
+ }
1563
1582
  // De-duplicate — but ONLY for dual-sent channels. The dual-send path
1564
1583
  // delivers a lossless packet over BOTH UDP and relay with the SAME
1565
1584
  // packet number, so without this guard a chat message is dispatched
@@ -62,6 +62,19 @@ export class UdpTransport extends EventEmitter {
62
62
  const onListening = () => {
63
63
  cleanup();
64
64
  this.#bound = true;
65
+ // Enlarge the kernel socket buffers. The default (often ~64-256 KB) is
66
+ // smaller than a single file-transfer send window (≈ 256 KB) plus the
67
+ // CCTV stream, so sustained bursts overflowed and the kernel silently
68
+ // dropped datagrams — a big file would stick at 0% as its early chunks
69
+ // kept getting dropped. 4 MB absorbs the bursts on both directions.
70
+ try {
71
+ socket.setSendBufferSize(4 * 1024 * 1024);
72
+ }
73
+ catch { /* best-effort */ }
74
+ try {
75
+ socket.setRecvBufferSize(4 * 1024 * 1024);
76
+ }
77
+ catch { /* best-effort */ }
65
78
  resolve();
66
79
  };
67
80
  const onError = (error) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.50",
3
+ "version": "0.1.52",
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",