nx_tracker_url.nx source
↩ module page · 125 lines · 5941 B
1// nx_tracker_url.nx -- parse a BitTorrent tracker URL (from nx_magnet's tr= list) into
2// scheme/host/port/path, the input the announce round-trip needs (resolve host -> IP, dial
3// host:port). Pure/deterministic/sovereign. scheme: udp=1 (BEP-15), http=2, https=3, else 0=reject.
4// Default port by scheme when absent (http=80, https=443, udp=6969); default path "/announce".
5// Self-gating (main = baked KAT). license_tier: ORIGINAL
6//
7// module: nishi-core.torrent.tracker_url
8// depends: nishi-core.sys.syscalls
9// capability: TORRENT_TRACKER_URL_PARSE
10import "nx_syscalls.nx"
11const K_MAGIC_6969: i64 = 6969
12const K_MAGIC_1337: i64 = 1337
13
14func tu_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 }
15func tu_wn(fd: i64, v: i64) -> i64 {
16 let t: *u8=sys_mmap(28); var m: i64=v; if m<0 {m=0-m; sys_write(fd,"-" as *u8,1)}
17 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}
18 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
19}
20func tu_len(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
21// buf[a,..) starts with lit?
22func tu_starts(buf: *u8, a: i64, n: i64, lit: *u8) -> i64 {
23 let ll: i64 = tu_len(lit)
24 if a + ll > n { return 0 }
25 var i: i64 = 0
26 while i < ll { if buf[a+i] != lit[i] { return 0 } i = i + 1 }
27 return 1
28}
29// str equals lit?
30func tu_streq(s: *u8, lit: *u8) -> i64 {
31 var i: i64 = 0
32 while s[i] != (0 as u8) { if s[i] != lit[i] { return 0 } i = i + 1 }
33 if lit[i] != (0 as u8) { return 0 }
34 return 1
35}
36
37// parse url -> scheme_id (ret), host (out), port (out), path (out). 0 = unknown/invalid scheme.
38func tu_parse(url: *u8, port_out: *i64, host: *u8, path: *u8) -> i64 {
39 let n: i64 = tu_len(url)
40 var scheme: i64 = 0
41 var rest: i64 = 0
42 if tu_starts(url, 0, n, "udp://" as *u8) == 1 { scheme = 1; rest = 6 }
43 if tu_starts(url, 0, n, "http://" as *u8) == 1 { scheme = 2; rest = 7 }
44 if tu_starts(url, 0, n, "https://" as *u8) == 1 { scheme = 3; rest = 8 }
45 if scheme == 0 { return 0 }
46 // host = [rest, until ':' or '/' or end)
47 var i: i64 = rest
48 var h: i64 = 0
49 while i < n { if url[i] == (58 as u8) { i = n + 1 } else { if url[i] == (47 as u8) { i = n + 2 } else { host[h] = url[i]; h = h + 1; i = i + 1 } } }
50 host[h] = 0 as u8
51 // default port by scheme
52 var port: i64 = K_MAGIC_6969
53 if scheme == 2 { port = 80 }
54 if scheme == 3 { port = 443 }
55 // re-scan from rest+h to find ':' (explicit port) and '/' (path)
56 var p: i64 = rest + h
57 if p < n { if url[p] == (58 as u8) {
58 // explicit port digits
59 var pv: i64 = 0
60 var any: i64 = 0
61 p = p + 1
62 while p < n { if url[p] == (47 as u8) { p = n + 5 } else { let c: i64 = url[p] as i64; if c >= 48 { if c <= 57 { pv = pv*10 + (c-48); any = 1 } } p = p + 1 } }
63 if any == 1 { port = pv }
64 if p > n { p = p - 5 } // landed on '/': restore p to the '/' index
65 } }
66 port_out[0] = port
67 // path = from the FIRST '/' after the authority to end; else "/announce"
68 var sp: i64 = rest
69 var slashpos: i64 = 0 - 1
70 while sp < n { if url[sp] == (47 as u8) { slashpos = sp; sp = n + 100 } else { sp = sp + 1 } }
71 if slashpos >= 0 {
72 var k: i64 = 0
73 var q: i64 = slashpos
74 while q < n { path[k] = url[q]; k = k + 1; q = q + 1 }
75 path[k] = 0 as u8
76 } else {
77 path[0]=47 as u8; path[1]=97 as u8; path[2]=110 as u8; path[3]=110 as u8; path[4]=111 as u8; path[5]=117 as u8; path[6]=110 as u8; path[7]=99 as u8; path[8]=101 as u8; path[9]=0 as u8 // "/announce"
78 }
79 return scheme
80}
81
82func main() -> i64 {
83 let host: *u8 = sys_mmap(512)
84 let path: *u8 = sys_mmap(512)
85 let port: *i64 = sys_mmap(16) as *i64
86
87 // pos1: udp with explicit port + path
88 let s1: i64 = tu_parse("udp://tracker.opentrackr.org:1337/announce" as *u8, port, host, path)
89 var pos1: i64 = 0
90 if s1 == 1 { if port[0] == K_MAGIC_1337 { if tu_streq(host, "tracker.opentrackr.org" as *u8) == 1 { if tu_streq(path, "/announce" as *u8) == 1 { pos1 = 1 } } } }
91
92 // pos2: http with explicit port
93 let s2: i64 = tu_parse("http://torrent.ubuntu.com:6969/announce" as *u8, port, host, path)
94 var pos2: i64 = 0
95 if s2 == 2 { if port[0] == K_MAGIC_6969 { if tu_streq(host, "torrent.ubuntu.com" as *u8) == 1 { pos2 = 1 } } }
96
97 // pos3: https, no explicit port -> default 443; path "/x"
98 let s3: i64 = tu_parse("https://tracker.example/x" as *u8, port, host, path)
99 var pos3: i64 = 0
100 if s3 == 3 { if port[0] == 443 { if tu_streq(host, "tracker.example" as *u8) == 1 { if tu_streq(path, "/x" as *u8) == 1 { pos3 = 1 } } } }
101
102 // pos4: udp, no port, no path -> default 6969 + "/announce"
103 let s4: i64 = tu_parse("udp://t.example" as *u8, port, host, path)
104 var pos4: i64 = 0
105 if s4 == 1 { if port[0] == K_MAGIC_6969 { if tu_streq(host, "t.example" as *u8) == 1 { if tu_streq(path, "/announce" as *u8) == 1 { pos4 = 1 } } } }
106
107 // neg1: unknown scheme
108 var neg1: i64 = 0
109 if tu_parse("ftp://x:1/y" as *u8, port, host, path) == 0 { neg1 = 1 }
110 // neg2: no scheme
111 var neg2: i64 = 0
112 if tu_parse("tracker.example:80/announce" as *u8, port, host, path) == 0 { neg2 = 1 }
113
114 tu_w(1, "TRACKERURL-GATE authored=organ pos1_udp=" as *u8); tu_wn(1, pos1)
115 tu_w(1, " pos2_http=" as *u8); tu_wn(1, pos2)
116 tu_w(1, " pos3_https_defport=" as *u8); tu_wn(1, pos3)
117 tu_w(1, " pos4_noport_nopath=" as *u8); tu_wn(1, pos4)
118 tu_w(1, " neg1_badscheme=" as *u8); tu_wn(1, neg1)
119 tu_w(1, " neg2_noscheme=" as *u8); tu_wn(1, neg2)
120 var ok: i64 = 0
121 if pos1==1 { if pos2==1 { if pos3==1 { if pos4==1 { if neg1==1 { if neg2==1 { ok = 1 } } } } } }
122 if ok == 1 { tu_w(1, " verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
123 tu_w(1, " verdict=RED\n" as *u8); sys_exit(1)
124 return 1
125}