nx_torrent_get.nx source
↩ module page · 1016 lines · 83401 B
1// nx_torrent_get.nx -- the DOWNLOAD WORKER (X-TORRENT-LIVE-001 L5): magnet -> a real file on disk +
2// a live STATUS file the daemon/UI polls. Composes the proven engine (mg_parse + cl_announce + BEP-3
3// handshake + BEP-9 metadata + BEP-3 data pieces + sha1 verify). FORK-BOUNDED per peer (parent
4// wait4(WNOHANG)+sys_sleep_ms+nx_kill so an unreachable peer can't hang ~127s). Forked children share
5// progress via on-disk files: outfile (non-trunc, write each verified piece at its offset), donefile
6// (bitmap, set [i]=1 per piece), npcfile (piece count). argv[1]=magnet argv[2]=outdir.
7// nx_sov_build_run drops args -> run the built elf directly. license_tier: ORIGINAL
8//
9// module: nishi-core.torrent.get
10// depends: nishi-core.torrent.peer_piece_live, nishi-core.torrent.magnet
11import "nx_connect.nx" // bounded connect -- SO_RCVTIMEO does NOT bound connect()
12import "nx_peer_piece_live.nx"
13import "nx_magnet.nx"
14import "nx_http_tracker.nx"
15import "nx_dht_get_peers.nx"
16import "nx_endgame.nx" // rarest-first availability map + endgame last-piece racing (Phase 2; re-exports nx_avail_map's am_*)
17import "nx_pex.nx" // BEP-11 peer-exchange: harvest MORE peers (incl. seeders) from connected peers -> finish trackerless/stuck swarms
18import "nx_tracker_list.nx" // DATA-DRIVEN HTTP/HTTPS tracker list (trackers.txt) -> tl_next_line -> wider peer discovery
19import "nx_mse_wire.nx" // MSE/PE anti-throttle: try an encrypted handshake per peer, fall back to plaintext (DPI can't fingerprint)
20import "nx_ipfilter.nx" // ip-filter: drop known-bad / anti-P2P-monitor peer IPs from the peer list (privacy while WAN-seeding)
21import "nx_poolgov.nx" // seq1402/1410/1450: pool width DERIVED from this machine + the live shared budget, never a literal
22const TG_MAGIC_1410: i64 = 1410
23const TG_MAGIC_1450: i64 = 1450
24const TG_MAGIC_1024: i64 = 1024
25const TG_MAGIC_15728640: i64 = 15728640
26const TG_MAGIC_65536: i64 = 65536
27const TG_MAGIC_262144: i64 = 262144
28const TG_MAGIC_40000: i64 = 40000
29// seq1317: ticks a peer-pool slot must rest after being FILLED before it may be refilled. The loop
30// sleeps 2s per tick, so 2 = a ~4s floor between forks into the SAME slot -- invisible to a healthy
31// peer (its slot stays occupied) and decisive against a dead one (which used to re-fork every tick).
32const TG_SLOT_COOLDOWN: i64 = 2
33// Peer connect budget. The 6s sys_set_socket_timeout beside each connect() only ever governed
34// READS -- connect() itself ran to the kernel's ~127s SYN ceiling, so one dead peer held a slot
35// for two minutes. Same 6s intent, now actually enforced on the connect.
36const TG_CONNECT_MS: i64 = 6000
37// Watchdog for the BACKGROUND ANNOUNCE (tg_announce_bg). Ticks are 2s. A tracker round that has
38// not finished in 90s is against a black-holed host -- the kernel's own SYN timeout is ~127s, so
39// this reclaims the slot BEFORE the kernel would, and well inside the 30s announce cadence's
40// tolerance for a skipped cycle. Derived from those two measured numbers, not chosen by taste.
41const TG_ANN_MAX_TICKS: i64 = 45
42const TG_MAGIC_2000000: i64 = 2000000
43const TG_MAGIC_2000000: i64 = 2000000
44const TG_MAGIC_16383: i64 = 16383
45const TG_MAGIC_16384: i64 = 16384
46const TG_MAGIC_1000000000: i64 = 1000000000
47const TG_MAGIC_65535: i64 = 65535
48const TG_MAGIC_1337: i64 = 1337
49const TG_MAGIC_262143: i64 = 262143
50const TG_MAGIC_80000: i64 = 80000
51const TG_MAGIC_2000: i64 = 2000
52
53// Endgame entry: once this many or fewer OBTAINABLE pieces remain (all already in-flight), idle
54// children race them instead of exiting, to beat the one slow holder (the dominant tail-latency
55// source). ~half the 32-child pool: above it there's fresh non-duplicated work; below it, racing
56// the tail beats leaving children idle. A heuristic lever, not a correctness value (SHA1 still guards).
57const TG_ENDGAME_THRESHOLD: i64 = 16
58// BULK unchoke-patience window (seconds). A pure-leecher must OUTLAST a seeder's optimistic-unchoke rotation
59// (~30s in mainline) to ever get served -- bailing at the 6s connect timeout or on the first CHOKE is THE
60// "holders exist but we never pulled" bug (seedeval "IGNORING", 2464 missing pieces w/ holders). We keep the
61// connection alive (keep-alives) waiting for the unchoke up to this window, then free the slot. Bounds slot
62// hold-time so the pool still turns over if every holder keeps choking us.
63const TG_UNCHOKE_WAIT: i64 = 90
64// DATA-PHASE read timeout (seconds). The 6s CONNECT timeout is far too short ONCE a seeder unchokes us:
65// a busy public seeder queues our request behind many peers, so its FIRST piece block -- and inter-block
66// gaps -- routinely exceed 6s. tg_read_msg then returns a spurious timeout and the child gives up
67// mid-request, so we pull NOTHING despite being unchoked. THIS is the residual "IGNORING" bug the pre-unchoke
68// patience window never covered: seedeval shows 23 seeders unchoke us yet have=0. Extending the read timeout
69// to a full optimistic-unchoke interval lets a slow-but-willing seeder actually feed us. Bounded: a seeder
70// truly silent this long AFTER unchoking is genuinely dead -> the read times out once, we free the slot.
71const TG_DATA_TIMEOUT: i64 = 30
72
73// per-connection DH private key for MSE (varies by wall-clock; nonzero ~128-bit). Hardening TODO: CSPRNG.
74func tg_dhpriv(x: *i64) -> i64 { return mse_gen_priv(x) } // CSPRNG per-connection key (nx_mse_wire)
75// MSE is OPT-IN (marker file) so it can't silently break real downloads before it's field-verified vs real
76// clients. Default (no marker) = plaintext-first = the known-good behavior. `touch /volume1/ai/torrent/mse.on` to enable.
77func tg_mse_on() -> i64 { let f: i64 = sys_openat_rd("/volume1/ai/torrent/mse.on" as *u8); if f>=0 { sys_close(f); return 1 } return 0 }
78// MULTI-FILE torrents have NO top-level "length" -- the REAL total is the SUM of the info-dict "files" list's
79// per-file "length". Using npc*plen (the old fallback) OVER-sizes the last piece (treats a partial last piece
80// as full plen) so it NEVER completes -> stuck at 99%/missing=1. This sums files[].length. Falls back to
81// npc*plen only if the list can't be parsed (fail-safe, same as before).
82func tg_multifile_total(meta: *u8, msize: i64, npc: i64, plen: i64) -> i64 {
83 // seq1786: the FOUR bail points below all returned npc*plen SILENTLY and were therefore
84 // INDISTINGUISHABLE -- a parse failure could not be told from a legitimate total, which is how
85 // this survived undetected. Each now returns a distinct NEGATIVE sentinel; the CALLER substitutes
86 // npc*plen so BEHAVIOUR IS UNCHANGED, and records WHICH bail fired.
87 // -1 = no "files" key -2 = "files" is not a list -3 = nx_bc_skip made no progress
88 // -4 = walked the list and summed nothing
89 // A caller MUST treat any negative return as "total unknown", never as a size.
90 let fo: i64 = nx_bc_dict_get(meta, 0, msize, "files" as *u8, 5)
91 if fo < 0 { return 0-1 }
92 if meta[fo] != (108 as u8) { return 0-2 } // 'l' = list of file dicts
93 var sum: i64 = 0; var o: i64 = fo + 1
94 while o < msize {
95 if meta[o] == (101 as u8) { if sum > 0 { return sum } return 0-4 } // 'e' ends the list
96 let lo: i64 = nx_bc_dict_get(meta, o, msize, "length" as *u8, 6)
97 if lo >= 0 { let iv: *i64 = sys_mmap(16) as *i64; if nx_bc_int(meta, lo, msize, iv) >= 0 { sum = sum + iv[0] } }
98 let nxt: i64 = nx_bc_skip(meta, o, msize) // advance past this file-dict
99 if nxt <= o { if sum > 0 { return sum } return 0-3 } // no progress -> bail
100 o = nxt
101 }
102 if sum > 0 { return sum } return 0-4
103}
104// seq1804: the grinding-tail status line used to pass npc*plen as `total` -- a FABRICATED figure,
105// indistinguishable from a measured one, that over-states the torrent by up to a full piece
106// (BANK-155: 4676648960 reported vs 4674889513 actual). It misled THREE of my own investigations
107// into believing the bencode walker had failed when it never had. The parent loop reads npc/plen from
108// download.npc and never parses metadata -- but the metadata is RIGHT THERE on disk, so read it and
109// report the truth. Falls back to npc*plen ONLY on a genuine read/parse failure, which is now a real
110// event rather than the default.
111// LAW: a derived field and a measured field must not share a name.
112func tg_meta_total_of(metapath: *u8, npc: i64, plen: i64) -> i64 {
113 let fd: i64 = sys_openat_rd(metapath); if fd < 0 { return npc*plen }
114 let mb2: *u8 = sys_mmap(TG_MAGIC_262144); let n: i64 = sys_read(fd, mb2, TG_MAGIC_262144 - 1); sys_close(fd)
115 if n <= 0 { return npc*plen }
116 let lno: i64 = nx_bc_dict_get(mb2, 0, n, "length" as *u8, 6)
117 if lno >= 0 { let iv: *i64 = sys_mmap(16) as *i64; if nx_bc_int(mb2, lno, n, iv) >= 0 { return iv[0] } }
118 let t: i64 = tg_multifile_total(mb2, n, npc, plen)
119 if t > 0 { return t }
120 return npc*plen
121}
122// SELECTIVE DOWNLOAD (operator: "if the file isnt the video and it stops the torrent, trim it"). Build a
123// per-piece WANTED mask: a piece is wanted iff it overlaps a file whose size >= min_bytes (the real content;
124// small cover/nfo/sample/txt junk is skipped). Single-file torrent (top-level "length") -> all wanted. If NO
125// file qualifies (e.g. an all-small-files torrent) -> ALL wanted (never accidentally want nothing = safe).
126// Boundary pieces that overlap ANY wanted file are wanted (needed for that file's bytes). Returns wanted_count.
127func tg_build_wanted(meta: *u8, msize: i64, npc: i64, plen: i64, wanted: *u8, min_bytes: i64) -> i64 {
128 var i: i64=0; while i<npc { wanted[i]=0 as u8; i=i+1 }
129 let lno: i64 = nx_bc_dict_get(meta, 0, msize, "length" as *u8, 6)
130 if lno >= 0 { i=0; while i<npc { wanted[i]=1 as u8; i=i+1 } return npc }
131 let fo: i64 = nx_bc_dict_get(meta, 0, msize, "files" as *u8, 5)
132 if fo < 0 { i=0; while i<npc { wanted[i]=1 as u8; i=i+1 } return npc }
133 if meta[fo] != (108 as u8) { i=0; while i<npc { wanted[i]=1 as u8; i=i+1 } return npc }
134 var off: i64=0; var o: i64=fo+1; var go2: i64=1
135 while go2==1 {
136 if o>=msize { go2=0 } else { if meta[o]==(101 as u8) { go2=0 } else {
137 let flo: i64 = nx_bc_dict_get(meta, o, msize, "length" as *u8, 6)
138 var flen: i64=0; if flo>=0 { let iv: *i64=sys_mmap(16) as *i64; if nx_bc_int(meta,flo,msize,iv)>=0 { flen=iv[0] } }
139 if flen >= min_bytes { var b: i64 = off/plen; let bend: i64 = (off+flen-1)/plen
140 while b<=bend { if b>=0 { if b<npc { wanted[b]=1 as u8 } } b=b+1 } }
141 off = off + flen
142 let nxt: i64 = nx_bc_skip(meta, o, msize); if nxt<=o { go2=0 } else { o=nxt }
143 } }
144 }
145 var wc: i64=0; i=0; while i<npc { if (wanted[i] as i64)==1 { wc=wc+1 } i=i+1 }
146 if wc==0 { i=0; while i<npc { wanted[i]=1 as u8; i=i+1 } return npc } // safety: nothing qualified -> want all
147 return wc
148}
149// the min-file-size (bytes) that marks a file as WANTED content. Data-driven: <selfdir>/torrent_wanted.conf
150// (a single integer) overrides; default 15 MB (video >> cover/nfo/sample). Config, not a magic number (rule 11).
151func tg_wanted_min() -> i64 {
152 let p: *u8 = sys_mmap(TG_MAGIC_1024); var o: i64 = pm_bstr(p, 0, tg_self_dir()); o = pm_bstr(p, o, "/torrent_wanted.conf" as *u8); p[o]=0 as u8
153 let fd: i64 = sys_openat_rd(p); if fd < 0 { return TG_MAGIC_15728640 }
154 let b: *u8 = sys_mmap(64); let n: i64 = sys_read(fd, b, 63); sys_close(fd)
155 var v: i64=0; var i: i64=0; while i<n { if b[i]>=(48 as u8) { if b[i]<=(57 as u8) { v=v*10+((b[i] as i64)-48) } } i=i+1 }
156 if v<=0 { return TG_MAGIC_15728640 }
157 return v
158}
159// pm_read_msg over an MseCtx (transparent decrypt; plaintext ctx == raw). >0 body len, 0 keep-alive, <0 error.
160func tg_read_msg(ctx: *MseCtx, fd: i64, mb: *u8, cap: i64) -> i64 {
161 if mse_read(ctx, fd, mb, 4) != 4 { return 0-1 }
162 let blen: i64 = _pw_get_u32(mb, 0)
163 if blen == 0 { return 0 }
164 if blen > cap-4 { return 0-1 }
165 if mse_read(ctx, fd, mb+4, blen) != blen { return 0-1 }
166 return blen
167}
168
169// raw open O_RDWR|O_CREAT (0x42) -- NO O_TRUNC, so children write at offsets without wiping.
170func tg_open_rw(path: *u8) -> i64 { return __syscall(SYS_OPENAT, AT_FDCWD, path as i64, 0x42, 0x1a4, 0, 0) }
171
172// PEX harvest (BEP-11): append gossiped compact peers (6B each: ip4 BE + port BE) to the shared
173// download.pex log under flock. Append-only + best-effort DISCOVERY -- never a data invariant (SHA1
174// still guards every piece), so a dropped append is harmless. The parent merges these into the peer
175// set on each re-announce. Reuses the avail-map flock idiom (sys_flock LOCK_EX) + the proven
176// O_WRONLY|O_CREAT|O_APPEND (0x441) atomic-append open.
177func tg_pex_append(pexpath: *u8, ips: *i64, ports: *i64, cnt: i64) -> i64 {
178 if cnt <= 0 { return 0 }
179 let fd: i64 = __syscall(SYS_OPENAT, AT_FDCWD, pexpath as i64, 0x441, 0x1a4, 0, 0)
180 if fd < 0 { return 0 }
181 sys_flock(fd, SYS_LOCK_EX)
182 let buf: *u8 = sys_mmap(cnt * 6 + 16)
183 var o: i64 = 0; var i: i64 = 0
184 while i < cnt {
185 let ip: i64 = ips[i]; let pt: i64 = ports[i]
186 buf[o]=((ip>>24)&0xff) as u8; buf[o+1]=((ip>>16)&0xff) as u8; buf[o+2]=((ip>>8)&0xff) as u8; buf[o+3]=(ip&0xff) as u8
187 buf[o+4]=((pt>>8)&0xff) as u8; buf[o+5]=(pt&0xff) as u8
188 o = o + 6; i = i + 1
189 }
190 cl_write_n(fd, buf, o)
191 sys_flock(fd, SYS_LOCK_UN)
192 sys_close(fd)
193 return cnt
194}
195
196// parent: merge harvested PEX peers (download.pex, 6B records) into the live peer set, deduped
197// against the current set. Returns the new count (bounded by max). Lock-free read -- a torn tail
198// record is ignored (i+6<=rn) and re-read next cycle.
199func tg_pex_merge(pexpath: *u8, ips: *i64, ports: *i64, have: i64, max: i64) -> i64 {
200 let fd: i64 = sys_openat_rd(pexpath)
201 if fd < 0 { return have }
202 let buf: *u8 = sys_mmap(6 * TG_MAGIC_65536 + 16)
203 let rn: i64 = sys_read(fd, buf, 6 * TG_MAGIC_65536); sys_close(fd)
204 if rn < 6 { return have }
205 var h: i64 = have
206 var i: i64 = 0
207 while i + 6 <= rn {
208 let ip: i64 = ((buf[i] as i64)<<24)|((buf[i+1] as i64)<<16)|((buf[i+2] as i64)<<8)|(buf[i+3] as i64)
209 let pt: i64 = ((buf[i+4] as i64)<<8)|(buf[i+5] as i64)
210 var dup: i64 = 0; var j: i64 = 0
211 while j < h { if ips[j]==ip { if ports[j]==pt { dup=1; j=h } } j=j+1 }
212 if dup == 0 { if h < max { ips[h]=ip; ports[h]=pt; h=h+1 } }
213 i = i + 6
214 }
215 return h
216}
217
218// ip-filter: compact the peer list in place, dropping any IP in a blocked range. Runs after each announce/PEX
219// merge in the PARENT -> children inherit the clean list via fork COW (no per-connect cost, no tg_from_peer
220// arg-cap change). cnt<=0 (no blocklist) -> pass-through no-op.
221func tg_ipf_filter(ips: *i64, ports: *i64, np: i64, arr: *i64, cnt: i64) -> i64 {
222 if cnt <= 0 { return np }
223 var w: i64 = 0; var i: i64 = 0
224 while i < np { if ipf_blocked(arr, cnt, ips[i]) == 0 { ips[w]=ips[i]; ports[w]=ports[i]; w=w+1 } i=i+1 }
225 return w
226}
227
228// read outdir/download.control -> 1 if the operator asked to stop (paused/removed), else 0.
229// pure file-based control (the daemon writes the file); no kill/getpid/setpgid needed.
230func tg_stop(ctlpath: *u8) -> i64 {
231 let fd: i64 = sys_openat_rd(ctlpath)
232 if fd < 0 { return 0 }
233 let b: *u8 = sys_mmap(16); let r: i64 = sys_read(fd, b, 15); sys_close(fd)
234 if r <= 0 { return 0 }
235 let c: i64 = b[0] as i64
236 if c == 112 { return 1 } // 'p' = paused
237 if c == 114 { return 1 } // 'r' = removed
238 return 0
239}
240
241func tg_status(path: *u8, name: *u8, total: i64, done: i64, have: i64, npc: i64, peers: i64, state: *u8) -> i64 {
242 let fd: i64 = sys_openat_wr(path, 0x1a4)
243 if fd < 0 { return 0 }
244 // newline-delimited key=value (value = rest of line) so a name with spaces parses cleanly
245 cl_w(fd, "total=" as *u8); cl_wn(fd, total); cl_w(fd, "\n" as *u8)
246 cl_w(fd, "done=" as *u8); cl_wn(fd, done); cl_w(fd, "\n" as *u8)
247 cl_w(fd, "have=" as *u8); cl_wn(fd, have); cl_w(fd, "\n" as *u8)
248 cl_w(fd, "pieces=" as *u8); cl_wn(fd, npc); cl_w(fd, "\n" as *u8)
249 cl_w(fd, "peers=" as *u8); cl_wn(fd, peers); cl_w(fd, "\n" as *u8)
250 cl_w(fd, "state=" as *u8); cl_w(fd, state); cl_w(fd, "\n" as *u8)
251 cl_w(fd, "name=" as *u8); cl_w(fd, name); cl_w(fd, "\n" as *u8)
252 sys_close(fd)
253 return 0
254}
255
256// CHILD: download as many NEEDED pieces as this peer serves; write each to outfile@offset + set
257// donefile bit. Returns pieces completed by this child.
258// STREAM MODE: present (the daemon writes it when a /stream request arrives) => download SEQUENTIALLY so
259// the contiguous playable prefix grows front-to-back for a <video> (rarest-first leaves holes that stall
260// playback). Absent => normal rarest-first+endgame (best for swarm health). 1 if the sidecar exists.
261func tg_stream_on(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 }
262
263// sequential pick: the LOWEST-index NEEDED piece this peer HAS. Pass 1 prefers a piece no other child is
264// downloading (in-flight==0) so the pool spreads; pass 2 allows an in-flight piece (race) so the prefix
265// always advances. -1 if the peer has nothing needed. (Relates to nx_sp_sequential, peer+in-flight aware.)
266func tg_seq_pick(donebits: *u8, peerbits: *u8, byte_len: i64, havebits: i64, inf: *i64, npc: i64) -> i64 {
267 var p: i64 = 0
268 while p < npc {
269 if (donebits[p] as i64) == 0 { var has: i64 = 1; if havebits == 1 { if nx_pw_bitfield_has(peerbits, byte_len, p) == 0 { has = 0 } } if has == 1 { if inf[p] == 0 { return p } } }
270 p = p + 1
271 }
272 p = 0
273 while p < npc {
274 if (donebits[p] as i64) == 0 { var h2: i64 = 1; if havebits == 1 { if nx_pw_bitfield_has(peerbits, byte_len, p) == 0 { h2 = 0 } } if h2 == 1 { return p } }
275 p = p + 1
276 }
277 return 0 - 1
278}
279
280// SEED what we already have (operator OK'd uploading -> s-class exceed): send our BITFIELD (peers learn
281// our pieces) + UNCHOKE (they may request). Earns RECIPROCITY -- a LEECHER that holds a piece we still
282// need (e.g. the last piece) but needs one WE have will TRADE it to us, instead of us begging a non-
283// ---- PARTIAL-PIECE PERSISTENCE (reciprocity-starvation fix) ----
284// Saturated public seeders give a pure-leecher only BRIEF optimistic-unchoke windows -- too short to move a
285// whole 2-4MB piece. Without this a child accumulates a piece in pbuf and DISCARDS it on CHOKE -> zero progress
286// on stingy swarms (seedeval "IGNORING": 23 seeders unchoke us yet have=0). Persist the received CONTIGUOUS
287// PREFIX of the in-flight piece to a staging file (download.pstage) + its byte-count (download.ppart) so the
288// NEXT window (this or another child) RESUMES from there -> pieces complete across many brief windows.
289// download.part stays VERIFIED-ONLY (verify/extract UNCHANGED); SHA1 still gates completion, so a torn/stale
290// prefix just fails verify -> redownload = SAFE BY CONSTRUCTION. cprefix (contiguous), NOT pbytes (total), is
291// persisted so a resumed prefix can never be garbage from an out-of-order gap. The staged prefix is bounded by
292// PCAP (block receipt drops beyond PCAP) so a load can never overflow pbuf.
293func tg_ppart_get(ppath: *u8, piece: i64) -> i64 {
294 let fd: i64 = sys_openat_rd(ppath); if fd < 0 { return 0 }
295 let b: *u8 = sys_mmap(16); sys_lseek(fd, piece*8, 0); let r: i64 = sys_read(fd, b, 8); sys_close(fd)
296 if r < 8 { return 0 }
297 var v: i64 = 0; var i: i64 = 0; while i < 8 { v = v | ((b[i] as i64) << (i*8)); i = i + 1 }
298 if v < 0 { return 0 }
299 return v
300}
301func tg_ppart_set(ppath: *u8, piece: i64, val: i64) -> i64 {
302 let fd: i64 = tg_open_rw(ppath); if fd < 0 { return 0 } // O_RDWR|O_CREAT, NO truncate -> per-piece 8-byte slot, sparse
303 let b: *u8 = sys_mmap(16); var i: i64 = 0; while i < 8 { b[i] = ((val >> (i*8)) & 0xff) as u8; i = i + 1 }
304 sys_lseek(fd, piece*8, 0); cl_write_n(fd, b, 8); sys_close(fd)
305 return 0
306}
307// flush pbuf[0..cprefix] of `piece` to the staging file + record cprefix. Called on CHOKE / child exit.
308func tg_ppart_flush(spath: *u8, ppath: *u8, piece: i64, plen: i64, pbuf: *u8, cprefix: i64) -> i64 {
309 if cprefix <= 0 { return 0 }
310 let fd: i64 = tg_open_rw(spath); if fd < 0 { return 0 }
311 sys_lseek(fd, piece*plen, 0); cl_write_n(fd, pbuf, cprefix); sys_close(fd)
312 tg_ppart_set(ppath, piece, cprefix)
313 return 0
314}
315// load `piece`'s staged prefix (cprefix bytes) into pbuf. Returns bytes loaded (0 => start fresh, safe).
316func tg_ppart_load(spath: *u8, piece: i64, plen: i64, pbuf: *u8, cprefix: i64) -> i64 {
317 if cprefix <= 0 { return 0 }
318 let fd: i64 = sys_openat_rd(spath); if fd < 0 { return 0 }
319 sys_lseek(fd, piece*plen, 0); let r: i64 = sys_read(fd, pbuf, cprefix); sys_close(fd)
320 if r < cprefix { return 0 }
321 return cprefix
322}
323// reciprocating seeder for a free optimistic-unchoke. THE "IGNORING" completion fix.
324func tg_seed_hello(ctx: *MseCtx, fd: i64, lbits: *u8, npc: i64) -> i64 {
325 let nbytes: i64 = (npc + 7) / 8
326 let bf: *u8 = sys_mmap(nbytes + 16); var b: i64 = 0; while b < nbytes { bf[b] = 0 as u8; b = b + 1 }
327 var p: i64 = 0
328 while p < npc { if (lbits[p] as i64) == 1 { let by: i64 = p / 8; let bit: i64 = 7 - (p - by*8); bf[by] = ((bf[by] as i64) | (1 << bit)) as u8 } p = p + 1 }
329 let m1: *u8 = sys_mmap(nbytes + 16); mse_write(ctx, fd, m1, nx_pw_build_msg(NX_PW_BITFIELD, bf, nbytes, m1))
330 let m2: *u8 = sys_mmap(16); mse_write(ctx, fd, m2, nx_pw_build_msg(NX_PW_UNCHOKE, 0 as *u8, 0, m2))
331 return 0
332}
333func tg_from_peer(ipv: i64, port: i64, ih: *u8, mypid: *u8, outpath: *u8, donepath: *u8, npcpath: *u8, metapath: *u8, statpath: *u8, ctlpath: *u8, availpath: *u8, inflightpath: *u8, streampath: *u8, pexpath: *u8, peers: i64) -> i64 {
334 let dest: *u8 = sys_mmap(16); cl_sockaddr(dest, port, (ipv>>24)&0xff, (ipv>>16)&0xff, (ipv>>8)&0xff, ipv&0xff)
335 var fd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
336 if fd < 0 { return 0 }
337 sys_set_socket_timeout(fd, 6)
338 if nx_connect_bounded(fd, dest, 16, TG_CONNECT_MS) != 0 { sys_close(fd); return 0 }
339 // MSE/PE ANTI-THROTTLE (OPT-IN via /volume1/ai/torrent/mse.on): try an encrypted handshake first (DPI can't
340 // fingerprint it); on reject the socket is dead -> reconnect + plaintext. DEFAULT (no marker) = plaintext-first
341 // = the known-good download path (MSE stays off until field-verified vs real clients, so it can't stall real DLs).
342 let ctx: *MseCtx = sys_mmap(MSE_CTX_BYTES) as *MseCtx
343 if tg_mse_on() == 1 {
344 let xpriv: *i64 = sys_mmap((MSE_N+2)*8) as *i64; tg_dhpriv(xpriv)
345 if mse_connect(fd, ih, xpriv, ctx) != 1 {
346 sys_close(fd)
347 fd = sys_socket(AF_INET, SOCK_STREAM, 0); if fd < 0 { return 0 }
348 sys_set_socket_timeout(fd, 6)
349 if nx_connect_bounded(fd, dest, 16, TG_CONNECT_MS) != 0 { sys_close(fd); return 0 }
350 mse_ctx_plain(ctx)
351 }
352 } else { mse_ctx_plain(ctx) } // DEFAULT plaintext (byte-identical to pre-MSE behavior)
353 let ch: *u8 = sys_mmap(128); nx_pw_build_handshake(ih, mypid, ch); ch[25] = (ch[25] as i64 | 0x10) as u8
354 if mse_write(ctx, fd, ch, 68) != 68 { sys_close(fd); return 0 }
355 let ph: *u8 = sys_mmap(128); if mse_read(ctx, fd, ph, 68) != 68 { sys_close(fd); return 0 }
356 let gih: *u8 = sys_mmap(20); let gpid: *u8 = sys_mmap(20); if nx_pw_parse_handshake(ph, 68, gih, gpid) != 1 { sys_close(fd); return 0 }
357 let ceb: *u8 = sys_mmap(64); let cm: *u8 = sys_mmap(128); mse_write(ctx, fd, cm, pm_build_ext(0, ceb, pm_bstr(ceb, 0, "d1:md11:ut_metadatai1e6:ut_pexi3eee" as *u8), cm)) // advertise ut_metadata=1 + ut_pex=3 (PEX_OUR_ID)
358
359 let outfd: i64 = tg_open_rw(outpath); let donefd: i64 = tg_open_rw(donepath)
360 let lbits: *u8 = sys_mmap(TG_MAGIC_262144)
361 sys_lseek(donefd, 0, 0); sys_read(donefd, lbits, TG_MAGIC_262144) // load current progress
362 // SELECTIVE DOWNLOAD: download.wanted (sibling of download.done) = per-piece wanted mask; pickbits = lbits | ~wanted
363 // so the picker treats unwanted (junk-file) pieces as done -> never fetches them. Built once after metadata resolves.
364 let wantedpath: *u8 = sys_mmap(640); var wpo: i64=0; var lastsl: i64=0; var wci: i64=0
365 while donepath[wci]!=(0 as u8) { if donepath[wci]==(47 as u8) { lastsl=wci } wci=wci+1 }
366 wci=0; while wci<=lastsl { wantedpath[wpo]=donepath[wci]; wpo=wpo+1; wci=wci+1 } wpo=pm_bstr(wantedpath, wpo, "download.wanted" as *u8); wantedpath[wpo]=0 as u8
367 let wbits: *u8 = sys_mmap(TG_MAGIC_262144); let pickbits: *u8 = sys_mmap(TG_MAGIC_262144); var wbuilt: i64=0
368 // partial-prefix persistence staging (siblings of download.part; same dir-prefix idiom as download.wanted)
369 let spath: *u8 = sys_mmap(640); var spo: i64=0; var si2: i64=0; while si2<=lastsl { spath[spo]=donepath[si2]; spo=spo+1; si2=si2+1 } spo=pm_bstr(spath, spo, "download.pstage" as *u8); spath[spo]=0 as u8
370 let ppath: *u8 = sys_mmap(640); var ppo2: i64=0; var pi3: i64=0; while pi3<=lastsl { ppath[ppo2]=donepath[pi3]; ppo2=ppo2+1; pi3=pi3+1 } ppo2=pm_bstr(ppath, ppo2, "download.ppart" as *u8); ppath[ppo2]=0 as u8
371
372 let meta: *u8 = sys_mmap(TG_MAGIC_262144); var msize: i64=0; var putm: i64=0; var gmeta: i64=0; var nmeta: i64=0; var rmeta: i64=0; var mdone: i64=0
373 var plen: i64=0; var poff: i64=0; var total: i64=0; var npc: i64=0; var unchoked: i64=0
374 let name: *u8 = sys_mmap(256); name[0]=63 as u8; name[1]=0 as u8
375 let mb: *u8 = sys_mmap(TG_MAGIC_40000); let pbuf: *u8 = sys_mmap(PCAP)
376 // seq1734: counts block receipts refused for landing beyond PCAP. Must never be silent -- a
377 // truncated piece can never verify, so a non-zero value here is the difference between
378 // "this torrent is slow" and "this torrent is structurally impossible with this buffer".
379 var dropped_blocks: i64 = 0
380 let peerbits: *u8 = sys_mmap(TG_MAGIC_40000) // THIS peer's advertised pieces (from BITFIELD + HAVE), MSB-first per BEP-3
381 var have: i64=0; var cur: i64=0-1; var pbytes: i64=0; var loops: i64=0; var go: i64=1; var chmsg: i64=0; var havebits: i64=0; var patient: i64=0 // tail-patience: stay glued to a holder waiting for its unchoke (the seedeval "IGNORING" fix)
382 var cprefix: i64=0 // contiguous received prefix of the in-flight piece (persisted on choke so brief unchoke windows accumulate)
383 let t_start: i64 = sys_now_realtime_sec() // connection start -> bounds the bulk unchoke-patience window (TG_UNCHOKE_WAIT)
384 var avail_added: i64=0; var avbuf: *i64 = 0 as *i64; var effbuf: *i64 = 0 as *i64; var infbuf: *i64 = 0 as *i64 // rarest-first + endgame scratch (lazy-alloc once npc known)
385 // METADATA CACHE LOAD: if a prior peer already resolved + SHA1-verified the metadata, load it from
386 // disk and skip the ut_metadata round-trip entirely (kills the per-child refetch tax). The SHA1
387 // re-verify guards a partial/corrupt cache -> falls back to the normal ut_metadata fetch.
388 let mcfd: i64 = sys_openat_rd(metapath)
389 if mcfd >= 0 {
390 let mr: i64 = sys_read(mcfd, meta, TG_MAGIC_262144); sys_close(mcfd)
391 if mr > 0 {
392 let gc: *u8 = sys_mmap(20); sha1(meta, mr, gc); var ec: i64=1; var xc: i64=0; while xc<20 { if gc[xc]!=ih[xc] { ec=0; xc=20 } else { xc=xc+1 } }
393 if ec==1 {
394 msize=mr; mdone=1; rmeta=1
395 let plo: i64=nx_bc_dict_get(meta,0,msize,"piece length" as *u8,12); let iv5: *i64=sys_mmap(16) as *i64; if plo>=0 { nx_bc_int(meta,plo,msize,iv5); plen=iv5[0] }
396 let pco: i64=nx_bc_dict_get(meta,0,msize,"pieces" as *u8,6); let so5: *i64=sys_mmap(16) as *i64; let sl5: *i64=sys_mmap(16) as *i64; if pco>=0 { nx_bc_str(meta,pco,msize,so5,sl5); poff=so5[0]; npc=sl5[0]/20 }
397 let lno: i64=nx_bc_dict_get(meta,0,msize,"length" as *u8,6); if lno>=0 { let iv6: *i64=sys_mmap(16) as *i64; nx_bc_int(meta,lno,msize,iv6); total=iv6[0] } else { total=tg_multifile_total(meta, msize, npc, plen) }
398 // seq1786: substitute the historical npc*plen fallback so BEHAVIOUR IS UNCHANGED, but
399 // publish WHICH bail fired -- a stuck torrent now names its own parse failure in
400 // download.status instead of silently reporting an invented total. A negative total
401 // must NEVER reach the piece math: pl_i = total - cur*plen would go wildly wrong.
402 if total < 0 {
403 if total == 0-1 { tg_status(statpath,name,0,0,0,npc,0,"meta-bail-nofiles" as *u8) }
404 if total == 0-2 { tg_status(statpath,name,0,0,0,npc,0,"meta-bail-notlist" as *u8) }
405 if total == 0-3 { tg_status(statpath,name,0,0,0,npc,0,"meta-bail-noprogress" as *u8) }
406 if total == 0-4 { tg_status(statpath,name,0,0,0,npc,0,"meta-bail-empty" as *u8) }
407 total = npc*plen
408 }
409 let nmo: i64=nx_bc_dict_get(meta,0,msize,"name" as *u8,4); if nmo>=0 { let so6: *i64=sys_mmap(16) as *i64; let sl6: *i64=sys_mmap(16) as *i64; if nx_bc_str(meta,nmo,msize,so6,sl6)>=0 { var k: i64=0; var nn: i64=sl6[0]; if nn>200 {nn=200} while k<nn { name[k]=meta[so6[0]+k]; k=k+1 } name[nn]=0 as u8 } }
410 let im: *u8=sys_mmap(16); mse_write(ctx,fd,im,nx_pw_build_msg(NX_PW_INTERESTED,0 as *u8,0,im))
411 // TAIL PATIENCE (the seedeval "IGNORING" fix): in the endgame (<= threshold pieces left) a
412 // holder is almost always a SEEDER that needs ~10-30s to optimistically-unchoke our pure-
413 // leecher. Extend this peer's read timeout so we WAIT for that unchoke instead of cycling
414 // off at the 6s connect timeout -- THE reason "76 peers HAVE the last piece but we never
415 // pull it". Only at the tail, so the bulk download keeps cycling fast off real chokers.
416 var done_n: i64=0; var dq: i64=0; while dq<npc { if (lbits[dq] as i64)==1 { done_n=done_n+1 } dq=dq+1 }
417 if npc - done_n <= TG_ENDGAME_THRESHOLD { sys_set_socket_timeout(fd, 45); patient=1 }
418 tg_seed_hello(ctx, fd, lbits, npc) // advertise what we hold + unchoke -> a leecher can TRADE us the tail piece
419 }
420 }
421 }
422 // LEAK ROOT-FIX 2026-07-30: the SEED/SERVE path (NX_PW_REQUEST, below) used to sys_mmap(rln+32)
423 // TWICE PER BLOCK SERVED and NEVER munmap -- ~40KB of leaked pages per served block, which is why
424 // long-lived children reached 1.5GB RSS (measured: 3 pids at 0.8-1.6GB, nx_leak_check CRITICAL).
425 // rln is BOUNDED (rln<=TG_MAGIC_16384 is checked at the serve guard), so these two buffers are
426 // LOOP-INVARIANT: map them ONCE here and reuse them every request. DO NOT move them back inside
427 // the loop -- that reintroduces the leak. This loop runs up to TG_MAGIC_2000000 iterations.
428 let sv_pbuf: *u8 = sys_mmap(TG_MAGIC_16384 + 64)
429 let sv_mbuf: *u8 = sys_mmap(TG_MAGIC_16384 + 64)
430 while go == 1 {
431 loops = loops + 1
432 if (loops % 512) == 0 { if tg_stop(ctlpath) == 1 { go = 0 } }
433 if loops > TG_MAGIC_2000000 { go = 0 }
434 if go == 1 {
435 let t_r0: i64 = sys_now_realtime_sec()
436 let blen: i64 = tg_read_msg(ctx, fd, mb, TG_MAGIC_40000)
437 if blen < 0 {
438 // Distinguish a recv TIMEOUT (blocked ~the socket timeout -> connection alive, peer just
439 // silent) from a real CLOSE/error (returns fast). While still waiting for a FIRST unchoke and
440 // inside the patience window, a timeout is NOT death: keep-alive and STAY so the seeder can
441 // rotate its optimistic-unchoke onto us. A fast return, or an active/expired peer -> give up.
442 var giveup: i64 = 1
443 if (sys_now_realtime_sec() - t_r0) >= 4 { if mdone==1 { if unchoked==0 { if cur<0 {
444 if (sys_now_realtime_sec() - t_start) < TG_UNCHOKE_WAIT {
445 let ka: *u8=sys_mmap(8); ka[0]=0 as u8; ka[1]=0 as u8; ka[2]=0 as u8; ka[3]=0 as u8; mse_write(ctx, fd, ka, 4); giveup=0
446 }
447 } } } }
448 if giveup == 1 { go = 0 }
449 }
450 if blen > 0 {
451 let id: i64 = nx_pw_msg_id(mb); let nt: i64 = 4 + blen
452 if id == PW_EXT {
453 let xi: i64 = mb[5] as i64
454 if xi == 0 {
455 let mo: i64 = nx_bc_dict_get(mb,6,nt,"m" as *u8,1); if mo>=0 { let uo: i64=nx_bc_dict_get(mb,mo,nt,"ut_metadata" as *u8,11); if uo>=0 { let iv: *i64=sys_mmap(16) as *i64; if nx_bc_int(mb,uo,nt,iv)>=0 { putm=iv[0] } } }
456 let so: i64 = nx_bc_dict_get(mb,6,nt,"metadata_size" as *u8,13); if so>=0 { let iv2: *i64=sys_mmap(16) as *i64; if nx_bc_int(mb,so,nt,iv2)>=0 { msize=iv2[0] } }
457 if putm>0 { if msize>0 { if rmeta==0 { nmeta=(msize+TG_MAGIC_16383)/TG_MAGIC_16384; var pi: i64=0; while pi<nmeta { let rb: *u8=sys_mmap(64); var ro: i64=pm_bstr(rb,0,"d8:msg_typei0e5:piecei" as *u8); ro=pm_bint(rb,ro,pi); ro=pm_bstr(rb,ro,"ee" as *u8); let rm: *u8=sys_mmap(128); mse_write(ctx,fd,rm,pm_build_ext(putm,rb,ro,rm)); pi=pi+1 } rmeta=1 } } }
458 }
459 if xi == 1 { if mdone==0 {
460 let pio: i64=nx_bc_dict_get(mb,6,nt,"piece" as *u8,5); var px: i64=0; if pio>=0 { let iv3: *i64=sys_mmap(16) as *i64; if nx_bc_int(mb,pio,nt,iv3)>=0 { px=iv3[0] } }
461 let raw: i64=nx_bc_skip(mb,6,nt); if raw>0 { let rl: i64=nt-raw; var c: i64=0; while c<rl { if px*TG_MAGIC_16384+c<TG_MAGIC_262144 { meta[px*TG_MAGIC_16384+c]=mb[raw+c] } c=c+1 } gmeta=gmeta+1 }
462 if gmeta>=nmeta { if nmeta>0 {
463 let gh: *u8=sys_mmap(20); sha1(meta,msize,gh); var eq: i64=1; var x: i64=0; while x<20 { if gh[x]!=ih[x] { eq=0; x=20 } else { x=x+1 } }
464 if eq==1 { mdone=1
465 let plo: i64=nx_bc_dict_get(meta,0,msize,"piece length" as *u8,12); let iv5: *i64=sys_mmap(16) as *i64; if plo>=0 { nx_bc_int(meta,plo,msize,iv5); plen=iv5[0] }
466 let pco: i64=nx_bc_dict_get(meta,0,msize,"pieces" as *u8,6); let so5: *i64=sys_mmap(16) as *i64; let sl5: *i64=sys_mmap(16) as *i64; if pco>=0 { nx_bc_str(meta,pco,msize,so5,sl5); poff=so5[0]; npc=sl5[0]/20 }
467 let lno: i64=nx_bc_dict_get(meta,0,msize,"length" as *u8,6); if lno>=0 { let iv6: *i64=sys_mmap(16) as *i64; nx_bc_int(meta,lno,msize,iv6); total=iv6[0] } else { total=tg_multifile_total(meta, msize, npc, plen) }
468 // seq1786: substitute the historical npc*plen fallback so BEHAVIOUR IS UNCHANGED, but
469 // publish WHICH bail fired -- a stuck torrent now names its own parse failure in
470 // download.status instead of silently reporting an invented total. A negative total
471 // must NEVER reach the piece math: pl_i = total - cur*plen would go wildly wrong.
472 if total < 0 {
473 if total == 0-1 { tg_status(statpath,name,0,0,0,npc,0,"meta-bail-nofiles" as *u8) }
474 if total == 0-2 { tg_status(statpath,name,0,0,0,npc,0,"meta-bail-notlist" as *u8) }
475 if total == 0-3 { tg_status(statpath,name,0,0,0,npc,0,"meta-bail-noprogress" as *u8) }
476 if total == 0-4 { tg_status(statpath,name,0,0,0,npc,0,"meta-bail-empty" as *u8) }
477 total = npc*plen
478 }
479 let nmo: i64=nx_bc_dict_get(meta,0,msize,"name" as *u8,4); if nmo>=0 { let so6: *i64=sys_mmap(16) as *i64; let sl6: *i64=sys_mmap(16) as *i64; if nx_bc_str(meta,nmo,msize,so6,sl6)>=0 { var k: i64=0; var nn: i64=sl6[0]; if nn>200 {nn=200} while k<nn { name[k]=meta[so6[0]+k]; k=k+1 } name[nn]=0 as u8 } }
480 let nf: i64=sys_openat_wr(npcpath,0x1a4); if nf>=0 { let nb: *u8=sys_mmap(16); nb[0]=(npc>>24)&0xff; nb[1]=(npc>>16)&0xff; nb[2]=(npc>>8)&0xff; nb[3]=npc&0xff; nb[4]=(plen>>24)&0xff; nb[5]=(plen>>16)&0xff; nb[6]=(plen>>8)&0xff; nb[7]=plen&0xff; cl_write_n(nf,nb,8); sys_close(nf) }
481 let mwf: i64=sys_openat_wr(metapath,0x1a4); if mwf>=0 { cl_write_n(mwf, meta, msize); sys_close(mwf) } // CACHE the verified metadata so sibling/recycled children skip the ut_metadata refetch
482 let im: *u8=sys_mmap(16); mse_write(ctx,fd,im,nx_pw_build_msg(NX_PW_INTERESTED,0 as *u8,0,im))
483 // reflect pieces ALREADY on disk (resume) instead of hardcoding 0 -- lbits
484 // was loaded from the donefile, so this shows preserved progress immediately.
485 var dn82: i64=0; var q82: i64=0; while q82<npc { if (lbits[q82] as i64)==1 { dn82=dn82+1 } q82=q82+1 }
486 tg_status(statpath,name,total,dn82*plen,dn82,npc,peers,"downloading" as *u8)
487 tg_seed_hello(ctx, fd, lbits, npc) // advertise + unchoke from first metadata so reciprocity bootstraps the bulk + 0%-non-starters
488 }
489 } }
490 } }
491 if xi == PEX_OUR_ID {
492 let pip: *i64 = sys_mmap(8*64) as *i64; let ppo: *i64 = sys_mmap(8*64) as *i64
493 let pc: i64 = pex_parse_added(mb, 6, nt, pip, ppo, 64)
494 if pc > 0 { tg_pex_append(pexpath, pip, ppo, pc) }
495 }
496 }
497 if id == NX_PW_UNCHOKE { unchoked=1; chmsg=0; sys_set_socket_timeout(fd, TG_DATA_TIMEOUT) } // DATA PHASE: a busy seeder's first block + inter-block gaps blow past the 6s connect timeout -> extend so we actually RECEIVE the pieces we just requested instead of bailing mid-request (the seedeval "23 seeders unchoke us, have=0 = IGNORING" fix)
498 if id == NX_PW_CHOKE { unchoked=0; if cur>=0 { tg_ppart_flush(spath, ppath, cur, plen, pbuf, cprefix); eg_clear(inflightpath, cur); cur=0-1; pbytes=0; cprefix=0 } } // choked: PERSIST the contiguous prefix (so the next window resumes it) + release the in-flight piece + return to waiting. DON'T give up here -- TG_UNCHOKE_WAIT bounds the wait so we outlast the optimistic-unchoke rotation (the "IGNORING" fix). Persisting the prefix is the reciprocity-starvation completion fix.
499 if id == NX_PW_BITFIELD { let bl2: i64=blen-1; var c: i64=0; while c<bl2 { if c<TG_MAGIC_40000 { peerbits[c]=mb[5+c] } c=c+1 } havebits=1 } // record which pieces THIS peer has
500 if id == NX_PW_HAVE { let hp: i64=_pw_get_u32(mb,5); let by: i64=hp/8; if by<TG_MAGIC_40000 { peerbits[by]=((peerbits[by] as i64) | (1 << (7 - (hp - by*8)))) as u8 } havebits=1; if avail_added==1 { if mdone==1 { am_add_have(availpath, hp) } } }
501 if id == NX_PW_PIECE {
502 let pidx: i64=_pw_get_u32(mb,5); let beg: i64=_pw_get_u32(mb,9); let bl: i64=blen-9
503 if pidx==cur { if beg+bl<=PCAP { var c: i64=0; while c<bl { pbuf[beg+c]=mb[13+c]; c=c+1 } pbytes=pbytes+bl; if beg==cprefix { cprefix=cprefix+bl } } }
504 // seq1734: a block landing beyond PCAP used to vanish here with NO else branch --
505 // silent data loss that made any plen>PCAP torrent retry forever at have=0. The cap
506 // is now 32 MiB, but the DROP MUST STAY VISIBLE: count it so a future oversized
507 // piece surfaces as a number instead of an eternal 0%.
508 if pidx==cur { if beg+bl>PCAP { dropped_blocks=dropped_blocks+1 } } // cprefix = length of the in-order prefix (what we can safely persist across a choke)
509 var pl_i: i64=plen; if cur==npc-1 { pl_i=total-cur*plen }
510 if pbytes>=pl_i { if pl_i>0 {
511 let g2: *u8=sys_mmap(20); sha1(pbuf,pl_i,g2); var ev: i64=1; var y: i64=0; while y<20 { if g2[y]!=meta[poff+cur*20+y] { ev=0; y=20 } else { y=y+1 } }
512 if ev==1 {
513 sys_lseek(outfd, cur*plen, 0); cl_write_n(outfd, pbuf, pl_i)
514 lbits[cur]=1 as u8; sys_lseek(donefd, cur, 0); let one: *u8=sys_mmap(4); one[0]=1 as u8; cl_write_n(donefd, one, 1)
515 have=have+1
516 var dn: i64=0; var q: i64=0; while q<npc { if (lbits[q] as i64)==1 { dn=dn+1 } q=q+1 }
517 tg_status(statpath,name,total,dn*plen,dn,npc,peers,"downloading" as *u8)
518 let hp2: *u8=sys_mmap(8); hp2[0]=((cur>>24)&0xff) as u8; hp2[1]=((cur>>16)&0xff) as u8; hp2[2]=((cur>>8)&0xff) as u8; hp2[3]=(cur&0xff) as u8; let hm: *u8=sys_mmap(16); mse_write(ctx,fd,hm,nx_pw_build_msg(NX_PW_HAVE,hp2,4,hm)) // advertise our NEW piece -> a peer needing it requests -> reciprocity
519 }
520 // seq1745: a SHA-1 verify failure used to be indistinguishable from success --
521 // same cleanup, no counter, no status. Four hours of failing every piece looked
522 // exactly like four hours of idle, which is why BANK-155 (done frozen at 30/2230
523 // since 13:22 while avail+wanted kept updating at 17:31) could not be diagnosed.
524 // Surfacing it costs one status write and DECIDES between the two live
525 // hypotheses: verify-failure vs reciprocity starvation. Same class as the PCAP
526 // silent drop -- a discard with no counter is invisible data loss.
527 if ev==0 { var dnf: i64=0; var qf: i64=0; while qf<npc { if (lbits[qf] as i64)==1 { dnf=dnf+1 } qf=qf+1 } tg_status(statpath,name,total,dnf*plen,dnf,npc,peers,"verify-fail" as *u8) }
528 tg_ppart_set(ppath, cur, 0); eg_clear(inflightpath, cur); cur=0-1; pbytes=0; cprefix=0 // piece done (or verify-failed) -> clear staged partial + no longer in-flight by this child
529 } }
530 }
531 if id == NX_PW_REQUEST { let ri: i64=_pw_get_u32(mb,5); let rqb: i64=_pw_get_u32(mb,9); let rln: i64=_pw_get_u32(mb,13)
532 if rln>0 { if rln<=TG_MAGIC_16384 { if ri>=0 { if ri<npc { if (lbits[ri] as i64)==1 { // we HAVE the requested piece -> SERVE it (seed back = reciprocity)
533 let sp: *u8=sv_pbuf
534 sp[0]=((ri>>24)&0xff) as u8; sp[1]=((ri>>16)&0xff) as u8; sp[2]=((ri>>8)&0xff) as u8; sp[3]=(ri&0xff) as u8
535 sp[4]=((rqb>>24)&0xff) as u8; sp[5]=((rqb>>16)&0xff) as u8; sp[6]=((rqb>>8)&0xff) as u8; sp[7]=(rqb&0xff) as u8
536 sys_lseek(outfd, ri*plen+rqb, 0); let got: i64=sys_read(outfd, (sp as i64 + 8) as *u8, rln)
537 if got==rln { let sm: *u8=sv_mbuf; mse_write(ctx, fd, sm, nx_pw_build_msg(NX_PW_PIECE, sp, 8+rln, sm)) }
538 } } } } } }
539 if mdone==1 { if unchoked==1 { if cur<0 {
540 sys_lseek(donefd, 0, 0); sys_read(donefd, lbits, npc) // refresh: skip pieces other parallel peers already finished
541 if wbuilt==0 { tg_build_wanted(meta, msize, npc, plen, wbits, tg_wanted_min()); let wf3: i64=tg_open_rw(wantedpath); if wf3>=0 { sys_lseek(wf3,0,0); cl_write_n(wf3, wbits, npc); sys_close(wf3) } wbuilt=1 }
542 var wpk: i64=0; while wpk<npc { if (wbits[wpk] as i64)==0 { pickbits[wpk]=1 as u8 } else { pickbits[wpk]=lbits[wpk] } wpk=wpk+1 } // pickbits: unwanted treated as done
543 // SMART LAYER (Phase 2): contribute THIS peer's availability to the shared cross-peer
544 // map ONCE -- deferred to here (not BITFIELD-receipt time) because the bitfield usually
545 // arrives before we know npc, and am_add_bitfield needs npc to know how far to scan.
546 if havebits==1 { if avail_added==0 { am_add_bitfield(availpath, peerbits, TG_MAGIC_40000, npc); avail_added=1 } }
547 if avbuf == (0 as *i64) { avbuf = sys_mmap(npc*8+64) as *i64; effbuf = sys_mmap(npc*8+64) as *i64; infbuf = sys_mmap(npc*8+64) as *i64 }
548 // SMART PICK (Phase 2): phase-1 = rarest NEEDED piece this peer HAS that no other child
549 // is already downloading (clean work-split -- kills the duplicate-download waste the old
550 // done-only scan allowed); phase-2 = in the tail (<= TG_ENDGAME_THRESHOLD obtainable
551 // pieces left, all in-flight) RACE the rarest to beat the one slow holder. eg_pick is
552 // self-sufficient (handles no-bitfield seeders + the avail map), so -1 means genuinely
553 // nothing for this peer right now -> free the slot (the pool refills with another peer).
554 var np: i64 = 0 - 1
555 if tg_stream_on(streampath) == 1 { am_load(inflightpath, infbuf, npc); np = tg_seq_pick(pickbits, peerbits, TG_MAGIC_40000, havebits, infbuf, npc) }
556 else { np = eg_pick(availpath, inflightpath, pickbits, peerbits, TG_MAGIC_40000, havebits, npc, TG_ENDGAME_THRESHOLD, avbuf, effbuf, infbuf) }
557 if np<0 { go=0 } else { cur=np; eg_mark(inflightpath, cur)
558 var pl_i: i64=plen; if cur==npc-1 { pl_i=total-cur*plen }
559 var pp: i64 = tg_ppart_get(ppath, cur); if pp >= pl_i { pp = 0 } // RESUME a staged prefix (defensive: stale/full -> fresh)
560 if pp > 0 { pbytes = tg_ppart_load(spath, cur, plen, pbuf, pp); cprefix = pbytes } else { pbytes = 0; cprefix = 0 }
561 let rq: *u8=sys_mmap(32); var b: i64=cprefix; while b<pl_i { var bk: i64=TG_MAGIC_16384; if pl_i-b<bk { bk=pl_i-b } mse_write(ctx,fd,rq,nx_pw_build_request(cur,b,bk,rq)); b=b+TG_MAGIC_16384 } // request only the MISSING blocks (skip the resumed prefix); one req buffer reused
562 }
563 } } }
564 if mdone==1 { if unchoked==0 { if cur<0 { if (sys_now_realtime_sec() - t_start) >= TG_UNCHOKE_WAIT { go=0 } } } } // give up ONLY after the unchoke-patience window elapses (covers choke-spammers that keep us choked-and-idle while sending messages, so the read-timeout path never fires). Bounds slot hold-time; productive/unchoked peers never reach here.
565 }
566 }
567 }
568 if cur>=0 { tg_ppart_flush(spath, ppath, cur, plen, pbuf, cprefix); eg_clear(inflightpath, cur) } // abandoned mid-piece (choke/timeout) -> PERSIST the contiguous prefix (resumed by the next child) + release the in-flight claim
569 sys_close(outfd); sys_close(donefd); sys_close(fd)
570 return have
571}
572
573// one HTTP/TCP tracker announce, appended to the peer set (dedup later). Bypasses ISP UDP blocking.
574func tg_http_one(host: *u8, port: i64, path: *u8, ih: *u8, pid: *u8, ips: *i64, ports: *i64, have: i64, max: i64) -> i64 {
575 let ip4: *u8 = sys_mmap(4)
576 if nx_dns_a_resolve(host, ip4) != 1 { return 0 }
577 let tip: *i64 = sys_mmap(8*80) as *i64; let tpo: *i64 = sys_mmap(8*80) as *i64
578 let c: i64 = ht_announce(host, ip4, port, path, ih, pid, TG_MAGIC_1000000000, tip, tpo, 80)
579 if c <= 0 { return 0 }
580 var added: i64 = 0; var k: i64 = 0
581 while k < c { if have + added < max { ips[have+added] = tip[k]; ports[have+added] = tpo[k]; added = added + 1 } k = k + 1 }
582 return added
583}
584
585// ---- DATA-DRIVEN WIDE tracker announce (Cardinal 11) ----------------------------------------------
586// Announce to EVERY HTTP/HTTPS tracker in <selfdir>/trackers.txt (one URL/line; '#' comments + blanks
587// skipped via tl_next_line) and append discovered peers to download.pex -- the SAME shared file BEP-11
588// PEX uses, so the parent's existing tg_pex_merge folds them into the live peer set. Widening the
589// tracker set = better odds of reaching the one seed holding a rare tail piece (the "stuck at 99%" fix
590// for poorly-seeded swarms). Absent file (e.g. dev box without trackers.txt) -> no-op; the synchronous
591// UDP + baked-HTTP + DHT discovery still runs. Returns peers appended.
592func tg_wide_to_pex(selfdir: *u8, outdir: *u8, ih: *u8, pid: *u8) -> i64 {
593 let path: *u8 = sys_mmap(640)
594 var pp: i64 = pm_bstr(path, 0, selfdir); pp = pm_bstr(path, pp, "/trackers.txt" as *u8); path[pp] = 0 as u8
595 let fd: i64 = sys_openat_rd(path)
596 if fd < 0 { return 0 }
597 let buf: *u8 = sys_mmap(TG_MAGIC_65536)
598 let n: i64 = sys_read(fd, buf, TG_MAGIC_65535); sys_close(fd)
599 if n <= 0 { return 0 }
600 let pexpath: *u8 = sys_mmap(640); var xp: i64 = pm_bstr(pexpath, 0, outdir); xp = pm_bstr(pexpath, xp, "/download.pex" as *u8); pexpath[xp] = 0 as u8
601 let tip: *i64 = sys_mmap(8*80) as *i64; let tpo: *i64 = sys_mmap(8*80) as *i64
602 let line: *u8 = sys_mmap(512)
603 var added: i64 = 0
604 var p2: i64 = tl_next_line(buf, n, 0, line)
605 while p2 >= 0 {
606 let cnt: i64 = ht_announce_url(line, ih, pid, TG_MAGIC_1000000000, tip, tpo, 80)
607 if cnt > 0 { tg_pex_append(pexpath, tip, tpo, cnt); added = added + cnt }
608 p2 = tl_next_line(buf, n, p2, line)
609 }
610 return added
611}
612// Run the wide announce in a DETACHED grandchild (double-fork -> reparents to init, no zombie) so a
613// firewalled tracker's ~127s connect() hang can NEVER stall the download (nx_http_client has no connect
614// timeout -- the very reason peers are fork-bounded). One-shot per worker run; a re-add starts a fresh
615// worker -> a fresh wide scan. The immediate child is reaped here; the grandchild is reaped by init.
616func tg_spawn_wide_announce(selfdir: *u8, outdir: *u8, ih: *u8, pid: *u8) -> i64 {
617 let p1: i64 = sys_fork()
618 if p1 == 0 {
619 let p2: i64 = sys_fork()
620 if p2 == 0 {
621 var fdx: i64 = 3; while fdx < 64 { sys_close(fdx); fdx = fdx + 1 }
622 tg_wide_to_pex(selfdir, outdir, ih, pid)
623 sys_exit(0)
624 }
625 sys_exit(0)
626 }
627 let st1: *i64 = sys_mmap(16) as *i64
628 sys_wait4(p1, st1, 0)
629 return 0
630}
631
632// MULTI-CHANNEL peer discovery -- the TEAM picks the set (UDP + HTTP/TCP); nothing external decides.
633// HTTP/TCP survives ISP UDP-tracker blocking AND a single tracker's announce rate-limit.
634func tg_announce_all(ih: *u8, pid: *u8, ips: *i64, ports: *i64, max: i64) -> i64 {
635 var have: i64 = cl_announce(ih, pid, ips, ports, max) // UDP open.stealth.si:80 (existing)
636 if have < 0 { have = 0 }
637 have = have + tg_http_one("open.stealth.si" as *u8, 80, "/announce" as *u8, ih, pid, ips, ports, have, max) // same tracker over TCP
638 have = have + tg_http_one("tracker.opentrackr.org" as *u8, TG_MAGIC_1337, "/announce" as *u8, ih, pid, ips, ports, have, max)
639 // DHT (BEP-5): trackerless peer discovery -- the ONLY source for tracker-less magnets (e.g. the
640 // operator's javdb magnets have no tr=). Append DHT peers to the set; reuses pid as the node id.
641 let dip: *i64 = sys_mmap(8*256) as *i64; let dpo: *i64 = sys_mmap(8*256) as *i64
642 let dc: i64 = dgp_find(ih, pid, dip, dpo, max)
643 var k: i64 = 0
644 while k < dc { if have < max { ips[have] = dip[k]; ports[have] = dpo[k]; have = have + 1 } k = k + 1 }
645 return have
646}
647
648// ---- BACKGROUND ANNOUNCE: THE PARENT MUST NEVER BLOCK ON THE NETWORK ------------------------------
649// tg_announce_all does a UDP tracker round (cl_announce), two DNS lookups + TCP tracker connects
650// (tg_http_one -> ht_announce) and a DHT get_peers (dgp_find). EVERY one of those can park the caller for
651// the kernel's full SYN / datagram timeout (~127s) against a black-holed tracker, and SO_RCVTIMEO does
652// NOT bound connect() -- so the 6s sys_set_socket_timeout calls on the PEER path buy nothing here.
653//
654// MEASURED 2026-07-31: worker parents sat in __inet_stream_connect and __skb_recv_datagram holding
655// EXACTLY 32 zombie children -- 32 == MAXP, the whole peer pool. While the parent is parked, the slot
656// reaper and the refill loop below it do not run, so every peer child that exits during the stall becomes
657// a zombie AND its slot is never refilled: the pool goes fully idle for the length of one stalled
658// announce. The zombies were the SYMPTOM that made it visible; the blocked parent was the defect.
659//
660// FIX: fork the announce. The child appends its peers to download.pex -- the same file BEP-11 PEX already
661// uses, that tg_wide_to_pex already publishes to, and that the parent already merges from on this exact
662// code path -- so discovery moves off the critical path with no new plumbing. The parent's loop stays hot
663// and its existing general wait4 sweep reaps the announce child. Peers land one cycle later; that costs
664// 30s of freshness and buys back a 2-minute total pool stall per bad tracker.
665//
666// One announce in flight at a time (slot[0]); a child still alive after TG_ANN_MAX_TICKS is SIGKILLed so
667// one wedged tracker cannot permanently silence discovery. Returns 1 if a fresh announce was started.
668func tg_announce_bg(ihb: *u8, mypid: *u8, pexpath: *u8, slot: *i64, stbuf: *i64, ticks: i64) -> i64 {
669 if slot[0] > 0 {
670 let r: i64 = sys_wait4(slot[0], stbuf, WNOHANG)
671 if r == 0 {
672 // Still running. Reclaim it if it outlived the watchdog, but NEVER block waiting on it --
673 // blocking here is the exact defect this function exists to remove.
674 if ticks - slot[1] >= TG_ANN_MAX_TICKS { nx_kill(slot[0], 9); slot[0] = 0 }
675 return 0
676 }
677 // r>0 = reaped right here; r<0 = the loop's general sweep already reaped it. Both mean FREE.
678 // Treating r<0 as "still running" would strand the slot on a dead pid and stop announcing forever.
679 slot[0] = 0
680 }
681 let p: i64 = sys_fork()
682 if p == 0 {
683 let aip: *i64 = sys_mmap(8 * 80) as *i64
684 let apo: *i64 = sys_mmap(8 * 80) as *i64
685 let c: i64 = tg_announce_all(ihb, mypid, aip, apo, 80)
686 if c > 0 { tg_pex_append(pexpath, aip, apo, c) }
687 sys_exit(0)
688 }
689 if p > 0 { slot[0] = p; slot[1] = ticks }
690 return 1
691}
692
693// on finish, split download.part into the real media files (multi-file torrents) so the operator sees a
694// playable REBDB-1026...mkv, not download.part. Best-effort: if the extractor elf is absent, exec fails
695// harmlessly (the manual extractor + .part remain). Streaming split lives in nx_torrent_extract.
696// The directory THIS worker binary lives in, read from /proc/self/cmdline argv[0] (mirrors the
697// daemon's d_self_dir). The extract + gallery-index elfs are deployed as the worker's SIBLINGS, so
698// they resolve on BOTH the dev box (/tmp) AND the NAS hub (/volume1/ai/torrent). Fallback "/tmp".
699func tg_self_dir() -> *u8 {
700 let buf: *u8 = sys_mmap(TG_MAGIC_1024)
701 let fd: i64 = sys_openat_rd("/proc/self/cmdline" as *u8)
702 var n: i64 = 0
703 if fd >= 0 { n = sys_read(fd, buf, 1023); sys_close(fd) }
704 if n <= 0 { let fb: *u8 = sys_mmap(8); fb[0]=47 as u8; fb[1]=116 as u8; fb[2]=109 as u8; fb[3]=112 as u8; fb[4]=0 as u8; return fb }
705 var z: i64 = 0; var dz: i64 = 0
706 while dz == 0 { if z >= n { dz = 1 } else { if buf[z] == (0 as u8) { dz = 1 } else { z = z + 1 } } }
707 var i: i64 = z - 1; var df: i64 = 0
708 while df == 0 { if i <= 0 { df = 1 } else { if buf[i] == (47 as u8) { buf[i] = 0 as u8; df = 1 } else { i = i - 1 } } }
709 if buf[0] == (0 as u8) { let fb: *u8 = sys_mmap(8); fb[0]=47 as u8; fb[1]=116 as u8; fb[2]=109 as u8; fb[3]=112 as u8; fb[4]=0 as u8; return fb }
710 return buf
711}
712// AUTO-SEED (the "sharing" half): on FULL completion, register this torrent in the seeder's registry so we
713// SHARE it back (download->seed reciprocity). srcpath = download.part = the EXACT concatenated payload the
714// piece hashes are computed over, so the seeder serves correct pieces for single AND multi file. total = the
715// .part file SIZE (== the exact byte total, no metadata re-parse). Idempotent (skips if the info_hash hex is
716// already registered). ONLY called on done_total>=npc -> never registers a partial (which would serve corrupt
717// zero-filled pieces to peers). regpath is a PARAM (config, not hardcoded) so it is gate-testable.
718func tg_autoseed(outdir: *u8, ih: *u8, plen: i64, name: *u8, regpath: *u8) -> i64 {
719 if plen <= 0 { return 0 }
720 let part: *u8 = sys_mmap(640); var po: i64=pm_bstr(part,0,outdir); po=pm_bstr(part,po,"/download.part" as *u8); part[po]=0 as u8
721 let pf: i64 = sys_openat_rd(part); if pf<0 { return 0 }
722 let total: i64 = sys_lseek(pf, 0, 2); sys_close(pf) // SEEK_END -> exact byte total
723 if total <= 0 { return 0 }
724 // ONLY seed a FULLY-complete torrent: a selective/complete-on-wanted download lacks the junk pieces, but the
725 // seeder advertises a FULL bitfield -> seeding a partial would serve corrupt (zero) junk pieces + get us banned.
726 let npcp: *u8=sys_mmap(640); var npo: i64=pm_bstr(npcp,0,outdir); npo=pm_bstr(npcp,npo,"/download.npc" as *u8); npcp[npo]=0 as u8
727 let nfd: i64=sys_openat_rd(npcp); if nfd<0 { return 0 } let nb: *u8=sys_mmap(16); let nn: i64=sys_read(nfd,nb,16); sys_close(nfd)
728 if nn<4 { return 0 } let npc_a: i64=((nb[0] as i64)<<24)|((nb[1] as i64)<<16)|((nb[2] as i64)<<8)|(nb[3] as i64)
729 let donp: *u8=sys_mmap(640); var dpo: i64=pm_bstr(donp,0,outdir); dpo=pm_bstr(donp,dpo,"/download.done" as *u8); donp[dpo]=0 as u8
730 let dfd: i64=sys_openat_rd(donp); if dfd<0 { return 0 } let dbf: *u8=sys_mmap(TG_MAGIC_262144); let dnn: i64=sys_read(dfd,dbf,TG_MAGIC_262144); sys_close(dfd)
731 var dc: i64=0; var di: i64=0; while di<dnn { if (dbf[di] as i64)==1 { dc=dc+1 } di=di+1 }
732 if dc <= 0 { return 0 } // nothing downloaded -> nothing to share (else OK: the seeder advertises+serves ONLY download.done pieces, so a selective/complete-on-wanted torrent seeds honestly)
733 let hd: *u8 = "0123456789abcdef" as *u8; let hx: *u8 = sys_mmap(48)
734 var i: i64=0; while i<20 { hx[i*2]=hd[((ih[i] as i64)>>4)&15]; hx[i*2+1]=hd[(ih[i] as i64)&15]; i=i+1 } hx[40]=0 as u8
735 let rf: i64 = sys_openat_rd(regpath)
736 if rf>=0 { let rb: *u8=sys_mmap(TG_MAGIC_262144); let rn: i64=sys_read(rf,rb,TG_MAGIC_262143); sys_close(rf)
737 var s: i64=0; while s+40<=rn { var m: i64=1; var k: i64=0; while k<40 { if rb[s+k]!=hx[k] { m=0; k=40 } else { k=k+1 } } if m==1 { return 0 } s=s+1 } } // already registered -> idempotent
738 let row: *u8=sys_mmap(TG_MAGIC_1024); var o: i64=0
739 o=pm_bstr(row,o,name); row[o]=9 as u8; o=o+1 // name \t
740 var j: i64=0; while j<40 { row[o]=hx[j]; o=o+1; j=j+1 } row[o]=9 as u8; o=o+1 // ih_hex40 \t
741 o=pm_bint(row,o,plen); row[o]=9 as u8; o=o+1 // piece_length \t
742 o=pm_bint(row,o,total); row[o]=9 as u8; o=o+1 // total \t
743 o=pm_bstr(row,o,part); row[o]=10 as u8; o=o+1 // srcpath \n
744 let wf: i64 = __syscall(SYS_OPENAT, AT_FDCWD, regpath as i64, 0x441, 0x1a4, 0, 0) // O_WRONLY|O_CREAT|O_APPEND
745 if wf>=0 { cl_write_n(wf, row, o); sys_close(wf) }
746 return 0
747}
748func tg_run_extract(outdir: *u8) -> i64 {
749 // CRITICAL (NAS): /tmp is mounted NOEXEC on the hub -- the old hardcoded "/tmp/...elf" execve here
750 // FAILED silently, so completed downloads stayed as download.part and never became playable media
751 // (and the gallery never refreshed). Resolve the SELF-DIR sibling FIRST (the deployed bundle path,
752 // /volume1/ai/torrent), then fall back to /tmp (dev box). In the child, the first execve replaces
753 // the process on success; it only returns on failure, so the second execve is the fallback. This is
754 // strictly safer than before on BOTH hosts. The extract elf being absent is still harmless (-> 127).
755 let sd: *u8 = tg_self_dir()
756 let exself: *u8 = sys_mmap(TG_MAGIC_1024); var eo: i64 = pm_bstr(exself,0,sd); eo=pm_bstr(exself,eo,"/nx_torrent_extract.sov.elf" as *u8); exself[eo]=0 as u8
757 let extmp: *u8 = "/tmp/nx_torrent_extract.sov.elf" as *u8
758 let exargv: *i64 = sys_mmap(32) as *i64; exargv[0]=exself as i64; exargv[1]=outdir as i64; exargv[2]=0
759 let exenvp: *i64 = sys_mmap(16) as *i64; exenvp[0]=0
760 let pid: i64 = sys_fork()
761 if pid==0 { sys_execve(exself, exargv, exenvp); sys_execve(extmp, exargv, exenvp); sys_exit(127) }
762 let stx: *i64 = sys_mmap(16) as *i64; sys_wait4(pid, stx, 0)
763 // GALLERY REFRESH: re-index the recordings/torrent video roots so the just-extracted media
764 // shows up + streams in the Nishi gallery. nx_galx_vidindex writes an ABSOLUTE index path so
765 // this is CWD-independent; exec failing (elf absent) is harmless (gallery just isn't refreshed).
766 let gself: *u8 = sys_mmap(TG_MAGIC_1024); var go: i64 = pm_bstr(gself,0,sd); go=pm_bstr(gself,go,"/nx_galx_vidindex.sov.elf" as *u8); gself[go]=0 as u8
767 let gtmp: *u8 = "/tmp/nx_galx_vidindex.sov.elf" as *u8
768 let gargv: *i64 = sys_mmap(16) as *i64; gargv[0]=gself as i64; gargv[1]=0
769 let genvp: *i64 = sys_mmap(16) as *i64; genvp[0]=0
770 let gpid: i64 = sys_fork()
771 if gpid==0 { sys_execve(gself, gargv, genvp); sys_execve(gtmp, gargv, genvp); sys_exit(127) }
772 let gstx: *i64 = sys_mmap(16) as *i64; sys_wait4(gpid, gstx, 0)
773 // ANALYSIS-ON-INGEST 2026-07-14: after re-indexing, trigger the derivation pipeline (thumbnail prewarm + NXVI
774 // duration/keyframe/markers) for the just-extracted media via the GUARDED galxpipeline hostctl sub
775 // (single-instance -> no stacking across concurrent torrents; it spawns the pipeline detached). Harmless if
776 // nx_hostctl is absent on this host (-> 127), matching the vidindex fork above.
777 let hcself: *u8 = "/volume1/homes/elderwesto/nishihost/nx_hostctl" as *u8
778 let pargv: *i64 = sys_mmap(16) as *i64; pargv[0]=hcself as i64; pargv[1]="galxpipeline" as *u8 as i64; pargv[2]=0
779 let penvp: *i64 = sys_mmap(16) as *i64; penvp[0]="PATH=/usr/bin:/bin" as *u8 as i64; penvp[1]=0
780 let ppid: i64 = sys_fork()
781 if ppid==0 { sys_execve(hcself, pargv, penvp); sys_exit(127) }
782 let pstx: *i64 = sys_mmap(16) as *i64; sys_wait4(ppid, pstx, 0)
783 return 0
784}
785
786func main(argc: i64, argv: *i64) -> i64 {
787 var magnet: *u8 = "magnet:?xt=urn:btih:dd8255ecdc7ca55fb0bbf81323d87062db1f6d1c&dn=Big+Buck+Bunny" as *u8
788 if argc >= 2 { magnet = argv[1] as *u8 }
789 var outdir: *u8 = "/mnt/c/Users/elder/Downloads/nishi-torrents" as *u8
790 if argc >= 3 { outdir = argv[2] as *u8 }
791 sys_mkdir(outdir, 0x1ff)
792 // SINGLE WORKER PER TORRENT (s-class robustness, the hardware rung): take a NON-BLOCKING exclusive
793 // flock on download.lock. If another worker for THIS torrent already holds it (a duplicate from a
794 // re-add / startup autoresume / the retry-sweep / a racing daemon restart), exit NOW instead of
795 // thrashing the swarm with redundant peer connections + DHT bootstraps -- the "lots of stalls /
796 // non-starters under load" failure mode. The kernel releases the lock when this process dies, so a
797 // dead worker's torrent is instantly re-spawnable. lockfd is intentionally kept open for our lifetime.
798 let lockp: *u8 = sys_mmap(640); var lkp: i64 = pm_bstr(lockp, 0, outdir); lkp = pm_bstr(lockp, lkp, "/download.lock" as *u8); lockp[lkp] = 0 as u8
799 let lockfd: i64 = sys_openat_wr(lockp, 0x1a4)
800 if lockfd >= 0 { if sys_flock(lockfd, SYS_LOCK_EX | SYS_LOCK_NB) != 0 { cl_w(1, "TGET already-running (download.lock held) -> exit clean\n" as *u8); sys_exit(0); return 0 } }
801
802 let ihb: *u8 = sys_mmap(20); let trk: *i64 = sys_mmap(8*32) as *i64; let ntrk: *i64 = sys_mmap(16) as *i64; let nm: *u8 = sys_mmap(512)
803 if mg_parse(magnet, ihb, trk, 32, ntrk, nm) != 1 { cl_w(1, "TGET verdict=RED reason=bad-magnet\n" as *u8); sys_exit(1); return 1 }
804 let mypid: *u8 = sys_mmap(20); let ps: *u8 = "-NX0001-000000000000" as *u8; var z: i64=0; while z<20 { mypid[z]=ps[z]; z=z+1 }
805
806 // emit a status BEFORE the (slow ~15-20s) DHT/tracker discovery so the UI shows "discovering peers"
807 // instead of looking dead/failed. Fresh add only -- a resume keeps its preserved have-count status.
808 if argc < 4 {
809 let estat: *u8 = sys_mmap(512); var es: i64=pm_bstr(estat,0,outdir); es=pm_bstr(estat,es,"/download.status" as *u8); estat[es]=0 as u8
810 tg_status(estat, nm, 0, 0, 0, 0, 0, "discovering peers" as *u8)
811 }
812 let ips: *i64 = sys_mmap(8*80) as *i64; let ports: *i64 = sys_mmap(8*80) as *i64
813 var np: i64 = tg_announce_all(ihb, mypid, ips, ports, 80)
814 cl_w(1, "TGET peers=" as *u8); cl_wn(1, np); cl_w(1, "\n" as *u8)
815 // ip-filter: load the blocklist ONCE (children inherit via fork COW); absent file -> ipf_n=0 -> no-op.
816 let ipf_arr: *i64 = sys_mmap(TG_MAGIC_80000*16 + 64) as *i64
817 let ipf_n: i64 = ipf_load("/volume1/ai/torrent/data/ipfilter.bin" as *u8, ipf_arr, TG_MAGIC_80000)
818 if ipf_n > 0 { let ipfb: i64 = np; np = tg_ipf_filter(ips, ports, np, ipf_arr, ipf_n); cl_w(1, "TGET ipfilter ranges=" as *u8); cl_wn(1, ipf_n); cl_w(1, " peers " as *u8); cl_wn(1, ipfb); cl_w(1, "->" as *u8); cl_wn(1, np); cl_w(1, "\n" as *u8) }
819 if np < 1 {
820 let sp2: *u8 = sys_mmap(512); var s2: i64=pm_bstr(sp2,0,outdir); s2=pm_bstr(sp2,s2,"/download.status" as *u8); sp2[s2]=0 as u8
821 tg_status(sp2, "no seeders found" as *u8, 0, 0, 0, 0, 0, "stalled" as *u8)
822 cl_w(1, "TGET verdict=RED reason=no-peers (tracker rate-limit? re-run)\n" as *u8); sys_exit(1); return 1
823 }
824
825 let outpath: *u8 = sys_mmap(512); var o: i64=pm_bstr(outpath,0,outdir); o=pm_bstr(outpath,o,"/download.part" as *u8); outpath[o]=0 as u8
826 let donepath: *u8 = sys_mmap(512); var d: i64=pm_bstr(donepath,0,outdir); d=pm_bstr(donepath,d,"/download.done" as *u8); donepath[d]=0 as u8
827 let npcpath: *u8 = sys_mmap(512); var nn2: i64=pm_bstr(npcpath,0,outdir); nn2=pm_bstr(npcpath,nn2,"/download.npc" as *u8); npcpath[nn2]=0 as u8
828 let metapath: *u8 = sys_mmap(512); var mpp: i64=pm_bstr(metapath,0,outdir); mpp=pm_bstr(metapath,mpp,"/download.meta" as *u8); metapath[mpp]=0 as u8 // shared metadata cache (fetch once, not per-child)
829 let statpath: *u8 = sys_mmap(512); var s: i64=pm_bstr(statpath,0,outdir); s=pm_bstr(statpath,s,"/download.status" as *u8); statpath[s]=0 as u8
830 let ctlpath: *u8 = sys_mmap(512); var cc: i64=pm_bstr(ctlpath,0,outdir); cc=pm_bstr(ctlpath,cc,"/download.control" as *u8); ctlpath[cc]=0 as u8
831 let availpath: *u8 = sys_mmap(512); var ap: i64=pm_bstr(availpath,0,outdir); ap=pm_bstr(availpath,ap,"/download.avail" as *u8); availpath[ap]=0 as u8 // shared cross-peer rarity map
832 let inflightpath: *u8 = sys_mmap(512); var ip2: i64=pm_bstr(inflightpath,0,outdir); ip2=pm_bstr(inflightpath,ip2,"/download.inflight" as *u8); inflightpath[ip2]=0 as u8 // shared in-flight refcount (endgame)
833 let streampath: *u8 = sys_mmap(512); var sp3: i64=pm_bstr(streampath,0,outdir); sp3=pm_bstr(streampath,sp3,"/download.stream" as *u8); streampath[sp3]=0 as u8 // stream-mode flag (sequential) when present
834 let pexpath: *u8 = sys_mmap(512); var pxp: i64=pm_bstr(pexpath,0,outdir); pxp=pm_bstr(pexpath,pxp,"/download.pex" as *u8); pexpath[pxp]=0 as u8 // shared PEX-harvested peer log (BEP-11)
835 // fresh add (argc<4) truncates done/npc/part for a clean run; RESUME (argv[3] present) keeps the
836 // partial so the worker continues from the donefile bitmap instead of re-downloading from zero.
837 if argc < 4 {
838 let z1: i64=sys_openat_wr(donepath,0x1a4); if z1>=0 { sys_close(z1) }
839 let z2: i64=sys_openat_wr(npcpath,0x1a4); if z2>=0 { sys_close(z2) }
840 let z3: i64=sys_openat_wr(outpath,0x1a4); if z3>=0 { sys_close(z3) }
841 let z5: i64=sys_openat_wr(pexpath,0x1a4); if z5>=0 { sys_close(z5) } // fresh add: drop stale harvested peers
842 }
843 // DATA-DRIVEN WIDE tracker scan (one-shot, detached -> download.pex; off the parent's critical path
844 // so a hung tracker can't stall the grind). Fires for fresh AND resume, so a re-added stuck torrent
845 // re-scans the wider tracker set for the seed holding its missing tail piece. Runs AFTER the pex
846 // truncate above so a fresh add never wipes the peers it appends.
847 tg_spawn_wide_announce(tg_self_dir(), outdir, ihb, mypid)
848 // fresh add: show "resolving/started". RESUME: leave the pre-pause status intact (preserved
849 // have-count stays visible) so the UI doesn't flash back to 0% while metadata re-resolves.
850 if argc < 4 { tg_status(statpath,"resolving" as *u8,0,0,0,0,np,"started" as *u8) }
851
852 // SMART LAYER: zero the shared availability + in-flight maps ONCE before any child runs (both fresh
853 // + resume -- both are per-session, rebuilt from THIS run's live swarm). 262144 = the donefile ceiling.
854 am_init(availpath, TG_MAGIC_262144)
855 eg_init(inflightpath, TG_MAGIC_262144)
856
857 let st: *i64 = sys_mmap(16) as *i64
858 var done_total: i64 = 0; var npc: i64 = 0
859 var fin: i64 = 0
860 // S-CLASS THROUGHPUT: a self-refilling pool of MAXP download children. Each child connects to ONE
861 // peer (ring round-robin over the discovered set), downloads the pieces that peer serves, and EXITS
862 // the instant it is choked/idle (see tg_from_peer) -- so a choking peer can never freeze a slot.
863 // Every 2s the parent reaps dead children and IMMEDIATELY refills every free slot from the peer ring
864 // (no gate). The pool stays full and constantly cycles connections => continuous optimistic-unchokes
865 // => sustained throughput instead of "fast burst then freeze". Re-announce every ~30s for fresh peers.
866 // seq1402/seq1410 -- POOL WIDTH IS DERIVED, NOT DECLARED. This was `let MAXP: i64 = 32`, a hardcoded
867 // literal (rule-11) that made every machine behave identically: the NAS (4c/8t), the west server, the
868 // laptop and any future box all ran 32 slots, sized for hardware nobody measured. Worse, 32 was
869 // PER-INSTANCE, and nx_procchurn measured 143 forks/sec = ~9 concurrent instances = ~288 concurrent
870 // slots against a box with 8 threads. NOBODY CHOSE 143; it was 32 x N.
871 // LAW: A PER-INSTANCE LIMIT IS NOT A LIMIT -- N instances multiply it and nobody ever picks N.
872 // What is NOT changed: the aggressive refill/cycling below. Constant connection cycling IS the
873 // BitTorrent throughput strategy (continuous optimistic-unchokes); throttling it would attack the
874 // feature to flatten a graph (rule 25). Only the WIDTH is governed; inside the budget the pool stays
875 // exactly as aggressive as it ever was.
876 // slots_per_cpu=4 reproduces the historical 32 on this 8-thread NAS => BEHAVIOUR-PRESERVING HERE,
877 // and correctly scales up on a bigger box / down inside a cgroup. Governor gate: 18/18 GREEN.
878 // ⚠LANDING BLOCKED BY LAYERING, NOT BY DESIGN: nx_poolwidth_lib lives in _hdl_build/ and a runtime/
879 // organ CANNOT import from there (`nx_compile_x86: expand_imports failed`). The governor is built and
880 // gate-proven 18/18; it must MOVE to runtime/ (the primitive layer, beside nx_hw.nx) before this line
881 // can become `pw_width(pw_budget_from_hw(4,8), pw_count_procs("nx_torrent_get"), pw_load_centi(), 800, 2, 32)`.
882 // Moving it needs care: a second copy under the same basename would SHADOW (seq207/284 dual-copy).
883 // REVERTED 2026-07-30 (seq1666/seq1681). The pg_* governor that stood here was on the WRONG AXIS
884 // and cost real downloads. A peer slot is a socket plus a piece buffer on a NETWORK-BLOCKED child:
885 // it consumes almost no CPU, so budgeting slots as cpus x 4 spent capability to relieve a resource
886 // peer slots never consumed. MEASURED HARM: nx_torstat returned VERDICT=IGNORING on BANK-155
887 // (2200/2200 missing pieces that DO have holders among connected peers) and ajvr-166 (468/1069)
888 // = 2668 fetchable pieces never pulled -- the exact signature of too few slots, because a pure
889 // leecher never wins optimistic-unchoke before its child times out.
890 // The block above claimed slots_per_cpu=4 was BEHAVIOUR-PRESERVING (4 x 8 = the historical 32).
891 // IT WAS NOT: 32 became the AGGREGATE budget SPLIT across instances. nx_poolgov_gate measures it
892 // directly -- T1 = 3 slots each across 9 instances, T6 = 2 under real load. 288 -> 27 aggregate,
893 // shipped believing it was a no-op, and the gate recorded the squeeze as a PASS.
894 // LAW: A GATE PROVES THE MECHANISM IS ARITHMETICALLY SOUND, NEVER THAT THE POLICY IS RIGHT.
895 // The per-instance-multiplication insight above IS STILL CORRECT and must not be lost: 32 x N
896 // instances is a width nobody chose. But the aggregate cap has to be derived from the resource
897 // slots ACTUALLY consume -- fd/socket budget (RLIMIT_NOFILE), or measured network saturation --
898 // never from CPU count, and never squeezed by a loadavg that on this host is dominated by
899 // D-state disk wait (measured: load 16.58 with only 4 runnable on 8 cores).
900 // Restoring the proven constant until that governor exists (rule 3: stop patching, rewrite).
901 let MAXP: i64 = 32
902 let cpids: *i64 = sys_mmap(8 * 64) as *i64 // child pid per slot (0/neg = free)
903 // seq1317 PER-SLOT COOLDOWN. This pool refilled EVERY free slot on EVERY tick with a fresh fork and
904 // no backoff whatsoever, so a peer that fails instantly frees its slot and is re-forked ~2s later,
905 // forever -- a self-inflicted fork treadmill (the perf lane measured bursts of 179 forks/s against an
906 // 85/s since-boot average). A slot is now ineligible for TG_SLOT_COOLDOWN ticks after it is FILLED,
907 // which bounds the refill rate structurally without needing to classify why a child died: a healthy
908 // long-lived peer is unaffected (its slot is occupied anyway), while a dead-peer slot stops spinning.
909 let cnext: *i64 = sys_mmap(8 * 64) as *i64 // earliest tick this slot may be refilled
910 var ci: i64 = 0
911 while ci < 64 { cnext[ci] = 0; ci = ci + 1 }
912 // Background-announce state: [0] = announce child pid (0 = idle), [1] = the tick it was forked.
913 // Allocated ONCE rather than per call so a multi-hour download does not leak a page per announce.
914 let annslot: *i64 = sys_mmap(16) as *i64
915 annslot[0] = 0; annslot[1] = 0
916 let annst: *i64 = sys_mmap(8) as *i64
917 var ring: i64 = 0 // round-robin index over the peer set
918 var s0: i64 = 0
919 while s0 < MAXP {
920 let pid: i64 = sys_fork()
921 if pid == 0 { tg_from_peer(ips[ring % np], ports[ring % np], ihb, mypid, outpath, donepath, npcpath, metapath, statpath, ctlpath, availpath, inflightpath, streampath, pexpath, np); sys_exit(0) }
922 cpids[s0] = pid; ring = ring + 1; s0 = s0 + 1
923 }
924 let nslots: i64 = MAXP
925 var last_done: i64 = 0 - 1; var stall_ticks: i64 = 0; var ticks: i64 = 0; var plen_p: i64 = 0
926 let lbp: *u8 = sys_mmap(TG_MAGIC_262144); let avp: *i64 = sys_mmap(TG_MAGIC_262144 * 8) as *i64; var done_rn: i64 = 0; var finalized: i64 = 0 // auto-finalize tail (reuse donefile + avail map)
927 // SELECTIVE DOWNLOAD completion: DONE when the WANTED pieces (not all npc) are complete -> a junk/sample file
928 // whose pieces are unavailable no longer blocks the torrent. wbp=download.wanted mask (sibling of donepath);
929 // effdone = have|unwanted (so the tail/finalize logic ignores skipped junk). No download.wanted -> all-npc.
930 let wbp: *u8 = sys_mmap(TG_MAGIC_262144); let effdone: *u8 = sys_mmap(TG_MAGIC_262144)
931 let wantedpath_p: *u8 = sys_mmap(640); var wpp: i64=0; var lsl: i64=0; var wpi: i64=0
932 while donepath[wpi]!=(0 as u8) { if donepath[wpi]==(47 as u8) { lsl=wpi } wpi=wpi+1 }
933 wpi=0; while wpi<=lsl { wantedpath_p[wpp]=donepath[wpi]; wpp=wpp+1; wpi=wpi+1 } wpp=pm_bstr(wantedpath_p, wpp, "download.wanted" as *u8); wantedpath_p[wpp]=0 as u8
934 var wanted_count: i64=0; var wanted_done: i64=0
935 while fin == 0 {
936 sys_sleep_ms(TG_MAGIC_2000); ticks = ticks + 1
937 if tg_stop(ctlpath) == 1 { fin = 1 } else {
938 var s: i64 = 0
939 while s < nslots { if cpids[s] > 0 { let r: i64 = sys_wait4(cpids[s], st, WNOHANG); if r > 0 { cpids[s] = 0 } } s = s + 1 }
940 while sys_wait4(0 - 1, st, WNOHANG) > 0 { } // reap ANY other exited child (untracked bounded-connect/announce forks) -- nx_zombie_audit flagged these leaking
941 let df: i64=sys_openat_rd(donepath); if df>=0 { let rn: i64=sys_read(df, lbp, TG_MAGIC_262144); sys_close(df); done_rn=rn; var dn: i64=0; var q: i64=0; while q<rn { if (lbp[q] as i64)==1 { dn=dn+1 } q=q+1 } done_total=dn }
942 let nf: i64=sys_openat_rd(npcpath); if nf>=0 { let nb: *u8=sys_mmap(16); let rn2: i64=sys_read(nf,nb,16); sys_close(nf); if rn2>=4 { npc=((nb[0] as i64)<<24)|((nb[1] as i64)<<16)|((nb[2] as i64)<<8)|(nb[3] as i64) } if rn2>=8 { plen_p=((nb[4] as i64)<<24)|((nb[5] as i64)<<16)|((nb[6] as i64)<<8)|(nb[7] as i64) } }
943 // SELECTIVE: recompute wanted_count/wanted_done + effdone(have|unwanted) from fresh lbp + download.wanted
944 wanted_count=0; wanted_done=0; var wloaded: i64=0
945 if npc > 0 { let wf: i64=sys_openat_rd(wantedpath_p); if wf>=0 { let wn: i64=sys_read(wf, wbp, TG_MAGIC_262144); sys_close(wf); if wn>=npc { wloaded=1 } }
946 var eq: i64=0
947 while eq<npc { var hv: i64=0; if eq<done_rn { if (lbp[eq] as i64)==1 { hv=1 } }
948 if wloaded==1 { if (wbp[eq] as i64)==1 { wanted_count=wanted_count+1; if hv==1 { wanted_done=wanted_done+1; effdone[eq]=1 as u8 } else { effdone[eq]=0 as u8 } } else { effdone[eq]=1 as u8 } }
949 else { effdone[eq]=lbp[eq]; if hv==1 { wanted_done=wanted_done+1 } }
950 eq=eq+1 }
951 if wloaded==0 { wanted_count=npc } }
952 if wanted_count > 0 { if wanted_done >= wanted_count { fin = 1 } } // WANTED-complete (junk pieces ignored)
953 if fin == 0 { if (ticks % 15) == 0 { tg_announce_bg(ihb, mypid, pexpath, annslot, annst, ticks); np = tg_pex_merge(pexpath, ips, ports, np, 80); np = tg_ipf_filter(ips, ports, np, ipf_arr, ipf_n) } } // fresh peers every ~30s (tracker+DHT+harvested PEX); ip-filter the refreshed list
954 if fin == 0 {
955 var s2: i64 = 0
956 while s2 < MAXP { if cpids[s2] <= 0 { if ticks >= cnext[s2] {
957 let pid2: i64 = sys_fork()
958 if pid2 == 0 { tg_from_peer(ips[ring % np], ports[ring % np], ihb, mypid, outpath, donepath, npcpath, metapath, statpath, ctlpath, availpath, inflightpath, streampath, pexpath, np); sys_exit(0) }
959 cpids[s2] = pid2; cnext[s2] = ticks + TG_SLOT_COOLDOWN; ring = ring + 1
960 } } s2 = s2 + 1 }
961 }
962 if done_total == last_done { stall_ticks = stall_ticks + 1 } else { stall_ticks = 0 }
963 last_done = done_total
964 // KEEP GRINDING THE TAIL: never abandon a partial download while peers exist. On a plateau
965 // (no new piece for ~16s) re-announce HARD every ~16s for fresh peers/seeders + keep cycling
966 // the pool, and publish an HONEST status that PRESERVES the have-count (name=nm, real bytes)
967 // instead of flashing "done=0 stalled". Real S-class clients grind the tail, they don't quit.
968 if fin == 0 { if stall_ticks >= 8 {
969 if (stall_ticks % 8) == 0 { tg_announce_bg(ihb, mypid, pexpath, annslot, annst, ticks); np = tg_pex_merge(pexpath, ips, ports, np, 80); np = tg_ipf_filter(ips, ports, np, ipf_arr, ipf_n) }
970 tg_status(statpath, nm, tg_meta_total_of(metapath, npc, plen_p), done_total*plen_p, done_total, npc, np, "downloading (grinding tail)" as *u8)
971 } }
972 if npc == 0 { if ticks > 90 { fin = 1 } } // never resolved metadata in ~180s -> give up
973 // AUTO-FINALIZE the tail: don't grind a hopeless last piece for 20 min or leave a 99%-done
974 // .part the operator can't open. On a sustained plateau, EXTRACT what we have NOW (a playable
975 // file, "most of a film") and stop -- (a) >=90% held + 60s plateau, or (b) the pieces we still
976 // need are provably UNOBTAINABLE here (no connected peer has them -> avail 0) after a 2-min
977 // plateau. This is the no-seeder-last-piece recovery (the 300MIUM-class fix).
978 // TAIL POLICY: at >=90% + plateau, EXTRACT a playable file ONCE (operator watches the "most of a
979 // film" now) but KEEP GRINDING while the missing pieces are OBTAINABLE (a connected peer has them).
980 // Only STOP when the tail is genuinely UNOBTAINABLE (avail 0) or the 20-min ultimate giveup below.
981 // BUG FIXED 2026-07-04: the old code STOPPED (fin=1) at 90%+60s UNCONDITIONALLY -> abandoned an
982 // obtainable last piece forever whenever the holders took >60s to optimistically-unchoke our
983 // leecher ("stuck at 99% with 177 holders"). Now an obtainable tail is ground until it lands.
984 if fin == 0 { if npc > 0 { if done_total > 0 { if done_rn >= npc {
985 am_load(availpath, avp, npc); let obt: i64 = eg_obtainable_remaining(effdone, avp, npc) // effdone ignores unwanted junk
986 if finalized == 0 { if stall_ticks >= 30 { if wanted_done * 100 >= wanted_count * 90 {
987 tg_run_extract(outdir); finalized = 1
988 tg_status(statpath, nm, npc*plen_p, done_total*plen_p, done_total, npc, np, "playable extracted - still grinding the last piece(s)" as *u8)
989 } } }
990 if stall_ticks >= 60 { if obt == 0 {
991 tg_run_extract(outdir)
992 tg_status(statpath, nm, npc*plen_p, done_total*plen_p, done_total, npc, np, "finalized - swarm has no more (tail unobtainable)" as *u8)
993 fin = 1
994 } }
995 } } } }
996 if npc > 0 { if stall_ticks > 600 { fin = 1 } } // ultimate giveup: ~20 min of zero new pieces -> exit (re-add resumes)
997 }
998 }
999 var k: i64 = 0; while k < nslots { if cpids[k] > 0 { nx_kill(cpids[k], 9); sys_wait4(cpids[k], st, 0) } k = k + 1 }
1000 cl_w(1, "TGET done_pieces=" as *u8); cl_wn(1, done_total); cl_w(1, "/" as *u8); cl_wn(1, npc); cl_w(1, " ticks=" as *u8); cl_wn(1, ticks); cl_w(1, " stall=" as *u8); cl_wn(1, stall_ticks); cl_w(1, " np=" as *u8); cl_wn(1, np); cl_w(1, " stop=" as *u8); cl_wn(1, tg_stop(ctlpath)); cl_w(1, " -> " as *u8); cl_w(1, outpath); cl_w(1, "\n" as *u8)
1001 if wanted_count > 0 { if wanted_done >= wanted_count { cl_w(1, "TGET verdict=GREEN COMPLETE (wanted="); cl_wn(1, wanted_done); cl_w(1, "/"); cl_wn(1, wanted_count); cl_w(1, ")\n" as *u8)
1002 let asreg: *u8=sys_mmap(TG_MAGIC_1024); var aso: i64=pm_bstr(asreg,0,tg_self_dir()); aso=pm_bstr(asreg,aso,"/seed_index.conf" as *u8); asreg[aso]=0 as u8
1003 tg_autoseed(outdir, ihb, plen_p, nm, asreg) // SHARE it back (skips partials internally: only FULL npc seeds)
1004 tg_run_extract(outdir); sys_exit(0); return 0 } }
1005 if done_total > 0 {
1006 if finalized == 0 { // not already extracted by the in-loop auto-finalize
1007 tg_status(statpath, nm, npc*plen_p, done_total*plen_p, done_total, npc, np, "partial - re-add to resume" as *u8)
1008 if npc > 0 { if done_total * 100 >= npc * 90 { tg_run_extract(outdir) } } // near-complete (>=90%) -> auto-extract playable media
1009 }
1010 cl_w(1, "TGET verdict=PARTIAL\n" as *u8); sys_exit(0); return 0
1011 }
1012 cl_w(1, "TGET verdict=RED reason=no-pieces\n" as *u8)
1013 tg_status(statpath, nm, 0, 0, done_total, npc, np, "stalled - no seeder served data" as *u8)
1014 sys_exit(1)
1015 return 1
1016}