From d1c97ef7e7d3e70b0daefe4e29127c0ba432fcee Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Thu, 13 Jan 2022 12:46:47 -0600 Subject: [PATCH 01/21] urbit: add ames prelude struct --- pkg/urbit/vere/io/ames.c | 218 ++++++++++++++++++++++++--------------- 1 file changed, 137 insertions(+), 81 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 18d2c8c61..4b6101933 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -72,16 +72,24 @@ c3_l mug_l; // truncated mug hash of u3_body c3_o rel_o; // relayed? } u3_head; + +/* u3_prel: ames/fine packet prelude +*/ + typedef struct _u3_prel { + c3_y sic_y; // sender life tick + c3_y ric_y; // receiver life tick + c3_d sen_d[2]; // sender + c3_d rec_d[2]; // receiver + c3_d rog_d; // origin lane (optional) + } u3_prel; /* TODO: request response bodies for scry */ /* u3_requ: fine packet request */ typedef struct _u3_requ { - c3_y sig_y[64]; // requester signature - c3_w lyf_w; // requester life - c3_d her_d[2]; // requester addres - c3_w fra_w; // fragment number - c3_d hos_d[2]; // host address - c3_s len_s; // path length + 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; @@ -117,7 +125,7 @@ c3_w len_w; // packet contents u3_lane lan_u; // recipient lane u3_ames* sam_u; // ames backpointer - union { + union { u3_resp* res_u; u3_reqp* req_u; u3_pact* pac_u; @@ -127,14 +135,10 @@ /* u3_body: ames packet body */ typedef struct _u3_body { - c3_d sen_d[2]; // sender - c3_d rec_d[2]; // receiver - c3_y sic_y; // sender life tick - c3_y ric_y; // receiver life tick - c3_s con_s; // content size - c3_y* con_y; // content - c3_d rog_d; // origin lane (optional) - c3_l mug_l; // checksum + u3_prel pre_u; // prelude + c3_s con_s; // content size + c3_y* con_y; // content + c3_l mug_l; // checksum } u3_body; /* u3_panc: deconstructed incoming packet @@ -294,7 +298,42 @@ _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 +*/ +static c3_y +_ames_sift_prelude(u3_head* hed_u, + u3_prel* pre_u, + c3_w len_w, + c3_y* pre_y) +{ + c3_y rog_y, sen_y, rec_y, len_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; + + pre_u->sic_y = pre_y[0] & 0xf; + pre_u->ric_y = pre_y[0] & 0xf0; + + _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) { + c3_y rag_y[8] = {0}; + memcpy(rag_y, pre_y + 1 + sen_y + rec_y, rog_y); + pre_u->rog_d = _ames_chub_bytes(rag_y); + } + else { + pre_u->rog_d = 0; + } + return len_y; +} + + + /* _fine_sift_requ(): parse request body, returning success + * TODO: bring up to date */ static c3_o _fine_sift_requ(u3_head* hed_u, @@ -309,14 +348,8 @@ _fine_sift_requ(u3_head* hed_u, memcpy(req_u->sig_y, req_y, 64); req_y += 64; - req_u->lyf_w = ( - (req_y[0] << 0x18) - | (req_y[1] << 0x10) - | (req_y[2] << 0x8) - | (req_y[3] << 0x0)); req_y += 4; - _ames_ship_to_chubs(req_u->her_d, hed_u->sac_y, req_y); req_y += hed_u->sac_y; req_u->fra_w = ( @@ -326,8 +359,8 @@ _fine_sift_requ(u3_head* hed_u, | (req_y[3] << 0x0)); req_y += 4; - _ames_ship_to_chubs(req_u->hos_d, hed_u->rac_y, req_y); - req_y += hed_u->rac_y; + //_ames_ship_to_chubs(req_u->hos_d, hed_u->rac_y, req_y); + //req_y += hed_u->rac_y; req_u->len_s = c3_min(384, @@ -411,42 +444,19 @@ _ames_sift_body(u3_head* hed_u, c3_w len_w, c3_y* bod_y) { - c3_y rog_y, sen_y, rec_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; - rog_y = ( c3y == hed_u->rel_o )? 6 : 0; + c3_y pre_y = _ames_sift_prelude(hed_u, &bod_u->pre_u, len_w, bod_y); - sen_y = 2 << hed_u->sac_y; - rec_y = 2 << hed_u->rac_y; - - if ( (1 + sen_y + rec_y + rog_y) >= len_w ) { + if (pre_y >= len_w ) { return c3n; } else { - c3_y* gob_y; - c3_s gob_s; - - if ( rog_y) { - c3_y rag_y[8] = {0}; - memcpy(rag_y, bod_y, rog_y); - bod_u->rog_d = _ames_chub_bytes(rag_y); - } - else { - bod_u->rog_d = 0; - } - - gob_y = bod_y + rog_y; - gob_s = len_w - rog_y; - bod_u->mug_l = u3r_mug_bytes(gob_y, gob_s) & 0xfffff; - bod_u->sic_y = gob_y[0] & 0xf; - bod_u->ric_y = (gob_y[0] >> 4) & 0xf; - - _ames_ship_to_chubs(bod_u->sen_d, sen_y, gob_y + 1); - _ames_ship_to_chubs(bod_u->rec_d, rec_y, gob_y + 1 + sen_y); - - bod_u->con_s = gob_s - 1 - sen_y - rec_y; - bod_u->con_y = gob_y + 1 + sen_y + rec_y; + bod_u->con_y = gob_y + 4; return c3y; } @@ -475,6 +485,63 @@ _ames_etch_head(u3_head* hed_u, c3_y buf_y[4]) buf_y[3] = (hed_w >> 24) & 0xff; } +/* _ames_etch_prelude(): serialize packet prelude +*/ +static c3_y +_ames_etch_prelude(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; + + + // 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 ) { + c3_y rag_y[8] = {0}; + _ames_bytes_chub(rag_y, pre_u->rog_d); + memcpy(buf_y, rag_y, rog_y); + } + 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; // TODO: check byte order + _ames_ship_of_chubs(res_u->hos_d, sen_y, pac_y + 4); + + *(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 @@ -484,33 +551,21 @@ _ames_etch_pack(u3_head* hed_u, { 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_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_malloc(len_w); // output buf c3_y* bod_y = pac_y + 4; // body cursor - c3_y* gob_y = bod_y + rog_y; // after origin // serialize the head // _ames_etch_head(hed_u, pac_y); - // serialize the origin, if present - // - if ( rog_y ) { - c3_y rag_y[8] = {0}; - _ames_bytes_chub(rag_y, bod_u->rog_d); - memcpy(bod_y, rag_y, rog_y); - } + 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 // serialize the body - // - gob_y[0] = (bod_u->sic_y & 0xf) ^ ((bod_u->ric_y & 0xf) << 4); - - _ames_ship_of_chubs(bod_u->sen_d, sen_y, gob_y + 1); - _ames_ship_of_chubs(bod_u->rec_d, rec_y, gob_y + 1 + sen_y); - - memcpy(gob_y + 1 + sen_y + rec_y, bod_u->con_y, bod_u->con_s); + memcpy(gob_y, bod_u->con_y, bod_u->con_s); *out_y = pac_y; return len_w; @@ -660,11 +715,11 @@ _ames_serialize_packet(u3_panc* pac_u, c3_o dop_o) // if ( c3y == dop_o && c3n == pac_u->hed_u.rel_o - && !( ( 256 > pac_u->bod_u.sen_d[0] ) - && ( 0 == pac_u->bod_u.sen_d[1] ) ) ) + && !( ( 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.rog_d = u3_ames_lane_to_chub(pac_u->ore_u); + pac_u->bod_u.pre_u.rog_d = u3_ames_lane_to_chub(pac_u->ore_u); } // serialize the packet @@ -1051,8 +1106,8 @@ _ames_forward(u3_panc* pac_u, u3_noun las) } if ( u3C.wag_w & u3o_verbose ) { - u3_noun sen = u3dc("scot", 'p', u3i_chubs(2, pac_u->bod_u.sen_d)); - u3_noun rec = u3dc("scot", 'p', u3i_chubs(2, pac_u->bod_u.rec_d)); + 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; @@ -1136,7 +1191,7 @@ _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.rec_d), + u3i_chubs(2, pac_u->bod_u.pre_u.rec_d), u3k(las)); // if there is no lane, drop the packet @@ -1167,15 +1222,15 @@ _ames_try_forward(u3_ames* sam_u, // if the recipient is a galaxy, their lane is always &+~gax // - if ( (256 > bod_u->rec_d[0]) - && (0 == bod_u->rec_d[1]) ) + if ( (256 > bod_u->pre_u.rec_d[0]) + && (0 == bod_u->pre_u.rec_d[1]) ) { - lac = u3nc(c3y, (c3_y)bod_u->rec_d[0]); + lac = u3nc(c3y, (c3_y)bod_u->pre_u.rec_d[0]); } // otherwise, try to get the lane from cache // else { - lac = _ames_lane_from_cache(sam_u->lax_p, u3i_chubs(2, bod_u->rec_d)); + 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 @@ -1233,7 +1288,7 @@ _ames_try_forward(u3_ames* sam_u, else { sam_u->sat_u.foq_d++; u3_noun pax = u3nq(u3i_string("peers"), - u3dc("scot", 'p', u3i_chubs(2, bod_u->rec_d)), + u3dc("scot", 'p', u3i_chubs(2, bod_u->pre_u.rec_d)), u3i_string("forward-lane"), u3_nul); u3_pier_peek_last(sam_u->pir_u, u3_nul, c3__ax, @@ -1468,6 +1523,7 @@ _ames_hear(u3_ames* sam_u, // ensure the mug is valid // + u3l_log("bod: %ux, hed: %ux\n", hed_u.mug_l, bod_u.mug_l); if ( bod_u.mug_l != hed_u.mug_l ) { sam_u->sat_u.mut_d++; if ( 0 == (sam_u->sat_u.mut_d % 100000) ) { @@ -1485,8 +1541,8 @@ _ames_hear(u3_ames* sam_u, // we might want to forward statelessly // if ( 0 && (c3y == sam_u->fig_u.see_o) - && ( (bod_u.rec_d[0] != sam_u->pir_u->who_d[0]) - || (bod_u.rec_d[1] != sam_u->pir_u->who_d[1]) ) ) + && ( (bod_u.pre_u.rec_d[0] != sam_u->pir_u->who_d[0]) + || (bod_u.pre_u.rec_d[1] != sam_u->pir_u->who_d[1]) ) ) { _ames_try_forward(sam_u, lan_u, &hed_u, &bod_u, hun_y); } From c808657e2a7d50b23b7945c324c31feccbd1b654 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Fri, 21 Jan 2022 11:44:21 -0600 Subject: [PATCH 02/21] wip --- .husky/post-checkout | 3 + .husky/post-commit | 3 + .husky/post-merge | 3 + .husky/pre-push | 3 + Makefile | 4 +- nix/overlays/m1.nix | 28 ++++++ pkg/urbit/configure | 5 + pkg/urbit/include/c/motes.h | 2 + pkg/urbit/tests/ames_tests.c | 76 +++++++++++++++ pkg/urbit/vere/io/ames.c | 176 +++++++++++++++++++---------------- shell.nix | 2 +- test | 2 + 12 files changed, 226 insertions(+), 81 deletions(-) create mode 100755 .husky/post-checkout create mode 100755 .husky/post-commit create mode 100755 .husky/post-merge create mode 100755 .husky/pre-push create mode 100644 nix/overlays/m1.nix create mode 100644 test diff --git a/.husky/post-checkout b/.husky/post-checkout new file mode 100755 index 000000000..cab40f264 --- /dev/null +++ b/.husky/post-checkout @@ -0,0 +1,3 @@ +#!/bin/sh +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting .git/hooks/post-checkout.\n"; exit 2; } +git lfs post-checkout "$@" diff --git a/.husky/post-commit b/.husky/post-commit new file mode 100755 index 000000000..9443f4161 --- /dev/null +++ b/.husky/post-commit @@ -0,0 +1,3 @@ +#!/bin/sh +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting .git/hooks/post-commit.\n"; exit 2; } +git lfs post-commit "$@" diff --git a/.husky/post-merge b/.husky/post-merge new file mode 100755 index 000000000..828b70891 --- /dev/null +++ b/.husky/post-merge @@ -0,0 +1,3 @@ +#!/bin/sh +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting .git/hooks/post-merge.\n"; exit 2; } +git lfs post-merge "$@" diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 000000000..81a9cc639 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,3 @@ +#!/bin/sh +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting .git/hooks/pre-push.\n"; exit 2; } +git lfs pre-push "$@" diff --git a/Makefile b/Makefile index a06eac1c8..3b4795e96 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ .PHONY: build build-all install cross release test pills ropsten-pills clean build: - nix-build -A urbit -A herb --no-out-link + nix-build -A urbit --no-out-link install: - nix-env -f . -iA urbit -iA herb + nix-env -f . -iA urbit release: sh/release diff --git a/nix/overlays/m1.nix b/nix/overlays/m1.nix new file mode 100644 index 000000000..857cb7504 --- /dev/null +++ b/nix/overlays/m1.nix @@ -0,0 +1,28 @@ +final: prev: + +let + + isMusl = prev.stdenv.hostPlatform.isMusl; + + optionalList = xs: if xs == null then [ ] else xs; + + overrideStdenv = pkg: pkg.override { stdenv = prev.gcc9Stdenv; }; + +in prev.lib.optionalAttrs isMusl { + libsigsegv = prev.libsigsegv.overrideAttrs (attrs: { + preConfigure = (attrs.preConfigure or "") + '' + sed -i 's/^CFG_FAULT=$/CFG_FAULT=fault-linux-i386.h/' configure + ''; + }); + + secp256k1 = prev.secp256k1.overrideAttrs (attrs: { + nativeBuildInputs = (attrs.nativeBuildInputs or [ ]) + ++ [ prev.buildPackages.stdenv.cc ]; + }); + + rhash = overrideStdenv prev.rhash; + + numactl = overrideStdenv prev.numactl; + + lmdb = overrideStdenv prev.lmdb; +} diff --git a/pkg/urbit/configure b/pkg/urbit/configure index ab5b3a3df..b7efcc19e 100755 --- a/pkg/urbit/configure +++ b/pkg/urbit/configure @@ -97,6 +97,11 @@ case $(tr A-Z a-z <<< $cpu) in defmacro U3_OS_ENDIAN_little 1 defmacro U3_CPU_aarch64 1 ;; + arm64) + defmacro U3_OS_ENDIAN_little 1 + defmacro U3_CPU_aarch64 1 + ;; + *) echo "Unknown or unsupported CPU: '$cpu'" >&2 exit 1 diff --git a/pkg/urbit/include/c/motes.h b/pkg/urbit/include/c/motes.h index 89880d3bf..b5a3a50ab 100644 --- a/pkg/urbit/include/c/motes.h +++ b/pkg/urbit/include/c/motes.h @@ -548,6 +548,7 @@ # define c3__homp c3_s4('h','o','m','p') # define c3__hook c3_s4('h','o','o','k') # define c3__hoon c3_s4('h','o','o','n') +# define c3__hoot c3_s4('h','o','o','t') # define c3__hop c3_s3('h','o','p') # define c3__hosc c3_s4('h','o','s','c') # define c3__hose c3_s4('h','o','s','e') @@ -914,6 +915,7 @@ # define c3__punk c3_s4('p','u','n','k') # define c3__punt c3_s4('p','u','n','t') # define c3__pure c3_s4('p','u','r','e') +# define c3__purr c3_s4('p','u','r','r') # define c3__push c3_s4('p','u','s','h') # define c3__put c3_s3('p','u','t') # define c3__quac c3_s4('q','u','a','c') diff --git a/pkg/urbit/tests/ames_tests.c b/pkg/urbit/tests/ames_tests.c index 69ed7b9b9..392fdf5fd 100644 --- a/pkg/urbit/tests/ames_tests.c +++ b/pkg/urbit/tests/ames_tests.c @@ -1,6 +1,37 @@ #include "all.h" #include "vere/vere.h" +// ripped TODO: reemove +/*u3_head: ames or fine packet header +*/ + typedef struct _u3_head { + c3_o req_o; // is request (fine only) + c3_o sim_o; // is ames protocol? + c3_y ver_y; // protocol version + c3_y sac_y; // sender class + c3_y rac_y; // receiver class + c3_l mug_l; // truncated mug hash of u3_body + c3_o rel_o; // relayed? + } u3_head; + +/* u3_prel: ames/fine packet prelude +*/ + typedef struct _u3_prel { + c3_y sic_y; // sender life tick + c3_y ric_y; // receiver life tick + c3_d sen_d[2]; // sender + c3_d rec_d[2]; // receiver + c3_d rog_d; // origin lane (optional) + } 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 + } u3_body; + + /* _setup(): prepare for tests. */ static void @@ -30,6 +61,51 @@ _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; + + 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 4b6101933..5385c4b8e 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -78,8 +78,8 @@ typedef struct _u3_prel { c3_y sic_y; // sender life tick c3_y ric_y; // receiver life tick - c3_d sen_d[2]; // sender - c3_d rec_d[2]; // receiver + c3_d sen_d[2]; // sender/requester + c3_d rec_d[2]; // receiver/responder c3_d rog_d; // origin lane (optional) } u3_prel; @@ -101,17 +101,16 @@ /* u3_resp: fine packet response */ typedef struct _u3_resp { + u3_prel pre_u; // request: - c3_w fra_w; // fragment number - c3_d hos_d[2]; // host address - c3_s len_s; // path length - c3_c* pat_c; // path as ascii + 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 lyf_w; // host life - c3_w num_w; // number of fragments - c3_s siz_s; // datum size - c3_y* dat_y; // datum (0 if null 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; @@ -341,17 +340,17 @@ _fine_sift_requ(u3_head* hed_u, c3_w len_w, c3_y* req_y) { - c3_w rem_w = (64 + 4 + hed_u->sac_y + 4 + hed_u->rac_y + 2); + c3_y pre_y = _ames_sift_prelude(hed_u, &req_u->pre_u, len_w, req_y); + + req_y += pre_y; + + c3_w rem_w = (64 + 4 + 2 + pre_y); if(rem_w > len_w) { return c3n; } memcpy(req_u->sig_y, req_y, 64); req_y += 64; - req_y += 4; - - req_y += hed_u->sac_y; - req_u->fra_w = ( (req_y[0] << 0x18) | (req_y[1] << 0x10) @@ -359,9 +358,6 @@ _fine_sift_requ(u3_head* hed_u, | (req_y[3] << 0x0)); req_y += 4; - //_ames_ship_to_chubs(req_u->hos_d, hed_u->rac_y, req_y); - //req_y += hed_u->rac_y; - req_u->len_s = c3_min(384, (req_y[0] << 0x8) @@ -374,11 +370,10 @@ _fine_sift_requ(u3_head* hed_u, } // TODO: defend maliciusly crafted lengths? - req_u->pat_c = c3_malloc(req_u->len_s + 1); + req_u->pat_c = c3_calloc(req_u->len_s + 1); memcpy(req_u->pat_c, req_y, req_u->len_s); req_u->pat_c[req_u->len_s] = '\0'; - // TODO: add null terminator? return c3y; } @@ -394,19 +389,12 @@ _fine_sift_resp(u3_head* hed_u, if(rem_w > len_w) { return c3n; } + c3_y pre_y = _ames_sift_prelude(hed_u, &res_u->pre_u, len_w, res_y); + res_y += pre_y; + memcpy(res_u->sig_y, res_y, 64); res_y += 64; - res_u->lyf_w = ( - (res_y[0] << 0x18) - | (res_y[1] << 0x10) - | (res_y[2] << 0x8) - | (res_y[3] << 0x0)); - res_y += 4; - - _ames_ship_to_chubs(res_u->hos_d, hed_u->sac_y, res_y); - res_y += hed_u->sac_y; - res_u->fra_w = ( (res_y[0] << 0x18) | (res_y[1] << 0x10) @@ -414,9 +402,6 @@ _fine_sift_resp(u3_head* hed_u, | (res_y[3] << 0x0)); res_y += 4; - _ames_ship_to_chubs(res_u->hos_d, hed_u->rac_y, res_y); - res_y += hed_u->rac_y; - res_u->len_s = c3_min(384, (res_y[0] << 0x8) @@ -529,7 +514,6 @@ _fine_etch_resp(u3_head* hed_u, memcpy(pac_w, &res_u->fra_w, 4); *pac_w = res_u->fra_w; // TODO: check byte order - _ames_ship_of_chubs(res_u->hos_d, sen_y, pac_y + 4); *(pac_y + sen_y + 4) = (0xff << 0) & res_u->len_s; *(pac_y + sen_y + 5) = (0xff << 1) & res_u->len_s; @@ -1354,12 +1338,8 @@ static void _fine_hear(u3_ames* sam_u, { u3_head hed_u; //u3_body bod_u; - c3_o val_o = _ames_sift_head(&hed_u, hun_y); - if(c3y == val_o) { - // invalid, maybe crash? - // - return; - } + c3_assert ( c3n == _ames_sift_head(&hed_u, hun_y)); + // skip past header len_w -= 4; hun_y += 4; @@ -1383,36 +1363,60 @@ static void _fine_hear(u3_ames* sam_u, if(u3_none == cac) { // cache miss // packet scry path - // /packet/requested/path/elements/ + // /packet/requested/path/elements // // eg: - // /packet/gx/~zod/graph-store/5/graphs/~zod/test/message/10/20 - // (fragment num is 20) + // /packet/gx/~zod/graph-store/5/graphs/~zod/test/message/10 // - u3_noun pax = u3dc("snoc", - u3do("stab", u3i_string(req_u.pat_c)), - u3i_words(1, &req_u.fra_w)); + u3_noun pax = u3nc(u3i_string("packet"), + u3do("stab", u3i_string(req_u.pat_c))); + + u3_reqp* rep_u = c3_malloc(sizeof(*rep_u)); rep_u->sam_u = sam_u; memcpy(&rep_u->hed_u, &hed_u, sizeof(u3_head)); memcpy(&rep_u->req_u, &req_u, sizeof(u3_requ)); u3_pier_peek_last(sam_u->fin_s.car_u.pir_u, u3_nul, c3__fx, u3_nul, - u3nc(u3i_string("packet"), pax), rep_u, _fine_pack_scry_cb); + pax, rep_u, _fine_pack_scry_cb); } else if(u3_nul == cac) { // cache hit, unbound // do nothing, maybe report? } else { - u3_noun hit = u3t(cac); - + // shape + // + u3_noun fra = u3dc("snag", u3i_word(req_u.fra_w), u3t(cac)); // - u3_resp res; - // _fine_etch_resp(); + + c3_w fra_w = u3r_met(3, fra); + c3_y* fra_y = c3_calloc(fra_w); + + u3r_bytes(0, fra_w, fra_y, fra); - //_fine_send(); + u3_resp* res_u = c3_calloc(sizeof(*res_u)); + c3_assert(c3y == _fine_sift_resp(&hed_u, res_u, fra_w, fra_y)); + + memcpy(&res_u->pre_u, &req_u.pre_u, sizeof(u3_prel)); + c3_y* res_y; + c3_w res_w = _fine_etch_resp(&hed_u, res_u, &res_y); + + // TODO: where free? maybe stack allocate instead? + u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); + pen_u->typ_y = 2; + pen_u->res_u = res_u; + pen_u->len_w = res_w; + pen_u->hun_y = res_y; + pen_u->her_d[0] = res_u->pre_u.sen_d[0]; + pen_u->her_d[1] = res_u->pre_u.sen_d[1]; + pen_u->lan_u = lan_u; + pen_u->sam_u = sam_u; + + _fine_send(pen_u); + + return; } } else { u3_resp res_u; @@ -1426,20 +1430,44 @@ static void _fine_hear(u3_ames* sam_u, 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 = u3nq(c3__fund, - pat, - u3i_words(1, &fra_w), - u3nc(u3i_words(1, &res_u.num_w), - u3i_bytes(res_u.siz_s, res_u.dat_y))); - + u3_noun cad = u3nc(c3__purr, u3i_bytes(len_w, hun_y)); u3_ovum* ovo_u = u3_ovum_init(0, c3__fine, wir, cad); u3_auto_plan(&sam_u->fin_s.car_u, ovo_u); - - // TODO: moar stats? } } +static void +_fine_request(u3_ames* sam_u, + u3_lane lan_u, + u3_noun req) +{ + u3l_log("fine: request\n"); + + u3_pend pen_u; + u3_head hed_u; + u3_requ 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); + + _ames_sift_head(&hed_u, req_y); + req_y += 4; + req_w -= 4; + + _fine_sift_requ(&hed_u, &req_u, req_w, req_y); + + + pen_u.typ_y = 1; + pen_u.her_d[0] = req_u.pre_u.rec_d[0]; + pen_u.her_d[1] = req_u.pre_u.rec_d[1]; + + pen_u.lan_u = lan_u; + pen_u.sam_u = sam_u; +} + /* _ames_hear(): parse a (potential) packet, dispatch appropriately. */ static void @@ -1484,7 +1512,7 @@ _ames_hear(u3_ames* sam_u, } else if (c3n == is_ames_o) { // TODO: dispatch fine request - //_fine_hear(sam_u, lan_u, len_w, hun_y) + _fine_hear(sam_u, *lan_u, len_w, hun_y); } // ensure the protocol version matches ours @@ -1708,25 +1736,17 @@ _ames_ef_turf(u3_ames* sam_u, u3_noun tuf) /* fine_io_kick:(): receive effect from arvo * TODO: */ -static c3_o _fine_io_kick(u3_noun nun) { - /** - * +task:fine - * $% [%find *] :: request - * [%fund =path frag-num=@ud frag-tot=@ud contents=@] - * == - * +gift:fine - * $% [%made *] :: notification - * [%find =lane =path] :: request packet to unix - * == - */ +static c3_o _fine_io_kick(u3_auto* car_u, u3_noun wir, u3_noun nun) { + u3_ames* sam_u = (u3_ames*)car_u; u3_noun hed = u3h(nun); - if(c3__made == hed) { + if(c3__hoot == hed) { // TODO: respond to notification of bound data - // put in cache return c3y; - } else if(c3__find == hed) { - // TODO: emit request packet to host ship - // _fine_io_request(); + } else if(c3__howl == hed) { + u3_noun lan, hot; + u3x_cell(u3t(nun), &lan, &hot); + u3_lane lan_u = u3_ames_decode_lane(lan); + _fine_request(sam_u, lan_u, hot); return c3y; } else { return c3n; diff --git a/shell.nix b/shell.nix index b1858df93..c6d03692a 100644 --- a/shell.nix +++ b/shell.nix @@ -22,7 +22,7 @@ let # # Typically the inputs listed here also have a shell.nix in their respective # source directory you can use directly. - inputsFrom = with pkgsLocal; [ ent herb urbit urcrypt ]; + inputsFrom = with pkgsLocal; [ ent urbit urcrypt ]; # Collect the named attribute from all dependencies listed in inputsFrom. mergeFrom = name: pkgs.lib.concatLists (pkgs.lib.catAttrs name inputsFrom); diff --git a/test b/test new file mode 100644 index 000000000..ff0e118fd --- /dev/null +++ b/test @@ -0,0 +1,2 @@ +~[46.318 46.574 46.830 47.086 47.342 47.598 47.854 48.110 48.366 48.622 48.878 49.134 49.390 49.646 49.902 50.158 50.414] + From 90cdc2de6aebd5b8c313ad84034c4264f7f94289 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Wed, 26 Jan 2022 18:01:48 -0600 Subject: [PATCH 03/21] wip --- nix/pkgs/2 | 2101 +++++++++++++++++++++++++++++++++ pkg/urbit/include/vere/vere.h | 2 +- pkg/urbit/vere/auto.c | 5 +- pkg/urbit/vere/io/ames.c | 340 ++++-- 4 files changed, 2377 insertions(+), 71 deletions(-) create mode 100644 nix/pkgs/2 diff --git a/nix/pkgs/2 b/nix/pkgs/2 new file mode 100644 index 000000000..f479e9c01 --- /dev/null +++ b/nix/pkgs/2 @@ -0,0 +1,2101 @@ +/* vere/ames.c +** +*/ +#include "all.h" +#include "vere/vere.h" +#include "ur/serial.h" + +/* u3_pact: outbound ames packet. +*/ + typedef struct _u3_pact { + uv_udp_send_t snd_u; // udp send request + u3_lane lan_u; // destination lane + c3_w len_w; // length in bytes + c3_y* hun_y; // packet buffer + c3_y imp_y; // galaxy number (optional) + c3_c* dns_c; // galaxy fqdn (optional) + struct _u3_ames* sam_u; // ames backpointer + } u3_pact; + +/* u3_fine: fine networking +*/ + typedef struct _u3_fine { + u3_auto car_u; // fine driver + c3_y ver_y; // fine protocol + u3p(u3h_root) sac_p; // scry cache hashtable + struct _u3_ames* sam_u; // ames backpointer + } u3_fine; + +/* u3_ames: ames networking. +*/ + typedef struct _u3_ames { // packet network state + u3_auto car_u; // ames driver + u3_fine fin_s; // fine networking + u3_pier* pir_u; // pier + union { // uv udp handle + uv_udp_t wax_u; // + uv_handle_t had_u; // + }; // + c3_l sev_l; // instance number + ur_cue_test_t* tes_u; // cue-test handle + u3_cue_xeno* sil_u; // cue handle + 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 + c3_w imp_w[256]; // imperial IPs + time_t imp_t[256]; // imperial IP timestamps + c3_o imp_o[256]; // imperial print status + struct { // config: + c3_o net_o; // can send + c3_o see_o; // can scry + c3_o fit_o; // filtering active + } fig_u; // + struct { // stats: + c3_d dop_d; // drop count + c3_d fal_d; // crash count + c3_d saw_d; // successive scry failures + c3_d hed_d; // failed to read header + c3_d vet_d; // version mismatches filtered + c3_d mut_d; // invalid mugs filtered + c3_d bod_d; // failed to read body + c3_d foq_d; // forward queue size + c3_d fow_d; // forwarded count + c3_d fod_d; // forwards dropped count + } sat_u; // + } u3_ames; + +/* u3_head: ames or fine packet header +*/ + typedef struct _u3_head { + c3_o req_o; // is request (fine only) + c3_o sim_o; // is ames protocol? + c3_y ver_y; // protocol version + c3_y sac_y; // sender class + c3_y rac_y; // receiver class + c3_l mug_l; // truncated mug hash of u3_body + c3_o rel_o; // relayed? + } u3_head; + +/* u3_prel: ames/fine packet prelude +*/ + typedef struct _u3_prel { + c3_y sic_y; // sender life tick + c3_y ric_y; // receiver life tick + c3_d sen_d[2]; // sender/requester + c3_d rec_d[2]; // receiver/responder + c3_d rog_d; // origin lane (optional) + } u3_prel; + +/* TODO: request response bodies for scry */ +/* 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; + + typedef struct _u3_reqp { + u3_ames* sam_u; + u3_head hed_u; + u3_requ req_u; + } u3_reqp; + +/* 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_pend: generic ames or fine pending packet */ + typedef struct _u3_pend { + uv_udp_send_t snd_u; // udp send request + c3_y typ_y; // 0 for ames, 1 for fine request, 2 for fine response + c3_d her_d[2]; // recipent mars address + c3_c* dns_c; // galaxy FQDN + c3_y* hun_y; // packet contents + c3_w len_w; // packet contents + u3_lane lan_u; // recipient lane + u3_ames* sam_u; // ames backpointer + union { + u3_resp* res_u; + u3_reqp* req_u; + u3_pact* pac_u; + }; + } u3_pend; + +/* 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 + } u3_body; + +/* u3_panc: deconstructed incoming packet +*/ + 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_panc; + +/* _ames_alloc(): libuv buffer allocator. +*/ +static void +_ames_alloc(uv_handle_t* had_u, + size_t len_i, + uv_buf_t* buf + ) +{ + // we allocate 2K, which gives us plenty of space + // for a single ames packet (max size 1060 bytes) + // + void* ptr_v = c3_malloc(2048); + *buf = uv_buf_init(ptr_v, 2048); +} + +/* _ames_pact_free(): free packet struct. +*/ +static void +_ames_pact_free(u3_pact* pac_u) +{ + c3_free(pac_u->hun_y); + c3_free(pac_u->dns_c); + c3_free(pac_u); +} + +static void +_ames_pend_free(u3_pend* pen_u) +{ + if(0 == pen_u->typ_y) { // ames packet + _ames_pact_free(pen_u->pac_u); + } else if (1 == pen_u->typ_y) { // fine request + c3_free(pen_u->req_u); + c3_free(pen_u->hun_y); + } else { // fine response + c3_free(pen_u->res_u); + c3_free(pen_u->hun_y); + } + c3_free(pen_u->dns_c); + c3_free(pen_u); +} + +/* _ames_panc_free(): remove references, lose refcounts and free struct +*/ +static void +_ames_panc_free(u3_panc* pac_u) +{ + if ( 0 != pac_u->nex_u ) { + pac_u->nex_u->pre_u = pac_u->pre_u; + } + + if ( 0 != pac_u->pre_u ) { + pac_u->pre_u->nex_u = pac_u->nex_u; + } + else { + c3_assert(pac_u == pac_u->sam_u->pac_u); + pac_u->sam_u->pac_u = pac_u->nex_u; + } + + c3_free(pac_u->ptr_v); + c3_free(pac_u); +} + +/* _ames_sift_head(): parse packet header. +*/ +static c3_o +_ames_sift_head(u3_head* hed_u, c3_y buf_y[4]) +{ + 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; +} + + +/* _ames_chub_bytes(): c3_y[8] to c3_d +** XX factor out, deduplicate with other conversions +*/ +static inline c3_d +_ames_chub_bytes(c3_y byt_y[8]) +{ + return (c3_d)byt_y[0] + | (c3_d)byt_y[1] << 8 + | (c3_d)byt_y[2] << 16 + | (c3_d)byt_y[3] << 24 + | (c3_d)byt_y[4] << 32 + | (c3_d)byt_y[5] << 40 + | (c3_d)byt_y[6] << 48 + | (c3_d)byt_y[7] << 56; +} + +/* _ames_ship_to_chubs(): pack [len_y] bytes into c3_d[2] +*/ +static inline void +_ames_ship_to_chubs(c3_d sip_d[2], c3_y len_y, c3_y* buf_y) +{ + c3_y sip_y[16] = {0}; + memcpy(sip_y, buf_y, c3_min(16, len_y)); + + sip_d[0] = _ames_chub_bytes(sip_y); + sip_d[1] = _ames_chub_bytes(sip_y + 8); +} + +/* _ames_chub_bytes(): c3_d to c3_y[8] +** XX factor out, deduplicate with other conversions +*/ +static inline void +_ames_bytes_chub(c3_y byt_y[8], c3_d num_d) +{ + byt_y[0] = num_d & 0xff; + byt_y[1] = (num_d >> 8) & 0xff; + byt_y[2] = (num_d >> 16) & 0xff; + byt_y[3] = (num_d >> 24) & 0xff; + byt_y[4] = (num_d >> 32) & 0xff; + byt_y[5] = (num_d >> 40) & 0xff; + byt_y[6] = (num_d >> 48) & 0xff; + byt_y[7] = (num_d >> 56) & 0xff; +} + +/* _ames_ship_of_chubs(): unpack c3_d[2] into [len_y] bytes. +*/ +static inline void +_ames_ship_of_chubs(c3_d sip_d[2], c3_y len_y, c3_y* buf_y) +{ + c3_y sip_y[16] = {0}; + + _ames_bytes_chub(sip_y, sip_d[0]); + _ames_bytes_chub(sip_y + 8, sip_d[1]); + + memcpy(buf_y, sip_y, c3_min(16, len_y)); +} + +/* _ames_sift_prelude(): parse prelude, returning length +*/ +static c3_y +_ames_sift_prelude(u3_head* hed_u, + u3_prel* pre_u, + c3_w len_w, + c3_y* pre_y) +{ + c3_y rog_y, sen_y, rec_y, len_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; + + pre_u->sic_y = pre_y[0] & 0xf; + pre_u->ric_y = pre_y[0] & 0xf0; + + _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) { + c3_y rag_y[8] = {0}; + memcpy(rag_y, pre_y + 1 + sen_y + rec_y, rog_y); + pre_u->rog_d = _ames_chub_bytes(rag_y); + } + else { + pre_u->rog_d = 0; + } + return len_y; +} + + + +/* _fine_sift_requ(): parse request body, returning success + * TODO: bring up to date +*/ +static c3_o +_fine_sift_requ(u3_head* hed_u, + u3_requ* req_u, + c3_w len_w, + c3_y* req_y) +{ + c3_y pre_y = _ames_sift_prelude(hed_u, &req_u->pre_u, len_w, req_y); + + req_y += pre_y; + + c3_w rem_w = (64 + 4 + 2 + pre_y); + if(rem_w > len_w) { + return c3n; + } + memcpy(req_u->sig_y, req_y, 64); + req_y += 64; + + req_u->fra_w = ( + (req_y[0] << 0x18) + | (req_y[1] << 0x10) + | (req_y[2] << 0x8) + | (req_y[3] << 0x0)); + req_y += 4; + + + req_u->len_s = c3_min(384, + (req_y[0] << 0x8) + | (req_y[1] << 0x0)); + req_y += 2; + + // TODO: strict inequality? + if(rem_w + req_u->len_s != len_w) { + return c3n; + } + + // TODO: defend maliciusly crafted lengths? + req_u->pat_c = c3_calloc(req_u->len_s + 1); + + memcpy(req_u->pat_c, req_y, req_u->len_s); + req_u->pat_c[req_u->len_s] = '\0'; + return c3y; +} + +/* _fine_sift_resp(): parse response body, returning success +*/ +static c3_o +_fine_sift_resp(u3_head* hed_u, + u3_resp* res_u, + c3_w len_w, + c3_y* res_y) +{ + c3_w rem_w = (64 + 4 + hed_u->sac_y + 4 + hed_u->rac_y + 2); + if(rem_w > len_w) { + return c3n; + } + c3_y pre_y = _ames_sift_prelude(hed_u, &res_u->pre_u, len_w, res_y); + res_y += pre_y; + + memcpy(res_u->sig_y, res_y, 64); + res_y += 64; + + res_u->fra_w = ( + (res_y[0] << 0x18) + | (res_y[1] << 0x10) + | (res_y[2] << 0x8) + | (res_y[3] << 0x0)); + res_y += 4; + + + res_u->len_s = c3_min(384, + (res_y[0] << 0x8) + | (res_y[1] << 0x0)); + res_y += 2; + + // TODO: strict inequality? + if(rem_w + res_u->len_s != len_w) { + return c3n; + } + + // TODO: defend maliciusly crafted lengths? + res_u->pat_c = c3_malloc(res_u->len_s); + + memcpy(res_u->pat_c, res_y, res_u->len_s); + // TODO: add null terminator? + 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; + } + else { + bod_u->mug_l = u3r_mug_bytes(gob_y, gob_s) & 0xfffff; + + bod_u->con_y = gob_y + 4; + + return c3y; + } +} + +/* _ames_etch_head(): serialize packet header. +*/ +static void +_ames_etch_head(u3_head* hed_u, c3_y buf_y[4]) +{ + c3_w hed_w = ((hed_u->req_o & 0x1) << 2) + ^ ((hed_u->sim_o & 0x1) << 3) + ^ ((hed_u->ver_y & 0x7) << 4) + ^ ((hed_u->sac_y & 0x3) << 7) + ^ ((hed_u->rac_y & 0x3) << 9) + ^ ((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_prelude(): serialize packet prelude +*/ +static c3_y +_ames_etch_prelude(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; + + + // 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 ) { + c3_y rag_y[8] = {0}; + _ames_bytes_chub(rag_y, pre_u->rog_d); + memcpy(buf_y, rag_y, rog_y); + } + 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; // TODO: check byte order + + *(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_malloc(len_w); // output buf + c3_y* bod_y = pac_y + 4; // body cursor + + // serialize the head + // + _ames_etch_head(hed_u, pac_y); + + 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 + + // serialize the body + memcpy(gob_y, bod_u->con_y, bod_u->con_s); + + *out_y = pac_y; + return len_w; +} + +/* _ames_send_cb(): send callback. +*/ +static void +_ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) +{ + u3_pend* pen_u = (u3_pend*)req_u; + u3_ames* sam_u = pen_u->sam_u; + + if (sas_i) { + u3l_log("ames: send fail: %s\n", uv_strerror(sas_i)); + sam_u->fig_u.net_o = c3n; + } + else { + sam_u->fig_u.net_o = c3y; + } + + //_ames_pend_free(pen_u); +} + +#define _fine_send _ames_send +/* _ames_send(): send buffer to address on port. +*/ +static void +_ames_send(u3_pend* pen_u) +{ + u3l_log("ames: send"); + u3_ames* sam_u = pen_u->sam_u; + + // TODO: prevalidation? + /*if ( !pen_u->hun_y ) { + // _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(pen_u->lan_u.pip_w); + add_u.sin_port = htons(pen_u->lan_u.por_s); + + { + uv_buf_t buf_u = uv_buf_init((c3_c*)pen_u->hun_y, pen_u->len_w); + + c3_i sas_i = uv_udp_send(&pen_u->snd_u, + &sam_u->wax_u, + &buf_u, 1, + (const struct sockaddr*)&add_u, + _ames_send_cb); + + if ( sas_i ) { + if ( c3y == sam_u->fig_u.net_o ) { + u3l_log("ames: send fail: %s\n", uv_strerror(sas_i)); + sam_u->fig_u.net_o = c3n; + } + + _ames_pend_free(pen_u); + } + } + } +} + +/* u3_ames_decode_lane(): deserialize noun to lane; 0.0.0.0:0 if invalid +*/ +u3_lane +u3_ames_decode_lane(u3_atom lan) { + u3_lane lan_u; + c3_d lan_d; + + if ( c3n == u3r_safe_chub(lan, &lan_d) || (lan_d >> 48) != 0 ) { + return (u3_lane){0, 0}; + } + + u3z(lan); + + lan_u.pip_w = (c3_w)lan_d; + lan_u.por_s = (c3_s)(lan_d >> 32); + return lan_u; +} + +/* u3_ames_lane_to_chub(): serialize lane to double-word +*/ +c3_d +u3_ames_lane_to_chub(u3_lane lan) { + return ((c3_d)lan.por_s << 32) ^ (c3_d)lan.pip_w; +} + +/* u3_ames_encode_lane(): serialize lane to noun +*/ +u3_atom +u3_ames_encode_lane(u3_lane lan) { + return u3i_chub(u3_ames_lane_to_chub(lan)); +} + +/* _ames_lane_into_cache(): put las for who into cache, including timestamp +*/ +static void +_ames_lane_into_cache(u3p(u3h_root) lax_p, u3_noun who, u3_noun las) { + struct timeval tim_tv; + gettimeofday(&tim_tv, 0); + u3_noun now = u3_time_in_tv(&tim_tv); + u3_noun val = u3nc(las, now); + u3h_put(lax_p, who, val); + u3z(who); +} + +/* _ames_lane_from_cache(): retrieve lane for who from cache, if any & fresh +*/ +static u3_weak +_ames_lane_from_cache(u3p(u3h_root) lax_p, u3_noun who) { + u3_weak lac = u3h_git(lax_p, who); + + if ( u3_none != lac ) { + struct timeval tim_tv; + gettimeofday(&tim_tv, 0); + u3_noun now = u3_time_in_tv(&tim_tv); + u3_noun den = u3t(lac); + + // consider entries older than 2 minutes stale, ignore them + // + if ( 120000 > u3_time_gap_ms(u3k(den), now) ) { + lac = u3k(u3h(lac)); + } else { + lac = u3_none; + } + } + + u3z(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) +{ + // 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; + } +} + +/* _ames_czar_port(): udp port for galaxy. +*/ +static c3_s +_ames_czar_port(c3_y imp_y) +{ + if ( c3n == u3_Host.ops_u.net ) { + return 31337 + imp_y; + } + else { + return 13337 + imp_y; + } +} + +/* _ames_czar_gone(): galaxy address resolution failed. +*/ +static void +_ames_czar_gone(u3_pend* pen_u, time_t now) +{ + u3_ames* sam_u = pen_u->sam_u; + c3_d imp_d = pen_u->her_d[0]; + + if ( c3y == sam_u->imp_o[imp_d] ) { + u3l_log("ames: czar at %s: not found (b)\n", pen_u->dns_c); + sam_u->imp_o[imp_d] = c3n; + } + + if ( (0 == sam_u->imp_w[imp_d]) || + (0xffffffff == sam_u->imp_w[imp_d]) ) + { + sam_u->imp_w[imp_d] = 0xffffffff; + } + + // keep existing ip for 5 more minutes + // + sam_u->imp_t[imp_d] = now; + + _ames_pend_free(pen_u); +} + +/* _ames_czar_here(): galaxy address resolution succeeded. +*/ +static void +_ames_czar_here(u3_pend* pen_u, time_t now, struct sockaddr_in* add_u) +{ + u3_ames* sam_u = pen_u->sam_u; + c3_y imp_y = pen_u->her_d[0]; + c3_w old_w = sam_u->imp_w[imp_y]; + c3_w pip_w = ntohl(add_u->sin_addr.s_addr); + + if ( pip_w != old_w ) { + 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", pen_u->dns_c, nam_c); + + c3_free(nam_c); + u3z(nam); + } + + sam_u->imp_w[imp_y] = pip_w; + sam_u->imp_t[imp_y] = now; + sam_u->imp_o[imp_y] = c3y; + + pen_u->lan_u.pip_w = pip_w; + _ames_send(pen_u); +} + +/* _ames_czar_cb(): galaxy address resolution callback. +*/ +static void +_ames_czar_cb(uv_getaddrinfo_t* adr_u, + c3_i sas_i, + struct addrinfo* aif_u) +{ + { + u3_pend* pen_u = (u3_pend*)adr_u->data; + struct addrinfo* rai_u = aif_u; + time_t now = time(0); + + while ( rai_u ) { + if ( (AF_INET == rai_u->ai_family) ) { + _ames_czar_here(pen_u, now, (struct sockaddr_in *)rai_u->ai_addr); + break; + } + else { + rai_u = rai_u->ai_next; + } + } + + if ( !rai_u ) { + _ames_czar_gone(pen_u, now); + } + } + + c3_free(adr_u); + uv_freeaddrinfo(aif_u); +} + +/* _ames_czar(): galaxy address resolution. +*/ +static void +_ames_czar(u3_pend* pen_u) +{ + u3_ames* sam_u = pen_u->sam_u; + + c3_d imp_d = pen_u->her_d[0]; + + c3_assert( imp_d < 256 ); + + pen_u->lan_u.por_s = _ames_czar_port(imp_d); + + if ( c3n == u3_Host.ops_u.net ) { + pen_u->lan_u.pip_w = 0x7f000001; + _ames_send(pen_u); + return; + } + + // if we don't have a galaxy domain, no-op + // + if ( !sam_u->dns_c ) { + u3_noun nam = u3dc("scot", 'p', pen_u->her_d[0]); + c3_c* nam_c = u3r_string(nam); + u3l_log("ames: no galaxy domain for %s, no-op\r\n", nam_c); + + c3_free(nam_c); + u3z(nam); + return; + } + + { + c3_w pip_w = sam_u->imp_w[imp_d]; + time_t wen = sam_u->imp_t[imp_d]; + time_t now = time(0); + + // backoff for 5 minutes after failed lookup + // + if ( ( now < wen ) // time shenanigans! + || ( (0xffffffff == pip_w) // sentinal ip address + && ((now - wen) < 300) ) ) + { + _ames_pend_free(pen_u); + return; + } + // cached addresses have a 5 minute TTL + // + else if ( (0 != pip_w) && ((now - wen) < 300) ) { + pen_u->lan_u.pip_w = pip_w; + _ames_send(pen_u); + return; + } + else { + c3_i sas_i; + + { + u3_noun nam = u3dc("scot", 'p', imp_d); + c3_c* nam_c = u3r_string(nam); + + // NB: . separator not counted, as [nam_c] includes a ~ that we skip + // + pen_u->dns_c = c3_malloc(1 + strlen(nam_c) + strlen(sam_u->dns_c)); + sas_i = snprintf(pen_u->dns_c, 255, "%s.%s", nam_c + 1, sam_u->dns_c); + + c3_free(nam_c); + u3z(nam); + } + + if ( 255 <= sas_i ) { + u3l_log("ames: czar: galaxy domain %s truncated\n", sam_u->dns_c); + _ames_pend_free(pen_u); + return; + } + + { + uv_getaddrinfo_t* adr_u = c3_malloc(sizeof(*adr_u)); + adr_u->data = pen_u; + + if ( 0 != (sas_i = uv_getaddrinfo(u3L, adr_u, + _ames_czar_cb, + pen_u->dns_c, 0, 0)) ) + { + u3l_log("ames: %s\n", uv_strerror(sas_i)); + _ames_czar_gone(pen_u, now); + return; + } + } + } + } +} + +/* _ames_ef_send(): send packet to network (v4). +*/ +static void +_ames_ef_send(u3_ames* sam_u, u3_noun lan, u3_noun pac) +{ + if ( c3n == sam_u->car_u.liv_o ) { + u3l_log("ames: not yet live, dropping outbound\r\n"); + u3z(lan); u3z(pac); + return; + } + + u3_pact* pac_u = c3_calloc(sizeof(*pac_u)); + pac_u->sam_u = sam_u; + pac_u->len_w = u3r_met(3, pac); + pac_u->hun_y = c3_malloc(pac_u->len_w); + + u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); + pen_u->typ_y = 0; + pen_u->len_w = pac_u->len_w; + pen_u->hun_y = pac_u->hun_y; + pen_u->sam_u = sam_u; + + + + u3r_bytes(0, pac_u->len_w, pac_u->hun_y, pac); + + u3_noun tag, val; + u3x_cell(lan, &tag, &val); + c3_assert( (c3y == tag) || (c3n == tag) ); + + // galaxy lane; do DNS lookup and send packet + // + if ( c3y == tag ) { + c3_assert( c3y == u3a_is_cat(val) ); + c3_assert( val < 256 ); + + pac_u->imp_y = val; + pen_u->her_d[0] = val; + _ames_czar(pen_u); + } + // non-galaxy lane + // + else { + u3_lane lan_u = u3_ames_decode_lane(u3k(val)); + // convert incoming localhost to outgoing localhost + // + lan_u.pip_w = ( 0 == lan_u.pip_w )? 0x7f000001 : lan_u.pip_w; + // if in local-only mode, don't send remote packets + // + if ( (c3n == u3_Host.ops_u.net) && (0x7f000001 != lan_u.pip_w) ) { + _ames_pact_free(pac_u); + } + // if the lane is uninterpretable, silently drop the packet + // + else if ( 0 == lan_u.por_s ) { + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("ames: inscrutable lane\n"); + } + _ames_pact_free(pac_u); + } + // otherwise, mutate destination and send packet + // + else { + pen_u->lan_u = lan_u; + _ames_send(pen_u); + } + } + u3z(lan); u3z(pac); +} + +/* _ames_cap_queue(): cap ovum queue at 1k, dropping oldest packets. +*/ +static void +_ames_cap_queue(u3_ames* sam_u) +{ + u3_ovum* egg_u = sam_u->car_u.ext_u; + + while ( egg_u && (1000 < sam_u->car_u.dep_w) ) { + u3_ovum* nex_u = egg_u->nex_u; + + if ( c3__hear == u3h(egg_u->cad) ) { + u3_auto_drop(&sam_u->car_u, egg_u); + sam_u->sat_u.dop_d++; + + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("ames: packet dropped (%" PRIu64 " total)\n", sam_u->sat_u.dop_d); + } + } + + egg_u = nex_u; + } + + if ( (sam_u->sat_u.dop_d && (0 == (sam_u->sat_u.dop_d % 1000))) + && !(u3C.wag_w & u3o_verbose) ) + { + u3l_log("ames: packet dropped (%" PRIu64 " total)\n", sam_u->sat_u.dop_d); + } +} + +/* _ames_punt_goof(): print %bail error report(s). +*/ +static void +_ames_punt_goof(u3_noun lud) +{ + if ( 2 == u3qb_lent(lud) ) { + u3_pier_punt_goof("hear", u3k(u3h(lud))); + u3_pier_punt_goof("crud", u3k(u3h(u3t(lud)))); + } + else { + u3_noun dul = lud; + c3_w len_w = 1; + + while ( u3_nul != dul ) { + u3l_log("ames: bail %u\r\n", len_w++); + u3_pier_punt_goof("ames", u3k(u3h(dul))); + dul = u3t(dul); + } + } + + u3z(lud); +} + +/* _ames_hear_bail(): handle packet failure. +*/ +static void +_ames_hear_bail(u3_ovum* egg_u, u3_noun lud) +{ + u3_ames* sam_u = (u3_ames*)egg_u->car_u; + sam_u->sat_u.fal_d++; + + if ( (u3C.wag_w & u3o_verbose) + || (0 == (sam_u->sat_u.fal_d % 1000)) ) + { + _ames_punt_goof(lud); + u3l_log("ames: packet failed (%" PRIu64 " total)\n\n", sam_u->sat_u.fal_d); + } + else { + u3z(lud); + + if ( 0 == (sam_u->sat_u.fal_d % 1000) ) { + u3l_log("ames: packet failed (%" PRIu64 " total)\n\n", sam_u->sat_u.fal_d); + } + } + + u3_ovum_free(egg_u); +} + +/* _ames_put_packet(): add packet to queue, drop old packets on pressure +*/ +static void +_ames_put_packet(u3_ames* sam_u, + u3_noun msg, + u3_lane lan_u) +{ + u3_noun wir = u3nc(c3__ames, u3_nul); + u3_noun cad = u3nt(c3__hear, u3nc(c3n, u3_ames_encode_lane(lan_u)), msg); + + u3_auto_peer( + u3_auto_plan(&sam_u->car_u, + u3_ovum_init(0, c3__a, wir, cad)), + 0, 0, _ames_hear_bail); + + _ames_cap_queue(sam_u); +} + +/* _ames_forward(): forward pac_u onto the (list lane) las, then free pac_u +*/ +static void +_ames_forward(u3_panc* pac_u, u3_noun las) +{ + u3_ames* sam_u = pac_u->sam_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 ( 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"); + u3m_p("lan", lan); + } + 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); + } + + _ames_panc_free(pac_u); + u3z(las); +} + +/* _ames_lane_scry_cb(): learn lane to forward packet on +*/ +static void +_ames_lane_scry_cb(void* vod_p, u3_noun nun) +{ + u3_panc* pac_u = vod_p; + u3_ames* sam_u = pac_u->sam_u; + u3_weak las = u3r_at(7, nun); + + sam_u->sat_u.foq_d--; + + // if scry fails, remember we can't scry, and just inject the packet + // + if ( u3_none == las ) { + if ( 5 < ++sam_u->sat_u.saw_d ) { + 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); + } + else { + sam_u->sat_u.saw_d = 0; + + // 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_panc_free(pac_u); + } + // if there is a lane, forward the packet on it + // + else { + _ames_forward(pac_u, u3k(las)); + } + } + + u3z(nun); +} + +/* _ames_try_forward(): try to forward a packet for another ship. +*/ +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) +{ + u3_weak lac; + + // 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]) ) + { + lac = u3nc(c3y, (c3_y)bod_u->pre_u.rec_d[0]); + } + // 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; + } + } + + // proceed with forwarding + // + { + // 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; + } + 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 { + sam_u->sat_u.foq_d++; + u3_noun pax = u3nq(u3i_string("peers"), + u3dc("scot", 'p', u3i_chubs(2, bod_u->pre_u.rec_d)), + u3i_string("forward-lane"), + u3_nul); + u3_pier_peek_last(sam_u->pir_u, u3_nul, c3__ax, + u3_nul, pax, pac_u, _ames_lane_scry_cb); + } + } +} + +#undef AMES_SKIP +#ifdef AMES_SKIP +/* _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 + ) ) { + return c3n; + } + else { + return c3y; + } +} +#endif + +/* _fine_pack_scry_cb(): receive all packets for datum out of fine + * TODO: implement + */ +static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) +{ + u3_pend* pen_u = vod_p; + u3_weak pack = u3r_at(3, nun); + // + // hashtable = (path, packet_num) -> cached_result; + // All cases, except 1st ~: put results in cache for all packets + // ~ -> if second request, ask for notification if 2nd, drop on floor + // [~ ~] -> send packet + // [~ ~ *] -> send packet + // TODO: cache logic, counting requests, evict? + + u3_weak lan = _ames_lane_from_cache(pen_u->sam_u->lax_p, + u3i_chubs(2, pen_u->her_d)); + if(u3_none == lan) { + // TODO: enqueue packet for later sending, populate lane cache + } else if(u3_nul == lan) { + // TODO: no lane, drop packet + } else { + _fine_send(pen_u); + } +} + + + +/* _fine_hear(): hear a (potential) packet, dispatch appropriately + */ +// _fine_hear(sam_u, lan_u, len_w, hun_y) +static void _fine_hear(u3_ames* sam_u, + u3_lane lan_u, + c3_w len_w, + c3_y* hun_y) +{ + u3_head hed_u; + //u3_body bod_u; + c3_assert ( c3n == _ames_sift_head(&hed_u, hun_y)); + + // skip past header + len_w -= 4; + hun_y += 4; + + if(hed_u.req_o) { + // lookup in cache + // (unit (unit (unit packet)) + // ~ -> miss + // [~ ~] -> hit, unbound + // [~ ~ ~] -> hit, empty + // [~ ~ ~ *] -> hit, w/ data + u3_requ req_u; + + + _fine_sift_requ(&hed_u, &req_u, len_w, hun_y); + + u3_noun pat = u3i_string(req_u.pat_c); + + u3_weak cac = u3h_git(sam_u->fin_s.sac_p, pat); + + if(u3_none == cac) { + // cache miss + // packet scry path + // /packet/requested/path/elements + // + // eg: + // /packet/gx/~zod/graph-store/5/graphs/~zod/test/message/10 + // + u3_noun pax = u3nc(u3i_string("packet"), + u3do("stab", u3i_string(req_u.pat_c))); + + + u3_reqp* rep_u = c3_malloc(sizeof(*rep_u)); + rep_u->sam_u = sam_u; + memcpy(&rep_u->hed_u, &hed_u, sizeof(u3_head)); + memcpy(&rep_u->req_u, &req_u, sizeof(u3_requ)); + + u3_pier_peek_last(sam_u->fin_s.car_u.pir_u, u3_nul, c3__fx, u3_nul, + pax, rep_u, _fine_pack_scry_cb); + + } else if(u3_nul == cac) { + // cache hit, unbound + // do nothing, maybe report? + } else { + // shape + // + u3_noun fra = u3dc("snag", u3i_word(req_u.fra_w), u3t(cac)); + // + + c3_w fra_w = u3r_met(3, fra); + c3_y* fra_y = c3_calloc(fra_w); + + u3r_bytes(0, fra_w, fra_y, fra); + + u3_resp* res_u = c3_calloc(sizeof(*res_u)); + + c3_assert(c3y == _fine_sift_resp(&hed_u, res_u, fra_w, fra_y)); + + memcpy(&res_u->pre_u, &req_u.pre_u, sizeof(u3_prel)); + + c3_y* res_y; + c3_w res_w = _fine_etch_resp(&hed_u, res_u, &res_y); + + // TODO: where free? maybe stack allocate instead? + u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); + pen_u->typ_y = 2; + pen_u->res_u = res_u; + pen_u->len_w = res_w; + pen_u->hun_y = res_y; + pen_u->her_d[0] = res_u->pre_u.sen_d[0]; + pen_u->her_d[1] = res_u->pre_u.sen_d[1]; + pen_u->lan_u = lan_u; + pen_u->sam_u = sam_u; + + _fine_send(pen_u); + + return; + } + } else { + u3_resp res_u; + + _fine_sift_resp(&hed_u, &res_u, len_w, hun_y); + u3_noun pat = u3do("stab", u3i_string(res_u.pat_c)); + + + // + // + 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 = u3nc(c3__purr, u3i_bytes(len_w, hun_y)); + + u3_ovum* ovo_u = u3_ovum_init(0, c3__fine, wir, cad); + u3_auto_plan(&sam_u->fin_s.car_u, ovo_u); + } +} + +static void +_fine_request(u3_ames* sam_u, + u3_lane lan_u, + u3_noun req) +{ + u3l_log("fine: request\n"); + + u3_pend pen_u; + u3_head hed_u; + u3_requ 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); + + _ames_sift_head(&hed_u, req_y); + req_y += 4; + req_w -= 4; + + _fine_sift_requ(&hed_u, &req_u, req_w, req_y); + + + pen_u.typ_y = 1; + pen_u.her_d[0] = req_u.pre_u.rec_d[0]; + pen_u.her_d[1] = req_u.pre_u.rec_d[1]; + + pen_u.lan_u = lan_u; + pen_u.sam_u = sam_u; +} + +/* _ames_hear(): parse a (potential) packet, dispatch appropriately. +*/ +static void +_ames_hear(u3_ames* sam_u, + u3_lane* lan_u, + c3_w len_w, + c3_y* hun_y) +{ + + u3l_log("ames: hear"); + // TODO: move from stack to heap to avoid reparsing + u3_head hed_u; + u3_body bod_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(&hed_u, hun_y); + + if (4 > 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", + sam_u->sat_u.hed_d); + } + + c3_free(hun_y); + return; + } + else if (c3n == is_ames_o) { + // TODO: dispatch fine request + _fine_hear(sam_u, *lan_u, len_w, hun_y); + } + + // ensure the protocol version matches ours + // + // XX rethink use of [fit_o] here and elsewhere + // + if ( (c3y == sam_u->fig_u.fit_o) + && (sam_u->ver_y != 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); + 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(&hed_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); + return; + } + + // ensure the mug is valid + // + u3l_log("bod: %ux, hed: %ux\n", hed_u.mug_l, bod_u.mug_l); + if ( bod_u.mug_l != hed_u.mug_l ) { + 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); + return; + } + } + + // if we can scry, + // and we are not the recipient, + // we might want to forward statelessly + // + if ( 0 && (c3y == sam_u->fig_u.see_o) + && ( (bod_u.pre_u.rec_d[0] != sam_u->pir_u->who_d[0]) + || (bod_u.pre_u.rec_d[1] != sam_u->pir_u->who_d[1]) ) ) + { + _ames_try_forward(sam_u, lan_u, &hed_u, &bod_u, hun_y); + } + // 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); + } + else { +#endif + _ames_put_packet(sam_u, msg, *lan_u); +#ifdef AMES_SKIP + } +#endif + } +} + +/* _ames_recv_cb(): udp message receive callback. +*/ +static void +_ames_recv_cb(uv_udp_t* wax_u, + ssize_t nrd_i, + const uv_buf_t * buf_u, + const struct sockaddr* adr_u, + unsigned flg_i) +{ + if ( 0 > nrd_i ) { + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("ames: recv: fail: %s\n", uv_strerror(nrd_i)); + } + c3_free(buf_u->base); + } + else if ( 0 == nrd_i ) { + c3_free(buf_u->base); + } + else if ( flg_i & UV_UDP_PARTIAL ) { + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("ames: recv: fail: message truncated\n"); + } + c3_free(buf_u->base); + } + else { + u3_ames* sam_u = wax_u->data; + struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; + u3_lane lan_u; + + lan_u.por_s = ntohs(add_u->sin_port); + lan_u.pip_w = ntohl(add_u->sin_addr.s_addr); + + // NB: [nrd_i] will never exceed max length from _ames_alloc() + // + _ames_hear(sam_u, &lan_u, (c3_w)nrd_i, (c3_y*)buf_u->base); + } +} + +/* _ames_io_start(): initialize ames I/O. +*/ +static void +_ames_io_start(u3_ames* sam_u) +{ + c3_s por_s = sam_u->pir_u->por_s; + u3_noun who = u3i_chubs(2, sam_u->pir_u->who_d); + u3_noun rac = u3do("clan:title", u3k(who)); + c3_i ret_i; + + if ( c3__czar == rac ) { + c3_y num_y = (c3_y)sam_u->pir_u->who_d[0]; + c3_s zar_s = _ames_czar_port(num_y); + + if ( 0 == por_s ) { + por_s = zar_s; + } + else if ( por_s != zar_s ) { + u3l_log("ames: czar: overriding port %d with -p %d\n", zar_s, por_s); + u3l_log("ames: czar: WARNING: %d required for discoverability\n", zar_s); + } + } + + // Bind and stuff. + { + struct sockaddr_in add_u; + c3_i add_i = sizeof(add_u); + + memset(&add_u, 0, sizeof(add_u)); + add_u.sin_family = AF_INET; + add_u.sin_addr.s_addr = _(u3_Host.ops_u.net) ? + htonl(INADDR_ANY) : + htonl(INADDR_LOOPBACK); + add_u.sin_port = htons(por_s); + + if ( (ret_i = uv_udp_bind(&sam_u->wax_u, + (const struct sockaddr*)&add_u, 0)) != 0 ) + { + u3l_log("ames: bind: %s\n", uv_strerror(ret_i)); + + if ( (c3__czar == rac) && + (UV_EADDRINUSE == ret_i) ) + { + u3l_log(" ...perhaps you've got two copies of vere running?\n"); + } + + // XX revise + // + u3_pier_bail(u3_king_stub()); + } + + uv_udp_getsockname(&sam_u->wax_u, (struct sockaddr *)&add_u, &add_i); + c3_assert(add_u.sin_port); + + sam_u->pir_u->por_s = ntohs(add_u.sin_port); + } + + if ( c3y == u3_Host.ops_u.net ) { + u3l_log("ames: live on %d\n", sam_u->pir_u->por_s); + } + else { + u3l_log("ames: live on %d (localhost only)\n", sam_u->pir_u->por_s); + } + + uv_udp_recv_start(&sam_u->wax_u, _ames_alloc, _ames_recv_cb); + + sam_u->car_u.liv_o = c3y; + u3z(rac); + u3z(who); +} + +/* _ames_ef_turf(): initialize ames I/O on domain(s). +*/ +static void +_ames_ef_turf(u3_ames* sam_u, u3_noun tuf) +{ + if ( u3_nul != tuf ) { + // XX save all for fallback, not just first + // + u3_noun hot = u3k(u3h(tuf)); + c3_w len_w = u3_mcut_host(0, 0, u3k(hot)); + + sam_u->dns_c = c3_malloc(1 + len_w); + u3_mcut_host(sam_u->dns_c, 0, hot); + sam_u->dns_c[len_w] = 0; + + // XX invalidate sam_u->imp_w &c ? + // + + u3z(tuf); + } + else if ( (c3n == sam_u->pir_u->fak_o) && (0 == sam_u->dns_c) ) { + u3l_log("ames: turf: no domains\n"); + } + + // XX is this ever necessary? + // + if ( c3n == sam_u->car_u.liv_o ) { + _ames_io_start(sam_u); + } +} + + +/* fine_io_kick:(): receive effect from arvo + * TODO: + */ +static c3_o _fine_io_kick(u3_auto* car_u, u3_noun wir, u3_noun nun) { + u3_ames* sam_u = (u3_ames*)car_u; + u3_noun hed = u3h(nun); + if(c3__hoot == hed) { + // TODO: respond to notification of bound data + return c3y; + } else if(c3__howl == hed) { + u3_noun lan, hot; + u3x_cell(u3t(nun), &lan, &hot); + u3_lane lan_u = u3_ames_decode_lane(lan); + _fine_request(sam_u, lan_u, hot); + return c3y; + } else { + return c3n; + } +} + +static void _fine_send_fail() +{ + // TODO: log some shit +} + +static void _fine_send_cb() +{ + // TODO: anything to do here? +} + +/* _ames_prot_scry_cb(): receive ames protocol version +*/ +static void +_ames_prot_scry_cb(void* vod_p, u3_noun nun) +{ + u3_ames* sam_u = vod_p; + u3_weak ver = u3r_at(7, nun); + + if ( u3_none == ver ) { + // assume protocol version 0 + // + sam_u->ver_y = 0; + } + else if ( (c3n == u3a_is_cat(ver)) + || (7 < ver) ) { + u3m_p("ames: strange protocol", nun); + sam_u->ver_y = 0; + } + else { + sam_u->ver_y = ver; + } + + // XX revise: filtering should probably be disabled if + // we get a protocol version above the latest one we know + // + sam_u->fig_u.fit_o = c3y; + u3z(nun); +} + +/* _fine_prot_scry_cb(): receive fine protocol version +*/ +static void +_fine_prot_scry_cb(void* vod_p, u3_noun nun) +{ + u3_ames* sam_u = vod_p; + u3_weak ver = u3r_at(7, nun); + + if ( u3_none == ver ) { + // assume protocol version 0 + // + sam_u->fin_s.ver_y = 0; + } + else if ( (c3n == u3a_is_cat(ver)) + || (7 < ver) ) { + u3m_p("fine: strange protocol", nun); + sam_u->fin_s.ver_y = 0; + } + else { + sam_u->fin_s.ver_y = ver; + } + + u3z(nun); +} + +/* _fine_io_talk(): start receiving ames traffic. +*/ +static void _fine_io_talk(u3_auto* car_u) +{ + // do nothing +} + + + +/* _ames_io_talk(): start receiving ames traffic. +*/ +static void +_ames_io_talk(u3_auto* car_u) +{ + u3_ames* sam_u = (u3_ames*)car_u; + _ames_io_start(sam_u); + + // send born event + // + { + // XX remove [sev_l] + // + u3_noun wir = u3nt(c3__newt, + u3dc("scot", c3__uv, sam_u->sev_l), + u3_nul); + u3_noun cad = u3nc(c3__born, u3_nul); + + u3_auto_plan(car_u, u3_ovum_init(0, c3__a, wir, cad)); + } + // TODO: scry the fine protocol out of arvo + // + u3_pier_peek_last(car_u->pir_u, u3_nul, c3__fx, u3_nul, + u3nt(u3i_string("protocol"), u3i_string("version"), u3_nul), + sam_u, _fine_prot_scry_cb); + + // scry the protocol version out of arvo + // + // XX this should be re-triggered periodically, + // or, better yet, %ames should emit a %turf + // (or some other reconfig) effect when it is reset. + // + u3_pier_peek_last(car_u->pir_u, u3_nul, c3__ax, u3_nul, + u3nt(u3i_string("protocol"), u3i_string("version"), u3_nul), + sam_u, _ames_prot_scry_cb); +} + +/* _ames_kick_newt(): apply packet network outputs. +*/ +static c3_o +_ames_kick_newt(u3_ames* sam_u, u3_noun tag, u3_noun dat) +{ + c3_o ret_o; + + switch ( tag ) { + default: { + ret_o = c3n; + } break; + + case c3__send: { + u3_noun lan = u3k(u3h(dat)); + u3_noun pac = u3k(u3t(dat)); + _ames_ef_send(sam_u, lan, pac); + ret_o = c3y; + } break; + + case c3__turf: { + _ames_ef_turf(sam_u, u3k(dat)); + ret_o = c3y; + } break; + } + + u3z(tag); u3z(dat); + return ret_o; +} + +/* _ames_io_kick(): apply effects +*/ +static c3_o +_ames_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) +{ + u3_ames* sam_u = (u3_ames*)car_u; + + u3_noun tag, dat, i_wir; + c3_o ret_o; + + if ( (c3n == u3r_cell(wir, &i_wir, 0)) + || (c3n == u3r_cell(cad, &tag, &dat)) ) + { + ret_o = c3n; + } + else { + switch ( i_wir ) { + default: { + ret_o = c3n; + } break; + + // XX should also be c3__ames + // + case c3__newt: { + ret_o = _ames_kick_newt(sam_u, u3k(tag), u3k(dat)); + } break; + + // XX obsolete + // + // used to also handle %west and %woot for tcp proxy setup + // + case c3__ames: { + ret_o = _( c3__init == tag); + } break; + + // this can return through dill due to our fscked up boot sequence + // + // XX s/b obsolete, verify + // + case c3__term: { + if ( c3__send != tag ) { + ret_o = c3n; + } + else { + u3l_log("kick: strange send\r\n"); + ret_o = _ames_kick_newt(sam_u, u3k(tag), u3k(dat)); + } + } break; + } + } + + u3z(wir); u3z(cad); + return ret_o; +} + +/* _ames_exit_cb(): dispose resources aftr close. +*/ +static void +_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; + } + + u3h_free(sam_u->lax_p); + + u3s_cue_xeno_done(sam_u->sil_u); + ur_cue_test_done(sam_u->tes_u); + + c3_free(sam_u); +} + +/* _fine_io_exit(): terminate fine I/O. +*/ +static void +_fine_io_exit(u3_auto* car_u) +{ + // cleanup handled in _ames_io_exit +} + +/* _ames_io_exit(): terminate ames I/O. +*/ +static void +_ames_io_exit(u3_auto* car_u) +{ + u3_ames* sam_u = (u3_ames*)car_u; + uv_close(&sam_u->had_u, _ames_exit_cb); +} + +/* _fine_io_info(): print status info. +*/ +static void +_fine_io_info(u3_auto* car_u) +{ + +} + + +/* _ames_io_info(): print status info. +*/ +static void +_ames_io_info(u3_auto* car_u) +{ + u3_ames* sam_u = (u3_ames*)car_u; + +# define FLAG(a) ( (c3y == a) ? "&" : "|" ) + + u3l_log(" config:\n"); + u3l_log(" filtering: %s\n", FLAG(sam_u->fig_u.fit_o)); + u3l_log(" can send: %s\n", FLAG(sam_u->fig_u.net_o)); + u3l_log(" can scry: %s\n", FLAG(sam_u->fig_u.see_o)); + u3l_log(" counters:\n"); + u3l_log(" dropped: %" PRIu64 "\n", sam_u->sat_u.dop_d); + u3l_log(" forwards dropped: %" PRIu64 "\n", sam_u->sat_u.fod_d); + u3l_log(" forwards pending: %" PRIu64 "\n", sam_u->sat_u.foq_d); + u3l_log(" forwarded: %" PRIu64 "\n", sam_u->sat_u.fow_d); + u3l_log(" filtered (hed): %" PRIu64 "\n", sam_u->sat_u.hed_d); + u3l_log(" filtered (ver): %" PRIu64 "\n", sam_u->sat_u.vet_d); + u3l_log(" filtered (mug): %" PRIu64 "\n", sam_u->sat_u.mut_d); + u3l_log(" filtered (bod): %" PRIu64 "\n", sam_u->sat_u.bod_d); + u3l_log(" crashed: %" PRIu64 "\n", sam_u->sat_u.fal_d); + u3l_log(" cached lanes: %u\n", u3h_wyt(sam_u->lax_p)); +} + +/* u3_ames_io_init(): initialize ames I/O. +*/ +u3_auto* +u3_ames_io_init(u3_pier* pir_u) +{ + u3_ames* sam_u = c3_calloc(sizeof(*sam_u)); + sam_u->pir_u = pir_u; + sam_u->fig_u.net_o = c3y; + sam_u->fig_u.see_o = c3y; + sam_u->fig_u.fit_o = c3n; + + // hashtable for scry cache + // TODO: review size + // 1500 bytes per packet * 100_000 = 150MB + // 50 bytes (average) per path * 100_000 = 5MB + sam_u->fin_s.sac_p = u3h_new_cache(100000); + + //NOTE some numbers on memory usage for the lane cache + // + // assuming we store: + // a (list lane) with 1 item, 1+8 + 1 + (6*2) = 22 words + // and a @da as timestamp, 8 words + // consed together, 6 words + // with worst-case (128-bit) @p keys, 8 words + // and an additional cell for the k-v pair, 6 words + // that makes for a per-entry memory use of 50 words => 200 bytes + // + // the 500k entries below would take about 100mb (in the worst case, but + // not accounting for hashtable overhead). + // we could afford more, but 500k entries is more than we'll likely use + // in the near future. + // + sam_u->lax_p = u3h_new_cache(500000); + + c3_assert( !uv_udp_init(u3L, &sam_u->wax_u) ); + sam_u->wax_u.data = sam_u; + + sam_u->sil_u = u3s_cue_xeno_init(); + sam_u->tes_u = ur_cue_test_init(); + + // Disable networking for fake ships + // + if ( c3y == sam_u->pir_u->fak_o ) { + u3_Host.ops_u.net = c3n; + } + + u3_auto* car_u = &sam_u->car_u; + car_u->nam_m = c3__ames; + car_u->liv_o = c3n; + car_u->io.talk_f = _ames_io_talk; + car_u->io.info_f = _ames_io_info; + car_u->io.kick_f = _ames_io_kick; + car_u->io.exit_f = _ames_io_exit; + + u3_auto* far_u = sam_u->fin_u.car_u; + far_u->nam_m = c3__fine; + far_u->liv_o = c3n; + far_u->io.talk_f = _fine_io_talk; + far_u->io.info_f = _fine_io_info; + far_u->io.kick_f = _fine_io_kick; + far_u->io.exit_f = _fine_io_exit; + + { + u3_noun now; + struct timeval tim_u; + gettimeofday(&tim_u, 0); + + now = u3_time_in_tv(&tim_u); + sam_u->sev_l = u3r_mug(now); + u3z(now); + } + + return car_u; +} diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index 64eea8eac..a457b045b 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -1136,7 +1136,7 @@ /* u3_ames_io_init(): initialize ames I/O. */ u3_auto* - u3_ames_io_init(u3_pier* pir_u); + u3_ames_io_init(u3_pier* pir_u, u3_auto** far_u); /* u3_ames_decode_lane(): destructure lane from noun */ diff --git a/pkg/urbit/vere/auto.c b/pkg/urbit/vere/auto.c index 5a56d22bc..0a6890113 100644 --- a/pkg/urbit/vere/auto.c +++ b/pkg/urbit/vere/auto.c @@ -405,10 +405,13 @@ u3_auto* u3_auto_init(u3_pier* pir_u) { u3_auto* car_u = 0; + u3_auto* fin_u = 0; car_u = _auto_link(u3_hind_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_behn_io_init(pir_u), pir_u, car_u); - car_u = _auto_link(u3_ames_io_init(pir_u), pir_u, car_u); + car_u = _auto_link(u3_ames_io_init(pir_u, &fin_u), pir_u, car_u); + // TODO: hacky, review + car_u = _auto_link(fin_u, pir_u, car_u); car_u = _auto_link(u3_http_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_cttp_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_unix_io_init(pir_u), pir_u, car_u); diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 5385c4b8e..7c76ee579 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -17,16 +17,20 @@ struct _u3_ames* sam_u; // ames backpointer } u3_pact; +/* u3_fine: fine networking +*/ + typedef struct _u3_fine { + u3_auto car_u; // fine driver + c3_y ver_y; // fine protocol + u3p(u3h_root) sac_p; // scry cache hashtable + struct _u3_ames* sam_u; // ames backpointer + } u3_fine; + /* u3_ames: ames networking. */ typedef struct _u3_ames { // packet network state u3_auto car_u; // ames driver - struct { - u3_auto car_u; // fine driver - c3_y ver_y; // fine protocol - u3p(u3h_root) sac_p; // scry cache hashtable - // TODO: stats, maybe config? etc. - } fin_s; + u3_fine fin_s; // fine networking u3_pier* pir_u; // pier union { // uv udp handle uv_udp_t wax_u; // @@ -94,7 +98,6 @@ } u3_requ; typedef struct _u3_reqp { - u3_ames* sam_u; u3_head hed_u; u3_requ req_u; } u3_reqp; @@ -123,6 +126,7 @@ c3_y* hun_y; // packet contents c3_w len_w; // packet contents u3_lane lan_u; // recipient lane + c3_w fra_w; // fragment number u3_ames* sam_u; // ames backpointer union { u3_resp* res_u; @@ -214,6 +218,40 @@ _ames_panc_free(u3_panc* pac_u) c3_free(pac_u); } +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_requ(u3_requ* req_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; +} + +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_sift_head(): parse packet header. */ static c3_o @@ -310,7 +348,7 @@ _ames_sift_prelude(u3_head* hed_u, 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; + len_y = rog_y + sen_y + rec_y + 1; pre_u->sic_y = pre_y[0] & 0xf; pre_u->ric_y = pre_y[0] & 0xf0; @@ -342,35 +380,44 @@ _fine_sift_requ(u3_head* hed_u, { c3_y pre_y = _ames_sift_prelude(hed_u, &req_u->pre_u, len_w, req_y); + //u3l_log("prelude size: %u\n", pre_y); + req_y += pre_y; c3_w rem_w = (64 + 4 + 2 + pre_y); if(rem_w > len_w) { + u3l_log("not big enough\n"); return c3n; } memcpy(req_u->sig_y, req_y, 64); req_y += 64; + //_log_bytes(req_y, 4); + req_u->fra_w = ( - (req_y[0] << 0x18) - | (req_y[1] << 0x10) - | (req_y[2] << 0x8) - | (req_y[3] << 0x0)); + (req_y[0] << 0x0) + | (req_y[1] << 0x8) + | (req_y[2] << 0x10) + | (req_y[3] << 0x18)); req_y += 4; req_u->len_s = c3_min(384, - (req_y[0] << 0x8) - | (req_y[1] << 0x0)); + (req_y[0] << 0x0) + | (req_y[1] << 0x8)); req_y += 2; + //_log_bytes(req_y, req_u->len_s); + // TODO: strict inequality? - if(rem_w + req_u->len_s != len_w) { + /*if(rem_w + req_u->len_s != len_w) { + u3l_log("bad format\n"); return c3n; - } + }*/ // TODO: defend maliciusly crafted lengths? req_u->pat_c = c3_calloc(req_u->len_s + 1); + u3l_log("byt: %x\n", *req_y); memcpy(req_u->pat_c, req_y, req_u->len_s); req_u->pat_c[req_u->len_s] = '\0'; @@ -387,36 +434,57 @@ _fine_sift_resp(u3_head* hed_u, { 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_y pre_y = _ames_sift_prelude(hed_u, &res_u->pre_u, len_w, res_y); res_y += pre_y; - memcpy(res_u->sig_y, res_y, 64); - res_y += 64; res_u->fra_w = ( - (res_y[0] << 0x18) - | (res_y[1] << 0x10) - | (res_y[2] << 0x8) - | (res_y[3] << 0x0)); + (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] << 0x8) - | (res_y[1] << 0x0)); + (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; + + u3l_log("dat siz: %u", res_u->siz_s); + + res_u->dat_y = c3_calloc(res_u->siz_s); + memcpy(&res_u->dat_y, res_y, res_u->siz_s); + + // TODO: strict inequality? - if(rem_w + res_u->len_s != len_w) { + /*if(rem_w + res_u->len_s != len_w) { return c3n; - } + }*/ // TODO: defend maliciusly crafted lengths? - res_u->pat_c = c3_malloc(res_u->len_s); - - memcpy(res_u->pat_c, res_y, res_u->len_s); // TODO: add null terminator? return c3y; } @@ -562,6 +630,7 @@ _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) { u3_pend* pen_u = (u3_pend*)req_u; u3_ames* sam_u = pen_u->sam_u; + u3l_log("ames: send \n"); if (sas_i) { u3l_log("ames: send fail: %s\n", uv_strerror(sas_i)); @@ -580,7 +649,7 @@ _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) static void _ames_send(u3_pend* pen_u) { - u3l_log("ames: send"); + u3l_log("ames: send\n"); u3_ames* sam_u = pen_u->sam_u; // TODO: prevalidation? @@ -611,7 +680,7 @@ _ames_send(u3_pend* pen_u) sam_u->fig_u.net_o = c3n; } - _ames_pend_free(pen_u); + //_ames_pend_free(pen_u); } } } @@ -646,6 +715,8 @@ u3_ames_lane_to_chub(u3_lane lan) { */ u3_atom u3_ames_encode_lane(u3_lane lan) { + // [%| p=@] + // [%& p=@pC] return u3i_chub(u3_ames_lane_to_chub(lan)); } @@ -787,7 +858,6 @@ _ames_czar_here(u3_pend* pen_u, time_t now, struct sockaddr_in* add_u) sam_u->imp_o[imp_y] = c3y; pen_u->lan_u.pip_w = pip_w; - _ames_send(pen_u); } /* _ames_czar_cb(): galaxy address resolution callback. @@ -1305,8 +1375,30 @@ _ames_skip(u3_body* bod_u) { */ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) { + + u3l_log("in scry cb\n"); u3_pend* pen_u = vod_p; - u3_weak pack = u3r_at(3, nun); + u3_weak pac = u3r_at(7, nun); + if(pac == u3_none) { + u3l_log("no result, bailing\n"); + return; + } + //u3m_p("pac:", pac); + u3_noun num = u3i_word(pen_u->fra_w - 1); + u3m_p("frag num", num); + + u3_noun fra = u3dc("snag", num, pac); + u3l_log("found fragment\n"); + + pen_u->len_w = u3r_met(3, fra); + pen_u->hun_y = c3_calloc(pen_u->len_w); + + u3r_bytes(0, pen_u->len_w, pen_u->hun_y, fra); + + + _fine_send(pen_u); + + // // hashtable = (path, packet_num) -> cached_result; // All cases, except 1st ~: put results in cache for all packets @@ -1315,7 +1407,7 @@ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) // [~ ~ *] -> send packet // TODO: cache logic, counting requests, evict? - u3_weak lan = _ames_lane_from_cache(pen_u->sam_u->lax_p, + /*u3_weak lan = _ames_lane_from_cache(pen_u->sam_u->lax_p, u3i_chubs(2, pen_u->her_d)); if(u3_none == lan) { // TODO: enqueue packet for later sending, populate lane cache @@ -1324,13 +1416,13 @@ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) } else { _fine_send(pen_u); } + */ } /* _fine_hear(): hear a (potential) packet, dispatch appropriately */ -// _fine_hear(sam_u, lan_u, len_w, hun_y) static void _fine_hear(u3_ames* sam_u, u3_lane lan_u, c3_w len_w, @@ -1340,11 +1432,10 @@ static void _fine_hear(u3_ames* sam_u, //u3_body bod_u; c3_assert ( c3n == _ames_sift_head(&hed_u, hun_y)); - // skip past header - len_w -= 4; - hun_y += 4; - - if(hed_u.req_o) { + + u3l_log("fine: request %u == %u \n", hed_u.req_o, c3y); + if(c3n == hed_u.req_o) { + u3l_log("fine: request\n"); // lookup in cache // (unit (unit (unit packet)) // ~ -> miss @@ -1353,12 +1444,22 @@ static void _fine_hear(u3_ames* sam_u, // [~ ~ ~ *] -> hit, w/ data u3_requ req_u; + // skip past header + len_w -= 4; + hun_y += 4; - _fine_sift_requ(&hed_u, &req_u, len_w, hun_y); + + c3_assert( c3y == _fine_sift_requ(&hed_u, &req_u, len_w, hun_y)); + + //_log_requ(&req_u); + + u3l_log("checking cache: %s\n", req_u.pat_c); u3_noun pat = u3i_string(req_u.pat_c); - u3_weak cac = u3h_git(sam_u->fin_s.sac_p, pat); + u3_weak cac = u3_none; // u3h_git(sam_u->fin_s.sac_p, pat); + + u3l_log("checked cache\n"); if(u3_none == cac) { // cache miss @@ -1368,22 +1469,36 @@ static void _fine_hear(u3_ames* sam_u, // eg: // /packet/gx/~zod/graph-store/5/graphs/~zod/test/message/10 // - u3_noun pax = u3nc(u3i_string("packet"), - u3do("stab", u3i_string(req_u.pat_c))); + u3l_log("constructing path\n"); + u3_noun pax = u3nc(u3i_string("message"), + u3do("stab", pat)); + u3l_log("constructed path\n"); + + u3_reqp* rep_u = c3_calloc(sizeof(*rep_u)); + u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); + + pen_u->sam_u = sam_u; + pen_u->typ_y = 2; + pen_u->req_u = rep_u; - u3_reqp* rep_u = c3_malloc(sizeof(*rep_u)); - rep_u->sam_u = sam_u; memcpy(&rep_u->hed_u, &hed_u, sizeof(u3_head)); memcpy(&rep_u->req_u, &req_u, sizeof(u3_requ)); + memcpy(&pen_u->lan_u, &lan_u, sizeof(u3_lane)); + u3l_log("frag num %u\n", req_u.fra_w); + pen_u->fra_w = req_u.fra_w; + + u3l_log("scrying...\n"); u3_pier_peek_last(sam_u->fin_s.car_u.pir_u, u3_nul, c3__fx, u3_nul, - pax, rep_u, _fine_pack_scry_cb); + pax, pen_u, _fine_pack_scry_cb); + } else if(u3_nul == cac) { // cache hit, unbound // do nothing, maybe report? } else { + u3l_log("cache hit\n"); // shape // u3_noun fra = u3dc("snag", u3i_word(req_u.fra_w), u3t(cac)); @@ -1419,24 +1534,50 @@ static void _fine_hear(u3_ames* sam_u, return; } } else { + u3l_log("fine: response\n"); u3_resp res_u; - _fine_sift_resp(&hed_u, &res_u, len_w, hun_y); - u3_noun pat = u3do("stab", u3i_string(res_u.pat_c)); - - + u3l_log("fine: parsing\n"); + // TODO: return + //_fine_sift_resp(&hed_u, &res_u, len_w, hun_y); + //u3l_log("pat: %s\n\n\n", res_u.pat_c); + //u3_noun pat = u3do("stab", u3i_string(res_u.pat_c)); + //u3m_p("pat", pat); // // u3_noun wir = u3nc(c3__fine, u3_nul); + u3l_log("made wire"); c3_w num_w = res_u.num_w; c3_w fra_w = res_u.fra_w; - u3_noun cad = u3nc(c3__purr, u3i_bytes(len_w, hun_y)); + u3l_log("making card"); + u3_noun cad = u3nt(c3__purr, + u3nt(0, c3n, u3_ames_encode_lane(lan_u)), + u3i_bytes(len_w, hun_y)); + u3l_log("making ovum"); u3_ovum* ovo_u = u3_ovum_init(0, c3__fine, wir, cad); + u3l_log("made ovum"); u3_auto_plan(&sam_u->fin_s.car_u, ovo_u); + u3l_log("sent ovum"); } } + + +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_lane lan_u, @@ -1444,28 +1585,35 @@ _fine_request(u3_ames* sam_u, { u3l_log("fine: request\n"); - u3_pend pen_u; - u3_head hed_u; - u3_requ req_u; - + u3_pend* pen_u = c3_calloc(sizeof(*pen_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); + pen_u->hun_y = req_y; + pen_u->len_w = req_w; - _ames_sift_head(&hed_u, req_y); + _ames_sift_head(hed_u, req_y); req_y += 4; req_w -= 4; - _fine_sift_requ(&hed_u, &req_u, req_w, req_y); + _log_head(hed_u); + _fine_sift_requ(hed_u, req_u, req_w, req_y); - pen_u.typ_y = 1; - pen_u.her_d[0] = req_u.pre_u.rec_d[0]; - pen_u.her_d[1] = req_u.pre_u.rec_d[1]; + _log_prel(&req_u->pre_u); - pen_u.lan_u = lan_u; - pen_u.sam_u = sam_u; + pen_u->typ_y = 1; + pen_u->her_d[0] = req_u->pre_u.rec_d[0]; + pen_u->her_d[1] = req_u->pre_u.rec_d[1]; + pen_u->lan_u.pip_w = lan_u.pip_w; + pen_u->lan_u.por_s = lan_u.por_s; + + pen_u->sam_u = sam_u; + _ames_czar(pen_u); } /* _ames_hear(): parse a (potential) packet, dispatch appropriately. @@ -1477,7 +1625,7 @@ _ames_hear(u3_ames* sam_u, c3_y* hun_y) { - u3l_log("ames: hear"); + u3l_log("ames: hear\n"); // TODO: move from stack to heap to avoid reparsing u3_head hed_u; u3_body bod_u; @@ -1512,7 +1660,9 @@ _ames_hear(u3_ames* sam_u, } else if (c3n == is_ames_o) { // TODO: dispatch fine request + u3l_log("fine: hear\n"); _fine_hear(sam_u, *lan_u, len_w, hun_y); + return; } // ensure the protocol version matches ours @@ -1734,15 +1884,18 @@ _ames_ef_turf(u3_ames* sam_u, u3_noun tuf) /* fine_io_kick:(): receive effect from arvo - * TODO: */ static c3_o _fine_io_kick(u3_auto* car_u, u3_noun wir, u3_noun nun) { - u3_ames* sam_u = (u3_ames*)car_u; + u3l_log("fine: received effect\n"); + u3_fine* fin_u = (u3_fine*)car_u; + u3_ames* sam_u = fin_u->sam_u; u3_noun hed = u3h(nun); - if(c3__hoot == hed) { + //u3m_p("head: ", hed); + + if(c3__howl == hed) { // TODO: respond to notification of bound data return c3y; - } else if(c3__howl == hed) { + } else if(c3__hoot == hed) { u3_noun lan, hot; u3x_cell(u3t(nun), &lan, &hot); u3_lane lan_u = u3_ames_decode_lane(lan); @@ -1817,6 +1970,13 @@ _fine_prot_scry_cb(void* vod_p, u3_noun nun) u3z(nun); } +/* _fine_io_talk(): start receiving ames traffic. +*/ +static void _fine_io_talk(u3_auto* car_u) +{ + // do nothing +} + /* _ames_io_talk(): start receiving ames traffic. @@ -1839,6 +1999,18 @@ _ames_io_talk(u3_auto* car_u) u3_auto_plan(car_u, u3_ovum_init(0, c3__a, wir, cad)); } + // send fine born + { + u3_noun wir = u3nt(c3__newt, + u3dc("scot", c3__uv, sam_u->sev_l), + u3_nul); + u3_noun cad = u3nc(c3__born, u3_nul); + + u3_auto_plan(&sam_u->fin_s.car_u, u3_ovum_init(0, c3__f, wir, cad)); + + } + + // TODO: scry the fine protocol out of arvo // u3_pier_peek_last(car_u->pir_u, u3_nul, c3__fx, u3_nul, @@ -1962,6 +2134,14 @@ _ames_exit_cb(uv_handle_t* had_u) c3_free(sam_u); } +/* _fine_io_exit(): terminate fine I/O. +*/ +static void +_fine_io_exit(u3_auto* car_u) +{ + // cleanup handled in _ames_io_exit +} + /* _ames_io_exit(): terminate ames I/O. */ static void @@ -1971,6 +2151,15 @@ _ames_io_exit(u3_auto* car_u) uv_close(&sam_u->had_u, _ames_exit_cb); } +/* _fine_io_info(): print status info. +*/ +static void +_fine_io_info(u3_auto* car_u) +{ + +} + + /* _ames_io_info(): print status info. */ static void @@ -2000,7 +2189,7 @@ _ames_io_info(u3_auto* car_u) /* u3_ames_io_init(): initialize ames I/O. */ u3_auto* -u3_ames_io_init(u3_pier* pir_u) +u3_ames_io_init(u3_pier* pir_u, u3_auto** far_u) { u3_ames* sam_u = c3_calloc(sizeof(*sam_u)); sam_u->pir_u = pir_u; @@ -2051,6 +2240,19 @@ u3_ames_io_init(u3_pier* pir_u) car_u->io.kick_f = _ames_io_kick; car_u->io.exit_f = _ames_io_exit; + u3_auto* fur_u = &sam_u->fin_s.car_u; + fur_u->nam_m = c3__fine; + fur_u->liv_o = c3y; + fur_u->io.talk_f = _fine_io_talk; + fur_u->io.info_f = _fine_io_info; + fur_u->io.kick_f = _fine_io_kick; + fur_u->io.exit_f = _fine_io_exit; + u3l_log("fur: %p\n", fur_u); + *far_u = fur_u; + u3l_log("far: %p\n", *far_u); + + sam_u->fin_s.sam_u = sam_u; + { u3_noun now; struct timeval tim_u; From f0aa946f576e8fca420e994528bc90d59ce005ed Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Wed, 26 Jan 2022 21:55:08 -0600 Subject: [PATCH 04/21] ames: remove logging --- pkg/urbit/vere/io/ames.c | 47 ++++------------------------------------ 1 file changed, 4 insertions(+), 43 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 7c76ee579..f4f5f945b 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -380,8 +380,6 @@ _fine_sift_requ(u3_head* hed_u, { c3_y pre_y = _ames_sift_prelude(hed_u, &req_u->pre_u, len_w, req_y); - //u3l_log("prelude size: %u\n", pre_y); - req_y += pre_y; c3_w rem_w = (64 + 4 + 2 + pre_y); @@ -417,7 +415,6 @@ _fine_sift_requ(u3_head* hed_u, // TODO: defend maliciusly crafted lengths? req_u->pat_c = c3_calloc(req_u->len_s + 1); - u3l_log("byt: %x\n", *req_y); memcpy(req_u->pat_c, req_y, req_u->len_s); req_u->pat_c[req_u->len_s] = '\0'; @@ -473,7 +470,6 @@ _fine_sift_resp(u3_head* hed_u, | (res_y[1] << 0x8)); res_y += 2; - u3l_log("dat siz: %u", res_u->siz_s); res_u->dat_y = c3_calloc(res_u->siz_s); memcpy(&res_u->dat_y, res_y, res_u->siz_s); @@ -630,7 +626,6 @@ _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) { u3_pend* pen_u = (u3_pend*)req_u; u3_ames* sam_u = pen_u->sam_u; - u3l_log("ames: send \n"); if (sas_i) { u3l_log("ames: send fail: %s\n", uv_strerror(sas_i)); @@ -649,7 +644,6 @@ _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) static void _ames_send(u3_pend* pen_u) { - u3l_log("ames: send\n"); u3_ames* sam_u = pen_u->sam_u; // TODO: prevalidation? @@ -1376,19 +1370,15 @@ _ames_skip(u3_body* bod_u) { static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) { - u3l_log("in scry cb\n"); u3_pend* pen_u = vod_p; u3_weak pac = u3r_at(7, nun); if(pac == u3_none) { u3l_log("no result, bailing\n"); return; } - //u3m_p("pac:", pac); u3_noun num = u3i_word(pen_u->fra_w - 1); - u3m_p("frag num", num); u3_noun fra = u3dc("snag", num, pac); - u3l_log("found fragment\n"); pen_u->len_w = u3r_met(3, fra); pen_u->hun_y = c3_calloc(pen_u->len_w); @@ -1433,9 +1423,7 @@ static void _fine_hear(u3_ames* sam_u, c3_assert ( c3n == _ames_sift_head(&hed_u, hun_y)); - u3l_log("fine: request %u == %u \n", hed_u.req_o, c3y); if(c3n == hed_u.req_o) { - u3l_log("fine: request\n"); // lookup in cache // (unit (unit (unit packet)) // ~ -> miss @@ -1454,12 +1442,11 @@ static void _fine_hear(u3_ames* sam_u, //_log_requ(&req_u); - u3l_log("checking cache: %s\n", req_u.pat_c); u3_noun pat = u3i_string(req_u.pat_c); + // TODO: revive u3_weak cac = u3_none; // u3h_git(sam_u->fin_s.sac_p, pat); - u3l_log("checked cache\n"); if(u3_none == cac) { // cache miss @@ -1469,11 +1456,9 @@ static void _fine_hear(u3_ames* sam_u, // eg: // /packet/gx/~zod/graph-store/5/graphs/~zod/test/message/10 // - u3l_log("constructing path\n"); u3_noun pax = u3nc(u3i_string("message"), u3do("stab", pat)); - u3l_log("constructed path\n"); u3_reqp* rep_u = c3_calloc(sizeof(*rep_u)); u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); @@ -1486,10 +1471,8 @@ static void _fine_hear(u3_ames* sam_u, memcpy(&rep_u->req_u, &req_u, sizeof(u3_requ)); memcpy(&pen_u->lan_u, &lan_u, sizeof(u3_lane)); - u3l_log("frag num %u\n", req_u.fra_w); pen_u->fra_w = req_u.fra_w; - u3l_log("scrying...\n"); u3_pier_peek_last(sam_u->fin_s.car_u.pir_u, u3_nul, c3__fx, u3_nul, pax, pen_u, _fine_pack_scry_cb); @@ -1498,7 +1481,6 @@ static void _fine_hear(u3_ames* sam_u, // cache hit, unbound // do nothing, maybe report? } else { - u3l_log("cache hit\n"); // shape // u3_noun fra = u3dc("snag", u3i_word(req_u.fra_w), u3t(cac)); @@ -1534,31 +1516,20 @@ static void _fine_hear(u3_ames* sam_u, return; } } else { - u3l_log("fine: response\n"); u3_resp res_u; - u3l_log("fine: parsing\n"); - // TODO: return - //_fine_sift_resp(&hed_u, &res_u, len_w, hun_y); - //u3l_log("pat: %s\n\n\n", res_u.pat_c); - //u3_noun pat = u3do("stab", u3i_string(res_u.pat_c)); - //u3m_p("pat", pat); - // - // + // TODO: check mug + u3_noun wir = u3nc(c3__fine, u3_nul); - u3l_log("made wire"); c3_w num_w = res_u.num_w; c3_w fra_w = res_u.fra_w; - u3l_log("making card"); + u3_noun cad = u3nt(c3__purr, u3nt(0, c3n, u3_ames_encode_lane(lan_u)), u3i_bytes(len_w, hun_y)); - u3l_log("making ovum"); u3_ovum* ovo_u = u3_ovum_init(0, c3__fine, wir, cad); - u3l_log("made ovum"); u3_auto_plan(&sam_u->fin_s.car_u, ovo_u); - u3l_log("sent ovum"); } } @@ -1600,12 +1571,8 @@ _fine_request(u3_ames* sam_u, req_y += 4; req_w -= 4; - _log_head(hed_u); - _fine_sift_requ(hed_u, req_u, req_w, req_y); - _log_prel(&req_u->pre_u); - pen_u->typ_y = 1; pen_u->her_d[0] = req_u->pre_u.rec_d[0]; pen_u->her_d[1] = req_u->pre_u.rec_d[1]; @@ -1625,7 +1592,6 @@ _ames_hear(u3_ames* sam_u, c3_y* hun_y) { - u3l_log("ames: hear\n"); // TODO: move from stack to heap to avoid reparsing u3_head hed_u; u3_body bod_u; @@ -1660,7 +1626,6 @@ _ames_hear(u3_ames* sam_u, } else if (c3n == is_ames_o) { // TODO: dispatch fine request - u3l_log("fine: hear\n"); _fine_hear(sam_u, *lan_u, len_w, hun_y); return; } @@ -1701,7 +1666,6 @@ _ames_hear(u3_ames* sam_u, // ensure the mug is valid // - u3l_log("bod: %ux, hed: %ux\n", hed_u.mug_l, bod_u.mug_l); if ( bod_u.mug_l != hed_u.mug_l ) { sam_u->sat_u.mut_d++; if ( 0 == (sam_u->sat_u.mut_d % 100000) ) { @@ -1886,7 +1850,6 @@ _ames_ef_turf(u3_ames* sam_u, u3_noun tuf) /* fine_io_kick:(): receive effect from arvo */ static c3_o _fine_io_kick(u3_auto* car_u, u3_noun wir, u3_noun nun) { - u3l_log("fine: received effect\n"); u3_fine* fin_u = (u3_fine*)car_u; u3_ames* sam_u = fin_u->sam_u; u3_noun hed = u3h(nun); @@ -2247,9 +2210,7 @@ u3_ames_io_init(u3_pier* pir_u, u3_auto** far_u) fur_u->io.info_f = _fine_io_info; fur_u->io.kick_f = _fine_io_kick; fur_u->io.exit_f = _fine_io_exit; - u3l_log("fur: %p\n", fur_u); *far_u = fur_u; - u3l_log("far: %p\n", *far_u); sam_u->fin_s.sam_u = sam_u; From c816d4378486eba4cf934087367ec3373d8430e0 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Wed, 26 Jan 2022 22:00:54 -0600 Subject: [PATCH 05/21] fine: remove unnecessary from in %purr --- pkg/urbit/vere/io/ames.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index f4f5f945b..61fd9715a 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -1525,7 +1525,7 @@ static void _fine_hear(u3_ames* sam_u, c3_w fra_w = res_u.fra_w; u3_noun cad = u3nt(c3__purr, - u3nt(0, c3n, u3_ames_encode_lane(lan_u)), + u3nc(c3n, u3_ames_encode_lane(lan_u)), u3i_bytes(len_w, hun_y)); u3_ovum* ovo_u = u3_ovum_init(0, c3__fine, wir, cad); From 2f78cf7e0130dc908bd5077f0d89d5b4d309a1fd Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Wed, 26 Jan 2022 22:21:40 -0600 Subject: [PATCH 06/21] ames: #freepackets --- pkg/urbit/vere/io/ames.c | 221 ++++++++++++++++++++++----------------- 1 file changed, 123 insertions(+), 98 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 61fd9715a..8309643dd 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -184,15 +184,16 @@ _ames_pact_free(u3_pact* pac_u) static void _ames_pend_free(u3_pend* pen_u) { - if(0 == pen_u->typ_y) { // ames packet + if ( 0 == pen_u->typ_y ) { // ames packet _ames_pact_free(pen_u->pac_u); - } else if (1 == pen_u->typ_y) { // fine request + } else if ( 1 == pen_u->typ_y ) { // fine request c3_free(pen_u->req_u); c3_free(pen_u->hun_y); } else { // fine response c3_free(pen_u->res_u); c3_free(pen_u->hun_y); } + c3_free(pen_u->dns_c); c3_free(pen_u); } @@ -635,7 +636,7 @@ _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) sam_u->fig_u.net_o = c3y; } - //_ames_pend_free(pen_u); + _ames_pend_free(pen_u); } #define _fine_send _ames_send @@ -674,7 +675,7 @@ _ames_send(u3_pend* pen_u) sam_u->fig_u.net_o = c3n; } - //_ames_pend_free(pen_u); + _ames_pend_free(pen_u); } } } @@ -1410,6 +1411,118 @@ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) } +static void _fine_hear_response(u3_ames* sam_u, + u3_lane lan_u, + c3_w len_w, + c3_y* hun_y) +{ + +} + + +static void _fine_hear_request(u3_ames* sam_u, + u3_lane lan_u, + c3_w len_w, + c3_y* hun_y) +{ + u3_head hed_u; + c3_assert ( c3n == _ames_sift_head(&hed_u, hun_y)); + // lookup in cache + // (unit (unit (unit packet)) + // ~ -> miss + // [~ ~] -> hit, unbound + // [~ ~ ~] -> hit, empty + // [~ ~ ~ *] -> hit, w/ data + 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 pat = u3i_string(req_u.pat_c); + + // TODO: revive + u3_weak cac = u3_none; // u3h_git(sam_u->fin_s.sac_p, pat); + + + if ( u3_none == cac ) { + // cache miss + // packet scry path + // /packet/requested/path/elements + // + // eg: + // /packet/gx/~zod/graph-store/5/graphs/~zod/test/message/10 + // + u3_noun pax = u3nc(u3i_string("message"), + u3do("stab", u3k(pat))); + + + u3_reqp* rep_u = c3_calloc(sizeof(*rep_u)); + u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); + + pen_u->sam_u = sam_u; + pen_u->typ_y = 2; + pen_u->req_u = rep_u; + + memcpy(&rep_u->hed_u, &hed_u, sizeof(u3_head)); + memcpy(&rep_u->req_u, &req_u, sizeof(u3_requ)); + + memcpy(&pen_u->lan_u, &lan_u, sizeof(u3_lane)); + pen_u->fra_w = req_u.fra_w; + + u3_pier_peek_last(sam_u->fin_s.car_u.pir_u, u3_nul, c3__fx, u3_nul, + pax, pen_u, _fine_pack_scry_cb); + + + } else if(u3_nul == cac) { + // cache hit, unbound + // do nothing, maybe report? + } else { + // shape + // + c3_w fra_w; + c3_y* fra_y; + + { + u3_noun fra = u3dc("snag", u3i_word(req_u.fra_w), u3t(cac)); + + fra_w = u3r_met(3, fra); + fra_y = c3_calloc(fra_w); + + u3r_bytes(0, fra_w, fra_y, fra); + + u3z(fra); + } + + u3_resp* res_u = c3_calloc(sizeof(*res_u)); + + c3_assert(c3y == _fine_sift_resp(&hed_u, res_u, fra_w, fra_y)); + + memcpy(&res_u->pre_u, &req_u.pre_u, sizeof(u3_prel)); + + c3_y* res_y; + c3_w res_w = _fine_etch_resp(&hed_u, res_u, &res_y); + + // TODO: where free? maybe stack allocate instead? + u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); + pen_u->typ_y = 2; + pen_u->res_u = res_u; + pen_u->len_w = res_w; + pen_u->hun_y = res_y; + pen_u->her_d[0] = res_u->pre_u.sen_d[0]; + pen_u->her_d[1] = res_u->pre_u.sen_d[1]; + pen_u->lan_u = lan_u; + pen_u->sam_u = sam_u; + + _fine_send(pen_u); + } + + u3z(pat); +} + + /* _fine_hear(): hear a (potential) packet, dispatch appropriately */ @@ -1419,102 +1532,11 @@ static void _fine_hear(u3_ames* sam_u, c3_y* hun_y) { u3_head hed_u; - //u3_body bod_u; c3_assert ( c3n == _ames_sift_head(&hed_u, hun_y)); if(c3n == hed_u.req_o) { - // lookup in cache - // (unit (unit (unit packet)) - // ~ -> miss - // [~ ~] -> hit, unbound - // [~ ~ ~] -> hit, empty - // [~ ~ ~ *] -> hit, w/ data - 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)); - - //_log_requ(&req_u); - - u3_noun pat = u3i_string(req_u.pat_c); - - // TODO: revive - u3_weak cac = u3_none; // u3h_git(sam_u->fin_s.sac_p, pat); - - - if(u3_none == cac) { - // cache miss - // packet scry path - // /packet/requested/path/elements - // - // eg: - // /packet/gx/~zod/graph-store/5/graphs/~zod/test/message/10 - // - u3_noun pax = u3nc(u3i_string("message"), - u3do("stab", pat)); - - - u3_reqp* rep_u = c3_calloc(sizeof(*rep_u)); - u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); - - pen_u->sam_u = sam_u; - pen_u->typ_y = 2; - pen_u->req_u = rep_u; - - memcpy(&rep_u->hed_u, &hed_u, sizeof(u3_head)); - memcpy(&rep_u->req_u, &req_u, sizeof(u3_requ)); - - memcpy(&pen_u->lan_u, &lan_u, sizeof(u3_lane)); - pen_u->fra_w = req_u.fra_w; - - u3_pier_peek_last(sam_u->fin_s.car_u.pir_u, u3_nul, c3__fx, u3_nul, - pax, pen_u, _fine_pack_scry_cb); - - - } else if(u3_nul == cac) { - // cache hit, unbound - // do nothing, maybe report? - } else { - // shape - // - u3_noun fra = u3dc("snag", u3i_word(req_u.fra_w), u3t(cac)); - // - - c3_w fra_w = u3r_met(3, fra); - c3_y* fra_y = c3_calloc(fra_w); - - u3r_bytes(0, fra_w, fra_y, fra); - - u3_resp* res_u = c3_calloc(sizeof(*res_u)); - - c3_assert(c3y == _fine_sift_resp(&hed_u, res_u, fra_w, fra_y)); - - memcpy(&res_u->pre_u, &req_u.pre_u, sizeof(u3_prel)); - - c3_y* res_y; - c3_w res_w = _fine_etch_resp(&hed_u, res_u, &res_y); - - // TODO: where free? maybe stack allocate instead? - u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); - pen_u->typ_y = 2; - pen_u->res_u = res_u; - pen_u->len_w = res_w; - pen_u->hun_y = res_y; - pen_u->her_d[0] = res_u->pre_u.sen_d[0]; - pen_u->her_d[1] = res_u->pre_u.sen_d[1]; - pen_u->lan_u = lan_u; - pen_u->sam_u = sam_u; - - _fine_send(pen_u); - - return; - } + _fine_hear_request(sam_u, lan_u, len_w, hun_y); } else { u3_resp res_u; @@ -1528,8 +1550,11 @@ static void _fine_hear(u3_ames* sam_u, u3nc(c3n, u3_ames_encode_lane(lan_u)), u3i_bytes(len_w, hun_y)); - u3_ovum* ovo_u = u3_ovum_init(0, c3__fine, wir, cad); + u3_ovum* ovo_u = u3_ovum_init(0, c3__fine, u3k(wir), u3k(cad)); u3_auto_plan(&sam_u->fin_s.car_u, ovo_u); + + u3z(cad); + u3z(wir); } } @@ -1554,7 +1579,6 @@ _fine_request(u3_ames* sam_u, u3_lane lan_u, u3_noun req) { - u3l_log("fine: request\n"); u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); u3_head* hed_u = c3_calloc(sizeof(*hed_u)); @@ -1580,6 +1604,7 @@ _fine_request(u3_ames* sam_u, pen_u->lan_u.por_s = lan_u.por_s; pen_u->sam_u = sam_u; + // TODO: revive for non-galaxy case _ames_czar(pen_u); } From 3a6b2352d0d6f7ef8919674dac3b495d56e4bc12 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Wed, 26 Jan 2022 22:35:37 -0600 Subject: [PATCH 07/21] ames: better protect against malicious packets --- pkg/urbit/vere/io/ames.c | 66 ++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 43 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 8309643dd..6346bfb7f 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -87,7 +87,6 @@ c3_d rog_d; // origin lane (optional) } u3_prel; -/* TODO: request response bodies for scry */ /* u3_requ: fine packet request */ typedef struct _u3_requ { u3_prel pre_u; @@ -371,7 +370,6 @@ _ames_sift_prelude(u3_head* hed_u, /* _fine_sift_requ(): parse request body, returning success - * TODO: bring up to date */ static c3_o _fine_sift_requ(u3_head* hed_u, @@ -384,7 +382,7 @@ _fine_sift_requ(u3_head* hed_u, req_y += pre_y; c3_w rem_w = (64 + 4 + 2 + pre_y); - if(rem_w > len_w) { + if ( rem_w > len_w ) { u3l_log("not big enough\n"); return c3n; } @@ -400,21 +398,17 @@ _fine_sift_requ(u3_head* hed_u, | (req_y[3] << 0x18)); req_y += 4; - req_u->len_s = c3_min(384, (req_y[0] << 0x0) | (req_y[1] << 0x8)); req_y += 2; - //_log_bytes(req_y, req_u->len_s); - - // TODO: strict inequality? - /*if(rem_w + req_u->len_s != len_w) { - u3l_log("bad format\n"); + 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); return c3n; - }*/ + } - // TODO: defend maliciusly crafted lengths? req_u->pat_c = c3_calloc(req_u->len_s + 1); memcpy(req_u->pat_c, req_y, req_u->len_s); @@ -1416,7 +1410,21 @@ static void _fine_hear_response(u3_ames* sam_u, c3_w len_w, c3_y* hun_y) { + u3_resp res_u; + 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__purr, + u3nc(c3n, u3_ames_encode_lane(lan_u)), + u3i_bytes(len_w, hun_y)); + + u3_ovum* ovo_u = u3_ovum_init(0, c3__fine, u3k(wir), u3k(cad)); + u3_auto_plan(&sam_u->fin_s.car_u, ovo_u); + + u3z(cad); + u3z(wir); } @@ -1427,6 +1435,8 @@ static void _fine_hear_request(u3_ames* sam_u, { u3_head hed_u; c3_assert ( c3n == _ames_sift_head(&hed_u, hun_y)); + // TODO: check mug + // lookup in cache // (unit (unit (unit packet)) // ~ -> miss @@ -1534,27 +1544,10 @@ static void _fine_hear(u3_ames* sam_u, u3_head hed_u; c3_assert ( c3n == _ames_sift_head(&hed_u, hun_y)); - if(c3n == hed_u.req_o) { _fine_hear_request(sam_u, lan_u, len_w, hun_y); } else { - u3_resp res_u; - - // TODO: check mug - - 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__purr, - u3nc(c3n, u3_ames_encode_lane(lan_u)), - u3i_bytes(len_w, hun_y)); - - u3_ovum* ovo_u = u3_ovum_init(0, c3__fine, u3k(wir), u3k(cad)); - u3_auto_plan(&sam_u->fin_s.car_u, ovo_u); - - u3z(cad); - u3z(wir); + _fine_hear_response(sam_u, lan_u, len_w, hun_y); } } @@ -1650,7 +1643,6 @@ _ames_hear(u3_ames* sam_u, return; } else if (c3n == is_ames_o) { - // TODO: dispatch fine request _fine_hear(sam_u, *lan_u, len_w, hun_y); return; } @@ -1894,16 +1886,6 @@ static c3_o _fine_io_kick(u3_auto* car_u, u3_noun wir, u3_noun nun) { } } -static void _fine_send_fail() -{ - // TODO: log some shit -} - -static void _fine_send_cb() -{ - // TODO: anything to do here? -} - /* _ames_prot_scry_cb(): receive ames protocol version */ static void @@ -1999,8 +1981,6 @@ _ames_io_talk(u3_auto* car_u) } - // TODO: scry the fine protocol out of arvo - // u3_pier_peek_last(car_u->pir_u, u3_nul, c3__fx, u3_nul, u3nt(u3i_string("protocol"), u3i_string("version"), u3_nul), sam_u, _fine_prot_scry_cb); @@ -2186,7 +2166,7 @@ u3_ames_io_init(u3_pier* pir_u, u3_auto** far_u) sam_u->fig_u.fit_o = c3n; // hashtable for scry cache - // TODO: review size + // // 1500 bytes per packet * 100_000 = 150MB // 50 bytes (average) per path * 100_000 = 5MB sam_u->fin_s.sac_p = u3h_new_cache(100000); From 00b7d2c4d4d6c7ea962145cb26edbca3e4933dc3 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Wed, 26 Jan 2022 22:53:31 -0600 Subject: [PATCH 08/21] ames: improve error handling --- pkg/urbit/vere/io/ames.c | 47 +++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 6346bfb7f..7fa90108d 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -1459,16 +1459,9 @@ static void _fine_hear_request(u3_ames* sam_u, if ( u3_none == cac ) { // cache miss - // packet scry path - // /packet/requested/path/elements - // - // eg: - // /packet/gx/~zod/graph-store/5/graphs/~zod/test/message/10 - // u3_noun pax = u3nc(u3i_string("message"), u3do("stab", u3k(pat))); - u3_reqp* rep_u = c3_calloc(sizeof(*rep_u)); u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); @@ -1485,7 +1478,6 @@ static void _fine_hear_request(u3_ames* sam_u, u3_pier_peek_last(sam_u->fin_s.car_u.pir_u, u3_nul, c3__fx, u3_nul, pax, pen_u, _fine_pack_scry_cb); - } else if(u3_nul == cac) { // cache hit, unbound // do nothing, maybe report? @@ -1508,25 +1500,26 @@ static void _fine_hear_request(u3_ames* sam_u, u3_resp* res_u = c3_calloc(sizeof(*res_u)); - c3_assert(c3y == _fine_sift_resp(&hed_u, res_u, fra_w, fra_y)); - - memcpy(&res_u->pre_u, &req_u.pre_u, sizeof(u3_prel)); + if ( c3n == _fine_sift_resp(&hed_u, res_u, fra_w, fra_y) ) { + c3_free(res_u); + } else { + memcpy(&res_u->pre_u, &req_u.pre_u, sizeof(u3_prel)); - c3_y* res_y; - c3_w res_w = _fine_etch_resp(&hed_u, res_u, &res_y); + c3_y* res_y; + c3_w res_w = _fine_etch_resp(&hed_u, res_u, &res_y); - // TODO: where free? maybe stack allocate instead? - u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); - pen_u->typ_y = 2; - pen_u->res_u = res_u; - pen_u->len_w = res_w; - pen_u->hun_y = res_y; - pen_u->her_d[0] = res_u->pre_u.sen_d[0]; - pen_u->her_d[1] = res_u->pre_u.sen_d[1]; - pen_u->lan_u = lan_u; - pen_u->sam_u = sam_u; + u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); + pen_u->typ_y = 2; + pen_u->res_u = res_u; + pen_u->len_w = res_w; + pen_u->hun_y = res_y; + pen_u->her_d[0] = res_u->pre_u.sen_d[0]; + pen_u->her_d[1] = res_u->pre_u.sen_d[1]; + pen_u->lan_u = lan_u; + pen_u->sam_u = sam_u; - _fine_send(pen_u); + _fine_send(pen_u); + } } u3z(pat); @@ -1542,9 +1535,9 @@ static void _fine_hear(u3_ames* sam_u, c3_y* hun_y) { u3_head hed_u; - c3_assert ( c3n == _ames_sift_head(&hed_u, hun_y)); - - if(c3n == hed_u.req_o) { + 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); From 64ab395fd0fd2eac0b0b50024337a0e4d8e2fa30 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Thu, 27 Jan 2022 14:57:15 -0600 Subject: [PATCH 09/21] ames: cache scry packets --- pkg/urbit/vere/io/ames.c | 117 ++++++++++++++------------------------- 1 file changed, 43 insertions(+), 74 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 7fa90108d..b4ab3aa75 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -630,7 +630,7 @@ _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) sam_u->fig_u.net_o = c3y; } - _ames_pend_free(pen_u); + //_ames_pend_free(pen_u); } #define _fine_send _ames_send @@ -669,7 +669,7 @@ _ames_send(u3_pend* pen_u) sam_u->fig_u.net_o = c3n; } - _ames_pend_free(pen_u); + //_ames_pend_free(pen_u); } } } @@ -1359,18 +1359,8 @@ _ames_skip(u3_body* bod_u) { } #endif -/* _fine_pack_scry_cb(): receive all packets for datum out of fine - * TODO: implement - */ -static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) +static void _fine_got_pack(u3_pend* pen_u, u3_noun pac) { - - u3_pend* pen_u = vod_p; - u3_weak pac = u3r_at(7, nun); - if(pac == u3_none) { - u3l_log("no result, bailing\n"); - return; - } u3_noun num = u3i_word(pen_u->fra_w - 1); u3_noun fra = u3dc("snag", num, pac); @@ -1404,6 +1394,32 @@ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) */ } +/* _fine_pack_scry_cb(): receive all packets for datum out of fine + * TODO: implement + */ +static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) +{ + u3l_log("got scry result\n"); + + u3_pend* pen_u = vod_p; + u3_ames* sam_u = pen_u->sam_u; + u3_weak pac = u3r_at(7, nun); + if(pac == u3_none) { + u3l_log("no result, bailing\n"); + return; + } + c3_assert( 1 == pen_u->typ_y); + u3_noun pax = u3i_string(pen_u->req_u->req_u.pat_c); + u3l_log("path: %s\n", pen_u->req_u->req_u.pat_c); + u3l_log("made pax\n"); + + u3h_put(sam_u->fin_s.sac_p, u3k(pax), u3k(pac)); + u3l_log("got scry result\n"); + + _fine_got_pack(pen_u, u3k(pac)); +} + + static void _fine_hear_response(u3_ames* sam_u, u3_lane lan_u, @@ -1437,12 +1453,6 @@ static void _fine_hear_request(u3_ames* sam_u, c3_assert ( c3n == _ames_sift_head(&hed_u, hun_y)); // TODO: check mug - // lookup in cache - // (unit (unit (unit packet)) - // ~ -> miss - // [~ ~] -> hit, unbound - // [~ ~ ~] -> hit, empty - // [~ ~ ~ *] -> hit, w/ data u3_requ req_u; // skip past header @@ -1454,72 +1464,31 @@ static void _fine_hear_request(u3_ames* sam_u, u3_noun pat = u3i_string(req_u.pat_c); // TODO: revive - u3_weak cac = u3_none; // u3h_git(sam_u->fin_s.sac_p, pat); + u3_weak cac = u3h_git(sam_u->fin_s.sac_p, pat); + u3_reqp* rep_u = c3_calloc(sizeof(*rep_u)); + u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); + + pen_u->sam_u = sam_u; + pen_u->typ_y = 1; + pen_u->req_u = rep_u; + + memcpy(&rep_u->hed_u, &hed_u, sizeof(u3_head)); + memcpy(&rep_u->req_u, &req_u, sizeof(u3_requ)); + + memcpy(&pen_u->lan_u, &lan_u, sizeof(u3_lane)); + pen_u->fra_w = req_u.fra_w; if ( u3_none == cac ) { // cache miss u3_noun pax = u3nc(u3i_string("message"), u3do("stab", u3k(pat))); - u3_reqp* rep_u = c3_calloc(sizeof(*rep_u)); - u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); - - pen_u->sam_u = sam_u; - pen_u->typ_y = 2; - pen_u->req_u = rep_u; - - memcpy(&rep_u->hed_u, &hed_u, sizeof(u3_head)); - memcpy(&rep_u->req_u, &req_u, sizeof(u3_requ)); - - memcpy(&pen_u->lan_u, &lan_u, sizeof(u3_lane)); - pen_u->fra_w = req_u.fra_w; - u3_pier_peek_last(sam_u->fin_s.car_u.pir_u, u3_nul, c3__fx, u3_nul, pax, pen_u, _fine_pack_scry_cb); - } else if(u3_nul == cac) { - // cache hit, unbound - // do nothing, maybe report? } else { - // shape - // - c3_w fra_w; - c3_y* fra_y; - - { - u3_noun fra = u3dc("snag", u3i_word(req_u.fra_w), u3t(cac)); - - fra_w = u3r_met(3, fra); - fra_y = c3_calloc(fra_w); - - u3r_bytes(0, fra_w, fra_y, fra); - - u3z(fra); - } - - u3_resp* res_u = c3_calloc(sizeof(*res_u)); - - if ( c3n == _fine_sift_resp(&hed_u, res_u, fra_w, fra_y) ) { - c3_free(res_u); - } else { - memcpy(&res_u->pre_u, &req_u.pre_u, sizeof(u3_prel)); - - c3_y* res_y; - c3_w res_w = _fine_etch_resp(&hed_u, res_u, &res_y); - - u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); - pen_u->typ_y = 2; - pen_u->res_u = res_u; - pen_u->len_w = res_w; - pen_u->hun_y = res_y; - pen_u->her_d[0] = res_u->pre_u.sen_d[0]; - pen_u->her_d[1] = res_u->pre_u.sen_d[1]; - pen_u->lan_u = lan_u; - pen_u->sam_u = sam_u; - - _fine_send(pen_u); - } + _fine_got_pack(pen_u, u3k(cac)); } u3z(pat); From d5040e7eae93acd2612c8cfdc2a64f9ba116daeb Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Thu, 27 Jan 2022 15:36:40 -0600 Subject: [PATCH 10/21] fine: correctly decode lane for the non-galaxy case --- pkg/urbit/vere/io/ames.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index b4ab3aa75..382ce0df8 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -1531,7 +1531,7 @@ static void _log_head(u3_head* hed_u) static void _fine_request(u3_ames* sam_u, - u3_lane lan_u, + u3_noun lan, u3_noun req) { @@ -1555,12 +1555,25 @@ _fine_request(u3_ames* sam_u, pen_u->typ_y = 1; pen_u->her_d[0] = req_u->pre_u.rec_d[0]; pen_u->her_d[1] = req_u->pre_u.rec_d[1]; - pen_u->lan_u.pip_w = lan_u.pip_w; - pen_u->lan_u.por_s = lan_u.por_s; - pen_u->sam_u = sam_u; - // TODO: revive for non-galaxy case - _ames_czar(pen_u); + + { + u3_noun tag, val; + u3x_cell(lan, &tag, &val); + u3m_p("tag", tag); + u3m_p("val", val); + if(tag == 0) { + _ames_czar(pen_u); + } else { + u3_lane lan_u = u3_ames_decode_lane(val); + pen_u->lan_u.pip_w = lan_u.pip_w; + u3l_log("IP: %u", lan_u.pip_w); + u3l_log("port: %u", lan_u.por_s); + pen_u->lan_u.por_s = lan_u.por_s; + + _ames_send(pen_u); + } + } } /* _ames_hear(): parse a (potential) packet, dispatch appropriately. @@ -1840,8 +1853,7 @@ static c3_o _fine_io_kick(u3_auto* car_u, u3_noun wir, u3_noun nun) { } else if(c3__hoot == hed) { u3_noun lan, hot; u3x_cell(u3t(nun), &lan, &hot); - u3_lane lan_u = u3_ames_decode_lane(lan); - _fine_request(sam_u, lan_u, hot); + _fine_request(sam_u, lan, hot); return c3y; } else { return c3n; From 10e617d4abe0ce285e05161d3e2d9208378791e8 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Fri, 28 Jan 2022 14:09:42 -0600 Subject: [PATCH 11/21] fine: prevent null ptr deref in _ames_pend_free --- pkg/urbit/vere/io/ames.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 382ce0df8..249aad54d 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -184,16 +184,18 @@ static void _ames_pend_free(u3_pend* pen_u) { if ( 0 == pen_u->typ_y ) { // ames packet - _ames_pact_free(pen_u->pac_u); + if( pen_u->pac_u ) { + _ames_pact_free(pen_u->pac_u); + } } else if ( 1 == pen_u->typ_y ) { // fine request c3_free(pen_u->req_u); - c3_free(pen_u->hun_y); } else { // fine response c3_free(pen_u->res_u); - c3_free(pen_u->hun_y); } c3_free(pen_u->dns_c); + c3_free(pen_u->hun_y); + c3_free(pen_u); } @@ -597,7 +599,7 @@ _ames_etch_pack(u3_head* hed_u, 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_malloc(len_w); // output buf + c3_y* pac_y = c3_calloc(len_w); // output buf c3_y* bod_y = pac_y + 4; // body cursor // serialize the head @@ -630,7 +632,7 @@ _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) sam_u->fig_u.net_o = c3y; } - //_ames_pend_free(pen_u); + _ames_pend_free(pen_u); } #define _fine_send _ames_send @@ -669,7 +671,7 @@ _ames_send(u3_pend* pen_u) sam_u->fig_u.net_o = c3n; } - //_ames_pend_free(pen_u); + _ames_pend_free(pen_u); } } } @@ -1560,17 +1562,12 @@ _fine_request(u3_ames* sam_u, { u3_noun tag, val; u3x_cell(lan, &tag, &val); - u3m_p("tag", tag); - u3m_p("val", val); if(tag == 0) { _ames_czar(pen_u); } else { u3_lane lan_u = u3_ames_decode_lane(val); pen_u->lan_u.pip_w = lan_u.pip_w; - u3l_log("IP: %u", lan_u.pip_w); - u3l_log("port: %u", lan_u.por_s); pen_u->lan_u.por_s = lan_u.por_s; - _ames_send(pen_u); } } From 3ec30d3e5755ac803aa26b465e284e7dbf9ae260 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Fri, 28 Jan 2022 15:18:14 -0600 Subject: [PATCH 12/21] ames: revamp scry cache Update scry cache to be a map of [path num] -> fragment --- pkg/urbit/vere/io/ames.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 249aad54d..da7699d28 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -1361,12 +1361,8 @@ _ames_skip(u3_body* bod_u) { } #endif -static void _fine_got_pack(u3_pend* pen_u, u3_noun pac) +static void _fine_got_pack(u3_pend* pen_u, u3_noun fra) { - u3_noun num = u3i_word(pen_u->fra_w - 1); - - u3_noun fra = u3dc("snag", num, pac); - pen_u->len_w = u3r_met(3, fra); pen_u->hun_y = c3_calloc(pen_u->len_w); @@ -1411,14 +1407,24 @@ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) return; } c3_assert( 1 == pen_u->typ_y); + u3_weak fra = u3_none; u3_noun pax = u3i_string(pen_u->req_u->req_u.pat_c); - u3l_log("path: %s\n", pen_u->req_u->req_u.pat_c); - u3l_log("made pax\n"); - - u3h_put(sam_u->fin_s.sac_p, u3k(pax), u3k(pac)); - u3l_log("got scry result\n"); - - _fine_got_pack(pen_u, u3k(pac)); + u3l_log("made string\n"); + c3_w cur_w = 1; + u3_noun lis = u3k(pac); + while(pac != u3_nul) { + u3h_put(sam_u->fin_s.sac_p, u3nc(u3k(pax), u3i_word(cur_w)), u3h(pac)); + if ( pen_u->fra_w == cur_w ) { + fra = u3k(u3h(pac)); + } + cur_w++; + pac = u3t(pac); + } + if ( fra == u3_none ) { + u3l_log("fragment number out of range\n"); + } else { + _fine_got_pack(pen_u, fra); + } } @@ -1464,9 +1470,10 @@ static void _fine_hear_request(u3_ames* sam_u, c3_assert( c3y == _fine_sift_requ(&hed_u, &req_u, len_w, hun_y)); u3_noun pat = u3i_string(req_u.pat_c); + u3_noun key = u3nc(u3k(pat), u3i_word(req_u.fra_w)); // TODO: revive - u3_weak cac = u3h_git(sam_u->fin_s.sac_p, pat); + u3_weak cac = u3h_git(sam_u->fin_s.sac_p, key); u3_reqp* rep_u = c3_calloc(sizeof(*rep_u)); u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); From 1e924cfa404b3bcd8260043e8e5b040bd9c9c7bd Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Mon, 31 Jan 2022 17:34:32 -0600 Subject: [PATCH 13/21] urbit: move fine runtime into ames --- pkg/urbit/include/vere/vere.h | 2 +- pkg/urbit/vere/auto.c | 5 +- pkg/urbit/vere/io/ames.c | 94 ++++++++++------------------------- 3 files changed, 27 insertions(+), 74 deletions(-) diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index a457b045b..64eea8eac 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -1136,7 +1136,7 @@ /* u3_ames_io_init(): initialize ames I/O. */ u3_auto* - u3_ames_io_init(u3_pier* pir_u, u3_auto** far_u); + u3_ames_io_init(u3_pier* pir_u); /* u3_ames_decode_lane(): destructure lane from noun */ diff --git a/pkg/urbit/vere/auto.c b/pkg/urbit/vere/auto.c index 0a6890113..5a56d22bc 100644 --- a/pkg/urbit/vere/auto.c +++ b/pkg/urbit/vere/auto.c @@ -405,13 +405,10 @@ u3_auto* u3_auto_init(u3_pier* pir_u) { u3_auto* car_u = 0; - u3_auto* fin_u = 0; car_u = _auto_link(u3_hind_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_behn_io_init(pir_u), pir_u, car_u); - car_u = _auto_link(u3_ames_io_init(pir_u, &fin_u), pir_u, car_u); - // TODO: hacky, review - car_u = _auto_link(fin_u, pir_u, car_u); + car_u = _auto_link(u3_ames_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_http_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_cttp_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_unix_io_init(pir_u), pir_u, car_u); diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index da7699d28..beb49fded 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -20,7 +20,6 @@ /* u3_fine: fine networking */ typedef struct _u3_fine { - u3_auto car_u; // fine driver c3_y ver_y; // fine protocol u3p(u3h_root) sac_p; // scry cache hashtable struct _u3_ames* sam_u; // ames backpointer @@ -989,16 +988,20 @@ _ames_ef_send(u3_ames* sam_u, u3_noun lan, u3_noun pac) pac_u->len_w = u3r_met(3, pac); pac_u->hun_y = c3_malloc(pac_u->len_w); + u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); - pen_u->typ_y = 0; pen_u->len_w = pac_u->len_w; pen_u->hun_y = pac_u->hun_y; pen_u->sam_u = sam_u; - - 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); + pen_u->typ_y = + hed_u.sim_o == c3y ? 0 : + hed_u.req_o == c3y ? 1 : 2; + u3_noun tag, val; u3x_cell(lan, &tag, &val); c3_assert( (c3y == tag) || (c3n == tag) ); @@ -1177,7 +1180,6 @@ _ames_forward(u3_panc* pac_u, u3_noun las) // if ( c3n == u3r_cell(lan, &tag, &dat) ) { u3l_log("ames: bogus lane\n"); - u3m_p("lan", lan); } else { c3_o sen_o = c3y; @@ -1440,12 +1442,12 @@ static void _fine_hear_response(u3_ames* sam_u, c3_w num_w = res_u.num_w; c3_w fra_w = res_u.fra_w; - u3_noun cad = u3nt(c3__purr, + u3_noun cad = u3nt(c3__hear, u3nc(c3n, u3_ames_encode_lane(lan_u)), u3i_bytes(len_w, hun_y)); - u3_ovum* ovo_u = u3_ovum_init(0, c3__fine, u3k(wir), u3k(cad)); - u3_auto_plan(&sam_u->fin_s.car_u, ovo_u); + u3_ovum* ovo_u = u3_ovum_init(0, c3__ames, u3k(wir), u3k(cad)); + u3_auto_plan(&sam_u->car_u, ovo_u); u3z(cad); u3z(wir); @@ -1490,10 +1492,11 @@ static void _fine_hear_request(u3_ames* sam_u, if ( u3_none == cac ) { // cache miss - u3_noun pax = u3nc(u3i_string("message"), + u3_noun pax = u3nt(u3i_string("fine"), + u3i_string("message"), u3do("stab", u3k(pat))); - u3_pier_peek_last(sam_u->fin_s.car_u.pir_u, u3_nul, c3__fx, u3_nul, + u3_pier_peek_last(sam_u->car_u.pir_u, u3_nul, c3__ax, u3_nul, pax, pen_u, _fine_pack_scry_cb); } else { @@ -1843,27 +1846,6 @@ _ames_ef_turf(u3_ames* sam_u, u3_noun tuf) } -/* fine_io_kick:(): receive effect from arvo - */ -static c3_o _fine_io_kick(u3_auto* car_u, u3_noun wir, u3_noun nun) { - u3_fine* fin_u = (u3_fine*)car_u; - u3_ames* sam_u = fin_u->sam_u; - u3_noun hed = u3h(nun); - //u3m_p("head: ", hed); - - if(c3__howl == hed) { - // TODO: respond to notification of bound data - return c3y; - } else if(c3__hoot == hed) { - u3_noun lan, hot; - u3x_cell(u3t(nun), &lan, &hot); - _fine_request(sam_u, lan, hot); - return c3y; - } else { - return c3n; - } -} - /* _ames_prot_scry_cb(): receive ames protocol version */ static void @@ -1918,15 +1900,6 @@ _fine_prot_scry_cb(void* vod_p, u3_noun nun) u3z(nun); } -/* _fine_io_talk(): start receiving ames traffic. -*/ -static void _fine_io_talk(u3_auto* car_u) -{ - // do nothing -} - - - /* _ames_io_talk(): start receiving ames traffic. */ static void @@ -1947,17 +1920,6 @@ _ames_io_talk(u3_auto* car_u) u3_auto_plan(car_u, u3_ovum_init(0, c3__a, wir, cad)); } - // send fine born - { - u3_noun wir = u3nt(c3__newt, - u3dc("scot", c3__uv, sam_u->sev_l), - u3_nul); - u3_noun cad = u3nc(c3__born, u3_nul); - - u3_auto_plan(&sam_u->fin_s.car_u, u3_ovum_init(0, c3__f, wir, cad)); - - } - u3_pier_peek_last(car_u->pir_u, u3_nul, c3__fx, u3_nul, u3nt(u3i_string("protocol"), u3i_string("version"), u3_nul), @@ -1997,6 +1959,17 @@ _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__howl: { + 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); @@ -2080,14 +2053,6 @@ _ames_exit_cb(uv_handle_t* had_u) c3_free(sam_u); } -/* _fine_io_exit(): terminate fine I/O. -*/ -static void -_fine_io_exit(u3_auto* car_u) -{ - // cleanup handled in _ames_io_exit -} - /* _ames_io_exit(): terminate ames I/O. */ static void @@ -2135,7 +2100,7 @@ _ames_io_info(u3_auto* car_u) /* u3_ames_io_init(): initialize ames I/O. */ u3_auto* -u3_ames_io_init(u3_pier* pir_u, u3_auto** far_u) +u3_ames_io_init(u3_pier* pir_u) { u3_ames* sam_u = c3_calloc(sizeof(*sam_u)); sam_u->pir_u = pir_u; @@ -2186,15 +2151,6 @@ u3_ames_io_init(u3_pier* pir_u, u3_auto** far_u) car_u->io.kick_f = _ames_io_kick; car_u->io.exit_f = _ames_io_exit; - u3_auto* fur_u = &sam_u->fin_s.car_u; - fur_u->nam_m = c3__fine; - fur_u->liv_o = c3y; - fur_u->io.talk_f = _fine_io_talk; - fur_u->io.info_f = _fine_io_info; - fur_u->io.kick_f = _fine_io_kick; - fur_u->io.exit_f = _fine_io_exit; - *far_u = fur_u; - sam_u->fin_s.sam_u = sam_u; { From 225aefb4ff3872c29ff51c6a30dedc38c294988e Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Tue, 1 Feb 2022 12:40:47 -0600 Subject: [PATCH 14/21] ames: unify disparate packet types --- pkg/urbit/vere/io/ames.c | 344 ++++++++++++++++----------------------- 1 file changed, 143 insertions(+), 201 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index beb49fded..202304d57 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -5,17 +5,7 @@ #include "vere/vere.h" #include "ur/serial.h" -/* u3_pact: outbound ames packet. -*/ - typedef struct _u3_pact { - uv_udp_send_t snd_u; // udp send request - u3_lane lan_u; // destination lane - c3_w len_w; // length in bytes - c3_y* hun_y; // packet buffer - c3_y imp_y; // galaxy number (optional) - c3_c* dns_c; // galaxy fqdn (optional) - struct _u3_ames* sam_u; // ames backpointer - } u3_pact; + /* u3_fine: fine networking */ @@ -95,11 +85,6 @@ c3_c* pat_c; // path as ascii } u3_requ; - typedef struct _u3_reqp { - u3_head hed_u; - u3_requ req_u; - } u3_reqp; - /* u3_resp: fine packet response */ typedef struct _u3_resp { u3_prel pre_u; @@ -115,23 +100,7 @@ } u3_resp; - /* u3_pend: generic ames or fine pending packet */ - typedef struct _u3_pend { - uv_udp_send_t snd_u; // udp send request - c3_y typ_y; // 0 for ames, 1 for fine request, 2 for fine response - c3_d her_d[2]; // recipent mars address - c3_c* dns_c; // galaxy FQDN - c3_y* hun_y; // packet contents - c3_w len_w; // packet contents - u3_lane lan_u; // recipient lane - c3_w fra_w; // fragment number - u3_ames* sam_u; // ames backpointer - union { - u3_resp* res_u; - u3_reqp* req_u; - u3_pact* pac_u; - }; - } u3_pend; + /* u3_body: ames packet body */ @@ -142,6 +111,25 @@ c3_l mug_l; // checksum } u3_body; +/* u3_pact: outbound ames packet. +*/ + typedef struct _u3_pact { + uv_udp_send_t snd_u; // udp send request + u3_lane lan_u; // destination lane + 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; + union { + u3_resp res_u; + u3_requ req_u; + u3_body bod_u; + }; + } u3_pact; + /* u3_panc: deconstructed incoming packet */ typedef struct _u3_panc { @@ -169,33 +157,21 @@ _ames_alloc(uv_handle_t* had_u, *buf = uv_buf_init(ptr_v, 2048); } -/* _ames_pact_free(): free packet struct. -*/ static void -_ames_pact_free(u3_pact* pac_u) +_ames_pact_free(u3_pact* pac_u) { - c3_free(pac_u->hun_y); - c3_free(pac_u->dns_c); - c3_free(pac_u); -} - -static void -_ames_pend_free(u3_pend* pen_u) -{ - if ( 0 == pen_u->typ_y ) { // ames packet - if( pen_u->pac_u ) { - _ames_pact_free(pen_u->pac_u); - } - } else if ( 1 == pen_u->typ_y ) { // fine request - c3_free(pen_u->req_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(pen_u->res_u); + c3_free(pac_u->res_u.pat_c); + c3_free(pac_u->res_u.dat_y); } - c3_free(pen_u->dns_c); - c3_free(pen_u->hun_y); + c3_free(pac_u->dns_c); + c3_free(pac_u->hun_y); - c3_free(pen_u); + c3_free(pac_u); } /* _ames_panc_free(): remove references, lose refcounts and free struct @@ -390,8 +366,6 @@ _fine_sift_requ(u3_head* hed_u, memcpy(req_u->sig_y, req_y, 64); req_y += 64; - //_log_bytes(req_y, 4); - req_u->fra_w = ( (req_y[0] << 0x0) | (req_y[1] << 0x8) @@ -471,13 +445,10 @@ _fine_sift_resp(u3_head* hed_u, memcpy(&res_u->dat_y, res_y, res_u->siz_s); - // TODO: strict inequality? - /*if(rem_w + res_u->len_s != len_w) { + if(rem_w + res_u->len_s != len_w) { return c3n; - }*/ + } - // TODO: defend maliciusly crafted lengths? - // TODO: add null terminator? return c3y; } @@ -573,7 +544,7 @@ _fine_etch_resp(u3_head* hed_u, c3_w* pac_w = (c3_w*)pac_y; memcpy(pac_w, &res_u->fra_w, 4); - *pac_w = res_u->fra_w; // TODO: check byte order + *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; @@ -620,8 +591,8 @@ _ames_etch_pack(u3_head* hed_u, static void _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) { - u3_pend* pen_u = (u3_pend*)req_u; - u3_ames* sam_u = pen_u->sam_u; + 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)); @@ -631,34 +602,33 @@ _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) sam_u->fig_u.net_o = c3y; } - _ames_pend_free(pen_u); + _ames_pact_free(pac_u); } #define _fine_send _ames_send /* _ames_send(): send buffer to address on port. */ static void -_ames_send(u3_pend* pen_u) +_ames_send(u3_pact* pac_u) { - u3_ames* sam_u = pen_u->sam_u; + u3_ames* sam_u = pac_u->sam_u; - // TODO: prevalidation? - /*if ( !pen_u->hun_y ) { - // _ames_pact_free(pac_u); - //return; + if ( !pac_u->hun_y ) { + _ames_pact_free(pac_u); + return; } - else */ { + 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(pen_u->lan_u.pip_w); - add_u.sin_port = htons(pen_u->lan_u.por_s); + add_u.sin_addr.s_addr = htonl(pac_u->lan_u.pip_w); + add_u.sin_port = htons(pac_u->lan_u.por_s); { - uv_buf_t buf_u = uv_buf_init((c3_c*)pen_u->hun_y, pen_u->len_w); + uv_buf_t buf_u = uv_buf_init((c3_c*)pac_u->hun_y, pac_u->len_w); - c3_i sas_i = uv_udp_send(&pen_u->snd_u, + c3_i sas_i = uv_udp_send(&pac_u->snd_u, &sam_u->wax_u, &buf_u, 1, (const struct sockaddr*)&add_u, @@ -670,7 +640,7 @@ _ames_send(u3_pend* pen_u) sam_u->fig_u.net_o = c3n; } - _ames_pend_free(pen_u); + _ames_pact_free(pac_u); } } } @@ -800,36 +770,36 @@ _ames_czar_port(c3_y imp_y) /* _ames_czar_gone(): galaxy address resolution failed. */ static void -_ames_czar_gone(u3_pend* pen_u, time_t now) +_ames_czar_gone(u3_pact* pac_u, time_t now) { - u3_ames* sam_u = pen_u->sam_u; - c3_d imp_d = pen_u->her_d[0]; + u3_ames* sam_u = pac_u->sam_u; + c3_d imp_y = pac_u->imp_y; - if ( c3y == sam_u->imp_o[imp_d] ) { - u3l_log("ames: czar at %s: not found (b)\n", pen_u->dns_c); - sam_u->imp_o[imp_d] = c3n; + if ( c3y == sam_u->imp_o[imp_y] ) { + u3l_log("ames: czar at %s: not found (b)\n", pac_u->dns_c); + sam_u->imp_o[imp_y] = c3n; } - if ( (0 == sam_u->imp_w[imp_d]) || - (0xffffffff == sam_u->imp_w[imp_d]) ) + if ( (0 == sam_u->imp_w[imp_y]) || + (0xffffffff == sam_u->imp_w[imp_y]) ) { - sam_u->imp_w[imp_d] = 0xffffffff; + sam_u->imp_w[imp_y] = 0xffffffff; } // keep existing ip for 5 more minutes // - sam_u->imp_t[imp_d] = now; + sam_u->imp_t[imp_y] = now; - _ames_pend_free(pen_u); + _ames_pact_free(pac_u); } /* _ames_czar_here(): galaxy address resolution succeeded. */ static void -_ames_czar_here(u3_pend* pen_u, time_t now, struct sockaddr_in* add_u) +_ames_czar_here(u3_pact* pac_u, time_t now, struct sockaddr_in* add_u) { - u3_ames* sam_u = pen_u->sam_u; - c3_y imp_y = pen_u->her_d[0]; + u3_ames* sam_u = pac_u->sam_u; + c3_y imp_y = pac_u->imp_y; c3_w old_w = sam_u->imp_w[imp_y]; c3_w pip_w = ntohl(add_u->sin_addr.s_addr); @@ -837,7 +807,7 @@ _ames_czar_here(u3_pend* pen_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", pen_u->dns_c, nam_c); + u3l_log("ames: czar %s: ip %s\n", pac_u->dns_c, nam_c); c3_free(nam_c); u3z(nam); @@ -847,7 +817,7 @@ _ames_czar_here(u3_pend* pen_u, time_t now, struct sockaddr_in* add_u) sam_u->imp_t[imp_y] = now; sam_u->imp_o[imp_y] = c3y; - pen_u->lan_u.pip_w = pip_w; + pac_u->lan_u.pip_w = pip_w; } /* _ames_czar_cb(): galaxy address resolution callback. @@ -858,13 +828,13 @@ _ames_czar_cb(uv_getaddrinfo_t* adr_u, struct addrinfo* aif_u) { { - u3_pend* pen_u = (u3_pend*)adr_u->data; + u3_pact* pac_u = (u3_pact*)adr_u->data; struct addrinfo* rai_u = aif_u; time_t now = time(0); while ( rai_u ) { if ( (AF_INET == rai_u->ai_family) ) { - _ames_czar_here(pen_u, now, (struct sockaddr_in *)rai_u->ai_addr); + _ames_czar_here(pac_u, now, (struct sockaddr_in *)rai_u->ai_addr); break; } else { @@ -873,7 +843,7 @@ _ames_czar_cb(uv_getaddrinfo_t* adr_u, } if ( !rai_u ) { - _ames_czar_gone(pen_u, now); + _ames_czar_gone(pac_u, now); } } @@ -884,26 +854,24 @@ _ames_czar_cb(uv_getaddrinfo_t* adr_u, /* _ames_czar(): galaxy address resolution. */ static void -_ames_czar(u3_pend* pen_u) +_ames_czar(u3_pact* pac_u) { - u3_ames* sam_u = pen_u->sam_u; + u3_ames* sam_u = pac_u->sam_u; - c3_d imp_d = pen_u->her_d[0]; + c3_y imp_y = pac_u->imp_y; - c3_assert( imp_d < 256 ); - - pen_u->lan_u.por_s = _ames_czar_port(imp_d); + pac_u->lan_u.por_s = _ames_czar_port(imp_y); if ( c3n == u3_Host.ops_u.net ) { - pen_u->lan_u.pip_w = 0x7f000001; - _ames_send(pen_u); + pac_u->lan_u.pip_w = 0x7f000001; + _ames_send(pac_u); return; } // if we don't have a galaxy domain, no-op // if ( !sam_u->dns_c ) { - u3_noun nam = u3dc("scot", 'p', pen_u->her_d[0]); + u3_noun nam = u3dc("scot", 'p', pac_u->imp_y); c3_c* nam_c = u3r_string(nam); u3l_log("ames: no galaxy domain for %s, no-op\r\n", nam_c); @@ -913,8 +881,8 @@ _ames_czar(u3_pend* pen_u) } { - c3_w pip_w = sam_u->imp_w[imp_d]; - time_t wen = sam_u->imp_t[imp_d]; + c3_w pip_w = sam_u->imp_w[imp_y]; + time_t wen = sam_u->imp_t[imp_y]; time_t now = time(0); // backoff for 5 minutes after failed lookup @@ -923,27 +891,27 @@ _ames_czar(u3_pend* pen_u) || ( (0xffffffff == pip_w) // sentinal ip address && ((now - wen) < 300) ) ) { - _ames_pend_free(pen_u); + _ames_pact_free(pac_u); return; } // cached addresses have a 5 minute TTL // else if ( (0 != pip_w) && ((now - wen) < 300) ) { - pen_u->lan_u.pip_w = pip_w; - _ames_send(pen_u); + pac_u->lan_u.pip_w = pip_w; + _ames_send(pac_u); return; } else { c3_i sas_i; { - u3_noun nam = u3dc("scot", 'p', imp_d); + u3_noun nam = u3dc("scot", 'p', imp_y); c3_c* nam_c = u3r_string(nam); // NB: . separator not counted, as [nam_c] includes a ~ that we skip // - pen_u->dns_c = c3_malloc(1 + strlen(nam_c) + strlen(sam_u->dns_c)); - sas_i = snprintf(pen_u->dns_c, 255, "%s.%s", nam_c + 1, sam_u->dns_c); + 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); c3_free(nam_c); u3z(nam); @@ -951,20 +919,20 @@ _ames_czar(u3_pend* pen_u) if ( 255 <= sas_i ) { u3l_log("ames: czar: galaxy domain %s truncated\n", sam_u->dns_c); - _ames_pend_free(pen_u); + _ames_pact_free(pac_u); return; } { uv_getaddrinfo_t* adr_u = c3_malloc(sizeof(*adr_u)); - adr_u->data = pen_u; + adr_u->data = pac_u; if ( 0 != (sas_i = uv_getaddrinfo(u3L, adr_u, _ames_czar_cb, - pen_u->dns_c, 0, 0)) ) + pac_u->dns_c, 0, 0)) ) { u3l_log("ames: %s\n", uv_strerror(sas_i)); - _ames_czar_gone(pen_u, now); + _ames_czar_gone(pac_u, now); return; } } @@ -988,17 +956,11 @@ _ames_ef_send(u3_ames* sam_u, u3_noun lan, u3_noun pac) pac_u->len_w = u3r_met(3, pac); pac_u->hun_y = c3_malloc(pac_u->len_w); - - u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); - pen_u->len_w = pac_u->len_w; - pen_u->hun_y = pac_u->hun_y; - pen_u->sam_u = sam_u; - 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); - pen_u->typ_y = + pac_u->typ_y = hed_u.sim_o == c3y ? 0 : hed_u.req_o == c3y ? 1 : 2; @@ -1013,8 +975,7 @@ _ames_ef_send(u3_ames* sam_u, u3_noun lan, u3_noun pac) c3_assert( val < 256 ); pac_u->imp_y = val; - pen_u->her_d[0] = val; - _ames_czar(pen_u); + _ames_czar(pac_u); } // non-galaxy lane // @@ -1039,8 +1000,8 @@ _ames_ef_send(u3_ames* sam_u, u3_noun lan, u3_noun pac) // otherwise, mutate destination and send packet // else { - pen_u->lan_u = lan_u; - _ames_send(pen_u); + pac_u->lan_u = lan_u; + _ames_send(pac_u); } } u3z(lan); u3z(pac); @@ -1363,74 +1324,58 @@ _ames_skip(u3_body* bod_u) { } #endif -static void _fine_got_pack(u3_pend* pen_u, u3_noun fra) +static void _fine_got_pack(u3_pact* pac_u, u3_noun fra) { - pen_u->len_w = u3r_met(3, fra); - pen_u->hun_y = c3_calloc(pen_u->len_w); + pac_u->len_w = u3r_met(3, fra); + pac_u->hun_y = c3_calloc(pac_u->len_w); - u3r_bytes(0, pen_u->len_w, pen_u->hun_y, fra); + u3r_bytes(0, pac_u->len_w, pac_u->hun_y, fra); - _fine_send(pen_u); - - - // - // hashtable = (path, packet_num) -> cached_result; - // All cases, except 1st ~: put results in cache for all packets - // ~ -> if second request, ask for notification if 2nd, drop on floor - // [~ ~] -> send packet - // [~ ~ *] -> send packet - // TODO: cache logic, counting requests, evict? - - /*u3_weak lan = _ames_lane_from_cache(pen_u->sam_u->lax_p, - u3i_chubs(2, pen_u->her_d)); - if(u3_none == lan) { - // TODO: enqueue packet for later sending, populate lane cache - } else if(u3_nul == lan) { - // TODO: no lane, drop packet - } else { - _fine_send(pen_u); - } - */ + _fine_send(pac_u); + u3z(fra); } /* _fine_pack_scry_cb(): receive all packets for datum out of fine - * TODO: implement */ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) { u3l_log("got scry result\n"); - u3_pend* pen_u = vod_p; - u3_ames* sam_u = pen_u->sam_u; - u3_weak pac = u3r_at(7, nun); - if(pac == u3_none) { + u3_pact* pac_u = vod_p; + u3_ames* sam_u = pac_u->sam_u; + u3_weak pas = u3r_at(7, nun); + if(pas == u3_none) { u3l_log("no result, bailing\n"); + _ames_pact_free(pac_u); + u3z(nun); return; } - c3_assert( 1 == pen_u->typ_y); + c3_assert( 1 == pac_u->typ_y); u3_weak fra = u3_none; - u3_noun pax = u3i_string(pen_u->req_u->req_u.pat_c); - u3l_log("made string\n"); + u3_noun pax = u3i_string(pac_u->req_u.pat_c); c3_w cur_w = 1; - u3_noun lis = u3k(pac); - while(pac != u3_nul) { - u3h_put(sam_u->fin_s.sac_p, u3nc(u3k(pax), u3i_word(cur_w)), u3h(pac)); - if ( pen_u->fra_w == cur_w ) { - fra = u3k(u3h(pac)); + u3k(pas); + while(pas != u3_nul) { + u3_noun key = u3nc(u3k(pax), u3i_word(cur_w)); + u3h_put(sam_u->fin_s.sac_p, key, u3h(pas)); + if ( pac_u->req_u.fra_w == cur_w ) { + fra = u3k(u3h(pas)); } cur_w++; - pac = u3t(pac); + pas = u3t(pas); + u3z(key); } if ( fra == u3_none ) { u3l_log("fragment number out of range\n"); } else { - _fine_got_pack(pen_u, fra); + _fine_got_pack(pac_u, fra); } + u3z(pas); + u3z(nun); } - static void _fine_hear_response(u3_ames* sam_u, u3_lane lan_u, c3_w len_w, @@ -1474,21 +1419,17 @@ static void _fine_hear_request(u3_ames* sam_u, u3_noun pat = u3i_string(req_u.pat_c); u3_noun key = u3nc(u3k(pat), u3i_word(req_u.fra_w)); - // TODO: revive u3_weak cac = u3h_git(sam_u->fin_s.sac_p, key); - u3_reqp* rep_u = c3_calloc(sizeof(*rep_u)); - u3_pend* pen_u = c3_calloc(sizeof(*pen_u)); + u3_pact* pac_u = c3_calloc(sizeof(*pac_u)); - pen_u->sam_u = sam_u; - pen_u->typ_y = 1; - pen_u->req_u = rep_u; + pac_u->sam_u = sam_u; + pac_u->typ_y = 1; - memcpy(&rep_u->hed_u, &hed_u, sizeof(u3_head)); - memcpy(&rep_u->req_u, &req_u, sizeof(u3_requ)); + memcpy(&pac_u->hed_u, &hed_u, sizeof(u3_head)); + memcpy(&pac_u->req_u, &req_u, sizeof(u3_requ)); - memcpy(&pen_u->lan_u, &lan_u, sizeof(u3_lane)); - pen_u->fra_w = req_u.fra_w; + memcpy(&pac_u->lan_u, &lan_u, sizeof(u3_lane)); if ( u3_none == cac ) { // cache miss @@ -1497,10 +1438,10 @@ static void _fine_hear_request(u3_ames* sam_u, u3do("stab", u3k(pat))); u3_pier_peek_last(sam_u->car_u.pir_u, u3_nul, c3__ax, u3_nul, - pax, pen_u, _fine_pack_scry_cb); + pax, pac_u, _fine_pack_scry_cb); } else { - _fine_got_pack(pen_u, u3k(cac)); + _fine_got_pack(pac_u, u3k(cac)); } u3z(pat); @@ -1547,7 +1488,7 @@ _fine_request(u3_ames* sam_u, u3_noun req) { - u3_pend* pen_u = c3_calloc(sizeof(*pen_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)); @@ -1555,8 +1496,8 @@ _fine_request(u3_ames* sam_u, c3_y* req_y = c3_calloc(req_w); u3r_bytes(0, req_w, req_y, req); //_log_bytes(req_y, 4); - pen_u->hun_y = req_y; - pen_u->len_w = req_w; + pac_u->hun_y = req_y; + pac_u->len_w = req_w; _ames_sift_head(hed_u, req_y); req_y += 4; @@ -1564,21 +1505,20 @@ _fine_request(u3_ames* sam_u, _fine_sift_requ(hed_u, req_u, req_w, req_y); - pen_u->typ_y = 1; - pen_u->her_d[0] = req_u->pre_u.rec_d[0]; - pen_u->her_d[1] = req_u->pre_u.rec_d[1]; - pen_u->sam_u = sam_u; + pac_u->typ_y = 1; + pac_u->sam_u = sam_u; { u3_noun tag, val; u3x_cell(lan, &tag, &val); if(tag == 0) { - _ames_czar(pen_u); + 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); - pen_u->lan_u.pip_w = lan_u.pip_w; - pen_u->lan_u.por_s = lan_u.por_s; - _ames_send(pen_u); + pac_u->lan_u.pip_w = lan_u.pip_w; + pac_u->lan_u.por_s = lan_u.por_s; + _ames_send(pac_u); } } } @@ -1593,8 +1533,7 @@ _ames_hear(u3_ames* sam_u, { // TODO: move from stack to heap to avoid reparsing - u3_head hed_u; - u3_body bod_u; + u3_pact* pac_u = c3_calloc(sizeof(*pac_u)); // XX packet filtering needs to revised for two protocol-change scenarios // @@ -1612,7 +1551,7 @@ _ames_hear(u3_ames* sam_u, // unpack header, ensuring buffer is large enough // // - c3_o is_ames_o = _ames_sift_head(&hed_u, hun_y); + c3_o is_ames_o = _ames_sift_head(&pac_u->hed_u, hun_y); if (4 > len_w) { sam_u->sat_u.hed_d++; @@ -1634,7 +1573,7 @@ _ames_hear(u3_ames* sam_u, // XX rethink use of [fit_o] here and elsewhere // if ( (c3y == sam_u->fig_u.fit_o) - && (sam_u->ver_y != hed_u.ver_y) ) + && (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) ) { @@ -1643,6 +1582,7 @@ _ames_hear(u3_ames* sam_u, } c3_free(hun_y); + _ames_pact_free(pac_u); return; } @@ -1652,7 +1592,7 @@ _ames_hear(u3_ames* sam_u, // unpack and validate the body // - if ( (c3n == _ames_sift_body(&hed_u, &bod_u, bod_w, bod_y)) ) { + 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", @@ -1660,12 +1600,13 @@ _ames_hear(u3_ames* sam_u, } c3_free(hun_y); + _ames_pact_free(pac_u); return; } // ensure the mug is valid // - if ( bod_u.mug_l != hed_u.mug_l ) { + if ( pac_u->bod_u.mug_l != pac_u->hed_u.mug_l ) { sam_u->sat_u.mut_d++; if ( 0 == (sam_u->sat_u.mut_d % 100000) ) { u3l_log("ames: %" PRIu64 " dropped for invalid mug\n", @@ -1673,6 +1614,7 @@ _ames_hear(u3_ames* sam_u, } c3_free(hun_y); + _ames_pact_free(pac_u); return; } } @@ -1682,10 +1624,10 @@ _ames_hear(u3_ames* sam_u, // we might want to forward statelessly // if ( 0 && (c3y == sam_u->fig_u.see_o) - && ( (bod_u.pre_u.rec_d[0] != sam_u->pir_u->who_d[0]) - || (bod_u.pre_u.rec_d[1] != sam_u->pir_u->who_d[1]) ) ) + && ( (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]) ) ) { - _ames_try_forward(sam_u, lan_u, &hed_u, &bod_u, hun_y); + _ames_try_forward(sam_u, lan_u, &pac_u->hed_u, &pac_u->bod_u, hun_y); } // otherwise, inject the packet as an event // From f31bf964ceb53a10fc5d9d12c46a7d67c6b7cf50 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Tue, 1 Feb 2022 20:30:50 -0600 Subject: [PATCH 15/21] urbit: working notifications support --- pkg/urbit/include/c/motes.h | 1 + pkg/urbit/vere/io/ames.c | 107 +++++++++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/pkg/urbit/include/c/motes.h b/pkg/urbit/include/c/motes.h index b5a3a50ab..fbb0a8d39 100644 --- a/pkg/urbit/include/c/motes.h +++ b/pkg/urbit/include/c/motes.h @@ -72,6 +72,7 @@ # define c3__ber c3_s3('b','e','r') # define c3__bias c3_s4('b','i','a','s') # define c3__bic c3_s3('b','i','c') +# define c3__bide c3_s4('b','i','d', 'e') # define c3__bind c3_s4('b','i','n','d') # define c3__bink c3_s4('b','i','n','k') # define c3__bird c3_s4('b','i','r','d') diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 202304d57..2563fa6c9 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -12,6 +12,7 @@ typedef struct _u3_fine { c3_y ver_y; // fine protocol u3p(u3h_root) sac_p; // scry cache hashtable + u3p(u3h_root) bid_p; // pending notifications struct _u3_ames* sam_u; // ames backpointer } u3_fine; @@ -130,6 +131,8 @@ }; } u3_pact; +static void _fine_got_pack(u3_pact*, u3_noun); + /* u3_panc: deconstructed incoming packet */ typedef struct _u3_panc { @@ -940,6 +943,58 @@ _ames_czar(u3_pact* pac_u) } } +/* _fine_ef_howl(): broadcast notification of newly bound data + */ +static void +_fine_ef_howl(u3_ames* sam_u, u3_noun pax, u3_noun lis) { + u3l_log("howling\n"); + u3_noun pas = lis; + + // TODO; refactor, + u3_weak fra = u3_none; + c3_w cur_w = 1; + u3k(pas); + u3l_log("howling a\n"); + while(pas != u3_nul) { + u3l_log("howling in list\n"); + u3_noun key = u3nc(u3k(pax), u3i_word(cur_w)); + u3h_put(sam_u->fin_s.sac_p, key, u3k(u3h(pas))); + pas = u3t(pas); + u3z(key); + } + u3l_log("howling after list\n"); + u3m_p("pax", pax); + u3_weak who = u3h_get(sam_u->fin_s.bid_p, pax); + if ( who == u3_none ) { + u3l_log("no listeners\n"); + } else { + + u3_noun her = who; + while ( her != u3_nul ) { + //u3m_p("her", her); + + /*u3_weak lac = _ames_lane_from_cache(sam_u->lax_p, u3h(her)); + if ( lac == u3_none ) { + u3l_log("no lane\n"); + u3m_p("for", u3h(her)); + her = u3t(her); + continue; + }*/ + u3_pact* pac_u = c3_calloc(sizeof(*pac_u)); + pac_u->sam_u = sam_u; + c3_d her_d[2]; + u3r_chubs(0, 2, her_d, u3k(u3h(her))); + u3l_log(" %"PRIu64", %" PRIu64 "\n", her_d[0], her_d[1]); + + // TODO: fix for non-galaxy case + pac_u->imp_y = her_d[0]; + + _fine_got_pack(pac_u, u3h(lis)); + her = u3t(her); + } + } +} + /* _ames_ef_send(): send packet to network (v4). */ static void @@ -1326,16 +1381,52 @@ _ames_skip(u3_body* bod_u) { static void _fine_got_pack(u3_pact* pac_u, u3_noun fra) { + u3l_log("got pack\n"); pac_u->len_w = u3r_met(3, fra); pac_u->hun_y = c3_calloc(pac_u->len_w); + u3m_p("fra", fra); u3r_bytes(0, pac_u->len_w, pac_u->hun_y, fra); + u3l_log("preczar\n"); - _fine_send(pac_u); + _ames_czar(pac_u); //_fine_send(pac_u); + u3l_log("postczar\n"); u3z(fra); } +static void _fine_bide(u3_pact* pac_u, u3_noun pax) +{ + u3_ames* sam_u = pac_u->sam_u; + u3_weak lis = u3h_get(sam_u->fin_s.bid_p, pax); + + if ( u3_none == lis ) { + lis = u3_nul; + } + u3_noun her = u3i_chubs(2, pac_u->req_u.pre_u.sen_d); + u3_noun new = u3nc(her, lis); + // TODO: linear search bad + + u3l_log("put in hashtable\n"); + u3m_p("hashtable", new); + u3_noun car, res; + u3x_cell(pax, &car, &res); + u3_noun our = u3dc("scot", 'p', u3i_chubs(2, sam_u->car_u.pir_u->who_d)); + + u3_noun pat = u3nt(car, our, res); + u3h_put(sam_u->fin_s.bid_p, pat, new); + u3m_p("pat", pat); + + u3_noun cad = u3nc(c3__bide, pat); + u3_noun wir = u3nc(c3__fine, u3_nul); + u3_ovum* ovo_u = u3_ovum_init(0, c3__ames, u3k(wir), u3k(cad)); + u3_auto_plan(&sam_u->car_u, ovo_u); + + u3z(wir); + u3z(cad); +} + + /* _fine_pack_scry_cb(): receive all packets for datum out of fine */ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) @@ -1345,15 +1436,18 @@ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) u3_pact* pac_u = vod_p; 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)); if(pas == u3_none) { + // TODO: send %bide u3l_log("no result, bailing\n"); + _fine_bide(pac_u, u3k(pax)); _ames_pact_free(pac_u); + u3z(pax); u3z(nun); return; } - c3_assert( 1 == pac_u->typ_y); + c3_assert( 1 == pac_u->typ_y ); u3_weak fra = u3_none; - u3_noun pax = u3i_string(pac_u->req_u.pat_c); c3_w cur_w = 1; u3k(pas); while(pas != u3_nul) { @@ -1903,6 +1997,10 @@ _ames_kick_newt(u3_ames* sam_u, u3_noun tag, u3_noun dat) } break; case c3__howl: { + u3_noun pat = u3k(u3h(dat)); + u3_noun lis = u3k(u3t(dat)); + u3l_log("fine: howl\n"); + _fine_ef_howl(sam_u, pat, lis); ret_o = c3y; } break; @@ -2056,6 +2154,9 @@ u3_ames_io_init(u3_pier* pir_u) // 50 bytes (average) per path * 100_000 = 5MB sam_u->fin_s.sac_p = u3h_new_cache(100000); + // hashtable for notificatiosn + sam_u->fin_s.bid_p = u3h_new_cache(100000); + //NOTE some numbers on memory usage for the lane cache // // assuming we store: From 86bafc98389a4a3996e87db987bac4c6702278a8 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Tue, 1 Feb 2022 20:47:55 -0600 Subject: [PATCH 16/21] urbit: unify path format --- pkg/urbit/vere/io/ames.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 2563fa6c9..2488e9592 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -1399,7 +1399,6 @@ static void _fine_bide(u3_pact* pac_u, u3_noun pax) { u3_ames* sam_u = pac_u->sam_u; u3_weak lis = u3h_get(sam_u->fin_s.bid_p, pax); - if ( u3_none == lis ) { lis = u3_nul; } @@ -1409,15 +1408,11 @@ static void _fine_bide(u3_pact* pac_u, u3_noun pax) u3l_log("put in hashtable\n"); u3m_p("hashtable", new); - u3_noun car, res; - u3x_cell(pax, &car, &res); - u3_noun our = u3dc("scot", 'p', u3i_chubs(2, sam_u->car_u.pir_u->who_d)); - u3_noun pat = u3nt(car, our, res); - u3h_put(sam_u->fin_s.bid_p, pat, new); - u3m_p("pat", pat); + u3h_put(sam_u->fin_s.bid_p, pax, new); + u3m_p("pax", pax); - u3_noun cad = u3nc(c3__bide, pat); + u3_noun cad = u3nc(c3__bide, pax); u3_noun wir = u3nc(c3__fine, u3_nul); u3_ovum* ovo_u = u3_ovum_init(0, c3__ames, u3k(wir), u3k(cad)); u3_auto_plan(&sam_u->car_u, ovo_u); @@ -1437,6 +1432,7 @@ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) 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)); + u3m_p("pax", pax); if(pas == u3_none) { // TODO: send %bide u3l_log("no result, bailing\n"); From 7bf6356d737303d24d0474043c6142e0c95b65e4 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Tue, 1 Feb 2022 20:49:31 -0600 Subject: [PATCH 17/21] urbit: remove unnecessary logs --- pkg/urbit/vere/io/ames.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 2488e9592..869fc966f 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -947,23 +947,18 @@ _ames_czar(u3_pact* pac_u) */ static void _fine_ef_howl(u3_ames* sam_u, u3_noun pax, u3_noun lis) { - u3l_log("howling\n"); u3_noun pas = lis; // TODO; refactor, u3_weak fra = u3_none; c3_w cur_w = 1; u3k(pas); - u3l_log("howling a\n"); while(pas != u3_nul) { - u3l_log("howling in list\n"); u3_noun key = u3nc(u3k(pax), u3i_word(cur_w)); u3h_put(sam_u->fin_s.sac_p, key, u3k(u3h(pas))); pas = u3t(pas); u3z(key); } - u3l_log("howling after list\n"); - u3m_p("pax", pax); u3_weak who = u3h_get(sam_u->fin_s.bid_p, pax); if ( who == u3_none ) { u3l_log("no listeners\n"); @@ -971,6 +966,7 @@ _fine_ef_howl(u3_ames* sam_u, u3_noun pax, u3_noun lis) { u3_noun her = who; while ( her != u3_nul ) { + // TODO: prime cache maybe??? //u3m_p("her", her); /*u3_weak lac = _ames_lane_from_cache(sam_u->lax_p, u3h(her)); @@ -984,7 +980,6 @@ _fine_ef_howl(u3_ames* sam_u, u3_noun pax, u3_noun lis) { pac_u->sam_u = sam_u; c3_d her_d[2]; u3r_chubs(0, 2, her_d, u3k(u3h(her))); - u3l_log(" %"PRIu64", %" PRIu64 "\n", her_d[0], her_d[1]); // TODO: fix for non-galaxy case pac_u->imp_y = her_d[0]; @@ -1381,17 +1376,14 @@ _ames_skip(u3_body* bod_u) { static void _fine_got_pack(u3_pact* pac_u, u3_noun fra) { - u3l_log("got pack\n"); pac_u->len_w = u3r_met(3, fra); pac_u->hun_y = c3_calloc(pac_u->len_w); - u3m_p("fra", fra); u3r_bytes(0, pac_u->len_w, pac_u->hun_y, fra); - u3l_log("preczar\n"); _ames_czar(pac_u); //_fine_send(pac_u); - u3l_log("postczar\n"); + u3z(fra); } @@ -1431,11 +1423,9 @@ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) u3_pact* pac_u = vod_p; 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)); - u3m_p("pax", pax); + u3_noun pax = u3do("stab", u3i_string(pac_u->req_u.pat_c)); u3m_p("pax", pax); if(pas == u3_none) { // TODO: send %bide - u3l_log("no result, bailing\n"); _fine_bide(pac_u, u3k(pax)); _ames_pact_free(pac_u); u3z(pax); From a71cf68170640c9692a92e01148f5af3b9e2e92a Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Wed, 2 Feb 2022 14:50:12 -0600 Subject: [PATCH 18/21] urbit: refactor caching --- pkg/urbit/vere/io/ames.c | 68 +++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 869fc966f..e1c6f84b5 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -862,6 +862,7 @@ _ames_czar(u3_pact* pac_u) u3_ames* sam_u = pac_u->sam_u; c3_y imp_y = pac_u->imp_y; + u3l_log("ames: send to %u\n", imp_y); pac_u->lan_u.por_s = _ames_czar_port(imp_y); @@ -943,22 +944,35 @@ _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) +{ + u3_noun beg = lis; + + c3_w cur_w = 1; + 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))); + + lis = u3t(lis); + cur_w++; + u3z(key); + } + u3l_log("put %u packets at\n", cur_w); + u3m_p("path", pax); +} + /* _fine_ef_howl(): broadcast notification of newly bound data */ static void -_fine_ef_howl(u3_ames* sam_u, u3_noun pax, u3_noun lis) { +_fine_ef_howl(u3_ames* sam_u, u3_noun pax, u3_noun lis) +{ u3_noun pas = lis; - // TODO; refactor, - u3_weak fra = u3_none; - c3_w cur_w = 1; - u3k(pas); - while(pas != u3_nul) { - u3_noun key = u3nc(u3k(pax), u3i_word(cur_w)); - u3h_put(sam_u->fin_s.sac_p, key, u3k(u3h(pas))); - pas = u3t(pas); - u3z(key); - } + _fine_put_cache(sam_u, pax, pas); + u3_weak who = u3h_get(sam_u->fin_s.bid_p, pax); if ( who == u3_none ) { u3l_log("no listeners\n"); @@ -1391,18 +1405,15 @@ static void _fine_bide(u3_pact* pac_u, u3_noun pax) { u3_ames* sam_u = pac_u->sam_u; u3_weak lis = u3h_get(sam_u->fin_s.bid_p, pax); + if ( u3_none == lis ) { lis = u3_nul; } + u3_noun her = u3i_chubs(2, pac_u->req_u.pre_u.sen_d); u3_noun new = u3nc(her, lis); - // TODO: linear search bad - - u3l_log("put in hashtable\n"); - u3m_p("hashtable", new); u3h_put(sam_u->fin_s.bid_p, pax, new); - u3m_p("pax", pax); u3_noun cad = u3nc(c3__bide, pax); u3_noun wir = u3nc(c3__fine, u3_nul); @@ -1418,12 +1429,12 @@ static void _fine_bide(u3_pact* pac_u, u3_noun pax) */ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) { - u3l_log("got scry result\n"); u3_pact* pac_u = vod_p; 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)); u3m_p("pax", pax); + u3_noun pax = u3do("stab", u3i_string(pac_u->req_u.pat_c)); + if(pas == u3_none) { // TODO: send %bide _fine_bide(pac_u, u3k(pax)); @@ -1434,23 +1445,25 @@ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) } c3_assert( 1 == pac_u->typ_y ); u3_weak fra = u3_none; + _fine_put_cache(sam_u, pax, pas); + c3_w cur_w = 1; - u3k(pas); - while(pas != u3_nul) { - u3_noun key = u3nc(u3k(pax), u3i_word(cur_w)); - u3h_put(sam_u->fin_s.sac_p, key, u3h(pas)); + + // find requested fragment + while ( pas != u3_nul ) { if ( pac_u->req_u.fra_w == cur_w ) { fra = u3k(u3h(pas)); } cur_w++; pas = u3t(pas); - u3z(key); } + if ( fra == u3_none ) { u3l_log("fragment number out of range\n"); } else { _fine_got_pack(pac_u, fra); } + u3z(pas); u3z(nun); } @@ -1496,7 +1509,7 @@ static void _fine_hear_request(u3_ames* sam_u, c3_assert( c3y == _fine_sift_requ(&hed_u, &req_u, len_w, hun_y)); - u3_noun pat = u3i_string(req_u.pat_c); + u3_noun pat = u3do("stab", u3i_string(req_u.pat_c)); u3_noun key = u3nc(u3k(pat), u3i_word(req_u.fra_w)); u3_weak cac = u3h_git(sam_u->fin_s.sac_p, key); @@ -1511,11 +1524,16 @@ static void _fine_hear_request(u3_ames* sam_u, 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]; + } + if ( u3_none == cac ) { // cache miss u3_noun pax = u3nt(u3i_string("fine"), u3i_string("message"), - u3do("stab", u3k(pat))); + u3k(pat)); u3_pier_peek_last(sam_u->car_u.pir_u, u3_nul, c3__ax, u3_nul, pax, pac_u, _fine_pack_scry_cb); From 5da80d7001e9d0b02f1baa3cecc34eb959a2a6ce Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Wed, 9 Feb 2022 13:04:22 -0600 Subject: [PATCH 19/21] wip --- pkg/urbit/Makefile | 7 +++++++ pkg/urbit/vere/io/ames.c | 27 +++++++++++++-------------- pkg/urbit/wireshark/main.c | 0 3 files changed, 20 insertions(+), 14 deletions(-) create mode 100644 pkg/urbit/wireshark/main.c diff --git a/pkg/urbit/Makefile b/pkg/urbit/Makefile index c079c2af3..e2a4fdabb 100644 --- a/pkg/urbit/Makefile +++ b/pkg/urbit/Makefile @@ -9,6 +9,7 @@ daemon = $(wildcard daemon/*.c) worker = $(wildcard worker/*.c) tests = $(wildcard tests/*.c) bench = $(wildcard bench/*.c) +wireshark = $(wildcard wireshark/*.c) compat := $(foreach dir,$(compat),$(wildcard compat/$(dir)/*.c)) @@ -77,6 +78,12 @@ build/urbit-worker: $(common_objs) $(worker_objs) @mkdir -p ./build @$(CC) $^ $(LDFLAGS) -o $@ +build/ames-wireshark: $(common_objs) $(worker_objs) + @echo CC -o $@ + @mkdir -p ./build + @$(CC) wireshark/main.c $(LDFLAGS) -o $@ + + # CCDEPS and CCEXTRA are empty except in MingW build, # which uses them to inject a C source transform step %.o: %.c $(headers) $(CCDEPS) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index e1c6f84b5..2e96f4d88 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -862,7 +862,6 @@ _ames_czar(u3_pact* pac_u) u3_ames* sam_u = pac_u->sam_u; c3_y imp_y = pac_u->imp_y; - u3l_log("ames: send to %u\n", imp_y); pac_u->lan_u.por_s = _ames_czar_port(imp_y); @@ -960,8 +959,6 @@ _fine_put_cache(u3_ames* sam_u, u3_noun pax, u3_noun lis) cur_w++; u3z(key); } - u3l_log("put %u packets at\n", cur_w); - u3m_p("path", pax); } /* _fine_ef_howl(): broadcast notification of newly bound data @@ -981,22 +978,19 @@ _fine_ef_howl(u3_ames* sam_u, u3_noun pax, u3_noun lis) u3_noun her = who; while ( her != u3_nul ) { // TODO: prime cache maybe??? - //u3m_p("her", her); - /*u3_weak lac = _ames_lane_from_cache(sam_u->lax_p, u3h(her)); + u3_weak lac = _ames_lane_from_cache(sam_u->lax_p, u3h(her)); if ( lac == u3_none ) { u3l_log("no lane\n"); - u3m_p("for", u3h(her)); her = u3t(her); continue; - }*/ + } u3_pact* pac_u = c3_calloc(sizeof(*pac_u)); pac_u->sam_u = sam_u; - c3_d her_d[2]; - u3r_chubs(0, 2, her_d, u3k(u3h(her))); - // TODO: fix for non-galaxy case - pac_u->imp_y = her_d[0]; + c3_d lan_d = u3r_chub(0, lac); + pac_u->lan_u.pip_w = (c3_w)lan_d; + pac_u->lan_u.por_s = (c3_s)(lan_d >> 32); _fine_got_pack(pac_u, u3h(lis)); her = u3t(her); @@ -1396,7 +1390,7 @@ static void _fine_got_pack(u3_pact* pac_u, u3_noun fra) u3r_bytes(0, pac_u->len_w, pac_u->hun_y, fra); - _ames_czar(pac_u); //_fine_send(pac_u); + _fine_send(pac_u); u3z(fra); } @@ -1661,7 +1655,13 @@ _ames_hear(u3_ames* sam_u, c3_free(hun_y); return; } - else if (c3n == is_ames_o) { + + u3_prel pre_u; + + // we always overwrite this later + _ames_sift_prelude(&pac_u->hed_u, &pac_u->bod_u.pre_u, len_w - 4, hun_y + 4); + + if (c3n == is_ames_o) { _fine_hear(sam_u, *lan_u, len_w, hun_y); return; } @@ -2003,7 +2003,6 @@ _ames_kick_newt(u3_ames* sam_u, u3_noun tag, u3_noun dat) case c3__howl: { u3_noun pat = u3k(u3h(dat)); u3_noun lis = u3k(u3t(dat)); - u3l_log("fine: howl\n"); _fine_ef_howl(sam_u, pat, lis); ret_o = c3y; } break; diff --git a/pkg/urbit/wireshark/main.c b/pkg/urbit/wireshark/main.c new file mode 100644 index 000000000..e69de29bb From 39d99f69d6636bd107a95ebf7a6ccdf1d2ecf045 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Thu, 10 Feb 2022 10:57:04 -0600 Subject: [PATCH 20/21] ames: use set for subscribers instead of list --- pkg/urbit/vere/io/ames.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 2e96f4d88..c5f168bf3 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -974,8 +974,8 @@ _fine_ef_howl(u3_ames* sam_u, u3_noun pax, u3_noun lis) if ( who == u3_none ) { u3l_log("no listeners\n"); } else { + u3_noun her = u3qdi_tap(who); - u3_noun her = who; while ( her != u3_nul ) { // TODO: prime cache maybe??? @@ -1398,14 +1398,14 @@ static void _fine_got_pack(u3_pact* pac_u, u3_noun fra) static void _fine_bide(u3_pact* pac_u, u3_noun pax) { u3_ames* sam_u = pac_u->sam_u; - u3_weak lis = u3h_get(sam_u->fin_s.bid_p, pax); + u3_weak set = u3h_get(sam_u->fin_s.bid_p, pax); - if ( u3_none == lis ) { - lis = u3_nul; + if ( u3_none == set ) { + set = u3_nul; } u3_noun her = u3i_chubs(2, pac_u->req_u.pre_u.sen_d); - u3_noun new = u3nc(her, lis); + u3_noun new = u3qdi_put(set, her); u3h_put(sam_u->fin_s.bid_p, pax, new); @@ -1454,6 +1454,7 @@ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) if ( fra == u3_none ) { u3l_log("fragment number out of range\n"); + _ames_pact_free(pac_u); } else { _fine_got_pack(pac_u, fra); } @@ -1660,6 +1661,12 @@ _ames_hear(u3_ames* sam_u, // 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); From 39a0f7c431e6b7b017d5c13c8aae7e40c2661685 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Thu, 10 Feb 2022 10:57:39 -0600 Subject: [PATCH 21/21] ames: scry for lane if not in cache --- pkg/urbit/vere/io/ames.c | 96 ++++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 18 deletions(-) diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index c5f168bf3..00e86d25f 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -198,6 +198,16 @@ _ames_panc_free(u3_panc* pac_u) c3_free(pac_u); } +/* _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); +} + static void _log_prel(u3_prel* pre_u) { u3l_log("-- PRELUDE --\n"); @@ -961,6 +971,47 @@ _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); +} + /* _fine_ef_howl(): broadcast notification of newly bound data */ static void @@ -968,33 +1019,43 @@ _fine_ef_howl(u3_ames* sam_u, u3_noun pax, u3_noun lis) { u3_noun pas = lis; + // put packets in cache _fine_put_cache(sam_u, pax, pas); + + // iterate over subscribers, sending immediately if we have the lane + // else, scry for a lane u3_weak who = u3h_get(sam_u->fin_s.bid_p, pax); if ( who == u3_none ) { u3l_log("no listeners\n"); } else { u3_noun her = u3qdi_tap(who); + u3_noun him = her; // original ref for counting while ( her != u3_nul ) { - // TODO: prime cache maybe??? u3_weak lac = _ames_lane_from_cache(sam_u->lax_p, u3h(her)); - if ( lac == u3_none ) { - u3l_log("no lane\n"); - her = u3t(her); - continue; - } + u3_pact* pac_u = c3_calloc(sizeof(*pac_u)); pac_u->sam_u = sam_u; - c3_d lan_d = u3r_chub(0, lac); - pac_u->lan_u.pip_w = (c3_w)lan_d; - pac_u->lan_u.por_s = (c3_s)(lan_d >> 32); - _fine_got_pack(pac_u, u3h(lis)); + if ( lac == u3_none ) { + u3l_log("no lane\n"); + u3_noun pax = _lane_scry_path(u3k(u3h(her))); + u3_pier_peek_last(sam_u->pir_u, u3_nul, c3__ax, + u3_nul, pax, pac_u, _fine_lane_scry_cb); + } else { + c3_d lan_d = u3r_chub(0, lac); + 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); + } + her = u3t(her); } + u3z(him); } } @@ -1230,6 +1291,8 @@ _ames_forward(u3_panc* pac_u, u3_noun las) u3z(las); } + + /* _ames_lane_scry_cb(): learn lane to forward packet on */ static void @@ -1353,10 +1416,8 @@ _ames_try_forward(u3_ames* sam_u, // else { sam_u->sat_u.foq_d++; - u3_noun pax = u3nq(u3i_string("peers"), - u3dc("scot", 'p', u3i_chubs(2, bod_u->pre_u.rec_d)), - u3i_string("forward-lane"), - u3_nul); + 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); } @@ -1389,9 +1450,6 @@ static void _fine_got_pack(u3_pact* pac_u, u3_noun fra) u3r_bytes(0, pac_u->len_w, pac_u->hun_y, fra); - - _fine_send(pac_u); - u3z(fra); } @@ -1430,9 +1488,9 @@ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) u3_noun pax = u3do("stab", u3i_string(pac_u->req_u.pat_c)); if(pas == u3_none) { - // TODO: send %bide _fine_bide(pac_u, u3k(pax)); _ames_pact_free(pac_u); + u3z(pax); u3z(nun); return; @@ -1457,6 +1515,7 @@ static void _fine_pack_scry_cb(void* vod_p, u3_noun nun) _ames_pact_free(pac_u); } else { _fine_got_pack(pac_u, fra); + _fine_send(pac_u); } u3z(pas); @@ -1535,6 +1594,7 @@ static void _fine_hear_request(u3_ames* sam_u, } else { _fine_got_pack(pac_u, u3k(cac)); + _fine_send(pac_u); } u3z(pat);