code wiki / (root) / nx_peer_handshake.nx

nx_peer_handshake.nx source

↩ module page · 122 lines · 6201 B

1// nx_peer_handshake.nx -- BEP-3 peer-wire HANDSHAKE over a real TCP connection (X-TORRENT-LIVE-001 2// R4-a): the gateway to BOTH metadata (BEP-9/10) and pieces (BEP-3 request/piece). Wires 3// nx_peerwire's KAT'd build/parse (nx_pw_build_handshake / nx_pw_parse_handshake / nx_pw_build_msg / 4// nx_pw_msg_id) to a TCP socket on the nx_syscalls layer (sys_socket SOCK_STREAM + connect/listen/ 5// accept; the UDP analog was nx_udp_tracker_announce). Import nx_peerwire ONLY (pulls nx_syscalls + 6// _pw_*/nx_pw_* transitively; no double-import). GATE = SOVEREIGN LOOPBACK: a mock peer (TCP 7// listen+accept on 127.0.0.1, listen-before-fork = no connect race) replies with its handshake 8// (same info_hash) + a bitfield; the client must parse the handshake (info_hash matches) + receive 9// the bitfield message. No external net; deterministic; no-hang (socket timeouts). license_tier: ORIGINAL 10// 11// module: nishi-core.torrent.peer_handshake 12// depends: nishi-core.torrent.peerwire 13import "nx_peerwire.nx" 14import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 15import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 16const K_MAGIC_53301: i64 = 53301 17 18func ph_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 ph_wn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 } 24func ph_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} 31// TCP stream: read EXACTLY n bytes (looping); -1 on error/EOF/timeout (no hang). 32func ph_read_n(fd: i64, buf: *u8, n: i64) -> i64 { 33 var got: i64 = 0 34 while got < n { let r: i64 = sys_read(fd, buf + got, n - got); if r <= 0 { return 0 - 1 } got = got + r } 35 return got 36} 37func ph_write_n(fd: i64, buf: *u8, n: i64) -> i64 { 38 var off: i64 = 0 39 while off < n { let w: i64 = sys_write(fd, buf + off, n - off); if w <= 0 { return 0 - 1 } off = off + w } 40 return n 41} 42 43func main() -> i64 { 44 let PORT: i64 = K_MAGIC_53301 45 let ih: *u8 = sys_mmap(20); var z: i64 = 0; while z < 20 { ih[z] = (z+1) as u8; z = z + 1 } // info_hash 1..20 46 let spid: *u8 = sys_mmap(20); z = 0; while z < 20 { spid[z] = (83) as u8; z = z + 1 } // server peer_id all 'S' 47 let cpid: *u8 = sys_mmap(20); z = 0; while z < 20 { cpid[z] = (67) as u8; z = z + 1 } // client peer_id all 'C' 48 let sa: *u8 = sys_mmap(16); ph_sockaddr(sa, PORT, 127, 0, 0, 1) 49 50 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 51 var bound: i64 = 0 52 if lfd >= 0 { 53 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 54 sys_setsockopt(lfd, SOL_SOCKET, 2, one, 4) // SO_REUSEADDR=2 (avoid TIME_WAIT bind fail on rerun) 55 sys_set_socket_timeout(lfd, 3) 56 if sys_bind(lfd, sa, 16) >= 0 { if sys_listen(lfd, 1) >= 0 { bound = 1 } } 57 } 58 if bound == 0 { ph_w(1, "PEERHS-GATE authored=organ bound=0 verdict=RED\n" as *u8); sys_exit(1); return 1 } 59 60 let pid: i64 = sys_fork() 61 if pid == 0 { 62 // MOCK PEER 63 let afd: i64 = sys_accept(lfd) 64 if afd >= 0 { 65 sys_set_socket_timeout(afd, 3) 66 let hb: *u8 = sys_mmap(128) 67 ph_read_n(afd, hb, 68) // client handshake (validated by client side) 68 let oh: *u8 = sys_mmap(128) 69 nx_pw_build_handshake(ih, spid, oh) // reply with same info_hash + our peer_id 70 ph_write_n(afd, oh, 68) 71 let bf: *u8 = sys_mmap(8); bf[0] = 255 as u8 // bitfield: has pieces 0-7 72 let msg: *u8 = sys_mmap(16) 73 let ml: i64 = nx_pw_build_msg(NX_PW_BITFIELD, bf, 1, msg) 74 ph_write_n(afd, msg, ml) 75 sys_close(afd) 76 } 77 sys_close(lfd) 78 sys_exit(0) 79 } 80 81 // CLIENT 82 let cfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 83 sys_set_socket_timeout(cfd, 3) 84 var conn_ok: i64 = 0 85 if nx_connect_bounded(cfd, sa, 16, NX_CONN_DEFAULT_MS) >= 0 { conn_ok = 1 } 86 var hs_ok: i64 = 0 87 var ih_eq: i64 = 0 88 var bf_ok: i64 = 0 89 if conn_ok == 1 { 90 let ch: *u8 = sys_mmap(128) 91 nx_pw_build_handshake(ih, cpid, ch) 92 ph_write_n(cfd, ch, 68) 93 let ph2: *u8 = sys_mmap(128) 94 let rr: i64 = ph_read_n(cfd, ph2, 68) 95 let gih: *u8 = sys_mmap(20); let gpid: *u8 = sys_mmap(20) 96 if rr == 68 { if nx_pw_parse_handshake(ph2, 68, gih, gpid) == 1 { hs_ok = 1 } } 97 if hs_ok == 1 { 98 var e: i64 = 1; var i: i64 = 0 99 while i < 20 { if gih[i] != ih[i] { e = 0; i = 20 } else { i = i + 1 } } 100 ih_eq = e 101 // read one message: 4-byte BE len + (id+payload) 102 let mb: *u8 = sys_mmap(512) 103 if ph_read_n(cfd, mb, 4) == 4 { 104 let blen: i64 = nx_pw_msg_len(mb) 105 if blen > 0 { if blen < 500 { if ph_read_n(cfd, mb + 4, blen) == blen { 106 if nx_pw_msg_id(mb) == NX_PW_BITFIELD { bf_ok = 1 } 107 } } } 108 } 109 } 110 } 111 let st: *i64 = sys_mmap(16) as *i64; sys_wait4(pid, st, 0); sys_close(cfd); sys_close(lfd) 112 113 ph_w(1, "PEERHS-GATE authored=organ conn_ok=" as *u8); ph_wn(1, conn_ok) 114 ph_w(1, " handshake_ok=" as *u8); ph_wn(1, hs_ok) 115 ph_w(1, " info_hash_eq=" as *u8); ph_wn(1, ih_eq) 116 ph_w(1, " bitfield_ok=" as *u8); ph_wn(1, bf_ok) 117 var allok: i64 = 0 118 if conn_ok==1 { if hs_ok==1 { if ih_eq==1 { if bf_ok==1 { allok = 1 } } } } 119 if allok == 1 { ph_w(1, " verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 120 ph_w(1, " verdict=RED\n" as *u8); sys_exit(1) 121 return 1 122}