@decentnetwork/peer 0.1.158 → 0.1.159

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 +25 -3
  2. package/package.json +1 -1
package/dist/peer.js CHANGED
@@ -103,6 +103,10 @@ const FAULT_REQUEST_HANG = process.env.DECENT_FAULT_REQUEST_HANG === "1";
103
103
  // toxcore expires announce entries on roughly this timescale, so a node that
104
104
  // acknowledged a store longer ago than this can no longer be counted on.
105
105
  const ANNOUNCE_ENTRY_TTL_MS = readEnvInt("DECENT_ANNOUNCE_ENTRY_TTL_MS", 300_000);
106
+ // How long a partial BULKMSG may go with no new fragment before it is
107
+ // abandoned. Refreshed on every fragment, so it bounds a STALLED transfer, not
108
+ // a large one.
109
+ const BULK_ASSEMBLY_IDLE_MS = readEnvInt("DECENT_BULK_ASSEMBLY_IDLE_MS", 60_000);
106
110
  const FAULT_ANNOUNCE_HANG_RUN = readEnvInt("DECENT_FAULT_ANNOUNCE_HANG", 0);
107
111
  // Classic-DHT maintenance cadence. Every tick we get_nodes toward our own key
108
112
  // (so neighbours store our address and native peers can find our UDP endpoint)
@@ -4826,10 +4830,25 @@ export class Peer {
4826
4830
  * lost fragment just expires this one message after 60s, nothing else). */
4827
4831
  #assembleBulkMsg(friendId, frag, packetNumber) {
4828
4832
  const now = Date.now();
4829
- // Lazy expiry sweep (C uses a 60s assembly timeout).
4833
+ // Lazy expiry sweep. The deadline is IDLE time, not total time.
4834
+ //
4835
+ // It used to be set once, at creation, and never extended — so an assembly
4836
+ // was thrown away 60s after its first fragment no matter how well it was
4837
+ // going. A phone photo is several megabytes; base64 makes it larger still,
4838
+ // and over a TCP relay that takes well over a minute. The transfer was
4839
+ // discarded mid-flight, with every fragment still arriving, and nothing was
4840
+ // logged. Small files were unaffected, which is why this survived testing:
4841
+ // a 300 KB file completes in seconds and never reaches the deadline.
4842
+ //
4843
+ // Idle is the right measure — give up when the SENDER stops, not when the
4844
+ // file is big. Unbounded growth is still prevented by the 16 MB size cap
4845
+ // that totalsz is checked against below.
4830
4846
  for (const [key, entry] of this.#bulkAssembly) {
4831
- if (entry.expireAtMs < now)
4847
+ if (entry.expireAtMs < now) {
4848
+ this.#debugLog(`bulkmsg ${key} abandoned: no fragment for ${Math.round(BULK_ASSEMBLY_IDLE_MS / 1000)}s ` +
4849
+ `(had ${entry.got}/${entry.total} bytes)`);
4832
4850
  this.#bulkAssembly.delete(key);
4851
+ }
4833
4852
  }
4834
4853
  const key = `${friendId}:${frag.tid.toString()}`;
4835
4854
  // A completed assembly is deleted, so a second copy of the same fragments
@@ -4852,7 +4871,7 @@ export class Peer {
4852
4871
  }
4853
4872
  let entry = this.#bulkAssembly.get(key);
4854
4873
  if (!entry) {
4855
- entry = { total: 0, frags: new Map(), got: 0, expireAtMs: now + 60_000 };
4874
+ entry = { total: 0, frags: new Map(), got: 0, expireAtMs: now + BULK_ASSEMBLY_IDLE_MS };
4856
4875
  this.#bulkAssembly.set(key, entry);
4857
4876
  }
4858
4877
  // The first fragment carries totalsz; it may arrive out of order.
@@ -4866,6 +4885,9 @@ export class Peer {
4866
4885
  }
4867
4886
  // Store by packet number; a duplicate (dual-send) fragment is ignored.
4868
4887
  if (frag.data.length > 0 && !entry.frags.has(packetNumber)) {
4888
+ // Progress: push the idle deadline out. This is what makes the timeout
4889
+ // mean "the sender went away" instead of "the file was too big".
4890
+ entry.expireAtMs = now + BULK_ASSEMBLY_IDLE_MS;
4869
4891
  entry.frags.set(packetNumber, frag.data);
4870
4892
  entry.got += frag.data.length;
4871
4893
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.158",
3
+ "version": "0.1.159",
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",