nx_peer_ext_handshake.nx source
↩ module page · 138 lines · 7110 B
1// nx_peer_ext_handshake.nx -- BEP-10 extension-protocol handshake (X-TORRENT-LIVE-001 R3a): the
2// gateway to BEP-9 ut_metadata (fetch the info-dict for a magnet). After the BEP-3 handshake with
3// the extension bit set (reserved[5] |= 0x10), peers exchange an extended message id=20, ext-id=0,
4// payload = a bencoded dict advertising their extensions: {m:{ut_metadata:<id>}, metadata_size:N}.
5// This rung exchanges them over loopback and PARSES the peer's ut_metadata ext-id + metadata_size
6// (via nx_bencode: nx_bc_dict_get + nx_bc_int). Reuses nx_peerwire (BEP-3 + nx_pw_build_msg) +
7// nx_bencode (DECODE). GATE = SOVEREIGN LOOPBACK; the small bencoded dicts are built BY HAND (no
8// encoder needed). license_tier: ORIGINAL
9//
10// module: nishi-core.torrent.peer_ext_handshake
11// depends: nishi-core.torrent.peerwire, nishi-core.torrent.bencode
12import "nx_peerwire.nx"
13import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
14import "nx_bencode.nx"
15const PW_MAGIC_53431: i64 = 53431
16const PW_MAGIC_1234: i64 = 1234
17
18const PW_EXTENDED: i64 = 20
19
20func eh_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 eh_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 eh_len(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
27func eh_sockaddr(sa: *u8, port: i64, i0: i64, i1: i64, i2: i64, i3: i64) -> i64 {
28 sa[0]=2 as u8; sa[1]=0 as u8
29 sa[2]=((port>>8)&0xff) as u8; sa[3]=(port&0xff) as u8
30 sa[4]=i0 as u8; sa[5]=i1 as u8; sa[6]=i2 as u8; sa[7]=i3 as u8
31 var k: i64=8; while k<16 { sa[k]=0 as u8; k=k+1 }
32 return 0
33}
34func eh_read_n(fd: i64, buf: *u8, n: i64) -> i64 {
35 var got: i64 = 0
36 while got < n { let r: i64 = sys_read(fd, buf + got, n - got); if r <= 0 { return 0 - 1 } got = got + r }
37 return got
38}
39func eh_write_n(fd: i64, buf: *u8, n: i64) -> i64 {
40 var off: i64 = 0
41 while off < n { let w: i64 = sys_write(fd, buf + off, n - off); if w <= 0 { return 0 - 1 } off = off + w }
42 return n
43}
44func eh_read_msg(fd: i64, mb: *u8, cap: i64) -> i64 {
45 if eh_read_n(fd, mb, 4) != 4 { return 0 - 1 }
46 let blen: i64 = _pw_get_u32(mb, 0)
47 if blen == 0 { return 0 }
48 if blen > cap - 4 { return 0 - 1 }
49 if eh_read_n(fd, mb + 4, blen) != blen { return 0 - 1 }
50 return blen
51}
52// build an extended message (id=20): payload = [ext_id] + bencoded; returns total bytes in out.
53func eh_build_ext(ext_id: i64, ben: *u8, out: *u8) -> i64 {
54 let bl: i64 = eh_len(ben)
55 let pl: *u8 = sys_mmap(512)
56 pl[0] = ext_id as u8
57 var i: i64 = 0; while i < bl { pl[1 + i] = ben[i]; i = i + 1 }
58 return nx_pw_build_msg(PW_EXTENDED, pl, 1 + bl, out)
59}
60
61func main() -> i64 {
62 let PORT: i64 = PW_MAGIC_53431
63 let ih: *u8 = sys_mmap(20); var z: i64 = 0; while z < 20 { ih[z] = (z+1) as u8; z = z + 1 }
64 let pidb: *u8 = sys_mmap(20); z = 0; while z < 20 { pidb[z] = 80 as u8; z = z + 1 }
65 let sa: *u8 = sys_mmap(16); eh_sockaddr(sa, PORT, 127, 0, 0, 1)
66 // peer advertises ut_metadata=2, metadata_size=1234
67 let peer_ben: *u8 = "d1:md11:ut_metadatai2ee13:metadata_sizei1234ee" as *u8
68 let cli_ben: *u8 = "d1:md11:ut_metadatai1eee" as *u8
69
70 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
71 var bound: i64 = 0
72 if lfd >= 0 {
73 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
74 sys_setsockopt(lfd, SOL_SOCKET, 2, one, 4)
75 sys_set_socket_timeout(lfd, 3)
76 if sys_bind(lfd, sa, 16) >= 0 { if sys_listen(lfd, 1) >= 0 { bound = 1 } }
77 }
78 if bound == 0 { eh_w(1, "EXTHS-GATE authored=organ bound=0 verdict=RED\n" as *u8); sys_exit(1); return 1 }
79
80 let pid: i64 = sys_fork()
81 if pid == 0 {
82 // MOCK PEER
83 let afd: i64 = sys_accept(lfd)
84 if afd >= 0 {
85 sys_set_socket_timeout(afd, 3)
86 let hb: *u8 = sys_mmap(128); eh_read_n(afd, hb, 68)
87 let oh: *u8 = sys_mmap(128); nx_pw_build_handshake(ih, pidb, oh); oh[25] = (oh[25] as i64 | 0x10) as u8; eh_write_n(afd, oh, 68)
88 let mb: *u8 = sys_mmap(512); eh_read_msg(afd, mb, 512) // client ext handshake
89 let om: *u8 = sys_mmap(512); let oml: i64 = eh_build_ext(0, peer_ben, om); eh_write_n(afd, om, oml)
90 sys_close(afd)
91 }
92 sys_close(lfd)
93 sys_exit(0)
94 }
95
96 // CLIENT
97 let cfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
98 sys_set_socket_timeout(cfd, 3)
99 var conn_ok: i64 = 0
100 if nx_connect_bounded(cfd, sa, 16, NX_CONN_DEFAULT_MS) >= 0 { conn_ok = 1 }
101 var hs_ok: i64 = 0; var ext_ok: i64 = 0; var utm_ok: i64 = 0; var size_ok: i64 = 0
102 if conn_ok == 1 {
103 let ch: *u8 = sys_mmap(128); nx_pw_build_handshake(ih, pidb, ch); ch[25] = (ch[25] as i64 | 0x10) as u8; eh_write_n(cfd, ch, 68)
104 let ph2: *u8 = sys_mmap(128)
105 if eh_read_n(cfd, ph2, 68) == 68 {
106 let gih: *u8 = sys_mmap(20); let gpid: *u8 = sys_mmap(20)
107 if nx_pw_parse_handshake(ph2, 68, gih, gpid) == 1 { hs_ok = 1 }
108 }
109 if hs_ok == 1 {
110 let cm: *u8 = sys_mmap(512); let cml: i64 = eh_build_ext(0, cli_ben, cm); eh_write_n(cfd, cm, cml)
111 let mb: *u8 = sys_mmap(512); let blen: i64 = eh_read_msg(cfd, mb, 512)
112 // mb[4]=msg id(20), mb[5]=ext id(0), mb[6..]=bencoded dict; n=4+blen
113 if blen > 2 { if nx_pw_msg_id(mb) == PW_EXTENDED { if (mb[5] as i64) == 0 {
114 ext_ok = 1
115 let ntot: i64 = 4 + blen
116 let m_off: i64 = nx_bc_dict_get(mb, 6, ntot, "m" as *u8, 1)
117 if m_off >= 0 {
118 let utm_off: i64 = nx_bc_dict_get(mb, m_off, ntot, "ut_metadata" as *u8, 11)
119 if utm_off >= 0 { let iv: *i64 = sys_mmap(16) as *i64; if nx_bc_int(mb, utm_off, ntot, iv) >= 0 { if iv[0] == 2 { utm_ok = 1 } } }
120 }
121 let ms_off: i64 = nx_bc_dict_get(mb, 6, ntot, "metadata_size" as *u8, 13)
122 if ms_off >= 0 { let iv2: *i64 = sys_mmap(16) as *i64; if nx_bc_int(mb, ms_off, ntot, iv2) >= 0 { if iv2[0] == PW_MAGIC_1234 { size_ok = 1 } } }
123 } } }
124 }
125 }
126 let st: *i64 = sys_mmap(16) as *i64; sys_wait4(pid, st, 0); sys_close(cfd); sys_close(lfd)
127
128 eh_w(1, "EXTHS-GATE authored=organ conn_ok=" as *u8); eh_wn(1, conn_ok)
129 eh_w(1, " handshake_ok=" as *u8); eh_wn(1, hs_ok)
130 eh_w(1, " ext_ok=" as *u8); eh_wn(1, ext_ok)
131 eh_w(1, " ut_metadata_id_ok=" as *u8); eh_wn(1, utm_ok)
132 eh_w(1, " metadata_size_ok=" as *u8); eh_wn(1, size_ok)
133 var allok: i64 = 0
134 if conn_ok==1 { if hs_ok==1 { if ext_ok==1 { if utm_ok==1 { if size_ok==1 { allok = 1 } } } } }
135 if allok == 1 { eh_w(1, " verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
136 eh_w(1, " verdict=RED\n" as *u8); sys_exit(1)
137 return 1
138}