code wiki / (root) / nx_hls_resolve.nx

nx_hls_resolve.nx source

↩ module page · 134 lines · 6617 B

1// nx_hls_resolve.nx -- X-DLP rung 1: resolve an HLS segment/variant URI against the 2// playlist's own URL -> an ABSOLUTE URL the sovereign fetch client can GET. HLS URIs 3// come in three shapes (RFC 8216 + RFC 3986 ยง5): 4// absolute "https://cdn/s.ts" -> use as-is 5// path-absolute "/v/s.ts" -> scheme://host + uri 6// relative "s0.ts" -> base-directory (up to last '/') + uri 7// Composes nx_hls_parse (rung 0). Pure string logic -> offline-gateable. Together 8// rungs 0+1 turn (playlist URL + bytes) into the concrete list of segment URLs to 9// fetch via the already-sovereign h2/https client. No JS, no curl. license_tier: ORIGINAL 10import "nx_hls_parse.nx" 11import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 12 13func hr_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 14// 1 iff buf[0:4] == "http" 15func hr_is_abs(uri: *u8, ulen: i64) -> i64 { 16 if ulen < 4 { return 0 } 17 if (uri[0] & 0xff) != 104 { return 0 } // h 18 if (uri[1] & 0xff) != 116 { return 0 } // t 19 if (uri[2] & 0xff) != 116 { return 0 } // t 20 if (uri[3] & 0xff) != 112 { return 0 } // p 21 return 1 22} 23 24// Resolve uri against base into out; return out length, or -1 on overflow / bad base. 25func nx_hls_resolve_uri(base: *u8, blen: i64, uri: *u8, ulen: i64, out: *u8, out_cap: i64) -> i64 { 26 // ---- absolute ---- 27 if hr_is_abs(uri, ulen) == 1 { 28 if ulen > out_cap { return 0 - 1 } 29 var i: i64 = 0 30 while i < ulen { out[i] = uri[i]; i = i + 1 } 31 return ulen 32 } 33 // ---- locate scheme + host in base ---- 34 let sc: i64 = hls_find(base, 0, blen, "://\x00" as *u8) 35 if sc < 0 { return 0 - 1 } 36 let after: i64 = sc + 3 37 var he: i64 = after 38 var g: i64 = 1 39 while g == 1 { if he >= blen { g = 0 } else { if (base[he] & 0xff) == 47 { g = 0 } else { he = he + 1 } } } // first '/' after host 40 // ---- path-absolute: scheme://host + uri ---- 41 if ulen > 0 { if (uri[0] & 0xff) == 47 { 42 let n: i64 = he + ulen 43 if n > out_cap { return 0 - 1 } 44 var i: i64 = 0 45 while i < he { out[i] = base[i]; i = i + 1 } 46 var j: i64 = 0 47 while j < ulen { out[he + j] = uri[j]; j = j + 1 } 48 return n 49 } } 50 // ---- relative: base directory (up to last '/' at/after host) + uri ---- 51 var found: i64 = he 52 var li: i64 = blen - 1 53 var g2: i64 = 1 54 while g2 == 1 { if li < he { g2 = 0 } else { if (base[li] & 0xff) == 47 { found = li; g2 = 0 } else { li = li - 1 } } } 55 let dirlen: i64 = found + 1 56 let n2: i64 = dirlen + ulen 57 if n2 > out_cap { return 0 - 1 } 58 var a: i64 = 0 59 while a < dirlen { out[a] = base[a]; a = a + 1 } 60 var b: i64 = 0 61 while b < ulen { out[dirlen + b] = uri[b]; b = b + 1 } 62 return n2 63} 64 65// ===================== GATE ===================== 66func hrr_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 67// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 68// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 69// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 70// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 71func hrr_putn(v: i64) -> i64 { nxi_out(v); return 0 } 72func hrr_eq(out: *u8, n: i64, want: *u8) -> i64 { 73 if n != hr_slen(want) { return 0 } 74 var i: i64 = 0 75 while i < n { if (out[i] & 0xff) != (want[i] & 0xff) { return 0 } i = i + 1 } 76 return 1 77} 78 79func main() -> i64 { 80 var pass: i64 = 0 81 var tot: i64 = 0 82 hrr_puts("nx_hls_resolve gate (X-DLP rung 1, RFC 3986 segment URL resolution)\n" as *u8) 83 let out: *u8 = sys_mmap(512) 84 let base: *u8 = "https://ex.com/a/b.m3u8\x00" as *u8 85 let bl: i64 = hr_slen(base) 86 87 // KAT1: relative -> base dir + uri 88 let u1: *u8 = "s0.ts\x00" as *u8 89 let n1: i64 = nx_hls_resolve_uri(base, bl, u1, hr_slen(u1), out, 512) 90 var r1: i64 = hrr_eq(out, n1, "https://ex.com/a/s0.ts\x00" as *u8) 91 if r1 == 1 { hrr_puts(" PASS KAT1 relative s0.ts -> https://ex.com/a/s0.ts\n" as *u8); pass=pass+1 } else { hrr_puts(" FAIL KAT1 relative got=" as *u8); sys_write(1, out, n1); hrr_puts("\n" as *u8) } 92 tot = tot + 1 93 94 // KAT2: path-absolute -> scheme://host + uri 95 let u2: *u8 = "/v/s.ts\x00" as *u8 96 let n2: i64 = nx_hls_resolve_uri(base, bl, u2, hr_slen(u2), out, 512) 97 var r2: i64 = hrr_eq(out, n2, "https://ex.com/v/s.ts\x00" as *u8) 98 if r2 == 1 { hrr_puts(" PASS KAT2 path-absolute /v/s.ts -> https://ex.com/v/s.ts\n" as *u8); pass=pass+1 } else { hrr_puts(" FAIL KAT2 path-abs got=" as *u8); sys_write(1, out, n2); hrr_puts("\n" as *u8) } 99 tot = tot + 1 100 101 // KAT3: absolute -> unchanged 102 let u3: *u8 = "https://cdn.x/seg.ts\x00" as *u8 103 let n3: i64 = nx_hls_resolve_uri(base, bl, u3, hr_slen(u3), out, 512) 104 var r3: i64 = hrr_eq(out, n3, "https://cdn.x/seg.ts\x00" as *u8) 105 if r3 == 1 { hrr_puts(" PASS KAT3 absolute -> unchanged\n" as *u8); pass=pass+1 } else { hrr_puts(" FAIL KAT3 absolute got=" as *u8); sys_write(1, out, n3); hrr_puts("\n" as *u8) } 106 tot = tot + 1 107 108 // KAT4 (end-to-end): parse a media playlist, resolve every segment to absolute. 109 let pl: *u8 = "#EXTM3U\n#EXTINF:6.0,\nseg0.ts\n#EXTINF:6.0,\nsub/seg1.ts\n\x00" as *u8 110 let entries: *i64 = sys_mmap(8*3*64) as *i64 111 let meta: *i64 = sys_mmap(8*8) as *i64 112 let cnt: i64 = nx_hls_parse(pl, hr_slen(pl), entries, 64, meta) 113 var r4: i64 = 1 114 if cnt != 2 { r4 = 0 } 115 if r4 == 1 { 116 // seg0 -> https://ex.com/a/seg0.ts 117 let s0: i64 = entries[0*3+0]; let l0: i64 = entries[0*3+1] 118 let rn0: i64 = nx_hls_resolve_uri(base, bl, (pl as i64 + s0) as *u8, l0, out, 512) 119 if hrr_eq(out, rn0, "https://ex.com/a/seg0.ts\x00" as *u8) == 0 { r4 = 0 } 120 } 121 if r4 == 1 { 122 // sub/seg1.ts -> https://ex.com/a/sub/seg1.ts 123 let s1: i64 = entries[1*3+0]; let l1: i64 = entries[1*3+1] 124 let rn1: i64 = nx_hls_resolve_uri(base, bl, (pl as i64 + s1) as *u8, l1, out, 512) 125 if hrr_eq(out, rn1, "https://ex.com/a/sub/seg1.ts\x00" as *u8) == 0 { r4 = 0 } 126 } 127 if r4 == 1 { hrr_puts(" PASS KAT4 end-to-end parse->resolve 2 segs to absolute URLs\n" as *u8); pass=pass+1 } else { hrr_puts(" FAIL KAT4 e2e\n" as *u8) } 128 tot = tot + 1 129 130 hrr_puts("---- nx_hls_resolve gate: passed " as *u8); hrr_putn(pass); hrr_puts(" / " as *u8); hrr_putn(tot); hrr_puts("\n" as *u8) 131 if pass == tot { sys_exit(0); return 0 } 132 sys_exit(1) 133 return 1 134}