code wiki / (root) / nx_peer_download.nx

nx_peer_download.nx source

↩ module page · 166 lines · 8401 B

1// nx_peer_download.nx -- DOWNLOAD a multi-block piece off a peer + WRITE it to a LOCAL FILE, 2// read-back verified (X-TORRENT-LIVE-001 R5): the literal "download locally" step. Builds on R4-b: 3// handshake -> interested -> unchoke -> request each 16-byte block -> PIECE -> assemble the 32-byte 4// piece -> sha1-verify -> sys_openat_wr the piece to a local file at its offset -> read it back -> 5// assert on-disk bytes + sha1 match. Reuses nx_peerwire (BEP-3) + nx_sha1. GATE = SOVEREIGN LOOPBACK: 6// a mock peer serves the two known blocks in request order; the client downloads, assembles, writes, 7// and re-reads from disk. Deterministic; no external net; no-hang (timeouts). license_tier: ORIGINAL 8// 9// module: nishi-core.torrent.peer_download 10// depends: nishi-core.torrent.peerwire, nishi-core.crypto.sha1 11import "nx_peerwire.nx" 12import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 13import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 14import "nx_sha1.nx" 15const K_MAGIC_53401: i64 = 53401 16 17func pd_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 } 18// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 19// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 20// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 21// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 22func pd_wn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 } 23func pd_sockaddr(sa: *u8, port: i64, i0: i64, i1: i64, i2: i64, i3: i64) -> i64 { 24 sa[0]=2 as u8; sa[1]=0 as u8 25 sa[2]=((port>>8)&0xff) as u8; sa[3]=(port&0xff) as u8 26 sa[4]=i0 as u8; sa[5]=i1 as u8; sa[6]=i2 as u8; sa[7]=i3 as u8 27 var k: i64=8; while k<16 { sa[k]=0 as u8; k=k+1 } 28 return 0 29} 30func pd_read_n(fd: i64, buf: *u8, n: i64) -> i64 { 31 var got: i64 = 0 32 while got < n { let r: i64 = sys_read(fd, buf + got, n - got); if r <= 0 { return 0 - 1 } got = got + r } 33 return got 34} 35func pd_write_n(fd: i64, buf: *u8, n: i64) -> i64 { 36 var off: i64 = 0 37 while off < n { let w: i64 = sys_write(fd, buf + off, n - off); if w <= 0 { return 0 - 1 } off = off + w } 38 return n 39} 40func pd_read_msg(fd: i64, mb: *u8, cap: i64) -> i64 { 41 if pd_read_n(fd, mb, 4) != 4 { return 0 - 1 } 42 let blen: i64 = _pw_get_u32(mb, 0) 43 if blen == 0 { return 0 } 44 if blen > cap - 4 { return 0 - 1 } 45 if pd_read_n(fd, mb + 4, blen) != blen { return 0 - 1 } 46 return blen 47} 48 49const BLK: i64 = 16 50const NBLK: i64 = 2 51const PIECE: i64 = 32 // BLK*NBLK 52 53func main() -> i64 { 54 let PORT: i64 = K_MAGIC_53401 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 } 57 // expected piece = block0 ++ block1 58 let expect: *u8 = sys_mmap(PIECE) 59 let b0: *u8 = "TORRENTBLOCK0123" as *u8 60 let b1: *u8 = "ABCDEFGHIJKLMNOP" as *u8 61 z = 0; while z < BLK { expect[z] = b0[z]; z = z + 1 } 62 z = 0; while z < BLK { expect[BLK + z] = b1[z]; z = z + 1 } 63 let sa: *u8 = sys_mmap(16); pd_sockaddr(sa, PORT, 127, 0, 0, 1) 64 let dlpath: *u8 = "/tmp/_nx_dl_test.bin" as *u8 65 66 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 67 var bound: i64 = 0 68 if lfd >= 0 { 69 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 70 sys_setsockopt(lfd, SOL_SOCKET, 2, one, 4) 71 sys_set_socket_timeout(lfd, 3) 72 if sys_bind(lfd, sa, 16) >= 0 { if sys_listen(lfd, 1) >= 0 { bound = 1 } } 73 } 74 if bound == 0 { pd_w(1, "PEERDL-GATE authored=organ bound=0 verdict=RED\n" as *u8); sys_exit(1); return 1 } 75 76 let pid: i64 = sys_fork() 77 if pid == 0 { 78 // MOCK PEER: serve the 2 blocks in request order. 79 let afd: i64 = sys_accept(lfd) 80 if afd >= 0 { 81 sys_set_socket_timeout(afd, 3) 82 let hb: *u8 = sys_mmap(128); pd_read_n(afd, hb, 68) 83 let oh: *u8 = sys_mmap(128); nx_pw_build_handshake(ih, pidb, oh); pd_write_n(afd, oh, 68) 84 let mb: *u8 = sys_mmap(256); pd_read_msg(afd, mb, 256) // INTERESTED 85 let un: *u8 = sys_mmap(16); let ul: i64 = nx_pw_build_msg(NX_PW_UNCHOKE, 0 as *u8, 0, un); pd_write_n(afd, un, ul) 86 var bi: i64 = 0 87 while bi < NBLK { 88 pd_read_msg(afd, mb, 256) // REQUEST 89 let begin: i64 = _pw_get_u32(mb, 9) 90 let pl: *u8 = sys_mmap(64); _pw_put_u32(pl, 0, 0); _pw_put_u32(pl, 4, begin) 91 var i: i64 = 0; while i < BLK { pl[8 + i] = expect[begin + i]; i = i + 1 } 92 let pm: *u8 = sys_mmap(128); let pml: i64 = nx_pw_build_msg(NX_PW_PIECE, pl, 8 + BLK, pm) 93 pd_write_n(afd, pm, pml) 94 bi = bi + 1 95 } 96 sys_close(afd) 97 } 98 sys_close(lfd) 99 sys_exit(0) 100 } 101 102 // CLIENT 103 let cfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 104 sys_set_socket_timeout(cfd, 3) 105 var conn_ok: i64 = 0 106 if nx_connect_bounded(cfd, sa, 16, NX_CONN_DEFAULT_MS) >= 0 { conn_ok = 1 } 107 var hs_ok: i64 = 0; var blocks_ok: i64 = 0; var sha_eq: i64 = 0; var disk_eq: i64 = 0 108 let piece: *u8 = sys_mmap(PIECE) 109 if conn_ok == 1 { 110 let ch: *u8 = sys_mmap(128); nx_pw_build_handshake(ih, pidb, ch); pd_write_n(cfd, ch, 68) 111 let ph2: *u8 = sys_mmap(128) 112 if pd_read_n(cfd, ph2, 68) == 68 { 113 let gih: *u8 = sys_mmap(20); let gpid: *u8 = sys_mmap(20) 114 if nx_pw_parse_handshake(ph2, 68, gih, gpid) == 1 { hs_ok = 1 } 115 } 116 if hs_ok == 1 { 117 let im: *u8 = sys_mmap(16); let il: i64 = nx_pw_build_msg(NX_PW_INTERESTED, 0 as *u8, 0, im); pd_write_n(cfd, im, il) 118 let mb: *u8 = sys_mmap(256); pd_read_msg(cfd, mb, 256) // UNCHOKE 119 var got_all: i64 = 1 120 var bi: i64 = 0 121 while bi < NBLK { 122 let rq: *u8 = sys_mmap(32); let rl: i64 = nx_pw_build_request(0, bi*BLK, BLK, rq); pd_write_n(cfd, rq, rl) 123 let pb: *u8 = sys_mmap(256); let plen: i64 = pd_read_msg(cfd, pb, 256) 124 if plen >= 9 { if nx_pw_msg_id(pb) == NX_PW_PIECE { 125 let begin: i64 = _pw_get_u32(pb, 9) 126 var i: i64 = 0; while i < BLK { piece[begin + i] = pb[13 + i]; i = i + 1 } 127 } else { got_all = 0 } } else { got_all = 0 } 128 bi = bi + 1 129 } 130 blocks_ok = got_all 131 if blocks_ok == 1 { 132 let gh: *u8 = sys_mmap(20); let eh: *u8 = sys_mmap(20) 133 sha1(piece, PIECE, gh); sha1(expect, PIECE, eh) 134 var se: i64 = 1; var i: i64 = 0 135 while i < 20 { if gh[i] != eh[i] { se = 0; i = 20 } else { i = i + 1 } } 136 sha_eq = se 137 // WRITE the verified piece to a LOCAL FILE, then read it back 138 let wf: i64 = sys_openat_wr(dlpath, 0x1a4) 139 if wf >= 0 { pd_write_n(wf, piece, PIECE); sys_close(wf) } 140 let rf: i64 = sys_openat_rd(dlpath) 141 if rf >= 0 { 142 let disk: *u8 = sys_mmap(PIECE) 143 let dn: i64 = pd_read_n(rf, disk, PIECE) 144 sys_close(rf) 145 if dn == PIECE { 146 var de: i64 = 1; i = 0 147 while i < PIECE { if disk[i] != expect[i] { de = 0; i = PIECE } else { i = i + 1 } } 148 disk_eq = de 149 } 150 } 151 } 152 } 153 } 154 let st: *i64 = sys_mmap(16) as *i64; sys_wait4(pid, st, 0); sys_close(cfd); sys_close(lfd) 155 156 pd_w(1, "PEERDL-GATE authored=organ conn_ok=" as *u8); pd_wn(1, conn_ok) 157 pd_w(1, " handshake_ok=" as *u8); pd_wn(1, hs_ok) 158 pd_w(1, " blocks_ok=" as *u8); pd_wn(1, blocks_ok) 159 pd_w(1, " sha1_verify=" as *u8); pd_wn(1, sha_eq) 160 pd_w(1, " disk_readback=" as *u8); pd_wn(1, disk_eq) 161 var allok: i64 = 0 162 if conn_ok==1 { if hs_ok==1 { if blocks_ok==1 { if sha_eq==1 { if disk_eq==1 { allok = 1 } } } } } 163 if allok == 1 { pd_w(1, " verdict=GREEN file=/tmp/_nx_dl_test.bin\n" as *u8); sys_exit(0); return 0 } 164 pd_w(1, " verdict=RED\n" as *u8); sys_exit(1) 165 return 1 166}