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}