code wiki / (root) / nx_peer_piece.nx

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}