:: :: :: :::: /hoon/ames/arvo :::::: vane prelude !: :: :: |= pit/vase :: kernel vase => =~ :: =, xmas :: :: :: :::: :::::: ames structures :: :: :: :: =* pipe channel:able:jael :: secure channel =* gree farm:pki:jael :: pki information |% :: ++ bait {p/skin q/@ud r/dove} :: fmt nrecvd spec ++ bath :: per friend $: det/pipe :: secure channel lun/(unit lane) :: latest route zam/scar :: outbound boles fon/(map bole lock) :: inbound locks sal/(map bole colt) :: outbound flows == :: ++ bole bone :: inbound opaque ++ cake {p/sock q/skin r/@} :: top level packet ++ chan path :: channel ++ clue :: live packet state $: vig/? :: true iff virgin tel/part :: block identity fap/flap :: fragment hash dat/rock :: fragment data == :: ++ coal :: live packet state $: out/@da :: sent date lod/@da :: lost-by deadline clu/clue :: packet to send == :: ++ colt :: outbound state $: seq/tick :: next tick to fill lac/tick :: acked tick until cob/(map tick comb) :: live messages myn/mini :: packet pump == :: ++ comb :: live message $: cup/(unit coop) :: final ack cha/path :: channel num/frag :: number of fragments ack/frag :: number acked cly/(list clue) :: left to send == :: ++ dove {p/@ud q/(map @ud @)} :: count 13-blocks ++ flap @uvH :: network packet id ++ flea (pair bole tick) :: message id ++ frag @ud :: fragment number ++ hand @uvH :: 128-bit hash ++ lock :: inbound sequencer $: laq/tick :: acknowledged until nys/(map tick bait) :: inbound partials laz/(unit (trel tick flap lane)) :: awaiting app exc/(map tick ares) :: negative acks == :: ++ meal :: payload $% {$back p/bone q/flap r/coop s/@dr} :: acknowledgment {$bond p/flea q/chan r/*} :: message {$carp p/moan q/(pair @ud @)} :: fragment {$fore p/ship q/(unit lane) r/@} :: forwarded packet == :: ++ mini :: pump data $: saw/stat :: statistics liv/(qeu coal) :: live packets lop/(qeu clue) :: lost packets == :: ++ moan :: message invariant $: {kos/bole liq/tick} :: flow identity syn/@ :: skin number cnt/@ :: number of packets == :: ++ mute :: awaiting channel $: inn/(list (pair lane rock)) :: inbound packets out/(list (trel duct chan *)) :: outbound messages == :: ++ part (pair frag tick) :: fragment of packet ++ rock @uvO :: packet ++ silo :: global state $: lyf/life :: current version wyr/(map life ring) :: private keys ech/(map ship mute) :: waiting partners pol/(map ship bath) :: open partners == :: ++ skin ?($none $open $fast $full) :: encoding stem ++ stat :: pump statistics $: $: cur/@ud :: window q length max/@ud :: max pax out rey/@ud :: retry q length == :: $: rtt/@dr :: roundtrip estimate las/@da :: last sent lad/@da :: last deadline == :: == :: ++ tick @ud :: message sequence no -- :: :: :: :::: :::: arvo structures :: :: |% :: ++ flam |=(a/flap `@p`(mug a)) :: debug flap ++ msec |=(a/@dr `@ud`(div a (div ~s1 1.000))) :: debug @dr ++ move %+ pair :: local move duct :: (wind note:able:xmas gift:able:xmas) :: :: :: :::: loft :::: main transceiver :: :: ++ loft :: => |% :: ++ gift :: output $% {$east p/duct q/ship r/chan s/*} :: network response {$home p/lane q/@} :: resend to self {$line p/ship q/@da r/code} :: add outbound key {$link p/ship q/@da r/code} :: add inbound key {$meet p/gree} :: add public key(s) {$rest p/duct q/coop} :: message result {$send p/lane q/@} :: transmit packet {$veil p/ship} :: cache channel {$west p/ship q/bole r/chan s/*} :: outbound message == :: ++ task :: input $% {$clue p/ship q/pipe} :: update channel {$done p/ship q/bole r/coop} :: completion {$hear p/lane q/@} :: incoming packet {$mess p/ship q/duct r/chan s/*} :: forward message {$rend p/ship q/bole r/chan s/*} :: backward message {$wake $~} :: wakeup == -- =| $: $: now/@da eny/@ == silo fex/(list gift) == =* syl ->- |% :: ++ abet [(flop fex) syl] :: resolve ++ apex :: compute |= job/task ^+ +> ?- -.job $clue (dear p.job q.job) $done abet:(done:(etre p.job) q.job r.job) $hear =+ kec=(bite q.job) ?> =(our q.p.kec) =+ buh=(~(get by pol) p.p.kec) ?~ buh ~& [%ames-from p.p.kec] =+ nut=(~(gut by ech) p.p.kec *mute) %_ +>.$ fex [[%veil p.p.kec] fex] ech (~(put by ech) p.p.kec nut(inn [+.job inn.nut])) == abet:(~(hear et p.p.kec u.buh) p.job (shaf %flap q.job) q.kec r.kec) :: $mess =+ buh=(~(get by pol) p.job) ?~ buh ~& [%ames-unto p.job] =+ nut=(~(gut by ech) p.job *mute) %_ +>.$ fex [[%veil p.job] fex] ech (~(put by ech) p.job nut(out [+>.job out.nut])) == =/ etc ~(. et p.job u.buh) =^ kos etc (blow:etc q.job) abet:(mess:etc kos r.job s.job) :: $rend abet:(mess:(etre p.job) q.job r.job s.job) :: $wake |- ^+ +>.^$ ?~ pol +>.^$ =+ lef=$(pol l.pol) =+ ryt=$(pol r.pol, fex fex.lef) =+ top=~(to-wake et(fex fex.ryt) n.pol) +>.^$(fex fex.top, pol [+<.top pol.lef pol.ryt]) == :: :: ++ dear :: neighbor update |= {who/@p det/pipe} ^+ +> =+ noz=(~(get by ech) who) ?~ noz :: :: we're not waiting for this ship; we must have it :: =+ bah=(~(got by pol) who) +>.$(pol (~(put by pol) who bah(det det))) :: :: new neighbor; run all waiting i/o :: =. pol (~(put by pol) who [det ~ [2 ~ ~] ~ ~]) =+ [inn out]=[(flop inn.u.noz) (flop out.u.noz)] =. +>.$ |- ^+ +>.^$ ?~ inn +>.^$ $(inn t.inn, +>.^$ (apex `task`[%hear i.inn])) |- ^+ +>.^$ ?~ out +>.^$ $(out t.out, +>.^$ (apex `task`[%mess who i.out])) :: ++ doze :: sleep until |- ^- (unit @da) ?~ pol ~ ;: (cury hunt lth) $(pol l.pol) $(pol r.pol) ~(to-wait et p.n.pol q.n.pol) == :: :: ++ etre :: old neighbor |= who/@p ~(. et who (~(got by pol) who)) :: :: ++ et :: per neighbor |_ $: who/ship bah/bath == ++ abet +>(pol (~(put by pol) who bah)) :: resolve ++ acme |=(fic/gift +>(fex [fic fex])) :: effect ++ blow :: register duct |= hen/duct ^- {bole _+>} =+ kus=(~(get by q.zam.bah) hen) ?^ kus [u.kus +>.$] :- p.zam.bah %= +>.$ p.zam.bah (add 2 p.zam.bah) q.zam.bah (~(put by q.zam.bah) hen p.zam.bah) r.zam.bah (~(put by r.zam.bah) p.zam.bah hen) == :: ++ done |= {kos/bole cop/coop} ^+ +> (in-task %done +<) :: :: ++ have :: receive message |= {kos/bole cha/chan val/*} ^+ +> ?: =(0 (end 0 1 kos)) =+ hen=(~(got by r.zam.bah) kos) :: :: if the bole is even, this is a backward flow, :: like a subscription update; ack automatically. :: (acme:(in-task %done kos ~) %east hen who cha val) :: :: if the bole is odd, it's a forward flow. we :: need to wait for the target to actively ack it. :: (acme %west who kos cha val) :: ++ hear :: |= {lyn/lane dam/flap syn/skin msg/@} :: hear packet ^+ +> (in-task %hear +<) :: :: ++ mess :: send message |= {kos/bole cha/chan val/*} ^+ +> (to-task kos %mess cha val) :: :: ++ sack :: send acknowledgment |= {kos/bole dam/flap cop/coop} =+ ^= yex ((knit who lyf wyr det.bah) now eny [%back (mix kos 1) dam cop ~s0]) =. +>.$ (to-gifs p.yex) |- ^+ +>.^$ ?~ q.yex +>.^$ $(q.yex t.q.yex, +>.^$ (send ~ i.q.yex)) :: :: ++ send :: send packet |= {urg/(unit lane) pac/rock} ^+ +> ?: =(our who) (acme [%send *lane pac]) =+ zaw=sax.det.bah |- ^+ +>.^$ ?~ zaw +>.^$ =+ ^= lun ^- (unit lane) ?: (lth i.zaw 256) :: :: galaxies are mapped into reserved IP space, :: which the interpreter maps into a DNS request. :: [~ %if ~2000.1.1 31.337 (mix i.zaw .0.0.1.0)] ?: =(who i.zaw) lun.bah =+ hab=(~(get by pol) i.zaw) ?~(hab ~ lun.u.hab) ?~ lun $(zaw t.zaw) =. pac ?: &(=(i.zaw who) =(~ urg)) pac :: :: forwarded packets are not signed/encrypted, :: because (a) we don't need to; (b) we don't :: want to turn one packet into two. the wrapped :: packet may exceed 8192 bits, but it's unlikely :: to blow the MTU (IP MTU == 1500). :: (spit [our i.zaw] %none (jam `meal`[%fore who urg pac])) =. +>.^$ (acme %send u.lun pac) :: :: stop if we have an %if (direct) address; :: continue if we only have %ix (forwarded). :: ?:(?=($if -.u.lun) +>.^$ $(zaw t.zaw)) :: ++ in-gift |= hox/gift:hose ^+ +> ?- -.hox $fore ?: =(our her.hox) (acme %home org.hox pac.hox) (send(who her.hox) [~ org.hox] pac.hox) :: $have (have +.hox) $link (acme %link who exp.hox key.hox) $meet (acme hox) $rack (to-task kos.hox %back dam.hox cop.hox ~s0) $rout +>(lun.bah `lyn.hox) $sack (sack +.hox) == :: ++ in-gifs |= hoz/(list gift:hose) ?~ hoz +> $(hoz t.hoz, +> (in-gift i.hoz)) :: ++ to-gift |= rax/gift:rail ?- -.rax $line (acme %line who ~2018.1.1 q.rax) $mack (acme %rest (~(got by r.zam.bah) p.rax) q.rax) $send (send ~ q.rax) == :: ++ to-gifs |= raz/(list gift:rail) ?~ raz +> $(raz t.raz, +> (to-gift i.raz)) :: ++ in-task |= kyz/task:hose ^+ +> =^ hoz fon.bah abet:(~(apex hose [who wyr det.bah] ~ fon.bah) kyz) (in-gifs hoz) :: ++ to-task |= {kos/bole kyz/task:rail} ^+ +> =+ cot=((bond |.(zeal:rail)) (~(get by sal.bah) kos)) =^ raz cot abet:(work:(to-rail kos cot) kyz) (to-gifs raz) :: ++ to-rail |= {kos/bole cot/colt} ~(. rail [[who lyf wyr det.bah] [now eny] kos (yawn:pump myn.cot) ~] cot) :: ++ to-wait |- ^- (unit @da) ?~ sal.bah ~ ;: (cury hunt lth) $(sal.bah l.sal.bah) $(sal.bah r.sal.bah) wait:(to-rail p.n.sal.bah q.n.sal.bah) == :: ++ to-wake |- ^+ +.$ ?~ sal.bah +.$ =+ lef=$(sal.bah l.sal.bah) =+ ryt=$(sal.bah r.sal.bah, fex fex.lef) =+ top=(work:(to-rail(fex fex.ryt) p.n.sal.bah q.n.sal.bah) %wake ~) +.$(fex fex.ryt, sal.bah [[kos cot]:top sal.bah.lef sal.bah.ryt]) -- -- :: :::: inbound cores :: :: :: :::: bite :::: packet format :: :: ++ bite :: packet to cake |= pac/rock ^- cake =+ [mag=(end 5 1 pac) bod=(rsh 5 1 pac)] =+ :* vez=(end 0 3 mag) :: protocol version chk=(cut 0 [3 20] mag) :: checksum wix=(bex +((cut 0 [23 2] mag))) :: width of receiver vix=(bex +((cut 0 [25 2] mag))) :: width of sender tay=(cut 0 [27 5] mag) :: message type == ?> =(7 vez) ?> =(chk (end 0 20 (mug bod))) :+ [(end 3 wix bod) (cut 3 [wix vix] bod)] (kins tay) (rsh 3 (add wix vix) bod) :: ++ kins |=(tay/@ (snag tay `(list skin)`[%none %open %fast %full ~])) ++ ksin |=(sin/skin `@`?-(sin $none 0, $open 1, $fast 2, $full 3)) :: ++ spit :: cake to packet |= kec/cake ^- @ =+ wim=(met 3 p.p.kec) =+ dum=(met 3 q.p.kec) =+ yax=?:((lte wim 2) 0 ?:((lte wim 4) 1 ?:((lte wim 8) 2 3))) =+ qax=?:((lte dum 2) 0 ?:((lte dum 4) 1 ?:((lte dum 8) 2 3))) =+ wix=(bex +(yax)) =+ vix=(bex +(qax)) =+ bod=:(mix p.p.kec (lsh 3 wix q.p.kec) (lsh 3 (add wix vix) r.kec)) =+ tay=(ksin q.kec) %+ mix %+ can 0 :~ [3 7] [20 (mug bod)] [2 yax] [2 qax] [5 tay] == (lsh 5 1 bod) :: :: :::: nose :::: packet decoder :: :: ++ nose !: => |% ++ gift :: side effect $% {$link exp/@da key/code} :: learn symmetric key {$meet doy/gree} :: learn public key(s) == :: -- |= $: him/@p wyr/(map life ring) det/pipe == |= {syn/skin msg/@} ^- (pair (list gift) {aut/? ham/meal}) |^ ?- syn $none [~ | (maul msg)] $fast =+ [mag=`hand`(end 7 1 msg) bod=(rsh 7 1 msg)] =+ key=q:(~(got by inn.det) mag) =+ clr=(need (de:crub:crypto key bod)) [~ & (maul clr)] :: $full =+ mex=;;({p/{p/life q/life} q/gree r/@} (cue msg)) =+ rig=(~(got by wyr) p.p.mex) =+ pas=(whom q.p.mex q.mex) =+ mes=(need (tear:as:(nol:nu:crub:crypto rig) pas r.mex)) =+ [key out]=;;((pair @ux @ux) (cue mes)) :- :~ [%link ~2018.1.1 key] [%meet q.mex] == [& (maul out)] :: $open =+ mex=;;({p/{$~ q/life} q/gree r/@} (cue msg)) =+ pas=(whom q.p.mex q.mex) =+ out=(need (sure:as:(com:nu:crub:crypto pas) r.mex)) [[%meet q.mex]~ & (maul r.mex)] == ++ maul |=(@ `meal`;;(meal (cue +<))) :: unpack message ++ whom :: select public key |= {lyf/life gyr/gree} ^- pass :: :: if we have the public key for this life, use it. :: otherwise, use the key the sender sent, without :: without checking its validity. invalid public-key :: data will crash the packet when we install it. :: %- (bond |.(pub.dat:(~(got by (~(got by gyr) lyf)) him))) (bind (~(get by pub.det) lyf) |=(cert:pki:jael pub.dat)) -- :: :: :::: hose :: :: :: ++ hose :: input decoder => |% :: ++ gift :: action $% {$fore her/ship org/lane pac/rock} :: send forward {$have kos/bole cha/chan val/*} :: report message {$link exp/@da key/code} :: learn symmetric key {$meet doy/gree} :: learn public key {$rack kos/bole dam/flap cop/coop} :: report ack {$rout lyn/lane} :: learn route {$sack kos/bole dam/flap cop/coop} :: send ack == :: ++ task :: event $% {$done kos/bole cop/coop} :: commit message {$hear lyn/lane dam/flap syn/skin msg/@} :: raw packet == :: -- :: =| $: $: him/ship :: wyr/(map life ring) :: det/pipe :: == :: fex/(list gift) :: fon/(map bole lock) :: == |% :: ++ abet [(flop fex) fon] :: resolve ++ acme |=(fic/gift +>(fex [fic fex])) :: effect ++ acts :: effects |=(fix/(list gift) +>(fex (weld (flop fix) fex))) :: :: :: ++ apex :: input |= job/task ^+ +> ?- -.job $done =+ loc=(~(got by fon) kos.job) ?> ?=(^ laz.loc) =< hy-abet (~(hy-done hy [kos.job p.u.laz.loc] [& [q r]:u.laz.loc] loc) cop.job) :: $hear =+ pet=((nose him wyr det) syn.job msg.job) =. +>.$ (acts p.pet) :: if packet is authenticated, use its routing info =. +>.$ ?.(aut.q.pet +>.$ (acme %rout lyn.job)) ?- -.ham.q.pet $back ~| %unsecured-back ?>(aut.q.pet (acme %rack [p q r]:ham.q.pet)) :: $bond =+ loc=((bond |.(*lock)) (~(get by fon) p.p.ham.q.pet)) =< hy-abet %. [q r]:ham.q.pet ~(hy-bond hy p.ham.q.pet [aut.q.pet [dam lyn]:job] loc) :: $carp =+ loc=((bond |.(*lock)) (~(get by fon) kos.p.ham.q.pet)) =< hy-abet %. [(kins syn.p.ham.q.pet) cnt.p.ham.q.pet q.ham.q.pet] ~(hy-carp hy [kos liq]:p.ham.q.pet [aut.q.pet [dam lyn]:job] loc) :: $fore (acme %fore p.ham.q.pet (born lyn.job q.ham.q.pet) r.ham.q.pet) == == :: :: ++ born :: set forward origin |= {lyn/lane urg/(unit lane)} ^- lane :: a forwarded packet contains its origin address, :: but only after the first hop. if the address :: field is empty, we fill it in with the address :: we received the packet from. but we replace :: %if with %ix, to show that the ultimate receiver :: may not be able to send back to the origin :: (due to non-full-cone NAT). ?~ urg lyn ?. ?=($if -.u.urg) u.urg [%ix +.u.urg] :: ++ hy :: message assembler =| $: $: kos/bole :: sender liq/tick :: message number == $: aut/? :: authenticated dam/flap :: critical flap lyn/lane :: origin address == lock == =* loq ->+ |% :: ++ hy-abet ..hy(fon (~(put by fon) kos loq)) :: resolve ++ hy-acme |=(fic/gift +>(+> (acme fic))) :: effect ++ hy-acts |=(fix/(list gift) +>(+> (acts fix))) :: effects ++ hy-bond :: full message |= {cha/chan val/*} ^+ +> ?: (lth liq laq) :: we already acked this msg; ack it again :: ~& [%hi-bond-low [kos liq] laq] hy-cong ?: (gth liq laq) :: later than the next msg; ignore ~& [%hy-bond-after [kos liq] laq] +> ?: !=(~ laz) :: this msg is already being processed; ignore ~& [%hy-bond-during [kos liq] laq] +> :: report completed message %. [%have kos cha val] %= hy-acme :: delete partial message nys (~(del by nys) liq) :: record message in application processing laz `[liq dam lyn] == :: :: ++ hy-done :: message completed |= cop/coop ^+ +> (hy-cone(laq +(laq), laz ~) cop) :: :: ++ hy-carp :: process fragment |= {syn/skin cnt/@ud far/(pair @ud @)} ^+ +> :: ~& [%carp fap/`@p`(mug fap) syn/syn cnt/cnt far/p.far] ?: (lth liq laq) :: fragment of a message we've already acknowledged - ack it again. :: ~& [%hy-carp-late liq laq] hy-cong ?: (gth liq laq) :: fragment of a message after the next we expect - drop it. :: ~& [%hy-carp-early liq laq] +> :: neb: current incomplete message =+ neb=`bait`(~(gut by nys) liq [syn 0 [cnt ~]]) :: all fragments must agree on the message parameters ?> &(=(p.neb syn) (gth p.r.neb p.far) =(p.r.neb cnt)) =+ doy=(~(get by q.r.neb) p.far) ?^ doy :: we've already heard this fragment (hy-conk ~) :: install fragment =: q.r.neb (~(put by q.r.neb) p.far q.far) q.neb +(q.neb) == ?. =(q.neb p.r.neb) :: message not yet complete, reinstall incomplete (hy-conk(nys (~(put by nys) liq neb)) ~) :: decode complete message =+ pet=((nose him wyr det) syn (hy-golf r.neb)) :: record decoder effects =. +>.$ (hy-acts p.pet) =. aut |(aut aut.q.pet) ?- -.ham.q.pet $back ~|(%unsecured-back ?>(aut (hy-acme %rack kos [q r]:ham.q.pet))) $carp ~|(%meta-carp !!) $fore (hy-acme %fore p.ham.q.pet (born lyn q.ham.q.pet) r.ham.q.pet) $bond ~| %bogus-assembly ?> &(aut =([kos liq] p.ham.q.pet)) (hy-bond [q r]:ham.q.pet) == :: ++ hy-cong (hy-conk (~(get by exc) liq)) :: duplicate ack ++ hy-conk :: ack current |=(cop/coop (hy-acme %sack kos dam cop)) ++ hy-cone :: record ack |= cop/coop => ?~(cop . .(exc (~(put by exc) liq u.cop))) (hy-conk cop) :: :: ++ hy-golf :: assemble fragments |= duv/dove =+ [nix=0 rax=*(list @)] |- ^- @ ?: =(p.duv nix) (can 13 (turn (flop rax) |=(a/@ [1 a]))) $(nix +(nix), rax [(need (~(get by q.duv) nix)) rax]) -- -- :: :: :::: outbound cores :::: :: :: :: :::: packet pump :: ++ pump :: packet pump => |% :: ++ gift :: effect $% {$good p/flap q/part r/@dr s/coop} :: logical ack {$send p/flap q/part r/rock} :: release packet == :: ++ task :: event $% {$back p/flap q/coop r/@dr} :: raw ack {$cull p/tick} :: cancel message {$pack p/(list clue)} :: submit packets {$wake $~} :: random wakeup == :: -- |% ++ yawn :: |= myn/mini :: ^+ zu ~(. zu ~ myn) :: :: ++ zu :: state machine |_ $: fex/(list gift) :: effects mini :: state == :: :: ++ abba :: a older than b |= {a/part b/part} |((lth q.a q.b) &(=(q.a q.b) (lth p.a p.b))) :: :: ++ abet :: resolve ^- {(list gift:pump) mini} :: =. . aver [(flop fex) +<+] :: :: ++ aver :: verify ?> (lte cur.saw max.saw) ?> !=(0 max.saw) ?. =(cur.saw (lent ~(tap to liv))) ~& [%aver-cur cur.saw (lent ~(tap to liv))] !! ?> =(rey.saw (lent ~(tap to lop))) ?> =+ |= {a/coal b/coal} &((lth out.a out.b) (lth lod.a lod.b)) |- ?| ?=($~ liv) ?& ?| ?=($~ r.liv) ?& (+< n.r.liv n.liv) $(liv r.liv) == == ?| ?=($~ l.liv) ?& (+< n.liv n.l.liv) $(liv l.liv) == == == == ?> =+ |= {a/part b/part} |((lth q.a q.b) &(=(q.a q.b) (lth p.a p.b))) |- ?| ?=($~ lop) ?& ?| ?=($~ r.lop) ?& (+< tel.n.r.lop tel.n.lop) $(lop r.lop) == == ?| ?=($~ l.lop) ?& (+< tel.n.lop tel.n.l.lop) $(lop l.lop) == == == == . :: :: ++ back :: process raw ack |= {now/@da dam/flap cop/coop lag/@dr} ^+ +> =- =/ rtt ?~(ack ~s0 (sub now out.u.ack)) =. rtt ?:((gth rtt lag) (sub rtt lag) rtt) (done:(lose(liv lov) ded) ack dam cop rtt) |- ^- $: ack/(unit coal) ded/(list coal) lov/(qeu coal) == ?~ liv [~ ~ ~] =+ ryt=$(liv r.liv) ?^ ack.ryt :: :: found in front, no need to search back. :: [ack.ryt ded.ryt [n.liv l.liv lov.ryt]] :: :: lose unacked packets sent before an acked virgin. :: =+ ^- $: top/? ack/(unit coal) ded/(list coal) lov/(qeu coal) == ?: =(dam fap.clu.n.liv) [| `n.liv ~ l.liv] [& $(liv l.liv)] ?~ ack [~ ~ liv] =. ded ?:(top [n.liv ded] ded) =? ded vig.clu.u.ack (weld ~(tap to r.liv) ded) =. lov ?:(top [n.liv lov ~] lov) [ack ded lov] :: :: ++ clap :: ordered enqueue :: :: the `lop` queue isn't really a queue in case of :: resent packets; packets from older messages :: need to be sent first. unfortunately hoon.hoon :: lacks a general sorted/balanced heap right now. :: so we implement a balanced queue insert by hand. :: |= clu/clue %_ +> lop |- ^+ lop ?~ lop [clu ~ ~] ?: ?| (abba tel.clu tel.n.lop) ?& =(tel.clu tel.n.lop) (lth fap.clu fap.n.lop) == == [n.lop l.lop $(lop r.lop)] [n.lop $(lop l.lop) r.lop] == :: :: ++ cull :: clear message |= tiq/tick %_ +> liv |- ^+ liv ?~ liv ~ =+ vil=[n.liv $(liv l.liv) $(liv r.liv)] ?. =(tiq q.tel.clu.n.liv) vil ~(nip to `(qeu coal)`vil) :: lop |- ^+ lop ?~ lop ~ =+ pol=[n.lop $(lop l.lop) $(lop r.lop)] ?: =(tiq q.tel.n.lop) pol ~(nip to `(qeu clue)`pol) == :: :: ++ done :: process cooked ack |= {lyd/(unit coal) dam/flap cop/coop rtt/@dr} ^+ +> ?~ lyd +> %_ +> cur.saw (dec cur.saw) fex [[%good dam tel.clu.u.lyd rtt cop] fex] == :: :: ++ fire :: send a packet |= {now/@da clu/clue} ^+ +> ?> (lth cur.saw max.saw) =+ out=?:((lte now las.saw) +(las.saw) now) =+ lod=(add now (mul 2 rtt.saw)) =. lod ?:((gth lod lad.saw) lod +(lad.saw)) :: ~& [%fire (flam fap.clu) `@da`out `@da`lod] %= +>.$ fex [[%send fap.clu tel.clu dat.clu] fex] las.saw out lad.saw lod cur.saw +(cur.saw) liv (~(put to liv) [out lod clu]) == :: :: ++ flay :: time out packets |= now/@da ^+ +> =- (lose(liv q.ole) p.ole) ^= ole =| ded/(list coal) |- ^+ [p=ded q=liv] ?~ liv [ded ~] ?: (gte now lod.n.liv) :: :: everything in front of a dead packet is dead :: $(liv l.liv, ded (welp ~(tap to r.liv) [n.liv ded])) =+ ryt=$(liv r.liv) [p.ryt [n.liv l.liv q.ryt]] :: :: ++ lose :: abandon packets |= cud/(list coal) ^+ +> ?~ cud +> =. +> (clap clu.i.cud) %= $ cud t.cud cur.saw (dec cur.saw) rey.saw +(rey.saw) == :: :: ++ ship :: send packets |= {now/@da cly/(list clue)} ^+ +> ?: (gte cur.saw max.saw) +> ?: =(0 rey.saw) ?~ cly +> $(cly t.cly, +> (fire now i.cly)) =^ clu lop ~(get to lop) $(+> (fire(rey.saw (dec rey.saw)) now clu)) :: :: ++ wait :: next wakeup ^- (unit @da) =+ tup=`(unit coal)`~(top to liv) ?~(tup ~ `lod.u.tup) :: :: ++ want :: window space ^- @ud ?: (gte cur.saw max.saw) 0 =+ gap=(sub max.saw cur.saw) ?: (gte rey.saw gap) 0 (sub gap rey.saw) :: ++ work :: |= {now/@da job/task} :: perform ^+ +> ?- -.job $back (back now [p q r]:job) $cull (cull p.job) $pack (ship now p.job) $wake (flay now) == -- -- :: :: :::: knit :::: message encoder :: :: ++ knit => |% ++ gift :: side effect $% {$line exp/@da key/code} :: set symmetric key == :: -- |= {her/@p lyf/life wyr/(map life ring) det/pipe} |= {now/@da eny/@ ham/meal} =+ hom=(jam ham) ^- (pair (list gift) (list rock)) =< weft |% ++ wain :: message identity ^- flea ?+ -.ham [0 0] $bond p.ham $carp [kos liq]:p.ham == :: ++ wasp ^-({p/skin q/@} [%none hom]) :: null security ++ weft :: fragment message ^- (pair (list gift) (list rock)) =+ gum=wisp :- p.gum =+ wit=(met 13 q.q.gum) ?: =(1 wit) :: message fits in one packet, don't fragment [(spit [our her] p.q.gum q.q.gum) ~] =+ ruv=(rip 13 q.q.gum) =+ inx=0 |- ^- (list rock) ?~ ruv ~ :_ $(ruv t.ruv, inx +(inx)) %+ spit [our her] wasp(ham [%carp [wain (ksin p.q.gum) wit] inx i.ruv]) :: ++ wisp :: generate message ^- (pair (list gift) (pair skin @)) ?: =(%carp -.ham) [~ wasp] ?^ out.det :- ~ :- %fast %^ cat 7 p.u.out.det (en:crub:crypto q.q.u.out.det hom) =+ cry=(nol:nu:crub:crypto (~(got by wyr) lyf)) ?~ cur.det :- ~ :- %open %^ jam [~ lyf] `gree`!! (sign:as:cry hom) =+ key=(shaz :(mix (mug ham) now eny)) :- [%line ~2018.1.1 key]~ :- %full %^ jam [u.cur.det lyf] `gree`!! (seal:as:cry pub.dat:(~(got by pub.det) u.cur.det) (jam key hom)) -- :: :: :::: rail :::: message manager :: :: ++ rail :: => |% :: ++ gift :: $% {$line p/@da q/code} :: sent key {$mack p/bole q/coop} :: message ack {$send p/flap q/rock} :: release packet == :: ++ task :: $% {$back p/flap q/coop r/@dr} :: raw ack {$mess p/chan q/*} :: send message {$wake $~} :: random wakeup == :: -- :: =| $: $: $: her/ship lyf/life wyr/(map life ring) det/pipe == $: now/@da eny/@ == kos/bole mup/_(yawn:pump) fex/(list gift) == colt == =* cot -> |% :: ++ abet [(flop fex) `colt`cot] :: resolve ++ view :: inspect |% :: ++ bulk :: queue count ^- @ud |-(?~(cob 0 :(add 1 $(cob l.cob) $(cob r.cob)))) :: :: ++ wait :: next wakeup ^- (unit @da) wait:mup -- :: ++ work :: |= job/task :: compute ^+ +> =< +>:wy-abet:wy-work |% :: ++ wy-abet +:wy-able :: resolve ++ wy-able wy-tire:wy-ably:wy-feed:wy-ably :: converge ++ wy-ably :: drain ^+ . =^ fix myn abet:mup =. mup (yawn:pump myn) |- ^+ +>.$ ?~ fix +>.$ $(fix t.fix, +>.$ (wy-abut i.fix)) :: :: ++ wy-abut :: pump effect |= fic/gift:pump ^+ +> ?- -.fic $good ~& [%ok her `@p`(mug p.fic) r.fic] (wy-good q.fic s.fic) :: $send ~& [%go her `@p`(mug p.fic) q.fic] +>(fex [[%send p.fic r.fic] fex]) == :: :: ++ wy-back :: hear an ack |= {dam/flap cop/coop lag/@dr} ~& [%wy-back (flam dam) cop lag] +>(mup (work:mup now %back dam cop lag)) :: :: ++ wy-feed :: feed pump ^+ . =^ cly . (wy-find want.mup) ~& [%wy-feed want.mup (lent cly)] +(mup (work:mup now %pack cly)) :: :: ++ wy-find :: collect packets |= may/@ud ^- {(list clue) _+>} =- [(flop -<) ->] =+ [inx=lac hav=*(list clue)] |- ^- {(list clue) _+>.^$} ?: |(=(0 may) =(inx seq)) [hav +>.^$] =^ hey +>.^$ (wy-flow inx may hav) $(inx +(inx), may p.hey, hav q.hey) :: :: ++ wy-flow :: collect by message |= {tiq/tick may/@ud hav/(list clue)} =+ mob=(~(got by cob) tiq) |- ^- {(pair @ud (list clue)) _+>.^$} ?: |(=(0 may) ?=($~ cly.mob)) [[may hav] +>.^$(cob (~(put by cob) tiq mob))] %= $ may (dec may) hav [i.cly.mob hav] cly.mob t.cly.mob == :: :: ++ wy-good :: message ack |= {paz/part cop/coop} ^+ +> =+ bum=(~(get by cob) q.paz) ?: |(?=($~ bum) =(~ cly.u.bum)) ~& [%wy-good-ignore paz ?=($~ cop)] +>.$ ?^ cop :: :: a failure; save this nack, clear the message :: ~& [%wy-good-fail q.paz] %_ +>.$ mup (work:mup now %cull q.paz) cob (~(put by cob) q.paz u.bum(cly ~, cup `cop)) == ?> (lth ack.u.bum num.u.bum) =. ack.u.bum +(ack.u.bum) =. cup.u.bum ?.(=(ack.u.bum num.u.bum) ~ [~ ~]) +>.$(cob (~(put by cob) q.paz u.bum)) :: :: ++ wy-mess :: send |= {cha/chan val/*} ^+ +> =+ yex=((knit her lyf wyr det) now eny [%bond [(mix kos 1) seq] cha val]) =. fex (weld (flop p.yex) fex) ~& [?:(=(0 (end 0 1 kos)) %tx %bx) her kos seq cha (lent fex)] %_ +>.$ seq +(seq) cob %+ ~(put by cob) seq ^- comb :* ~ cha (lent q.yex) 0 =+ inx=0 |- ?~ q.yex ~ :_ $(q.yex +.q.yex, inx +(inx)) [& [inx seq] (shaf %flap i.q.yex) i.q.yex] == == :: :: ++ wy-tire :: report results |- ^+ + =+ zup=(~(get by cob) lac) ?~ zup +.$ ?~ cup.u.zup +.$ ~& [?:(=(0 (end 0 1 kos)) %ta %ba) her kos lac] %= $ lac +(lac) cob (~(del by cob) lac) fex :_(fex [%mack kos `coop`u.cup.u.zup]) == :: :: ++ wy-wake :: timeout ^+ . .(mup (work:mup now %wake ~)) :: ++ wy-work ^+ . ?- -.job $back (wy-back +.job) $mess (wy-mess +.job) $wake wy-wake == -- :: :: ++ zeal :: default state ^- colt :* 0 :: seq/tick 0 :: lac/tick ~ :: cob/(map tick comb) ^- mini :* ^- stat :* :* 0 :: cur/@ud 2 :: max/@ud 0 :: rey/@ud == :* ~s5 :: rtt/@dr ~2010.1.1 :: las/@da ~2010.1.1 :: lad/@da == == ~ ~ == == -- -- . == :: :: :::: :::: kernel interface :: :: =| $: syl/silo :: kernel state == :: |= {now/@da eny/@ ski/sley} :: current invocation => |% ++ love ~(. loft [now eny] syl ~) :: create loft ++ lung :: gift to move |= gax/gift:loft ^- move ?- -.gax $east [p.gax %give [%east s.gax]] $home [~ %give gax] $link [~ %pass ~ %j gax] $line [~ %pass ~ %j gax] $meet [~ %pass ~ %j gax] $rest [p.gax %give %rest q.gax] $send [~ %give gax] $veil [~ %pass /det/(scot %p p.gax) %j gax] $west =+ pax=/msg/(scot %p p.gax)/(scot %ud q.gax) =+ cad=[%west p.gax +.r.gax s.gax] =+ dat=?+(-.r.gax !! $c [%c cad], $e [%e cad], $g [%g cad]) [~ %pass pax dat] == :: ++ work |= job/task:loft ^- {(list move) q/_..^$} =^ fex syl abet:(apex:love job) [(turn fex lung) ..^$] -- |% :: vane interface ++ neon |= our/ship ^- (vane task:able gift:able sign:able note:able silo silo) =| syl/silo |% ++ load |=(silo +>) ++ stay syl ++ plow =| $: now/@da eny/@e sky/roof == |% ++ doze ~ ++ peek |= $: lyc/(unit (set ship)) car/term bem/beam == ^- (unit (unit (cask vase))) ~ :: ++ spin =| $: hen/duct moz/(list move) == |% ++ call |= tac/task:able ^+ +> =* job ^- task:loft ?- -.tac $hear tac $mess [%mess p.tac hen q.tac r.tac] $wake tac == =^ fex syl abet:(apex:love job) +>.$(moz (weld (turn fex lung) moz)) :: ++ take |= {tea/wire hin/sign:able} =* job ^- task:loft ?+ -.tea !! $msg ?> ?=({@ @ $~} +.tea) =+ [who kos]=[(slav %p i.t.tea) (slav %ud i.t.t.tea)] ?- +<.hin $rend [%rend who kos p.+.hin q.+.hin] $mack [%done who kos ?~(p.+.hin ~ `coop`[~ `[%fail u.p.+.hin]])] == == =^ fex syl abet:(apex:love job) +>.$(moz (weld (turn fex lung) moz)) -- -- -- ++ call :: handle request |= $: hen/duct hic/(hypo task:able:xmas) == ^- {p/(list move) q/_..^$} %- work ^- task:loft ?- -.q.hic $hear q.hic $mess [%mess p.q.hic hen q.q.hic r.q.hic] $wake q.hic == :: ++ doze |= {now/@da hen/duct} ^- (unit @da) doze:love :: ++ load |= old/silo ^+ ..^$ ..^$(syl old) :: ++ scry |= {fur/(unit (set monk)) ren/@tas why/shop syd/desk lot/coin tyl/path} ^- (unit (unit cage)) ~ :: ++ stay syl ++ take :: accept response |= {tea/wire hen/duct hin/(hypo sign-arvo)} ^- {p/(list move) q/_..^$} %- work ?+ -.tea !! $msg ?> ?=({@ @ $~} +.tea) =+ [who kos]=[(slav %p i.t.tea) (slav %ud i.t.t.tea)] ?> ?=(?($rend $mack) +<.q.hin) ?- +<.q.hin $rend [%rend who kos p.+.q.hin q.+.q.hin] $mack [%done who kos ?~(p.+.q.hin ~ `coop`[~ `[%fail u.p.+.q.hin]])] == :: $det ?> ?=({@ $~} +.tea) =+ who=(slav %p i.t.tea) ?> ?=($veil +<.q.hin) [%clue who p.+.q.hin] == --