code wiki / (root) / nx_pex_gate.nx

nx_pex_gate.nx source

↩ module page · 159 lines · 8674 B

1// nx_pex_gate.nx -- SOVEREIGN LOOPBACK gate for BEP-11 ut_pex: proves PEX rides the REAL BEP-10 2// extension channel over a real TCP socket (not just the deterministic parser, which nx_pex's baked 3// KAT already covers). A mock peer does the BEP-3 handshake (ext bit) + BEP-10 ext handshake 4// (advertising ut_pex) + sends a real ut_pex ext message carrying a compact peer list; the client 5// dispatches on the ext-id WE advertised, learns the peer's ut_pex id, and pex_parse_added's the 6// gossiped peers. This is the live-channel proof that, once connected to ONE peer, we harvest MORE. 7// license_tier: ORIGINAL 8// 9// module: nishi-core.torrent.pex_gate 10// depends: nishi-core.torrent.pex, nishi-core.torrent.peerwire 11import "nx_pex.nx" 12import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 13import "nx_peerwire.nx" 14import "nx_gate_verdict.nx" 15 16const PW_EXTENDED: i64 = 20 17 18func gx_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 } 19func gx_wn(fd: i64, v: i64) -> i64 { 20 let t: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) } 21 var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 }; while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 22 let b: *u8 = sys_mmap(28); var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 }; sys_write(fd, b, k); return 0 23} 24func gx_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 25func gx_sockaddr(sa: *u8, port: i64, i0: i64, i1: i64, i2: i64, i3: i64) -> i64 { 26 sa[0] = 2 as u8; sa[1] = 0 as u8 27 sa[2] = ((port >> 8) & 0xff) as u8; sa[3] = (port & 0xff) as u8 28 sa[4] = i0 as u8; sa[5] = i1 as u8; sa[6] = i2 as u8; sa[7] = i3 as u8 29 var k: i64 = 8; while k < 16 { sa[k] = 0 as u8; k = k + 1 } 30 return 0 31} 32func gx_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 gx_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} 42func gx_read_msg(fd: i64, mb: *u8, cap: i64) -> i64 { 43 if gx_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 gx_read_n(fd, mb + 4, blen) != blen { return 0 - 1 } 48 return blen 49} 50// build extended message id=20: payload = [ext_id] + ben(benlen); EXPLICIT length (compact peer 51// bytes can contain NUL, so a strlen-based builder would truncate). returns total bytes. 52func px_build_ext(ext_id: i64, ben: *u8, benlen: i64, out: *u8) -> i64 { 53 let pl: *u8 = sys_mmap(4096) 54 pl[0] = ext_id as u8 55 var i: i64 = 0; while i < benlen { pl[1 + i] = ben[i]; i = i + 1 } 56 return nx_pw_build_msg(PW_EXTENDED, pl, 1 + benlen, out) 57} 58 59func main() -> i64 { 60 let PORT: i64 = 53441 61 let ih: *u8 = sys_mmap(20); var z: i64 = 0; while z < 20 { ih[z] = (z + 1) as u8; z = z + 1 } 62 let pidb: *u8 = sys_mmap(20); z = 0; while z < 20 { pidb[z] = 80 as u8; z = z + 1 } 63 let sa: *u8 = sys_mmap(16); gx_sockaddr(sa, PORT, 127, 0, 0, 1) 64 65 // the 3 peers the mock will gossip via PEX 66 let gips: *i64 = sys_mmap(8 * 8) as *i64 67 let gpts: *i64 = sys_mmap(8 * 8) as *i64 68 gips[0] = (11 << 24) | (22 << 16) | (33 << 8) | 44; gpts[0] = 12345 69 gips[1] = (99 << 24) | (88 << 16) | (77 << 8) | 66; gpts[1] = 6881 70 gips[2] = (203 << 24) | (0 << 16) | (113 << 8) | 7; gpts[2] = 51999 71 72 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 73 var bound: i64 = 0 74 if lfd >= 0 { 75 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 76 sys_setsockopt(lfd, SOL_SOCKET, 2, one, 4) 77 sys_set_socket_timeout(lfd, 3) 78 if sys_bind(lfd, sa, 16) >= 0 { if sys_listen(lfd, 1) >= 0 { bound = 1 } } 79 } 80 if bound == 0 { gx_w(1, "PEX-GATE authored=organ bound=0 verdict=RED\n" as *u8); sys_exit(1); return 1 } 81 82 let pid: i64 = sys_fork() 83 if pid == 0 { 84 // ---- MOCK PEER ---- 85 let afd: i64 = sys_accept(lfd) 86 if afd >= 0 { 87 sys_set_socket_timeout(afd, 3) 88 let hb: *u8 = sys_mmap(128); gx_read_n(afd, hb, 68) 89 let oh: *u8 = sys_mmap(128); nx_pw_build_handshake(ih, pidb, oh); oh[25] = (oh[25] as i64 | 0x10) as u8; gx_write_n(afd, oh, 68) 90 let cmb: *u8 = sys_mmap(512); gx_read_msg(afd, cmb, 512) // client ext handshake 91 // mock's own ext handshake: advertise ut_pex=7 (so the client can learn our id) 92 let mben: *u8 = "d1:md6:ut_pexi7eee" as *u8 93 let om: *u8 = sys_mmap(512); let oml: i64 = px_build_ext(0, mben, gx_len(mben), om); gx_write_n(afd, om, oml) 94 // mock's PEX message: ext-id = PEX_OUR_ID (the id the client advertised for incoming ut_pex) 95 let pdict: *u8 = sys_mmap(512); let pdl: i64 = pex_build_added(gips, gpts, 3, pdict) 96 let pm: *u8 = sys_mmap(512); let pml: i64 = px_build_ext(PEX_OUR_ID, pdict, pdl, pm); gx_write_n(afd, pm, pml) 97 sys_close(afd) 98 } 99 sys_close(lfd) 100 sys_exit(0) 101 } 102 103 // ---- CLIENT ---- 104 let cfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 105 sys_set_socket_timeout(cfd, 3) 106 var conn_ok: i64 = 0 107 if nx_connect_bounded(cfd, sa, 16, NX_CONN_DEFAULT_MS) >= 0 { conn_ok = 1 } 108 var hs_ok: i64 = 0; var ext_ok: i64 = 0; var peer_id_ok: i64 = 0 109 var pex_count: i64 = 0; var p0_ok: i64 = 0; var p2_ok: i64 = 0 110 if conn_ok == 1 { 111 let ch: *u8 = sys_mmap(128); nx_pw_build_handshake(ih, pidb, ch); ch[25] = (ch[25] as i64 | 0x10) as u8; gx_write_n(cfd, ch, 68) 112 let ph: *u8 = sys_mmap(128) 113 if gx_read_n(cfd, ph, 68) == 68 { 114 let gih: *u8 = sys_mmap(20); let gpid: *u8 = sys_mmap(20) 115 if nx_pw_parse_handshake(ph, 68, gih, gpid) == 1 { hs_ok = 1 } 116 } 117 if hs_ok == 1 { 118 // advertise ut_metadata=1 + ut_pex=PEX_OUR_ID(3); keys sorted (ut_metadata < ut_pex) 119 let cben: *u8 = "d1:md11:ut_metadatai1e6:ut_pexi3eee" as *u8 120 let cm: *u8 = sys_mmap(512); let cml: i64 = px_build_ext(0, cben, gx_len(cben), cm); gx_write_n(cfd, cm, cml) 121 // msg1: peer ext handshake (id20 ext-id0) -> learn peer ut_pex id 122 let mb1: *u8 = sys_mmap(512); let bl1: i64 = gx_read_msg(cfd, mb1, 512) 123 if bl1 > 2 { if nx_pw_msg_id(mb1) == PW_EXTENDED { if (mb1[5] as i64) == 0 { 124 ext_ok = 1 125 if pex_peer_id(mb1, 6, 4 + bl1) == 7 { peer_id_ok = 1 } 126 } } } 127 // msg2: peer PEX message (id20 ext-id == PEX_OUR_ID) -> harvest gossiped peers 128 let mb2: *u8 = sys_mmap(512); let bl2: i64 = gx_read_msg(cfd, mb2, 512) 129 if bl2 > 2 { if nx_pw_msg_id(mb2) == PW_EXTENDED { if (mb2[5] as i64) == PEX_OUR_ID { 130 let oip: *i64 = sys_mmap(8 * 8) as *i64; let opt: *i64 = sys_mmap(8 * 8) as *i64 131 pex_count = pex_parse_added(mb2, 6, 4 + bl2, oip, opt, 8) 132 if pex_count == 3 { 133 if oip[0] == gips[0] { if opt[0] == gpts[0] { p0_ok = 1 } } 134 if oip[2] == gips[2] { if opt[2] == gpts[2] { p2_ok = 1 } } 135 } 136 } } } 137 } 138 } 139 let st: *i64 = sys_mmap(16) as *i64; sys_wait4(pid, st, 0); sys_close(cfd); sys_close(lfd) 140 141 gx_w(1, "PEX-GATE authored=organ conn_ok=" as *u8); gx_wn(1, conn_ok) 142 gx_w(1, " handshake_ok=" as *u8); gx_wn(1, hs_ok) 143 gx_w(1, " ext_ok=" as *u8); gx_wn(1, ext_ok) 144 gx_w(1, " peer_ut_pex_id_ok=" as *u8); gx_wn(1, peer_id_ok) 145 gx_w(1, " pex_count=" as *u8); gx_wn(1, pex_count) 146 gx_w(1, " peer0_ok=" as *u8); gx_wn(1, p0_ok) 147 gx_w(1, " peer2_ok=" as *u8); gx_wn(1, p2_ok) 148 var allok: i64 = 0 149 if conn_ok == 1 { if hs_ok == 1 { if ext_ok == 1 { if peer_id_ok == 1 { if pex_count == 3 { if p0_ok == 1 { if p2_ok == 1 { allok = 1 } } } } } } } 150 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 151 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 152 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 153 let ctr__dry: *i64 = gv_ctr() 154 ctr__dry[0] = allok 155 ctr__dry[1] = 1 156 let rc__dry: i64 = gv_verdict("PEX-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 157 sys_exit(rc__dry) 158 return rc__dry 159}