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}