nx_peer_piece.nx source
↩ module page · 145 lines · 7482 B
1// nx_peer_piece.nx -- BEP-3 REQUEST/PIECE block transfer + sha1 verify (X-TORRENT-LIVE-001 R4-b):
2// the actual download mechanism. interested -> unchoke -> request(index,begin,length) -> PIECE
3// (<index><begin><block>) -> extract block -> sha1-verify. Reuses nx_peerwire (BEP-3 build/parse,
4// KAT'd) + nx_sha1 (hash) -- both on the nx_syscalls layer. GATE = SOVEREIGN LOOPBACK (TCP, the
5// nx_peer_handshake pattern): a mock peer (listen-before-fork) completes the handshake, unchokes,
6// and serves a known 16-byte block in a PIECE msg; the client requests it, extracts it, and
7// asserts the block bytes + its sha1 match the expected. No external net; deterministic; no-hang.
8// license_tier: ORIGINAL
9//
10// module: nishi-core.torrent.peer_piece
11// depends: nishi-core.torrent.peerwire, nishi-core.crypto.sha1
12import "nx_peerwire.nx"
13import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
14import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
15import "nx_sha1.nx"
16const K_MAGIC_53377: i64 = 53377
17
18func pp_w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
19// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
20// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
21// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
22// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
23func pp_wn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 }
24func pp_sockaddr(sa: *u8, port: i64, i0: i64, i1: i64, i2: i64, i3: i64) -> i64 {
25 sa[0]=2 as u8; sa[1]=0 as u8
26 sa[2]=((port>>8)&0xff) as u8; sa[3]=(port&0xff) as u8
27 sa[4]=i0 as u8; sa[5]=i1 as u8; sa[6]=i2 as u8; sa[7]=i3 as u8
28 var k: i64=8; while k<16 { sa[k]=0 as u8; k=k+1 }
29 return 0
30}
31func pp_read_n(fd: i64, buf: *u8, n: i64) -> i64 {
32 var got: i64 = 0
33 while got < n { let r: i64 = sys_read(fd, buf + got, n - got); if r <= 0 { return 0 - 1 } got = got + r }
34 return got
35}
36func pp_write_n(fd: i64, buf: *u8, n: i64) -> i64 {
37 var off: i64 = 0
38 while off < n { let w: i64 = sys_write(fd, buf + off, n - off); if w <= 0 { return 0 - 1 } off = off + w }
39 return n
40}
41// read one length-prefixed message into mb (mb[4]=id, mb[5..]=payload). returns body len (1+plen), 0=keepalive, -1 err.
42func pp_read_msg(fd: i64, mb: *u8, cap: i64) -> i64 {
43 if pp_read_n(fd, mb, 4) != 4 { return 0 - 1 }
44 let blen: i64 = _pw_get_u32(mb, 0)
45 if blen == 0 { return 0 }
46 if blen > cap - 4 { return 0 - 1 }
47 if pp_read_n(fd, mb + 4, blen) != blen { return 0 - 1 }
48 return blen
49}
50
51const BLK: i64 = 16
52
53func main() -> i64 {
54 let PORT: i64 = K_MAGIC_53377
55 let ih: *u8 = sys_mmap(20); var z: i64 = 0; while z < 20 { ih[z] = (z+1) as u8; z = z + 1 }
56 let pidb: *u8 = sys_mmap(20); z = 0; while z < 20 { pidb[z] = 80 as u8; z = z + 1 } // peer_id all 'P'
57 let block: *u8 = sys_mmap(BLK)
58 let blksrc: *u8 = "TORRENTBLOCK0123" as *u8
59 z = 0; while z < BLK { block[z] = blksrc[z]; z = z + 1 }
60 let sa: *u8 = sys_mmap(16); pp_sockaddr(sa, PORT, 127, 0, 0, 1)
61
62 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
63 var bound: i64 = 0
64 if lfd >= 0 {
65 let one: *u8 = sys_mmap(4); one[0]=1 as u8; one[1]=0 as u8; one[2]=0 as u8; one[3]=0 as u8
66 sys_setsockopt(lfd, SOL_SOCKET, 2, one, 4)
67 sys_set_socket_timeout(lfd, 3)
68 if sys_bind(lfd, sa, 16) >= 0 { if sys_listen(lfd, 1) >= 0 { bound = 1 } }
69 }
70 if bound == 0 { pp_w(1, "PEERPIECE-GATE authored=organ bound=0 verdict=RED\n" as *u8); sys_exit(1); return 1 }
71
72 let pid: i64 = sys_fork()
73 if pid == 0 {
74 // MOCK PEER
75 let afd: i64 = sys_accept(lfd)
76 if afd >= 0 {
77 sys_set_socket_timeout(afd, 3)
78 let hb: *u8 = sys_mmap(128)
79 pp_read_n(afd, hb, 68) // client handshake
80 let oh: *u8 = sys_mmap(128); nx_pw_build_handshake(ih, pidb, oh); pp_write_n(afd, oh, 68)
81 let mb: *u8 = sys_mmap(256)
82 pp_read_msg(afd, mb, 256) // INTERESTED
83 let un: *u8 = sys_mmap(16); let ul: i64 = nx_pw_build_msg(NX_PW_UNCHOKE, 0 as *u8, 0, un); pp_write_n(afd, un, ul)
84 pp_read_msg(afd, mb, 256) // REQUEST
85 // build PIECE: payload = <4 index=0><4 begin=0><block>
86 let pl: *u8 = sys_mmap(64); _pw_put_u32(pl, 0, 0); _pw_put_u32(pl, 4, 0)
87 var i: i64 = 0; while i < BLK { pl[8 + i] = block[i]; i = i + 1 }
88 let pm: *u8 = sys_mmap(128); let pml: i64 = nx_pw_build_msg(NX_PW_PIECE, pl, 8 + BLK, pm)
89 pp_write_n(afd, pm, pml)
90 sys_close(afd)
91 }
92 sys_close(lfd)
93 sys_exit(0)
94 }
95
96 // CLIENT
97 let cfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
98 sys_set_socket_timeout(cfd, 3)
99 var conn_ok: i64 = 0
100 if nx_connect_bounded(cfd, sa, 16, NX_CONN_DEFAULT_MS) >= 0 { conn_ok = 1 }
101 var hs_ok: i64 = 0; var piece_ok: i64 = 0; var blk_eq: i64 = 0; var sha_eq: i64 = 0
102 if conn_ok == 1 {
103 let ch: *u8 = sys_mmap(128); nx_pw_build_handshake(ih, pidb, ch); pp_write_n(cfd, ch, 68)
104 let ph2: *u8 = sys_mmap(128)
105 if pp_read_n(cfd, ph2, 68) == 68 {
106 let gih: *u8 = sys_mmap(20); let gpid: *u8 = sys_mmap(20)
107 if nx_pw_parse_handshake(ph2, 68, gih, gpid) == 1 { hs_ok = 1 }
108 }
109 if hs_ok == 1 {
110 let im: *u8 = sys_mmap(16); let il: i64 = nx_pw_build_msg(NX_PW_INTERESTED, 0 as *u8, 0, im); pp_write_n(cfd, im, il)
111 let mb: *u8 = sys_mmap(256)
112 pp_read_msg(cfd, mb, 256) // UNCHOKE (id at mb[4])
113 // request piece 0, begin 0, length BLK
114 let rq: *u8 = sys_mmap(32); let rl: i64 = nx_pw_build_request(0, 0, BLK, rq); pp_write_n(cfd, rq, rl)
115 let pb: *u8 = sys_mmap(256)
116 let plen: i64 = pp_read_msg(cfd, pb, 256)
117 if plen >= 9 { if nx_pw_msg_id(pb) == NX_PW_PIECE {
118 piece_ok = 1
119 // block starts at pb[5 + 8] (after id-excluded payload: index4+begin4)
120 let got: *u8 = sys_mmap(BLK)
121 var i: i64 = 0; while i < BLK { got[i] = pb[13 + i]; i = i + 1 }
122 var e: i64 = 1; i = 0
123 while i < BLK { if got[i] != block[i] { e = 0; i = BLK } else { i = i + 1 } }
124 blk_eq = e
125 let gh: *u8 = sys_mmap(20); let eh: *u8 = sys_mmap(20)
126 sha1(got, BLK, gh); sha1(block, BLK, eh)
127 var se: i64 = 1; i = 0
128 while i < 20 { if gh[i] != eh[i] { se = 0; i = 20 } else { i = i + 1 } }
129 sha_eq = se
130 } }
131 }
132 }
133 let st: *i64 = sys_mmap(16) as *i64; sys_wait4(pid, st, 0); sys_close(cfd); sys_close(lfd)
134
135 pp_w(1, "PEERPIECE-GATE authored=organ conn_ok=" as *u8); pp_wn(1, conn_ok)
136 pp_w(1, " handshake_ok=" as *u8); pp_wn(1, hs_ok)
137 pp_w(1, " piece_ok=" as *u8); pp_wn(1, piece_ok)
138 pp_w(1, " block_match=" as *u8); pp_wn(1, blk_eq)
139 pp_w(1, " sha1_verify=" as *u8); pp_wn(1, sha_eq)
140 var allok: i64 = 0
141 if conn_ok==1 { if hs_ok==1 { if piece_ok==1 { if blk_eq==1 { if sha_eq==1 { allok = 1 } } } } }
142 if allok == 1 { pp_w(1, " verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
143 pp_w(1, " verdict=RED\n" as *u8); sys_exit(1)
144 return 1
145}