code wiki / _hdl_build / nx_dist_index.nx
nx_dist_index.nx source
↩ module page · 90 lines · 4999 B
1// nx_dist_index.nx -- LIB: the NAPSTER-STYLE distribution INDEX (operator: "lots of peers can share with lots of
2// peers like napster or torrents"). The hub keeps a central registry of WHAT content exists and WHO has it, so any
3// peer can DISCOVER content + its holders, then transfer P2P (via the magnet/swarm the enabler minted). Two
4// append-only logs (additive-only, history sacred -- Cardinal 13):
5// CONTENT registry: name<TAB>cid<TAB>size<TAB>magnet<TAB>url\n (one row per published item; the enabler's row)
6// PEER registry: cid<TAB>peer\n (one row per announce = "peer HAS cid")
7// Publish is idempotent by cid (Cardinal 10). Search-by-name + count-holders + lookup-by-cid = the Napster query
8// surface. Composes the enabler (nx_dist_publish) descriptors. No TLS. license_tier: ORIGINAL
9import "nx_syscalls.nx"
10
11func di_strlen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
12func di_cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var i: i64=0; while s[i]!=(0 as u8){dst[o]=s[i];o=o+1;i=i+1} return o }
13func di_wdec(dst: *u8, off: i64, v: i64) -> i64 { var o: i64=off; if v==0 { dst[o]=48 as u8; return o+1 } let t:*u8=sys_mmap(24); var k:i64=0; var m:i64=v; while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } var j:i64=k-1; while j>=0 { dst[o]=t[j]; o=o+1; j=j-1 } return o }
14func di_memeq(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if a[i]!=b[i] { return 0 } i=i+1 } return 1 }
15func di_eol(buf: *u8, from: i64, blen: i64) -> i64 { var e: i64=from; while e<blen { if buf[e]==10 as u8 { return e } e=e+1 } return blen }
16func di_tab(buf: *u8, from: i64, limit: i64) -> i64 { var e: i64=from; while e<limit { if buf[e]==9 as u8 { return e } e=e+1 } return limit }
17// substring: does hay[0..hlen] contain the C-string needle?
18func di_contains(hay: *u8, hlen: i64, needle: *u8) -> i64 {
19 let nl: i64 = di_strlen(needle)
20 if nl==0 { return 1 }
21 var i: i64 = 0
22 while i+nl<=hlen { var ok: i64=1; var j: i64=0; while j<nl { if hay[i+j]!=needle[j] { ok=0 } j=j+1 } if ok==1 { return 1 } i=i+1 }
23 return 0
24}
25// number of content/peer rows (newline count).
26func di_count_rows(buf: *u8, blen: i64) -> i64 { var c: i64=0; var i: i64=0; while i<blen { if buf[i]==10 as u8 { c=c+1 } i=i+1 } return c }
27// is this cid already registered (as the flanked 2nd field <TAB>cid<TAB>)?
28func di_has_cid(buf: *u8, blen: i64, cid: *u8) -> i64 {
29 let ndl: *u8 = sys_mmap(128); var o: i64=0; ndl[o]=9 as u8; o=o+1
30 o = di_cat(ndl, o, cid); ndl[o]=9 as u8; o=o+1; ndl[o]=0 as u8
31 return di_contains(buf, blen, ndl)
32}
33
34// PUBLISH: append a content row iff cid is new. Returns the new content-buffer length. Idempotent by cid.
35func di_publish(buf: *u8, blen: i64, name: *u8, cid: *u8, size: i64, magnet: *u8, url: *u8) -> i64 {
36 if di_has_cid(buf, blen, cid)==1 { return blen }
37 var o: i64 = blen
38 o = di_cat(buf, o, name); buf[o]=9 as u8; o=o+1
39 o = di_cat(buf, o, cid); buf[o]=9 as u8; o=o+1
40 o = di_wdec(buf, o, size); buf[o]=9 as u8; o=o+1
41 o = di_cat(buf, o, magnet); buf[o]=9 as u8; o=o+1
42 o = di_cat(buf, o, url); buf[o]=10 as u8; o=o+1
43 return o
44}
45// ANNOUNCE: record "peer HAS cid" -> append cid<TAB>peer\n to the peer registry. Returns new peer-buffer length.
46func di_announce(pbuf: *u8, plen: i64, cid: *u8, peer: *u8) -> i64 {
47 var o: i64 = plen
48 o = di_cat(pbuf, o, cid); pbuf[o]=9 as u8; o=o+1
49 o = di_cat(pbuf, o, peer); pbuf[o]=10 as u8; o=o+1
50 return o
51}
52// SEARCH: count content rows whose NAME field contains substr (the discovery query).
53func di_search_name(buf: *u8, blen: i64, substr: *u8) -> i64 {
54 var cnt: i64=0; var ls: i64=0
55 while ls<blen {
56 let le: i64 = di_eol(buf, ls, blen)
57 let nt: i64 = di_tab(buf, ls, le)
58 if di_contains((buf as i64 + ls) as *u8, nt-ls, substr)==1 { cnt=cnt+1 }
59 ls = le+1
60 }
61 return cnt
62}
63// COUNT HOLDERS: how many peers announced they have this cid (who-has-what).
64func di_count_peers(pbuf: *u8, plen: i64, cid: *u8) -> i64 {
65 let cl: i64 = di_strlen(cid)
66 var cnt: i64=0; var ls: i64=0
67 while ls<plen {
68 let le: i64 = di_eol(pbuf, ls, plen)
69 let ft: i64 = di_tab(pbuf, ls, le)
70 if ft-ls==cl { if di_memeq((pbuf as i64 + ls) as *u8, cid, cl)==1 { cnt=cnt+1 } }
71 ls = le+1
72 }
73 return cnt
74}
75// LOOKUP: copy the content row for cid into out (0-terminated); returns row length or 0 if absent.
76func di_lookup(buf: *u8, blen: i64, cid: *u8, out: *u8) -> i64 {
77 let cl: i64 = di_strlen(cid)
78 var ls: i64=0
79 while ls<blen {
80 let le: i64 = di_eol(buf, ls, blen)
81 let t1: i64 = di_tab(buf, ls, le)
82 let cs: i64 = t1+1
83 let ce: i64 = di_tab(buf, cs, le)
84 if ce-cs==cl { if di_memeq((buf as i64 + cs) as *u8, cid, cl)==1 {
85 var o: i64=0; var k: i64=ls; while k<le { out[o]=buf[k]; o=o+1; k=k+1 } out[o]=0 as u8; return o
86 } }
87 ls = le+1
88 }
89 return 0
90}