nx_peer_connect_live.nx source
↩ module page · 145 lines · 8061 B
1// nx_peer_connect_live.nx -- LIVE BEP-3 handshake with a REAL peer (X-TORRENT-LIVE-001 L3a):
2// announce -> real peers -> TCP connect + handshake each, validate info_hash. BOUNDED CONNECT (no-
3// hang law): blocking connect() to an unreachable peer hangs ~127s, so each attempt runs in a FORK
4// and the PARENT bounds it (WNOHANG poll loop + nx_kill on timeout) -- reliable, no fcntl needed.
5// Composes nx_dns_a + nx_udp_tracker (announce) + nx_peerwire (handshake). Test = Big Buck Bunny.
6// GATE = LIVE: any real peer completes the BEP-3 handshake (info_hash matches). license_tier: ORIGINAL
7//
8// module: nishi-core.torrent.peer_connect_live
9// depends: nishi-core.torrent.dns_a, nishi-core.torrent.udp_tracker, nishi-core.torrent.peerwire
10import "nx_dns_a.nx"
11import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
12import "nx_udp_tracker.nx"
13import "nx_peerwire.nx"
14const K_MAGIC_305419896: i64 = 305419896
15const K_MAGIC_1000000000: i64 = 1000000000
16const K_MAGIC_6881: i64 = 6881
17const K_MAGIC_2048: i64 = 2048
18const K_MAGIC_6000: i64 = 6000
19
20func cl_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 }
21func cl_wn(fd: i64, v: i64) -> i64 {
22 let t: *u8=sys_mmap(28); var m: i64=v; if m<0 {m=0-m; sys_write(fd,"-" as *u8,1)}
23 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}
24 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
25}
26func cl_sockaddr(sa: *u8, port: i64, i0: i64, i1: i64, i2: i64, i3: i64) -> i64 {
27 sa[0]=2 as u8; sa[1]=0 as u8
28 sa[2]=((port>>8)&0xff) as u8; sa[3]=(port&0xff) as u8
29 sa[4]=i0 as u8; sa[5]=i1 as u8; sa[6]=i2 as u8; sa[7]=i3 as u8
30 var k: i64=8; while k<16 { sa[k]=0 as u8; k=k+1 }
31 return 0
32}
33func cl_read_n(fd: i64, buf: *u8, n: i64) -> i64 {
34 var got: i64 = 0
35 while got < n { let r: i64 = sys_read(fd, buf + got, n - got); if r <= 0 { return 0 - 1 } got = got + r }
36 return got
37}
38func cl_write_n(fd: i64, buf: *u8, n: i64) -> i64 {
39 var off: i64 = 0
40 while off < n { let w: i64 = sys_write(fd, buf + off, n - off); if w <= 0 { return 0 - 1 } off = off + w }
41 return n
42}
43
44// announce BBB to open.stealth.si:80 -> fill ips[]/ports[]; returns peer count
45func cl_announce(ih: *u8, pid: *u8, ips: *i64, ports: *i64, max: i64) -> i64 {
46 let ip: *u8 = sys_mmap(4)
47 if nx_dns_a_resolve("open.stealth.si" as *u8, ip) != 1 { return 0 - 1 }
48 let fd: i64 = sys_socket(AF_INET, SOCK_DGRAM, 0); if fd < 0 { return 0 - 1 }
49 sys_set_socket_timeout(fd, 5)
50 let dest: *u8 = sys_mmap(16); cl_sockaddr(dest, 80, ip[0] as i64, ip[1] as i64, ip[2] as i64, ip[3] as i64)
51 let txid: i64 = K_MAGIC_305419896
52 let creq: *u8 = sys_mmap(32); nx_udp_build_connect(txid, creq); sys_sendto(fd, creq, 16, 0, dest, 16)
53 let cr: *u8 = sys_mmap(64); let cn: i64 = sys_recvfrom(fd, cr, 64, 0, 0 as *u8, 0 as *i64)
54 let oc: *i64 = sys_mmap(16) as *i64
55 if cn < 16 { sys_close(fd); return 0 - 1 }
56 if nx_udp_parse_connect_resp(cr, cn, txid, oc) != 1 { sys_close(fd); return 0 - 1 }
57 let areq: *u8 = sys_mmap(128); nx_udp_build_announce(oc[0], txid, ih, pid, 0, K_MAGIC_1000000000, 0, 2, 80, K_MAGIC_6881, areq)
58 sys_sendto(fd, areq, 98, 0, dest, 16)
59 let ar: *u8 = sys_mmap(K_MAGIC_2048); let an: i64 = sys_recvfrom(fd, ar, K_MAGIC_2048, 0, 0 as *u8, 0 as *i64)
60 sys_close(fd)
61 if an < 20 { return 0 - 1 }
62 let oiv: *i64 = sys_mmap(16) as *i64; let osd: *i64 = sys_mmap(16) as *i64; let olc: *i64 = sys_mmap(16) as *i64
63 return nx_udp_parse_announce_resp(ar, an, txid, oiv, osd, olc, ips, ports, max)
64}
65
66// CHILD: connect+handshake one peer; on success write [1][20 peer_id] to respath.
67func cl_child(ipv: i64, port: i64, ih: *u8, mypid: *u8, respath: *u8) -> i64 {
68 let fd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
69 if fd < 0 { return 0 }
70 sys_set_socket_timeout(fd, 3)
71 let dest: *u8 = sys_mmap(16)
72 cl_sockaddr(dest, port, (ipv>>24)&0xff, (ipv>>16)&0xff, (ipv>>8)&0xff, ipv&0xff)
73 if nx_connect_bounded(fd, dest, 16, NX_CONN_DEFAULT_MS) == 0 {
74 let ch: *u8 = sys_mmap(128); nx_pw_build_handshake(ih, mypid, ch); ch[25] = (ch[25] as i64 | 0x10) as u8
75 if cl_write_n(fd, ch, 68) == 68 {
76 let ph: *u8 = sys_mmap(128)
77 if cl_read_n(fd, ph, 68) == 68 {
78 let gih: *u8 = sys_mmap(20); let gpid: *u8 = sys_mmap(20)
79 if nx_pw_parse_handshake(ph, 68, gih, gpid) == 1 {
80 var eqv: i64 = 1; var i: i64 = 0; while i < 20 { if gih[i] != ih[i] { eqv = 0; i = 20 } else { i = i + 1 } }
81 if eqv == 1 {
82 let rf: i64 = sys_openat_wr(respath, 0x1a4)
83 if rf >= 0 { let ob: *u8 = sys_mmap(32); ob[0]=1 as u8; var k: i64=0; while k<20 { ob[1+k]=gpid[k]; k=k+1 } cl_write_n(rf, ob, 21); sys_close(rf) }
84 }
85 }
86 }
87 }
88 }
89 sys_close(fd)
90 return 0
91}
92
93func main() -> i64 {
94 let ih: *u8 = sys_mmap(20)
95 ih[0]=221 as u8; ih[1]=130 as u8; ih[2]=85 as u8; ih[3]=236 as u8; ih[4]=220 as u8
96 ih[5]=124 as u8; ih[6]=165 as u8; ih[7]=95 as u8; ih[8]=176 as u8; ih[9]=187 as u8
97 ih[10]=248 as u8; ih[11]=19 as u8; ih[12]=35 as u8; ih[13]=216 as u8; ih[14]=112 as u8
98 ih[15]=98 as u8; ih[16]=219 as u8; ih[17]=31 as u8; ih[18]=109 as u8; ih[19]=28 as u8
99 let mypid: *u8 = sys_mmap(20); let ps: *u8 = "-NX0001-000000000000" as *u8; var z: i64 = 0; while z < 20 { mypid[z] = ps[z]; z = z + 1 }
100
101 let ips: *i64 = sys_mmap(8*64) as *i64; let ports: *i64 = sys_mmap(8*64) as *i64
102 let np: i64 = cl_announce(ih, mypid, ips, ports, 64)
103 cl_w(1, "PEERCONNLIVE peers_from_tracker=" as *u8); cl_wn(1, np); cl_w(1, "\n" as *u8)
104 if np < 1 { cl_w(1, "PEERCONNLIVE verdict=RED reason=no-peers\n" as *u8); sys_exit(1); return 1 }
105
106 let respath: *u8 = "/tmp/_nx_peer_hs.bin" as *u8
107 let st: *i64 = sys_mmap(16) as *i64
108 var tries: i64 = np; if tries > 20 { tries = 20 }
109 var ok: i64 = 0
110 var attempted: i64 = 0
111 var i: i64 = 0
112 while i < tries {
113 if ok == 0 {
114 // clear result
115 let cf: i64 = sys_openat_wr(respath, 0x1a4); if cf >= 0 { let zb: *u8 = sys_mmap(4); zb[0]=0 as u8; cl_write_n(cf, zb, 1); sys_close(cf) }
116 attempted = attempted + 1
117 let pid: i64 = sys_fork()
118 if pid == 0 { cl_child(ips[i], ports[i], ih, mypid, respath); sys_exit(0) }
119 // parent: bound to ~6s
120 var el: i64 = 0; var go: i64 = 1
121 while go == 1 {
122 let r: i64 = sys_wait4(pid, st, WNOHANG)
123 if r > 0 { go = 0 } else { if el >= K_MAGIC_6000 { go = 0 } else { sys_sleep_ms(150); el = el + 150 } }
124 }
125 // if still alive, kill + reap
126 if sys_wait4(pid, st, WNOHANG) <= 0 { nx_kill(pid, 9); sys_wait4(pid, st, 0) }
127 // read result
128 let rf: i64 = sys_openat_rd(respath)
129 if rf >= 0 { let rb: *u8 = sys_mmap(32); let rn: i64 = sys_read(rf, rb, 32); sys_close(rf)
130 if rn >= 1 { if (rb[0] as i64) == 1 {
131 ok = 1
132 let a: i64 = ips[i]
133 cl_w(1, "PEERCONNLIVE HANDSHAKE OK peer=" as *u8)
134 cl_wn(1, (a>>24)&0xff); cl_w(1, "." as *u8); cl_wn(1, (a>>16)&0xff); cl_w(1, "." as *u8); cl_wn(1, (a>>8)&0xff); cl_w(1, "." as *u8); cl_wn(1, a&0xff); cl_w(1, ":" as *u8); cl_wn(1, ports[i])
135 cl_w(1, " peer_id[0..8]=" as *u8); var q: i64 = 1; while q < 9 { cl_wn(1, rb[q] as i64); cl_w(1, " " as *u8); q = q + 1 } cl_w(1, "\n" as *u8)
136 } }
137 }
138 }
139 i = i + 1
140 }
141 cl_w(1, "PEERCONNLIVE attempted=" as *u8); cl_wn(1, attempted)
142 if ok == 1 { cl_w(1, " verdict=GREEN (real BEP-3 handshake with a real peer)\n" as *u8); sys_exit(0); return 0 }
143 cl_w(1, " verdict=RED reason=no-peer-handshook (firewalled/timeout)\n" as *u8); sys_exit(1)
144 return 1
145}