diff --git a/pkg/arvo/sys/lull.hoon b/pkg/arvo/sys/lull.hoon index 8010e8017..eb4d1b41b 100644 --- a/pkg/arvo/sys/lull.hoon +++ b/pkg/arvo/sys/lull.hoon @@ -1196,7 +1196,7 @@ :: +$ hoot @uxhoot :: request packet +$ purr @uxpurr :: response packet - +$ song (list purr) :: full response + +$ hunk [lop=@ len=@] :: range specifier :: :: +| %kinetics :: $dyad: pair of sender and receiver ships @@ -1211,8 +1211,13 @@ :: address. Routes are opaque to Arvo and only have meaning in the :: interpreter. This enforces that Ames is transport-agnostic. :: + :: req: is a request + :: sam: is using the ames protocol (not fine or another protocol) + :: +$ packet $: dyad + req=? + sam=? sndr-tick=@ubC rcvr-tick=@ubC origin=(unit @uxaddress) @@ -1306,9 +1311,9 @@ == +$ have $: fra=@ud - rawr + meow == - +$ rawr :: response packet ::TODO meow + +$ meow :: response packet $: sig=@ siz=@ud byts @@ -1542,16 +1547,16 @@ :: ++ decode-packet |= =blob - ^- [ames=? =packet] + ^- packet ~| %decode-packet-fail :: first 32 (2^5) bits are header; the rest is body :: =/ header (end 5 blob) =/ body (rsh 5 blob) - :: read header; first three bits are reserved + :: read header; first two bits are reserved :: - =/ is-ames (cut 0 [3 1] header) - :- =(& is-ames) + =/ req =(& (cut 0 [2 1] header)) + =/ sam =(& (cut 0 [3 1] header)) :: =/ version (cut 0 [4 3] header) ?. =(protocol-version version) @@ -1597,7 +1602,7 @@ :: read variable-length .content from the rest of .body :: =/ content (cut 3 [off (sub (met 3 body) off)] body) - [[sndr rcvr] sndr-tick rcvr-tick origin content] + [[sndr rcvr] req sam sndr-tick rcvr-tick origin content] :: ++ decode-request |= =hoot @@ -1617,7 +1622,7 @@ :: +encode-packet: serialize a packet into a bytestream :: ++ encode-packet - |= [ames=? packet] + |= packet ^- blob :: =/ sndr-meta (encode-ship-metadata sndr) @@ -1636,8 +1641,9 @@ :: =/ header=@ %+ can 0 - :~ [3 reserved=0] - [1 is-ames=ames] + :~ [2 reserved=0] + [1 req] + [1 sam] [3 protocol-version] [2 rank.sndr-meta] [2 rank.rcvr-meta] diff --git a/pkg/arvo/sys/vane/ames.hoon b/pkg/arvo/sys/vane/ames.hoon index 6c386b290..4131f1e39 100644 --- a/pkg/arvo/sys/vane/ames.hoon +++ b/pkg/arvo/sys/vane/ames.hoon @@ -269,9 +269,9 @@ :: ++ decode-response-packet |= =purr - =; =rawr - ~? !=(wid.rawr (met 3 dat.rawr)) [%fine %unexpected-dat-size] - rawr + =; =meow + ~? !=(wid.meow (met 3 dat.meow)) [%fine %unexpected-dat-size] + meow :* sig=(cut 3 [0 64] purr) siz=(cut 3 [64 4] purr) wid=(cut 3 [68 2] purr) @@ -308,6 +308,7 @@ |= [pac=open-packet =acru:ames] ^- packet :* [sndr rcvr]:pac + req=& sam=& (mod sndr-life.pac 16) (mod rcvr-life.pac 16) origin=~ @@ -367,8 +368,15 @@ =/ vec ~[sndr rcvr sndr-life rcvr-life] =/ [siv=@uxH len=@ cyf=@ux] (~(en sivc:aes:crypto (shaz symmetric-key) vec) (jam shut-packet)) - =/ content :(mix siv (lsh 7 len) (lsh [3 18] cyf)) - [[sndr rcvr] (mod sndr-life 16) (mod rcvr-life 16) origin=~ content] + :: + :* ^= dyad [sndr rcvr] + ^= req ?=(%& -.meat.shut-packet) + ^= sam & + ^= sndr-tick (mod sndr-life 16) + ^= sndr-tick (mod rcvr-life 16) + ^= origin ~ + ^= content :(mix siv (lsh 7 len) (lsh [3 18] cyf)) + == :: +decode-shut-packet: decrypt a $shut-packet from a $packet :: ++ decode-shut-packet @@ -1113,6 +1121,7 @@ :: /ax/fine/message/[path/...] song :: ?. ?=(%x ren) ~ + => .(tyl `(pole knot)`tyl) ?+ tyl ~ [%protocol %version ~] ``noun+!>(protocol-version) @@ -1122,11 +1131,11 @@ !> ^- (map ship ?(%alien %known)) (~(run by peers.ames-state) head) :: - [%peers @ *] - =/ who (slaw %p i.t.tyl) + [%peers her=@ req=*] + =/ who (slaw %p her.tyl) ?~ who [~ ~] =/ peer (~(get by peers.ames-state) u.who) - ?+ t.t.tyl [~ ~] + ?+ req.tyl [~ ~] ~ ?~ peer [~ ~] @@ -1164,8 +1173,8 @@ $(peer next) == :: - [%bones @ ~] - =/ who (slaw %p i.t.tyl) + [%bones her=@ ~] + =/ who (slaw %p her.tyl) ?~ who [~ ~] =/ per (~(get by peers.ames-state) u.who) ?. ?=([~ %known *] per) [~ ~] @@ -1174,10 +1183,10 @@ [snd=~(key by snd) rcv=~(key by rcv)] ``noun+!>(res) :: - [%snd-bones @ @ ~] - =/ who (slaw %p i.t.tyl) + [%snd-bones her=@ bon=@ ~] + =/ who (slaw %p her.tyl) ?~ who [~ ~] - =/ ost (slaw %ud i.t.t.tyl) + =/ ost (slaw %ud bon.tyl) ?~ ost [~ ~] =/ per (~(get by peers.ames-state) u.who) ?. ?=([~ %known *] per) [~ ~] @@ -1187,14 +1196,12 @@ u.mps ``noun+!>(!>(res)) :: - [%fine %message @ *] + [%fine %hunk lop=@t len=@t pax=^] ::TODO separate endpoint for the full message (instead of packet list) - :: t.t.tyl is expected to be a scry path of the shape /vc/desk/rev/etc, + :: .pax is expected to be a scry path of the shape /vc/desk/rev/etc, :: so we need to give it the right shape :: - =* path t.t.tyl - ~| path - ?~ blk=(de-path-soft:balk path) ~ + ?~ blk=(de-path-soft:balk pax.tyl) ~ =+ nom=(en-roof:balk u.blk) ~| nom :: we only support scrying into clay, @@ -1208,12 +1215,13 @@ =+ per=!<([r=dict:clay w=dict:clay] q.u.u.pem) ?. =([%black ~ ~] rul.r.per) ~ =+ res=(rof lyc nom) + =/ =hunk [(slav %ud lop.tyl) (slav %ud len.tyl)] ::TODO suggests we need to factor differently - =+ ven=(per-event [now 0v0 rof] *duct ames-state) + =/ fin fine:(per-event [now 0v0 rof] *duct ames-state) ?- res ~ ~ - [~ ~] ``noun+!>((encode-response:fine:ven path ~)) - [~ ~ *] ``noun+!>((encode-response:fine:ven path [p q.q]:u.u.res)) + [~ ~] ``noun+!>((encode-hunk:fin pax.tyl hunk ~)) + [~ ~ *] ``noun+!>((encode-hunk:fin pax.tyl hunk [p q.q]:u.u.res)) == == -- @@ -1436,11 +1444,10 @@ ++ on-hear |= [l=lane b=blob d=(unit goof)] ^+ event-core - =/ [ames=? =packet] - (decode-packet b) - ?: ames + =/ =packet (decode-packet b) + ?: sam.packet (on-hear-packet l packet d) - ?. response==(& (cut 0 [2 1] b)) + ?: req.packet ~|([%fine %request-events-forbidden] !!) (on-hear-response:fine l packet d) :: +on-hear-packet: handle mildly processed packet receipt @@ -1485,7 +1492,7 @@ ~| ames-lane-size+p.lane !! `p.lane :: - =/ =blob (encode-packet & packet) + =/ =blob (encode-packet packet) (send-blob & rcvr.packet blob) :: +on-hear-open: handle receipt of plaintext comet self-attestation :: @@ -2105,7 +2112,7 @@ ++ attestation-packet |= [her=ship =her=life] ^- blob - %+ encode-packet & + %- encode-packet %- encode-open-packet :_ crypto-core.ames-state :* ^= public-key pub:ex:crypto-core.ames-state @@ -2394,7 +2401,7 @@ :: =. event-core %^ send-blob | her.channel - %+ encode-packet & + %- encode-packet %: encode-shut-packet shut-packet(bone (mix 1 bone.shut-packet)) symmetric-key.channel @@ -2643,12 +2650,9 @@ |= [=path =^duct] ?: (~(has by order.scry) path) ke-abet:(ke-sub:(ke-abed:keen-core path) duct) - =/ keen-id=@ud seq.scry - =. seq.scry +(seq.scry) - =. order.scry - (~(put by order.scry) path keen-id) - =| =keen-state - =. keens.scry (put:orm keens.scry keen-id keen-state) + =^ keen-id=@ud seq.scry [seq.scry +(seq.scry)] + =. order.scry (~(put by order.scry) path keen-id) + =. keens.scry (put:orm keens.scry keen-id *keen-state) ke-abet:(ke-start:(ke-abed:keen-core path) duct) :: ++ pe-pine @@ -2848,18 +2852,18 @@ $(listeners t.listeners) :: ++ ke-first-rcv - |= =rawr + |= =meow ^+ ke-core =- ke-core(keen -) :: =/ paz=(list want) - %+ turn (gulf 1 siz.rawr) + %+ turn (gulf 1 siz.meow) |= fra=@ud ^- want [fra (ke-encode-req fra) now 0 0] :: %_ keen - num-fragments siz.rawr + num-fragments siz.meow nex (tail paz) == :: +ke-continue: send packets according to normal congestion flow @@ -2915,28 +2919,28 @@ ++ ke-rcv |= [fra=@ud =purr =lane:ames] ^+ ke-core - =/ =rawr (decode-response-packet purr) + =/ =meow (decode-response-packet purr) =/ og ke-core =. pe-core (pe-update-qos %live last-contact=now) :: handle empty - ?: =(0 siz.rawr) - ?> =(~ dat.rawr) - (ke-done sig.rawr ~) + ?: =(0 siz.meow) + ?> =(~ dat.meow) + (ke-done sig.meow ~) :: update congestion, or fill details :: =? ke-core =(0 num-fragments.keen) ?> =(fra 1) - (ke-first-rcv rawr) + (ke-first-rcv meow) :: - ~| failed-signature/fra^`@ux`sig.rawr + ~| failed-signature/fra^`@ux`sig.meow ~| life.peer - ?> (veri-fra:keys ship life.peer ke-full-path fra [dat sig]:rawr) + ?> (veri-fra:keys ship life.peer ke-full-path fra [dat sig]:meow) =^ found=? ke-core (ke-on-ack fra) :: ?. found (ke-fast-retransmit:og fra) - =/ =have [fra rawr] + =/ =have [fra meow] =. hav.keen `(list ^have)`[have hav.keen] =. num-received.keen +(num-received.keen) @@ -3067,9 +3071,11 @@ =+ !<(=cass:clay q.u.u.cag) (emit duct %give %boon `*`ud.cass) == + :: ++ on-keen |= [=ship =path] ^+ event-core + =+ ~:(spit path) :: assert length =/ peer-core (pe-abed:fine-peer ship) ?^ peer-core pe-abet:(pe-keen:u.peer-core path duct) %+ enqueue-alien-todo ship @@ -3127,7 +3133,7 @@ num=@ud == :: - +$ rawr :: response packet ::TODO meow + +$ meow :: response packet $: sig=@ siz=@ud byts @@ -3138,81 +3144,74 @@ dat=$@(~ (cask)) == ++ orm ((on @ud keen-state) lte) + :: +gum: glue together a list of $byts into one + :: + :: TODO: move to hoon.hoon + :: + ++ gum + ~/ %gum + |= biz=(list byts) + ^- byts + :- (roll biz |=([[wid=@ *] acc=@] (add wid acc))) + (can 3 biz) :: ++ spit |= =path ^- [pat=@t wid=@ud] =+ pat=(spat path) =+ wid=(met 3 pat) - ?> (lte wid 384) ::TODO check when we handle %keen, in addition to here + ?> (lte wid 384) [pat wid] :: ++ request-body |= [=path num=@ud] - ::NOTE path is expected to be a namespace path without the ship ^- byts ?> (lth num (bex 32)) =+ (spit path) - :- :(add 4 2 wid) - %+ can 3 + %- gum :~ 4^num :: fragment number 2^wid :: path size wid^`@`pat :: namespace path == :: + ++ frag-body + |= [=path mes=@ num=@ud] + ^- @uxmeow + =/ tot (met 13 mes) + =/ fra (cut 13 [(dec num) 1] mes) + =/ wid (met 3 fra) + %+ can 3 + :~ 64^(sign-fra:keys path num fra) + 4^tot :: number of fragments + 2^wid :: response data fragment size in bytes + wid^fra :: response data fragment + == + :: ++ encode-request |= [=ship =path num=@ud] - ::NOTE path is expected to be a namespace path without the ship ^- hoot ^- @ - =+ bod=(request-body path num) - =+ sig=64^(sign:keys dat.bod) - =+ syn=(can 3 sig bod ~) - %+ con 0b100 ::NOTE request bit - %^ encode-packet | - [our ship] - [(mod life.ames-state 16) (mod (lyfe:keys ship) 16) ~ syn] + =/ sic (mod life.ames-state 16) + =/ ric (mod (lyfe:keys ship) 16) + =/ syn + =/ bod (request-body path num) + =/ sig 64^(sign:keys dat.bod) + (can 3 sig bod ~) + (encode-packet [our ship] req=& sam=| sic ric ~ syn) :: - ++ encode-response ::TODO unit tests - |= [=path data=$@(~ (cask))] - ^- song - :: prepend request descriptions to each response packet - :: - =; pacs=(list @ux) - %- head - %^ spin pacs 1 - |= [pac=@ux num=@ud] - ^- [purr _num] - :_ +(num) - ^- @ux - ::NOTE we stub out the receiver & origin details, - :: runtime should replace them as appropriate. - (encode-packet | [our ~zod] (mod life.ames-state 16) 0b0 ~ pac) - :: prepend a signature and split the data into 1024-byte fragments - :: - =/ frag=(list @) + ++ encode-hunk ::TODO unit tests + |= [=path =hunk data=$@(~ (cask))] + ^- (list @uxmeow) + =/ mes=@ =/ sig=@ (full:keys path data) - ?~ data [sig]~ - %+ rip response-size ::NOTE 1024 bytes - (cat 9 sig (jam data)) ::TODO should include life - :: sign & packetize the fragments + ?~ data sig + (cat 9 sig (jam data)) :: - %- head - %^ spin frag 1 - |= [dat=@ num=@ud] - :_ +(num) - ^- @ux - =/ req=byts (request-body path num) - =/ bod=byts - =/ wid=@ud (met 3 dat) - :- :(add 4 2 wid) - %+ can 3 - :~ 4^(lent frag) :: number of fragments - 2^wid :: response data fragment size in bytes - wid^dat :: response data fragment - == - =/ sig=byts - 64^(sign-fra:keys path num dat) - (can 3 req sig bod ~) + =/ top +((min (met 13 mes) (add [lop len]:hunk))) + =/ num lop.hunk + =| res=(list @uxmeow) + |- ^+ res + ?: =(num top) (flop res) + $(num +(num), res :_(res (frag-body path mes num))) :: ++ keys |% @@ -3270,11 +3269,17 @@ (got-peer-state ship) ?^ route.peer-state lane.u.route.peer-state - :- %& - %- rear - !< (list ^ship) - =< q %- need %- need - (rof `(sy our ~) %j [our %saxo da+now] /(scot %p ship)) + ?: ?=(%czar (rank:title ship)) + [%& ship] + !! +:: :- %& +:: ;; ship +:: =- -.q.q.- +:: %- need %- need +:: %- rof +:: %j +:: /(scot %p our)/saxo/(scot %da now)/(scot %p who) +:: == -- -- :: +make-message-pump: constructor for |message-pump diff --git a/pkg/urbit/tests/ames_tests.c b/pkg/urbit/tests/ames_tests.c index 8dba7fe45..1effefbaa 100644 --- a/pkg/urbit/tests/ames_tests.c +++ b/pkg/urbit/tests/ames_tests.c @@ -25,7 +25,6 @@ } u3_prel; typedef struct _u3_body { - u3_prel pre_u; // prelude c3_s con_s; // content size c3_y* con_y; // content c3_l mug_l; // checksum @@ -61,52 +60,52 @@ _test_ames(void) } } -static void -_test_sift_etch() -{ - u3_head* hed_u = c3_calloc(sizeof(*hed_u)); - u3_body* bod_u = c3_calloc(sizeof(*bod_u)); - - hed_u->sim_o = c3y; - hed_u->ver_y = 1; - hed_u->sac_y = 4; - hed_u->rac_y = 4; - hed_u->rel_o = c3n; - - bod_u->pre_u.sen_d[0] = 0; - bod_u->pre_u.sen_d[1] = 0; - bod_u->pre_u.rec_d[0] = 182; - bod_u->pre_u.rec_d[1] = 0; - - c3_y* str = (c3_y*)"test"; - - bod_u->con_y = str; - bod_u->con_s = 5; - - c3_y** out_y; - - //TODO fix me! - // c3_w pac_w = _ames_etch_pack(hed_u, bod_u, out_y); - - // u3_head* nhed_u = c3_calloc(sizeof(*nhed_u)); - // u3_body* nbod_u = c3_calloc(sizeof(*nbod_u)); - // _ames_sift_head(nhed_u, *out_y); - // *out_y += 4; - // c3_y_ames_sift_body(nbod_u, *out_y); - - // if( 0 != memcmp(hed_u, nhed_u, sizeof(*hed_u))) { - // fprintf(stderr, "ames: header serialisation mismatch(a)\r\n"); - // exit(1); - // } - // if( 0 != memcmp(bod_u, nbod_u, sizeof(*bod_u))) { - // fprintf(stderr, "ames: body serialisation fail(a)\r\n"); - // exit(1); - // } else { - // fprintf(stderr, "ames: pass (a)\r\n"); - // exit(1); - // } - -} +//TODO: rewrite with more types: purr, wail, body,etc. +//static void +//_test_sift_etch() +//{ +// u3_head* hed_u = c3_calloc(sizeof(*hed_u)); +// u3_body* bod_u = c3_calloc(sizeof(*bod_u)); +// +// hed_u->sim_o = c3y; +// hed_u->ver_y = 1; +// hed_u->sac_y = 4; +// hed_u->rac_y = 4; +// hed_u->rel_o = c3n; +// +// bod_u->pre_u.sen_d[0] = 0; +// bod_u->pre_u.sen_d[1] = 0; +// bod_u->pre_u.rec_d[0] = 182; +// bod_u->pre_u.rec_d[1] = 0; +// +// c3_y* str = (c3_y*)"test"; +// +// bod_u->con_y = str; +// bod_u->con_s = 5; +// +// c3_y** out_y; +// +// c3_w pac_w = _ames_etch_pack(hed_u, bod_u, out_y); +// +// u3_head* nhed_u = c3_calloc(sizeof(*nhed_u)); +// u3_body* nbod_u = c3_calloc(sizeof(*nbod_u)); +// _ames_sift_head(nhed_u, *out_y); +// *out_y += 4; +// c3_y_ames_sift_body(nbod_u, *out_y); +// +// if( 0 != memcmp(hed_u, nhed_u, sizeof(*hed_u))) { +// fprintf(stderr, "ames: header serialisation mismatch(a)\r\n"); +// exit(1); +// } +// if( 0 != memcmp(bod_u, nbod_u, sizeof(*bod_u))) { +// fprintf(stderr, "ames: body serialisation fail(a)\r\n"); +// exit(1); +// } else { +// fprintf(stderr, "ames: pass (a)\r\n"); +// exit(1); +// } +// +//} /* main(): run all test cases. */ int diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index c4243bdee..2928fb0f2 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -1,11 +1,14 @@ /* vere/ames.c -** + */ #include "all.h" #include "vere/vere.h" #include "ur/serial.h" - +#define FINE_PAGE 16384 // packets per page +#define FINE_FRAG 1024 // bytes per fragment packet +#define FINE_PATH_MAX 384 // longest allowed scry path +#define HEAD_SIZE 4 // header size in bytes /* u3_fine: fine networking */ @@ -31,7 +34,7 @@ c3_c* dns_c; // domain XX multiple/fallback c3_y ver_y; // protocol version u3p(u3h_root) lax_p; // lane scry cache - struct _u3_panc* pac_u; // packets pending forwards + struct _u3_panc* pan_u; // outbound packet queue, backward c3_w imp_w[256]; // imperial IPs time_t imp_t[256]; // imperial IP timestamps c3_o imp_o[256]; // imperial print status @@ -45,6 +48,7 @@ c3_d fal_d; // crash count c3_d saw_d; // successive scry failures c3_d hed_d; // failed to read header + c3_d pre_d; // failed to read prelude c3_d vet_d; // version mismatches filtered c3_d mut_d; // invalid mugs filtered c3_d bod_d; // failed to read body @@ -76,74 +80,132 @@ c3_d rog_d; // origin lane (optional) } u3_prel; -/* u3_requ: fine packet request */ - typedef struct _u3_requ { - u3_prel pre_u; - c3_y sig_y[64]; // requester signature - c3_w fra_w; // fragment number - c3_s len_s; // path length - c3_c* pat_c; // path as ascii - } u3_requ; - -/* u3_resp: fine packet response */ - typedef struct _u3_resp { - u3_prel pre_u; - // request: - c3_w fra_w; // fragment number - c3_s len_s; // path length - c3_c* pat_c; // path as ascii - // response: - c3_y sig_y[64]; // host signature - c3_w num_w; // number of fragments - c3_s siz_s; // datum size - c3_y* dat_y; // datum (0 if null response) - } u3_resp; +/* u3_keen: unsigned fine request body +*/ + typedef struct _u3_keen { + c3_w fra_w; // fragment number + c3_s len_s; // path length + c3_c* pat_c; // path as ascii + } u3_keen; +/* u3_wail: signed fine request body +*/ + typedef struct _u3_wail { + c3_y sig_y[64]; // signature + u3_keen ken_u; // request payload + } u3_wail; +/* u3_meow: response portion of purr packet +*/ + typedef struct _u3_meow { + c3_y sig_y[64]; // host signature + c3_w num_w; // number of fragments + c3_s siz_s; // datum size + c3_y* dat_y; // datum (0 if null response) + } u3_meow; +/* u3_purr: fine packet response +*/ + typedef struct _u3_purr { + u3_keen ken_u; + u3_meow mew_u; + } u3_purr; /* u3_body: ames packet body */ typedef struct _u3_body { - u3_prel pre_u; // prelude - c3_s con_s; // content size - c3_y* con_y; // content - c3_l mug_l; // checksum + c3_s con_s; // content size + c3_y* con_y; // content + c3_l mug_l; // checksum } u3_body; -/* u3_pact: outbound ames packet. +/* u3_ptag: packet-type tag +*/ + typedef enum _u3_ptag { + PACT_AMES = 1, // ames packet + PACT_WAIL = 2, // fine request packet + PACT_PURR = 3 // fine response packet + } u3_ptag; + +/* u3_pact: ames packet + * + * Filled in piece by piece as we parse or construct it. */ typedef struct _u3_pact { uv_udp_send_t snd_u; // udp send request - u3_lane lan_u; // destination lane + struct _u3_ames* sam_u; // ames backpointer c3_w len_w; // length in bytes c3_y* hun_y; // packet buffer u3_head hed_u; // head of packet - c3_y imp_y; // galaxy number (optional) - c3_c* dns_c; // galaxy fqdn (optional) - struct _u3_ames* sam_u; // ames backpointer - c3_y typ_y; + u3_prel pre_u; // packet prelude + u3_ptag typ_y; // packet type tag + struct { + u3_lane lan_u; // destination/origin lane + c3_y imp_y; // galaxy (optional) + c3_c* dns_c; // galaxy fqdn (optional) + } rut_u; union { - u3_resp res_u; - u3_requ req_u; - u3_body bod_u; + u3_body bod_u; // tagged by PACT_AMES + u3_wail wal_u; // tagged by PACT_WAIL + u3_purr pur_u; // tagged by PACT_PURR }; } u3_pact; -static void _fine_got_pack(u3_pact*, u3_noun); - -/* u3_panc: deconstructed incoming packet +/* u3_panc: packet queue */ typedef struct _u3_panc { - u3_ames* sam_u; // ames backpointer struct _u3_panc* pre_u; // previous packet struct _u3_panc* nex_u; // next packet - u3_lane ore_u; // origin lane - u3_head hed_u; // header - u3_body bod_u; // body - void* ptr_v; // buffer (to free) + u3_pact* pac_u; // this packet + c3_o for_o; // are we forwarding this? } u3_panc; +static void +_log_head(u3_head* hed_u) +{ + u3l_log("-- HEADER --\n"); + u3l_log("is request: %s\n", (c3y == hed_u->req_o)? "yes" : "no"); + u3l_log("is ames: %s\n", (c3y == hed_u->sim_o)? "yes" : "no"); + u3l_log("mug: 0x%05x\n", (hed_u->mug_l &0xfffff)); + u3l_log("protocol version: %u\n", hed_u->ver_y); + u3l_log("sender class: %u\n", hed_u->sac_y); + u3l_log("recevr class: %u\n", hed_u->rac_y); + u3l_log("is relayed: %s\n", (c3y == hed_u->rel_o)? "yes" : "no"); + u3l_log("\n"); +} + +static void +_log_prel(u3_prel* pre_u) +{ + u3l_log("-- PRELUDE --\n"); + u3l_log("sender life: %u\n", pre_u->sic_y); + u3l_log("receiver life: %u\n", pre_u->ric_y); + u3l_log("sender: %" PRIu64 "\n", pre_u->sen_d[0]); + u3l_log("receiver: %" PRIu64" \n", pre_u->rec_d[0]); + u3l_log("\n"); +} + +static void +_log_keen(u3_keen* req_u) +{ + u3l_log("--- REQUEST ---\n"); + u3l_log("strlen: %u\n", req_u->len_s); + u3l_log("path: %s\n", req_u->pat_c); + u3l_log("frag: %u\n", req_u->fra_w); + u3l_log("\n"); +} + +static void +_log_bytes(c3_y* byt_y, c3_w len_w) +{ + int i; + u3l_log("-- BYTES (%u) --\n", len_w); + for(i = 0; i < len_w; i++) { + u3l_log("%x\n", byt_y[i]); + } + u3l_log("\n"); +} + /* _ames_alloc(): libuv buffer allocator. */ static void @@ -162,109 +224,112 @@ _ames_alloc(uv_handle_t* had_u, static void _ames_pact_free(u3_pact* pac_u) { - if ( 0 == pac_u->typ_y ) { // ames packet - } else if ( 1 == pac_u->typ_y ) { // fine request - c3_free(pac_u->req_u.pat_c); - } else { // fine response - c3_free(pac_u->res_u.pat_c); - c3_free(pac_u->res_u.dat_y); + switch ( pac_u->typ_y ) { + case PACT_AMES: + c3_free(pac_u->bod_u.con_y); + break; + + case PACT_WAIL: + c3_free(pac_u->wal_u.ken_u.pat_c); + break; + + case PACT_PURR: + c3_free(pac_u->pur_u.ken_u.pat_c); + c3_free(pac_u->pur_u.mew_u.dat_y); + break; + + default: + u3l_log("ames_pact_free: bad packet type %d\n", pac_u->typ_y); + u3_pier_bail(u3_king_stub()); } - c3_free(pac_u->dns_c); + c3_free(pac_u->rut_u.dns_c); c3_free(pac_u->hun_y); - c3_free(pac_u); } /* _ames_panc_free(): remove references, lose refcounts and free struct */ static void -_ames_panc_free(u3_panc* pac_u) +_ames_panc_free(u3_panc* pan_u) { - if ( 0 != pac_u->nex_u ) { - pac_u->nex_u->pre_u = pac_u->pre_u; + if ( pan_u->for_o ) { + if ( 0 != pan_u->nex_u ) { + pan_u->nex_u->pre_u = pan_u->pre_u; + } + + if ( 0 != pan_u->pre_u ) { + pan_u->pre_u->nex_u = pan_u->nex_u; + } + else { + c3_assert(pan_u == pan_u->pac_u->sam_u->pan_u); + pan_u->pac_u->sam_u->pan_u = pan_u->nex_u; + } } - - if ( 0 != pac_u->pre_u ) { - pac_u->pre_u->nex_u = pac_u->nex_u; - } - else if ( pan_u == pan_u->pac_u->sam_u->pan_u ) { - pan_u->pac_u->sam_u->pan_u = pan_u->nex_u; - } - - c3_free(pac_u->ptr_v); - c3_free(pac_u); + _ames_pact_free(pan_u->pac_u); + c3_free(pan_u); } -/* _lane_scry_path(): format scry path for retrieving a lane -*/ -static inline u3_noun _lane_scry_path(u3_noun who) +static inline c3_y +_ames_origin_size(u3_head* hed_u) { - return u3nq(u3i_string("peers"), - u3dc("scot", 'p', who), - u3i_string("forward-lane"), - u3_nul); + return ( c3y == hed_u->rel_o ) ? 6 : 0; // origin is 6 bytes } -static void _log_prel(u3_prel* pre_u) +static c3_y +_ames_prel_size(u3_head* hed_u) { - u3l_log("-- PRELUDE --\n"); - u3l_log("sender life: %u\n", pre_u->sic_y); - u3l_log("receiver life: %u\n", pre_u->ric_y); - u3l_log("sender: %" PRIu64 "\n", pre_u->sen_d[0]); - u3l_log("receiver: %" PRIu64" \n", pre_u->rec_d[0]); - u3l_log("\n"); + c3_y lif_y = 1; + c3_y sen_y = 2 << hed_u->sac_y; + c3_y rec_y = 2 << hed_u->rac_y; + c3_y rog_y = _ames_origin_size(hed_u); + return lif_y + sen_y + rec_y + rog_y; } -static void _log_requ(u3_requ* req_u) +static inline c3_s +_ames_body_size(u3_body* bod_u) { - _log_prel(&req_u->pre_u); - u3l_log("--- REQUEST ---\n"); - u3l_log("strlen: %u\n", req_u->len_s); - u3l_log("path: %s\n", req_u->pat_c); - u3l_log("frag: %u\n", req_u->fra_w); - u3l_log("\n"); - return; + return bod_u->con_s; } -static void -_log_bytes(c3_y* byt_y, c3_w len_w) +static inline c3_s +_fine_keen_size(u3_keen* ken_u) { - int i; - u3l_log("-- BYTES (%u) --\n", len_w); - for(i = 0; i < len_w; i++) { - u3l_log("%x\n", byt_y[i]); - } - u3l_log("\n"); + return ( + sizeof(ken_u->fra_w) + + sizeof(ken_u->len_s) + + ken_u->len_s); } - - -/* _ames_sift_head(): parse packet header. -*/ -static c3_o -_ames_sift_head(u3_head* hed_u, c3_y buf_y[4]) +static inline c3_s +_fine_meow_size(u3_meow* mew_u) { - c3_w hed_w = buf_y[0] - | (buf_y[1] << 8) - | (buf_y[2] << 16) - | (buf_y[3] << 24); - - // first three bits are reserved - // - hed_u->req_o = (hed_w >> 2) & 0x1; - hed_u->sim_o = (hed_w >> 3) & 0x1; - hed_u->ver_y = (hed_w >> 4) & 0x7; - hed_u->sac_y = (hed_w >> 7) & 0x3; - hed_u->rac_y = (hed_w >> 9) & 0x3; - hed_u->mug_l = (hed_w >> 11) & 0xfffff; // 20 bits - hed_u->rel_o = (hed_w >> 31) & 0x1; - - // reject packets that don't even claim to be ames packets - // - return hed_u->sim_o; + return ( + sizeof(mew_u->sig_y) + + sizeof(mew_u->num_w) + + sizeof(mew_u->siz_s) + + mew_u->siz_s); } +static c3_s +_fine_purr_size(u3_purr* pur_u) +{ + c3_s pur_s = _fine_keen_size(&pur_u->ken_u); + c3_s mew_s = _fine_meow_size(&pur_u->mew_u); + return pur_s + mew_s; +} + +static inline c3_s +_ames_sift_short(c3_y buf_y[2]) +{ + return (buf_y[1] << 8 | buf_y[0]); +} + +static inline c3_w +_ames_sift_word(c3_y buf_y[4]) +{ + return (buf_y[3] << 24 | buf_y[2] << 16 | buf_y[1] << 8 | buf_y[0]); +} /* _ames_chub_bytes(): c3_y[8] to c3_d ** XX factor out, deduplicate with other conversions @@ -323,170 +388,181 @@ _ames_ship_of_chubs(c3_d sip_d[2], c3_y len_y, c3_y* buf_y) memcpy(buf_y, sip_y, c3_min(16, len_y)); } -/* _ames_sift_prelude(): parse prelude, returning length +/* _ames_sift_head(): parse packet header. */ -static c3_y -_ames_sift_prelude(u3_head* hed_u, - u3_prel* pre_u, - c3_w len_w, - c3_y* pre_y) +static void +_ames_sift_head(u3_head* hed_u, c3_y buf_y[4]) { - c3_y rog_y, sen_y, rec_y, len_y; + c3_w hed_w = _ames_sift_word(buf_y); - rog_y = ( c3y == hed_u->rel_o )? 6 : 0; - sen_y = 2 << hed_u->sac_y; - rec_y = 2 << hed_u->rac_y; - len_y = rog_y + sen_y + rec_y + 1; + // first two bits are reserved + // + hed_u->req_o = (hed_w >> 2) & 0x1; + hed_u->sim_o = (hed_w >> 3) & 0x1; + hed_u->ver_y = (hed_w >> 4) & 0x7; + hed_u->sac_y = (hed_w >> 7) & 0x3; + hed_u->rac_y = (hed_w >> 9) & 0x3; + hed_u->mug_l = (hed_w >> 11) & 0xfffff; // 20 bits + hed_u->rel_o = (hed_w >> 31) & 0x1; +} - pre_u->sic_y = pre_y[0] & 0xf; - pre_u->ric_y = pre_y[0] & 0xf0; +/* _ames_sift_prel(): parse prelude, +*/ +static void +_ames_sift_prel(u3_head* hed_u, + u3_prel* pre_u, + c3_y* buf_y) +{ + c3_y sen_y, rec_y; + c3_w cur_w = 0; - _ames_ship_to_chubs(pre_u->sen_d, sen_y, pre_y + 1); - _ames_ship_to_chubs(pre_u->rec_d, rec_y, pre_y + 1 + sen_y); - - if (rog_y) { + // if packet is relayed, parse 6-byte origin field + // + if ( c3y == hed_u->rel_o ) { c3_y rag_y[8] = {0}; - memcpy(rag_y, pre_y + 1 + sen_y + rec_y, rog_y); + memcpy(rag_y, buf_y + cur_w, 6); pre_u->rog_d = _ames_chub_bytes(rag_y); + cur_w += 6; } else { pre_u->rog_d = 0; } - return len_y; + + // parse life ticks + // + pre_u->sic_y = buf_y[cur_w] & 0xf; + pre_u->ric_y = (buf_y[cur_w] >> 4) & 0xf; + cur_w++; + + // parse sender ship + // + sen_y = 2 << hed_u->sac_y; + _ames_ship_to_chubs(pre_u->sen_d, sen_y, buf_y + cur_w); + cur_w += sen_y; + + // parse receiver ship + // + rec_y = 2 << hed_u->rac_y; + _ames_ship_to_chubs(pre_u->rec_d, rec_y, buf_y + cur_w); + cur_w += rec_y; } - - -/* _fine_sift_requ(): parse request body, returning success +/* _fine_sift_wail(): parse request body, returning success */ static c3_o -_fine_sift_requ(u3_head* hed_u, - u3_requ* req_u, - c3_w len_w, - c3_y* req_y) +_fine_sift_wail(u3_pact* pac_u, c3_w cur_w) { - c3_y pre_y = _ames_sift_prelude(hed_u, &req_u->pre_u, len_w, req_y); + c3_w tot_w, exp_w; + c3_s len_s; - req_y += pre_y; + c3_w sig_w = sizeof(pac_u->wal_u.sig_y); + c3_w fra_w = sizeof(pac_u->wal_u.ken_u.fra_w); + c3_w len_w = sizeof(pac_u->wal_u.ken_u.len_s); + exp_w = sig_w + fra_w + len_w; - c3_w rem_w = (64 + 4 + 2 + pre_y); - if ( rem_w > len_w ) { - u3l_log("not big enough\n"); + if ( cur_w + exp_w > pac_u->len_w ) { + u3l_log("fine: wail not big enough\n"); return c3n; } - memcpy(req_u->sig_y, req_y, 64); - req_y += 64; + // parse signature + // + memcpy(pac_u->wal_u.sig_y, pac_u->hun_y + cur_w, sig_w); + cur_w += sig_w; - req_u->fra_w = ( - (req_y[0] << 0x0) - | (req_y[1] << 0x8) - | (req_y[2] << 0x10) - | (req_y[3] << 0x18)); - req_y += 4; + // parse fragment number + // + pac_u->wal_u.ken_u.fra_w = _ames_sift_word(pac_u->hun_y + cur_w); + cur_w += fra_w; - req_u->len_s = c3_min(384, - (req_y[0] << 0x0) - | (req_y[1] << 0x8)); - req_y += 2; + // parse path length field + // + len_s = _ames_sift_short(pac_u->hun_y + cur_w); + pac_u->wal_u.ken_u.len_s = len_s; + cur_w += len_w; - c3_w exp_w = rem_w + req_u->len_s; - if ( exp_w != len_w ) { - u3l_log("expected len: %u, actual %u\n", exp_w, len_w); + if ( len_s > FINE_PATH_MAX ) { + u3l_log("ames wail len: %u, max %u\n", len_s, FINE_PATH_MAX); return c3n; } - req_u->pat_c = c3_calloc(req_u->len_s + 1); + tot_w = cur_w + len_s; + if ( tot_w != pac_u->len_w ) { + u3l_log("fine: wail expected total len: %u, actual %u\n", + tot_w, pac_u->len_w); + return c3n; + } - memcpy(req_u->pat_c, req_y, req_u->len_s); - req_u->pat_c[req_u->len_s] = '\0'; + // parse request path + // + pac_u->wal_u.ken_u.pat_c = c3_calloc(len_s + 1); + memcpy(pac_u->wal_u.ken_u.pat_c, pac_u->hun_y + cur_w, len_s); + pac_u->wal_u.ken_u.pat_c[len_s] = '\0'; return c3y; } -/* _fine_sift_resp(): parse response body, returning success +/* _fine_sift_meow(): parse signed scry response fragment */ static c3_o -_fine_sift_resp(u3_head* hed_u, - u3_resp* res_u, - c3_w len_w, - c3_y* res_y) +_fine_sift_meow(u3_meow* mew_u, u3_noun mew) { - c3_w rem_w = (64 + 4 + hed_u->sac_y + 4 + hed_u->rac_y + 2); - if(rem_w > len_w) { - u3l_log("bad size %u", len_w); - return c3n; - } + c3_o ret_o; + c3_w len_w = u3r_met(3, mew); - c3_y pre_y = _ames_sift_prelude(hed_u, &res_u->pre_u, len_w, res_y); - res_y += pre_y; + c3_y sig_w = sizeof(mew_u->sig_y); + c3_y num_w = sizeof(mew_u->num_w); + c3_y siz_w = sizeof(mew_u->siz_s); + c3_y mew_w = sig_w + num_w + siz_w; - res_u->fra_w = ( - (res_y[0] << 0x0) - | (res_y[1] << 0x8) - | (res_y[2] << 0x10) - | (res_y[3] << 0x18)); - res_y += 4; - - - res_u->len_s = c3_min(384, - (res_y[0] << 0x0) - | (res_y[1] << 0x8)); - res_y += 2; - - res_u->pat_c = c3_calloc(res_u->len_s + 1); - memcpy(res_u->pat_c, res_y, res_u->len_s); - - memcpy(res_u->sig_y, res_y, 64); - res_y += 64; - - res_u->num_w = ( - (res_y[0] << 0x0) - | (res_y[1] << 0x8) - | (res_y[2] << 0x10) - | (res_y[3] << 0x18)); - res_y += 4; - - res_u->siz_s = c3_min(384, - (res_y[0] << 0x0) - | (res_y[1] << 0x8)); - res_y += 2; - - - res_u->dat_y = c3_calloc(res_u->siz_s); - memcpy(&res_u->dat_y, res_y, res_u->siz_s); - - - if(rem_w + res_u->len_s != len_w) { - return c3n; - } - - return c3y; -} - -/* _ames_sift_body(): parse packet body. -*/ -static c3_o -_ames_sift_body(u3_head* hed_u, - u3_body* bod_u, - c3_w len_w, - c3_y* bod_y) -{ - c3_y rog_y = ( c3y == hed_u->rel_o )? 6 : 0; - c3_y* gob_y = bod_y + rog_y; - c3_s gob_s = len_w - rog_y; - - c3_y pre_y = _ames_sift_prelude(hed_u, &bod_u->pre_u, len_w, bod_y); - - if (pre_y >= len_w ) { - return c3n; + if ( (len_w < mew_w) || (len_w > FINE_FRAG + mew_w) ) + { + u3l_log("sift_meow len_w %u, mew_w %u\n", len_w, mew_w); + ret_o = c3n; } else { - bod_u->mug_l = u3r_mug_bytes(gob_y, gob_s) & 0xfffff; + c3_w cur_w = 0; - bod_u->con_y = gob_y + 4; + // parse signature + // + u3r_bytes(cur_w, sig_w, mew_u->sig_y, mew); + cur_w += sig_w; - return c3y; + // parse number of fragments + // + u3r_bytes(cur_w, num_w, (c3_y*)&mew_u->num_w, mew); + cur_w += num_w; + + // parse data size field + // + u3r_bytes(cur_w, siz_w, (c3_y*)&mew_u->siz_s, mew); + cur_w += siz_w; + + // parse data payload + // + mew_u->dat_y = c3_calloc(mew_u->siz_s); + u3r_bytes(cur_w, mew_u->siz_s, mew_u->dat_y, mew); + + ret_o = c3y; } + + u3z(mew); + return ret_o; +} + +static void +_ames_etch_short(c3_y buf_y[2], c3_s sot_s) +{ + buf_y[0] = sot_s & 0xff; + buf_y[1] = (sot_s >> 8) & 0xff; +} + +static void +_ames_etch_word(c3_y buf_y[4], c3_w wod_w) +{ + buf_y[0] = wod_w & 0xff; + buf_y[1] = (wod_w >> 8) & 0xff; + buf_y[2] = (wod_w >> 16) & 0xff; + buf_y[3] = (wod_w >> 24) & 0xff; } /* _ames_etch_head(): serialize packet header. @@ -494,6 +570,10 @@ _ames_sift_body(u3_head* hed_u, static void _ames_etch_head(u3_head* hed_u, c3_y buf_y[4]) { + // only version 0 currently recognized + // + c3_assert( 0 == hed_u->ver_y ); // XX remove after testing + c3_w hed_w = ((hed_u->req_o & 0x1) << 2) ^ ((hed_u->sim_o & 0x1) << 3) ^ ((hed_u->ver_y & 0x7) << 4) @@ -502,99 +582,151 @@ _ames_etch_head(u3_head* hed_u, c3_y buf_y[4]) ^ ((hed_u->mug_l & 0xfffff) << 11) ^ ((hed_u->rel_o & 0x1) << 31); - // only version 0 currently recognized - // - c3_assert( 0 == hed_u->ver_y ); // XX remove after testing - - buf_y[0] = hed_w & 0xff; - buf_y[1] = (hed_w >> 8) & 0xff; - buf_y[2] = (hed_w >> 16) & 0xff; - buf_y[3] = (hed_w >> 24) & 0xff; + _ames_etch_word(buf_y, hed_w); } -/* _ames_etch_prelude(): serialize packet prelude +/* _ames_etch_prel(): serialize packet prelude */ -static c3_y -_ames_etch_prelude(u3_head* hed_u, u3_prel* pre_u, c3_y* buf_y) +static void +_ames_etch_prel(u3_head* hed_u, u3_prel* pre_u, c3_y* buf_y) { - c3_y rog_y = ( c3y == hed_u->rel_o ) ? 6 : 0; // origin len - c3_y sen_y = 2 << pre_u->sic_y; - c3_y rec_y = 2 << pre_u->ric_y; - c3_y len_y = sen_y + rec_y + rog_y; + c3_w cur_w = 0; - - // copy lives - buf_y[0] = (pre_u->sic_y & 0xf) ^ ((pre_u->ric_y & 0xf) << 4); - - _ames_ship_of_chubs(pre_u->sen_d, sen_y, buf_y + 1); - _ames_ship_of_chubs(pre_u->rec_d, rec_y, buf_y + 1 + sen_y); - - if ( rog_y ) { + // if packet is relayed, write the 6-byte origin field + // + if ( c3y == hed_u->rel_o ) { c3_y rag_y[8] = {0}; _ames_bytes_chub(rag_y, pre_u->rog_d); - memcpy(buf_y, rag_y, rog_y); + memcpy(buf_y + cur_w, rag_y, 6); + cur_w += 6; } - return len_y; -} -/* _fine_etch_resp(): serialise response packet - */ -static c3_w -_fine_etch_resp(u3_head* hed_u, - u3_resp* res_u, - c3_y** out_y) -{ - c3_assert(0 == hed_u->req_o); - c3_assert(0 == hed_u->sim_o); - - c3_y sen_y = 2 << hed_u->sac_y; // sender len - c3_y rec_y = 2 << hed_u->rac_y; // receiver len - c3_y len_w = 80 + sen_y + rec_y + res_u->siz_s + res_u->len_s; - - c3_y* pac_y = c3_calloc(len_w); - c3_w* pac_w = (c3_w*)pac_y; - - memcpy(pac_w, &res_u->fra_w, 4); - *pac_w = res_u->fra_w; - - *(pac_y + sen_y + 4) = (0xff << 0) & res_u->len_s; - *(pac_y + sen_y + 5) = (0xff << 1) & res_u->len_s; - - memcpy(pac_y + sen_y + 6, res_u->pat_c, res_u->len_s); - - memcpy(pac_y + sen_y + 6 + res_u->len_s, &res_u->sig_y, 64 + 4 + 4 + 2); - - return len_w; -} - - -/* _ames_etch_pack(): serialize packet header and body. -*/ -static c3_w -_ames_etch_pack(u3_head* hed_u, - u3_body* bod_u, - c3_y** out_y) -{ - c3_y sen_y = 2 << hed_u->sac_y; // sender len - c3_y rec_y = 2 << hed_u->rac_y; // receiver len - c3_y rog_y = ( c3y == hed_u->rel_o ) ? 6 : 0; // origin len - c3_w bod_w = rog_y + 1 + sen_y + rec_y + bod_u->con_s; // body len - c3_w len_w = 4 + bod_w; // packet len - c3_y* pac_y = c3_calloc(len_w); // output buf - c3_y* bod_y = pac_y + 4; // body cursor - - // serialize the head + // write life ticks // - _ames_etch_head(hed_u, pac_y); + buf_y[cur_w] = (pre_u->sic_y & 0xf) ^ ((pre_u->ric_y & 0xf) << 4); + cur_w++; - c3_y pre_y = _ames_etch_prelude(hed_u, &bod_u->pre_u, bod_y + 4); - c3_y* gob_y = bod_y + pre_y; // after origin + // write sender ship + // + c3_y sen_y = 2 << hed_u->sac_y; + _ames_ship_of_chubs(pre_u->sen_d, sen_y, buf_y + cur_w); + cur_w += sen_y; - // serialize the body - memcpy(gob_y, bod_u->con_y, bod_u->con_s); + // write receiver ship + // + c3_y rec_y = 2 << hed_u->rac_y; + _ames_ship_of_chubs(pre_u->rec_d, rec_y, buf_y + cur_w); + cur_w += rec_y; +} - *out_y = pac_y; - return len_w; +/* _fine_etch_keen(): serialize unsigned scry request +*/ +static void +_fine_etch_keen(u3_keen* ken_u, c3_y* buf_y) +{ + c3_w cur_w = 0; + + // write fragment number + // + _ames_etch_word(buf_y + cur_w, ken_u->fra_w); + cur_w += sizeof(ken_u->fra_w); + + // write path length + // + _ames_etch_short(buf_y + cur_w, ken_u->len_s); + cur_w += sizeof(ken_u->len_s); + + // write request path + // + memcpy(buf_y + cur_w, ken_u->pat_c, ken_u->len_s); +} + +/* fine_etch_meow(): serialize signed scry response fragment +*/ +static void +_fine_etch_meow(u3_meow* mew_u, c3_y* buf_y) +{ + c3_w cur_w = 0; + + // write signature + // + c3_w sig_w = sizeof(mew_u->sig_y); + memcpy(buf_y + cur_w, mew_u->sig_y, sig_w); + cur_w += sig_w; + + // write number of fragments + // + _ames_etch_word(buf_y + cur_w, mew_u->num_w); + cur_w += sizeof(mew_u->num_w); + + // write response length field + // + _ames_etch_short(buf_y + cur_w, mew_u->siz_s); + cur_w += sizeof(mew_u->siz_s); + + // write response fragment data + // + memcpy(buf_y + cur_w, mew_u->dat_y, mew_u->siz_s); +} + +/* _fine_etch_purr(): serialise response packet + */ +static void +_fine_etch_purr(u3_purr* pur_u, c3_y* buf_y) +{ + c3_w cur_w = 0; + + // write unsigned scry request + // + _fine_etch_keen(&pur_u->ken_u, buf_y + cur_w); + cur_w += _fine_keen_size(&pur_u->ken_u); + + // write signed response fragment + _fine_etch_meow(&pur_u->mew_u, buf_y + cur_w); +} + +/* _fine_etch_response(): serialize scry response packet +*/ +static void +_fine_etch_response(u3_pact* pac_u) +{ + c3_w pre_w, pur_w, cur_w, rog_w; + + pre_w = _ames_prel_size(&pac_u->hed_u); + pur_w = _fine_purr_size(&pac_u->pur_u); + pac_u->len_w = HEAD_SIZE + pre_w + pur_w; + pac_u->hun_y = c3_calloc(pac_u->len_w); + + // skip the header until we know what the mug should be + // + cur_w = HEAD_SIZE; + + // write prelude + // + _ames_etch_prel(&pac_u->hed_u, &pac_u->pre_u, pac_u->hun_y + cur_w); + cur_w += pre_w; + + // write body + // + _fine_etch_purr(&pac_u->pur_u, pac_u->hun_y + cur_w); + + // calculate mug and write header + // + rog_w = HEAD_SIZE + _ames_origin_size(&pac_u->hed_u); + pac_u->hed_u.mug_l = u3r_mug_bytes(pac_u->hun_y + rog_w, + pac_u->len_w - rog_w); + _ames_etch_head(&pac_u->hed_u, pac_u->hun_y); +} + +/* _lane_scry_path(): format scry path for retrieving a lane +*/ +static inline u3_noun +_lane_scry_path(u3_noun who) +{ + return u3nq(u3i_string("peers"), + u3dc("scot", 'p', who), + u3i_string("forward-lane"), + u3_nul); } /* _ames_send_cb(): send callback. @@ -605,8 +737,8 @@ _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) u3_pact* pac_u = (u3_pact*)req_u; u3_ames* sam_u = pac_u->sam_u; - if (sas_i) { - u3l_log("ames: send fail: %s\n", uv_strerror(sas_i)); + if ( sas_i ) { + u3l_log("ames: send fail_async: %s\n", uv_strerror(sas_i)); sam_u->fig_u.net_o = c3n; } else { @@ -624,17 +756,22 @@ _ames_send(u3_pact* pac_u) { u3_ames* sam_u = pac_u->sam_u; - if ( !pac_u->hun_y ) { + if ( !pac_u->hun_y + || !sam_u + || !&sam_u->wax_u + || !pac_u->len_w + || !pac_u->rut_u.lan_u.por_s ) + { + u3l_log("_ames_send null\n"); _ames_pact_free(pac_u); - return; } else { struct sockaddr_in add_u; memset(&add_u, 0, sizeof(add_u)); add_u.sin_family = AF_INET; - add_u.sin_addr.s_addr = htonl(pac_u->lan_u.pip_w); - add_u.sin_port = htons(pac_u->lan_u.por_s); + add_u.sin_addr.s_addr = htonl(pac_u->rut_u.lan_u.pip_w); + add_u.sin_port = htons(pac_u->rut_u.lan_u.por_s); { uv_buf_t buf_u = uv_buf_init((c3_c*)pac_u->hun_y, pac_u->len_w); @@ -647,7 +784,7 @@ _ames_send(u3_pact* pac_u) if ( sas_i ) { if ( c3y == sam_u->fig_u.net_o ) { - u3l_log("ames: send fail: %s\n", uv_strerror(sas_i)); + u3l_log("ames: send fail_sync: %s\n", uv_strerror(sas_i)); sam_u->fig_u.net_o = c3n; } @@ -728,41 +865,11 @@ _ames_lane_from_cache(u3p(u3h_root) lax_p, u3_noun who) { return lac; } -/* _ames_serialize_packet(): u3_panc to atom, updating the origin lane if dop_o -** (retains pac_u) -*/ static u3_noun -_ames_serialize_packet(u3_panc* pac_u, c3_o dop_o) +_ames_pact_to_noun(u3_pact* pac_u) { - // update the body's lane, if: - // - we're supposed to (dop_o) - // - it hasn't already been updated (rel_o) - // - sender is not a galaxy - // - if ( c3y == dop_o - && c3n == pac_u->hed_u.rel_o - && !( ( 256 > pac_u->bod_u.pre_u.sen_d[0] ) - && ( 0 == pac_u->bod_u.pre_u.sen_d[1] ) ) ) - { - pac_u->hed_u.rel_o = c3y; - pac_u->bod_u.pre_u.rog_d = u3_ames_lane_to_chub(pac_u->ore_u); - } - - // serialize the packet - // - // XX serialize on stack? - // - { - u3_noun pac; - c3_y* pac_y; - c3_w len_w = _ames_etch_pack(&pac_u->hed_u, - &pac_u->bod_u, - &pac_y); - pac = u3i_bytes(len_w, pac_y); - c3_free(pac_y); - - return pac; - } + u3_noun pac = u3i_bytes(pac_u->len_w, pac_u->hun_y); + return pac; } /* _ames_czar_port(): udp port for galaxy. @@ -784,10 +891,10 @@ static void _ames_czar_gone(u3_pact* pac_u, time_t now) { u3_ames* sam_u = pac_u->sam_u; - c3_d imp_y = pac_u->imp_y; + c3_d imp_y = pac_u->rut_u.imp_y; if ( c3y == sam_u->imp_o[imp_y] ) { - u3l_log("ames: czar at %s: not found (b)\n", pac_u->dns_c); + u3l_log("ames: czar at %s: not found (b)\n", pac_u->rut_u.dns_c); sam_u->imp_o[imp_y] = c3n; } @@ -810,7 +917,7 @@ static void _ames_czar_here(u3_pact* pac_u, time_t now, struct sockaddr_in* add_u) { u3_ames* sam_u = pac_u->sam_u; - c3_y imp_y = pac_u->imp_y; + c3_y imp_y = pac_u->rut_u.imp_y; c3_w old_w = sam_u->imp_w[imp_y]; c3_w pip_w = ntohl(add_u->sin_addr.s_addr); @@ -818,7 +925,7 @@ _ames_czar_here(u3_pact* pac_u, time_t now, struct sockaddr_in* add_u) u3_noun nam = u3dc("scot", c3__if, u3i_word(pip_w)); c3_c* nam_c = u3r_string(nam); - u3l_log("ames: czar %s: ip %s\n", pac_u->dns_c, nam_c); + u3l_log("ames: czar %s: ip %s\n", pac_u->rut_u.dns_c, nam_c); c3_free(nam_c); u3z(nam); @@ -828,7 +935,7 @@ _ames_czar_here(u3_pact* pac_u, time_t now, struct sockaddr_in* add_u) sam_u->imp_t[imp_y] = now; sam_u->imp_o[imp_y] = c3y; - pac_u->lan_u.pip_w = pip_w; + pac_u->rut_u.lan_u.pip_w = pip_w; } /* _ames_czar_cb(): galaxy address resolution callback. @@ -869,12 +976,12 @@ _ames_czar(u3_pact* pac_u) { u3_ames* sam_u = pac_u->sam_u; - c3_y imp_y = pac_u->imp_y; + c3_y imp_y = pac_u->rut_u.imp_y; - pac_u->lan_u.por_s = _ames_czar_port(imp_y); + pac_u->rut_u.lan_u.por_s = _ames_czar_port(imp_y); if ( c3n == u3_Host.ops_u.net ) { - pac_u->lan_u.pip_w = 0x7f000001; + pac_u->rut_u.lan_u.pip_w = 0x7f000001; _ames_send(pac_u); return; } @@ -882,7 +989,7 @@ _ames_czar(u3_pact* pac_u) // if we don't have a galaxy domain, no-op // if ( !sam_u->dns_c ) { - u3_noun nam = u3dc("scot", 'p', pac_u->imp_y); + u3_noun nam = u3dc("scot", 'p', pac_u->rut_u.imp_y); c3_c* nam_c = u3r_string(nam); u3l_log("ames: no galaxy domain for %s, no-op\r\n", nam_c); @@ -908,7 +1015,7 @@ _ames_czar(u3_pact* pac_u) // cached addresses have a 5 minute TTL // else if ( (0 != pip_w) && ((now - wen) < 300) ) { - pac_u->lan_u.pip_w = pip_w; + pac_u->rut_u.lan_u.pip_w = pip_w; _ames_send(pac_u); return; } @@ -921,8 +1028,11 @@ _ames_czar(u3_pact* pac_u) // NB: . separator not counted, as [nam_c] includes a ~ that we skip // - pac_u->dns_c = c3_malloc(1 + strlen(nam_c) + strlen(sam_u->dns_c)); - sas_i = snprintf(pac_u->dns_c, 255, "%s.%s", nam_c + 1, sam_u->dns_c); + pac_u->rut_u.dns_c = + c3_malloc(1 + strlen(nam_c) + strlen(sam_u->dns_c)); + + sas_i = + snprintf(pac_u->rut_u.dns_c, 255, "%s.%s", nam_c + 1, sam_u->dns_c); c3_free(nam_c); u3z(nam); @@ -940,7 +1050,7 @@ _ames_czar(u3_pact* pac_u) if ( 0 != (sas_i = uv_getaddrinfo(u3L, adr_u, _ames_czar_cb, - pac_u->dns_c, 0, 0)) ) + pac_u->rut_u.dns_c, 0, 0)) ) { u3l_log("ames: %s\n", uv_strerror(sas_i)); _ames_czar_gone(pac_u, now); @@ -954,11 +1064,9 @@ _ames_czar(u3_pact* pac_u) /* _fine_put_cache(): put list of packets into cache */ static void -_fine_put_cache(u3_ames* sam_u, u3_noun pax, u3_noun lis) +_fine_put_cache(u3_ames* sam_u, u3_noun pax, c3_w lop_w, u3_noun lis) { - u3_noun beg = lis; - - c3_w cur_w = 1; + c3_w cur_w = lop_w; while ( lis != u3_nul ) { u3_noun key = u3nc(u3k(pax), u3i_word(cur_w)); u3h_put(sam_u->fin_s.sac_p, key, u3k(u3h(lis))); @@ -969,48 +1077,6 @@ _fine_put_cache(u3_ames* sam_u, u3_noun pax, u3_noun lis) } } -/* _fine_lane_scry_cb(): learn lane to send response on -*/ -static void -_fine_lane_scry_cb(void* vod_p, u3_noun nun) -{ - u3_pact* pac_u = vod_p; - u3_ames* sam_u = pac_u->sam_u; - u3_weak las = u3r_at(7, nun); - - // if scry fails, just drop the packet - // - if ( u3_none == las ) { - u3l_log("failed to scry\n"); - _ames_pact_free(pac_u); - } - else { - - // cache the scry result for later use - // - _ames_lane_into_cache(sam_u->lax_p, - u3i_chubs(2, pac_u->bod_u.pre_u.rec_d), - u3k(las)); - - // if there is no lane, drop the packet - // - if ( u3_nul == las ) { - _ames_pact_free(pac_u); - } - // if there is a lane, forward the packet on it - // - else { - c3_d lan_d = u3r_chub(0, las); - pac_u->lan_u.pip_w = (c3_w)lan_d; - pac_u->lan_u.por_s = (c3_s)(lan_d >> 32); - _fine_send(pac_u); - } - } - - u3z(nun); -} - - /* _ames_ef_send(): send packet to network (v4). */ static void @@ -1029,11 +1095,10 @@ _ames_ef_send(u3_ames* sam_u, u3_noun lan, u3_noun pac) u3r_bytes(0, pac_u->len_w, pac_u->hun_y, pac); - u3_head hed_u; - _ames_sift_head(&hed_u, pac_u->hun_y); + _ames_sift_head(&pac_u->hed_u, pac_u->hun_y); pac_u->typ_y = - hed_u.sim_o == c3y ? 0 : - hed_u.req_o == c3y ? 1 : 2; + ( pac_u->hed_u.sim_o == c3y ) ? PACT_AMES : + ( pac_u->hed_u.req_o == c3y ) ? PACT_WAIL : PACT_PURR; u3_noun tag, val; u3x_cell(lan, &tag, &val); @@ -1045,7 +1110,7 @@ _ames_ef_send(u3_ames* sam_u, u3_noun lan, u3_noun pac) c3_assert( c3y == u3a_is_cat(val) ); c3_assert( val < 256 ); - pac_u->imp_y = val; + pac_u->rut_u.imp_y = val; _ames_czar(pac_u); } // non-galaxy lane @@ -1071,7 +1136,7 @@ _ames_ef_send(u3_ames* sam_u, u3_noun lan, u3_noun pac) // otherwise, mutate destination and send packet // else { - pac_u->lan_u = lan_u; + pac_u->rut_u.lan_u = lan_u; _ames_send(pac_u); } } @@ -1173,84 +1238,83 @@ _ames_put_packet(u3_ames* sam_u, _ames_cap_queue(sam_u); } -/* _ames_forward(): forward pac_u onto the (list lane) las, then free pac_u +/* _ames_send_many(): send pac_u on the (list lane) las; retains pac_u */ static void -_ames_forward(u3_panc* pac_u, u3_noun las) +_ames_send_many(u3_pact* pac_u, u3_noun las, c3_o for_o) { u3_ames* sam_u = pac_u->sam_u; + u3_noun tag, dat, lan, t = las; + u3_noun pac = _ames_pact_to_noun(pac_u); - sam_u->sat_u.fow_d++; - if ( 0 == (sam_u->sat_u.fow_d % 1000000) ) { - u3l_log("ames: forwarded %" PRIu64 " total\n", sam_u->sat_u.fow_d); - } + // if forwarding, track metrics + // + if ( for_o ) { + u3_ames* sam_u = pac_u->sam_u; - if ( u3C.wag_w & u3o_verbose ) { - u3_noun sen = u3dc("scot", 'p', u3i_chubs(2, pac_u->bod_u.pre_u.sen_d)); - u3_noun rec = u3dc("scot", 'p', u3i_chubs(2, pac_u->bod_u.pre_u.rec_d)); - c3_c* sen_c = u3r_string(sen); - c3_c* rec_c = u3r_string(rec); - c3_y* pip_y = (c3_y*)&pac_u->ore_u.pip_w; - - u3l_log("ames: forwarding for %s to %s from %d.%d.%d.%d:%d\n", - sen_c, rec_c, - pip_y[0], pip_y[1], pip_y[2], pip_y[3], - pac_u->ore_u.por_s); - - c3_free(sen_c); c3_free(rec_c); - u3z(sen); u3z(rec); - } - - { - u3_noun pac = _ames_serialize_packet(pac_u, c3y); - u3_noun tag, dat, lan, t = las; - - while ( u3_nul != t ) { - u3x_cell(t, &lan, &t); - - // validate lane and skip self if galaxy - // - if ( c3n == u3r_cell(lan, &tag, &dat) ) { - u3l_log("ames: bogus lane\n"); - } - else { - c3_o sen_o = c3y; - c3_d who_d[2]; - - if ( c3y == tag ) { - u3r_chubs(0, 2, who_d, dat); - - if ( (who_d[0] == sam_u->pir_u->who_d[0]) - && (who_d[1] == sam_u->pir_u->who_d[1]) ) - { - sen_o = c3n; - if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: forward skipping self\n"); - } - } - } - - if ( c3y == sen_o ) { - _ames_ef_send(sam_u, u3k(lan), u3k(pac)); - } - } + sam_u->sat_u.fow_d++; + if ( 0 == (sam_u->sat_u.fow_d % 1000000) ) { + u3l_log("ames: forwarded %" PRIu64 " total\n", sam_u->sat_u.fow_d); } - u3z(pac); + if ( u3C.wag_w & u3o_verbose ) { + u3_noun sen = u3dc("scot", 'p', u3i_chubs(2, pac_u->pre_u.sen_d)); + u3_noun rec = u3dc("scot", 'p', u3i_chubs(2, pac_u->pre_u.rec_d)); + c3_c* sen_c = u3r_string(sen); + c3_c* rec_c = u3r_string(rec); + c3_y* pip_y = (c3_y*)&pac_u->rut_u.lan_u.pip_w; + + u3l_log("ames: forwarding for %s to %s from %d.%d.%d.%d:%d\n", + sen_c, rec_c, + pip_y[0], pip_y[1], pip_y[2], pip_y[3], + pac_u->rut_u.lan_u.por_s); + + c3_free(sen_c); c3_free(rec_c); + u3z(sen); u3z(rec); + } } - _ames_panc_free(pac_u); + while ( u3_nul != t ) { + u3x_cell(t, &lan, &t); + + // validate lane and skip self if galaxy + // + if ( c3n == u3r_cell(lan, &tag, &dat) ) { + u3l_log("ames: bogus lane\n"); + } + else { + c3_o sen_o = c3y; + c3_d who_d[2]; + + if ( c3y == tag ) { + u3r_chubs(0, 2, who_d, dat); + + if ( (who_d[0] == sam_u->pir_u->who_d[0]) + && (who_d[1] == sam_u->pir_u->who_d[1]) ) + { + sen_o = c3n; + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("ames: forward skipping self\n"); + } + } + } + + if ( c3y == sen_o ) { + _ames_ef_send(sam_u, u3k(lan), u3k(pac)); + } + } + } + u3z(pac); u3z(las); } - - -/* _ames_lane_scry_cb(): learn lane to forward packet on +/* _ames_lane_scry_cb(): learn lanes to send packet on */ static void _ames_lane_scry_cb(void* vod_p, u3_noun nun) { - u3_panc* pac_u = vod_p; + u3_panc* pan_u = vod_p; + u3_pact* pac_u = pan_u->pac_u; u3_ames* sam_u = pac_u->sam_u; u3_weak las = u3r_at(7, nun); @@ -1263,8 +1327,9 @@ _ames_lane_scry_cb(void* vod_p, u3_noun nun) u3l_log("ames: giving up scry\n"); sam_u->fig_u.see_o = c3n; } - _ames_put_packet(sam_u, _ames_serialize_packet(pac_u, c3n), pac_u->ore_u); - _ames_panc_free(pac_u); + _ames_put_packet(sam_u, + _ames_pact_to_noun(pac_u), + pac_u->rut_u.lan_u); } else { sam_u->sat_u.saw_d = 0; @@ -1272,107 +1337,93 @@ _ames_lane_scry_cb(void* vod_p, u3_noun nun) // cache the scry result for later use // _ames_lane_into_cache(sam_u->lax_p, - u3i_chubs(2, pac_u->bod_u.pre_u.rec_d), + u3i_chubs(2, pac_u->pre_u.rec_d), u3k(las)); - // if there is no lane, drop the packet + // if there are lanes, send the packet on them; otherwise drop it // - if ( u3_nul == las ) { - _ames_panc_free(pac_u); - } - // if there is a lane, forward the packet on it - // - else { - _ames_forward(pac_u, u3k(las)); + if ( u3_nul != las ) { + _ames_send_many(pac_u, u3k(las), pan_u->for_o); } } - + _ames_panc_free(pan_u); u3z(nun); } -/* _ames_try_forward(): try to forward a packet for another ship. +/* _ames_try_send(): try to send a packet to a ship and its sponsors */ static void -_ames_try_forward(u3_ames* sam_u, - u3_lane* lan_u, - u3_head* hed_u, - u3_body* bod_u, - c3_y* hun_y) +_ames_try_send(u3_pact* pac_u, c3_o for_o) { u3_weak lac; + u3_ames* sam_u = pac_u->sam_u; // if the recipient is a galaxy, their lane is always &+~gax // - if ( (256 > bod_u->pre_u.rec_d[0]) - && (0 == bod_u->pre_u.rec_d[1]) ) + if ( (256 > pac_u->pre_u.rec_d[0]) + && (0 == pac_u->pre_u.rec_d[1]) ) { - lac = u3nc(c3y, (c3_y)bod_u->pre_u.rec_d[0]); + lac = u3nc(u3nc(c3y, (c3_y)pac_u->pre_u.rec_d[0]), u3_nul); } // otherwise, try to get the lane from cache // else { - lac = _ames_lane_from_cache(sam_u->lax_p, u3i_chubs(2, bod_u->pre_u.rec_d)); - - // if we don't know the lane, and the scry queue is full, - // just drop the packet - // - //TODO drop oldest item in forward queue in favor of this one. - // ames.c doesn't/shouldn't know about the shape of scry events, - // so can't pluck these out of the event queue like it does in - // _ames_cap_queue. as such, blocked on u3_lord_peek_cancel or w/e. - // - if ( (u3_none == lac) && (1000 < sam_u->sat_u.foq_d) ) { - sam_u->sat_u.fod_d++; - if ( 0 == (sam_u->sat_u.fod_d % 10000) ) { - u3l_log("ames: dropped %" PRIu64 " forwards total\n", - sam_u->sat_u.fod_d); - } - - c3_free(hun_y); - return; - } - // if we know there's no lane, drop the packet - // - else if ( u3_nul == lac ) { - c3_free(hun_y); - return; - } + u3_noun key = u3i_chubs(2, pac_u->pre_u.rec_d); + lac = _ames_lane_from_cache(sam_u->lax_p, key); } - // proceed with forwarding + // if we know there's no lane, drop the packet // - { - // store the packet details for later processing - // - // XX allocates unnecessarily when we know the lane - // - u3_panc* pac_u = c3_calloc(sizeof(*pac_u)); - pac_u->sam_u = sam_u; - pac_u->hed_u = *hed_u; - pac_u->bod_u = *bod_u; - pac_u->ore_u = *lan_u; - pac_u->ptr_v = hun_y; - - if ( 0 != sam_u->pac_u ) { - pac_u->nex_u = sam_u->pac_u; - sam_u->pac_u->pre_u = pac_u; + if ( u3_nul == lac ) { + _ames_pact_free(pac_u); + return; + } + // if we don't know the lane, and the lane scry queue is full, + // just drop the packet + // + //TODO drop oldest item in forward queue in favor of this one. + // ames.c doesn't/shouldn't know about the shape of scry events, + // so can't pluck these out of the event queue like it does in + // _ames_cap_queue. as such, blocked on u3_lord_peek_cancel or w/e. + // + if ( (u3_none == lac) && (1000 < sam_u->sat_u.foq_d) ) { + sam_u->sat_u.fod_d++; + if ( 0 == (sam_u->sat_u.fod_d % 10000) ) { + u3l_log("ames: dropped %" PRIu64 " forwards total\n", + sam_u->sat_u.fod_d); } - sam_u->pac_u = pac_u; - // if we already know the lane, just forward - // - if ( u3_none != lac ) { - _ames_forward(pac_u, lac); - } - // otherwise, there's space in the scry queue; scry the lane out of ames - // - else { + _ames_pact_free(pac_u); + return; + } + + // if we already know the lane, just send + // + if ( u3_none != lac ) { + _ames_send_many(pac_u, lac, for_o); + } + // if forwarding, store the packet details for later processing + // + else { + u3_panc* pan_u = c3_calloc(sizeof(*pan_u)); + pan_u->pac_u = pac_u; + pan_u->for_o = for_o; + + if ( c3y == for_o ) { + if ( 0 != sam_u->pan_u ) { + pan_u->nex_u = sam_u->pan_u; + sam_u->pan_u->pre_u = pan_u; + } + sam_u->pan_u = pan_u; sam_u->sat_u.foq_d++; - u3_noun pax = _lane_scry_path(u3i_chubs(2, bod_u->pre_u.rec_d)); - - u3_pier_peek_last(sam_u->pir_u, u3_nul, c3__ax, - u3_nul, pax, pac_u, _ames_lane_scry_cb); } + + // there's space in the scry queue; scry the lane out of ames + // + u3_noun pax = _lane_scry_path(u3i_chubs(2, pac_u->pre_u.rec_d)); + + u3_pier_peek_last(sam_u->pir_u, u3_nul, c3__ax, + u3_nul, pax, pan_u, _ames_lane_scry_cb); } } @@ -1381,11 +1432,12 @@ _ames_try_forward(u3_ames* sam_u, /* _ames_skip(): decide whether to skip this packet, for rescue */ static c3_o -_ames_skip(u3_body* bod_u) { - if ( bod_u->sen_d[1] == 0 && - ( bod_u->sen_d[0] == 0x743a17a6 - || bod_u->sen_d[0] == 0xea99acb6 - || bod_u->sen_d[0] == 0x10100 +_ames_skip(u3_prel* pre_u) +{ + if ( pre_u->sen_d[1] == 0 && + ( pre_u->sen_d[0] == 0x743a17a6 + || pre_u->sen_d[0] == 0xea99acb6 + || pre_u->sen_d[0] == 0x10100 ) ) { return c3n; } @@ -1395,224 +1447,285 @@ _ames_skip(u3_body* bod_u) { } #endif -static void _fine_got_pack(u3_pact* pac_u, u3_noun fra) +/* _fine_lop(): find beginning of page containing fra_w +*/ +static inline c3_w +_fine_lop(c3_w fra_w) { - pac_u->len_w = u3r_met(3, fra); - pac_u->hun_y = c3_calloc(pac_u->len_w); - - u3r_bytes(0, pac_u->len_w, pac_u->hun_y, fra); - - u3z(fra); + return fra_w - (fra_w % FINE_PAGE) + 1; } -/* _fine_pack_scry_cb(): receive all packets for datum out of fine +/* _fine_pack_scry_cb(): receive packets for datum out of fine */ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) { - u3_pact* pac_u = vod_p; + c3_assert( PACT_PURR == pac_u->typ_y ); u3_ames* sam_u = pac_u->sam_u; - u3_weak pas = u3r_at(7, nun); - u3_noun pax = u3do("stab", u3i_string(pac_u->req_u.pat_c)); + u3_keen* ken_u = &pac_u->pur_u.ken_u; + u3_weak pas = u3r_at(7, nun); if(pas == u3_none) { _ames_pact_free(pac_u); - u3z(pax); u3z(nun); return; } - c3_assert( 1 == pac_u->typ_y ); - u3_weak fra = u3_none; - _fine_put_cache(sam_u, pax, pas); - c3_w cur_w = 1; + u3_noun pax = u3do("stab", u3i_string(ken_u->pat_c)); + c3_w lop_w = _fine_lop(ken_u->fra_w); + _fine_put_cache(sam_u, pax, lop_w, pas); // find requested fragment + u3_weak fra = u3_none; + c3_w fra_w = lop_w; + u3_noun puz = pas; while ( pas != u3_nul ) { - if ( pac_u->req_u.fra_w == cur_w ) { - fra = u3k(u3h(pas)); + if ( ken_u->fra_w == fra_w ) { + fra = u3k(u3h(puz)); + break; } - cur_w++; - pas = u3t(pas); + fra_w++; + puz = u3t(puz); } if ( fra == u3_none ) { - u3l_log("fragment number out of range\n"); + u3l_log("fine: fragment number out of range\n"); + _ames_pact_free(pac_u); + } + else if ( c3y == _fine_sift_meow(&pac_u->pur_u.mew_u, u3k(fra)) ) { + _fine_etch_response(pac_u); + _ames_try_send(pac_u, c3n); + } + else { + u3l_log("fine: bad meow\n"); _ames_pact_free(pac_u); - } else { - _fine_got_pack(pac_u, fra); - _fine_send(pac_u); } - u3z(pas); u3z(nun); + u3z(fra); } - -static void _fine_hear_response(u3_ames* sam_u, - u3_lane lan_u, - c3_w len_w, - c3_y* hun_y) +// TODO: check protocol version +static void +_fine_hear_request(u3_pact* req_u, c3_w cur_w) { - u3_resp res_u; + u3_pact* res_u; + if ( c3n == _fine_sift_wail(req_u, cur_w) ) { + u3l_log("_fine_hear_request bad wail\n"); + _ames_pact_free(req_u); + return; + } + + u3_noun pux = u3i_string(req_u->wal_u.ken_u.pat_c); + u3_noun pat = u3dc("rush", pux, u3v_wish("stap")); + if ( u3_nul == pat ) { + u3l_log("fine: bad request\n"); + _ames_pact_free(req_u); + u3z(pat); + return; + } + + // fill in the parts of res_u that we know from req_u + { + res_u = c3_calloc(sizeof(*res_u)); + res_u->sam_u = req_u->sam_u; + res_u->typ_y = PACT_PURR; + res_u->rut_u.lan_u = req_u->rut_u.lan_u; + + // copy header, swapping sender and receiver + // + res_u->hed_u = (u3_head) { + .req_o = c3n, + .sim_o = c3n, + .ver_y = req_u->hed_u.ver_y, + .sac_y = req_u->hed_u.rac_y, + .rac_y = req_u->hed_u.sac_y, + .mug_l = 0, // filled in later + .rel_o = c3n + }; + + // copy prelude, swapping sender and receiver + // + res_u->pre_u = (u3_prel) { + .sic_y = req_u->pre_u.ric_y, + .ric_y = req_u->pre_u.sic_y, + .sen_d = { req_u->pre_u.rec_d[0], req_u->pre_u.rec_d[1] }, + .rec_d = { req_u->pre_u.sen_d[0], req_u->pre_u.sen_d[1] }, + .rog_d = 0 + }; + + // copy unsigned request payload into response body + // + res_u->pur_u = (u3_purr) { + .ken_u = req_u->wal_u.ken_u, + .mew_u = {0} // filled in later + }; + + // copy path string from request into response body + { + c3_s len_s = req_u->wal_u.ken_u.len_s; + res_u->pur_u.ken_u.pat_c = c3_calloc(len_s + 1); + memcpy(res_u->pur_u.ken_u.pat_c, req_u->wal_u.ken_u.pat_c, len_s); + } + // free incoming request + // + _ames_pact_free(req_u); + } + + // if receiver is a galaxy, note that in res_u + // + if ( res_u->pre_u.rec_d[0] < 256 + && res_u->pre_u.rec_d[1] == 0 ) + { + res_u->rut_u.imp_y = res_u->pre_u.rec_d[0]; + } + + // look up request in scry cache + // + u3_noun key = u3nc(u3k(pat), u3i_word(res_u->pur_u.ken_u.fra_w)); + u3_weak cac = u3h_git(res_u->sam_u->fin_s.sac_p, key); + if ( u3_none == cac ) { + // cache miss, scry into arvo for a page of packets + // + c3_w lop_w = _fine_lop(res_u->pur_u.ken_u.fra_w); + u3_noun pax = + u3nc(c3__fine, + u3nq(c3__hunk, + u3dc("scot", c3__ud, lop_w), + u3dc("scot", c3__ud, FINE_PAGE), + u3k(u3t(pat)))); + + u3_pier_peek_last(res_u->sam_u->car_u.pir_u, u3_nul, c3__ax, u3_nul, + pax, res_u, _fine_pack_scry_cb); + + } + // cache hit, fill in response meow and send + // + else if ( c3y == _fine_sift_meow(&res_u->pur_u.mew_u, u3k(cac)) ) { + _fine_etch_response(res_u); + _ames_try_send(res_u, c3n); + } + else { + u3l_log("_fine_hear_request meow bad\n"); + } + + u3z(key); + u3z(pat); +} + +// TODO: check protocol version +static void +_fine_hear_response(u3_pact* pac_u, c3_w cur_w) +{ u3_noun wir = u3nc(c3__fine, u3_nul); - c3_w num_w = res_u.num_w; - c3_w fra_w = res_u.fra_w; - u3_noun cad = u3nt(c3__hear, - u3nc(c3n, u3_ames_encode_lane(lan_u)), - u3i_bytes(len_w, hun_y)); + u3nc(c3n, u3_ames_encode_lane(pac_u->rut_u.lan_u)), + u3i_bytes(pac_u->len_w, pac_u->hun_y)); u3_ovum* ovo_u = u3_ovum_init(0, c3__ames, u3k(wir), u3k(cad)); - u3_auto_plan(&sam_u->car_u, ovo_u); + u3_auto_plan(&pac_u->sam_u->car_u, ovo_u); u3z(cad); u3z(wir); } - -static void _fine_hear_request(u3_ames* sam_u, - u3_lane lan_u, - c3_w len_w, - c3_y* hun_y) +static void +_ames_hear_ames(u3_pact* pac_u, c3_w cur_w) { - u3_head hed_u; - c3_assert ( c3n == _ames_sift_head(&hed_u, hun_y)); - // TODO: check mug + // ensure the protocol version matches ours + // + // XX rethink use of [fit_o] here and elsewhere + // + u3_ames* sam_u = pac_u->sam_u; + if ( (c3y == sam_u->fig_u.fit_o) + && (sam_u->ver_y != pac_u->hed_u.ver_y) ) + { + sam_u->sat_u.vet_d++; + if ( 0 == (sam_u->sat_u.vet_d % 100000) ) { + u3l_log("ames: %" PRIu64 " dropped for version mismatch\n", + sam_u->sat_u.vet_d); + } - u3_requ req_u; - - // skip past header - len_w -= 4; - hun_y += 4; - - c3_assert( c3y == _fine_sift_requ(&hed_u, &req_u, len_w, hun_y)); - - u3_noun rul = u3v_wish("stap"); - u3_noun pat = u3dc("rush", u3i_string(req_u.pat_c), rul); - if ( u3_nul == pat ) { - u3l_log("bad request\n"); - - u3z(pat); + _ames_pact_free(pac_u); return; } - u3_noun key = u3nc(u3k(u3t(pat)), u3i_word(req_u.fra_w)); - - u3_weak cac = u3h_git(sam_u->fin_s.sac_p, key); - - u3_pact* pac_u = c3_calloc(sizeof(*pac_u)); - - pac_u->sam_u = sam_u; - pac_u->typ_y = 1; - - memcpy(&pac_u->hed_u, &hed_u, sizeof(u3_head)); - memcpy(&pac_u->req_u, &req_u, sizeof(u3_requ)); - - memcpy(&pac_u->lan_u, &lan_u, sizeof(u3_lane)); - - if ( pac_u->req_u.pre_u.sen_d[0] < 256 - && pac_u->req_u.pre_u.sen_d[1] == 0 ) { - pac_u->imp_y = pac_u->req_u.pre_u.sen_d[0]; + // otherwise, inject the packet as an event + // + else { + u3_noun msg = u3i_bytes(pac_u->len_w, pac_u->hun_y); +#ifdef AMES_SKIP + if ( _ames_skip(&pac_u->pre_u) == c3y ) { + u3z(msg); + } + else { +#endif + _ames_put_packet(sam_u, msg, pac_u->rut_u.lan_u); +#ifdef AMES_SKIP + } +#endif + _ames_pact_free(pac_u); } - - if ( u3_none == cac ) { - // cache miss - u3_noun pax = u3nt(u3i_string("fine"), - u3i_string("message"), - u3k(u3t(pat))); - - u3_pier_peek_last(sam_u->car_u.pir_u, u3_nul, c3__ax, u3_nul, - pax, pac_u, _fine_pack_scry_cb); - - } else { - _fine_got_pack(pac_u, u3k(cac)); - _fine_send(pac_u); - } - - //u3z(pat); - //u3z(rul); } - - -/* _fine_hear(): hear a (potential) packet, dispatch appropriately - */ -static void _fine_hear(u3_ames* sam_u, - u3_lane lan_u, - c3_w len_w, - c3_y* hun_y) +static c3_o +_ames_check_mug(u3_pact* pac_u) { - u3_head hed_u; - if ( c3y == _ames_sift_head(&hed_u, hun_y) ) { - c3_free(hun_y); - } else if ( c3n == hed_u.req_o ) { - _fine_hear_request(sam_u, lan_u, len_w, hun_y); - } else { - _fine_hear_response(sam_u, lan_u, len_w, hun_y); - } + c3_w rog_w = HEAD_SIZE + _ames_origin_size(&pac_u->hed_u); + c3_l mug_l = u3r_mug_bytes(pac_u->hun_y + rog_w, + pac_u->len_w - rog_w); + return ( + ((mug_l & 0xfffff) == (pac_u->hed_u.mug_l & 0xfffff)) + ? c3y : c3n); } - - -static void _log_head(u3_head* hed_u) -{ - u3l_log("-- HEAADER --\n"); - u3l_log("is request: %u\n", hed_u->req_o); - u3l_log("is ames: %u\n", hed_u->sim_o); - u3l_log("protocol ames: %u\n", hed_u->ver_y); - u3l_log("sender class: %u\n", hed_u->sac_y); - u3l_log("recevr class: %u\n", hed_u->rac_y); - u3l_log("\n"); -} - - - - static void -_fine_request(u3_ames* sam_u, - u3_noun lan, - u3_noun req) +_ames_try_forward(u3_pact* pac_u) { - - u3_pact* pac_u = c3_calloc(sizeof(*pac_u)); - u3_head* hed_u = c3_calloc(sizeof(*hed_u)); - u3_requ* req_u = c3_calloc(sizeof(*req_u)); - - c3_w req_w = u3r_met(3, req); - c3_y* req_y = c3_calloc(req_w); - u3r_bytes(0, req_w, req_y, req); - //_log_bytes(req_y, 4); - pac_u->hun_y = req_y; - pac_u->len_w = req_w; - - _ames_sift_head(hed_u, req_y); - req_y += 4; - req_w -= 4; - - _fine_sift_requ(hed_u, req_u, req_w, req_y); - - pac_u->typ_y = 1; - pac_u->sam_u = sam_u; - + // insert origin lane if needed + // + if ( c3n == pac_u->hed_u.rel_o + && !( ( 256 > pac_u->pre_u.sen_d[0] ) + && ( 0 == pac_u->pre_u.sen_d[1] ) ) ) { - u3_noun tag, val; - u3x_cell(lan, &tag, &val); - if(tag == 0) { - pac_u->imp_y = req_u->pre_u.rec_d[0]; - _ames_czar(pac_u); - } else { - u3_lane lan_u = u3_ames_decode_lane(val); - pac_u->lan_u.pip_w = lan_u.pip_w; - pac_u->lan_u.por_s = lan_u.por_s; - _ames_send(pac_u); - } + c3_y* old_y; + c3_w old_w; + + pac_u->hed_u.rel_o = c3y; + pac_u->pre_u.rog_d = u3_ames_lane_to_chub(pac_u->rut_u.lan_u); + + old_w = pac_u->len_w; + old_y = pac_u->hun_y; + + pac_u->len_w += 6; + pac_u->hun_y = c3_calloc(pac_u->len_w); + + _ames_etch_head(&pac_u->hed_u, pac_u->hun_y); + memcpy(pac_u->hun_y + HEAD_SIZE + 6, + old_y + HEAD_SIZE, + old_w - HEAD_SIZE); + + c3_free(old_y); } + + _ames_try_send(pac_u, c3y); } /* _ames_hear(): parse a (potential) packet, dispatch appropriately. + + packet filtering needs to revised for two protocol-change scenarios + + - packets using old protocol versions from our sponsees + these must be let through, and this is a transitive condition; + they must also be forwarded where appropriate + they can be validated, as we know their semantics + + - packets using newer protocol versions + these should probably be let through, or at least + trigger printfs suggesting upgrade. + they cannot be filtered, as we do not know their semantics */ static void _ames_hear(u3_ames* sam_u, @@ -1620,29 +1733,12 @@ _ames_hear(u3_ames* sam_u, c3_w len_w, c3_y* hun_y) { + u3_pact* pac_u; + c3_w pre_w; + c3_w cur_w = 0; // cursor: how many bytes we've read from hun_y - // TODO: move from stack to heap to avoid reparsing - u3_pact* pac_u = c3_calloc(sizeof(*pac_u)); - - // XX packet filtering needs to revised for two protocol-change scenarios - // - // - packets using old protocol versions from our sponsees - // these must be let through, and this is a transitive condition; - // they must also be forwarded where appropriate - // they can be validated, as we know their semantics - // - // - packets using newer protocol versions - // these should probably be let through, or at least - // trigger printfs suggesting upgrade. - // they cannot be filtered, as we do not know their semantics - // - - // unpack header, ensuring buffer is large enough - // - // - c3_o is_ames_o = _ames_sift_head(&pac_u->hed_u, hun_y); - - if (4 > len_w) { + // make sure packet is big enough to have a header + if (HEAD_SIZE > len_w) { sam_u->sat_u.hed_d++; if ( 0 == (sam_u->sat_u.hed_d % 100000) ) { u3l_log("ames: %" PRIu64 " dropped, failed to read header\n", @@ -1653,98 +1749,81 @@ _ames_hear(u3_ames* sam_u, return; } - u3_prel pre_u; + pac_u = c3_calloc(sizeof(*pac_u)); + pac_u->sam_u = sam_u; + pac_u->len_w = len_w; + pac_u->hun_y = hun_y; + pac_u->rut_u.lan_u = *lan_u; + cur_w = 0; - // we always overwrite this later - _ames_sift_prelude(&pac_u->hed_u, &pac_u->bod_u.pre_u, len_w - 4, hun_y + 4); - { - u3_noun her = u3i_chubs(2, pac_u->bod_u.pre_u.sen_d); - u3_noun las = u3_ames_encode_lane(*lan_u); - - _ames_lane_into_cache(sam_u->lax_p, her, las); - } - - if (c3n == is_ames_o) { - _fine_hear(sam_u, *lan_u, len_w, hun_y); - return; - } - - // ensure the protocol version matches ours + // parse the header // - // XX rethink use of [fit_o] here and elsewhere + _ames_sift_head(&pac_u->hed_u, hun_y); + cur_w += HEAD_SIZE; + + pac_u->typ_y = ( c3y == pac_u->hed_u.sim_o ) ? PACT_AMES : + ( c3y == pac_u->hed_u.req_o ) ? PACT_WAIL : PACT_PURR; + + + // check contents match mug in header // - if ( (c3y == sam_u->fig_u.fit_o) - && (sam_u->ver_y != pac_u->hed_u.ver_y) ) - { - sam_u->sat_u.vet_d++; - if ( 0 == (sam_u->sat_u.vet_d % 100000) ) { - u3l_log("ames: %" PRIu64 " dropped for version mismatch\n", - sam_u->sat_u.vet_d); - } - - c3_free(hun_y); - _ames_pact_free(pac_u); - return; - } - - { - c3_w bod_w = len_w - 4; - c3_y* bod_y = hun_y + 4; - - // unpack and validate the body - // - if ( (c3n == _ames_sift_body(&pac_u->hed_u, &pac_u->bod_u, bod_w, bod_y)) ) { - sam_u->sat_u.bod_d++; - if ( 0 == (sam_u->sat_u.bod_d % 100) ) { - u3l_log("ames: %" PRIu64 " dropped, failed to read body\n", - sam_u->sat_u.bod_d); - } - - c3_free(hun_y); - _ames_pact_free(pac_u); - return; - } - - // ensure the mug is valid - // - if ( pac_u->bod_u.mug_l != pac_u->hed_u.mug_l ) { + if ( c3n == _ames_check_mug(pac_u) ) { sam_u->sat_u.mut_d++; if ( 0 == (sam_u->sat_u.mut_d % 100000) ) { u3l_log("ames: %" PRIu64 " dropped for invalid mug\n", sam_u->sat_u.mut_d); } - - c3_free(hun_y); - _ames_pact_free(pac_u); - return; - } + _ames_pact_free(pac_u); + return; } - // if we can scry, + // check that packet is big enough for prelude + // + pre_w = _ames_prel_size(&pac_u->hed_u); + if ( len_w < cur_w + pre_w ) { + sam_u->sat_u.pre_d++; + u3l_log("ames: %" PRIu64 " dropped, failed to read prelude\n", + sam_u->sat_u.pre_d); + _ames_pact_free(pac_u); + return; + } + + // parse prelude + // + _ames_sift_prel(&pac_u->hed_u, &pac_u->pre_u, pac_u->hun_y + cur_w); + cur_w += pre_w; + + // if we can scry for lanes, // and we are not the recipient, // we might want to forward statelessly // if ( 0 && (c3y == sam_u->fig_u.see_o) - && ( (pac_u->bod_u.pre_u.rec_d[0] != sam_u->pir_u->who_d[0]) - || (pac_u->bod_u.pre_u.rec_d[1] != sam_u->pir_u->who_d[1]) ) ) + && ( (pac_u->pre_u.rec_d[0] != sam_u->pir_u->who_d[0]) + || (pac_u->pre_u.rec_d[1] != sam_u->pir_u->who_d[1]) ) ) { - _ames_try_forward(sam_u, lan_u, &pac_u->hed_u, &pac_u->bod_u, hun_y); + _ames_try_forward(pac_u); } - // otherwise, inject the packet as an event - // else { - u3_noun msg = u3i_bytes(len_w, hun_y); - c3_free(hun_y); -#ifdef AMES_SKIP - if (_ames_skip(&bod_u) == c3y ) { - u3z(msg); + // enter protocol-specific packet handling + // + switch ( pac_u->typ_y ) { + case PACT_WAIL: { + _fine_hear_request(pac_u, cur_w); + } break; + + case PACT_PURR: { + _fine_hear_response(pac_u, cur_w); + } break; + + case PACT_AMES: { + _ames_hear_ames(pac_u, cur_w); + } break; + + default: { + u3l_log("ames_hear: bad packet type %d\n", pac_u->typ_y); + u3_pier_bail(u3_king_stub()); + } } - else { -#endif - _ames_put_packet(sam_u, msg, *lan_u); -#ifdef AMES_SKIP - } -#endif } } @@ -1991,6 +2070,7 @@ _ames_kick_newt(u3_ames* sam_u, u3_noun tag, u3_noun dat) ret_o = c3n; } break; + case c3__hoot: case c3__send: { u3_noun lan = u3k(u3h(dat)); u3_noun pac = u3k(u3t(dat)); @@ -2002,13 +2082,6 @@ _ames_kick_newt(u3_ames* sam_u, u3_noun tag, u3_noun dat) _ames_ef_turf(sam_u, u3k(dat)); ret_o = c3y; } break; - - case c3__hoot: { - u3_noun lan = u3k(u3h(dat)); - u3_noun pac = u3k(u3t(dat)); - _fine_request(sam_u, lan, pac); - ret_o = c3y; - } break; } u3z(tag); u3z(dat); @@ -2077,11 +2150,11 @@ _ames_exit_cb(uv_handle_t* had_u) { u3_ames* sam_u = had_u->data; - u3_panc* pac_u = sam_u->pac_u; - while (0 != pac_u) { - u3_panc* nex_u = pac_u->nex_u; - _ames_panc_free(pac_u); - pac_u = nex_u; + u3_panc* pan_u = sam_u->pan_u; + while (0 != pan_u) { + u3_panc* nex_u = pan_u->nex_u; + _ames_panc_free(pan_u); + pan_u = nex_u; } u3h_free(sam_u->lax_p);