diff --git a/ext/urcrypt/build.zig.zon b/ext/urcrypt/build.zig.zon index 0ab23988ac..38598af00a 100644 --- a/ext/urcrypt/build.zig.zon +++ b/ext/urcrypt/build.zig.zon @@ -15,8 +15,9 @@ .hash = "N-V-__8AAJ4DSwC7aDpt90TmGPWKAI6q4-titwp4M0zsZ2vY", }, .urcrypt = .{ - .url = "https://github.com/urbit/urcrypt/archive/465aad6262f2710f76f75adfe74effb5751c5ab3.tar.gz", - .hash = "N-V-__8AAL3OSQDA9xQasK60FkxcKuQoSANeWy_f9SxmxX1X", + .path = "../../../urcrypt", + //.url = "https://github.com/urbit/urcrypt/archive/465aad6262f2710f76f75adfe74effb5751c5ab3.tar.gz", + //.hash = "N-V-__8AAL3OSQDA9xQasK60FkxcKuQoSANeWy_f9SxmxX1X", }, }, .paths = .{ diff --git a/pkg/c3/motes.h b/pkg/c3/motes.h index 3ba8a700ed..8bb3b132ac 100644 --- a/pkg/c3/motes.h +++ b/pkg/c3/motes.h @@ -419,6 +419,7 @@ # define c3__fent c3_s4('f','e','n','t') # define c3__ferd c3_s4('f','e','r','d') # define c3__fhex c3_s4('f','h','e','x') +# define c3__fief c3_s4('f','i','e','f') # define c3__file c3_s4('f','i','l','e') # define c3__film c3_s4('f','i','l','m') # define c3__find c3_s4('f','i','n','d') diff --git a/pkg/noun/jets.c b/pkg/noun/jets.c index 3598364b1a..cca0d6449f 100644 --- a/pkg/noun/jets.c +++ b/pkg/noun/jets.c @@ -893,23 +893,29 @@ _cj_kick_z(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe) u3z(cor); return pro; } - ham_u->liv = c3n; + //ham_u->liv = c3n; ame = _cj_soft(cor, axe); - ham_u->liv = c3y; + //ham_u->liv = c3y; if ( c3n == u3r_sing(ame, pro) ) { - u3l_log("test: %s %s: mismatch: good %x, bad %x", + //u3l_log("test: %s %s: mismatch: good %x, bad %x", + // cop_u->cos_c, + // (!strcmp(".2", ham_u->fcs_c)) ? "$" : ham_u->fcs_c, + // u3r_mug(ame), + // u3r_mug(pro)); + //ham_u->liv = c3n; + u3l_log("test: %s %s: mismatch", cop_u->cos_c, - (!strcmp(".2", ham_u->fcs_c)) ? "$" : ham_u->fcs_c, - u3r_mug(ame), - u3r_mug(pro)); - ham_u->liv = c3n; + (!strcmp(".2", ham_u->fcs_c)) ? "$" : ham_u->fcs_c + ); + u3m_p("good", ame); + u3m_p("baad", pro); return u3m_bail(c3__fail); } else { -#if 0 +#if 1 u3l_log("test: %s %s", cop_u->cos_c, (!strcmp(".2", ham_u->fcs_c)) ? "$" : ham_u->fcs_c); diff --git a/pkg/noun/jets/137/tree.c b/pkg/noun/jets/137/tree.c index 956413530e..3c5e364fab 100644 --- a/pkg/noun/jets/137/tree.c +++ b/pkg/noun/jets/137/tree.c @@ -214,6 +214,9 @@ static u3j_core _137_hex_scr_d[] = static u3j_harm _137_hex_secp_secp256k1_make_a[] = {{".2", u3we_make, c3y}, {}}; static u3j_harm _137_hex_secp_secp256k1_sign_a[] = {{".2", u3we_sign, c3y}, {}}; static u3j_harm _137_hex_secp_secp256k1_reco_a[] = {{".2", u3we_reco, c3y}, {}}; +static u3j_harm _137_hex_secp_secp256k1_priv_to_pub_a[] = {{".2", u3we_priv_to_pub, c3n}, {}}; +static u3j_harm _137_hex_secp_secp256k1_tweak_sec_a[] = {{".2", u3we_tweak_sec, c3n}, {}}; +static u3j_harm _137_hex_secp_secp256k1_tweak_pub_a[] = {{".2", u3we_tweak_pub, c3n}, {}}; static u3j_harm _137_hex_secp_secp256k1_schnorr_sosi_a[] = {{".2", u3we_sosi}, {}}; @@ -233,6 +236,9 @@ static u3j_core _137_hex_secp_secp256k1_d[] = { { "make", 7, _137_hex_secp_secp256k1_make_a, 0, no_hashes }, { "sign", 7, _137_hex_secp_secp256k1_sign_a, 0, no_hashes }, { "reco", 7, _137_hex_secp_secp256k1_reco_a, 0, no_hashes }, + { "priv-to-pub", 7, _137_hex_secp_secp256k1_priv_to_pub_a, 0, no_hashes }, + { "tweak-sec", 7, _137_hex_secp_secp256k1_tweak_sec_a, 0, no_hashes }, + { "tweak-pub", 7, _137_hex_secp_secp256k1_tweak_pub_a, 0, no_hashes }, { "schnorr", 7, 0, _137_hex_secp_secp256k1_schnorr_d, no_hashes }, diff --git a/pkg/noun/jets/e/secp.c b/pkg/noun/jets/e/secp.c index fa0fbd20c4..7a3ca706a5 100644 --- a/pkg/noun/jets/e/secp.c +++ b/pkg/noun/jets/e/secp.c @@ -296,3 +296,106 @@ u3we_sove(u3_noun cor) return _cqes_sove(pub, mes, sig); } } + +static u3_atom +_cqes_tweak_sec(u3_atom sek, u3_atom tek) { + c3_y scalar[32], tweak[32]; + + if (0 != u3r_bytes_fit(32, scalar, sek)) { + return u3m_bail(c3__exit); + } + + if (0 != u3r_bytes_fit(32, tweak, tek)) { + return u3m_bail(c3__exit); + } + + if (0 != urcrypt_secp_scalar_tweak_add(sec_u, scalar, tweak)) { + return u3m_bail(c3__exit); + } + + return u3i_bytes(32, scalar); +} + +u3_noun +u3we_tweak_sec(u3_noun cor) +{ + u3_noun sek, tek; + + if ( (c3n == u3r_mean(cor, + u3x_sam_2, &sek, + u3x_sam_3, &tek, + 0)) || + (c3n == u3ud(sek)) || + (c3n == u3ud(tek))) { + return u3m_bail(c3__exit); + } + else { + return _cqes_tweak_sec(sek, tek); + } +} + +static u3_atom +_cqes_tweak_pub(u3_atom pub, u3_atom tek) { + c3_y cmp_point[33], tweak[32]; + + if (0 != u3r_bytes_fit(33, cmp_point, pub)) { + return u3m_bail(c3__exit); + } + + if (0 != u3r_bytes_fit(32, tweak, tek)) { + return u3m_bail(c3__exit); + } + + if (0 != urcrypt_secp_cmp_point_tweak_add(sec_u, cmp_point, tweak)) { + return u3m_bail(c3__exit); + } + + return u3i_bytes(33, cmp_point); +} + +u3_noun +u3we_tweak_pub(u3_noun cor) +{ + u3_noun pub, tek; + + if ( (c3n == u3r_mean(cor, + u3x_sam_2, &pub, + u3x_sam_3, &tek, + 0)) || + (c3n == u3ud(pub)) || + (c3n == u3ud(tek))) { + return u3m_bail(c3__exit); + } + else { + return _cqes_tweak_pub(pub, tek); + } +} + +static u3_noun +_cqes_priv_to_pub(u3_atom sek) { + c3_y scalar[32], cmp_point[33]; + + if (0 != u3r_bytes_fit(32, scalar, sek)) { + return u3m_bail(c3__exit); + } + + if (0 != urcrypt_secp_cmp_point_from_scalar(sec_u, scalar, cmp_point)) { + return u3m_bail(c3__exit); + } + + return u3i_bytes(33, cmp_point); +} + +u3_noun +u3we_priv_to_pub(u3_noun cor) +{ + + u3_noun a = u3r_at(u3x_sam, cor); + + if ( (u3_none == a) || (c3n == u3ud(a)) ) { + return u3m_bail(c3__exit); + } + else { + return _cqes_priv_to_pub(a); + } +} diff --git a/pkg/noun/jets/w.h b/pkg/noun/jets/w.h index 57d9677e7d..30b7b5a41c 100644 --- a/pkg/noun/jets/w.h +++ b/pkg/noun/jets/w.h @@ -247,6 +247,10 @@ u3_noun u3we_sosi(u3_noun); u3_noun u3we_sove(u3_noun); + u3_noun u3we_priv_to_pub(u3_noun); + u3_noun u3we_tweak_sec(u3_noun); + u3_noun u3we_tweak_pub(u3_noun); + u3_noun u3we_en_base16(u3_noun); u3_noun u3we_de_base16(u3_noun); diff --git a/pkg/noun/noun.h b/pkg/noun/noun.h index 965330a519..565c6eedd3 100644 --- a/pkg/noun/noun.h +++ b/pkg/noun/noun.h @@ -19,6 +19,7 @@ #include "log.h" #include "nock.h" #include "retrieve.h" +#include "ship.h" #include "trace.h" #include "urth.h" #include "xtract.h" diff --git a/pkg/noun/ship.c b/pkg/noun/ship.c index 6aebff71aa..95c5414c9b 100644 --- a/pkg/noun/ship.c +++ b/pkg/noun/ship.c @@ -5,57 +5,33 @@ #include "vortex.h" #include "ship.h" -static inline void -_s_chub_to_bytes(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; -} - -static inline c3_d -_s_bytes_to_chub(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; -} - void u3_ship_to_bytes(u3_ship who_u, c3_y len_y, c3_y* buf_y) { c3_y sip_y[16] = {0}; - _s_chub_to_bytes(sip_y, who_u[0]); - _s_chub_to_bytes(sip_y + 8, who_u[1]); + c3_etch_chub(sip_y, who_u.hed_d); + c3_etch_chub(sip_y + 8, who_u.tel_d); memcpy(buf_y, sip_y, c3_min(16, len_y)); } -void -u3_ship_of_bytes(u3_ship who_u, c3_y len_y, c3_y* buf_y) +u3_ship +u3_ship_of_bytes(c3_y len_y, c3_y* buf_y) { + u3_ship who_u; c3_y sip_y[16] = {0}; memcpy(sip_y, buf_y, c3_min(16, len_y)); - who_u[0] = _s_bytes_to_chub(sip_y); - who_u[1] = _s_bytes_to_chub(sip_y + 8); + who_u.hed_d = c3_sift_chub(sip_y); + who_u.tel_d = c3_sift_chub(sip_y + 8); + return who_u; } u3_atom u3_ship_to_noun(u3_ship who_u) { - return u3i_chubs(2, who_u); + return u3i_chubs(2, &who_u.hed_d); } c3_c* @@ -67,43 +43,45 @@ u3_ship_to_string(u3_ship who_u) return who_c; } -void -u3_ship_of_noun(u3_ship who_u, u3_noun who) +u3_ship +u3_ship_of_noun(u3_noun who) { - u3r_chubs(0, 2, who_u, who); + u3_ship who_u; + u3r_chubs(0, 2, &who_u.hed_d, who); + return who_u; } c3_o u3_ships_equal(u3_ship sip_u, u3_ship sap_u) { - return __((sip_u[0] == sap_u[0]) && (sip_u[1] == sap_u[1])); + return __((sip_u.hed_d == sap_u.hed_d) && (sip_u.tel_d == sap_u.tel_d)); } void u3_ship_copy(u3_ship des_u, u3_ship src_u) { - des_u[0] = src_u[0]; - des_u[1] = src_u[1]; + des_u.hed_d = src_u.hed_d; + des_u.tel_d = src_u.tel_d; } c3_l u3_ship_rank(u3_ship who_u) { - if ( who_u[1] ) return c3__pawn; - else if ( who_u[0] >> 32 ) return c3__earl; - else if ( who_u[0] >> 16 ) return c3__duke; - else if ( who_u[0] >> 8 ) return c3__king; + if ( who_u.tel_d ) return c3__pawn; + else if ( who_u.hed_d >> 32 ) return c3__earl; + else if ( who_u.hed_d >> 16 ) return c3__duke; + else if ( who_u.hed_d >> 8 ) return c3__king; else return c3__czar; } c3_y -u3_ship_czar(u3_ship who_u) { return who_u[0] & 0xFF; } +u3_ship_czar(u3_ship who_u) { return who_u.hed_d & 0xFF; } c3_s -u3_ship_king(u3_ship who_u) { return who_u[0] & 0xffff; } +u3_ship_king(u3_ship who_u) { return who_u.hed_d & 0xffff; } c3_w -u3_ship_duke(u3_ship who_u) { return who_u[0] & 0xffffffff; } +u3_ship_duke(u3_ship who_u) { return who_u.hed_d & 0xffffffff; } c3_d -u3_ship_earl(u3_ship who_u) { return who_u[0]; } +u3_ship_earl(u3_ship who_u) { return who_u.hed_d; } diff --git a/pkg/noun/ship.h b/pkg/noun/ship.h index 8104c42d5b..e23620992a 100644 --- a/pkg/noun/ship.h +++ b/pkg/noun/ship.h @@ -4,19 +4,22 @@ #include "c3/c3.h" #include "types.h" -typedef c3_d u3_ship[2]; +typedef struct _u3_ship { + c3_d hed_d; + c3_d tel_d; +} u3_ship; void -u3_ship_to_bytes(c3_d sip_d[2], c3_y len_y, c3_y* buf_y); +u3_ship_to_bytes(u3_ship who_u, c3_y len_y, c3_y* buf_y); -void -u3_ship_of_bytes(u3_ship who_u, c3_y len_y, c3_y* buf_y); +u3_ship +u3_ship_of_bytes(c3_y len_y, c3_y* buf_y); u3_atom u3_ship_to_noun(u3_ship who_u); -void -u3_ship_of_noun(u3_ship who_u, u3_noun who); +u3_ship +u3_ship_of_noun(u3_noun who); c3_c* u3_ship_to_string(u3_ship who_u); @@ -27,9 +30,6 @@ u3_ships_equal(u3_ship sip_u, u3_ship sap_u); c3_l u3_ship_rank(u3_ship who_u); -void -u3_ship_copy(u3_ship des_u, u3_ship src_u); - /** * Returns a ship's galaxy byte prefix. */ diff --git a/pkg/vere/auto.c b/pkg/vere/auto.c index d59e5df0ef..0414e958f5 100644 --- a/pkg/vere/auto.c +++ b/pkg/vere/auto.c @@ -341,6 +341,7 @@ u3_auto_exit(u3_auto* car_u) while ( egg_u ) { xen_u = egg_u->nex_u; + _auto_news(egg_u, u3_ovum_exit); u3_ovum_free(egg_u); egg_u = xen_u; } @@ -489,7 +490,6 @@ u3_auto_init(u3_pier* pir_u) car_u = _auto_link(u3_conn_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_lick_io_init(pir_u), pir_u, car_u); car_u = _auto_link(u3_mesa_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_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/vere/build.zig b/pkg/vere/build.zig index 6832a320f3..c352d01137 100644 --- a/pkg/vere/build.zig +++ b/pkg/vere/build.zig @@ -222,8 +222,10 @@ const c_source_files = [_][]const u8{ "db/lmdb.c", "disk.c", "foil.c", - "io/ames.c", + "io/ames/ames.c", "io/ames/stun.c", + "io/ames/lamp.c", + "io/ames/nat.c", "io/behn.c", "io/conn.c", "io/cttp.c", diff --git a/pkg/vere/dawn.c b/pkg/vere/dawn.c index 1ae0289f36..e586daac01 100644 --- a/pkg/vere/dawn.c +++ b/pkg/vere/dawn.c @@ -143,10 +143,10 @@ _dawn_get_jam(c3_c* url_c) return u3ke_cue(jammed); } -/* _dawn_eth_rpc(): ethereum JSON RPC with request/response as +octs +/* _dawn_gat_rpc(): ethereum JSON RPC with request/response as +octs */ static u3_noun -_dawn_eth_rpc(c3_c* url_c, u3_noun oct) +_dawn_gat_rpc_old(c3_c* url_c, u3_noun oct) { uv_buf_t buf_u = _dawn_post_json(url_c, _dawn_oct_to_buf(oct)); u3_noun pro = _dawn_buf_to_oct(buf_u); @@ -269,13 +269,11 @@ _dawn_sponsor(u3_noun who, u3_noun rac, u3_noun pot) u3_noun u3_dawn_vent(u3_noun ship, u3_noun feed, u3_noun* rift) { - u3_noun fed, pos, pon, zar, tuf; + u3_noun fed, pos, pon, zar, tuf, src; u3_noun rank = u3do("clan:title", u3k(ship)); - c3_c* url_c = ( 0 != u3_Host.ops_u.eth_c ) ? - u3_Host.ops_u.eth_c : - "https://roller.urbit.org/v1/azimuth"; + c3_c url_c[4096]; { // +point:azimuth: on-chain state @@ -295,12 +293,11 @@ u3_dawn_vent(u3_noun ship, u3_noun feed, u3_noun* rift) u3_Host.ops_u.who_c); { - u3_noun oct = u3do("point:give:dawn", u3k(ship)); - u3_noun luh = _dawn_eth_rpc(url_c, u3k(oct)); + sprintf(url_c, "%s/_~_/=pynt=/j/%s", + u3_Host.ops_u.gat_c, u3_Host.ops_u.who_c); + u3_noun top = u3_king_get_noun(url_c); - pot = _dawn_need_unit(u3dc("point:take:dawn", u3k(ship), u3k(luh)), - "boot: failed to retrieve public keys"); - u3z(oct); u3z(luh); + pot = _dawn_need_unit(top, "boot: failed to retrieve public keys"); } } @@ -345,12 +342,9 @@ u3_dawn_vent(u3_noun ship, u3_noun feed, u3_noun* rift) { u3l_log("boot: retrieving galaxy table"); - u3_noun oct = u3v_wish("czar:give:dawn"); - u3_noun raz = _dawn_eth_rpc(url_c, u3k(oct)); - - zar = _dawn_need_unit(u3do("czar:take:dawn", u3k(raz)), - "boot: failed to retrieve galaxy table"); - u3z(oct); u3z(raz); + sprintf(url_c, "%s/_~_/=lamp=/j", + u3_Host.ops_u.gat_c); + zar = u3_king_get_noun(url_c); } // (list turf): ames domains @@ -361,12 +355,9 @@ u3_dawn_vent(u3_noun ship, u3_noun feed, u3_noun* rift) else { u3l_log("boot: retrieving network domains"); - u3_noun oct = u3v_wish("turf:give:dawn"); - u3_noun fut = _dawn_eth_rpc(url_c, u3k(oct)); - - tuf = _dawn_need_unit(u3do("turf:take:dawn", u3k(fut)), - "boot: failed to retrieve network domains"); - u3z(oct); u3z(fut); + sprintf(url_c, "%s/_~_/=turf=/j", + u3_Host.ops_u.gat_c); + u3_noun tuf = u3_king_get_noun(url_c); } pon = u3_nul; @@ -385,15 +376,18 @@ u3_dawn_vent(u3_noun ship, u3_noun feed, u3_noun* rift) // retrieve +point:azimuth of pos (sponsor of ship) // { - u3_noun oct = u3do("point:give:dawn", u3k(pos)); - u3_noun luh = _dawn_eth_rpc(url_c, u3k(oct)); - - son = _dawn_need_unit(u3dc("point:take:dawn", u3k(pos), u3k(luh)), - "boot: failed to retrieve sponsor keys"); + u3_noun top = u3dc("scot", c3__p, u3k(pos)); + c3_c* pot_c = u3r_string(top); + u3z(top); + sprintf(url_c, "%s/_~_/=pynt=/j/%s", + u3_Host.ops_u.gat_c, pot_c); + u3_noun nos = u3_king_get_noun(url_c); + c3_free(pot_c); + + son = _dawn_need_unit(top, "boot: failed to retrieve public keys"); // append to sponsor chain list // - pon = u3nc(u3nc(u3k(pos), u3k(son)), pon); - u3z(oct); u3z(luh); + pon = u3nc(u3nc(u3k(pos), son), pon); } // find next sponsor @@ -405,13 +399,20 @@ u3_dawn_vent(u3_noun ship, u3_noun feed, u3_noun* rift) u3z(son); } + + if ( 0 != u3_Host.ops_u.src_c ) { + src = u3v_wish(u3_Host.ops_u.src_c); + } + else { + src = u3_nul; + } - // [%dawn seed sponsors galaxies domains block eth-url snap] + // [%dawn seed sponsors galaxies domains block eth-url sources] // //NOTE blocknum of 0 is fine because jael ignores it. // should probably be removed from dawn event. u3_noun ven = u3nc(c3__dawn, - u3nq(u3k(u3t(fed)), pon, zar, u3nt(tuf, 0, u3_nul))); + u3nq(u3k(u3t(fed)), pon, zar, u3nq(tuf, 0, u3_nul, src))); u3z(fed); u3z(rank); u3z(pos); u3z(ship); u3z(feed); diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 19a03b5372..121526cc82 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -480,10 +480,10 @@ u3_disk_save_meta(MDB_env* mdb_u, const u3_meta* met_u) { u3_assert( c3y == u3a_is_cat(met_u->lif_w) ); - u3_noun who = u3i_chubs(2, met_u->who_d); + u3_noun who = u3_ship_to_noun(met_u->who_u); if ( (c3n == _disk_save_meta(mdb_u, "version", sizeof(c3_w), (c3_y*)&met_u->ver_w)) - || (c3n == _disk_save_meta(mdb_u, "who", 2 * sizeof(c3_d), (c3_y*)met_u->who_d)) + || (c3n == _disk_save_meta(mdb_u, "who", sizeof(u3_ship), (c3_y*)&met_u->who_u)) || (c3n == _disk_save_meta(mdb_u, "fake", sizeof(c3_o), (c3_y*)&met_u->fak_o)) || (c3n == _disk_save_meta(mdb_u, "life", sizeof(c3_w), (c3_y*)&met_u->lif_w)) ) { @@ -547,7 +547,7 @@ c3_o u3_disk_read_meta(MDB_env* mdb_u, u3_meta* met_u) { c3_w ver_w, lif_w; - c3_d who_d[2]; + u3_ship who_u; c3_o fak_o; _mdb_val val_u; @@ -572,26 +572,7 @@ u3_disk_read_meta(MDB_env* mdb_u, u3_meta* met_u) fprintf(stderr, "disk: read meta: strange identity\r\n"); } - c3_y* byt_y = val_u.buf_y; - - who_d[0] = (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; - - byt_y += 8; - who_d[1] = (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; + who_u = u3_ship_of_bytes(16, val_u.buf_y); // fake bit // @@ -627,7 +608,7 @@ u3_disk_read_meta(MDB_env* mdb_u, u3_meta* met_u) fprintf(stderr, "disk: read meta: strange life\r\n"); } - byt_y = val_u.buf_y; + c3_y* byt_y = val_u.buf_y; lif_w = (c3_w)byt_y[0] | (c3_w)byt_y[1] << 8 | (c3_w)byt_y[2] << 16 @@ -658,7 +639,7 @@ u3_disk_read_meta(MDB_env* mdb_u, u3_meta* met_u) // because sometimes we call this just to ensure metadata exists if ( met_u ) { met_u->ver_w = ver_w; - memcpy(met_u->who_d, who_d, 2 * sizeof(c3_d)); + met_u->who_u = who_u; met_u->fak_o = fak_o; met_u->lif_w = lif_w; } diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c deleted file mode 100644 index 39f04b5ebf..0000000000 --- a/pkg/vere/io/ames.c +++ /dev/null @@ -1,2984 +0,0 @@ -/// @file - -#include "vere.h" -#include "mdns.h" -#include "io/ames/stun.h" - -#include "noun.h" -#include "ur/ur.h" - -#include "zlib.h" -#include "natpmp.h" - -#include "ent/ent.h" - -#ifndef U3_OS_windows -#include -#endif - -#define FINE_PAGE 4096 // packets per page -#define FINE_FRAG 1024 // bytes per fragment packet -#define FINE_PATH_MAX 384 // longest allowed scry path -#define HEAD_SIZE 4 // header size in bytes - -// a hack to work around the inability to delete from a hashtable -// -#define FINE_PEND 1 // scry cache sentinel value: "pending" -#define FINE_DEAD 2 // scry cache sentinel value: "dead" - -#define QUEUE_MAX 30 // max number of packets in queue - -#define _CZAR_GONE UINT32_MAX - -typedef enum u3_stun_state { - STUN_OFF = 0, - STUN_TRYING = 1, - STUN_KEEPALIVE = 2, -} u3_stun_state; - -/* u3_fine: fine networking -*/ - typedef struct _u3_fine { - 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_y ver_y; // protocol version - u3p(u3h_root) lax_p; // lane scry cache - struct _u3_panc* pan_u; // outbound packet queue, backward - struct { // - c3_c dom_c[251]; // domain - c3_o dom_o; // have domain - uv_timer_t tim_u; // resolve timer - c3_s pen_s; // pending - c3_w pip_w[256]; // ipv4 - c3_w log_w[256 >> 5]; // log error - } zar_u; // - struct { // stun client state: - u3_stun_state sat_y; // formal state - c3_y tid_y[12]; // last transaction id - c3_y dad_y; // sponsoring galaxy - u3_lane lan_u; // sponsoring galaxy IP and port - uv_timer_t tim_u; // keepalive timer handle - struct timeval sar_u; // date we started trying to send - u3_lane sef_u; // our lane, if we know it - c3_o wok_o; // STUN worked, set on first success - } sun_u; // - struct { - natpmp_t req_u; // libnatpmp struct for mapping request - uv_poll_t pol_u; // handle waits on libnatpmp socket - uv_timer_t tim_u; // every two hours if mapping succeeds - } nat_u; // libnatpmp stuff for port forwarding - c3_o nal_o; // lane cache backcompat flag - struct { // config: - c3_o see_o; // can scry - c3_o fit_o; // filtering active - } fig_u; // - struct { // stats: - c3_d dop_d; // drop count - c3_d fod_d; // forwards dropped count - c3_d foq_d; // forward queue size - c3_d fow_d; // forwarded count - c3_o for_o; // forwarding enabled - c3_d hed_d; // failed to read header - c3_d vet_d; // version mismatches filtered - c3_d mut_d; // invalid mugs filtered - c3_d pre_d; // failed to read prelude - c3_d wal_d; // failed to read wail - c3_d wap_d; // failed to read wail path - c3_d fal_d; // crash count - c3_d vil_d; // encryption failures - c3_d saw_d; // successive scry failures - } 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; - -/* u3_peep: unsigned fine request body -*/ - typedef struct _u3_peep { - c3_w fra_w; // fragment number - c3_s len_s; // path length - c3_c* pat_c; // path as ascii - } u3_peep; - -/* u3_wail: fine request body -*/ - typedef struct _u3_wail { - c3_y tag_y; // tag (always 0, unsigned) - u3_peep pep_u; // request payload - } u3_wail; - -/* u3_meow: response portion of purr packet - * - * siz_s: number of bytes in the packet -*/ - typedef struct _u3_meow { - c3_y sig_y[64]; // host signature - c3_w num_w; // number of fragments - c3_s siz_s; // datum size (actual) - c3_y* dat_y; // datum (0 if null response) - } u3_meow; - -/* u3_purr: fine packet response -*/ - typedef struct _u3_purr { - u3_peep pep_u; // fragment number + path - u3_meow mew_u; // fragment - } u3_purr; - -/* u3_body: ames packet body -*/ - typedef struct _u3_body { - c3_s con_s; // content size - c3_y* con_y; // content - c3_l mug_l; // checksum - } u3_body; - -/* u3_ptag: packet-type tag -*/ - typedef enum _u3_ptag { - PACT_AMES = 1, // ames packet - PACT_WAIL = 2, // fine request packet - PACT_PURR = 3 // fine response packet - } u3_ptag; - -/* u3_pact: ames packet - * - * Filled in piece by piece as we parse or construct it. -*/ - typedef struct _u3_pact { - uv_udp_send_t snd_u; // udp send request - struct _u3_ames* sam_u; // ames backpointer - c3_w len_w; // length in bytes - c3_y* hun_y; // packet buffer - u3_lane lan_u; // destination/origin lane - u3_head hed_u; // head of packet - u3_prel pre_u; // packet prelude - u3_ptag typ_y; // packet type tag - union { - u3_body bod_u; // tagged by PACT_AMES - u3_wail wal_u; // tagged by PACT_WAIL - u3_purr pur_u; // tagged by PACT_PURR - }; - } u3_pact; - -/* u3_panc: packet queue -*/ - typedef struct _u3_panc { - struct _u3_panc* pre_u; // previous packet - struct _u3_panc* nex_u; // next packet - u3_pact* pac_u; // this packet - c3_o for_o; // are we forwarding this? - } u3_panc; - -#define _str_typ(typ_y) ( \ - ( PACT_AMES == typ_y ) ? "ames" \ - : ( PACT_WAIL == typ_y ) ? "wail" \ - : ( PACT_PURR == typ_y ) ? "purr" : "????") - -const c3_c* PATH_PARSER = - ";~(pfix fas (most fas (cook crip (star ;~(less fas prn)))))"; - -static c3_o net_o = c3y; // online heuristic to limit verbosity - -/* _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); -} - -static void -_ames_pact_free(u3_pact* pac_u) -{ - switch ( pac_u->typ_y ) { - case PACT_AMES: - c3_free(pac_u->bod_u.con_y); - break; - - case PACT_WAIL: - c3_free(pac_u->wal_u.pep_u.pat_c); - break; - - case PACT_PURR: - c3_free(pac_u->pur_u.pep_u.pat_c); - c3_free(pac_u->pur_u.mew_u.dat_y); - break; - - default: - u3l_log("ames_pact_free: bad packet type %s", - _str_typ(pac_u->typ_y)); - u3_pier_bail(u3_king_stub()); - } - - c3_free(pac_u->hun_y); - c3_free(pac_u); -} - -/* _ames_panc_free(): remove references, lose refcounts and free struct -*/ -static void -_ames_panc_free(u3_panc* pan_u) -{ - if ( c3y == pan_u->for_o ) { - if ( 0 != pan_u->nex_u ) { - pan_u->nex_u->pre_u = pan_u->pre_u; - } - - if ( 0 != pan_u->pre_u ) { - pan_u->pre_u->nex_u = pan_u->nex_u; - } - else { - u3_assert(pan_u == pan_u->pac_u->sam_u->pan_u); - pan_u->pac_u->sam_u->pan_u = pan_u->nex_u; - } - } - _ames_pact_free(pan_u->pac_u); - c3_free(pan_u); -} - -static inline u3_ptag -_ames_pact_typ(u3_head* hed_u) -{ - return (( c3y == hed_u->sim_o ) ? PACT_AMES : - ( c3y == hed_u->req_o ) ? PACT_WAIL : PACT_PURR); -} - -static inline c3_y -_ames_origin_size(u3_head* hed_u) -{ - return ( c3y == hed_u->rel_o ) ? 6 : 0; // origin is 6 bytes -} - -static c3_y -_ames_prel_size(u3_head* hed_u) -{ - c3_y lif_y = 1; - c3_y sen_y = 2 << hed_u->sac_y; - c3_y rec_y = 2 << hed_u->rac_y; - c3_y rog_y = _ames_origin_size(hed_u); - return lif_y + sen_y + rec_y + rog_y; -} - -static inline c3_s -_ames_body_size(u3_body* bod_u) -{ - return bod_u->con_s; -} - -static inline c3_s -_fine_peep_size(u3_peep* pep_u) -{ - return ( - sizeof(pep_u->fra_w) + - sizeof(pep_u->len_s) + - pep_u->len_s); -} - -static inline c3_y -_fine_bytes_word(c3_w num_w) -{ - return (c3_bits_word(num_w) + 7) >> 3; -} - -static inline c3_s -_fine_meow_size(u3_meow* mew_u) -{ - c3_y cur_y = 0; - if (mew_u->siz_s != 0) { - cur_y = sizeof(mew_u->num_w); - } - else { - cur_y = _fine_bytes_word(mew_u->num_w); - } - return ( - sizeof(mew_u->sig_y) + - cur_y + - mew_u->siz_s); -} - -static c3_s -_fine_purr_size(u3_purr* pur_u) -{ - c3_s pur_s = _fine_peep_size(&pur_u->pep_u); - c3_s mew_s = _fine_meow_size(&pur_u->mew_u); - return pur_s + mew_s; -} - -static c3_o -_ames_check_mug(u3_pact* pac_u) -{ - c3_w rog_w = HEAD_SIZE + _ames_origin_size(&pac_u->hed_u); - c3_l mug_l = u3r_mug_bytes(pac_u->hun_y + rog_w, - pac_u->len_w - rog_w); - // u3l_log("len_w: %u, rog_w: %u, bod_l 0x%05x, hed_l 0x%05x", - // pac_u->len_w, rog_w, - // (mug_l & 0xfffff), - // (pac_u->hed_u.mug_l & 0xfffff)); - return ( - ((mug_l & 0xfffff) == (pac_u->hed_u.mug_l & 0xfffff)) - ? c3y : c3n); -} - -/* _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] = c3_sift_chub(sip_y); - sip_d[1] = c3_sift_chub(sip_y + 8); -} - -/* _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}; - - c3_etch_chub(sip_y, sip_d[0]); - c3_etch_chub(sip_y + 8, sip_d[1]); - - memcpy(buf_y, sip_y, c3_min(16, len_y)); -} - -/* _ames_sift_head(): parse packet header. -*/ -static void -_ames_sift_head(u3_head* hed_u, c3_y buf_y[4]) -{ - c3_w hed_w = c3_sift_word(buf_y); - - // first two bits are reserved - // - hed_u->req_o = (hed_w >> 2) & 0x1; - hed_u->sim_o = (hed_w >> 3) & 0x1; - hed_u->ver_y = (hed_w >> 4) & 0x7; - hed_u->sac_y = (hed_w >> 7) & 0x3; - hed_u->rac_y = (hed_w >> 9) & 0x3; - hed_u->mug_l = (hed_w >> 11) & 0xfffff; // 20 bits - hed_u->rel_o = (hed_w >> 31) & 0x1; -} - -/* _ames_sift_prel(): parse prelude, -*/ -static void -_ames_sift_prel(u3_head* hed_u, - u3_prel* pre_u, - c3_y* buf_y) -{ - c3_y sen_y, rec_y; - c3_w cur_w = 0; - - // if packet is relayed, parse 6-byte origin field - // - if ( c3y == hed_u->rel_o ) { - c3_y rag_y[8] = {0}; - memcpy(rag_y, buf_y + cur_w, 6); - pre_u->rog_d = c3_sift_chub(rag_y); - cur_w += 6; - } - else { - pre_u->rog_d = 0; - } - - // parse life ticks - // - pre_u->sic_y = buf_y[cur_w] & 0xf; - pre_u->ric_y = (buf_y[cur_w] >> 4) & 0xf; - cur_w++; - - // parse sender ship - // - sen_y = 2 << hed_u->sac_y; - _ames_ship_to_chubs(pre_u->sen_d, sen_y, buf_y + cur_w); - cur_w += sen_y; - - // parse receiver ship - // - rec_y = 2 << hed_u->rac_y; - _ames_ship_to_chubs(pre_u->rec_d, rec_y, buf_y + cur_w); - cur_w += rec_y; -} - -/* _fine_sift_wail(): parse request body, returning success -*/ -static c3_o -_fine_sift_wail(u3_pact* pac_u, c3_w cur_w) -{ - c3_w fra_w = sizeof(pac_u->wal_u.pep_u.fra_w); - c3_w len_w = sizeof(pac_u->wal_u.pep_u.len_s); - c3_w exp_w = fra_w + len_w; - c3_s len_s; - - if ( cur_w + exp_w > pac_u->len_w ) { - u3l_log("fine: wail not big enough"); - return c3n; - } - - // parse tag - // - pac_u->wal_u.tag_y = *(pac_u->hun_y + cur_w); - cur_w++; - - if ( 0 != pac_u->wal_u.tag_y ) { - u3l_log("fine: wail tag unknown %u", pac_u->wal_u.tag_y); - return c3n; - } - - // parse fragment number - // - pac_u->wal_u.pep_u.fra_w = c3_sift_word(pac_u->hun_y + cur_w); - cur_w += fra_w; - - // parse path length field - // - len_s = c3_sift_short(pac_u->hun_y + cur_w); - pac_u->wal_u.pep_u.len_s = len_s; - cur_w += len_w; - - if ( len_s > FINE_PATH_MAX ) { - u3l_log("ames wail len: %u, max %u", len_s, FINE_PATH_MAX); - return c3n; - } - - { - c3_w tot_w = cur_w + len_s; - if ( tot_w != pac_u->len_w ) { - u3l_log("fine: wail expected total len: %u, actual %u", - tot_w, pac_u->len_w); - return c3n; - } - } - - // parse request path - // - pac_u->wal_u.pep_u.pat_c = c3_calloc(len_s + 1); - memcpy(pac_u->wal_u.pep_u.pat_c, pac_u->hun_y + cur_w, len_s); - pac_u->wal_u.pep_u.pat_c[len_s] = '\0'; - return c3y; -} - -/* _fine_sift_meow(): parse signed scry response fragment -*/ -static c3_o -_fine_sift_meow(u3_meow* mew_u, u3_noun mew) -{ - c3_o ret_o; - c3_w len_w = u3r_met(3, mew); - c3_w sig_w = sizeof(mew_u->sig_y); - c3_w num_w = sizeof(mew_u->num_w); - c3_w min_w = sig_w + 1; - c3_w max_w = sig_w + num_w + FINE_FRAG; - - if ( (len_w < min_w) || (len_w > max_w) ) { - u3l_log("sift_meow len_w %u (min_w %u, max_w %u)", len_w, min_w, max_w); - ret_o = c3n; - } - else { - c3_w cur_w = 0; - - // parse signature - // - u3r_bytes(cur_w, sig_w, mew_u->sig_y, mew); - cur_w += sig_w; - - // parse number of fragments - // - u3r_bytes(cur_w, num_w, (c3_y*)&mew_u->num_w, mew); - num_w = c3_min(num_w, (len_w - cur_w)); - cur_w += num_w; - u3_assert(len_w >= cur_w); - - // parse data payload - // - mew_u->siz_s = len_w - cur_w; - - if ( !mew_u->siz_s ) { - mew_u->dat_y = 0; - } - else { - mew_u->dat_y = c3_calloc(mew_u->siz_s); - u3r_bytes(cur_w, mew_u->siz_s, mew_u->dat_y, mew); - } - - ret_o = c3y; - } - - u3z(mew); - return ret_o; -} - -/* _ames_etch_head(): serialize packet header. -*/ -static void -_ames_etch_head(u3_head* hed_u, c3_y buf_y[4]) -{ - // only version 0 currently recognized - // - u3_assert( 0 == hed_u->ver_y ); // XX remove after testing - - c3_w hed_w = ((hed_u->req_o & 0x1) << 2) - ^ ((hed_u->sim_o & 0x1) << 3) - ^ ((hed_u->ver_y & 0x7) << 4) - ^ ((hed_u->sac_y & 0x3) << 7) - ^ ((hed_u->rac_y & 0x3) << 9) - ^ ((hed_u->mug_l & 0xfffff) << 11) - ^ (((c3_w)hed_u->rel_o & 0x1) << 31); - - c3_etch_word(buf_y, hed_w); -} - -static void -_ames_etch_origin(c3_d rog_d, c3_y* buf_y) -{ - c3_y rag_y[8] = {0}; - c3_etch_chub(rag_y, rog_d); - memcpy(buf_y, rag_y, 6); -} - -/* _ames_etch_prel(): serialize packet prelude -*/ -static void -_ames_etch_prel(u3_head* hed_u, u3_prel* pre_u, c3_y* buf_y) -{ - c3_w cur_w = 0; - - // if packet is relayed, write the 6-byte origin field - // - if ( c3y == hed_u->rel_o ) { - _ames_etch_origin(pre_u->rog_d, buf_y + cur_w); - cur_w += 6; - } - - // write life ticks - // - buf_y[cur_w] = (pre_u->sic_y & 0xf) ^ ((pre_u->ric_y & 0xf) << 4); - cur_w++; - - // write sender ship - // - c3_y sen_y = 2 << hed_u->sac_y; - _ames_ship_of_chubs(pre_u->sen_d, sen_y, buf_y + cur_w); - cur_w += sen_y; - - // write receiver ship - // - c3_y rec_y = 2 << hed_u->rac_y; - _ames_ship_of_chubs(pre_u->rec_d, rec_y, buf_y + cur_w); - cur_w += rec_y; -} - -/* _fine_etch_peep(): serialize unsigned scry request -*/ -static void -_fine_etch_peep(u3_peep* pep_u, c3_y* buf_y) -{ - c3_w cur_w = 0; - - // write fragment number - // - c3_etch_word(buf_y + cur_w, pep_u->fra_w); - cur_w += sizeof(pep_u->fra_w); - - // write path length - // - c3_etch_short(buf_y + cur_w, pep_u->len_s); - cur_w += sizeof(pep_u->len_s); - - // write request path - // - memcpy(buf_y + cur_w, pep_u->pat_c, pep_u->len_s); -} - -/* fine_etch_meow(): serialize signed scry response fragment -*/ -static void -_fine_etch_meow(u3_meow* mew_u, c3_y* buf_y) -{ - c3_w cur_w = 0; - - // write signature - // - c3_w sig_w = sizeof(mew_u->sig_y); - memcpy(buf_y + cur_w, mew_u->sig_y, sig_w); - cur_w += sig_w; - - { - c3_y num_y[4]; - c3_y len_y = _fine_bytes_word(mew_u->num_w); - - // write number of fragments - // - c3_etch_word(num_y, mew_u->num_w); - memcpy(buf_y + cur_w, num_y, len_y); - - if (mew_u->siz_s != 0) { - cur_w += sizeof(mew_u->num_w); - } - else { - cur_w += len_y; - } - } - - // write response fragment data - // - memcpy(buf_y + cur_w, mew_u->dat_y, mew_u->siz_s); -} - -/* _fine_etch_purr(): serialise response packet - */ -static void -_fine_etch_purr(u3_purr* pur_u, c3_y* buf_y) -{ - c3_w cur_w = 0; - - // write unsigned scry request - // - _fine_etch_peep(&pur_u->pep_u, buf_y + cur_w); - cur_w += _fine_peep_size(&pur_u->pep_u); - - // write signed response fragment - _fine_etch_meow(&pur_u->mew_u, buf_y + cur_w); -} - -/* _fine_etch_response(): serialize scry response packet -*/ -static void -_fine_etch_response(u3_pact* pac_u) -{ - c3_w pre_w, pur_w, cur_w, rog_w; - - pre_w = _ames_prel_size(&pac_u->hed_u); - pur_w = _fine_purr_size(&pac_u->pur_u); - pac_u->len_w = HEAD_SIZE + pre_w + pur_w; - pac_u->hun_y = c3_calloc(pac_u->len_w); - - // skip the header until we know what the mug should be - // - cur_w = HEAD_SIZE; - - // write prelude - // - _ames_etch_prel(&pac_u->hed_u, &pac_u->pre_u, pac_u->hun_y + cur_w); - cur_w += pre_w; - - // write body - // - _fine_etch_purr(&pac_u->pur_u, pac_u->hun_y + cur_w); - - // calculate mug and write header - // - rog_w = HEAD_SIZE + _ames_origin_size(&pac_u->hed_u); - pac_u->hed_u.mug_l = u3r_mug_bytes(pac_u->hun_y + rog_w, - pac_u->len_w - rog_w); - _ames_etch_head(&pac_u->hed_u, pac_u->hun_y); - - u3_assert( c3y == _ames_check_mug(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); -} - -/* _ames_send_cb(): send callback. -*/ -static void -_ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) -{ - u3_pact* pac_u = (u3_pact*)req_u; - u3_ames* sam_u = pac_u->sam_u; - - if ( !sas_i ) { - net_o = c3y; - } - else if ( c3y == net_o ) { - u3l_log("ames: send fail: %s", uv_strerror(sas_i)); - net_o = c3n; - } - - _ames_pact_free(pac_u); -} - -/* _ames_send(): send buffer to address on port. -*/ -static void -_ames_send(u3_pact* pac_u) -{ - u3_ames* sam_u = pac_u->sam_u; - - if ( !pac_u->hun_y - || !sam_u - || !pac_u->len_w - || !pac_u->lan_u.por_s ) - { - u3l_log("ames: _ames_send null"); - _ames_pact_free(pac_u); - } - else { - struct sockaddr_in add_u; - - memset(&add_u, 0, sizeof(add_u)); - add_u.sin_family = AF_INET; - add_u.sin_addr.s_addr = htonl(pac_u->lan_u.pip_w); - add_u.sin_port = htons(pac_u->lan_u.por_s); - - { - 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(&pac_u->snd_u, - &u3_Host.wax_u, - &buf_u, 1, - (const struct sockaddr*)&add_u, - _ames_send_cb); - - if ( sas_i ) { - _ames_send_cb(&pac_u->snd_u, sas_i); - } - } - } -} - -/* 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) { - // [%| p=@] - // [%& p=@pC] - 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 -*/ -static u3_weak -_ames_lane_from_cache(u3p(u3h_root) lax_p, u3_noun who, c3_o nal_o) { - u3_weak lac = u3h_git(lax_p, who); - - if ( u3_none == lac ) { - u3z(who); - return lac; - } - - if ( nal_o == c3y ) { - lac = u3k(u3h(lac)); - } - - else { - 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; -} - -static u3_noun -_ames_pact_to_noun(u3_pact* pac_u) -{ - u3_noun pac = u3i_bytes(pac_u->len_w, pac_u->hun_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_str: galaxy name as c3_c[3] -*/ -static void -_ames_czar_str(c3_c zar_c[3], c3_y imp_y) -{ - u3_po_to_suffix(imp_y, (c3_y*)zar_c, (c3_y*)zar_c + 1, (c3_y*)zar_c + 2); -} - -/* _ames_etch_czar: galaxy fqdn -*/ -static c3_i -_ames_etch_czar(c3_c dns_c[256], const c3_c* dom_c, c3_y imp_y) -{ - c3_c* bas_c = dns_c; - c3_w len_w = strlen(dom_c); - - // name 3, '.' 2, trailing null - // - if ( 250 <= len_w ) { - return -1; - } - - _ames_czar_str(dns_c, imp_y); - dns_c += 3; - *dns_c++ = '.'; - - memcpy(dns_c, dom_c, len_w); - dns_c += len_w; - *dns_c++ = '.'; - - memset(dns_c, 0, 256 - (dns_c - bas_c)); - - return 0; -} - -/* _ames_czar_lane: retrieve lane for galaxy if stored. -*/ -static c3_o -_ames_czar_lane(u3_ames* sam_u, c3_y imp_y, u3_lane* lan_u) -{ - c3_s por_s = _ames_czar_port(imp_y); - c3_w pip_w; - - if ( c3n == u3_Host.ops_u.net ) { - pip_w = 0x7f000001; - } - else { - pip_w = sam_u->zar_u.pip_w[imp_y]; - - if ( !pip_w ) { - if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: czar not resolved"); - } - return c3n; - } - else if ( _CZAR_GONE == pip_w ) { - // print only on first send failure - // - c3_w blk_w = imp_y >> 5; - c3_w bit_w = (c3_w)1 << (imp_y & 31); - - if ( !(sam_u->zar_u.log_w[blk_w] & bit_w) ) { - c3_c dns_c[256]; - u3_assert ( !_ames_etch_czar(dns_c, sam_u->zar_u.dom_c, imp_y) ); - u3l_log("ames: czar at %s: not found (b)", dns_c); - sam_u->zar_u.log_w[blk_w] |= bit_w; - } - - return c3n; - } - } - - lan_u->por_s = por_s; - lan_u->pip_w = pip_w; - return c3y; -} - -/* _fine_get_cache(): get packet list or status from cache. RETAIN - */ -static u3_weak -_fine_get_cache(u3_ames* sam_u, u3_noun pax, c3_w fra_w) -{ - u3_noun key = u3nc(u3k(pax), u3i_word(fra_w)); - u3_weak pro = u3h_git(sam_u->fin_s.sac_p, key); - u3z(key); - return pro; -} - -/* _fine_put_cache(): put packet list or status into cache. RETAIN. - */ -static void -_fine_put_cache(u3_ames* sam_u, u3_noun pax, c3_w lop_w, u3_noun lis) -{ - if ( (FINE_PEND == lis) || (FINE_DEAD == lis) ) { - u3_noun key = u3nc(u3k(pax), u3i_word(lop_w)); - u3h_put(sam_u->fin_s.sac_p, key, lis); - u3z(key); - } - else { - while ( u3_nul != lis ) { - u3_noun key = u3nc(u3k(pax), u3i_word(lop_w)); - u3h_put(sam_u->fin_s.sac_p, key, u3k(u3h(lis))); - u3z(key); - - lis = u3t(lis); - lop_w++; - } - } -} - -typedef struct _stun_send { - uv_udp_send_t req_u; // uv udp request handle - c3_y hun_y[0]; // buffer -} _stun_send; - -/* _stun_send_cb(): stun udp send callback. - */ -static void -_stun_send_cb(uv_udp_send_t *rep_u, c3_i sas_i) -{ - _stun_send* snd_u = (_stun_send*)rep_u; - - if ( !sas_i ) { - net_o = c3y; - } - else if ( c3y == net_o ) { - u3l_log("stun: send response fail: %s", uv_strerror(sas_i)); - net_o = c3n; - } - - c3_free(snd_u); -} - -/* _stun_on_request(): hear stun request, send response. - */ -static void -_stun_on_request(u3_ames* sam_u, - const c3_y* req_y, - const struct sockaddr* adr_u) -{ - _stun_send* snd_u = c3_malloc(sizeof(*snd_u) + 40); - - struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; - u3_lane lan_u = { - .por_s = ntohs(add_u->sin_port), - .pip_w = ntohl(add_u->sin_addr.s_addr) - }; - u3_stun_make_response(req_y, &lan_u, snd_u->hun_y); - - uv_buf_t buf_u = uv_buf_init((c3_c*)snd_u->hun_y, 40); - c3_i sas_i = uv_udp_send(&snd_u->req_u, &u3_Host.wax_u, - &buf_u, 1, adr_u, _stun_send_cb); - - if ( sas_i ) { - _stun_send_cb(&snd_u->req_u, sas_i); - } -} - -static void -_stun_start(u3_ames* sam_u, c3_w tim_w); - -/* _stun_on_response(): hear stun response from galaxy. - */ -static void -_stun_on_response(u3_ames* sam_u, c3_y* buf_y, c3_w buf_len) -{ - u3_lane lan_u; - - // Ignore STUN responses that dont' have the XOR-MAPPED-ADDRESS attribute - if ( c3n == u3_stun_find_xor_mapped_address(buf_y, buf_len, &lan_u) ) { - return; - } - - if ( (sam_u->sun_u.sef_u.por_s != lan_u.por_s) || - (sam_u->sun_u.sef_u.pip_w != lan_u.pip_w) ) - { - // lane changed - u3_noun wir = u3nc(c3__ames, u3_nul); - u3_noun cad = u3nq(c3__stun, c3__once, sam_u->sun_u.dad_y, - u3nc(c3n, u3_ames_encode_lane(lan_u))); - u3_auto_plan(&sam_u->car_u, - u3_ovum_init(0, c3__ames, wir, cad)); - } - else if ( c3n == sam_u->sun_u.wok_o ) { - // stop %ping app - u3_noun wir = u3nc(c3__ames, u3_nul); - u3_noun cad = u3nq(c3__stun, c3__stop, sam_u->sun_u.dad_y, - u3nc(c3n, u3_ames_encode_lane(lan_u))); - u3_auto_plan(&sam_u->car_u, - u3_ovum_init(0, c3__ames, wir, cad)); - sam_u->sun_u.wok_o = c3y; - } - - sam_u->sun_u.sef_u = lan_u; - - // XX should no-op early - // - switch ( sam_u->sun_u.sat_y ) { - case STUN_OFF: break; // ignore; stray response - case STUN_KEEPALIVE: break; // ignore; duplicate response - - case STUN_TRYING: { - _stun_start(sam_u, 25000); - } break; - - default: u3_assert(!"programmer error"); - } -} - -/* _stun_send_request(): send stun request to galaxy lane. - */ -static void -_stun_send_request(u3_ames* sam_u) -{ - u3_assert( STUN_OFF != sam_u->sun_u.sat_y ); - - _stun_send* snd_u = c3_malloc(sizeof(*snd_u) + 28); - - u3_stun_make_request(snd_u->hun_y, sam_u->sun_u.tid_y); - - 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(sam_u->sun_u.lan_u.pip_w); - add_u.sin_port = htons(sam_u->sun_u.lan_u.por_s); - - uv_buf_t buf_u = uv_buf_init((c3_c*)snd_u->hun_y, 28); - c3_i sas_i = uv_udp_send(&snd_u->req_u, &u3_Host.wax_u, &buf_u, 1, - (const struct sockaddr*)&add_u, _stun_send_cb); - - if ( sas_i ) { - _stun_send_cb(&snd_u->req_u, sas_i); - } -} - -/* _stun_reset(): stun failed. start again using max backoff - */ -static void -_stun_reset(uv_timer_t* tim_u) -{ - u3_ames* sam_u = (u3_ames*)(tim_u->data); - - _stun_start(sam_u, 39000); -} - -/* _stun_on_lost(): stun failed (timeout); capture and reset. - */ -static void -_stun_on_lost(u3_ames* sam_u) -{ - sam_u->sun_u.sat_y = STUN_OFF; - - // only inject event into arvo to %kick ping app on first failure - // - if ( c3y == sam_u->sun_u.wok_o ) { - u3_noun wir = u3nc(c3__ames, u3_nul); - u3_noun cad = u3nq(c3__stun, c3__fail, sam_u->sun_u.dad_y, - u3nc(c3n, u3_ames_encode_lane(sam_u->sun_u.sef_u))); - u3_auto_plan(&sam_u->car_u, - u3_ovum_init(0, c3__ames, wir, cad)); - sam_u->sun_u.wok_o = c3n; - } - - uv_timer_start(&sam_u->sun_u.tim_u, _stun_reset, 5*1000, 0); -} - -/* _stun_time_gap(): elapsed milliseconds. - */ -static c3_d -_stun_time_gap(struct timeval sar_tv) -{ - struct timeval tim_tv; - gettimeofday(&tim_tv, 0); - u3_noun now = u3_time_in_tv(&tim_tv); - u3_noun den = u3_time_in_tv(&sar_tv); - return u3_time_gap_ms(den, now); -} - -/* _stun_timer_cb(): advance stun state machine. - */ -static void -_stun_timer_cb(uv_timer_t* tim_u) -{ - u3_ames* sam_u = (u3_ames*)(tim_u->data); - c3_w rto_w = 500; - - switch ( sam_u->sun_u.sat_y ) { - case STUN_OFF: { - // ignore; stray timer (although this shouldn't happen) - u3l_log("stun: stray timer STUN_OFF"); - } break; - - case STUN_KEEPALIVE: { - u3_lane* lan_u = &(sam_u->sun_u.lan_u); - c3_y imp_y = sam_u->sun_u.dad_y; - - if ( c3n == _ames_czar_lane(sam_u, imp_y, lan_u) ) { - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); - } - else { - sam_u->sun_u.sat_y = STUN_TRYING; - gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, rto_w, 0); - _stun_send_request(sam_u); - } - } break; - - case STUN_TRYING: { - c3_d gap_d = _stun_time_gap(sam_u->sun_u.sar_u); - c3_d nex_d = (gap_d * 2) + rto_w - gap_d; - - if ( gap_d >= 39500 ) { - _stun_on_lost(sam_u); - } - else { - // wait ~s8 for the last STUN request - // - // https://datatracker.ietf.org/doc/html/rfc5389#section-7.2.1 - // - c3_w tim_w = (gap_d >= 31500) ? 8000 : c3_max(nex_d, 31500); - - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, tim_w, 0); - _stun_send_request(sam_u); - } - } break; - - default: u3_assert(!"programmer error"); - } -} - -/* _stun_start(): begin/restart STUN state machine. -*/ -static void -_stun_start(u3_ames* sam_u, c3_w tim_w) -{ - if ( ent_getentropy(sam_u->sun_u.tid_y, 12) ) { - u3l_log("stun: getentropy fail: %s", strerror(errno)); - u3_king_bail(); - } - - sam_u->sun_u.sat_y = STUN_KEEPALIVE; - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, tim_w, 0); -} - -/* _ames_is_czar(): [who] is galaxy. -*/ -static c3_o -_ames_is_czar(u3_noun who) -{ - u3_noun rac = u3do("clan:title", u3k(who)); - c3_o zar = ( c3y == (c3__czar == rac) ); - u3z(rac); - return zar; -} - -/* _ames_ef_saxo(): handle sponsorship chain notification -*/ -static void -_ames_ef_saxo(u3_ames* sam_u, u3_noun zad) -{ - u3_noun daz, dad; - - daz = u3qb_flop(zad); - if ( u3_nul == daz ) { - u3l_log("ames: empty sponsorship chain"); - u3z(zad); u3z(daz); - return; - } - - dad = u3h(daz); - u3_noun our = u3i_chubs(2, sam_u->pir_u->who_d); - - // if we are a galaxy, don't STUN - // - if ( c3y == _ames_is_czar(dad) && c3n == _ames_is_czar(our)) { - sam_u->sun_u.dad_y = (c3_y)dad; - _stun_start(sam_u, 0); - } - - u3z(zad); u3z(daz); u3z(our); -} - -/* _ames_send_lane(): resolve/decode lane. RETAIN -*/ -static c3_o -_ames_send_lane(u3_ames* sam_u, u3_noun lan, u3_lane* lan_u) -{ - u3_noun tag, val; - - if ( c3n == u3r_cell(lan, &tag, &val) ) { - u3l_log("ames: bad lane; not a cell"); - return c3n; - } - - switch ( tag ) { - case c3y: { // galaxy - if ( val >= 256 ) { - u3l_log("ames: bad galaxy lane: 0x%x", val); - return c3n; - } - return _ames_czar_lane(sam_u, (c3_y)val, lan_u); - } - - case c3n: { // ip:port - u3_lane nal_u = u3_ames_decode_lane(u3k(val)); - - // convert incoming localhost to outgoing localhost - // - // XX this looks like en/de-coding problems ... - // - nal_u.pip_w = ( nal_u.pip_w ) ? nal_u.pip_w : 0x7f000001; - - // if in local-only mode, don't send remote packets - // - if ( (c3n == u3_Host.ops_u.net) && (0x7f000001 != nal_u.pip_w) ) { - return c3n; - } - // if the lane is uninterpretable, silently drop the packet - // - else if ( !nal_u.por_s ) { - if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: inscrutable lane"); - } - return c3n; - } - - *lan_u = nal_u; - return c3y; - } - - default: { - u3l_log("ames: bad lane tag"); - return c3n; - } - } -} - -/* _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"); - u3z(lan); u3z(pac); - return; - } - - u3_lane lan_u; - - if ( c3y == _ames_send_lane(sam_u, lan, &lan_u) ) { - u3_pact* pac_u = c3_calloc(sizeof(*pac_u)); - pac_u->sam_u = sam_u; - pac_u->lan_u = lan_u; - pac_u->len_w = u3r_met(3, pac); - pac_u->hun_y = c3_malloc(pac_u->len_w); - - u3r_bytes(0, pac_u->len_w, pac_u->hun_y, pac); - - _ames_sift_head(&pac_u->hed_u, pac_u->hun_y); - pac_u->typ_y = _ames_pact_typ(&pac_u->hed_u); - - _ames_send(pac_u); - } - - u3z(lan); u3z(pac); -} - -/* _ames_cap_queue(): cap ovum queue at QUEUE_MAX, dropping oldest packets. -*/ -static void -_ames_cap_queue(u3_ames* sam_u) -{ - u3_ovum* egg_u = sam_u->car_u.ext_u; - c3_d old_d = sam_u->sat_u.dop_d; - - while ( egg_u && (QUEUE_MAX < 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)", sam_u->sat_u.dop_d); - } - } - - egg_u = nex_u; - } - - if ( !(u3C.wag_w & u3o_verbose) - && (old_d != sam_u->sat_u.dop_d) - && !(sam_u->sat_u.dop_d % 1000) ) - { - u3l_log("ames: packet dropped (%" PRIu64 " total)", sam_u->sat_u.dop_d); - } -} - -/* _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; - c3_w len_w = u3qb_lent(lud); - - if ( (1 == len_w) && c3__evil == u3h(u3h(lud)) ) { - sam_u->sat_u.vil_d++; - - if ( (u3C.wag_w & u3o_verbose) - || (0 == (sam_u->sat_u.vil_d % 100)) ) - { - u3l_log("ames: heard bad crypto (%" PRIu64 " total), " - "check azimuth state\r\n", - sam_u->sat_u.vil_d); - } - } - else { - sam_u->sat_u.fal_d++; - - if ( (u3C.wag_w & u3o_verbose) - || (0 == (sam_u->sat_u.fal_d % 100)) ) - { - if ( 2 == len_w ) { - u3_pier_punt_goof("hear", u3k(u3h(lud))); - u3_pier_punt_goof("crud", u3k(u3h(u3t(lud)))); - } - // !2 traces is unusual, just print the first if present - // - else if ( len_w ) { - u3_pier_punt_goof("hear", u3k(u3h(lud))); - } - - u3l_log("ames: packet failed (%" PRIu64 " total)\r\n", - sam_u->sat_u.fal_d); - } - } - - u3z(lud); - 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_send_many(): send pac_u on the (list lane) las; retains pac_u -*/ -static void -_ames_send_many(u3_pact* pac_u, u3_noun las, c3_o for_o) -{ - u3_ames* sam_u = pac_u->sam_u; - u3_noun tag, dat, lan, t = las; - u3_noun pac = _ames_pact_to_noun(pac_u); - - // if forwarding, track metrics - // - if ( c3y == for_o ) { - 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", sam_u->sat_u.fow_d); - } - - if ( u3C.wag_w & u3o_verbose ) { - u3_noun sen = u3dc("scot", 'p', u3i_chubs(2, pac_u->pre_u.sen_d)); - u3_noun rec = u3dc("scot", 'p', u3i_chubs(2, pac_u->pre_u.rec_d)); - c3_c* sen_c = u3r_string(sen); - c3_c* rec_c = u3r_string(rec); - c3_y* pip_y = (c3_y*)&pac_u->lan_u.pip_w; - - //NOTE ip byte order assumes little-endian - u3l_log("ames: forwarding for %s to %s from %d.%d.%d.%d:%d", - sen_c, rec_c, - pip_y[3], pip_y[2], pip_y[1], pip_y[0], - pac_u->lan_u.por_s); - - c3_free(sen_c); c3_free(rec_c); - u3z(sen); u3z(rec); - } - } - - 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"); - } - 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"); - } - } - } - - if ( c3y == sen_o ) { - _ames_ef_send(sam_u, u3k(lan), u3k(pac)); - } - } - } - u3z(pac); - u3z(las); -} - -/* _ames_lane_scry_cb(): learn lanes to send packet on -*/ -static void -_ames_lane_scry_cb(void* vod_p, u3_noun nun) -{ - u3_panc* pan_u = vod_p; - u3_pact* pac_u = pan_u->pac_u; - u3_ames* sam_u = pac_u->sam_u; - u3_weak las = u3r_at(7, nun); - - // 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"); - sam_u->fig_u.see_o = c3n; - } - _ames_put_packet(sam_u, - _ames_pact_to_noun(pac_u), - pac_u->lan_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->pre_u.rec_d), - u3k(las)); - - // if there are lanes, send the packet on them; otherwise drop it - // - if ( u3_nul != las ) { - _ames_send_many(pac_u, u3k(las), pan_u->for_o); - } - } - _ames_panc_free(pan_u); - u3z(nun); -} - -/* _ames_lane_scry_forward_cb(): learn lanes to forward packet on - */ -static void -_ames_lane_scry_forward_cb(void *vod_p, u3_noun nun) -{ - u3_panc *pan_u = vod_p; - u3_ames *sam_u = pan_u->pac_u->sam_u; - - sam_u->sat_u.foq_d--; - - _ames_lane_scry_cb(vod_p, nun); -} - -/* _ames_try_send(): try to send a packet to a ship and its sponsors -*/ -static void -_ames_try_send(u3_pact* pac_u, c3_o for_o) -{ - u3_weak lac; - u3_ames* sam_u = pac_u->sam_u; - - // if the recipient is a galaxy, their lane is always &+~gax - // - if ( (256 > pac_u->pre_u.rec_d[0]) - && (0 == pac_u->pre_u.rec_d[1]) ) - { - lac = u3nc(u3nc(c3y, (c3_y)pac_u->pre_u.rec_d[0]), u3_nul); - } - // otherwise, try to get the lane from cache - // - else { - u3_noun key = u3i_chubs(2, pac_u->pre_u.rec_d); - lac = _ames_lane_from_cache(sam_u->lax_p, key, sam_u->nal_o); - } - - // if we know there's no lane, drop the packet - // - if ( u3_nul == lac ) { - _ames_pact_free(pac_u); - return; - } - // if we don't know the lane, and the lane scry queue is full, - // just drop the packet - //TODO cap queue for lane lookups for scry responses, not just forwards - // - //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 ( (c3y == for_o) - && (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", - sam_u->sat_u.fod_d); - } - - _ames_pact_free(pac_u); - return; - } - - // if we already know the lane, just send - // - if ( u3_none != lac ) { - _ames_send_many(pac_u, lac, for_o); - _ames_pact_free(pac_u); - } - // store the packet to be sent later when the lane scry completes - // - else { - u3_panc* pan_u = c3_calloc(sizeof(*pan_u)); - pan_u->pac_u = pac_u; - pan_u->for_o = for_o; - - u3_noun pax = _lane_scry_path(u3i_chubs(2, pac_u->pre_u.rec_d)); - - // if forwarding, enqueue the packet and scry for the lane - // - u3_noun gang = u3nc(u3_nul, u3_nul); - if ( c3y == for_o ) { - if ( 0 != sam_u->pan_u ) { - pan_u->nex_u = sam_u->pan_u; - sam_u->pan_u->pre_u = pan_u; - } - sam_u->pan_u = pan_u; - sam_u->sat_u.foq_d++; - - u3_pier_peek_last(sam_u->pir_u, gang, c3__ax, - u3_nul, pax, pan_u, _ames_lane_scry_forward_cb); - } - // otherwise, just scry for the lane - // - else { - u3_pier_peek_last(sam_u->pir_u, gang, c3__ax, - u3_nul, pax, pan_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_prel* pre_u) -{ - if ( pre_u->sen_d[1] == 0 && - ( pre_u->sen_d[0] == 0x743a17a6 - || pre_u->sen_d[0] == 0xea99acb6 - || pre_u->sen_d[0] == 0x10100 - ) ) { - return c3n; - } - else { - return c3y; - } -} -#endif - -/* _fine_lop(): find beginning of page containing fra_w -*/ -static inline c3_w -_fine_lop(c3_w fra_w) -{ - return 1 + (((fra_w - 1) / FINE_PAGE) * FINE_PAGE); -} - -/* _fine_scry_path(): parse path from wail or purr. -*/ -static u3_weak -_fine_scry_path(u3_pact* pac_u) -{ - u3_peep* pep_u = ( PACT_WAIL == pac_u->typ_y ) - ? &pac_u->wal_u.pep_u - : &pac_u->pur_u.pep_u; - u3_noun ful = u3dc("rush", u3i_string(pep_u->pat_c), u3v_wish(PATH_PARSER)); - - if ( u3_nul == ful ) { - return u3_none; - } - else { - u3_noun pro = u3k(u3t(ful)); - u3z(ful); - return pro; - } -} - -/* _fine_hunk_scry_cb(): receive packets for datum out of fine - */ -static void -_fine_hunk_scry_cb(void* vod_p, u3_noun nun) -{ - u3_pact* pac_u = vod_p; - u3_ames* sam_u = pac_u->sam_u; - u3_peep* pep_u = &pac_u->pur_u.pep_u; - u3_weak fra = u3_none; - - u3_assert( PACT_PURR == pac_u->typ_y ); - - { - // XX virtualize - u3_noun pax = u3dc("rash", u3i_string(pep_u->pat_c), u3v_wish(PATH_PARSER)); - c3_w lop_w = _fine_lop(pep_u->fra_w); - u3_weak pas = u3r_at(7, nun); - - // if not [~ ~ fragments], mark as dead - // - if( u3_none == pas ) { - _fine_put_cache(sam_u, pax, lop_w, FINE_DEAD); - _ames_pact_free(pac_u); - - u3z(nun); - return; - } - - _fine_put_cache(sam_u, pax, lop_w, pas); - - // find requested fragment - // - while ( u3_nul != pas ) { - if ( pep_u->fra_w == lop_w ) { - fra = u3k(u3h(pas)); - break; - } - lop_w++; - pas = u3t(pas); - } - - u3z(pax); - } - - if ( fra == u3_none ) { - u3l_log("fine: fragment number out of range"); - _ames_pact_free(pac_u); - } - else if ( c3y == _fine_sift_meow(&pac_u->pur_u.mew_u, fra) ) { - if ( u3C.wag_w & u3o_verbose ) { - u3l_log("fine: send %u %s", pac_u->pur_u.pep_u.fra_w, - pac_u->pur_u.pep_u.pat_c); - } - - _fine_etch_response(pac_u); - _ames_try_send(pac_u, c3n); - } - else { - u3l_log("fine: bad meow"); - _ames_pact_free(pac_u); - } - - u3z(nun); -} - -/* _fine_hear_request(): hear wail (fine request packet packet). -*/ -static void -_fine_hear_request(u3_pact* req_u, c3_w cur_w) -{ - u3_ames* sam_u = req_u->sam_u; - u3_pact* res_u; - u3_noun key; - - if ( c3n == _fine_sift_wail(req_u, cur_w) ) { - sam_u->sat_u.wal_d++; - if ( 0 == (sam_u->sat_u.wal_d % 100) ) { - u3l_log("fine: %" PRIu64 " dropped wails", - sam_u->sat_u.wal_d); - } - _ames_pact_free(req_u); - return; - } - // make scry cache key - // - else { - u3_weak yek = _fine_scry_path(req_u); - - if ( u3_none == yek ) { - sam_u->sat_u.wap_d++; - if ( 0 == (sam_u->sat_u.wap_d % 100) ) { - u3l_log("fine: %" PRIu64 " dropped wails (path)", - sam_u->sat_u.wap_d); - } - _ames_pact_free(req_u); - return; - } - - key = yek; - } - - // fill in the parts of res_u that we know from req_u - { - res_u = c3_calloc(sizeof(*res_u)); - res_u->sam_u = req_u->sam_u; - res_u->typ_y = PACT_PURR; - res_u->lan_u = req_u->lan_u; - - // copy header, swapping sender and receiver - // - res_u->hed_u = (u3_head) { - .req_o = c3n, - .sim_o = c3n, - .ver_y = req_u->hed_u.ver_y, - .sac_y = req_u->hed_u.rac_y, - .rac_y = req_u->hed_u.sac_y, - .mug_l = 0, // filled in later - .rel_o = c3n - }; - - // copy prelude, swapping sender and receiver - // - res_u->pre_u = (u3_prel) { - .sic_y = req_u->pre_u.ric_y, - .ric_y = req_u->pre_u.sic_y, - .sen_d = { req_u->pre_u.rec_d[0], req_u->pre_u.rec_d[1] }, - .rec_d = { req_u->pre_u.sen_d[0], req_u->pre_u.sen_d[1] }, - .rog_d = 0 - }; - - // copy unsigned request payload into response body - // - res_u->pur_u = (u3_purr) { - .pep_u = req_u->wal_u.pep_u, - .mew_u = {0} // filled in later - }; - - // copy path string from request into response body - { - c3_s len_s = req_u->wal_u.pep_u.len_s; - res_u->pur_u.pep_u.pat_c = c3_calloc(len_s + 1); - memcpy(res_u->pur_u.pep_u.pat_c, req_u->wal_u.pep_u.pat_c, len_s); - } - - // free incoming request - // - _ames_pact_free(req_u); - } - - // look up request in scry cache - // - c3_w fra_w = res_u->pur_u.pep_u.fra_w; - c3_w lop_w = _fine_lop(fra_w); - u3_weak pec = _fine_get_cache(sam_u, key, lop_w); - - // already pending; drop - // - if ( FINE_PEND == pec ) { - if ( u3C.wag_w & u3o_verbose ) { - u3l_log("fine: pend %u %s", res_u->pur_u.pep_u.fra_w, - res_u->pur_u.pep_u.pat_c); - } - _ames_pact_free(res_u); - } - // cache miss or a previous scry blocked; try again - // - else { - u3_weak cac = _fine_get_cache(sam_u, key, fra_w); - - if ( (u3_none == cac) || (FINE_DEAD == cac) ) { - if ( u3C.wag_w & u3o_verbose ) { - u3l_log("fine: miss %u %s", res_u->pur_u.pep_u.fra_w, - res_u->pur_u.pep_u.pat_c); - } - - u3_noun pax = - u3nc(c3__fine, - u3nq(c3__hunk, - u3dc("scot", c3__ud, u3i_word(lop_w)), - u3dc("scot", c3__ud, FINE_PAGE), - u3k(key))); - - // mark as pending in the scry cache - // - _fine_put_cache(res_u->sam_u, key, lop_w, FINE_PEND); - - // scry into arvo for a page of packets - // - u3_pier_peek_last(res_u->sam_u->car_u.pir_u, u3_nul, c3__ax, u3_nul, - pax, res_u, _fine_hunk_scry_cb); - } - // cache hit, fill in response meow and send - // - else if ( c3y == _fine_sift_meow(&res_u->pur_u.mew_u, u3k(cac)) ) { - if ( u3C.wag_w & u3o_verbose ) { - u3l_log("fine: hit %u %s", res_u->pur_u.pep_u.fra_w, - res_u->pur_u.pep_u.pat_c); - } - _fine_etch_response(res_u); - _ames_try_send(res_u, c3n); - } - else { - u3l_log("fine: _fine_hear_request meow bad"); - _ames_pact_free(res_u); - } - } - - u3z(key); -} - -/* _fine_hear_response(): hear purr (fine response packet). -*/ -static void -_fine_hear_response(u3_pact* pac_u, c3_w cur_w) -{ - u3_noun wir = u3nc(c3__fine, u3_nul); - u3_noun cad = u3nt(c3__hear, - u3nc(c3n, u3_ames_encode_lane(pac_u->lan_u)), - u3i_bytes(pac_u->len_w, pac_u->hun_y)); - - u3_ovum* ovo_u = u3_ovum_init(0, c3__ames, wir, cad); - u3_auto_plan(&pac_u->sam_u->car_u, ovo_u); - - _ames_cap_queue(pac_u->sam_u); - _ames_pact_free(pac_u); -} - -/* _ames_hear_ames(): hear ames packet. -*/ -static void -_ames_hear_ames(u3_pact* pac_u, c3_w cur_w) -{ -#ifdef AMES_SKIP - if ( c3_y == _ames_skip(&pac_u->pre_u) ) { - _ames_pact_free(pac_u); - return; - } -#endif - - { - u3_noun msg = u3i_bytes(pac_u->len_w, pac_u->hun_y); - _ames_put_packet(pac_u->sam_u, msg, pac_u->lan_u); - _ames_pact_free(pac_u); - } -} - -/* _ames_try_forward(): forward packet, updating lane if needed. -*/ -static void -_ames_try_forward(u3_pact* pac_u) -{ - // insert origin lane if needed - // - if ( c3n == pac_u->hed_u.rel_o - && !( ( 256 > pac_u->pre_u.sen_d[0] ) - && ( 0 == pac_u->pre_u.sen_d[1] ) ) ) - { - c3_y* old_y; - c3_w old_w, cur_w; - - pac_u->hed_u.rel_o = c3y; - pac_u->pre_u.rog_d = u3_ames_lane_to_chub(pac_u->lan_u); - - old_w = pac_u->len_w; - old_y = pac_u->hun_y; - - pac_u->len_w += 6; - pac_u->hun_y = c3_calloc(pac_u->len_w); - - cur_w = 0; - - _ames_etch_head(&pac_u->hed_u, pac_u->hun_y); - cur_w += HEAD_SIZE; - - _ames_etch_origin(pac_u->pre_u.rog_d, pac_u->hun_y + cur_w); - cur_w += 6; - - memcpy(pac_u->hun_y + cur_w, - old_y + HEAD_SIZE, - old_w - HEAD_SIZE); - - c3_free(old_y); - } - - _ames_try_send(pac_u, c3y); -} - -/* _ames_hear(): parse a (potential) packet, dispatch appropriately. -** -** packet filtering needs to revised for two protocol-change scenarios -** -** - packets using old protocol versions from our sponsees -** these must be let through, and this is a transitive condition; -** they must also be forwarded where appropriate -** they can be validated, as we know their semantics -** -** - packets using newer protocol versions -** these should probably be let through, or at least -** trigger printfs suggesting upgrade. -** they cannot be filtered, as we do not know their semantics -*/ -void -_ames_hear(u3_ames* sam_u, - const struct sockaddr* adr_u, - c3_w len_w, - c3_y* hun_y) -{ - u3_pact* pac_u; - c3_w pre_w; - c3_w cur_w = 0; // cursor: how many bytes we've read from hun_y - - - // XX reorg, check if a STUN req/resp can look like an ames packet - // check the mug hash of the body of the packet, if not check if STUN - // otherwise , invalid packet, log failure - // check ames first, assume that STUN could maybe (not likely) overlap with ames - // for next protocol version, have an urbit cookie - // - if ( c3y == u3_stun_is_request(hun_y, len_w) ) { - _stun_on_request(sam_u, hun_y, adr_u); - c3_free(hun_y); - } - else if ( c3y == u3_stun_is_our_response(hun_y, - sam_u->sun_u.tid_y, len_w) ) - { - _stun_on_response(sam_u, hun_y, len_w); - c3_free(hun_y); - } - else { - struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; - u3_lane lan_u = { - .por_s = ntohs(add_u->sin_port), - .pip_w = ntohl(add_u->sin_addr.s_addr) - }; - - // make sure packet is big enough to have a header - // - if ( HEAD_SIZE > len_w ) { - sam_u->sat_u.hed_d++; - if ( 0 == (sam_u->sat_u.hed_d % 100000) ) { - u3l_log("ames: %" PRIu64 " dropped, failed to read header", - sam_u->sat_u.hed_d); - } - - c3_free(hun_y); - return; - } - - pac_u = c3_calloc(sizeof(*pac_u)); - pac_u->sam_u = sam_u; - pac_u->len_w = len_w; - pac_u->hun_y = hun_y; - pac_u->lan_u = lan_u; - cur_w = 0; - - // parse the header - // - _ames_sift_head(&pac_u->hed_u, pac_u->hun_y); - cur_w += HEAD_SIZE; - - pac_u->typ_y = _ames_pact_typ(&pac_u->hed_u); - - // 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 != pac_u->hed_u.ver_y) ) - { - sam_u->sat_u.vet_d++; - if ( 0 == (sam_u->sat_u.vet_d % 100000) ) { - u3l_log("ames: %" PRIu64 " dropped for version mismatch", - sam_u->sat_u.vet_d); - } - _ames_pact_free(pac_u); - return; - } - - // check contents match mug in header - // - if ( c3n == _ames_check_mug(pac_u) ) { - // _log_head(&pac_u->hed_u); - sam_u->sat_u.mut_d++; - if ( 0 == (sam_u->sat_u.mut_d % 100000) ) { - u3l_log("ames: %" PRIu64 " dropped for invalid mug", - sam_u->sat_u.mut_d); - } - _ames_pact_free(pac_u); - return; - } - - // check that packet is big enough for prelude - // - pre_w = _ames_prel_size(&pac_u->hed_u); - if ( len_w < cur_w + pre_w ) { - sam_u->sat_u.pre_d++; - if ( 0 == (sam_u->sat_u.pre_d % 100000) ) { - u3l_log("ames: %" PRIu64 " dropped, failed to read prelude", - sam_u->sat_u.pre_d); - } - _ames_pact_free(pac_u); - return; - } - - // parse prelude - // - _ames_sift_prel(&pac_u->hed_u, &pac_u->pre_u, pac_u->hun_y + cur_w); - cur_w += pre_w; - - // if we can scry for lanes, - // and we are not the recipient, - // we might want to forward statelessly - // - if ( (c3y == sam_u->fig_u.see_o) - && ( (pac_u->pre_u.rec_d[0] != sam_u->pir_u->who_d[0]) - || (pac_u->pre_u.rec_d[1] != sam_u->pir_u->who_d[1]) ) ) - { - if ( c3y == sam_u->sat_u.for_o ) { - _ames_try_forward(pac_u); - } - } - else { - // enter protocol-specific packet handling - // - switch ( pac_u->typ_y ) { - case PACT_WAIL: { - _fine_hear_request(pac_u, cur_w); - } break; - - case PACT_PURR: { - _fine_hear_response(pac_u, cur_w); - } break; - - case PACT_AMES: { - _ames_hear_ames(pac_u, cur_w); - } break; - - default: { - u3l_log("ames_hear: bad packet type %d", pac_u->typ_y); - u3_king_bail(); - exit(1); - } - } - } - } -} - -/* _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) -{ - u3_ames* sam_u = u3_Host.sam_u; // wax_u->data; - - if ( 0 > nrd_i ) { - if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: recv: fail: %s", 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"); - } - c3_free(buf_u->base); - } - else { - // NB: [nrd_i] will never exceed max length from _ames_alloc() - // - _ames_hear(sam_u, adr_u, (c3_w)nrd_i, (c3_y*)buf_u->base); - } -} - -static void natpmp_init(uv_timer_t* handle); - -static void -natpmp_cb(uv_poll_t* handle, - c3_i status, - c3_i events) -{ - - if (status != 0) { - return; - } - - u3_ames* sam_u = handle->data; - - natpmpresp_t response; - c3_i err_i = readnatpmpresponseorretry(&sam_u->nat_u.req_u, &response); - if ( NATPMP_TRYAGAIN == err_i ) { - return; - } - - uv_poll_stop(handle); - - if ( 0 != err_i ) { - u3l_log("ames: natpmp error %i", err_i); - uv_poll_stop(&sam_u->nat_u.pol_u); - closenatpmp(&sam_u->nat_u.req_u); - return; - } - - u3l_log("ames: mapped public port %hu to localport %hu lifetime %u", - response.pnu.newportmapping.mappedpublicport, - response.pnu.newportmapping.privateport, - response.pnu.newportmapping.lifetime); - - closenatpmp(&sam_u->nat_u.req_u); - sam_u->nat_u.tim_u.data = sam_u; - uv_timer_start(&sam_u->nat_u.tim_u, natpmp_init, 7200000, 0); -} - -static void -natpmp_init(uv_timer_t *handle) -{ - u3_ames* sam_u = handle->data; - c3_s por_s = sam_u->pir_u->por_s; - - c3_i err_i = initnatpmp(&sam_u->nat_u.req_u, 0, 0); - - if (err_i != 0) { - return; - } - - err_i = uv_poll_init(u3L, &sam_u->nat_u.pol_u, sam_u->nat_u.req_u.s); - - if (err_i != 0) { - return; - } - - sendnewportmappingrequest(&sam_u->nat_u.req_u, NATPMP_PROTOCOL_UDP, por_s, por_s, 7200); - - sam_u->nat_u.pol_u.data = sam_u; - uv_poll_start(&sam_u->nat_u.pol_u, UV_READABLE, natpmp_cb); -} - -static void -_mdns_dear_bail(u3_ovum* egg_u, u3_noun lud) -{ - u3z(lud); - u3_ovum_free(egg_u); -} - -/* _ames_put_dear(): send lane to arvo after hearing mdns response -*/ -static void -_ames_put_dear(c3_c* ship, bool fake, c3_w saddr, c3_s port, void* context) -{ - u3_ames* sam_u = (u3_ames*)context; - - // one is loobean one is boolean - if (fake == sam_u->pir_u->fak_o) { - return; - } - - u3_lane lan; - lan.pip_w = ntohl(saddr); - lan.por_s = ntohs(port); - - u3_noun whu = u3dc("slaw", c3__p, u3i_string(ship)); - - if (u3_nul == whu) { - u3l_log("ames: strange ship from mdns: %s", ship); - return; - } - - u3_noun our = u3i_chubs(2, sam_u->pir_u->who_d); - if (our == u3t(whu)) { - u3z(whu); - u3z(our); - return; - } - - u3z(our); - - u3_noun wir = u3nc(c3__ames, u3_nul); - u3_noun cad = u3nt(c3__dear, u3k(u3t(whu)), u3nc(c3n, u3_ames_encode_lane(lan))); - - u3_auto_peer( - u3_auto_plan(&sam_u->car_u, - u3_ovum_init(0, c3__a, wir, cad)), - 0, 0, _mdns_dear_bail); - u3z(whu); -} - -/* _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); - c3_o zar_o = _ames_is_czar(who); - c3_i ret_i; - - - if ( c3y == zar_o ) { - 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", zar_s, por_s); - u3l_log("ames: czar: WARNING: %d required for discoverability", 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); - u3l_log("ames: skipping port: %u", por_s); - - /*if ( (ret_i = uv_udp_bind(&sam_u->wax_u, - (const struct sockaddr*)&add_u, 0)) != 0 ) - { - u3l_log("ames: port: %u", por_s); - u3l_log("ames: bind: %s", uv_strerror(ret_i)); - - if ( (c3y == zar_o) && - (UV_EADDRINUSE == ret_i) ) - { - u3l_log(" ...perhaps you've got two copies of vere running?"); - } - - // XX revise - // - u3_pier_bail(u3_king_stub()); - }*/ - - /* - uv_udp_getsockname(&sam_u->wax_u, (struct sockaddr *)&add_u, &add_i); - u3_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", sam_u->pir_u->por_s); - } - else { - u3l_log("ames: live on %d (localhost only)", sam_u->pir_u->por_s); - } - - { - u3_noun our = u3dc("scot", 'p', u3k(who)); - char* our_s = u3r_string(our); - u3z(our); - -#ifndef U3_OS_windows - mdns_init(por_s, !sam_u->pir_u->fak_o, our_s, _ames_put_dear, (void *)sam_u); - - if ( c3n == sam_u->pir_u->fak_o ) { - uv_timer_start(&sam_u->nat_u.tim_u, natpmp_init, 0, 0); - } -#endif - c3_free(our_s); - } - - /* - uv_udp_recv_start(&sam_u->wax_u, _ames_alloc, _ames_recv_cb); - */ - - sam_u->car_u.liv_o = c3y; - u3z(who); -} - -typedef struct _czar_resv { - uv_getaddrinfo_t adr_u; - u3_ames* sam_u; - c3_y imp_y; -} _czar_resv; - -/* _ames_czar_gone(): galaxy address resolution failed. -*/ -static void -_ames_czar_gone(u3_ames* sam_u, c3_y imp_y) -{ - c3_w old_w = sam_u->zar_u.pip_w[imp_y]; - - if ( !old_w ) { - sam_u->zar_u.pip_w[imp_y] = _CZAR_GONE; - } -} - -/* _ames_czar_here(): galaxy address resolution succeeded. -*/ -static void -_ames_czar_here(u3_ames* sam_u, c3_y imp_y, c3_w pip_w) -{ - c3_w old_w = sam_u->zar_u.pip_w[imp_y]; - - if ( pip_w != old_w ) { - c3_c dns_c[256]; - u3_assert ( !_ames_etch_czar(dns_c, sam_u->zar_u.dom_c, imp_y) ); - u3l_log("ames: czar %s ip .%d.%d.%d.%d", dns_c, - (pip_w >> 24) & 0xff, - (pip_w >> 16) & 0xff, - (pip_w >> 8) & 0xff, - (pip_w >> 0) & 0xff); - } - - sam_u->zar_u.pip_w[imp_y] = pip_w; - - { - c3_w blk_w = imp_y >> 5; - c3_w bit_w = 1 << (imp_y & 31); - - sam_u->zar_u.log_w[blk_w] &= ~bit_w; - } -} - -/* _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) -{ - struct addrinfo* rai_u = aif_u; - _czar_resv* res_u = (_czar_resv*)adr_u; - u3_ames* sam_u = res_u->sam_u; - c3_y imp_y = res_u->imp_y; - - while ( rai_u && (AF_INET != rai_u->ai_family) ) { - rai_u = rai_u->ai_next; - } - - if ( rai_u && rai_u->ai_addr ) { - struct sockaddr_in* add_u = (void*)rai_u->ai_addr; - c3_w pip_w = ntohl(add_u->sin_addr.s_addr); - _ames_czar_here(sam_u, imp_y, pip_w); - } - else { - if ( !sas_i ) { - // XX unpossible - u3l_log("ames: czar: strange failure, no error"); - } - else if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: czar fail: %s", uv_strerror(sas_i)); - } - - _ames_czar_gone(sam_u, imp_y); - } - - sam_u->zar_u.pen_s--; - - uv_freeaddrinfo(aif_u); - c3_free(res_u); -} - -/* _ames_czar(): single galaxy address resolution. -*/ -static void -_ames_czar(u3_ames* sam_u, const c3_c* dom_c, c3_y imp_y) -{ - struct addrinfo hin_u = { .ai_family = AF_INET }; - uv_getaddrinfo_t* adr_u; - _czar_resv* res_u; - c3_c dns_c[256]; - c3_i sas_i; - - u3_assert ( !_ames_etch_czar(dns_c, dom_c, imp_y) ); - - res_u = c3_malloc(sizeof(*res_u)); - res_u->sam_u = sam_u; - res_u->imp_y = imp_y; - - adr_u = &(res_u->adr_u); - sas_i = uv_getaddrinfo(u3L, adr_u, _ames_czar_cb, dns_c, 0, &hin_u); - - if ( sas_i ) { - _ames_czar_cb(adr_u, sas_i, NULL); - } -} - -/* _ames_czar_all(): galaxy address resolution. -*/ -static void -_ames_czar_all(uv_timer_t* tim_u) -{ - u3_ames* sam_u = tim_u->data; - - // requests still pending - if ( sam_u->zar_u.pen_s ) { - uv_timer_start(&sam_u->zar_u.tim_u, _ames_czar_all, 30*1000, 0); - return; - } - - sam_u->zar_u.pen_s = 256; - - for ( c3_w i_w = 0; i_w < 256; i_w++ ) { - _ames_czar(sam_u, sam_u->zar_u.dom_c, (c3_y)i_w); - } - - uv_timer_start(&sam_u->zar_u.tim_u, _ames_czar_all, 300*1000, 0); -} - -/* _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 ) { - c3_c dom_c[sizeof(sam_u->zar_u.dom_c)]; - u3_noun hot = u3h(tuf); - c3_w len_w = u3_mcut_host(0, 0, u3k(hot)); - - if ( len_w >= sizeof(dom_c) ) { // >250 - // 3 char for the galaxy (e.g. zod) and two dots - u3l_log("ames: galaxy domain too big (len=%u)", len_w); - u3m_p("hot", hot); - u3_pier_bail(u3_king_stub()); - } - - u3_mcut_host(dom_c, 0, u3k(hot)); - memset(dom_c + len_w, 0, sizeof(dom_c) - len_w); - - if ( 0 != memcmp(sam_u->zar_u.dom_c, dom_c, sizeof(dom_c)) ) { - memcpy(sam_u->zar_u.dom_c, dom_c, sizeof(dom_c)); - memset(sam_u->zar_u.pip_w, 0, sizeof(sam_u->zar_u.pip_w)); - sam_u->zar_u.dom_o = c3y; - _ames_czar_all(&(sam_u->zar_u.tim_u)); - } - - // XX save all for fallback, not just first - // - if ( u3_nul != u3t(tuf) ) { - u3l_log("ames: turf: ignoring additional domains"); - u3m_p("second", u3h(u3t(tuf))); - - if ( u3_nul != u3t(u3t(tuf)) ) { - u3m_p("third", u3h(u3t(u3t(tuf)))); - } - } - - u3z(tuf); - } - else if ( (c3n == sam_u->pir_u->fak_o) && (c3n == sam_u->zar_u.dom_o) ) { - u3l_log("ames: turf: no domains"); - } - - // XX is this ever necessary? - // - if ( c3n == sam_u->car_u.liv_o ) { - _ames_io_start(sam_u); - } -} - - -/* _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; - sam_u->fin_s.ver_y = 0; - } - else if ( (c3n == u3a_is_cat(ver)) - || (7 < ver) ) { - u3m_p("ames: strange protocol", nun); - sam_u->ver_y = 0; - sam_u->fin_s.ver_y = 0; - } - else { - sam_u->ver_y = ver; - sam_u->fin_s.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); -} - -/* _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)); - // } - - // 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_noun gang = u3nc(u3_nul, u3_nul); - // XX drop this; done at another level - // - u3_pier_peek_last(car_u->pir_u, gang, 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. -*/ -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; - - case c3__saxo: { - _ames_ef_saxo(sam_u, u3k(dat)); - ret_o = c3y; - } - - case c3__nail: { - u3_noun who = u3k(u3h(dat)); - u3_noun las = u3k(u3t(dat)); - _ames_lane_into_cache(sam_u->lax_p, who, las); - sam_u->nal_o = c3y; - 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"); - 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* pan_u = sam_u->pan_u; - while (0 != pan_u) { - u3_panc* nex_u = pan_u->nex_u; - _ames_panc_free(pan_u); - pan_u = nex_u; - } - - u3h_free(sam_u->lax_p); - - u3s_cue_xeno_done(sam_u->sil_u); - ur_cue_test_done(sam_u->tes_u); - - c3_free(sam_u); -} - -/* _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); - uv_close((uv_handle_t*)&sam_u->sun_u.tim_u, 0); - uv_close((uv_handle_t*)&sam_u->nat_u.tim_u, 0); - - uv_handle_type handle = uv_handle_get_type((uv_handle_t *)&sam_u->nat_u.pol_u); - if ( UV_UNKNOWN_HANDLE != handle) { - uv_close((uv_handle_t*)&sam_u->nat_u.pol_u, 0); - } -} - -/* _ames_io_info(): produce status info. -*/ -static u3_noun -_ames_io_info(u3_auto* car_u) -{ - u3_ames* sam_u = (u3_ames*)car_u; - c3_w sac_w, lax_w; - - sac_w = u3h_count(sam_u->fin_s.sac_p) * 4; - u3h_discount(sam_u->fin_s.sac_p); - - lax_w = u3h_count(sam_u->lax_p) * 4; - u3h_discount(sam_u->lax_p); - - return u3i_list( - u3_pier_mase("filtering", sam_u->fig_u.fit_o), - u3_pier_mase("can-send", net_o), - u3_pier_mase("can-scry", sam_u->fig_u.see_o), - u3_pier_mase("stun-working", sam_u->sun_u.wok_o), - u3_pier_mase("scry-cache", u3i_word(u3h_wyt(sam_u->fin_s.sac_p))), - u3_pier_mase("scry-cache-size", u3i_word(sac_w)), - u3_pier_mase("lane-cache", u3i_word(u3h_wyt(sam_u->lax_p))), - u3_pier_mase("lane-cache-size", u3i_word(lax_w)), - u3_pier_mase("dropped", u3i_chub(sam_u->sat_u.dop_d)), - u3_pier_mase("forwards-dropped", u3i_chub(sam_u->sat_u.fod_d)), - u3_pier_mase("forwards-pending", u3i_chub(sam_u->sat_u.foq_d)), - u3_pier_mase("forwarded", u3i_chub(sam_u->sat_u.fow_d)), - u3_pier_mase("filtered-hed", u3i_chub(sam_u->sat_u.hed_d)), - u3_pier_mase("filtered-ver", u3i_chub(sam_u->sat_u.vet_d)), - u3_pier_mase("filtered-mug", u3i_chub(sam_u->sat_u.mut_d)), - u3_pier_mase("filtered-pre", u3i_chub(sam_u->sat_u.pre_d)), - u3_pier_mase("filtered-wal", u3i_chub(sam_u->sat_u.wal_d)), - u3_pier_mase("filtered-wap", u3i_chub(sam_u->sat_u.wap_d)), - u3_pier_mase("crashed", u3i_chub(sam_u->sat_u.fal_d)), - u3_pier_mase("evil", u3i_chub(sam_u->sat_u.vil_d)), - u3_pier_mase("lane-scry-fails", u3i_chub(sam_u->sat_u.saw_d)), - u3_pier_mase("cached-lanes", u3i_word(u3h_wyt(sam_u->lax_p))), - u3_none); -} - -/* _ames_io_slog(): print status info. -*/ -static void -_ames_io_slog(u3_auto* car_u) -{ - u3_ames* sam_u = (u3_ames*)car_u; - c3_w sac_w, lax_w; - - sac_w = u3h_count(sam_u->fin_s.sac_p) * 4; - u3h_discount(sam_u->fin_s.sac_p); - - lax_w = u3h_count(sam_u->lax_p) * 4; - u3h_discount(sam_u->lax_p); - - -# define FLAG(a) ( (c3y == a) ? "&" : "|" ) - - // TODO rewrite in terms of info_f - // - u3l_log(" config:"); - u3l_log(" filtering: %s", FLAG(sam_u->fig_u.fit_o)); - u3l_log(" can send: %s", FLAG(net_o)); - u3l_log(" can scry: %s", FLAG(sam_u->fig_u.see_o)); - u3l_log(" stun:"); - u3l_log(" working: %s", FLAG(sam_u->sun_u.wok_o)); - u3l_log(" caches:"); - u3l_log(" cached lanes: %u, %u B", u3h_wyt(sam_u->lax_p), lax_w); - u3l_log(" cached meows: %u, %u B", u3h_wyt(sam_u->fin_s.sac_p), sac_w); - u3l_log(" counters:"); - u3l_log(" dropped: %" PRIu64, sam_u->sat_u.dop_d); - u3l_log(" forwards dropped: %" PRIu64, sam_u->sat_u.fod_d); - u3l_log(" forwards pending: %" PRIu64, sam_u->sat_u.foq_d); - u3l_log(" forwarded: %" PRIu64, sam_u->sat_u.fow_d); - u3l_log(" filtered (hed): %" PRIu64, sam_u->sat_u.hed_d); - u3l_log(" filtered (ver): %" PRIu64, sam_u->sat_u.vet_d); - u3l_log(" filtered (mug): %" PRIu64, sam_u->sat_u.mut_d); - u3l_log(" filtered (pre): %" PRIu64, sam_u->sat_u.pre_d); - u3l_log(" filtered (wal): %" PRIu64, sam_u->sat_u.wal_d); - u3l_log(" filtered (wap): %" PRIu64, sam_u->sat_u.wap_d); - u3l_log(" crashed: %" PRIu64, sam_u->sat_u.fal_d); - u3l_log(" evil: %" PRIu64, sam_u->sat_u.vil_d); - u3l_log(" lane scry fails: %" PRIu64, sam_u->sat_u.saw_d); - u3l_log(" cached lanes: %u", u3h_wyt(sam_u->lax_p)); -} - -static u3m_quac** -_ames_io_mark(u3_auto* car_u, c3_w *out_w) -{ - u3m_quac** all_u = c3_malloc(4 * sizeof(*all_u)); - u3_ames *sam_u = (u3_ames*)car_u; - - all_u[0] = c3_malloc(sizeof(**all_u)); - all_u[0]->nam_c = strdup("scry cache"); - all_u[0]->siz_w = 4 * u3h_mark(sam_u->fin_s.sac_p); - all_u[0]->qua_u = 0; - - all_u[1] = c3_malloc(sizeof(**all_u)); - all_u[1]->nam_c = strdup("lane cache"); - all_u[1]->siz_w = 4 * u3h_mark(sam_u->lax_p); - all_u[1]->qua_u = 0; - - all_u[2] = 0; - - *out_w = all_u[0]->siz_w + all_u[1]->siz_w; - - return all_u; -} - -/* 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->nal_o = c3n; - sam_u->fig_u.see_o = c3y; - sam_u->fig_u.fit_o = c3n; - sam_u->sun_u.wok_o = c3n; - sam_u->zar_u.dom_o = c3n; - - uv_timer_init(u3L, &sam_u->zar_u.tim_u); - sam_u->zar_u.tim_u.data = sam_u; - - uv_timer_init(u3L, &sam_u->sun_u.tim_u); - sam_u->sun_u.tim_u.data = sam_u; - - // initialize libnatpmp - sam_u->nat_u.tim_u.data = sam_u; - uv_timer_init(u3L, &sam_u->nat_u.tim_u); - - // enable forwarding on galaxies only - u3_noun who = u3i_chubs(2, sam_u->pir_u->who_d); - u3_noun rac = u3do("clan:title", who); - sam_u->sat_u.for_o = ( c3__czar == rac ) ? c3y : c3n; - - // hashtable for scry cache - // - // 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); - - u3_assert( !uv_udp_init(u3L, &sam_u->wax_u) ); - u3_assert( !uv_udp_init_ex(u3L, &u3_Host.wax_u, UV_UDP_RECVMMSG) ); - 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.slog_f = _ames_io_slog; - car_u->io.kick_f = _ames_io_kick; - car_u->io.mark_f = _ames_io_mark; - car_u->io.exit_f = _ames_io_exit; - - sam_u->fin_s.sam_u = sam_u; - - { - 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); - } - - // XX declare void pointer to u3_host and add sam_u in it - u3_Host.sam_u = sam_u; - u3_Host.imp_u = sam_u->zar_u.pip_w; - return car_u; -} diff --git a/pkg/vere/io/ames/ames.c b/pkg/vere/io/ames/ames.c new file mode 100644 index 0000000000..5488dbd981 --- /dev/null +++ b/pkg/vere/io/ames/ames.c @@ -0,0 +1,2194 @@ +/// @file + +#include "vere.h" +#include "io/ames/stun.h" +#include "io/ames/lamp.h" +#include "io/mesa/mesa.h" + +#include "noun.h" +#include "ur/ur.h" + +#include "zlib.h" + +#include "ent/ent.h" + +#ifndef U3_OS_windows +#include +#endif + +#define FINE_PAGE 4096 // packets per page +#define FINE_FRAG 1024 // bytes per fragment packet +#define FINE_PATH_MAX 384 // longest allowed scry path +#define HEAD_SIZE 4 // header size in bytes + +// a hack to work around the inability to delete from a hashtable +// +#define FINE_PEND 1 // scry cache sentinel value: "pending" +#define FINE_DEAD 2 // scry cache sentinel value: "dead" + +#define QUEUE_MAX 30 // max number of packets in queue + +#define DIRECT_ROUTE_TIMEOUT_MICROS 120000000 + + typedef struct _u3_ames u3_ames; + typedef struct _u3_mesa_auto { + u3_auto car_u; + u3_ames* sam_u; + u3_pier* pir_u; + union { // uv udp handle + uv_udp_t wax_u; // + uv_handle_t had_u; // + }; // + } u3_mesa_auto; + +/* u3_fine: fine networking +*/ + typedef struct _u3_fine { + 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_mesa_auto* mes_u; // ames driver + u3_pier* pir_u; + u3_fine fin_s; // fine networking + 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_y ver_y; // protocol version + struct { // config: + c3_o see_o; // can scry + c3_o fit_o; // filtering active + } fig_u; // + struct { // stats: + c3_d dop_d; // drop count + c3_d fod_d; // forwards dropped count + c3_d foq_d; // forward queue size + c3_d fow_d; // forwarded count + c3_o for_o; // forwarding enabled + c3_d hed_d; // failed to read header + c3_d vet_d; // version mismatches filtered + c3_d mut_d; // invalid mugs filtered + c3_d pre_d; // failed to read prelude + c3_d wal_d; // failed to read wail + c3_d wap_d; // failed to read wail path + c3_d fal_d; // crash count + c3_d vil_d; // encryption failures + c3_d saw_d; // successive scry failures + } sat_u; // + } u3_ames; + +STATIC_ASSERT( + ( ((void*)(u3_ames*)(void*)0) == + ((void*)(u3_ames*)(void*)&(((u3_ames*)(void*)0)->mes_u)) ), + "u3_ames struct alignment" ); + +/* 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 + u3_ship sen_u; // sender/requester + u3_ship rec_u; // receiver/responder + c3_d rog_d; // origin lane (optional) + } u3_prel; + +/* u3_peep: unsigned fine request body +*/ + typedef struct _u3_peep { + c3_w fra_w; // fragment number + c3_s len_s; // path length + c3_c* pat_c; // path as ascii + } u3_peep; + +/* u3_wail: fine request body +*/ + typedef struct _u3_wail { + c3_y tag_y; // tag (always 0, unsigned) + u3_peep pep_u; // request payload + } u3_wail; + +/* u3_meow: response portion of purr packet + * + * siz_s: number of bytes in the packet +*/ + typedef struct _u3_meow { + c3_y sig_y[64]; // host signature + c3_w num_w; // number of fragments + c3_s siz_s; // datum size (actual) + c3_y* dat_y; // datum (0 if null response) + } u3_meow; + +/* u3_purr: fine packet response +*/ + typedef struct _u3_purr { + u3_peep pep_u; // fragment number + path + u3_meow mew_u; // fragment + } u3_purr; + +/* u3_body: ames packet body +*/ + typedef struct _u3_body { + c3_s con_s; // content size + c3_y* con_y; // content + c3_l mug_l; // checksum + } u3_body; + +/* u3_ptag: packet-type tag +*/ + typedef enum _u3_ptag { + PACT_AMES = 1, // ames packet + PACT_WAIL = 2, // fine request packet + PACT_PURR = 3 // fine response packet + } u3_ptag; + + typedef struct _u3_ref_hun { + c3_w ref_w; + c3_w len_w; // length in bytes + c3_y hun_y[0]; // packet buffer + } u3_ref_hun; + + typedef struct _u3_send_handle { + uv_udp_send_t snd_u; // udp send request + u3_ref_hun *hun_u; + } u3_send_handle; + +/* u3_pact: ames packet + * + * Filled in piece by piece as we parse or construct it. +*/ + typedef struct _u3_pact { + struct _u3_ames* sam_u; // ames backpointer + sockaddr_in lan_u; // destination/origin lane + u3_ref_hun* hun_u; + u3_head hed_u; // head of packet + u3_prel pre_u; // packet prelude + u3_ptag typ_y; // packet type tag + c3_d her_d; // time packet was heard + c3_o for_o; // are we forwarding + union { + u3_body bod_u; // tagged by PACT_AMES + u3_wail wal_u; // tagged by PACT_WAIL + u3_purr pur_u; // tagged by PACT_PURR + }; + } u3_pact; + +#define _str_typ(typ_y) ( \ + ( PACT_AMES == typ_y ) ? "ames" \ + : ( PACT_WAIL == typ_y ) ? "wail" \ + : ( PACT_PURR == typ_y ) ? "purr" : "????") + +const c3_c* PATH_PARSER = + ";~(pfix fas (most fas (cook crip (star ;~(less fas prn)))))"; + +static c3_o net_o = c3y; // online heuristic to limit verbosity + +///* _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); +//} + +static void +_ames_ref_hun_lose(u3_ref_hun* hun_u) { + assert(0 != hun_u->ref_w); + hun_u->ref_w--; + if (0 == hun_u->ref_w) c3_free(hun_u); +} + +static u3_ref_hun* +_ames_ref_hun_gain(u3_ref_hun* hun_u) { + assert(0 != hun_u->ref_w); + assert(UINT32_MAX != hun_u->ref_w); + hun_u->ref_w++; + return hun_u; +} + +static u3_ref_hun* +_ames_ref_hun_new(c3_w len_w) { + u3_ref_hun* hun_u = c3_malloc(sizeof(hun_u) + len_w); + hun_u->ref_w = 1; + hun_u->len_w = len_w; + return hun_u; +} + +static void +_ames_pact_free(u3_pact* pac_u) +{ + switch ( pac_u->typ_y ) { + case PACT_AMES: + c3_free(pac_u->bod_u.con_y); + break; + + case PACT_WAIL: + c3_free(pac_u->wal_u.pep_u.pat_c); + break; + + case PACT_PURR: + c3_free(pac_u->pur_u.pep_u.pat_c); + c3_free(pac_u->pur_u.mew_u.dat_y); + break; + + default: + u3l_log("ames_pact_free: bad packet type %s", + _str_typ(pac_u->typ_y)); + u3_king_bail(); + exit(1); + } + + _ames_ref_hun_lose(pac_u->hun_u); + c3_free(pac_u); +} + +static inline u3_ptag +_ames_pact_typ(u3_head* hed_u) +{ + return (( c3y == hed_u->sim_o ) ? PACT_AMES : + ( c3y == hed_u->req_o ) ? PACT_WAIL : PACT_PURR); +} + +static inline c3_y +_ames_origin_size(u3_head* hed_u) +{ + return ( c3y == hed_u->rel_o ) ? 6 : 0; // origin is 6 bytes +} + +static c3_y +_ames_prel_size(u3_head* hed_u) +{ + c3_y lif_y = 1; + c3_y sen_y = 2 << hed_u->sac_y; + c3_y rec_y = 2 << hed_u->rac_y; + c3_y rog_y = _ames_origin_size(hed_u); + return lif_y + sen_y + rec_y + rog_y; +} + +static inline c3_s +_ames_body_size(u3_body* bod_u) +{ + return bod_u->con_s; +} + +static inline c3_s +_fine_peep_size(u3_peep* pep_u) +{ + return ( + sizeof(pep_u->fra_w) + + sizeof(pep_u->len_s) + + pep_u->len_s); +} + +static inline c3_y +_fine_bytes_word(c3_w num_w) +{ + return (c3_bits_word(num_w) + 7) >> 3; +} + +static inline c3_s +_fine_meow_size(u3_meow* mew_u) +{ + c3_y cur_y = 0; + if (mew_u->siz_s != 0) { + cur_y = sizeof(mew_u->num_w); + } + else { + cur_y = _fine_bytes_word(mew_u->num_w); + } + return ( + sizeof(mew_u->sig_y) + + cur_y + + mew_u->siz_s); +} + +static c3_s +_fine_purr_size(u3_purr* pur_u) +{ + c3_s pur_s = _fine_peep_size(&pur_u->pep_u); + c3_s mew_s = _fine_meow_size(&pur_u->mew_u); + return pur_s + mew_s; +} + +static c3_o +_ames_check_mug(u3_pact* pac_u) +{ + c3_w rog_w = HEAD_SIZE + _ames_origin_size(&pac_u->hed_u); + c3_l mug_l = u3r_mug_bytes(pac_u->hun_u->hun_y + rog_w, + pac_u->hun_u->len_w - rog_w); + // u3l_log("len_w: %u, rog_w: %u, bod_l 0x%05x, hed_l 0x%05x", + // pac_u->hun_u->len_w, rog_w, + // (mug_l & 0xfffff), + // (pac_u->hed_u.mug_l & 0xfffff)); + return ( + ((mug_l & 0xfffff) == (pac_u->hed_u.mug_l & 0xfffff)) + ? c3y : c3n); +} + +/* _ames_sift_head(): parse packet header. +*/ +static void +_ames_sift_head(u3_head* hed_u, c3_y buf_y[4]) +{ + c3_w hed_w = c3_sift_word(buf_y); + + // first two bits are reserved + // + hed_u->req_o = (hed_w >> 2) & 0x1; + hed_u->sim_o = (hed_w >> 3) & 0x1; + hed_u->ver_y = (hed_w >> 4) & 0x7; + hed_u->sac_y = (hed_w >> 7) & 0x3; + hed_u->rac_y = (hed_w >> 9) & 0x3; + hed_u->mug_l = (hed_w >> 11) & 0xfffff; // 20 bits + hed_u->rel_o = (hed_w >> 31) & 0x1; +} + +/* _ames_sift_prel(): parse prelude, +*/ +static void +_ames_sift_prel(u3_head* hed_u, + u3_prel* pre_u, + c3_y* buf_y) +{ + c3_y sen_y, rec_y; + c3_w cur_w = 0; + + // if packet is relayed, parse 6-byte origin field + // + if ( c3y == hed_u->rel_o ) { + c3_y rag_y[8] = {0}; + memcpy(rag_y, buf_y + cur_w, 6); + pre_u->rog_d = c3_sift_chub(rag_y); + cur_w += 6; + } + else { + pre_u->rog_d = 0; + } + + // parse life ticks + // + pre_u->sic_y = buf_y[cur_w] & 0xf; + pre_u->ric_y = (buf_y[cur_w] >> 4) & 0xf; + cur_w++; + + // parse sender ship + // + sen_y = 2 << hed_u->sac_y; + pre_u->sen_u = u3_ship_of_bytes(sen_y, buf_y + cur_w); + cur_w += sen_y; + + // parse receiver ship + // + rec_y = 2 << hed_u->rac_y; + pre_u->rec_u = u3_ship_of_bytes(rec_y, buf_y + cur_w); + cur_w += rec_y; +} + +/* _fine_sift_wail(): parse request body, returning success +*/ +static c3_o +_fine_sift_wail(u3_pact* pac_u, c3_w cur_w) +{ + c3_w fra_w = sizeof(pac_u->wal_u.pep_u.fra_w); + c3_w len_w = sizeof(pac_u->wal_u.pep_u.len_s); + c3_w exp_w = fra_w + len_w; + c3_s len_s; + + if ( cur_w + exp_w > pac_u->hun_u->len_w ) { + u3l_log("fine: wail not big enough"); + return c3n; + } + + // parse tag + // + pac_u->wal_u.tag_y = *(pac_u->hun_u->hun_y + cur_w); + cur_w++; + + if ( 0 != pac_u->wal_u.tag_y ) { + u3l_log("fine: wail tag unknown %u", pac_u->wal_u.tag_y); + return c3n; + } + + // parse fragment number + // + pac_u->wal_u.pep_u.fra_w = c3_sift_word(pac_u->hun_u->hun_y + cur_w); + cur_w += fra_w; + + // parse path length field + // + len_s = c3_sift_short(pac_u->hun_u->hun_y + cur_w); + pac_u->wal_u.pep_u.len_s = len_s; + cur_w += len_w; + + if ( len_s > FINE_PATH_MAX ) { + u3l_log("ames wail len: %u, max %u", len_s, FINE_PATH_MAX); + return c3n; + } + + { + c3_w tot_w = cur_w + len_s; + if ( tot_w != pac_u->hun_u->len_w ) { + u3l_log("fine: wail expected total len: %u, actual %u", + tot_w, pac_u->hun_u->len_w); + return c3n; + } + } + + // parse request path + // + pac_u->wal_u.pep_u.pat_c = c3_calloc(len_s + 1); + memcpy(pac_u->wal_u.pep_u.pat_c, pac_u->hun_u->hun_y + cur_w, len_s); + pac_u->wal_u.pep_u.pat_c[len_s] = '\0'; + return c3y; +} + +/* _fine_sift_meow(): parse signed scry response fragment +*/ +static c3_o +_fine_sift_meow(u3_meow* mew_u, u3_noun mew) +{ + c3_o ret_o; + c3_w len_w = u3r_met(3, mew); + c3_w sig_w = sizeof(mew_u->sig_y); + c3_w num_w = sizeof(mew_u->num_w); + c3_w min_w = sig_w + 1; + c3_w max_w = sig_w + num_w + FINE_FRAG; + + if ( (len_w < min_w) || (len_w > max_w) ) { + u3l_log("sift_meow len_w %u (min_w %u, max_w %u)", len_w, min_w, max_w); + ret_o = c3n; + } + else { + c3_w cur_w = 0; + + // parse signature + // + u3r_bytes(cur_w, sig_w, mew_u->sig_y, mew); + cur_w += sig_w; + + // parse number of fragments + // + u3r_bytes(cur_w, num_w, (c3_y*)&mew_u->num_w, mew); + num_w = c3_min(num_w, (len_w - cur_w)); + cur_w += num_w; + u3_assert(len_w >= cur_w); + + // parse data payload + // + mew_u->siz_s = len_w - cur_w; + + if ( !mew_u->siz_s ) { + mew_u->dat_y = 0; + } + else { + mew_u->dat_y = c3_calloc(mew_u->siz_s); + u3r_bytes(cur_w, mew_u->siz_s, mew_u->dat_y, mew); + } + + ret_o = c3y; + } + + u3z(mew); + return ret_o; +} + +/* _ames_etch_head(): serialize packet header. +*/ +static void +_ames_etch_head(u3_head* hed_u, c3_y buf_y[4]) +{ + // only version 0 currently recognized + // + u3_assert( 0 == hed_u->ver_y ); // XX remove after testing + + c3_w hed_w = ((hed_u->req_o & 0x1) << 2) + ^ ((hed_u->sim_o & 0x1) << 3) + ^ ((hed_u->ver_y & 0x7) << 4) + ^ ((hed_u->sac_y & 0x3) << 7) + ^ ((hed_u->rac_y & 0x3) << 9) + ^ ((hed_u->mug_l & 0xfffff) << 11) + ^ (((c3_w)hed_u->rel_o & 0x1) << 31); + + c3_etch_word(buf_y, hed_w); +} + +static void +_ames_etch_origin(c3_d rog_d, c3_y* buf_y) +{ + c3_y rag_y[8] = {0}; + c3_etch_chub(rag_y, rog_d); + memcpy(buf_y, rag_y, 6); +} + +/* _ames_etch_prel(): serialize packet prelude +*/ +static void +_ames_etch_prel(u3_head* hed_u, u3_prel* pre_u, c3_y* buf_y) +{ + c3_w cur_w = 0; + + // if packet is relayed, write the 6-byte origin field + // + if ( c3y == hed_u->rel_o ) { + _ames_etch_origin(pre_u->rog_d, buf_y + cur_w); + cur_w += 6; + } + + // write life ticks + // + buf_y[cur_w] = (pre_u->sic_y & 0xf) ^ ((pre_u->ric_y & 0xf) << 4); + cur_w++; + + // write sender ship + // + c3_y sen_y = 2 << hed_u->sac_y; + u3_ship_to_bytes(pre_u->sen_u, sen_y, buf_y + cur_w); + cur_w += sen_y; + + // write receiver ship + // + c3_y rec_y = 2 << hed_u->rac_y; + u3_ship_to_bytes(pre_u->rec_u, sen_y, buf_y + cur_w); + cur_w += rec_y; +} + +/* _fine_etch_peep(): serialize unsigned scry request +*/ +static void +_fine_etch_peep(u3_peep* pep_u, c3_y* buf_y) +{ + c3_w cur_w = 0; + + // write fragment number + // + c3_etch_word(buf_y + cur_w, pep_u->fra_w); + cur_w += sizeof(pep_u->fra_w); + + // write path length + // + c3_etch_short(buf_y + cur_w, pep_u->len_s); + cur_w += sizeof(pep_u->len_s); + + // write request path + // + memcpy(buf_y + cur_w, pep_u->pat_c, pep_u->len_s); +} + +/* fine_etch_meow(): serialize signed scry response fragment +*/ +static void +_fine_etch_meow(u3_meow* mew_u, c3_y* buf_y) +{ + c3_w cur_w = 0; + + // write signature + // + c3_w sig_w = sizeof(mew_u->sig_y); + memcpy(buf_y + cur_w, mew_u->sig_y, sig_w); + cur_w += sig_w; + + { + c3_y num_y[4]; + c3_y len_y = _fine_bytes_word(mew_u->num_w); + + // write number of fragments + // + c3_etch_word(num_y, mew_u->num_w); + memcpy(buf_y + cur_w, num_y, len_y); + + if (mew_u->siz_s != 0) { + cur_w += sizeof(mew_u->num_w); + } + else { + cur_w += len_y; + } + } + + // write response fragment data + // + memcpy(buf_y + cur_w, mew_u->dat_y, mew_u->siz_s); +} + +/* _fine_etch_purr(): serialise response packet + */ +static void +_fine_etch_purr(u3_purr* pur_u, c3_y* buf_y) +{ + c3_w cur_w = 0; + + // write unsigned scry request + // + _fine_etch_peep(&pur_u->pep_u, buf_y + cur_w); + cur_w += _fine_peep_size(&pur_u->pep_u); + + // write signed response fragment + _fine_etch_meow(&pur_u->mew_u, buf_y + cur_w); +} + +/* _fine_etch_response(): serialize scry response packet +*/ +static void +_fine_etch_response(u3_pact* pac_u) +{ + c3_w pre_w, pur_w, cur_w, rog_w; + + pre_w = _ames_prel_size(&pac_u->hed_u); + pur_w = _fine_purr_size(&pac_u->pur_u); + pac_u->hun_u = _ames_ref_hun_new(HEAD_SIZE + pre_w + pur_w); + + // skip the header until we know what the mug should be + // + cur_w = HEAD_SIZE; + + // write prelude + // + _ames_etch_prel(&pac_u->hed_u, &pac_u->pre_u, pac_u->hun_u->hun_y + cur_w); + cur_w += pre_w; + + // write body + // + _fine_etch_purr(&pac_u->pur_u, pac_u->hun_u->hun_y + cur_w); + + // calculate mug and write header + // + rog_w = HEAD_SIZE + _ames_origin_size(&pac_u->hed_u); + pac_u->hed_u.mug_l = u3r_mug_bytes(pac_u->hun_u->hun_y + rog_w, + pac_u->hun_u->len_w - rog_w); + _ames_etch_head(&pac_u->hed_u, pac_u->hun_u->hun_y); + + u3_assert( c3y == _ames_check_mug(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); +} + +/* _ames_send_cb(): send callback. +*/ +static void +_ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) +{ + + u3_send_handle* snd_u = (u3_send_handle*)req_u; + + if ( !sas_i ) { + net_o = c3y; + } + else if ( c3y == net_o ) { + u3l_log("ames: send fail: %s", uv_strerror(sas_i)); + net_o = c3n; + } + + _ames_ref_hun_lose(snd_u->hun_u); + c3_free(req_u); +} + +u3_peer* +_mesa_get_peer(u3_mesa_auto* sam_u, u3_ship her_u); + +u3_peer* +_mesa_gut_peer(u3_mesa_auto* sam_u, u3_ship her_u); + +c3_o +_mesa_is_lane_zero(sockaddr_in lan_u); + +/* _ames_send(): send buffer to address on port. +*/ +static void +_ames_send(u3_ames* sam_u, sockaddr_in lan_u, u3_ref_hun* hun_u) +{ + if ( c3n == sam_u->mes_u->car_u.liv_o ) { + u3l_log("ames: not yet live, dropping outbound\r"); + if ( NULL != hun_u) + _ames_ref_hun_lose(hun_u); + return; + } + + assert( (NULL == hun_u) || (0 != hun_u->ref_w) ); + if ( !hun_u + || !hun_u->len_w + || c3y == _mesa_is_lane_zero(lan_u) ) + { + u3l_log("ames: _ames_send null"); + if ( NULL != hun_u) + _ames_ref_hun_lose(hun_u); + } + else { + u3_send_handle* snd_u = c3_calloc(sizeof(*snd_u)); + snd_u->hun_u = hun_u; + uv_buf_t buf_u = uv_buf_init((c3_c*)hun_u->hun_y, hun_u->len_w); + c3_w nip_w = lan_u.sin_addr.s_addr; + c3_c nip_c[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &nip_w, nip_c, INET_ADDRSTRLEN); + u3l_log("send ip .%s port %u", + nip_c, ntohs(lan_u.sin_port)); + + c3_i sas_i = uv_udp_send(&snd_u->snd_u, + sam_u->wax_u, + &buf_u, 1, + (const struct sockaddr*)&lan_u, + _ames_send_cb); + + if ( sas_i ) { + _ames_send_cb(&snd_u->snd_u, sas_i); + } + } +} + +sockaddr_in +u3_ames_chub_to_lane(c3_d lan_d) { + sockaddr_in lan_u; + lan_u.sin_family = AF_INET; + lan_u.sin_addr.s_addr = htonl((c3_w)lan_d); + lan_u.sin_port = htons((c3_s)(lan_d >> 32)); + return lan_u; +} + +/* u3_ames_decode_lane(): deserialize noun to lane; 0.0.0.0:0 if invalid +*/ +sockaddr_in +u3_ames_decode_lane(u3_atom lan) { + c3_d lan_d; + + if ( c3n == u3r_safe_chub(lan, &lan_d) || (lan_d >> 48) != 0 ) { + return (sockaddr_in){0}; + } + + u3z(lan); + + return u3_ames_chub_to_lane(lan_d); +} + +/* u3_ames_lane_to_chub(): serialize lane to double-word +*/ +c3_d +u3_ames_lane_to_chub(sockaddr_in lan) { + return ((c3_d)ntohs(lan.sin_port) << 32) + ^ (c3_d)ntohl(lan.sin_addr.s_addr); +} + +/* u3_ames_encode_lane(): serialize lane to noun +*/ +u3_atom +u3_ames_encode_lane(sockaddr_in lan) { + // [%| p=@] + // [%& p=@pC] + return u3i_chub(u3_ames_lane_to_chub(lan)); +} + +/* _ames_lane_into_cache(): put las for who into cache, including timestamp + * TODO: remove? use callbacks +*/ +u3_peer* +_ames_lane_into_cache(u3_ames* sam_u, u3_noun who, u3_noun las) +{ + u3_ship who_u = u3_ship_of_noun(who); + u3_peer* per_u = _mesa_gut_peer(sam_u->mes_u, who_u); + if ( c3y == per_u->lam_o ) return per_u; + + // XX the format of the lane %nail gives is (list (each @p address)) + + if ( las == u3_nul ) { + per_u->dan_u = (sockaddr_in){0}; + } + else { + u3_noun lan = u3h(las); + // we either have a direct route, and a galaxy, or just one lane + if ( c3n == u3h(lan) ) { + per_u->dan_u = u3_ames_decode_lane(u3k(u3t(lan))); + if ( c3y == u3du(u3t(las)) ) { + u3_noun lan = u3h(u3t(las)); + if ( c3n == u3h(lan) ) + u3m_p("strange second lane", lan); + else + per_u->lam_u = u3_ship_of_noun(u3t(lan)); + } + } else { + u3_ship who_u = u3_ship_of_noun(u3t(lan)); + if ( c3n == u3_ships_equal(sam_u->pir_u->who_u, who_u) ) { + // delete direct lane if galaxy + per_u->dan_u = (sockaddr_in){0}; + } else { + per_u->lam_o = c3y; + per_u->dan_u = u3_ames_decode_lane(u3k(u3t(lan))); + } + per_u->lam_u = who_u; + } + } + u3z(who); u3z(las); + return per_u; +} + +c3_d +_get_now_micros(); + +c3_o +_ames_is_direct_mode(u3_peer* per_u) +{ + c3_d now_d = _get_now_micros(); + return __( (c3y == per_u->lam_o) || + (per_u->dir_u.her_d + DIRECT_ROUTE_TIMEOUT_MICROS > now_d) ); +} + +static c3_o +_ames_lane_from_peer(u3_ames* sam_u, + u3_peer* per_u, + sockaddr_in lan_u[2]) { + if ( NULL == per_u ) return c3n; + if ( u3_peer_full != per_u->liv_e ) return c3n; + if ( c3y == u3_ships_equal(per_u->her_u, sam_u->pir_u->who_u) ) + return c3y; + if ( c3y == _mesa_is_lane_zero(per_u->dan_u) ) { + if ( c3y == u3_ships_equal(per_u->lam_u, sam_u->pir_u->who_u) ) + return c3y; + u3_peer* lam_u = _mesa_get_peer(sam_u->mes_u, per_u->lam_u); + if ( (NULL == lam_u) || + (c3y == _mesa_is_lane_zero(lam_u->dan_u)) ) + return c3y; + lan_u[0] = lam_u->dan_u; + return c3y; + } else if ( c3y == _ames_is_direct_mode(per_u) ) { + lan_u[0] = per_u->dan_u; + return c3y; + } else { + lan_u[0] = per_u->dan_u; + if ( c3y == u3_ships_equal(per_u->lam_u, sam_u->pir_u->who_u) ) + return c3y; + u3_peer* lam_u = _mesa_get_peer(sam_u->mes_u, per_u->lam_u); + if ( (NULL == lam_u) || + (c3y == _mesa_is_lane_zero(lam_u->dan_u)) ) + return c3y; + lan_u[1] = lam_u->dan_u; + return c3y; + } +} + +/* _ames_lane_from_cache(): retrieve lane for who from cache, if any +*/ +static c3_o +_ames_lane_from_cache(u3_ames* sam_u, + u3_noun who, + sockaddr_in lan_u[2]) { + memset(lan_u, 0, sizeof(sockaddr_in) * 2); + u3_ship who_u = u3_ship_of_noun(who); + u3_peer* per_u = _mesa_get_peer(sam_u->mes_u, who_u); + return _ames_lane_from_peer(sam_u, per_u, lan_u); +} + +static u3_noun +_ames_pact_to_noun(u3_pact* pac_u) +{ + u3_noun pac = u3i_bytes(pac_u->hun_u->len_w, pac_u->hun_u->hun_y); + return pac; +} + +/* _fine_get_cache(): get packet list or status from cache. RETAIN + */ +static u3_weak +_fine_get_cache(u3_ames* sam_u, u3_noun pax, c3_w fra_w) +{ + u3_noun key = u3nc(u3k(pax), u3i_word(fra_w)); + u3_weak pro = u3h_git(sam_u->fin_s.sac_p, key); + u3z(key); + return pro; +} + +/* _fine_put_cache(): put packet list or status into cache. RETAIN. + */ +static void +_fine_put_cache(u3_ames* sam_u, u3_noun pax, c3_w lop_w, u3_noun lis) +{ + if ( (FINE_PEND == lis) || (FINE_DEAD == lis) ) { + u3_noun key = u3nc(u3k(pax), u3i_word(lop_w)); + u3h_put(sam_u->fin_s.sac_p, key, lis); + u3z(key); + } + else { + while ( u3_nul != lis ) { + u3_noun key = u3nc(u3k(pax), u3i_word(lop_w)); + u3h_put(sam_u->fin_s.sac_p, key, u3k(u3h(lis))); + u3z(key); + + lis = u3t(lis); + lop_w++; + } + } +} + +/* _ames_is_czar(): [who] is galaxy. +*/ +static c3_o +_ames_is_czar(u3_noun who) +{ + u3_noun rac = u3do("clan:title", u3k(who)); + c3_o zar = ( c3y == (c3__czar == rac) ); + u3z(rac); + return zar; +} + +c3_o +_ames_lamp_lane(u3_mesa_auto* mes_u, u3_ship her_u, sockaddr_in* lan_u); + +static void +_saxo_cb(void* vod_p, u3_noun nun) +{ + u3_pact* pac_u = vod_p; + u3_ames* sam_u = pac_u->sam_u; + + u3_weak sax = u3r_at(7, nun); + + u3_peer* per_u = NULL; + if ( sax != u3_none ) { + per_u = _mesa_gut_peer(sam_u->mes_u, pac_u->pre_u.rec_u); + u3_noun her = u3h(sax); + u3_ship her_u = u3_ship_of_noun(her); + u3_noun lam = u3do("rear", u3k(sax)); + //u3_assert( c3y == u3a_is_cat(gal) && gal < 256 ); + // both atoms guaranteed to be cats, bc we don't call unless forwarding + per_u->lam_u = u3_ship_of_noun(lam); + per_u->liv_e |= u3_peer_lamp; + u3z(lam); + } + + u3z(nun); +} + +sockaddr_in +_mesa_realise_lane(u3_mesa_auto* mes_u, u3_noun lan); + +static void +_ames_lane_scry_cb(u3_pact* pac_u, u3_peer* per_u); + +static void +_forward_lanes_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); + // u3m_p("_forward_lanes_cb", las); + + u3_peer* per_u = NULL; + if ( las != u3_none ) { + per_u = _mesa_gut_peer(sam_u->mes_u, pac_u->pre_u.rec_u); + u3_noun gal = u3h(las); + //u3_assert( c3y == u3a_is_cat(gal) && gal < 256 ); + // both atoms guaranteed to be cats, bc we don't call unless forwarding + per_u->liv_e |= u3_peer_lane; + per_u->lam_u = u3_ship_of_noun(gal); + u3_noun sal, tal; + + if ( c3n == per_u->lam_o ) { + if ( (c3y == u3r_cell(u3t(las), &sal, &tal)) && + (c3y == u3du(sal)) ) { + per_u->dan_u = _mesa_realise_lane(sam_u->mes_u, u3k(sal)); + } else { + per_u->dan_u = (sockaddr_in){0}; + } + } + } + _ames_lane_scry_cb(pac_u, per_u); + + u3z(nun); + +} + +static void +_meet_peer(u3_ames* sam_u, u3_pact* pac_u) +{ + u3_peer* per_u = _mesa_get_peer(sam_u->mes_u, pac_u->pre_u.rec_u); + u3_noun her = u3_ship_to_noun(pac_u->pre_u.rec_u); + u3_noun gan = u3nc(u3_nul, u3_nul); + + if ( (NULL == per_u) || !(u3_peer_lamp & per_u->liv_e) ) { + u3_noun pax = u3nc(u3dc("scot", c3__p, u3k(her)), u3_nul); + u3_pier_peek_last(sam_u->mes_u->pir_u, u3k(gan), c3__j, c3__saxo, pax, pac_u, _saxo_cb); + } + + if ( (NULL == per_u) || !(u3_peer_lane & per_u->liv_e) ) { + u3_noun pax = u3nq(u3i_string("chums"), + u3dc("scot", 'p', u3k(her)), + u3i_string("lanes"), + u3_nul); + u3_pier_peek_last(sam_u->mes_u->pir_u, u3k(gan), c3__ax, u3_nul, pax, pac_u, _forward_lanes_cb); + } + u3z(her); u3z(gan); +} + +/* _ames_send_lane(): resolve/decode lane. RETAIN +*/ +static c3_o +_ames_send_lane(u3_ames* sam_u, u3_noun lan, sockaddr_in* lan_u) +{ + + u3_noun tag, val; + + if ( c3n == u3r_cell(lan, &tag, &val) ) { + u3l_log("ames: bad lane; not a cell"); + return c3n; + } + + switch ( tag ) { + case c3y: { // galaxy/lamp + return _ames_lamp_lane(sam_u->mes_u, u3_ship_of_noun(val), lan_u); + } + + case c3n: { // ip:port + sockaddr_in nal_u = u3_ames_decode_lane(u3k(val)); + + // convert incoming localhost to outgoing localhost + // + // XX this looks like en/de-coding problems ... + // + if (!nal_u.sin_addr.s_addr) + nal_u.sin_addr.s_addr = NLOCALHOST; + + // if in local-only mode, don't send remote packets + // + if ( (c3n == u3_Host.ops_u.net) && (NLOCALHOST != nal_u.sin_addr.s_addr) ) { + return c3n; + } + // if the lane is uninterpretable, silently drop the packet + // + else if ( !nal_u.sin_port ) { + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("ames: inscrutable lane"); + } + return c3n; + } + + *lan_u = nal_u; + return c3y; + } + + default: { + u3l_log("ames: bad lane tag"); + return c3n; + } + } +} + +/* _ames_ef_send(): send packet to network (v4). +*/ +static void +_ames_ef_send(u3_ames* sam_u, sockaddr_in lan_u, u3_noun pac) +{ + if ( c3n == sam_u->mes_u->car_u.liv_o ) { + u3l_log("ames: not yet live, dropping outbound\r"); + u3z(pac); + return; + } + + u3_ref_hun* hun_u = _ames_ref_hun_new(u3r_met(3, pac)); + u3r_bytes(0, hun_u->len_w, hun_u->hun_y, pac); + + _ames_send(sam_u, lan_u, hun_u); + + u3z(pac); +} + +/* _ames_cap_queue(): cap ovum queue at QUEUE_MAX, dropping oldest packets. +*/ +static void +_ames_cap_queue(u3_ames* sam_u) +{ + u3_ovum* egg_u = sam_u->mes_u->car_u.ext_u; + c3_d old_d = sam_u->sat_u.dop_d; + + while ( egg_u && (QUEUE_MAX < sam_u->mes_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->mes_u->car_u, egg_u); + sam_u->sat_u.dop_d++; + + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("ames: packet dropped (%" PRIu64 " total)", sam_u->sat_u.dop_d); + } + } + + egg_u = nex_u; + } + + if ( !(u3C.wag_w & u3o_verbose) + && (old_d != sam_u->sat_u.dop_d) + && !(sam_u->sat_u.dop_d % 1000) ) + { + u3l_log("ames: packet dropped (%" PRIu64 " total)", sam_u->sat_u.dop_d); + } +} + +static void +_ames_hear_news(u3_ovum* egg_u, u3_ovum_news new_e) +{ + u3_pact* pac_u = egg_u->ptr_v; + u3_ames* sam_u = pac_u->sam_u; + if ( u3_ovum_exit == new_e ) { + _ames_pact_free(pac_u); + } + else if ( u3_ovum_done == new_e ) { + if ( c3n == pac_u->for_o) { + c3_o dir_o = (pac_u->pre_u.rog_d == 0) ? c3y : c3n; + u3_peer* per_u = _mesa_gut_peer(sam_u->mes_u, pac_u->pre_u.sen_u); + if (c3n == dir_o) { + if ( c3n == per_u->lam_o ) + per_u->dan_u = u3_ames_chub_to_lane(pac_u->pre_u.rog_d); + per_u->ind_u.her_d = pac_u->her_d; + } else { + per_u->dir_u.her_d = pac_u->her_d; + } + } + _ames_pact_free(pac_u); + } +} + +/* _ames_hear_bail(): handle packet failure. +*/ +static void +_ames_hear_bail(u3_ovum* egg_u, u3_noun lud) +{ + u3_pact* pac_u = egg_u->ptr_v; + u3_ames* sam_u = pac_u->sam_u; + c3_w len_w = u3qb_lent(lud); + + if ( (1 == len_w) && c3__evil == u3h(u3h(lud)) ) { + sam_u->sat_u.vil_d++; + + if ( (u3C.wag_w & u3o_verbose) + || (0 == (sam_u->sat_u.vil_d % 100)) ) + { + u3l_log("ames: heard bad crypto (%" PRIu64 " total), " + "check azimuth state\r\n", + sam_u->sat_u.vil_d); + } + } + else { + sam_u->sat_u.fal_d++; + + if ( (u3C.wag_w & u3o_verbose) + || (0 == (sam_u->sat_u.fal_d % 100)) ) + { + if ( 2 == len_w ) { + u3_pier_punt_goof("hear", u3k(u3h(lud))); + u3_pier_punt_goof("crud", u3k(u3h(u3t(lud)))); + } + // !2 traces is unusual, just print the first if present + // + else if ( len_w ) { + u3_pier_punt_goof("hear", u3k(u3h(lud))); + } + + u3l_log("ames: packet failed (%" PRIu64 " total)\r\n", + sam_u->sat_u.fal_d); + } + } + + _ames_pact_free(pac_u); + u3z(lud); + 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_pact* pac_u, + sockaddr_in lan_u) +{ + u3_noun wir = u3nc(c3__ames, u3_nul); + u3_noun cad = u3nt(c3__hear, u3nc(c3n, u3_ames_encode_lane(lan_u)), + _ames_pact_to_noun(pac_u)); + + u3_auto_peer( + u3_auto_plan(&sam_u->mes_u->car_u, + u3_ovum_init(0, c3__a, wir, cad)), + pac_u, _ames_hear_news, _ames_hear_bail); + + _ames_cap_queue(sam_u); +} + +/* _ames_send_many(): send pac_u on the (list lane) las; retains pac_u +*/ +static void +_ames_send_many(u3_pact* pac_u, sockaddr_in lan_u[2], c3_o for_o) +{ + u3_ames* sam_u = pac_u->sam_u; + // if forwarding, track metrics + // + if ( c3y == for_o ) { + 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", sam_u->sat_u.fow_d); + } + + if ( u3C.wag_w & u3o_verbose ) { + u3_noun sen = u3dc("scot", 'p', u3_ship_to_noun(pac_u->pre_u.sen_u)); + u3_noun rec = u3dc("scot", 'p', u3_ship_to_noun(pac_u->pre_u.rec_u)); + c3_c* sen_c = u3r_string(sen); + c3_c* rec_c = u3r_string(rec); + + c3_w nip_w = pac_u->lan_u.sin_addr.s_addr; + c3_c nip_c[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &nip_w, nip_c, INET_ADDRSTRLEN); + + + //NOTE ip byte order assumes little-endian + u3l_log("ames: forwarding for %s to %s from %s:%d", + sen_c, rec_c, nip_c, + ntohs(pac_u->lan_u.sin_port)); + + c3_free(sen_c); c3_free(rec_c); + u3z(sen); u3z(rec); + } + } + + for ( c3_w i = 0; + ( (i < 2) && _mesa_is_lane_zero(lan_u[i]) ); + i++) { + _ames_send(sam_u, lan_u[i], _ames_ref_hun_gain(pac_u->hun_u)); + } +} + + +/* _ames_lane_scry_cb(): learn lanes to send packet on +*/ +static void +_ames_lane_scry_cb(u3_pact* pac_u, u3_peer* per_u) +{ + u3_ames* sam_u = pac_u->sam_u; + + if ( c3y == pac_u->for_o ) + sam_u->sat_u.foq_d--; + + // if scry fails, remember we can't scry, and just inject the packet + // + if ( (NULL == per_u) || (u3_peer_full != per_u->liv_e) ) { + if ( 5 < ++sam_u->sat_u.saw_d ) { + u3l_log("ames: giving up scry"); + sam_u->fig_u.see_o = c3n; + } + _ames_put_packet(sam_u, + pac_u, + pac_u->lan_u); + } + else { + sam_u->sat_u.saw_d = 0; + sockaddr_in lan_u[2]; + _ames_lane_from_peer(sam_u, per_u, lan_u); + + // if there are lanes, send the packet on them; otherwise drop it + // + if ( c3n == _mesa_is_lane_zero(lan_u[0]) ) { + _ames_send_many(pac_u, lan_u, pac_u->for_o); + } + _ames_pact_free(pac_u); + } +} + +/* _ames_try_send(): try to send a packet to a ship and its sponsors +*/ +static void +_ames_try_send(u3_pact* pac_u) +{ + u3_ames* sam_u = pac_u->sam_u; + if ( c3n == sam_u->mes_u->car_u.liv_o ) { + u3l_log("ames: not yet live, dropping outbound\r"); + _ames_pact_free(pac_u); + return; + } + + u3_noun key = u3_ship_to_noun(pac_u->pre_u.rec_u); + sockaddr_in lan_u[2]; + c3_o lan_o = _ames_lane_from_cache(sam_u, key, lan_u); + + // if we know there's no lane, drop the packet + // + if ( (c3y == lan_o) && ( c3y == _mesa_is_lane_zero(lan_u[0]) ) ) { + _ames_pact_free(pac_u); + return; + } + // if we don't know the lane, and the lane scry queue is full, + // just drop the packet + //TODO cap queue for lane lookups for scry responses, not just forwards + // + //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 ( (c3y == pac_u->for_o) + && (c3n == lan_o) + && (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", + sam_u->sat_u.fod_d); + } + + _ames_pact_free(pac_u); + return; + } + + // if we already know the lane, just send + // + if ( c3y == lan_o ) { + _ames_send_many(pac_u, lan_u, pac_u->for_o); + _ames_pact_free(pac_u); + } + // store the packet to be sent later when the lane scry completes + // + else { + if ( c3y == pac_u->for_o ) { + sam_u->sat_u.foq_d++; + } + _meet_peer(sam_u, pac_u); + } +} + +#undef AMES_SKIP +#ifdef AMES_SKIP +/* _ames_skip(): decide whether to skip this packet, for rescue +*/ +static c3_o +_ames_skip(u3_prel* pre_u) +{ + if ( pre_u->sen_u[1] == 0 && + ( pre_u->sen_u[0] == 0x743a17a6 + || pre_u->sen_u[0] == 0xea99acb6 + || pre_u->sen_u[0] == 0x10100 + ) ) { + return c3n; + } + else { + return c3y; + } +} +#endif + +/* _fine_lop(): find beginning of page containing fra_w +*/ +static inline c3_w +_fine_lop(c3_w fra_w) +{ + return 1 + (((fra_w - 1) / FINE_PAGE) * FINE_PAGE); +} + +/* _fine_scry_path(): parse path from wail or purr. +*/ +static u3_weak +_fine_scry_path(u3_pact* pac_u) +{ + u3_peep* pep_u = ( PACT_WAIL == pac_u->typ_y ) + ? &pac_u->wal_u.pep_u + : &pac_u->pur_u.pep_u; + u3_noun ful = u3dc("rush", u3i_string(pep_u->pat_c), u3v_wish(PATH_PARSER)); + + if ( u3_nul == ful ) { + return u3_none; + } + else { + u3_noun pro = u3k(u3t(ful)); + u3z(ful); + return pro; + } +} + +/* _fine_hunk_scry_cb(): receive packets for datum out of fine + */ +static void +_fine_hunk_scry_cb(void* vod_p, u3_noun nun) +{ + u3_pact* pac_u = vod_p; + u3_ames* sam_u = pac_u->sam_u; + u3_peep* pep_u = &pac_u->pur_u.pep_u; + u3_weak fra = u3_none; + + u3_assert( PACT_PURR == pac_u->typ_y ); + + { + // XX virtualize + u3_noun pax = u3dc("rash", u3i_string(pep_u->pat_c), u3v_wish(PATH_PARSER)); + c3_w lop_w = _fine_lop(pep_u->fra_w); + u3_weak pas = u3r_at(7, nun); + + // if not [~ ~ fragments], mark as dead + // + if( u3_none == pas ) { + _fine_put_cache(sam_u, pax, lop_w, FINE_DEAD); + _ames_pact_free(pac_u); + + u3z(nun); + return; + } + + _fine_put_cache(sam_u, pax, lop_w, pas); + + // find requested fragment + // + while ( u3_nul != pas ) { + if ( pep_u->fra_w == lop_w ) { + fra = u3k(u3h(pas)); + break; + } + lop_w++; + pas = u3t(pas); + } + + u3z(pax); + } + + if ( fra == u3_none ) { + u3l_log("fine: fragment number out of range"); + _ames_pact_free(pac_u); + } + else if ( c3y == _fine_sift_meow(&pac_u->pur_u.mew_u, fra) ) { + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("fine: send %u %s", pac_u->pur_u.pep_u.fra_w, + pac_u->pur_u.pep_u.pat_c); + } + + _fine_etch_response(pac_u); + _ames_try_send(pac_u); + } + else { + u3l_log("fine: bad meow"); + _ames_pact_free(pac_u); + } + + u3z(nun); +} + +/* _fine_hear_request(): hear wail (fine request packet packet). +*/ +static void +_fine_hear_request(u3_pact* req_u, c3_w cur_w) +{ + u3_ames* sam_u = req_u->sam_u; + u3_pact* res_u; + u3_noun key; + + if ( c3n == _fine_sift_wail(req_u, cur_w) ) { + sam_u->sat_u.wal_d++; + if ( 0 == (sam_u->sat_u.wal_d % 100) ) { + u3l_log("fine: %" PRIu64 " dropped wails", + sam_u->sat_u.wal_d); + } + _ames_pact_free(req_u); + return; + } + // make scry cache key + // + else { + u3_weak yek = _fine_scry_path(req_u); + + if ( u3_none == yek ) { + sam_u->sat_u.wap_d++; + if ( 0 == (sam_u->sat_u.wap_d % 100) ) { + u3l_log("fine: %" PRIu64 " dropped wails (path)", + sam_u->sat_u.wap_d); + } + _ames_pact_free(req_u); + return; + } + + key = yek; + } + + // fill in the parts of res_u that we know from req_u + { + res_u = c3_calloc(sizeof(*res_u)); + res_u->sam_u = req_u->sam_u; + res_u->typ_y = PACT_PURR; + res_u->lan_u = req_u->lan_u; + + // copy header, swapping sender and receiver + // + res_u->hed_u = (u3_head) { + .req_o = c3n, + .sim_o = c3n, + .ver_y = req_u->hed_u.ver_y, + .sac_y = req_u->hed_u.rac_y, + .rac_y = req_u->hed_u.sac_y, + .mug_l = 0, // filled in later + .rel_o = c3n + }; + + // copy prelude, swapping sender and receiver + // + res_u->pre_u = (u3_prel) { + .sic_y = req_u->pre_u.ric_y, + .ric_y = req_u->pre_u.sic_y, + .sen_u = req_u->pre_u.rec_u, + .rec_u = req_u->pre_u.sen_u, + .rog_d = 0 + }; + + // copy unsigned request payload into response body + // + res_u->pur_u = (u3_purr) { + .pep_u = req_u->wal_u.pep_u, + .mew_u = {0} // filled in later + }; + + // copy path string from request into response body + { + c3_s len_s = req_u->wal_u.pep_u.len_s; + res_u->pur_u.pep_u.pat_c = c3_calloc(len_s + 1); + memcpy(res_u->pur_u.pep_u.pat_c, req_u->wal_u.pep_u.pat_c, len_s); + } + + // free incoming request + // + _ames_pact_free(req_u); + } + + // look up request in scry cache + // + c3_w fra_w = res_u->pur_u.pep_u.fra_w; + c3_w lop_w = _fine_lop(fra_w); + u3_weak pec = _fine_get_cache(sam_u, key, lop_w); + + // already pending; drop + // + if ( FINE_PEND == pec ) { + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("fine: pend %u %s", res_u->pur_u.pep_u.fra_w, + res_u->pur_u.pep_u.pat_c); + } + _ames_pact_free(res_u); + } + // cache miss or a previous scry blocked; try again + // + else { + u3_weak cac = _fine_get_cache(sam_u, key, fra_w); + + if ( (u3_none == cac) || (FINE_DEAD == cac) ) { + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("fine: miss %u %s", res_u->pur_u.pep_u.fra_w, + res_u->pur_u.pep_u.pat_c); + } + + u3_noun pax = + u3nc(c3__fine, + u3nq(c3__hunk, + u3dc("scot", c3__ud, u3i_word(lop_w)), + u3dc("scot", c3__ud, FINE_PAGE), + u3k(key))); + + // mark as pending in the scry cache + // + _fine_put_cache(res_u->sam_u, key, lop_w, FINE_PEND); + + // scry into arvo for a page of packets + // + u3_pier_peek_last(res_u->sam_u->pir_u, u3_nul, c3__ax, u3_nul, + pax, res_u, _fine_hunk_scry_cb); + } + // cache hit, fill in response meow and send + // + else if ( c3y == _fine_sift_meow(&res_u->pur_u.mew_u, u3k(cac)) ) { + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("fine: hit %u %s", res_u->pur_u.pep_u.fra_w, + res_u->pur_u.pep_u.pat_c); + } + _fine_etch_response(res_u); + _ames_try_send(res_u); + } + else { + u3l_log("fine: _fine_hear_request meow bad"); + _ames_pact_free(res_u); + } + } + + u3z(key); +} + +/* _fine_hear_response(): hear purr (fine response packet). +*/ +static void +_fine_hear_response(u3_pact* pac_u, c3_w cur_w) +{ + u3_noun wir = u3nc(c3__fine, u3_nul); + u3_noun cad = u3nt(c3__hear, + u3nc(c3n, u3_ames_encode_lane(pac_u->lan_u)), + u3i_bytes(pac_u->hun_u->len_w, pac_u->hun_u->hun_y)); + + u3_ovum* ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_peer( + u3_auto_plan(&pac_u->sam_u->mes_u->car_u, ovo_u), + pac_u, _ames_hear_news, _ames_hear_bail); + + _ames_cap_queue(pac_u->sam_u); + _ames_pact_free(pac_u); +} + +/* _ames_hear_ames(): hear ames packet. +*/ +static void +_ames_hear_ames(u3_pact* pac_u, c3_w cur_w) +{ + +#ifdef AMES_SKIP + if ( c3_y == _ames_skip(&pac_u->pre_u) ) { + _ames_pact_free(pac_u); + return; + } +#endif + + _ames_put_packet(pac_u->sam_u, pac_u, pac_u->lan_u); +} + +/* _ames_try_forward(): forward packet, updating lane if needed. +*/ +static void +_ames_try_forward(u3_pact* pac_u) +{ + // insert origin lane if needed + // + if ( c3n == pac_u->hed_u.rel_o ) + //&& ( c3__czar == u3_ship_rank(pac_u->pre_u.sen_u) ) ) + { + c3_w cur_w; + u3_ref_hun* old_u; + + pac_u->hed_u.rel_o = c3y; + pac_u->pre_u.rog_d = u3_ames_lane_to_chub(pac_u->lan_u); + + old_u = pac_u->hun_u; + + pac_u->hun_u = _ames_ref_hun_new(pac_u->hun_u->len_w + 6); + + cur_w = 0; + + _ames_etch_head(&pac_u->hed_u, pac_u->hun_u->hun_y); + cur_w += HEAD_SIZE; + + _ames_etch_origin(pac_u->pre_u.rog_d, pac_u->hun_u->hun_y + cur_w); + cur_w += 6; + + memcpy(pac_u->hun_u->hun_y + cur_w, + old_u->hun_y + HEAD_SIZE, + old_u->len_w - HEAD_SIZE); + + _ames_ref_hun_lose(old_u); + } + + _ames_try_send(pac_u); +} + +/* _ames_hear(): parse a (potential) packet, dispatch appropriately. +** +** packet filtering needs to revised for two protocol-change scenarios +** +** - packets using old protocol versions from our sponsees +** these must be let through, and this is a transitive condition; +** they must also be forwarded where appropriate +** they can be validated, as we know their semantics +** +** - packets using newer protocol versions +** these should probably be let through, or at least +** trigger printfs suggesting upgrade. +** they cannot be filtered, as we do not know their semantics +*/ +void +_ames_hear(u3_ames* sam_u, + const struct sockaddr_in* lan_u, + c3_w len_w, + c3_y* hun_y) +{ + u3_pact* pac_u; + c3_w pre_w; + c3_w cur_w = 0; // cursor: how many bytes we've read from hun_y + + // make sure packet is big enough to have a header + // + if ( HEAD_SIZE > len_w ) { + sam_u->sat_u.hed_d++; + if ( 0 == (sam_u->sat_u.hed_d % 100000) ) { + u3l_log("ames: %" PRIu64 " dropped, failed to read header", + sam_u->sat_u.hed_d); + } + + c3_free(hun_y); + return; + } + + pac_u = c3_calloc(sizeof(*pac_u)); + pac_u->sam_u = sam_u; + pac_u->hun_u = _ames_ref_hun_new(len_w); + memcpy(pac_u->hun_u->hun_y, hun_y, len_w); + + pac_u->lan_u = *lan_u; + cur_w = 0; + + // parse the header + // + _ames_sift_head(&pac_u->hed_u, pac_u->hun_u->hun_y); + cur_w += HEAD_SIZE; + + pac_u->typ_y = _ames_pact_typ(&pac_u->hed_u); + + // 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 != pac_u->hed_u.ver_y) ) + { + sam_u->sat_u.vet_d++; + if ( 0 == (sam_u->sat_u.vet_d % 100000) ) { + u3l_log("ames: %" PRIu64 " dropped for version mismatch", + sam_u->sat_u.vet_d); + } + _ames_pact_free(pac_u); + return; + } + + // check contents match mug in header + // + if ( c3n == _ames_check_mug(pac_u) ) { + // _log_head(&pac_u->hed_u); + sam_u->sat_u.mut_d++; + if ( 0 == (sam_u->sat_u.mut_d % 100000) ) { + u3l_log("ames: %" PRIu64 " dropped for invalid mug", + sam_u->sat_u.mut_d); + } + _ames_pact_free(pac_u); + return; + } + + // check that packet is big enough for prelude + // + pre_w = _ames_prel_size(&pac_u->hed_u); + if ( len_w < cur_w + pre_w ) { + sam_u->sat_u.pre_d++; + if ( 0 == (sam_u->sat_u.pre_d % 100000) ) { + u3l_log("ames: %" PRIu64 " dropped, failed to read prelude", + sam_u->sat_u.pre_d); + } + _ames_pact_free(pac_u); + return; + } + + // parse prelude + // + _ames_sift_prel(&pac_u->hed_u, &pac_u->pre_u, pac_u->hun_u->hun_y + cur_w); + cur_w += pre_w; + + pac_u->her_d = _get_now_micros(); + pac_u->for_o = (c3y == u3_ships_equal(pac_u->pre_u.rec_u, + sam_u->pir_u->who_u)) + ? c3n : c3y; + + // if we can scry for lanes, + // and we are not the recipient, + // we might want to forward statelessly + // + if ( (c3y == sam_u->fig_u.see_o) + && ( c3y == pac_u->for_o ) ) + { + if ( c3y == sam_u->sat_u.for_o ) { + _ames_try_forward(pac_u); + } + } + else { + // enter protocol-specific packet handling + // + switch ( pac_u->typ_y ) { + case PACT_WAIL: { + _fine_hear_request(pac_u, cur_w); + } break; + + case PACT_PURR: { + _fine_hear_response(pac_u, cur_w); + } break; + + case PACT_AMES: { + _ames_hear_ames(pac_u, cur_w); + } break; + + default: { + u3l_log("ames_hear: bad packet type %d", pac_u->typ_y); + u3_king_bail(); + exit(1); + } + } + } +} + +/* _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; + sam_u->fin_s.ver_y = 0; + } + else if ( (c3n == u3a_is_cat(ver)) + || (7 < ver) ) { + u3m_p("ames: strange protocol", nun); + sam_u->ver_y = 0; + sam_u->fin_s.ver_y = 0; + } + else { + sam_u->ver_y = ver; + sam_u->fin_s.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); +} + +static void +_saxo_self_cb(void* vod_p, u3_noun nun) +{ + u3_ames* sam_u = vod_p; + u3_weak sax = u3r_at(7, nun); + + if ( sax != u3_none ) { + u3_noun lam = u3do("rear", u3k(sax)); + u3_ship lam_u = u3_ship_of_noun(lam); + if ( c3y == u3_ships_equal(lam_u, sam_u->mes_u->pir_u->who_u) ) + sam_u->sat_u.for_o = c3y; + u3z(lam); + } + + u3z(nun); +} + +static void +_meet_self(u3_ames* sam_u) +{ + u3_noun her = u3_ship_to_noun(sam_u->mes_u->pir_u->who_u); + u3_noun gan = u3nc(u3_nul, u3_nul); + + u3_noun pax = u3nc(u3dc("scot", c3__p, her), u3_nul); + u3_pier_peek_last(sam_u->mes_u->pir_u, gan, c3__j, c3__saxo, pax, sam_u, _saxo_self_cb); +} + +/* _ames_io_talk(): start receiving ames traffic. +*/ +void +_ames_io_talk(u3_ames* 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)); + // } + + // 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_noun gang = u3nc(u3_nul, u3_nul); + // XX drop this; done at another level + // + u3_pier_peek_last(sam_u->pir_u, gang, c3__ax, u3_nul, + u3nt(u3i_string("protocol"), u3i_string("version"), u3_nul), + sam_u, _ames_prot_scry_cb); + if ( c3n == sam_u->sat_u.for_o ) + _meet_self(sam_u); +} + +/* _ames_kick_newt(): apply packet network outputs. +*/ +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 pac = u3k(u3t(dat)); + u3_noun lan = u3k(u3h(dat)); + sockaddr_in lan_u; + if ( c3y == _ames_send_lane(sam_u, lan, &lan_u) ) { + _ames_ef_send(sam_u, lan_u, pac); + } + ret_o = c3y; + } break; + } + + u3z(tag); u3z(dat); + return ret_o; +} + +/* _ames_io_kick(): apply effects +*/ +c3_o +_ames_io_kick(u3_ames* sam_u, u3_noun wir, u3_noun cad) +{ + + 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"); + 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. +*/ +void +_ames_exit_cb(u3_ames* sam_u) +{ + u3s_cue_xeno_done(sam_u->sil_u); + ur_cue_test_done(sam_u->tes_u); + + c3_free(sam_u); +} + +/* _ames_io_info(): produce status info. +*/ +u3_noun +_ames_io_info(u3_ames* sam_u) +{ + c3_w sac_w; + + sac_w = u3h_count(sam_u->fin_s.sac_p) * 4; + u3h_discount(sam_u->fin_s.sac_p); + + return u3i_list( + u3_pier_mase("filtering", sam_u->fig_u.fit_o), + u3_pier_mase("can-send", net_o), + u3_pier_mase("can-scry", sam_u->fig_u.see_o), + u3_pier_mase("scry-cache", u3i_word(u3h_wyt(sam_u->fin_s.sac_p))), + u3_pier_mase("scry-cache-size", u3i_word(sac_w)), + u3_pier_mase("dropped", u3i_chub(sam_u->sat_u.dop_d)), + u3_pier_mase("forwards-dropped", u3i_chub(sam_u->sat_u.fod_d)), + u3_pier_mase("forwards-pending", u3i_chub(sam_u->sat_u.foq_d)), + u3_pier_mase("forwarded", u3i_chub(sam_u->sat_u.fow_d)), + u3_pier_mase("filtered-hed", u3i_chub(sam_u->sat_u.hed_d)), + u3_pier_mase("filtered-ver", u3i_chub(sam_u->sat_u.vet_d)), + u3_pier_mase("filtered-mug", u3i_chub(sam_u->sat_u.mut_d)), + u3_pier_mase("filtered-pre", u3i_chub(sam_u->sat_u.pre_d)), + u3_pier_mase("filtered-wal", u3i_chub(sam_u->sat_u.wal_d)), + u3_pier_mase("filtered-wap", u3i_chub(sam_u->sat_u.wap_d)), + u3_pier_mase("crashed", u3i_chub(sam_u->sat_u.fal_d)), + u3_pier_mase("evil", u3i_chub(sam_u->sat_u.vil_d)), + u3_pier_mase("lane-scry-fails", u3i_chub(sam_u->sat_u.saw_d)), + u3_none); +} + +/* _ames_io_slog(): print status info. +*/ +void +_ames_io_slog(u3_ames* sam_u) +{ + c3_w sac_w; + + sac_w = u3h_count(sam_u->fin_s.sac_p) * 4; + u3h_discount(sam_u->fin_s.sac_p); + +# define FLAG(a) ( (c3y == a) ? "&" : "|" ) + + // TODO rewrite in terms of info_f + // + u3l_log(" config:"); + u3l_log(" filtering: %s", FLAG(sam_u->fig_u.fit_o)); + u3l_log(" can send: %s", FLAG(net_o)); + u3l_log(" can scry: %s", FLAG(sam_u->fig_u.see_o)); + u3l_log(" caches:"); + u3l_log(" cached meows: %u, %u B", u3h_wyt(sam_u->fin_s.sac_p), sac_w); + u3l_log(" counters:"); + u3l_log(" dropped: %" PRIu64, sam_u->sat_u.dop_d); + u3l_log(" forwards dropped: %" PRIu64, sam_u->sat_u.fod_d); + u3l_log(" forwards pending: %" PRIu64, sam_u->sat_u.foq_d); + u3l_log(" forwarded: %" PRIu64, sam_u->sat_u.fow_d); + u3l_log(" filtered (hed): %" PRIu64, sam_u->sat_u.hed_d); + u3l_log(" filtered (ver): %" PRIu64, sam_u->sat_u.vet_d); + u3l_log(" filtered (mug): %" PRIu64, sam_u->sat_u.mut_d); + u3l_log(" filtered (pre): %" PRIu64, sam_u->sat_u.pre_d); + u3l_log(" filtered (wal): %" PRIu64, sam_u->sat_u.wal_d); + u3l_log(" filtered (wap): %" PRIu64, sam_u->sat_u.wap_d); + u3l_log(" crashed: %" PRIu64, sam_u->sat_u.fal_d); + u3l_log(" evil: %" PRIu64, sam_u->sat_u.vil_d); + u3l_log(" lane scry fails: %" PRIu64, sam_u->sat_u.saw_d); +} + +u3m_quac** +_ames_io_mark(u3_auto* car_u, c3_w* out_w) +{ + u3m_quac** all_u = c3_malloc(2 * sizeof(*all_u)); + u3_ames *sam_u = (u3_ames*)car_u; + + all_u[0] = c3_malloc(sizeof(**all_u)); + all_u[0]->nam_c = strdup("scry cache"); + all_u[0]->siz_w = 4 * u3h_mark(sam_u->fin_s.sac_p); + all_u[0]->qua_u = 0; + + all_u[1] = 0; + + *out_w = all_u[0]->siz_w; + + return all_u; +} + +/* u3_ames_io_init(): initialize ames I/O. +*/ +u3_ames* +u3_ames_io_init(u3_mesa_auto* mes_u) +{ + u3_ames* sam_u = c3_calloc(sizeof(*sam_u)); + sam_u->mes_u = mes_u; + sam_u->wax_u = &mes_u->wax_u; + sam_u->mes_u = mes_u; + sam_u->pir_u = mes_u->pir_u; + sam_u->fig_u.see_o = c3y; + sam_u->fig_u.fit_o = c3n; + + // enable forwarding on galaxies only + u3_noun who = u3_ship_to_noun(sam_u->mes_u->pir_u->who_u); + u3_noun rac = u3do("clan:title", who); + // XX: fix for groundwire + sam_u->sat_u.for_o = ( c3__czar == rac ) ? c3y : c3n; + + // hashtable for scry cache + // + // 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. + // + + //XX: zif what? + //u3_assert( !uv_udp_init(u3L, &sam_u->wax_u) ); + //u3_assert( !uv_udp_init_ex(u3L, sam_u->wax_u, UV_UDP_RECVMMSG) ); + //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; + } + + sam_u->fin_s.sam_u = sam_u; + + { + 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 sam_u; +} diff --git a/pkg/vere/io/ames/lamp.c b/pkg/vere/io/ames/lamp.c new file mode 100644 index 0000000000..5d4a48b9e8 --- /dev/null +++ b/pkg/vere/io/ames/lamp.c @@ -0,0 +1,393 @@ +#include "vere.h" +#include "io/ames/lamp.h" + +c3_o +_mesa_is_lane_zero(sockaddr_in lan_u); + +c3_o +_mesa_lanes_equal(sockaddr_in lan_u, sockaddr_in lon_u); + + +/* _ames_czar_port(): udp port for galaxy. +*/ +c3_s +_ames_czar_port(c3_y imp_y) +{ + if ( c3n == u3_Host.ops_u.net ) { + return htons(31337 + imp_y); + } + else { + return htons(13337 + imp_y); + } +} + +/* _ames_czar_str: galaxy name as c3_c[3] +*/ +static void +_ames_czar_str(c3_c zar_c[3], c3_y imp_y) +{ + u3_po_to_suffix(imp_y, (c3_y*)zar_c, (c3_y*)zar_c + 1, (c3_y*)zar_c + 2); +} + +u3_peer* +_mesa_get_peer(void* sam_u, u3_ship her_u); + +u3_peer* +_mesa_gut_peer(void* sam_u, u3_ship her_u); + +/* _ames: retrieve lane for galaxy if stored. +*/ +c3_o +_ames_lamp_lane(u3_auto* car_u, u3_ship her_u, sockaddr_in* lan_u) +{ + u3_peer* per_u = _mesa_get_peer(car_u, her_u); + if (NULL == per_u) return c3n; + + if (c3n == per_u->lam_o) { + u3l_log("fatal: peer is not lamp"); + u3_king_bail(); + } + + if ( c3n == u3_Host.ops_u.net ) { + lan_u->sin_family = AF_INET; + lan_u->sin_addr.s_addr = NLOCALHOST; + lan_u->sin_port = per_u->dan_u.sin_port; + } + else { + *lan_u = per_u->dan_u; + if ( c3y == _mesa_is_lane_zero(*lan_u) ) { + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("ames: lamp not resolved"); + } + return c3n; + } + else if ( _CZAR_GONE == lan_u->sin_addr.s_addr ) { + // print only on first send failure + // + + if ( c3n == per_u->log_o ) { + // XX + //u3l_log("ames: lamp at %s: not found (b)", *dns_c); + per_u->log_o = c3y; + } + + return c3n; + } + } + + return c3y; +} + +typedef struct _lamp_resv { + uv_getaddrinfo_t adr_u; + u3_lamp_state* lam_u; + u3_peer* per_u; + c3_c** dns_c; +} _lamp_resv; + +/* _ames_lamp_gone(): galaxy address resolution failed. +*/ +static void +_ames_lamp_gone(u3_lamp_state* lam_u, u3_peer* per_u) +{ + c3_w old_w = per_u->dan_u.sin_addr.s_addr; + + if ( !old_w ) { + per_u->dan_u.sin_addr.s_addr = _CZAR_GONE; + } +} + +/* _ames_lamp_here(): galaxy address resolution succeeded. +*/ +static void +_ames_lamp_here(u3_lamp_state* lam_u, u3_peer* per_u, sockaddr_in lan_u, c3_c* dns_c) +{ + if ( c3n == _mesa_lanes_equal(lan_u, per_u->dan_u) ) { + c3_w nip_w = lan_u.sin_addr.s_addr; + c3_c nip_c[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &nip_w, nip_c, INET_ADDRSTRLEN); + + c3_c* who_c = u3_ship_to_string(per_u->her_u); + if ( dns_c ) + u3l_log("ames: lamp %s domain %s ip .%s port %u", + who_c, dns_c, + nip_c, ntohs(lan_u.sin_port)); + else + u3l_log("ames: lamp %s static ip .%s port %u", + who_c, + nip_c, ntohs(lan_u.sin_port)); + + c3_free(who_c); + } + + per_u->dan_u = lan_u; + per_u->log_o = c3n; +} + +static void +_ames_lamp(u3_lamp_state* lam_u, u3_peer* per_u, c3_c** dns_c); + +/* _ames_lamp_cb(): galaxy address resolution callback. +*/ +static void +_ames_lamp_cb(uv_getaddrinfo_t* adr_u, + c3_i sas_i, + struct addrinfo* aif_u) +{ + struct addrinfo* rai_u = aif_u; + _lamp_resv* res_u = (_lamp_resv*)adr_u; + u3_lamp_state* lam_u = res_u->lam_u; + u3_peer* per_u = res_u->per_u; + + while ( rai_u && (AF_INET != rai_u->ai_family) ) { + rai_u = rai_u->ai_next; + } + + if ( rai_u && rai_u->ai_addr ) { + struct sockaddr_in* adr_u = (void*)rai_u->ai_addr; + sockaddr_in lan_u = {0}; + lan_u.sin_family = AF_INET; + lan_u.sin_port = per_u->dan_u.sin_port; + lan_u.sin_addr.s_addr = adr_u->sin_addr.s_addr; + _ames_lamp_here(lam_u, per_u, lan_u, *res_u->dns_c); + lam_u->pen_s--; + uv_freeaddrinfo(aif_u); + c3_free(res_u); + } + else { + if ( !sas_i ) { + // XX unpossible + u3l_log("ames: lamp: strange failure, no error"); + _ames_lamp_gone(lam_u, per_u); + lam_u->pen_s--; + uv_freeaddrinfo(aif_u); + c3_free(res_u); + } + else { + c3_c** dns_c = res_u->dns_c; + c3_o nex_o = (NULL != *(dns_c + 1)) ? c3y : c3n; + if ( u3C.wag_w & u3o_verbose ) { + u3l_log("ames: lamp fail: %s", uv_strerror(sas_i)); + //if (nex_o) u3l_log("trying next"); + } + if (c3y == nex_o) + _ames_lamp(lam_u, per_u, dns_c + 1); + else { + // XX: wait should we do this here? + _ames_lamp_gone(lam_u, per_u); + lam_u->pen_s--; + uv_freeaddrinfo(aif_u); + c3_free(res_u); + } + } + } +} + +/* _ames_lamp(): single galaxy address resolution. +*/ +static void +_ames_lamp(u3_lamp_state* lam_u, u3_peer* per_u, c3_c** dns_c) +{ + struct addrinfo hin_u = { .ai_family = AF_INET }; + uv_getaddrinfo_t* adr_u; + _lamp_resv* res_u; + c3_i sas_i; + + res_u = c3_malloc(sizeof(*res_u)); + res_u->lam_u = lam_u; + res_u->per_u = per_u; + res_u->dns_c = dns_c; + + adr_u = &(res_u->adr_u); + sas_i = uv_getaddrinfo(u3L, adr_u, _ames_lamp_cb, *dns_c, 0, &hin_u); + + if ( sas_i ) { + _ames_lamp_cb(adr_u, sas_i, NULL); + } +} + +static void +_ames_etch_czars(u3_lamp_state* lam_u) { + for (c3_w i = 0; i < 256; i++) { + u3_ship who_u = u3_ship_of_noun(i); + u3_peer* per_u = _mesa_gut_peer(lam_u->car_u, who_u); + per_u->lam_o = c3y; + per_u->dan_u.sin_family = AF_INET; + per_u->dan_u.sin_port = _ames_czar_port(i); + c3_c* who_c = u3_ship_to_string(who_u); + c3_w len_w = u3_mpef_turfs(NULL, 0, who_c + 1, lam_u->dns_c); + if (0 != len_w) { + if (per_u->dns_c) c3_free(per_u->dns_c); + c3_c** dns_c = per_u->dns_c = c3_malloc(len_w); + u3_mpef_turfs((c3_c*)dns_c, 0, who_c + 1, lam_u->dns_c); + } + c3_free(who_c); + } +} + +/* _ames_lamp_all(): galaxy address resolution. +*/ +static void +_ames_lamp_all(uv_timer_t* tim_u) +{ + u3_lamp_state* lam_u = tim_u->data; + + // requests still pending + if ( lam_u->pen_s ) { + uv_timer_start(&lam_u->tim_u, _ames_lamp_all, 30*1000, 0); + return; + } + + lam_u->pen_s = 0; + //c3_w i = 0; + for( + per_map_itr itr = + per_map_first( lam_u->per_u ); + !per_map_is_end( itr ); + itr = per_map_next( itr ) ) { + u3_peer* per_u = itr.data->val; + //c3_c* who_c = u3_ship_to_string(per_u->her_u); + //u3l_log("czar %u %s", i, who_c); + //c3_free(who_c); + //i++; + if (per_u->dns_c) { + lam_u->pen_s++; + _ames_lamp(lam_u, per_u, per_u->dns_c); + } + } + + uv_timer_start(&lam_u->tim_u, _ames_lamp_all, 300*1000, 0); +} + +static c3_o +_ames_cmp_turfs(c3_c** a, c3_c** b) { + if (a == NULL) { + if (b == NULL) return c3y; + return c3n; + } + if (b == NULL) { + return c3n; + } + while (*a != NULL || *b != NULL) { + if (*a == NULL) { + if (*b == NULL) return c3y; + return c3n; + } + if (*b == NULL) { + return c3n; + } + if (0 != strcmp(*a, *b)) return 0; + a++; + b++; + } + return c3y; +} + +void +_ames_init_czars(u3_lamp_state* lam_u) +{ + for (c3_w i = 0; i < 256; i++) { + u3_ship who_u = u3_ship_of_noun(i); + u3_peer* per_u = _mesa_gut_peer(lam_u->car_u, who_u); + per_u->lam_o = c3y; + per_u->dan_u.sin_family = AF_INET; + per_u->dan_u.sin_port = _ames_czar_port(i); + } +} + +/* _ames_ef_turf(): initialize ames I/O on domain(s). +*/ +void +_ames_ef_turf(u3_lamp_state* lam_u, u3_noun tuf) +{ + if ( u3_nul != tuf) { + c3_w len_w = u3_mcut_hosts(NULL, 0, u3k(tuf)); + if (len_w == 0) { + // todo: clear? + u3z(tuf); + return; + } + c3_c** dns_c = c3_malloc(len_w); + u3_mcut_hosts((c3_c*)dns_c, 0, u3k(tuf)); + if ( c3n == _ames_cmp_turfs(dns_c, lam_u->dns_c) ) { + c3_free(lam_u->dns_c); + lam_u->dns_c = dns_c; + lam_u->dom_o = c3y; + _ames_etch_czars(lam_u); + _ames_lamp_all(&(lam_u->tim_u)); + } + } + else if ( (c3n == lam_u->car_u->pir_u->fak_o) && (c3n == lam_u->dom_o) ) { + u3l_log("ames: turf: no domains"); + } + + //// XX is this ever necessary? + //// + //if ( c3n == lam_u->car_u.liv_o ) { + // _ames_io_start(lam_u); + //} + u3z(tuf); +} + +void +_ames_fief(u3_lamp_state* lam_u, u3_noun fef) { + u3_noun who, q_fef; + u3x_cell(fef, &who, &q_fef); + u3_ship who_u = u3_ship_of_noun(who); + u3_peer* per_u = _mesa_gut_peer(lam_u->car_u, who_u); + if ( u3_nul == q_fef ) { + per_u->lam_o = c3n; + } else { + per_u->lam_o = c3y; + } + u3_noun tag, val; + u3x_cell(u3t(q_fef), &tag, &val); + switch ( tag ) { + default: { + u3l_log("ames: inscrutable fief"); + } break; + case c3__turf: { + u3_noun tuf, por; + u3x_cell(val, &tuf, &por); + per_u->dan_u.sin_family = AF_INET; + per_u->dan_u.sin_port = htons(por); + if ( u3_nul == tuf ) break; + c3_w len_w = u3_mcut_hosts(NULL, 0, u3k(tuf)); + if (len_w == 0) { + // todo: clear? + break; + } + c3_c** dns_c = c3_malloc(len_w); + u3_mcut_hosts((c3_c*)dns_c, 0, u3k(tuf)); + if ( c3n == _ames_cmp_turfs(dns_c, per_u->dns_c) ) { + if ( NULL != per_u->dns_c ) + c3_free(per_u->dns_c); + per_u->dns_c = dns_c; + lam_u->pen_s++; + _ames_lamp(lam_u, per_u, per_u->dns_c); + } + } break; + case c3__if: { + u3_noun pip, por; + u3x_cell(val, &pip, &por); + sockaddr_in lan_u; + lan_u.sin_family = AF_INET; + lan_u.sin_addr.s_addr = htonl(u3r_word(0, pip)); + lan_u.sin_port = htons(por); + _ames_lamp_here(lam_u, per_u, lan_u, NULL); + } break; + } + u3z(fef); +} + +void +_ames_ef_fief(u3_lamp_state* lam_u, u3_noun fef) +{ + u3_noun _fef = fef = u3kdi_tap(fef); + while ( u3_nul != fef ) { + _ames_fief(lam_u, u3k(u3h(fef))); + fef = u3t(fef); + } + u3z(_fef); +} + diff --git a/pkg/vere/io/ames/lamp.h b/pkg/vere/io/ames/lamp.h new file mode 100644 index 0000000000..a873708bfc --- /dev/null +++ b/pkg/vere/io/ames/lamp.h @@ -0,0 +1,14 @@ +#include "io/mesa/mesa.h" + +#define _CZAR_GONE (htonl(UINT32_MAX)) +#define NLOCALHOST (htonl(0x7f000001)) + +typedef struct _u3_lamp_state { // + u3_auto* car_u; + per_map* per_u; + c3_c** dns_c; // domain + c3_o dom_o; // have domain + uv_timer_t tim_u; // resolve timer + c3_s pen_s; // pending +} u3_lamp_state; // + diff --git a/pkg/vere/io/ames/nat.c b/pkg/vere/io/ames/nat.c new file mode 100644 index 0000000000..fe25d2b8d4 --- /dev/null +++ b/pkg/vere/io/ames/nat.c @@ -0,0 +1,64 @@ +#include "nat.h" + +static void +natpmp_cb(uv_poll_t* handle, + c3_i status, + c3_i events) +{ + + if (status != 0) { + return; + } + + u3_natpmp_state* nat_u = handle->data; + + natpmpresp_t response; + c3_i err_i = readnatpmpresponseorretry(&nat_u->req_u, &response); + if ( NATPMP_TRYAGAIN == err_i ) { + return; + } + + uv_poll_stop(handle); + + if ( 0 != err_i ) { + u3l_log("ames: natpmp error %i", err_i); + uv_poll_stop(&nat_u->pol_u); + closenatpmp(&nat_u->req_u); + return; + } + + u3l_log("ames: mapped public port %hu to localport %hu lifetime %u", + response.pnu.newportmapping.mappedpublicport, + response.pnu.newportmapping.privateport, + response.pnu.newportmapping.lifetime); + + closenatpmp(&nat_u->req_u); + nat_u->tim_u.data = nat_u; + uv_timer_start(&nat_u->tim_u, natpmp_init, 7200000, 0); +} + +void +natpmp_init(uv_timer_t *handle) +{ + u3_natpmp_state* nat_u = handle->data; + c3_s por_s = nat_u->car_u->pir_u->por_s; + + c3_i err_i = initnatpmp(&nat_u->req_u, 0, 0); + + if (err_i != 0) { + return; + } + + err_i = uv_poll_init(u3L, &nat_u->pol_u, nat_u->req_u.s); + + if (err_i != 0) { + return; + } + + sendnewportmappingrequest(&nat_u->req_u, NATPMP_PROTOCOL_UDP, por_s, por_s, 7200); + + nat_u->pol_u.data = nat_u; + uv_poll_start(&nat_u->pol_u, UV_READABLE, natpmp_cb); +} + + diff --git a/pkg/vere/io/ames/nat.h b/pkg/vere/io/ames/nat.h new file mode 100644 index 0000000000..e888b4d978 --- /dev/null +++ b/pkg/vere/io/ames/nat.h @@ -0,0 +1,11 @@ +#include "vere.h" +#include "natpmp.h" + +typedef struct _u3_natpmp_state { + u3_auto* car_u; + natpmp_t req_u; // libnatpmp struct for mapping request + uv_poll_t pol_u; // handle waits on libnatpmp socket + uv_timer_t tim_u; // every two hours if mapping succeeds + } u3_natpmp_state; // libnatpmp stuff for port forwarding + // +void natpmp_init(uv_timer_t* handle); diff --git a/pkg/vere/io/ames/stun.c b/pkg/vere/io/ames/stun.c index 0f830c1f4a..821ed07221 100644 --- a/pkg/vere/io/ames/stun.c +++ b/pkg/vere/io/ames/stun.c @@ -1,5 +1,7 @@ #include "vere.h" #include "zlib.h" +#include "ent/ent.h" +#include "io/ames/stun.h" static c3_y* _stun_add_fingerprint(c3_y *message, c3_w index) @@ -48,10 +50,10 @@ _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len_w) } } -/* u3_stun_is_request(): buffer is a stun request. +/* _stun_is_request(): buffer is a stun request. */ c3_o -u3_stun_is_request(c3_y* buf_y, c3_w len_w) +_stun_is_request(c3_y* buf_y, c3_w len_w) { c3_w cookie = htonl(0x2112A442); @@ -67,10 +69,10 @@ u3_stun_is_request(c3_y* buf_y, c3_w len_w) return c3n; } -/* u3_stun_is_our_response(): buffer is a response to our request. +/* _stun_is_our_response(): buffer is a response to our request. */ c3_o -u3_stun_is_our_response(c3_y* buf_y, c3_y tid_y[12], c3_w len_w) +_stun_is_our_response(c3_y* buf_y, c3_y tid_y[12], c3_w len_w) { c3_w cookie = htonl(0x2112A442); @@ -87,10 +89,10 @@ u3_stun_is_our_response(c3_y* buf_y, c3_y tid_y[12], c3_w len_w) return c3n; } -/* u3_stun_make_request(): serialize stun request. +/* _stun_make_request(): serialize stun request. */ void -u3_stun_make_request(c3_y buf_y[28], c3_y tid_y[12]) +_stun_make_request(c3_y buf_y[28], c3_y tid_y[12]) { // see STUN RFC 8489 // https://datatracker.ietf.org/doc/html/rfc8489#section-5 @@ -112,12 +114,12 @@ u3_stun_make_request(c3_y buf_y[28], c3_y tid_y[12]) _stun_add_fingerprint(buf_y, 20); } -/* u3_stun_make_response(): serialize stun response from request. +/* _stun_make_response(): serialize stun response from request. */ void -u3_stun_make_response(const c3_y req_y[20], - u3_lane* lan_u, - c3_y buf_y[40]) +_stun_make_response(const c3_y req_y[20], + const sockaddr_in* lan_u, + c3_y buf_y[40]) { c3_w cok_w = 0x2112A442; c3_w cur_w = 20; @@ -141,8 +143,10 @@ u3_stun_make_response(const c3_y req_y[20], buf_y[cur_w + 4] = 0x00; // extra reserved 0x0 byte buf_y[cur_w + 5] = 0x01; // family 0x01:IPv4 - c3_s por_s = htons(lan_u->por_s ^ (cok_w >> 16)); - c3_w pip_w = htonl(lan_u->pip_w ^ cok_w); + c3_s por_s = ntohs(lan_u->sin_port); + c3_w pip_w = ntohl(lan_u->sin_addr.s_addr); + por_s = htons(por_s ^ (cok_w >> 16)); + pip_w = htonl(pip_w ^ cok_w); memcpy(buf_y + cur_w + 6, &por_s, 2); // X-Port memcpy(buf_y + cur_w + 8, &pip_w, 4); // X-IP Addres @@ -151,12 +155,12 @@ u3_stun_make_response(const c3_y req_y[20], _stun_add_fingerprint(buf_y, cur_w + 12); } -/* u3_stun_find_xor_mapped_address(): extract lane from response. +/* _stun_find_xor_mapped_address(): extract lane from response. */ c3_o -u3_stun_find_xor_mapped_address(c3_y* buf_y, - c3_w len_w, - u3_lane* lan_u) +_stun_find_xor_mapped_address(c3_y* buf_y, + c3_w len_w, + sockaddr_in* lan_u) { c3_y xor_y[4] = {0x00, 0x20, 0x00, 0x08}; c3_w cookie = 0x2112A442; @@ -177,16 +181,279 @@ u3_stun_find_xor_mapped_address(c3_y* buf_y, cur += 2; - lan_u->por_s = ntohs(c3_sift_short(buf_y + cur)) ^ (cookie >> 16); - lan_u->pip_w = ntohl(c3_sift_word(buf_y + cur + 2)) ^ cookie; + c3_s por_s = ntohs(c3_sift_short(buf_y + cur)) ^ (cookie >> 16); + c3_w pip_w = ntohl(c3_sift_word(buf_y + cur + 2)) ^ cookie; + + lan_u->sin_family = AF_INET; + lan_u->sin_port = htons(por_s); + lan_u->sin_addr.s_addr = htonl(pip_w); if ( u3C.wag_w & u3o_verbose ) { - c3_w nip_w = htonl(lan_u->pip_w); + c3_w nip_w = lan_u->sin_addr.s_addr; c3_c nip_c[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &nip_w, nip_c, INET_ADDRSTRLEN); - u3l_log("stun: hear ip:port %s:%u", nip_c, lan_u->por_s); + u3l_log("stun: hear ip:port %s:%u", nip_c, ntohs(lan_u->sin_port)); } return c3y; } return c3n; } + +typedef struct _stun_send { + uv_udp_send_t req_u; // uv udp request handle + u3_stun_client* sun_u; // backpointer + c3_y hun_y[0]; // buffer +} _stun_send; + +/* _stun_send_cb(): stun udp send callback. + */ +static void +_stun_send_cb(uv_udp_send_t *rep_u, c3_i sas_i) +{ + _stun_send* snd_u = (_stun_send*)rep_u; + + if ( !sas_i ) { + snd_u->sun_u->net_o = c3y; + } + else if ( c3y == snd_u->sun_u->net_o ) { + u3l_log("stun: send response fail: %s", uv_strerror(sas_i)); + snd_u->sun_u->net_o = c3n; + } + + c3_free(snd_u); +} + +/* _stun_on_request(): hear stun request, send response. + */ +static void +_stun_on_request(u3_stun_client* sun_u, + const c3_y* req_y, + const sockaddr_in* lan_u) +{ + _stun_send* snd_u = c3_malloc(sizeof(*snd_u) + 40); + snd_u->sun_u = sun_u; + + _stun_make_response(req_y, lan_u, snd_u->hun_y); + + uv_buf_t buf_u = uv_buf_init((c3_c*)snd_u->hun_y, 40); + c3_i sas_i = uv_udp_send(&snd_u->req_u, sun_u->wax_u, + &buf_u, 1, (const struct sockaddr*)lan_u, _stun_send_cb); + + if ( sas_i ) { + _stun_send_cb(&snd_u->req_u, sas_i); + } +} + +void +u3_stun_start(u3_stun_client* sun_u, c3_w tim_w); + +/* _stun_on_response(): hear stun response from galaxy. + */ +static void +_stun_on_response(u3_stun_client* sun_u, c3_y* buf_y, c3_w buf_len) +{ + sockaddr_in lan_u; + + // Ignore STUN responses that dont' have the XOR-MAPPED-ADDRESS attribute + if ( c3n == _stun_find_xor_mapped_address(buf_y, buf_len, &lan_u) ) { + return; + } + + if ( (sun_u->sef_u.sin_addr.s_addr != lan_u.sin_addr.s_addr) || + (sun_u->sef_u.sin_port != lan_u.sin_port) ) + { + // lane changed + u3_noun wir = u3nc(c3__ames, u3_nul); + u3_noun cad = u3nq(c3__stun, c3__once, u3_ship_to_noun(sun_u->dad_u), + u3nc(c3n, u3_ames_encode_lane(lan_u))); + u3_auto_plan(sun_u->car_u, + u3_ovum_init(0, c3__ames, wir, cad)); + } + else if ( c3n == sun_u->wok_o ) { + // stop %ping app + u3_noun wir = u3nc(c3__ames, u3_nul); + u3_noun cad = u3nq(c3__stun, c3__stop, u3_ship_to_noun(sun_u->dad_u), + u3nc(c3n, u3_ames_encode_lane(lan_u))); + u3_auto_plan(sun_u->car_u, + u3_ovum_init(0, c3__ames, wir, cad)); + sun_u->wok_o = c3y; + } + + sun_u->sef_u = lan_u; + + // XX should no-op early + // + switch ( sun_u->sat_y ) { + case STUN_OFF: break; // ignore; stray response + case STUN_KEEPALIVE: break; // ignore; duplicate response + + case STUN_TRYING: { + u3_stun_start(sun_u, 25000); + } break; + + default: u3_assert(!"programmer error"); + } +} + +/* _stun_send_request(): send stun request to galaxy lane. + */ +static void +_stun_send_request(u3_stun_client* sun_u) +{ + u3_assert( STUN_OFF != sun_u->sat_y ); + + _stun_send* snd_u = c3_malloc(sizeof(*snd_u) + 28); + snd_u->sun_u = sun_u; + + _stun_make_request(snd_u->hun_y, sun_u->tid_y); + + uv_buf_t buf_u = uv_buf_init((c3_c*)snd_u->hun_y, 28); + c3_i sas_i = uv_udp_send(&snd_u->req_u, sun_u->wax_u, &buf_u, 1, + (const struct sockaddr*)&sun_u->lan_u, _stun_send_cb); + + if ( sas_i ) { + _stun_send_cb(&snd_u->req_u, sas_i); + } +} + +/* _stun_reset(): stun failed. start again using max backoff + */ +static void +_stun_reset(uv_timer_t* tim_u) +{ + u3_stun_client* sun_u = (u3_stun_client*)(tim_u->data); + + u3_stun_start(sun_u, 39000); +} + +/* _stun_on_lost(): stun failed (timeout); capture and reset. + */ +static void +_stun_on_lost(u3_stun_client* sun_u) +{ + sun_u->sat_y = STUN_OFF; + + // only inject event into arvo to %kick ping app on first failure + // + if ( c3y == sun_u->wok_o ) { + u3_noun wir = u3nc(c3__ames, u3_nul); + u3_noun cad = u3nq(c3__stun, c3__fail, u3_ship_to_noun(sun_u->dad_u), + u3nc(c3n, u3_ames_encode_lane(sun_u->sef_u))); + u3_auto_plan(sun_u->car_u, + u3_ovum_init(0, c3__ames, wir, cad)); + sun_u->wok_o = c3n; + } + + uv_timer_start(&sun_u->tim_u, _stun_reset, 5*1000, 0); +} + +/* _stun_time_gap(): elapsed milliseconds. + */ +static c3_d +_stun_time_gap(struct timeval sar_tv) +{ + struct timeval tim_tv; + gettimeofday(&tim_tv, 0); + u3_noun now = u3_time_in_tv(&tim_tv); + u3_noun den = u3_time_in_tv(&sar_tv); + return u3_time_gap_ms(den, now); +} + +c3_o _ames_lamp_lane(u3_auto*, u3_ship, sockaddr_in*); + +/* _stun_timer_cb(): advance stun state machine. + */ +static void +_stun_timer_cb(uv_timer_t* tim_u) +{ + u3_stun_client* sun_u = (u3_stun_client*)(tim_u->data); + c3_w rto_w = 500; + + switch ( sun_u->sat_y ) { + case STUN_OFF: { + // ignore; stray timer (although this shouldn't happen) + u3l_log("stun: stray timer STUN_OFF"); + } break; + + case STUN_KEEPALIVE: { + sockaddr_in* lan_u = &(sun_u->lan_u); + u3_ship lam_u = sun_u->dad_u; + + if ( c3n == _ames_lamp_lane(sun_u->car_u, lam_u, lan_u) ) { + uv_timer_start(&sun_u->tim_u, _stun_timer_cb, 25*1000, 0); + } + else { + sun_u->sat_y = STUN_TRYING; + gettimeofday(&sun_u->sar_u, 0); // set start time to now + uv_timer_start(&sun_u->tim_u, _stun_timer_cb, rto_w, 0); + _stun_send_request(sun_u); + } + } break; + + case STUN_TRYING: { + c3_d gap_d = _stun_time_gap(sun_u->sar_u); + c3_d nex_d = (gap_d * 2) + rto_w - gap_d; + + if ( gap_d >= 39500 ) { + _stun_on_lost(sun_u); + } + else { + // wait ~s8 for the last STUN request + // + // https://datatracker.ietf.org/doc/html/rfc5389#section-7.2.1 + // + c3_w tim_w = (gap_d >= 31500) ? 8000 : c3_max(nex_d, 31500); + + uv_timer_start(&sun_u->tim_u, _stun_timer_cb, tim_w, 0); + _stun_send_request(sun_u); + } + } break; + + default: u3_assert(!"programmer error"); + } +} + +/* u3_stun_start(): begin/restart STUN state machine. +*/ +void +u3_stun_start(u3_stun_client* sun_u, c3_w tim_w) +{ + if ( ent_getentropy(sun_u->tid_y, 12) ) { + u3l_log("stun: getentropy fail: %s", strerror(errno)); + u3_king_bail(); + } + + sun_u->sat_y = STUN_KEEPALIVE; + uv_timer_start(&sun_u->tim_u, _stun_timer_cb, tim_w, 0); +} + + +/* u3_stun_hear(): maybe hear stun packet + */ +c3_o +u3_stun_hear(u3_stun_client* sun_u, + const struct sockaddr_in* lan_u, + c3_w len_w, + c3_y* hun_y) +{ + // XX reorg, check if a STUN req/resp can look like an ames packet + // check the mug hash of the body of the packet, if not check if STUN + // otherwise , invalid packet, log failure + // check ames first, assume that STUN could maybe (not likely) overlap with ames + // for next protocol version, have an urbit cookie + // + if ( c3y == _stun_is_request(hun_y, len_w) ) { + _stun_on_request(sun_u, hun_y, lan_u); + //c3_free(hun_y); + return c3y; + } + else if ( c3y == _stun_is_our_response(hun_y, + sun_u->tid_y, len_w) ) + { + _stun_on_response(sun_u, hun_y, len_w); + //c3_free(hun_y); + return c3y; + } + return c3n; +} + diff --git a/pkg/vere/io/ames/stun.h b/pkg/vere/io/ames/stun.h index 0fcaff6466..6ede01f798 100644 --- a/pkg/vere/io/ames/stun.h +++ b/pkg/vere/io/ames/stun.h @@ -1,35 +1,41 @@ #include "vere.h" +#include "c3/types.h" #ifndef U3_STUN_H #define U3_STUN_H - /* u3_stun_is_request(): buffer is a stun request. - */ - c3_o - u3_stun_is_request(c3_y* buf_y, c3_w len_w); - - /* u3_stun_is_our_response(): buffer is a response to our request. - */ - c3_o - u3_stun_is_our_response(c3_y* buf_y, c3_y tid_y[12], c3_w len_w); + typedef enum _u3_stun_state { + STUN_OFF = 0, + STUN_TRYING = 1, + STUN_KEEPALIVE = 2, + } u3_stun_state; + + typedef struct _u3_stun_client { // stun client state: + u3_auto* car_u; // driver backpointer + uv_udp_t* wax_u; + u3_stun_state sat_y; // formal state + c3_y tid_y[12]; // last transaction id + u3_ship dad_u; // sponsoring galaxy + sockaddr_in lan_u; // sponsoring galaxy IP and port + uv_timer_t tim_u; // keepalive timer handle + struct timeval sar_u; // date we started trying to send + sockaddr_in sef_u; // our lane, if we know it + c3_o wok_o; // STUN worked, set on first success + c3_o net_o; // online heuristic to limit verbosity + } u3_stun_client; // - /* u3_stun_make_request(): serialize stun request. + /* u3_stun_start(): begin/restart STUN state machine. */ void - u3_stun_make_request(c3_y buf_y[28], c3_y tid_y[12]); - - /* u3_stun_make_response(): serialize stun response from request. - */ - void - u3_stun_make_response(const c3_y req_y[20], - u3_lane* lan_u, - c3_y buf_y[40]); + u3_stun_start(u3_stun_client* sam_u, c3_w tim_w); - /* u3_stun_find_xor_mapped_address(): extract lane from response. + /* u3_stun_hear(): maybe hear stun packet */ c3_o - u3_stun_find_xor_mapped_address(c3_y* buf_y, - c3_w len_w, - u3_lane* lan_u); + u3_stun_hear(u3_stun_client* sun_u, + const struct sockaddr_in* adr_u, + c3_w len_w, + c3_y* hun_y); + #endif /* ifndef U3_STUN_H */ diff --git a/pkg/vere/io/conn.c b/pkg/vere/io/conn.c index 8e0c3bfbe6..61ca4c24e5 100644 --- a/pkg/vere/io/conn.c +++ b/pkg/vere/io/conn.c @@ -417,10 +417,12 @@ _conn_ovum_news(u3_ovum* egg_u, u3_ovum_news new_e) u3_chan* can_u = ran_u->can_u; if ( u3_ovum_done == new_e || - u3_ovum_drop == new_e ) + u3_ovum_drop == new_e || + u3_ovum_exit == new_e ) { if ( can_u ) { - _conn_send_noun(can_u, + if ( u3_ovum_exit != new_e ) + _conn_send_noun(can_u, u3nt(ran_u->rid, c3__news, ( u3_ovum_done == new_e ? c3__done @@ -549,7 +551,7 @@ _conn_read_peel(u3_conn* con_u, u3_noun dat) // current ship. // case c3__who: { - res = u3nc(u3_nul, u3i_chubs(2, pir_u->who_d)); + res = u3nc(u3_nul, u3_ship_to_noun(pir_u->who_u)); } } } @@ -724,7 +726,7 @@ _conn_init_sock(u3_shan* san_u) { #ifdef _WIN32 u3_pier* pir_u = san_u->con_u->car_u.pir_u; - u3_atom who = u3dc("scot", c3__p, u3i_chubs(2, pir_u->who_d)); + u3_atom who = u3dc("scot", c3__p, u3_ship_to_noun(pir_u->who_u)); c3_c* who_c = u3r_string(who); c3_c pip_c[256]; c3_i ret_i; diff --git a/pkg/vere/io/http.c b/pkg/vere/io/http.c index c58fbde303..4dfab91380 100644 --- a/pkg/vere/io/http.c +++ b/pkg/vere/io/http.c @@ -893,7 +893,7 @@ _get_beam(u3_hreq* req_u, c3_c* txt_c, c3_w len_w) if ( 0 == i_w ) { u3_http* htp_u = req_u->hon_u->htp_u; u3_httd* htd_u = htp_u->htd_u; - *wer = u3dc("scot", 'p', u3i_chubs(2, htd_u->car_u.pir_u->who_d)); + *wer = u3dc("scot", 'p', u3_ship_to_noun(htd_u->car_u.pir_u->who_u)); } else if ( 1 == i_w ) { *wer = c3__base; @@ -1037,7 +1037,7 @@ _http_req_dispatch(u3_hreq* req_u, u3_noun req) // peek or respond from cache // if ( c3y == req_u->peq_u->las_o ) { - u3_noun our = u3dc("scot", 'p', u3i_chubs(2, htd_u->car_u.pir_u->who_d)); + u3_noun our = u3dc("scot", 'p', u3_ship_to_noun(htd_u->car_u.pir_u->who_u)); if ( c3y == u3r_sing(our, bem.who) ) { u3_pier_peek_last(htd_u->car_u.pir_u, gang, c3__ex, u3k(bem.des), spur, req_u->peq_u, _http_scry_cb); @@ -3134,7 +3134,7 @@ u3_http_io_init(u3_pier* pir_u) { u3_noun key = u3dt("cat", 3, u3i_string("urbauth-"), - u3dc("scot", 'p', u3i_chubs(2, pir_u->who_d))); + u3dc("scot", 'p', u3_ship_to_noun(pir_u->who_u))); htd_u->fig_u.ses = u3_nul; htd_u->fig_u.key_c = u3r_string(key); u3z(key); diff --git a/pkg/vere/io/mesa.c b/pkg/vere/io/mesa.c index 2d71418945..8f1cb643c8 100644 --- a/pkg/vere/io/mesa.c +++ b/pkg/vere/io/mesa.c @@ -7,6 +7,8 @@ #include "ur/ur.h" #include "ship.h" #include "io/ames/stun.h" +#include "io/ames/nat.h" +#include "io/ames/lamp.h" #include "mesa/mesa.h" #include "mesa/bitset.h" #include @@ -16,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +26,7 @@ #include #include "lss.h" #include "arena.h" +#include "mdns.h" static c3_o dop_o = c3n; @@ -34,7 +38,7 @@ static c3_y are_y[524288]; /* #define PACKET_TEST c3y */ -// #define MESA_DEBUG c3y +//#define MESA_DEBUG c3y //#define MESA_TEST #define RED_TEXT "\033[0;31m" #define DEF_TEXT "\033[0m" @@ -92,47 +96,25 @@ typedef struct _u3_mesa_stat { struct _u3_mesa_pact; +typedef struct _u3_mesa u3_mesa; + typedef struct _u3_pact_stat { c3_y tie_y; // tries c3_d sen_d; // last sent c3_y sip_y; // skips } u3_pact_stat; -struct _u3_mesa; - -typedef struct _u3_gage { - c3_w rtt_w; // rtt - c3_w rto_w; // rto - c3_w rtv_w; // rttvar - c3_w wnd_w; // cwnd - c3_w wnf_w; // cwnd fraction - c3_w sst_w; // ssthresh - c3_w con_w; // counter - // -} u3_gage; - -struct _u3_mesa; - typedef struct _u3_mesa_pict { uv_udp_send_t snd_u; - struct _u3_mesa* sam_u; + struct _u3_mesa* mes_u; u3_mesa_pact pac_u; } u3_mesa_pict; -typedef struct _u3_lane_state { - c3_d sen_d; // last sent date - c3_d her_d; // last heard date - c3_w rtt_w; // round-trip time - c3_w rtv_w; // round-trip time variance -} u3_lane_state; - /* _u3_mesa: next generation networking */ typedef struct _u3_pit_addr u3_pit_addr; -typedef struct sockaddr_in sockaddr_in; - typedef struct _u3_pit_addr { sockaddr_in sdr_u; u3_pit_addr* nex_p; @@ -144,23 +126,6 @@ typedef struct _u3_pit_entry { arena are_u; } u3_pit_entry; -typedef struct _u3_shap { - c3_d hed_d; - c3_d tel_d; -} u3_shap; - - -static u3_shap u3_ship_to_shap( u3_ship ship ) -{ - return (u3_shap){ship[0], ship[1]}; -} - -static void u3_shap_to_ship( u3_ship ship, u3_shap shap ) -{ - ship[0] = shap.hed_d; - ship[1] = shap.tel_d; -} - static void u3_free_pit( u3_pit_entry* pit_u ) { arena_free(&pit_u->are_u); @@ -185,12 +150,12 @@ static uint64_t u3_cmpr_str( u3_str key1, u3_str key2 ) return key1.len_w == key2.len_w && memcmp( key1.str_c, key2.str_c, key1.len_w ) == 0; } -static uint64_t u3_cmpr_shap( u3_shap ship1, u3_shap ship2 ) +static uint64_t u3_cmpr_ship( u3_ship ship1, u3_ship ship2 ) { return ship1.hed_d == ship2.hed_d && ship1.tel_d == ship2.tel_d; } -static uint64_t u3_hash_shap(u3_shap ship) +static uint64_t u3_hash_ship(u3_ship ship) { uint64_t combined = ship.hed_d ^ (ship.tel_d * 0x9e3779b97f4a7c15ull); combined ^= combined >> 23; @@ -216,13 +181,6 @@ typedef struct _u3_pend_req u3_pend_req; #define VAL_DTOR_FN u3_free_pit #include "verstable.h" -#define NAME gag_map -#define KEY_TY u3_shap -#define HASH_FN u3_hash_shap -#define CMPR_FN u3_cmpr_shap -#define VAL_TY u3_gage* -#include "verstable.h" - typedef enum _u3_mesa_ctag { CTAG_WAIT = 1, CTAG_BLOCK = 2, @@ -266,29 +224,28 @@ static void u3_free_line( u3_mesa_line* lin_u ) #define VAL_TY u3_mesa_line* #include "verstable.h" -typedef struct _u3_peer u3_peer; - #define NAME per_map -#define KEY_TY u3_shap -#define HASH_FN u3_hash_shap -#define CMPR_FN u3_cmpr_shap +#define KEY_TY u3_ship +#define HASH_FN u3_hash_ship +#define CMPR_FN u3_cmpr_ship #define VAL_TY u3_peer* +#define IMPLEMENTATION_MODE #include "verstable.h" typedef struct _u3_mesa { u3_auto car_u; + void* sam_u; // ames pointer u3_pier* pir_u; - union { - uv_udp_t wax_u; - uv_handle_t had_u; - }; + union { // uv udp handle + uv_udp_t wax_u; // + uv_handle_t had_u; // + }; // u3_mesa_stat sat_u; // statistics c3_l sev_l; // XX: ?? c3_o for_o; // is forwarding per_map per_u; // (map ship u3_peer) c3_d jum_d; // bytes in jumbo cache jum_map jum_u; // jumbo cache - gag_map gag_u; // lane cache pit_map pit_u; // (map path [our=? las=(set lane)]) req_map req_u; // (map [rift path] u3_pend_req) c3_c* dns_c; // turf (urb.otrg) @@ -296,17 +253,15 @@ typedef struct _u3_mesa { arena are_u; // per packet arena arena par_u; // permanent arena uv_timer_t tim_u; // pit clear timer + u3_stun_client sun_u; // stun client state + u3_lamp_state lam_u; // lamp state + u3_natpmp_state nat_u; // natpmp state } u3_mesa; -typedef struct _u3_peer { - u3_mesa* sam_u; // backpointer - u3_ship her_u; // who is this peer - c3_o ful_o; // has this been initialized? - sockaddr_in dan_u; // direct lane (nullable) - u3_lane_state dir_u; // direct lane state - c3_y imp_y; // galaxy @p - u3_lane_state ind_u; // indirect lane state -} u3_peer; +STATIC_ASSERT( + ( ((void*)(u3_mesa*)(void*)0) == + ((void*)(u3_mesa*)(void*)&(((u3_mesa*)(void*)0)->car_u)) ), + "u3_mesa struct alignment" ); typedef struct _u3_pend_req { u3_peer* per_u; // backpointer @@ -321,7 +276,6 @@ typedef struct _u3_pend_req { c3_d out_d; // outstanding fragments in flight c3_d old_d; // frag num of oldest packet sent c3_d ack_d; // highest acked fragment number - u3_gage* gag_u; // congestion control lss_pair* mis_u; // misordered packets lss_verifier* los_u; // Lockstep verifier u3_mesa_pict* pic_u; // preallocated request packet @@ -354,18 +308,22 @@ typedef struct _u3_cace_enty { // instead just alloc new buffer and stick here typedef struct _u3_seal { uv_udp_send_t snd_u; // udp send request - u3_mesa* sam_u; + u3_mesa* mes_u; c3_w len_w; c3_y* buf_y; arena are_u; } u3_seal; typedef struct _u3_mesa_cb_data { - u3_mesa* sam_u; + u3_mesa* mes_u; u3_mesa_name nam_u; sockaddr_in lan_u; } u3_mesa_cb_data; +void _meet_peer(u3_mesa* mes_u, u3_peer* per_u); +static void _init_peer(u3_mesa* mes_u, u3_peer* per_u, u3_ship her_u); +static void _mesa_ef_saxo(u3_mesa* mes_u, u3_noun zad); + static c3_d get_millis() { struct timeval tp; @@ -400,9 +358,9 @@ _log_gage(u3_gage* gag_u) } static void -_log_lane(u3_lane* lan_u) +_log_lane(sockaddr_in* lan_u) { - u3l_log("mesa: lane (%s,%u)", u3r_string(u3dc("scot", c3__if, u3i_word(lan_u->pip_w))), lan_u->por_s); + u3l_log("mesa: lane (%s,%u)", u3r_string(u3dc("scot", c3__if, u3i_word(ntohl(lan_u->sin_addr.s_addr)))), ntohs(lan_u->sin_port)); } static void _log_peer(u3_peer* per_u) @@ -412,7 +370,9 @@ static void _log_peer(u3_peer* per_u) return; } u3l_log("dir"); - u3l_log("galaxy: %s", u3r_string(u3dc("scot", 'p', per_u->imp_y))); + c3_c* lam_c = u3_ship_to_string(per_u->lam_u); + u3l_log("galaxy: %s", lam_c); + c3_free(lam_c); } static void @@ -425,7 +385,7 @@ _log_pend_req(u3_pend_req* req_u) u3l_log("have: %"PRIu64, req_u->hav_d); u3l_log("next: %"PRIu64, req_u->nex_d); u3l_log("total: %" PRIu64, req_u->tof_d); - u3l_log("gage: %c", req_u->gag_u == NULL ? 'n' : 'y'); + //u3l_log("gage: %c", req_u->gag_u == NULL ? 'n' : 'y'); //u3l_log("timer in: %" PRIu64 " ms", uv_timer_get_due_in(&req_u->tim_u)); } @@ -445,7 +405,7 @@ _mesa_lop(c3_d fra_d) return fra_d & ~((1 << u3_Host.ops_u.jum_y) - 1); } -static c3_d +c3_d _get_now_micros() { struct timeval tim_u; @@ -464,17 +424,21 @@ _clamp_rto(c3_d rto_d) { return c3_min(c3_max(rto_d, 200 * 1000), 25000 * 1000); // ~s25 max backoff } -static inline c3_o +//static inline c3_o +c3_o _mesa_is_lane_zero(sockaddr_in lan_u) { - return __((lan_u.sin_addr.s_addr == 0) && (lan_u.sin_port == 0)); + return __( (lan_u.sin_addr.s_addr == _CZAR_GONE) + || ((lan_u.sin_addr.s_addr == 0) + && (lan_u.sin_port == 0)) ); } -static c3_o +c3_o _mesa_is_direct_mode(u3_peer* per_u) { c3_d now_d = _get_now_micros(); - return __(per_u->dir_u.her_d + DIRECT_ROUTE_TIMEOUT_MICROS > now_d); + return __( (c3y == per_u->lam_o) || + (per_u->dir_u.her_d + DIRECT_ROUTE_TIMEOUT_MICROS > now_d) ); } /* _mesa_encode_path(): produce buf_y as a parsed path @@ -543,7 +507,6 @@ static void _mesa_copy_name(u3_mesa_name* des_u, u3_mesa_name* src_u, arena* are_u) { memcpy(des_u, src_u, sizeof(u3_mesa_name)); - u3_ship_copy(des_u->her_u, src_u->her_u); des_u->str_u.str_c = new(are_u, c3_c, src_u->str_u.len_w); memcpy(des_u->str_u.str_c, src_u->str_u.str_c, src_u->str_u.len_w); des_u->pat_c = des_u->str_u.str_c + (src_u->pat_c - src_u->str_u.str_c); @@ -566,7 +529,7 @@ _dire_etch_ud(c3_d num_d) return u3i_bytes(26 - dif_w, buf_y); // XX known-non-null } -/* _mesa_request_key(): produce key for request hashtable sam_u->req_p from nam_u +/* _mesa_request_key(): produce key for request hashtable mes_u->req_p from nam_u */ u3_noun _mesa_request_key(u3_mesa_name* nam_u) @@ -576,20 +539,6 @@ _mesa_request_key(u3_mesa_name* nam_u) return res; } -static void -_init_gage(u3_gage* gag_u) // microseconds -{ - gag_u->rto_w = 200 * 1000; // ~s1 - gag_u->rtt_w = 1000 * 1000; // ~s1 - gag_u->rtv_w = 1000 * 1000; // ~s1 - /* gag_u->rto_w = 200 * 1000; // ~s1 */ - /* gag_u->rtt_w = 82 * 1000; // ~s1 */ - /* gag_u->rtv_w = 100 * 1000; // ~s1 */ - gag_u->con_w = 0; - gag_u->wnd_w = 1; - gag_u->sst_w = 10000; -} - /* u3_mesa_encode_lane(): serialize lane to noun */ static u3_noun @@ -600,24 +549,40 @@ u3_mesa_encode_lane(sockaddr_in lan_u) { return u3nt(c3__if, u3i_word(pip_w), por_s); } -static u3_peer* -_mesa_get_peer(u3_mesa* sam_u, u3_ship her) +u3_peer* +_mesa_get_peer(u3_mesa* mes_u, u3_ship her_u) +{ + per_map_itr itr_u = vt_get(&mes_u->per_u, her_u); + if ( vt_is_end(itr_u) ) { + return NULL; + } + return itr_u.data->val; +} + +u3_peer* +_mesa_gut_peer(u3_mesa* mes_u, u3_ship her_u) { - per_map_itr itr_u = vt_get(&sam_u->per_u, u3_ship_to_shap(her)); + per_map_itr itr_u = vt_get_or_insert(&mes_u->per_u, her_u, NULL); if ( vt_is_end(itr_u) ) { + fprintf(stderr, "mesa: cannot allocate memory for peer, dying"); return NULL; } + + if (NULL == itr_u.data->val) { + u3_peer* per_u = itr_u.data->val + = new(&mes_u->par_u, u3_peer, 1); + _init_peer(mes_u, per_u, her_u); + } return itr_u.data->val; } static void -_mesa_put_peer(u3_mesa* sam_u, u3_ship her_u, u3_peer* per_u) +_mesa_put_peer(u3_mesa* mes_u, u3_ship her_u, u3_peer* per_u) { - u3_shap him_u = u3_ship_to_shap(her_u); - per_map_itr itr_u = vt_get(&sam_u->per_u, him_u); + per_map_itr itr_u = vt_get(&mes_u->per_u, her_u); if ( vt_is_end(itr_u) ) { - itr_u = vt_insert(&sam_u->per_u, him_u, per_u); + itr_u = vt_insert(&mes_u->per_u, her_u, per_u); if ( vt_is_end(itr_u) ) { fprintf(stderr, "mesa: cannot allocate memory for peer, dying"); @@ -633,9 +598,9 @@ _mesa_put_peer(u3_mesa* sam_u, u3_ship her_u, u3_peer* per_u) * produces a NULL pointer if no pending request exists */ static u3_pend_req* -_mesa_get_request(u3_mesa* sam_u, u3_mesa_name* nam_u) { +_mesa_get_request(u3_mesa* mes_u, u3_mesa_name* nam_u) { u3_str key_u = {nam_u->pat_c, nam_u->pat_s}; - req_map_itr itr_u = vt_get(&sam_u->req_u, key_u); + req_map_itr itr_u = vt_get(&mes_u->req_u, key_u); if ( vt_is_end(itr_u) ) { return NULL; } @@ -649,16 +614,16 @@ _mesa_del_request_cb(uv_handle_t* han_u) { } static void -_mesa_del_request(u3_mesa* sam_u, u3_mesa_name* nam_u) { +_mesa_del_request(u3_mesa* mes_u, u3_mesa_name* nam_u) { u3_str key_u = {nam_u->pat_c, nam_u->pat_s}; - req_map_itr itr_u = vt_get(&sam_u->req_u, key_u); + req_map_itr itr_u = vt_get(&mes_u->req_u, key_u); if ( vt_is_end(itr_u) ) { return; } u3_pend_req* req_u = itr_u.data->val; - vt_erase(&sam_u->req_u, key_u); + vt_erase(&mes_u->req_u, key_u); if ( (u3_pend_req*)CTAG_WAIT != req_u ) { uv_timer_stop(&req_u->tim_u); req_u->tim_u.data = req_u; @@ -669,9 +634,9 @@ _mesa_del_request(u3_mesa* sam_u, u3_mesa_name* nam_u) { /* _mesa_put_request(): save new pending request state for nam_u */ static void -_mesa_put_request(u3_mesa* sam_u, u3_mesa_name* nam_u, u3_pend_req* req_u) { +_mesa_put_request(u3_mesa* mes_u, u3_mesa_name* nam_u, u3_pend_req* req_u) { u3_str key_u = {nam_u->pat_c, nam_u->pat_s}; - req_map_itr itr_u = vt_insert(&sam_u->req_u, key_u, req_u); + req_map_itr itr_u = vt_insert(&mes_u->req_u, key_u, req_u); if ( vt_is_end(itr_u) ) { fprintf(stderr, "mesa: cannot allocate memory for request, dying"); @@ -679,84 +644,27 @@ _mesa_put_request(u3_mesa* sam_u, u3_mesa_name* nam_u, u3_pend_req* req_u) { } } -/* _ames_czar_port(): udp port for galaxy. - XX copied from io/ames.c -*/ -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; - } -} - -static sockaddr_in -_mesa_get_direct_lane(u3_mesa* sam_u, u3_ship her_u) +sockaddr_in +_mesa_get_direct_lane(u3_mesa* mes_u, u3_ship her_u) { sockaddr_in adr_u = {0}; - adr_u.sin_family = AF_INET; - if ( c3__czar == u3_ship_rank(her_u) ) { - c3_s por_s = _ames_czar_port(her_u[0]); - adr_u.sin_addr.s_addr = htonl(u3_Host.imp_u[her_u[0]]); - adr_u.sin_port = htons(por_s); - return adr_u; - } - - per_map_itr itr_u = vt_get(&sam_u->per_u, u3_ship_to_shap(her_u)); + per_map_itr itr_u = vt_get(&mes_u->per_u, her_u); if ( vt_is_end(itr_u) ) { return adr_u; } adr_u = itr_u.data->val->dan_u; - return adr_u; } -static c3_o +c3_o _mesa_lanes_equal(sockaddr_in lan_u, sockaddr_in lon_u) { return __((lan_u.sin_addr.s_addr == lon_u.sin_addr.s_addr) && (lan_u.sin_port == lon_u.sin_port)); } -static sockaddr_in -_mesa_get_czar_lane(u3_mesa* sam_u, c3_y imp_y) -{ - c3_s por_s = _ames_czar_port(imp_y); - sockaddr_in adr_u = {0}; - adr_u.sin_family = AF_INET; - adr_u.sin_addr.s_addr = htonl(u3_Host.imp_u[imp_y]); - adr_u.sin_port = htons(por_s); - return adr_u; -} - -/* _mesa_get_lane(): get lane -*/ -static u3_gage* -_mesa_get_gage(u3_mesa* sam_u, u3_ship her_u) { - gag_map_itr itr_u = vt_get(&sam_u->gag_u, u3_ship_to_shap(her_u)); - if ( vt_is_end(itr_u) ) { - return NULL; - } - return itr_u.data->val; -} - -/* _mesa_put_gage(): put gage state in state - * -*/ -static void -_mesa_put_gage(u3_mesa* sam_u, u3_ship her_u, u3_gage* gag_u) -{ - gag_map_itr itr_u = vt_insert(&sam_u->gag_u, u3_ship_to_shap(her_u), gag_u); - if ( vt_is_end(itr_u) ) { - fprintf(stderr, "mesa: cannot allocate memory for gage, dying"); - u3_king_bail(); - } -} // congestion control update static void _mesa_handle_ack(u3_gage* gag_u, u3_pact_stat* pat_u) { @@ -802,13 +710,13 @@ _mesa_req_get_cwnd(u3_pend_req* req_u) { /* c3_w liv_w = bitset_wyt(&req_u->was_u); */ c3_w rem_w = _mesa_req_get_remaining(req_u); - /* u3l_log("rem_w %u wnd_w %u", rem_w, req_u->gag_u->wnd_w); */ + /* u3l_log("rem_w %u wnd_w %u", rem_w, req_u->per_u->gag_u.wnd_w); */ /* u3l_log("rem_w %u", rem_w); */ - /* u3l_log("wnd_w %u", req_u->gag_u->wnd_w); */ + /* u3l_log("wnd_w %u", req_u->per_u->gag_u.wnd_w); */ /* u3l_log("out_d %"PRIu64, req_u->out_d); */ /* return c3_min(rem_w, _safe_sub(3500, req_u->out_d)); */ - c3_d ava_d = _safe_sub((c3_d)req_u->gag_u->wnd_w, req_u->out_d); + c3_d ava_d = _safe_sub((c3_d)req_u->per_u->gag_u.wnd_w, req_u->out_d); return c3_min(rem_w, ava_d); /* return c3_min(rem_w, 5000 - req_u->out_d); */ } @@ -844,9 +752,9 @@ _mesa_req_pact_sent(u3_pend_req* req_u, c3_d fra_d, c3_d now_d) static void _mesa_alloc(uv_handle_t* had_u, size_t len_i, uv_buf_t* buf) { - u3_mesa* sam_u = (u3_mesa*)had_u->data; - sam_u->are_u.beg = (char*)are_y; - c3_c* ptr_v = new(&sam_u->are_u, c3_c, 400000); + u3_mesa* mes_u = (u3_mesa*)had_u->data; + mes_u->are_u.beg = (char*)are_y; + c3_c* ptr_v = new(&mes_u->are_u, c3_c, 400000); buf->base = ptr_v; buf->len = 400000; } @@ -890,14 +798,14 @@ static void _mesa_send_cb(uv_udp_send_t* req_u, c3_i sas_i) { u3_seal* sel_u = (u3_seal*)req_u; - u3_mesa* sam_u = sel_u->sam_u; + u3_mesa* mes_u = sel_u->mes_u; if ( sas_i ) { u3l_log("mesa: send fail_async: %s", uv_strerror(sas_i)); - //sam_u->fig_u.net_o = c3n; + //mes_u->fig_u.net_o = c3n; } else { - //sam_u->fig_u.net_o = c3y; + //mes_u->fig_u.net_o = c3y; } _mesa_free_seal(sel_u); @@ -908,7 +816,7 @@ _mesa_send_cb2(uv_udp_send_t* req_u, c3_i sas_i) { if ( sas_i ) { u3l_log("mesa: send fail_async: %s", uv_strerror(sas_i)); - //sam_u->fig_u.net_o = c3n; + //mes_u->fig_u.net_o = c3n; } c3_free(req_u); } @@ -925,14 +833,14 @@ _mesa_send_cb3(uv_udp_send_t* snt_u, c3_i sas_i) send_helper* snd_u = (send_helper*)snt_u; if ( sas_i ) { u3l_log("mesa: send fail_async: %s", uv_strerror(sas_i)); - //sam_u->fig_u.net_o = c3n; + //mes_u->fig_u.net_o = c3n; } else { /* _mesa_req_pact_sent(snd_u->req_u, snd_u->fra_d); */ } c3_free(snd_u); } -static c3_i _mesa_send_buf2(struct sockaddr** ads_u, uv_buf_t** bfs_u, c3_w* int_u, c3_w num_w) +static c3_i _mesa_send_buf2(u3_mesa* mes_u, struct sockaddr** ads_u, uv_buf_t** bfs_u, c3_w* int_u, c3_w num_w) { /* add_u.sin_family = AF_INET; */ @@ -945,7 +853,7 @@ static c3_i _mesa_send_buf2(struct sockaddr** ads_u, uv_buf_t** bfs_u, c3_w* int /* c3_c* sip_c = inet_ntoa(add_u.sin_addr); */ // u3l_log("mesa: sending packet to %s:%u", sip_c, por_s); #endif - c3_i sas_i = uv_udp_try_send2(&u3_Host.wax_u, num_w, bfs_u, int_u, ads_u, 0); + c3_i sas_i = uv_udp_try_send2(&mes_u->wax_u, num_w, bfs_u, int_u, ads_u, 0); if ( sas_i < 0 ) { u3l_log("ames: send fail_sync: %s", uv_strerror(sas_i)); return 0; @@ -954,11 +862,11 @@ static c3_i _mesa_send_buf2(struct sockaddr** ads_u, uv_buf_t** bfs_u, c3_w* int // else if ( sas_i < (c3_i)num_w) { // for ( c3_i i = sas_i; i < (c3_i)num_w; i++) { // uv_udp_send_t* req_u = c3_malloc(sizeof(*req_u)); -// uv_udp_send(req_u, &u3_Host.wax_u, bfs_u[i], 1, ads_u[0], _mesa_send_cb2); +// uv_udp_send(req_u, &mes_u->wax_u, bfs_u[i], 1, ads_u[0], _mesa_send_cb2); // } // } } -static void _mesa_send_buf3(sockaddr_in add_u, uv_buf_t buf_u) +static void _mesa_send_buf3(u3_mesa* mes_u, sockaddr_in add_u, uv_buf_t buf_u) { add_u.sin_addr.s_addr = ( u3_Host.ops_u.net == c3y ) ? add_u.sin_addr.s_addr : htonl(0x7f000001); @@ -977,20 +885,20 @@ static void _mesa_send_buf3(sockaddr_in add_u, uv_buf_t buf_u) uv_udp_send_t* snd_u = c3_malloc(sizeof(*snd_u)); c3_i sas_i = uv_udp_send((uv_udp_send_t*)snd_u, - &u3_Host.wax_u, + &mes_u->wax_u, &buf_u, 1, (const struct sockaddr*)&add_u, _mesa_send_cb3); if ( sas_i ) { u3l_log("ames: send fail_sync: %s", uv_strerror(sas_i)); - /*if ( c3y == sam_u->fig_u.net_o ) { - //sam_u->fig_u.net_o = c3n; + /*if ( c3y == mes_u->fig_u.net_o ) { + //mes_u->fig_u.net_o = c3n; }*/ } } -static void _mesa_send_buf(u3_mesa* sam_u, sockaddr_in add_u, c3_y* buf_y, c3_w len_w) +static void _mesa_send_buf(u3_mesa* mes_u, sockaddr_in add_u, c3_y* buf_y, c3_w len_w) { add_u.sin_addr.s_addr = ( u3_Host.ops_u.net == c3y ) ? add_u.sin_addr.s_addr : htonl(0x7f000001); @@ -1004,7 +912,7 @@ static void _mesa_send_buf(u3_mesa* sam_u, sockaddr_in add_u, c3_y* buf_y, c3_w u3_seal* sel_u = c3_calloc(sizeof(*sel_u)); sel_u->buf_y = buf_y; sel_u->len_w = len_w; - sel_u->sam_u = sam_u; + sel_u->mes_u = mes_u; @@ -1016,15 +924,15 @@ static void _mesa_send_buf(u3_mesa* sam_u, sockaddr_in add_u, c3_y* buf_y, c3_w uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, len_w); c3_i sas_i = uv_udp_send(&sel_u->snd_u, - &u3_Host.wax_u, + &mes_u->wax_u, &buf_u, 1, (const struct sockaddr*)&add_u, _mesa_send_cb); if ( sas_i ) { u3l_log("ames: send fail_sync: %s", uv_strerror(sas_i)); - /*if ( c3y == sam_u->fig_u.net_o ) { - //sam_u->fig_u.net_o = c3n; + /*if ( c3y == mes_u->fig_u.net_o ) { + //mes_u->fig_u.net_o = c3n; }*/ _mesa_free_seal(sel_u); } @@ -1032,14 +940,14 @@ static void _mesa_send_buf(u3_mesa* sam_u, sockaddr_in add_u, c3_y* buf_y, c3_w static void _mesa_send(u3_mesa_pict* pic_u, sockaddr_in lan_u) { - u3_mesa* sam_u = pic_u->sam_u; + u3_mesa* mes_u = pic_u->mes_u; c3_y *buf_y = c3_calloc(PACT_SIZE); c3_w len_w = mesa_etch_pact_to_buf(buf_y, PACT_SIZE, &pic_u->pac_u); - _mesa_send_buf(sam_u, lan_u, buf_y, len_w); + _mesa_send_buf(mes_u, lan_u, buf_y, len_w); } typedef struct _u3_mesa_request_data { - u3_mesa* sam_u; + u3_mesa* mes_u; u3_ship her_u; u3_mesa_name* nam_u; c3_y* buf_y; @@ -1072,7 +980,7 @@ _mesa_free_resend_data(u3_mesa_resend_data* res_u) } static void -_mesa_send_bufs(u3_mesa* sam_u, +_mesa_send_bufs(u3_mesa* mes_u, u3_peer* per_u, c3_y* buf_y, c3_w len_w, @@ -1081,41 +989,40 @@ _mesa_send_bufs(u3_mesa* sam_u, static void _mesa_send_modal(u3_peer* per_u, uv_buf_t buf_u, u3_pit_addr* las_u) { - u3_mesa* sam_u = per_u->sam_u; + u3_mesa* mes_u = per_u->mes_u; c3_d now_d = _get_now_micros(); c3_w len_w = buf_u.len; c3_y* sen_y = c3_calloc(len_w); memcpy(sen_y, buf_u.base, len_w); - u3_ship gal_u = {0}; - gal_u[0] = per_u->imp_y; - c3_o our_o = u3_ships_equal(gal_u, sam_u->pir_u->who_d); + u3_ship lam_u = per_u->lam_u; + c3_o our_o = u3_ships_equal(lam_u, mes_u->pir_u->who_u); if ( ( c3y == _mesa_is_direct_mode(per_u) ) || // if we are the sponsor of the ship, don't send to ourselves (our_o == c3y) ) { // u3l_log("mesa: direct"); - _mesa_send_buf(sam_u, per_u->dan_u, sen_y, len_w); + _mesa_send_buf(mes_u, per_u->dan_u, sen_y, len_w); per_u->dir_u.sen_d = now_d; } else if ( las_u != NULL ) { - _mesa_send_bufs(sam_u, per_u, sen_y, len_w, las_u); + _mesa_send_bufs(mes_u, per_u, sen_y, len_w, las_u); } else { #ifdef MESA_DEBUG - /* c3_c* gal_c = u3_ship_to_string(gal_u); */ + /* c3_c* gal_c = u3_ship_to_string(lam_u); */ // u3l_log("mesa: sending to %s", gal_c); /* c3_free(gal_c); */ #endif // - sockaddr_in imp_u = _mesa_get_czar_lane(sam_u, per_u->imp_y); - _mesa_send_buf(sam_u, imp_u, sen_y, len_w); + sockaddr_in ind_u = _mesa_get_direct_lane(mes_u, per_u->lam_u); + _mesa_send_buf(mes_u, ind_u, sen_y, len_w); per_u->ind_u.sen_d = now_d; if ( c3n == _mesa_is_lane_zero(per_u->dan_u) ) { c3_y* san_y = c3_calloc(len_w); memcpy(san_y, buf_u.base, len_w); - _mesa_send_buf(sam_u, per_u->dan_u, san_y, len_w); + _mesa_send_buf(mes_u, per_u->dan_u, san_y, len_w); per_u->dir_u.sen_d = now_d; } } @@ -1167,10 +1074,10 @@ _try_resend(u3_pend_req* req_u, c3_d nex_d) // TODO: make fast recovery different from slow // TODO: track skip count but not dupes, since dupes are meaningless if ( (c3n == bitset_has(&req_u->was_u, i_d)) && - (now_d - req_u->wat_u[i_d].sen_d > req_u->gag_u->rto_w) ) { + (now_d - req_u->wat_u[i_d].sen_d > req_u->per_u->gag_u.rto_w) ) { // u3l_log("now_d %"PRIu64, now_d); // u3l_log("sen_d %"PRIu64, req_u->wat_u[i_d].sen_d); - // u3l_log("rto_w %u", req_u->gag_u->rto_w); + // u3l_log("rto_w %u", req_u->per_u->gag_u.rto_w); los_o = c3y; /* u3l_log("resend fra_w: %llu", i_d); */ @@ -1182,7 +1089,7 @@ _try_resend(u3_pend_req* req_u, c3_d nex_d) /* new(&scr_u, uv_buf_t, 1); */ /* bfs_u[i_w] = buf_u; */ /* c3_w len_w = mesa_etch_pact_to_buf(buf_y, PACT_SIZE, pac_u); */ - /* _mesa_send_buf3(req_u->per_u->dan_u, buf_u, req_u, i_d); */ + /* _mesa_send_buf3(req_u->per_u->mes_u, req_u->per_u->dan_u, buf_u, req_u, i_d); */ _mesa_send_modal(req_u->per_u, buf_u, NULL); _mesa_req_pact_resent(req_u, &pac_u->pek_u.nam_u, now_d); // i_w++; @@ -1198,15 +1105,15 @@ _try_resend(u3_pend_req* req_u, c3_d nex_d) /* } */ if ( c3y == los_o ) { - /* _mesa_send_buf2(req_u->per_u->sam_u, ads_u, bus_u, int_u, i_w); */ - /* _mesa_send_buf2(req_u->per_u->sam_u, req_u->per_u->dan_u, bfs_u, i_w); */ - req_u->gag_u->sst_w = c3_max(1, req_u->gag_u->wnd_w / 2); - req_u->gag_u->wnd_w = req_u->gag_u->sst_w; - req_u->gag_u->rto_w = _clamp_rto(req_u->gag_u->rto_w * 2); + /* _mesa_send_buf2(req_u->per_u->mes_u, ads_u, bus_u, int_u, i_w); */ + /* _mesa_send_buf2(req_u->per_u->mes_u, req_u->per_u->dan_u, bfs_u, i_w); */ + req_u->per_u->gag_u.sst_w = c3_max(1, req_u->per_u->gag_u.wnd_w / 2); + req_u->per_u->gag_u.wnd_w = req_u->per_u->gag_u.sst_w; + req_u->per_u->gag_u.rto_w = _clamp_rto(req_u->per_u->gag_u.rto_w * 2); // u3l_log("loss"); // u3l_log("resent %u", i_w); // u3l_log("counter %u hav_d %"PRIu64 " nex_d %"PRIu64 " ack_d %"PRIu64 " lef_d %"PRIu64 " old_d %"PRIu64, req_u->los_u->counter, req_u->hav_d, req_u->nex_d, req_u->ack_d, req_u->lef_d, req_u->old_d); - // _log_gage(req_u->gag_u); + // _log_gage(&req_u->per_u->gag_u); } } @@ -1240,7 +1147,7 @@ _update_resend_timer(u3_pend_req *req_u) // c3_d gap_d = req_u->wat_u[idx_d].sen_d == 0 ? // 0 : // now_d - req_u->wat_u[idx_d].sen_d; - c3_d next_expiry = req_u->gag_u->rto_w; + c3_d next_expiry = req_u->per_u->gag_u.rto_w; // u3l_log("next_expiry %llu", next_expiry / 1000); // u3l_log("DUE %llu", uv_timer_get_due_in(&req_u->tim_u)); uv_timer_start(&req_u->tim_u, _mesa_packet_timeout, next_expiry / 1000, 0); @@ -1300,20 +1207,20 @@ _mesa_req_pact_done(u3_pend_req* req_u, c3_y hop_y, sockaddr_in lan_u) { - u3_mesa* sam_u = req_u->per_u->sam_u; // needed for the MESA_LOG macro + u3_mesa* mes_u = req_u->per_u->mes_u; // needed for the MESA_LOG macro // received past the end of the message if ( mesa_num_leaves(dat_u->tob_d) <= nam_u->fra_d ) { u3l_log("strange tob_d %"PRIu64" fra_d %"PRIu64" req_u %"PRIu64, dat_u->tob_d, nam_u->fra_d, req_u->hav_d); - MESA_LOG(sam_u, STRANGE); + MESA_LOG(mes_u, STRANGE); // XX: is this sufficient to drop whole request return; } // received duplicate if ( c3y == bitset_has(&req_u->was_u, nam_u->fra_d) ) { - // MESA_LOG(sam_u, DUPE); + // MESA_LOG(mes_u, DUPE); /* _update_resend_timer(req_u); */ return; } @@ -1337,7 +1244,7 @@ _mesa_req_pact_done(u3_pend_req* req_u, req_u->out_d--; bitset_put(&req_u->was_u, nam_u->fra_d); - _mesa_handle_ack(req_u->gag_u, &req_u->wat_u[nam_u->fra_d]); + _mesa_handle_ack(&req_u->per_u->gag_u, &req_u->wat_u[nam_u->fra_d]); /* _try_resend(req_u, nam_u->fra_d); */ /* _update_resend_timer(req_u); */ return; @@ -1345,13 +1252,13 @@ _mesa_req_pact_done(u3_pend_req* req_u, else if ( c3y != lss_verifier_ingest(req_u->los_u, dat_u->fra_y, dat_u->len_w, par_u) ) { u3l_log("auth fail frag %"PRIu64, nam_u->fra_d); u3l_log("nit_o %u", nam_u->nit_o); - _mesa_del_request(sam_u, nam_u); - MESA_LOG(sam_u, AUTH); + _mesa_del_request(mes_u, nam_u); + MESA_LOG(mes_u, AUTH); return; } else if ( c3y != _mesa_burn_misorder_queue(req_u, nam_u->boq_y, req_u->los_u->counter) ) { - MESA_LOG(sam_u, AUTH) - _mesa_del_request(sam_u, nam_u); + MESA_LOG(mes_u, AUTH) + _mesa_del_request(mes_u, nam_u); return; } else { @@ -1371,7 +1278,8 @@ _mesa_req_pact_done(u3_pend_req* req_u, u3_lane_state* sat_u; if ( 0 == hop_y && (c3n == _mesa_lanes_equal(lan_u, req_u->per_u->dan_u)) ) { - req_u->per_u->dan_u = lan_u; + if ( c3n == req_u->per_u->lam_o ) + req_u->per_u->dan_u = lan_u; sat_u = &req_u->per_u->dir_u; _init_lane_state(sat_u); } @@ -1381,26 +1289,28 @@ _mesa_req_pact_done(u3_pend_req* req_u, sat_u->her_d = _get_now_micros(); // handle gauge update - _mesa_handle_ack(req_u->gag_u, &req_u->wat_u[nam_u->fra_d]); + _mesa_handle_ack(&req_u->per_u->gag_u, &req_u->wat_u[nam_u->fra_d]); // XX FIXME? /* _try_resend(req_u, nam_u->fra_d); */ _update_resend_timer(req_u); } -static sockaddr_in -_realise_lane(u3_noun lan) { +/* _ames_czar_port(): udp port for galaxy. +*/ +c3_s +_ames_czar_port(c3_y imp_y); + +sockaddr_in +_mesa_realise_lane(u3_mesa* mes_u, u3_noun lan) { sockaddr_in lan_u = {0}; lan_u.sin_family = AF_INET; - if ( c3y == u3a_is_cat(lan) ) { + if ( c3y == u3a_is_atom(lan) ) { + lan_u = _mesa_get_direct_lane(mes_u, u3_ship_of_noun(lan)); // u3_assert( lan < 256 ); if ( (c3n == u3_Host.ops_u.net) ) { lan_u.sin_addr.s_addr = htonl(0x7f000001); - lan_u.sin_port = htons(_ames_czar_port(lan)); - } else { - lan_u.sin_addr.s_addr = htonl(u3_Host.imp_u[lan]); - lan_u.sin_port = htons(_ames_czar_port(lan)); } } else { u3_noun tag, pip, por; @@ -1419,7 +1329,7 @@ _realise_lane(u3_noun lan) { } static void -_mesa_send_bufs(u3_mesa* sam_u, +_mesa_send_bufs(u3_mesa* mes_u, u3_peer* per_u, // null for response packets c3_y* buf_y, c3_w len_w, @@ -1431,11 +1341,12 @@ _mesa_send_bufs(u3_mesa* sam_u, sockaddr_in lan_u = t->sdr_u; if ( !lan_u.sin_port ) { + // XX: noisy u3l_log("mesa: failed to realise lane"); } else { c3_y* sen_y = c3_calloc(len_w); memcpy(sen_y, buf_y, len_w); - _mesa_send_buf(sam_u, lan_u, sen_y, len_w); + _mesa_send_buf(mes_u, lan_u, sen_y, len_w); if ( per_u && (c3y == _mesa_lanes_equal(lan_u, per_u->dan_u)) ) { per_u->dir_u.sen_d = _get_now_micros(); } @@ -1445,9 +1356,9 @@ _mesa_send_bufs(u3_mesa* sam_u, } static u3_pit_entry* -_mesa_get_pit(u3_mesa* sam_u, u3_mesa_name* nam_u) +_mesa_get_pit(u3_mesa* mes_u, u3_mesa_name* nam_u) { - pit_map_itr itr_u = vt_get(&sam_u->pit_u, nam_u->str_u); + pit_map_itr itr_u = vt_get(&mes_u->pit_u, nam_u->str_u); if ( vt_is_end(itr_u) ) { return NULL; } @@ -1455,16 +1366,16 @@ _mesa_get_pit(u3_mesa* sam_u, u3_mesa_name* nam_u) } static void -_mesa_del_pit(u3_mesa* sam_u, u3_mesa_name* nam_u) +_mesa_del_pit(u3_mesa* mes_u, u3_mesa_name* nam_u) { /* u3l_log("deleting %llu", nam_u->fra_d); */ - vt_erase(&sam_u->pit_u, nam_u->str_u); + vt_erase(&mes_u->pit_u, nam_u->str_u); } static void -_mesa_add_lane_to_pit(u3_mesa* sam_u, u3_mesa_name* nam_u, sockaddr_in lan_u) +_mesa_add_lane_to_pit(u3_mesa* mes_u, u3_mesa_name* nam_u, sockaddr_in lan_u) { - pit_map_itr itr_u = vt_get(&sam_u->pit_u, nam_u->str_u); + pit_map_itr itr_u = vt_get(&mes_u->pit_u, nam_u->str_u); c3_d now_d = _get_now_micros(); @@ -1482,7 +1393,7 @@ _mesa_add_lane_to_pit(u3_mesa* sam_u, u3_mesa_name* nam_u, sockaddr_in lan_u) memcpy(str_c, nam_u->str_u.str_c, nam_u->str_u.len_w); u3_str str_u = {str_c, nam_u->str_u.len_w}; - itr_u = vt_insert(&sam_u->pit_u, str_u, ent_u); + itr_u = vt_insert(&mes_u->pit_u, str_u, ent_u); if ( vt_is_end(itr_u) ) { fprintf(stderr, "mesa: cannot allocate memory for pit, dying"); @@ -1517,7 +1428,7 @@ _mesa_resend_timer_cb(uv_timer_t* tim_u) u3_mesa_request_data* dat_u = &res_u->dat_u; res_u->ret_y--; - u3_pend_req* pit_u = _mesa_get_request(dat_u->sam_u, dat_u->nam_u); + u3_pend_req* pit_u = _mesa_get_request(dat_u->mes_u, dat_u->nam_u); if ( (u3_pend_req*)CTAG_WAIT != pit_u ) { #ifdef MESA_DEBUG // u3l_log("mesa: resend PIT entry gone %u", res_u->ret_y); @@ -1531,7 +1442,7 @@ _mesa_resend_timer_cb(uv_timer_t* tim_u) #endif } - _mesa_send_bufs(dat_u->sam_u, + _mesa_send_bufs(dat_u->mes_u, NULL, dat_u->buf_y, dat_u->len_w, @@ -1541,19 +1452,19 @@ _mesa_resend_timer_cb(uv_timer_t* tim_u) uv_timer_start(&res_u->tim_u, _mesa_resend_timer_cb, 1000, 0); } else { - _mesa_del_request(res_u->dat_u.sam_u, res_u->dat_u.nam_u); + _mesa_del_request(res_u->dat_u.mes_u, res_u->dat_u.nam_u); _mesa_free_resend_data(res_u); } } static u3_pit_addr* -_mesa_lanes_to_addrs(u3_noun las, arena* are_u) { +_mesa_lanes_to_addrs(u3_mesa* mes_u, u3_noun las, arena* are_u) { u3_pit_addr* adr_u = NULL; u3_noun lan, t = las; while ( t != u3_nul ) { u3x_cell(t, &lan, &t); u3_pit_addr* new_u = new(are_u, u3_pit_addr, 1); - new_u->sdr_u = _realise_lane(u3k(lan)); + new_u->sdr_u = _mesa_realise_lane(mes_u, u3k(lan)); new_u->nex_p = adr_u; adr_u = new_u; } @@ -1561,8 +1472,8 @@ _mesa_lanes_to_addrs(u3_noun las, arena* are_u) { } static void -_mesa_hear(u3_mesa* sam_u, - const struct sockaddr* adr_u, +_mesa_hear(u3_mesa* mes_u, + const struct sockaddr_in* adr_u, c3_w len_w, c3_y* hun_y); @@ -1574,7 +1485,7 @@ static void time_elapsed(c3_d fra_d, c3_d total, c3_d begin, c3_d end) } static void -packet_test(u3_mesa* sam_u, c3_c* fil_c) { +packet_test(u3_mesa* mes_u, c3_c* fil_c) { FILE* fd = fopen(fil_c, "rb"); fseek(fd, 0L, SEEK_END); c3_d sz = ftell(fd); @@ -1601,9 +1512,9 @@ packet_test(u3_mesa* sam_u, c3_c* fil_c) { c3_w len_w = *(c3_w*)(packets+i); /* u3l_log("len_w %u i %"PRIu64, len_w, i); */ i += 4; - _mesa_hear(sam_u, &adr_u, len_w, packets + i); + _mesa_hear(mes_u, (const sockaddr_in*)&adr_u, len_w, packets + i); /* tim_y[tidx] = _get_now_micros(); */ - sam_u->are_u.beg = (char*)are_y; + mes_u->are_u.beg = (char*)are_y; i += len_w; /* tidx++; */ } @@ -1617,7 +1528,7 @@ packet_test(u3_mesa* sam_u, c3_c* fil_c) { } static void -_mesa_ef_send(u3_mesa* sam_u, u3_noun las, u3_noun pac) +_mesa_ef_send(u3_mesa* mes_u, u3_noun las, u3_noun pac) { c3_w len_w = u3r_met(3, pac); arena are_u = arena_create(len_w + 16384); @@ -1635,7 +1546,7 @@ _mesa_ef_send(u3_mesa* sam_u, u3_noun las, u3_noun pac) return; } - u3_pend_req* old_u = _mesa_get_request(sam_u, &pac_u.pek_u.nam_u); + u3_pend_req* old_u = _mesa_get_request(mes_u, &pac_u.pek_u.nam_u); if (old_u) { u3z(pac); @@ -1645,7 +1556,7 @@ _mesa_ef_send(u3_mesa* sam_u, u3_noun las, u3_noun pac) } if ( PACT_PAGE == pac_u.hed_u.typ_y ) { - u3_pit_entry* pin_u = _mesa_get_pit(sam_u, &pac_u.pek_u.nam_u); + u3_pit_entry* pin_u = _mesa_get_pit(mes_u, &pac_u.pek_u.nam_u); if ( NULL == pin_u ) { arena_free(&are_u); @@ -1654,8 +1565,8 @@ _mesa_ef_send(u3_mesa* sam_u, u3_noun las, u3_noun pac) return; } - _mesa_send_bufs(sam_u, NULL, buf_y, len_w, pin_u->adr_u); - _mesa_del_pit(sam_u, &pac_u.pek_u.nam_u); + _mesa_send_bufs(mes_u, NULL, buf_y, len_w, pin_u->adr_u); + _mesa_del_pit(mes_u, &pac_u.pek_u.nam_u); arena_free(&are_u); } else { @@ -1664,10 +1575,10 @@ _mesa_ef_send(u3_mesa* sam_u, u3_noun las, u3_noun pac) u3_mesa_name* nam_u = _mesa_copy_name_alloc(&pac_u.pek_u.nam_u, &res_u->are_u); u3_mesa_request_data* dat_u = &res_u->dat_u; { - dat_u->sam_u = sam_u; - u3_ship_copy(dat_u->her_u, nam_u->her_u); + dat_u->mes_u = mes_u; + dat_u->her_u = nam_u->her_u; dat_u->nam_u = nam_u; - dat_u->las_u = _mesa_lanes_to_addrs(las, &res_u->are_u); + dat_u->las_u = _mesa_lanes_to_addrs(mes_u, las, &res_u->are_u); dat_u->buf_y = buf_y; dat_u->len_w = len_w; } @@ -1675,13 +1586,13 @@ _mesa_ef_send(u3_mesa* sam_u, u3_noun las, u3_noun pac) res_u->ret_y = 9; uv_timer_init(u3L, &res_u->tim_u); } - _mesa_put_request(sam_u, nam_u, (u3_pend_req*)CTAG_WAIT); + _mesa_put_request(mes_u, nam_u, (u3_pend_req*)CTAG_WAIT); res_u->tim_u.data = res_u; #ifdef PACKET_TEST - packet_test(sam_u, "pages.packs"); + packet_test(mes_u, "pages.packs"); #else - _mesa_send_bufs(sam_u, NULL, buf_y, len_w, dat_u->las_u); + _mesa_send_bufs(mes_u, NULL, buf_y, len_w, dat_u->las_u); uv_timer_start(&res_u->tim_u, _mesa_resend_timer_cb, 1000, 0); #endif } @@ -1691,21 +1602,39 @@ _mesa_ef_send(u3_mesa* sam_u, u3_noun las, u3_noun pac) } c3_o -_ames_kick_newt(void* sam_u, u3_noun tag, u3_noun dat); +_ames_kick_newt(void* mes_u, u3_noun tag, u3_noun dat); u3_atom -u3_ames_encode_lane(u3_lane lan); +u3_ames_encode_lane(sockaddr_in lan); + +void +_ames_ef_turf(u3_lamp_state* lam_u, u3_noun tuf); + +void +_ames_ef_fief(u3_lamp_state* lam_u, u3_noun fef); + +void +_ames_lane_into_cache(void* mes_u, u3_noun who, u3_noun las); -static void _meet_peer(u3_mesa* sam_u, u3_peer* per_u, u3_ship her_u); -static void _init_peer(u3_mesa* sam_u, u3_peer* per_u); -static c3_o _mesa_kick(u3_mesa* sam_u, u3_noun tag, u3_noun dat) +static c3_o _mesa_kick(u3_mesa* mes_u, u3_noun tag, u3_noun dat) { c3_o ret_o; switch ( tag ) { default: { ret_o = c3n; } break; + case c3__init: { + ret_o = c3y; + } break; + case c3__turf: { + _ames_ef_turf(&mes_u->lam_u, u3k(dat)); + ret_o = c3y; + } break; + case c3__fief: { + _ames_ef_fief(&mes_u->lam_u, u3k(dat)); + ret_o = c3y; + } break; case c3__push: { u3_noun las, pac; if ( c3n == u3r_cell(dat, &las, &pac) ) { @@ -1713,52 +1642,29 @@ static c3_o _mesa_kick(u3_mesa* sam_u, u3_noun tag, u3_noun dat) ret_o = c3n; } else { // u3l_log(" mesa: send new"); - _mesa_ef_send(sam_u, u3k(las), u3k(pac)); + _mesa_ef_send(mes_u, u3k(las), u3k(pac)); ret_o = c3y; } } break; - case c3__send: - case c3__turf: - case c3__saxo: { + case c3__send: { #ifdef MESA_DEBUG c3_c* tag_c = u3r_string(tag); /* u3l_log("mesa: send old %s", tag_c); */ c3_free(tag_c); #endif - ret_o = _ames_kick_newt(u3_Host.sam_u, u3k(tag), u3k(dat)); + ret_o = _ames_kick_newt(mes_u->sam_u, u3k(tag), u3k(dat)); } break; + case c3__saxo: { + _mesa_ef_saxo(mes_u, u3k(dat)); + ret_o = c3y; + break; + } case c3__nail: { - u3_ship who_u; - u3_ship_of_noun(who_u, u3h(dat)); - u3_peer* per_u = _mesa_get_peer(sam_u, who_u); - - if ( NULL == per_u ) { - per_u = new(&sam_u->par_u, u3_peer, 1); - _init_peer(sam_u, per_u); - } - - // XX the format of the lane %nail gives is (list (each @p address)) - // - u3_noun las = u3t(dat); - - if ( las == u3_nul ) { - per_u->dan_u = (sockaddr_in){0}; - } - else { - u3_noun lan = u3h(las); - // we either have a direct route, and a galaxy, or just one lane - if ( c3n == u3h(lan) ) { - sockaddr_in lan_u = u3_mesa_decode_lane(u3k(u3t(lan))); - per_u->dan_u = lan_u; - } else { - // delete direct lane if galaxy - per_u->dan_u = (sockaddr_in){0}; - } - } - - _meet_peer(sam_u, per_u, who_u); - - ret_o = _ames_kick_newt(u3_Host.sam_u, u3k(tag), u3k(dat)); + // TODO: remove? use callbacks + u3_noun who = u3k(u3h(dat)); + u3_noun las = u3k(u3t(dat)); + _ames_lane_into_cache(mes_u->sam_u, who, las); + ret_o = c3y; } break; } @@ -1768,9 +1674,12 @@ static c3_o _mesa_kick(u3_mesa* sam_u, u3_noun tag, u3_noun dat) return ret_o; } +c3_o +_ames_io_kick(void* sam_u, u3_noun wir, u3_noun cad); + static c3_o _mesa_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) { - u3_mesa* sam_u = (u3_mesa*)car_u; + u3_mesa* mes_u = (u3_mesa*)car_u; u3_noun tag, dat, i_wir; c3_o ret_o; @@ -1778,43 +1687,64 @@ static c3_o _mesa_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) || (c3__ames != i_wir) || (c3n == u3r_cell(cad, &tag, &dat)) ) { - ret_o = c3n; + ret_o = _ames_io_kick(mes_u->sam_u, u3k(wir), u3k(cad)); } else { - ret_o = _mesa_kick(sam_u, u3k(tag), u3k(dat)); + ret_o = _mesa_kick(mes_u, u3k(tag), u3k(dat)); } u3z(wir); u3z(cad); return ret_o; } +u3_noun +_ames_io_info(void* sam_u); + static u3_noun _mesa_io_info(u3_auto* car_u) { - - return u3_nul; + u3_mesa* mes_u = (u3_mesa*)car_u; + return u3kb_weld( + _ames_io_info(mes_u->sam_u), + u3i_list( + u3_pier_mase("stun-can-send", mes_u->sun_u.net_o), + u3_pier_mase("stun-working", mes_u->sun_u.wok_o), + u3_none) ); } +void +_ames_io_slog(void* sam_u); + static void _mesa_io_slog(u3_auto* car_u) { + u3_mesa* mes_u = (u3_mesa*)car_u; +# define FLAG(a) ( (c3y == a) ? "&" : "|" ) u3l_log("mesa is online"); + u3l_log(" stun:"); + u3l_log(" working: %s", FLAG(mes_u->sun_u.wok_o)); + u3l_log(" can send: %s", FLAG(mes_u->sun_u.net_o)); + _ames_io_slog(mes_u->sam_u); } +void +_ames_exit_cb(void* sam_u); + static void _mesa_exit_cb(uv_handle_t* han_u) { - u3_mesa* sam_u = (u3_mesa*)han_u->data; - arena_free(&sam_u->par_u); + u3_mesa* mes_u = (u3_mesa*)han_u->data; + _ames_exit_cb(mes_u->sam_u); + arena_free(&mes_u->par_u); } static void _mesa_io_exit(u3_auto* car_u) { - u3_mesa* sam_u = (u3_mesa*)car_u; - uv_timer_stop(&sam_u->tim_u); - sam_u->tim_u.data = sam_u; - uv_udp_recv_stop(&u3_Host.wax_u); - uv_close((uv_handle_t*)&sam_u->tim_u, _mesa_exit_cb); - uv_close((uv_handle_t*)&u3_Host.wax_u, 0); + u3_mesa* mes_u = (u3_mesa*)car_u; + uv_timer_stop(&mes_u->tim_u); + mes_u->tim_u.data = mes_u; + uv_udp_recv_stop(&mes_u->wax_u); + uv_close((uv_handle_t*)&mes_u->tim_u, _mesa_exit_cb); + uv_close((uv_handle_t*)&mes_u->wax_u, 0); } static void @@ -1827,14 +1757,30 @@ _init_lane_state(u3_lane_state* sat_u) } static void -_init_peer(u3_mesa* sam_u, u3_peer* per_u) +_init_gage(u3_gage* gag_u) // microseconds { - per_u->sam_u = sam_u; - per_u->ful_o = c3n; + gag_u->rto_w = 200 * 1000; // ~s1 + gag_u->rtt_w = 1000 * 1000; // ~s1 + gag_u->rtv_w = 1000 * 1000; // ~s1 + /* gag_u->rto_w = 200 * 1000; // ~s1 */ + /* gag_u->rtt_w = 82 * 1000; // ~s1 */ + /* gag_u->rtv_w = 100 * 1000; // ~s1 */ + gag_u->con_w = 0; + gag_u->wnd_w = 1; + gag_u->sst_w = 10000; +} +static void +_init_peer(u3_mesa* mes_u, u3_peer* per_u, u3_ship her_u) +{ + memset(per_u, 0, sizeof(*per_u)); + per_u->mes_u = mes_u; + per_u->liv_e = 0; + per_u->lam_o = c3n; per_u->dan_u = (sockaddr_in){0}; _init_lane_state(&per_u->dir_u); - per_u->imp_y = 0; + per_u->her_u = her_u; _init_lane_state(&per_u->ind_u); + _init_gage(&per_u->gag_u); } static u3_noun @@ -1871,13 +1817,13 @@ _name_to_jumbo_str(u3_mesa_name* nam_u, c3_y* buf_y) } static u3_mesa_line* -_mesa_get_jumbo_cache(u3_mesa* sam_u, u3_mesa_name* nam_u) +_mesa_get_jumbo_cache(u3_mesa* mes_u, u3_mesa_name* nam_u) { c3_y buf_y[PACT_SIZE]; c3_w len_w = _name_to_jumbo_str(nam_u, buf_y); u3_str str_u = {(c3_c*)buf_y, len_w}; - jum_map_itr itr_u = vt_get(&sam_u->jum_u, str_u); + jum_map_itr itr_u = vt_get(&mes_u->jum_u, str_u); if ( vt_is_end(itr_u) ) { return NULL; } @@ -1885,7 +1831,7 @@ _mesa_get_jumbo_cache(u3_mesa* sam_u, u3_mesa_name* nam_u) } static void -_mesa_put_jumbo_cache(u3_mesa* sam_u, u3_mesa_name* nam_u, u3_mesa_line* lin_u) +_mesa_put_jumbo_cache(u3_mesa* mes_u, u3_mesa_name* nam_u, u3_mesa_line* lin_u) { c3_y* buf_y = c3_malloc(PACT_SIZE); @@ -1894,15 +1840,15 @@ _mesa_put_jumbo_cache(u3_mesa* sam_u, u3_mesa_name* nam_u, u3_mesa_line* lin_u) // CTAG_BLOCK, CTAG_WAIT if ( lin_u > (u3_mesa_line*)2 ) { - if (sam_u->jum_d > JUMBO_CACHE_MAX_SIZE) { - vt_cleanup(&sam_u->jum_u); - sam_u->jum_d = 0; + if (mes_u->jum_d > JUMBO_CACHE_MAX_SIZE) { + vt_cleanup(&mes_u->jum_u); + mes_u->jum_d = 0; } - sam_u->jum_d += lin_u->tob_d; + mes_u->jum_d += lin_u->tob_d; } - jum_map_itr itr_u = vt_insert(&sam_u->jum_u, str_u, lin_u); + jum_map_itr itr_u = vt_insert(&mes_u->jum_u, str_u, lin_u); if ( vt_is_end(itr_u) ) { fprintf(stderr, "mesa: cannot allocate memory for jumbo cache, dying"); @@ -1911,28 +1857,28 @@ _mesa_put_jumbo_cache(u3_mesa* sam_u, u3_mesa_name* nam_u, u3_mesa_line* lin_u) } static void -_mesa_send_pact_single(u3_mesa* sam_u, +_mesa_send_pact_single(u3_mesa* mes_u, sockaddr_in adr_u, u3_mesa_pact* pac_u) { c3_y* buf_y = c3_calloc(PACT_SIZE); c3_w len_w = mesa_etch_pact_to_buf(buf_y, PACT_SIZE, pac_u); - _mesa_send_buf(sam_u, adr_u, buf_y, len_w); + _mesa_send_buf(mes_u, adr_u, buf_y, len_w); } static void -_mesa_send_pact(u3_mesa* sam_u, +_mesa_send_pact(u3_mesa* mes_u, u3_pit_addr* las_u, u3_peer* per_u, // null for response packets u3_mesa_pact* pac_u) { c3_y* buf_y = c3_calloc(PACT_SIZE); c3_w len_w = mesa_etch_pact_to_buf(buf_y, PACT_SIZE, pac_u); - _mesa_send_bufs(sam_u, per_u, buf_y, len_w, las_u); + _mesa_send_bufs(mes_u, per_u, buf_y, len_w, las_u); } static void -_mesa_send_leaf(u3_mesa* sam_u, +_mesa_send_leaf(u3_mesa* mes_u, u3_mesa_line* lin_u, u3_mesa_pact* pac_u, // scratchpad c3_d fra_d, @@ -1962,11 +1908,11 @@ _mesa_send_leaf(u3_mesa* sam_u, // u3l_log(" sending leaf packet, fra_d: %"PRIu64, nam_u->fra_d); #endif // log_pact(pac_u); - _mesa_send_pact_single(sam_u, adr_u, pac_u); + _mesa_send_pact_single(mes_u, adr_u, pac_u); } static void -_mesa_send_piece(u3_mesa* sam_u, u3_mesa_line* lin_u, u3_mesa_name* nam_u, c3_d fra_d, sockaddr_in adr_u) { +_mesa_send_piece(u3_mesa* mes_u, u3_mesa_line* lin_u, u3_mesa_name* nam_u, c3_d fra_d, sockaddr_in adr_u) { u3_mesa_pact pac_u = {0}; u3_mesa_head* hed_u = &pac_u.hed_u; { @@ -1993,20 +1939,20 @@ _mesa_send_piece(u3_mesa* sam_u, u3_mesa_line* lin_u, u3_mesa_name* nam_u, c3_d c3_y* pro_y = c3_malloc(dat_u->len_w); memcpy(pro_y, lin_u->tip_y, dat_u->len_w); dat_u->fra_y = pro_y; - _mesa_send_pact_single(sam_u, adr_u, &pac_u); + _mesa_send_pact_single(mes_u, adr_u, &pac_u); c3_free(pro_y); } // single-fragment message; just send the one data fragment else if ( 0 == fra_d ) { - _mesa_send_leaf(sam_u, lin_u, &pac_u, 0, adr_u); + _mesa_send_leaf(mes_u, lin_u, &pac_u, 0, adr_u); } else { u3l_log("mesa: weird fragment number %"PRIu64, fra_d); } } else { - _mesa_send_leaf(sam_u, lin_u, &pac_u, fra_d, adr_u); + _mesa_send_leaf(mes_u, lin_u, &pac_u, fra_d, adr_u); } } @@ -2015,21 +1961,21 @@ _mesa_page_scry_jumbo_cb(void* vod_p, u3_noun res) { u3_scry_handle* han_u = (u3_scry_handle*)vod_p; u3_mesa_cb_data* dat_u = (u3_mesa_cb_data*)han_u->vod_p; - u3_mesa* sam_u = dat_u->sam_u; + u3_mesa* mes_u = dat_u->mes_u; u3_mesa_name* nam_u = &dat_u->nam_u; u3_weak pag = u3r_at(7, res); if ( u3_none == pag ) { // TODO: mark as dead - u3_mesa_line* lin_u = _mesa_get_jumbo_cache(sam_u, nam_u); + u3_mesa_line* lin_u = _mesa_get_jumbo_cache(mes_u, nam_u); u3z(res); if ( NULL == lin_u ) { arena_free(&han_u->are_u); return; } lin_u = (u3_mesa_line*)CTAG_BLOCK; - _mesa_put_jumbo_cache(sam_u, nam_u, lin_u); + _mesa_put_jumbo_cache(mes_u, nam_u, lin_u); arena_free(&han_u->are_u); return; } @@ -2094,20 +2040,20 @@ _mesa_page_scry_jumbo_cb(void* vod_p, u3_noun res) } - _mesa_put_jumbo_cache(sam_u, nam_u, lin_u); + _mesa_put_jumbo_cache(mes_u, nam_u, lin_u); - u3_pit_entry* ent_u = _mesa_get_pit(sam_u, nam_u); + u3_pit_entry* ent_u = _mesa_get_pit(mes_u, nam_u); if ( NULL != ent_u ) { u3_pit_addr* adr_u = ent_u->adr_u; while (adr_u) { - _mesa_send_piece(sam_u, lin_u, nam_u, 0, adr_u->sdr_u); + _mesa_send_piece(mes_u, lin_u, nam_u, 0, adr_u->sdr_u); adr_u = adr_u->nex_p; } - _mesa_del_pit(sam_u, nam_u); + _mesa_del_pit(mes_u, nam_u); } - /* _mesa_send_jumbo_pieces(sam_u, lin_u, NULL); */ + /* _mesa_send_jumbo_pieces(mes_u, lin_u, NULL); */ u3z(res); arena_free(&han_u->are_u); @@ -2135,20 +2081,14 @@ _saxo_cb(void* vod_p, u3_noun nun) if ( sax != u3_none ) { u3_noun her = u3h(sax); - u3_ship her_u; - u3_ship_of_noun(her_u, her); - u3_peer* new_u = _mesa_get_peer(per_u->sam_u, her_u); - if ( new_u != NULL ) { - per_u = new_u; - } else { - _mesa_put_peer(per_u->sam_u, her_u, per_u); - } - u3_mesa* sam_u = per_u->sam_u; - u3_noun gal = u3do("rear", u3k(sax)); - u3_assert( c3y == u3a_is_cat(gal) && gal < 256 ); + u3_ship her_u = u3_ship_of_noun(her); + u3_mesa* mes_u = per_u->mes_u; + u3_noun lam = u3do("rear", u3k(sax)); + //u3_assert( c3y == u3a_is_cat(gal) && gal < 256 ); // both atoms guaranteed to be cats, bc we don't call unless forwarding - per_u->ful_o = c3y; - per_u->imp_y = gal; + per_u->lam_u = u3_ship_of_noun(lam); + per_u->liv_e |= u3_peer_lamp; + u3z(lam); } u3z(nun); @@ -2158,35 +2098,27 @@ static void _forward_lanes_cb(void* vod_p, u3_noun nun) { u3_peer* per_u = vod_p; - u3_mesa* sam_u = per_u->sam_u; + u3_mesa* mes_u = per_u->mes_u; u3_weak las = u3r_at(7, nun); // u3m_p("_forward_lanes_cb", las); if ( las != u3_none ) { - u3_peer* new_u = _mesa_get_peer(per_u->sam_u, per_u->her_u); - if ( new_u != NULL ) { - per_u = new_u; - } u3_noun gal = u3h(las); - u3_assert( c3y == u3a_is_cat(gal) && gal < 256 ); + //u3_assert( c3y == u3a_is_cat(gal) && gal < 256 ); // both atoms guaranteed to be cats, bc we don't call unless forwarding - per_u->ful_o = c3y; - per_u->imp_y = gal; - u3_noun sal = u3k(u3t(las)); - u3_noun lan; - while ( sal != u3_nul ) { - u3x_cell(sal, &lan, &sal); - - if ( c3n == u3a_is_cat(lan) ) { - // there should be only one lane that is not a direct atom - // - sockaddr_in lan_u = _realise_lane(u3k(lan)); - per_u->dan_u = lan_u; + per_u->liv_e |= u3_peer_lane; + per_u->lam_u = u3_ship_of_noun(gal); + u3_noun sal, tal; + + if ( c3n == per_u->lam_o ) { + if ( (c3y == u3r_cell(u3t(las), &sal, &tal)) && + (c3y == u3du(sal)) ) { + per_u->dan_u = _mesa_realise_lane(mes_u, u3k(sal)); + } else { + per_u->dan_u = (sockaddr_in){0}; } } - u3z(sal); - _mesa_put_peer(per_u->sam_u, per_u->her_u, per_u); } u3z(nun); @@ -2194,37 +2126,32 @@ _forward_lanes_cb(void* vod_p, u3_noun nun) } static void -_meet_peer(u3_mesa* sam_u, u3_peer* per_u, u3_ship her_u) +_meet_peer(u3_mesa* mes_u, u3_peer* per_u) { - u3_noun her = u3_ship_to_noun(her_u); + u3_noun her = u3_ship_to_noun(per_u->her_u); u3_noun gan = u3nc(u3_nul, u3_nul); - per_u->her_u[0] = her_u[0]; - per_u->her_u[1] = her_u[1]; - - u3_noun pax = u3nc(u3dc("scot", c3__p, her), u3_nul); - u3_pier_peek_last(sam_u->pir_u, gan, c3__j, c3__saxo, pax, per_u, _saxo_cb); - -} + if ( !(u3_peer_lamp & per_u->liv_e) ) { + u3_noun pax = u3nc(u3dc("scot", c3__p, u3k(her)), u3_nul); + u3_pier_peek_last(mes_u->pir_u, u3k(gan), c3__j, c3__saxo, pax, per_u, _saxo_cb); + } -static void -_get_peer_lanes(u3_mesa* sam_u, u3_peer* per_u) -{ - u3_noun her = u3_ship_to_noun(per_u->her_u); - u3_noun gan = u3nc(u3_nul, u3_nul); - u3_noun pax = u3nq(u3i_string("chums"), - u3dc("scot", 'p', her), - u3i_string("lanes"), - u3_nul); - u3m_p("pax", pax); - u3_pier_peek_last(sam_u->pir_u, gan, c3__ax, u3_nul, pax, per_u, _forward_lanes_cb); + if ( !(u3_peer_lane & per_u->liv_e) ) { + u3_noun pax = u3nq(u3i_string("chums"), + u3dc("scot", 'p', u3k(her)), + u3i_string("lanes"), + u3_nul); + u3_pier_peek_last(mes_u->pir_u, u3k(gan), c3__ax, u3_nul, pax, per_u, _forward_lanes_cb); + } + u3z(her); u3z(gan); } static void -_hear_peer(u3_mesa* sam_u, u3_peer* per_u, sockaddr_in lan_u, c3_o dir_o) +_hear_peer(u3_mesa* mes_u, u3_peer* per_u, sockaddr_in lan_u, c3_o dir_o) { if ( c3y == dir_o ) { - per_u->dan_u = lan_u; + if ( c3n == per_u->lam_o ) + per_u->dan_u = lan_u; per_u->dir_u.her_d = _get_now_micros(); } else { per_u->ind_u.her_d = _get_now_micros(); @@ -2232,7 +2159,7 @@ _hear_peer(u3_mesa* sam_u, u3_peer* per_u, sockaddr_in lan_u, c3_o dir_o) } static void -_mesa_request_next_fragments(u3_mesa* sam_u, +_mesa_request_next_fragments(u3_mesa* mes_u, u3_pend_req* req_u, sockaddr_in lan_u) { @@ -2272,7 +2199,7 @@ _mesa_request_next_fragments(u3_mesa* sam_u, /* _mesa_send(nex_u, lan_u); */ } /* if ( i > 0 ) { */ - /* c3_i sen_i = _mesa_send_buf2(ads_u, bus_u, int_u, i); */ + /* c3_i sen_i = _mesa_send_buf2(req_u->per_u->mes_u, ads_u, bus_u, int_u, i); */ /* for (c3_w i = 0; i < sen_i; i++) { */ /* c3_w fra_w = nex_d + i; */ /* _mesa_req_pact_sent(req_u, fra_w, now_d); */ @@ -2285,12 +2212,12 @@ _mesa_veri_scry_cb(void* vod_p, u3_noun nun) { u3_mesa_cb_data* ver_u = vod_p; #ifndef PACKET_TEST - u3_pend_req* req_u = _mesa_get_request(ver_u->sam_u, &ver_u->nam_u); + u3_pend_req* req_u = _mesa_get_request(ver_u->mes_u, &ver_u->nam_u); if ( !req_u ) { return; } else if ( c3y == nun ) { // XX - _mesa_request_next_fragments(ver_u->sam_u, req_u, ver_u->lan_u); + _mesa_request_next_fragments(ver_u->mes_u, req_u, ver_u->lan_u); } else if ( c3n == nun ) { u3l_log("mesa: packet auth failed verification"); @@ -2305,21 +2232,13 @@ _mesa_veri_scry_cb(void* vod_p, u3_noun nun) } static void -_mesa_req_pact_init(u3_mesa* sam_u, u3_mesa_pict* pic_u, sockaddr_in lan_u, u3_peer* per_u) +_mesa_req_pact_init(u3_mesa* mes_u, u3_mesa_pict* pic_u, sockaddr_in lan_u, u3_peer* per_u) { - sam_u->tim_d = _get_now_micros(); + mes_u->tim_d = _get_now_micros(); u3_mesa_pact* pac_u = &pic_u->pac_u; u3_mesa_name* nam_u = &pac_u->pag_u.nam_u; u3_mesa_data* dat_u = &pac_u->pag_u.dat_u; - u3_gage* gag_u = _mesa_get_gage(sam_u, nam_u->her_u); - if ( gag_u == NULL ) { - gag_u = new(&sam_u->par_u, u3_gage, 1); - _init_gage(gag_u); - _mesa_put_gage(sam_u, nam_u->her_u, gag_u); - u3_assert( gag_u != NULL ); - } - // _log_gage(gag_u); u3_mesa_pact exa_u; exa_u.hed_u.typ_y = PACT_PEEK; @@ -2336,7 +2255,7 @@ _mesa_req_pact_init(u3_mesa* sam_u, u3_mesa_pict* pic_u, sockaddr_in lan_u, u3_p u3_pend_req* req_u = new(&are_u, u3_pend_req, 1); req_u->are_u = are_u; req_u->pic_u = new(&req_u->are_u, u3_mesa_pict, 1); - req_u->pic_u->sam_u = sam_u; + req_u->pic_u->mes_u = mes_u; req_u->pic_u->pac_u.hed_u.typ_y = PACT_PEEK; req_u->pic_u->pac_u.hed_u.pro_y = MESA_VER; req_u->pic_u->pac_u.pek_u.nam_u = *(_mesa_copy_name_alloc(nam_u, &req_u->are_u)); @@ -2347,7 +2266,6 @@ _mesa_req_pact_init(u3_mesa* sam_u, u3_mesa_pict* pic_u, sockaddr_in lan_u, u3_p uv_timer_init(u3L, &req_u->tim_u); u3_assert( pac_u->pag_u.nam_u.boq_y == 13 ); - req_u->gag_u = gag_u; req_u->tob_d = dat_u->tob_d; /* req_u->out_d = 4000; */ req_u->out_d = 0; @@ -2386,7 +2304,7 @@ _mesa_req_pact_init(u3_mesa* sam_u, u3_mesa_pict* pic_u, sockaddr_in lan_u, u3_p req_u->per_u = per_u; - _mesa_put_request(sam_u, &req_u->pic_u->pac_u.pek_u.nam_u, req_u); + _mesa_put_request(mes_u, &req_u->pic_u->pac_u.pek_u.nam_u, req_u); _update_resend_timer(req_u); // scry to verify auth @@ -2408,19 +2326,19 @@ _mesa_req_pact_init(u3_mesa* sam_u, u3_mesa_pict* pic_u, sockaddr_in lan_u, u3_p u3_noun pax = _mesa_encode_path(nam_u->pat_s, (c3_y*)nam_u->pat_c); u3_noun sky = u3i_list(typ, her, aut, rut, pax, u3_none); u3_mesa_cb_data* ver_u = c3_malloc(sizeof(u3_mesa_cb_data)); - ver_u->sam_u = sam_u; + ver_u->mes_u = mes_u; ver_u->nam_u = req_u->pic_u->pac_u.pek_u.nam_u; ver_u->lan_u = lan_u; - u3_pier_peek_last(sam_u->pir_u, u3_nul, c3__a, c3__veri, sky, ver_u, _mesa_veri_scry_cb); + u3_pier_peek_last(mes_u->pir_u, u3_nul, c3__a, c3__veri, sky, ver_u, _mesa_veri_scry_cb); } typedef struct _u3_mesa_lane_cb_data { - u3_lane lan_u; + sockaddr_in lan_u; u3_peer* per_u; } u3_mesa_lane_cb_data; static void -_mesa_page_bail_cb(u3_ovum* egg_u, u3_ovum_news new_e) +_mesa_page_bail_cb(u3_ovum* egg_u, u3_noun why) { u3l_log("mesa: arvo page event failed"); } @@ -2448,27 +2366,19 @@ _mesa_add_hop(c3_y hop_y, u3_mesa_head* hed_u, u3_mesa_page_pact* pag_u, sockadd /* } */ static void -_mesa_forward_request(u3_mesa* sam_u, u3_mesa_pict* pic_u, sockaddr_in lan_u) +_mesa_forward_request(u3_mesa* mes_u, u3_mesa_pict* pic_u, sockaddr_in lan_u) { u3_mesa_pact* pac_u = &pic_u->pac_u; - u3_peer* per_u = _mesa_get_peer(sam_u, pac_u->pek_u.nam_u.her_u); - if ( !per_u ) { - #ifdef MESA_DEBUG - c3_c* mes = u3_ship_to_string(pac_u->pek_u.nam_u.her_u); - u3l_log("mesa: alien forward for %s; meeting ship", mes); - c3_free(mes); - #endif - per_u = new(&sam_u->par_u, u3_peer, 1); - _init_peer(sam_u, per_u); - per_u->her_u[0] = pac_u->pek_u.nam_u.her_u[0]; - per_u->her_u[1] = pac_u->pek_u.nam_u.her_u[1]; - - _get_peer_lanes(sam_u, per_u); // forward-lanes - return; + u3_peer* per_u = _mesa_gut_peer(mes_u, pac_u->pek_u.nam_u.her_u); + if ( u3_peer_full != per_u->liv_e ) { + _meet_peer(mes_u, per_u); + return; } - if ( c3y == sam_u->for_o && sam_u->pir_u->who_d[0] == per_u->imp_y ) { - // if ( c3y == sam_u->for_o ) { - sockaddr_in lin_u = _mesa_get_direct_lane(sam_u, pac_u->pek_u.nam_u.her_u); + + if ( c3y == mes_u->for_o && + c3y == u3_ships_equal(mes_u->pir_u->who_u, per_u->lam_u) ) { + // if ( c3y == mes_u->for_o ) { + sockaddr_in lin_u = _mesa_get_direct_lane(mes_u, pac_u->pek_u.nam_u.her_u); if ( _mesa_is_lane_zero(lin_u) == c3y) { c3_c* shp_c = u3_ship_to_string(pac_u->pek_u.nam_u.her_u); u3l_log("zero lane for %s", shp_c); @@ -2486,7 +2396,7 @@ _mesa_forward_request(u3_mesa* sam_u, u3_mesa_pict* pic_u, sockaddr_in lan_u) u3l_log("mesa: sending packet to %s:%u", sip_c, ntohs(lin_u.sin_port)); #endif - _mesa_add_lane_to_pit(sam_u, &pac_u->pek_u.nam_u, lan_u); + _mesa_add_lane_to_pit(mes_u, &pac_u->pek_u.nam_u, lan_u); _mesa_send(pic_u, lin_u); } } @@ -2500,19 +2410,17 @@ _mesa_hear_page(u3_mesa_pict* pic_u, sockaddr_in lan_u) u3_assert( PACT_PAGE == pic_u->pac_u.hed_u.typ_y ); #endif - u3_mesa* sam_u = pic_u->sam_u; + u3_mesa* mes_u = pic_u->mes_u; u3_mesa_pact* pac_u = &pic_u->pac_u; u3_mesa_name* nam_u = &pac_u->pag_u.nam_u; - c3_o our_o = u3_ships_equal(nam_u->her_u, sam_u->pir_u->who_d); + c3_o our_o = u3_ships_equal(nam_u->her_u, mes_u->pir_u->who_u); - u3_peer* per_u = _mesa_get_peer(sam_u, nam_u->her_u); + u3_peer* per_u = _mesa_gut_peer(mes_u, nam_u->her_u); c3_o new_o = c3n; - if ( NULL == per_u ) { - new_o = c3y; - per_u = new(&sam_u->par_u, u3_peer, 1); - _init_peer(sam_u, per_u); - _meet_peer(sam_u, per_u, nam_u->her_u); + if ( u3_peer_full != per_u->liv_e ) { + _meet_peer(mes_u, per_u); + return; } c3_o dir_o = __(pac_u->hed_u.hop_y == 0); @@ -2521,16 +2429,20 @@ _mesa_hear_page(u3_mesa_pict* pic_u, sockaddr_in lan_u) // } else { // u3l_log(" received forwarded page"); // } - _hear_peer(sam_u, per_u, lan_u, dir_o); + // XX: we haven't validated the packet yet + // maybe what we should do is move away from nails (joe says it's bad io overhead) + // and only scry lanes if peer is NULL, and do all of our updating in our callbacks + // (what the nail would be, by looking at peer state and the hops data) + _hear_peer(mes_u, per_u, lan_u, dir_o); if ( new_o == c3y ) { //u3l_log("new lane is direct %c", c3y == dir_o ? 'y' : 'n'); //_log_lane(&lan_u); } - _mesa_put_peer(sam_u, nam_u->her_u, per_u); + _mesa_put_peer(mes_u, nam_u->her_u, per_u); - u3_pit_entry* pin_u = _mesa_get_pit(sam_u, nam_u); + u3_pit_entry* pin_u = _mesa_get_pit(mes_u, nam_u); if ( NULL != pin_u ) { #ifdef MESA_DEBUG @@ -2545,12 +2457,12 @@ _mesa_hear_page(u3_mesa_pict* pic_u, sockaddr_in lan_u) _mesa_add_hop(pac_u->hed_u.hop_y, &pac_u->hed_u, &pac_u->pag_u, lan_u); - _mesa_send_pact(sam_u, pin_u->adr_u, NULL, pac_u); - _mesa_del_pit(sam_u, nam_u); + _mesa_send_pact(mes_u, pin_u->adr_u, NULL, pac_u); + _mesa_del_pit(mes_u, nam_u); } c3_d lev_d = mesa_num_leaves(pac_u->pag_u.dat_u.tob_d); - u3_pend_req* req_u = _mesa_get_request(sam_u, nam_u); + u3_pend_req* req_u = _mesa_get_request(mes_u, nam_u); if ( !req_u ) { return; } @@ -2576,19 +2488,19 @@ _mesa_hear_page(u3_mesa_pict* pic_u, sockaddr_in lan_u) u3_noun wir = u3nc(c3__ames, u3_nul); u3_ovum* ovo = u3_ovum_init(0, c3__ames, wir, cad); - ovo = u3_auto_plan(&sam_u->car_u, ovo); + ovo = u3_auto_plan(&mes_u->car_u, ovo); // early deletion, to avoid injecting retries, // (in case of failure, the retry timer will add it again to the PIT) // - _mesa_del_request(sam_u, nam_u); + _mesa_del_request(mes_u, nam_u); u3_auto_peer(ovo, 0, 0, _mesa_page_bail_cb); return; } c3_d now_d = _get_now_micros(); - _mesa_req_pact_init(sam_u, pic_u, lan_u, per_u); + _mesa_req_pact_init(mes_u, pic_u, lan_u, per_u); return; } @@ -2626,7 +2538,7 @@ _mesa_hear_page(u3_mesa_pict* pic_u, sockaddr_in lan_u) /* c3_d now_d = _get_now_micros(); */ /* u3l_log("%" PRIu64 " kilobytes took %f ms", */ /* req_u->tof_d, */ - /* (now_d - sam_u->tim_d)/1000.0); */ + /* (now_d - mes_u->tim_d)/1000.0); */ // u3l_log("page handling took %"PRIu64, avg_time()); //done = c3y; @@ -2652,15 +2564,15 @@ _mesa_hear_page(u3_mesa_pict* pic_u, sockaddr_in lan_u) } - _mesa_del_request(sam_u, &pac_u->pag_u.nam_u); + _mesa_del_request(mes_u, &pac_u->pag_u.nam_u); - u3_auto_plan(&sam_u->car_u, + u3_auto_plan(&mes_u->car_u, u3_ovum_init(0, c3__ames, u3nc(c3__ames, u3_nul), cad)); #else - _mesa_del_request(sam_u, &pac_u->pag_u.nam_u); + _mesa_del_request(mes_u, &pac_u->pag_u.nam_u); #endif } else if ( req_u->hav_d < lev_d ) { - _mesa_request_next_fragments(sam_u, req_u, lan_u); + _mesa_request_next_fragments(mes_u, req_u, lan_u); } } @@ -2673,11 +2585,10 @@ _mesa_hear_peek(u3_mesa_pict* pic_u, sockaddr_in lan_u) #endif u3_mesa_pact* pac_u = &pic_u->pac_u; - u3_mesa* sam_u = pic_u->sam_u; - c3_o our_o = u3_ships_equal(pac_u->pek_u.nam_u.her_u, sam_u->pir_u->who_d); - + u3_mesa* mes_u = pic_u->mes_u; + c3_o our_o = u3_ships_equal(pac_u->pek_u.nam_u.her_u, mes_u->pir_u->who_u); if ( c3n == our_o ) { - _mesa_forward_request(sam_u, pic_u, lan_u); + _mesa_forward_request(mes_u, pic_u, lan_u); return; } @@ -2689,28 +2600,28 @@ _mesa_hear_peek(u3_mesa_pict* pic_u, sockaddr_in lan_u) /* u3l_log("hear peek fra %llu", fra_d); */ // if we have the page, send it - u3_mesa_line* lin_u = _mesa_get_jumbo_cache(sam_u, &pac_u->pek_u.nam_u); + u3_mesa_line* lin_u = _mesa_get_jumbo_cache(mes_u, &pac_u->pek_u.nam_u); if ( ( (u3_mesa_line*)CTAG_WAIT == lin_u )) { return; } if ( ( NULL != lin_u && (u3_mesa_line*)CTAG_BLOCK != lin_u)) { - _mesa_send_piece(sam_u, lin_u, &pac_u->pek_u.nam_u, fra_d, lan_u); + _mesa_send_piece(mes_u, lin_u, &pac_u->pek_u.nam_u, fra_d, lan_u); return; } // record interest - _mesa_add_lane_to_pit(sam_u, &pac_u->pek_u.nam_u, lan_u); + _mesa_add_lane_to_pit(mes_u, &pac_u->pek_u.nam_u, lan_u); // otherwise, if blocked or NULL scry lin_u = (u3_mesa_line*)CTAG_WAIT; /* _mesa_copy_name(&lin_u->nam_u, &pac_u->pek_u.nam_u); // XX */ - _mesa_put_jumbo_cache(sam_u, &pac_u->pek_u.nam_u, lin_u); + _mesa_put_jumbo_cache(mes_u, &pac_u->pek_u.nam_u, lin_u); u3_noun sky = _name_to_jumbo_scry(&pac_u->pek_u.nam_u); - u3_noun our = u3i_chubs(2, sam_u->car_u.pir_u->who_d); + u3_noun our = u3_ship_to_noun(mes_u->car_u.pir_u->who_u); u3_noun bem = u3nc(u3nt(our, u3_nul, u3nc(c3__ud, 1)), sky); arena are_u = arena_create(sizeof(u3_mesa_cb_data) + 1024); @@ -2718,10 +2629,10 @@ _mesa_hear_peek(u3_mesa_pict* pic_u, sockaddr_in lan_u) han_u->are_u = are_u; u3_mesa_cb_data* dat_u = new(&han_u->are_u, u3_mesa_cb_data, 1); han_u->vod_p = dat_u; - dat_u->sam_u = sam_u; + dat_u->mes_u = mes_u; _mesa_copy_name(&dat_u->nam_u, &pac_u->pek_u.nam_u, &han_u->are_u); - u3_pier_peek(sam_u->car_u.pir_u, u3_nul, u3k(u3nq(1, c3__beam, c3__ax, bem)), han_u, _mesa_page_scry_jumbo_cb); + u3_pier_peek(mes_u->car_u.pir_u, u3_nul, u3k(u3nq(1, c3__beam, c3__ax, bem)), han_u, _mesa_page_scry_jumbo_cb); } static void @@ -2735,37 +2646,35 @@ static void _mesa_hear_poke(u3_mesa_pict* pic_u, sockaddr_in lan_u) { u3_mesa_pact* pac_u = &pic_u->pac_u; - u3_mesa* sam_u = pic_u->sam_u; + u3_mesa* mes_u = pic_u->mes_u; #ifdef MESA_DEBUG u3l_log("mesa: hear_poke()"); u3_assert( PACT_POKE == pac_u->hed_u.typ_y ); #endif - c3_o our_o = u3_ships_equal(pac_u->pek_u.nam_u.her_u, sam_u->pir_u->who_d); + c3_o our_o = u3_ships_equal(pac_u->pek_u.nam_u.her_u, mes_u->pir_u->who_u); if ( c3n == our_o ) { - _mesa_forward_request(sam_u, pic_u, lan_u); + _mesa_forward_request(mes_u, pic_u, lan_u); return; } // TODO check if lane already in pit, drop dupes - _mesa_add_lane_to_pit(sam_u, &pac_u->pek_u.nam_u, lan_u); + _mesa_add_lane_to_pit(mes_u, &pac_u->pek_u.nam_u, lan_u); // XX if this lane management stuff is necessary // it should be deferred to after successful event processing - u3_peer* per_u = _mesa_get_peer(sam_u, pac_u->pok_u.pay_u.her_u); + u3_peer* per_u = _mesa_gut_peer(mes_u, pac_u->pok_u.pay_u.her_u); c3_o new_o = c3n; - if ( NULL == per_u ) { - new_o = c3y; - per_u = new(&sam_u->par_u, u3_peer, 1); - _init_peer(sam_u, per_u); - _meet_peer(sam_u, per_u, pac_u->pok_u.pay_u.her_u); + if ( u3_peer_full != per_u->liv_e ) { + _meet_peer(mes_u, per_u); + return; } c3_o dir_o = __(pac_u->hed_u.hop_y == 0); if ( pac_u->hed_u.hop_y == 0 ) { new_o = c3y; - _hear_peer(sam_u, per_u, lan_u, dir_o); + _hear_peer(mes_u, per_u, lan_u, dir_o); // u3l_log("learnt lane"); } else { // u3l_log("received forwarded poke"); @@ -2776,9 +2685,9 @@ _mesa_hear_poke(u3_mesa_pict* pic_u, sockaddr_in lan_u) } // XX _meet_peer, in the _saxo_cb, is already putting the peer in her_p // - _mesa_put_peer(sam_u, pac_u->pok_u.pay_u.her_u, per_u); + _mesa_put_peer(mes_u, pac_u->pok_u.pay_u.her_u, per_u); - u3_pend_req* req_u = _mesa_get_request(sam_u, &pac_u->pok_u.pay_u); + u3_pend_req* req_u = _mesa_get_request(mes_u, &pac_u->pok_u.pay_u); if ( req_u != NULL) { // u3l_log("req pending"); return; @@ -2801,7 +2710,7 @@ _mesa_hear_poke(u3_mesa_pict* pic_u, sockaddr_in lan_u) } u3_ovum* ovo = u3_ovum_init(0, c3__ames, wir, cad); - ovo = u3_auto_plan(&sam_u->car_u, ovo); + ovo = u3_auto_plan(&mes_u->car_u, ovo); // XX check request state for *payload* (in-progress duplicate) assert(pac_u->pok_u.dat_u.tob_d); @@ -2811,13 +2720,13 @@ _mesa_hear_poke(u3_mesa_pict* pic_u, sockaddr_in lan_u) void _ames_hear(void* sam_u, - const struct sockaddr* adr_u, + const struct sockaddr_in* adr_u, c3_w len_w, c3_y* hun_y); static void -_mesa_hear(u3_mesa* sam_u, - const struct sockaddr* adr_u, +_mesa_hear(u3_mesa* mes_u, + const struct sockaddr_in* lan_u, c3_w len_w, c3_y* hun_y) { @@ -2825,21 +2734,29 @@ _mesa_hear(u3_mesa* sam_u, /* fwrite(hun_y, 1, len_w, packs); */ // c3_d now_d = _get_now_micros(); if ( c3n == mesa_is_new_pact(hun_y, len_w) ) { - c3_y* han_y = c3_malloc(len_w); - memcpy(han_y, hun_y, len_w); - _ames_hear(u3_Host.sam_u, adr_u, len_w, han_y); + // XX reorg, check if a STUN req/resp can look like an ames packet + // check the mug hash of the body of the packet, if not check if STUN + // otherwise , invalid packet, log failure + // check ames first, assume that STUN could maybe (not likely) overlap with ames + // for next protocol version, have an urbit cookie + // + + if ( c3y == u3_stun_hear(&mes_u->sun_u, lan_u, len_w, hun_y) ) + return; + + _ames_hear(mes_u->sam_u, lan_u, len_w, hun_y); return; } - u3_mesa_pict* pic_u = new(&sam_u->are_u, u3_mesa_pict, 1); - pic_u->sam_u = sam_u; + u3_mesa_pict* pic_u = new(&mes_u->are_u, u3_mesa_pict, 1); + pic_u->mes_u = mes_u; c3_c* err_c = mesa_sift_pact_from_buf(&pic_u->pac_u, hun_y, len_w); if ( err_c ) { u3l_log("mesa: hear: sift failed: %s", err_c); return; } - sockaddr_in sdr_u = *((sockaddr_in*)adr_u); + sockaddr_in sdr_u = *((sockaddr_in*)lan_u); switch ( pic_u->pac_u.hed_u.typ_y ) { case PACT_PEEK: { @@ -2872,7 +2789,8 @@ static void _mesa_recv_cb(uv_udp_t* wax_u, const struct sockaddr* adr_u, unsigned flg_i) { - u3_mesa* sam_u = (u3_mesa*)wax_u->data; + u3_mesa* mes_u = (u3_mesa*)wax_u->data; + const struct sockaddr_in* lan_u = (const struct sockaddr_in*)adr_u; if ( 0 > nrd_i ) { if ( u3C.wag_w & u3o_verbose ) { u3l_log("mesa: recv: fail: %s", uv_strerror(nrd_i)); @@ -2886,15 +2804,69 @@ static void _mesa_recv_cb(uv_udp_t* wax_u, } } else { - _mesa_hear(wax_u->data, adr_u, (c3_w)nrd_i, (c3_y*)buf_u->base); + _mesa_hear(wax_u->data, lan_u, (c3_w)nrd_i, (c3_y*)buf_u->base); } } +static void +_mdns_dear_bail(u3_ovum* egg_u, u3_noun lud) +{ + u3z(lud); + u3_ovum_free(egg_u); +} + +/* _mesa_put_dear(): send lane to arvo after hearing mdns response +*/ +static void +_mesa_put_dear(c3_c* ship, bool fake, c3_w s_addr, c3_s port, void* context) +{ + u3_mesa* mes_u = (u3_mesa*)context; + + // one is loobean one is boolean + if (fake == mes_u->pir_u->fak_o) { + return; + } + + sockaddr_in lan; + lan.sin_family = AF_INET; + lan.sin_addr.s_addr = s_addr; + lan.sin_port = port; + + u3_noun whu = u3dc("slaw", c3__p, u3i_string(ship)); + + if (u3_nul == whu) { + u3l_log("ames: strange ship from mdns: %s", ship); + return; + } + + u3_noun our = u3_ship_to_noun(mes_u->pir_u->who_u); + if (our == u3t(whu)) { + u3z(whu); + u3z(our); + return; + } + + u3z(our); + + u3_noun wir = u3nc(c3__ames, u3_nul); + u3_noun cad = u3nt(c3__dear, u3k(u3t(whu)), u3nc(c3n, u3_ames_encode_lane(lan))); + + u3_auto_peer( + u3_auto_plan(&mes_u->car_u, + u3_ovum_init(0, c3__a, wir, cad)), + 0, 0, _mdns_dear_bail); + u3z(whu); +} + +void +_ames_io_talk(void* sam_u); + static void _mesa_io_talk(u3_auto* car_u) { - u3_mesa* sam_u = (u3_mesa*)car_u; - sam_u->dns_c = "urbit.org"; // TODO: receive turf + u3_mesa* mes_u = (u3_mesa*)car_u; + _ames_io_talk(mes_u->sam_u); + mes_u->dns_c = "urbit.org"; // TODO: receive turf { // XX remove [sev_l] // @@ -2903,38 +2875,38 @@ _mesa_io_talk(u3_auto* car_u) u3_auto_plan(car_u, u3_ovum_init(0, c3__a, wir, cad)); } - u3_noun who = u3i_chubs(2, sam_u->pir_u->who_d); + u3_noun who = u3_ship_to_noun(mes_u->pir_u->who_u); u3_noun rac = u3do("clan:title", u3k(who)); - c3_s por_s = sam_u->pir_u->por_s; + c3_s por_s = mes_u->pir_u->por_s; 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); + c3_y num_y = (c3_y)mes_u->pir_u->who_u.hed_d; + c3_s zar_s = ntohs(_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", zar_s, por_s); - u3l_log("ames: czar: WARNING: %d required for discoverability", zar_s); + u3l_log("ames: czar: overriding port %u with -p %u", zar_s, por_s); + u3l_log("ames: czar: WARNING: %u required for discoverability", zar_s); } } // Bind and stuff. { - struct sockaddr_in add_u; - c3_i add_i = sizeof(add_u); + struct sockaddr_in lan_u; + c3_i add_i = sizeof(lan_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) ? + memset(&lan_u, 0, sizeof(lan_u)); + lan_u.sin_family = AF_INET; + lan_u.sin_addr.s_addr = _(u3_Host.ops_u.net) ? htonl(INADDR_ANY) : htonl(INADDR_LOOPBACK); - add_u.sin_port = htons(por_s); + lan_u.sin_port = htons(por_s); - if ( (ret_i = uv_udp_bind(&u3_Host.wax_u, - (const struct sockaddr*)&add_u, 0)) != 0 ) + if ( (ret_i = uv_udp_bind(&mes_u->wax_u, + (const struct sockaddr*)&lan_u, 0)) != 0 ) { u3l_log("mesa: bind: %s", uv_strerror(ret_i)); @@ -2949,47 +2921,99 @@ _mesa_io_talk(u3_auto* car_u) u3_pier_bail(u3_king_stub()); } - uv_udp_getsockname(&u3_Host.wax_u, (struct sockaddr *)&add_u, &add_i); - u3_assert(add_u.sin_port); + uv_udp_getsockname(&mes_u->wax_u, (struct sockaddr *)&lan_u, &add_i); + u3_assert(lan_u.sin_port); - sam_u->pir_u->por_s = ntohs(add_u.sin_port); + mes_u->pir_u->por_s = ntohs(lan_u.sin_port); + c3_c* our_s = u3_ship_to_string(mes_u->pir_u->who_u); + mdns_init(lan_u.sin_port, !mes_u->pir_u->fak_o, our_s, _mesa_put_dear, (void *)mes_u); + c3_free(our_s); } if ( c3y == u3_Host.ops_u.net ) { - u3l_log("mesa: live on %d", sam_u->pir_u->por_s); + u3l_log("mesa: live on %u", mes_u->pir_u->por_s); } else { - u3l_log("mesa: live on %d (localhost only)", sam_u->pir_u->por_s); + u3l_log("mesa: live on %u (localhost only)", mes_u->pir_u->por_s); + } + + if ( c3n == mes_u->pir_u->fak_o ) { + uv_timer_start(&mes_u->nat_u.tim_u, natpmp_init, 0, 0); } - u3_Host.wax_u.data = sam_u; - uv_udp_recv_start(&u3_Host.wax_u, _mesa_alloc, _mesa_recv_cb); + mes_u->wax_u.data = mes_u; + uv_udp_recv_start(&mes_u->wax_u, _mesa_alloc, _mesa_recv_cb); c3_i rec_i = 2 * 1024 * 1024; - uv_recv_buffer_size((uv_handle_t*)&u3_Host.wax_u, &rec_i); + uv_recv_buffer_size((uv_handle_t*)&mes_u->wax_u, &rec_i); - uv_send_buffer_size((uv_handle_t*)&u3_Host.wax_u, &rec_i); + uv_send_buffer_size((uv_handle_t*)&mes_u->wax_u, &rec_i); - sam_u->car_u.liv_o = c3y; + mes_u->car_u.liv_o = c3y; //u3z(rac); u3z(who); } static void _mesa_clear_pit(uv_timer_t *tim_u) { - u3_mesa* sam_u = (u3_mesa*)tim_u->data; - pit_map_itr itr_u = vt_first( &sam_u->pit_u ); + u3_mesa* mes_u = (u3_mesa*)tim_u->data; + pit_map_itr itr_u = vt_first( &mes_u->pit_u ); c3_d now_d = _get_now_micros(); while (!vt_is_end(itr_u)) { u3_pit_entry* pit_u = itr_u.data->val; if ( (now_d - pit_u->tim_d) > PIT_EXPIRE_MICROS) { - itr_u = vt_erase_itr(&sam_u->pit_u, itr_u); + itr_u = vt_erase_itr(&mes_u->pit_u, itr_u); } else { itr_u = vt_next(itr_u); } } } +/* _mesa_ef_saxo(): handle sponsorship chain notification +*/ +static void +_mesa_ef_saxo(u3_mesa* mes_u, u3_noun zad) +{ + u3_noun daz; + + daz = u3qb_flop(zad); + if ( u3_nul == daz ) { + u3l_log("ames: empty sponsorship chain"); + u3z(zad); u3z(daz); + return; + } + + u3_ship dad_u = u3_ship_of_noun(u3h(daz)); + + // if we are a galaxy, don't STUN + // + if ( c3n == u3_ships_equal(dad_u, mes_u->pir_u->who_u) ) { + mes_u->sun_u.dad_u = dad_u; + u3_stun_start(&mes_u->sun_u, 0); +#ifdef MESA_DEBUG + u3l_log("mesa: starting stun"); +#endif + } else { + mes_u->for_o = c3y; +#ifdef MESA_DEBUG + u3l_log("mesa: enabling forwarding"); +#endif + } + + u3z(zad); u3z(daz); +} + +/* u3_ames_io_init(): initialize ames I/O. +*/ +void* +u3_ames_io_init(void* mes_u); + +void +_ames_init_czars(u3_lamp_state* lam_u); + +u3m_quac** +_ames_io_mark(u3_auto*, c3_w*); + /* _mesa_io_init(): initialize ames I/O. */ u3_auto* @@ -2998,58 +3022,73 @@ u3_mesa_io_init(u3_pier* pir_u) u3l_log("mesa: INIT"); /* packs = fopen("/home/ec2-user/pages.packs", "rb"); */ arena par_u = arena_create(67108864); - u3_mesa* sam_u = new(&par_u, u3_mesa, 1); - sam_u->par_u = par_u; - sam_u->pir_u = pir_u; + u3_mesa* mes_u = new(&par_u, u3_mesa, 1); + mes_u->par_u = par_u; + mes_u->pir_u = pir_u; arena are_u; are_u.dat = (char*)are_y; are_u.beg = (char*)are_y; are_u.end = (char*)(are_y + 524288); - sam_u->are_u = are_u; + mes_u->are_u = are_u; - sam_u->jum_d = 0; + mes_u->jum_d = 0; - uv_timer_init(u3L, &sam_u->tim_u); + uv_timer_init(u3L, &mes_u->tim_u); // clear pit every 30 seconds - sam_u->tim_u.data = sam_u; - uv_timer_start(&sam_u->tim_u, _mesa_clear_pit, 30000, 30000); + mes_u->tim_u.data = mes_u; + uv_timer_start(&mes_u->tim_u, _mesa_clear_pit, 30000, 30000); + + u3_assert( !uv_udp_init_ex(u3L, &mes_u->wax_u, UV_UDP_RECVMMSG) ); + mes_u->wax_u.data = mes_u; - vt_init(&sam_u->pit_u); - vt_init(&sam_u->per_u); - vt_init(&sam_u->gag_u); - vt_init(&sam_u->jum_u); - vt_init(&sam_u->req_u); + vt_init(&mes_u->pit_u); + vt_init(&mes_u->per_u); + vt_init(&mes_u->jum_u); + vt_init(&mes_u->req_u); // Disable networking for fake ships // - if ( c3y == sam_u->pir_u->fak_o ) { + if ( c3y == mes_u->pir_u->fak_o ) { u3_Host.ops_u.net = c3n; } - sam_u->for_o = c3n; - { - u3_noun her = u3i_chubs(2, pir_u->who_d); - if ( c3y == u3a_is_cat(her) && her < 256 ) { - u3l_log("mesa: forwarding enabled"); - sam_u->for_o = c3y; - } - u3z(her); - } - + mes_u->for_o = c3n; - u3_auto* car_u = &sam_u->car_u; + u3_auto* car_u = &mes_u->car_u; memset(car_u, 0, sizeof(*car_u)); - car_u->nam_m = c3__ames; - car_u->liv_o = c3y; + car_u->nam_m = c3__mesa; + car_u->liv_o = c3n; car_u->io.talk_f = _mesa_io_talk; car_u->io.info_f = _mesa_io_info; car_u->io.slog_f = _mesa_io_slog; + car_u->io.mark_f = _ames_io_mark; car_u->io.kick_f = _mesa_io_kick; car_u->io.exit_f = _mesa_io_exit; + mes_u->sun_u.car_u = car_u; + mes_u->sun_u.wax_u = &mes_u->wax_u; + mes_u->sun_u.net_o = c3y; + mes_u->sun_u.wok_o = c3n; + uv_timer_init(u3L, &mes_u->sun_u.tim_u); + mes_u->sun_u.tim_u.data = &mes_u->sun_u; + u3l_log("mesa start %p", &mes_u->sun_u); + + mes_u->lam_u.car_u = car_u; + mes_u->lam_u.per_u = &mes_u->per_u; + mes_u->lam_u.dom_o = c3n; + uv_timer_init(u3L, &mes_u->lam_u.tim_u); + mes_u->lam_u.tim_u.data = &mes_u->lam_u; + _ames_init_czars(&mes_u->lam_u); + + // initialize libnatpmp + mes_u->nat_u.car_u = car_u; + mes_u->nat_u.tim_u.data = &mes_u->nat_u; + uv_timer_init(u3L, &mes_u->nat_u.tim_u); + + mes_u->sam_u = u3_ames_io_init(car_u); /*{ u3_noun now; @@ -3057,9 +3096,10 @@ u3_mesa_io_init(u3_pier* pir_u) gettimeofday(&tim_u, 0); now = u3_time_in_tv(&tim_u); - //sam_u->sev_l = u3r_mug(now); + //mes_u->sev_l = u3r_mug(now); u3z(now); }*/ + return car_u; } diff --git a/pkg/vere/io/mesa/mesa.h b/pkg/vere/io/mesa/mesa.h index c7c3d07f18..f229e48d75 100644 --- a/pkg/vere/io/mesa/mesa.h +++ b/pkg/vere/io/mesa/mesa.h @@ -1,6 +1,7 @@ #ifndef VERE_MESA_H #define VERE_MESA_H +#include "vere.h" #include "c3/c3.h" #include "ship.h" @@ -172,4 +173,52 @@ void inc_hopcount(u3_mesa_head*); void log_pact(u3_mesa_pact* pac_u); void log_name(u3_mesa_name* nam_u); +typedef struct sockaddr_in sockaddr_in; + +typedef struct _u3_lane_state { + c3_d sen_d; // last sent date + c3_d her_d; // last heard date + c3_w rtt_w; // round-trip time + c3_w rtv_w; // round-trip time variance +} u3_lane_state; + +typedef struct _u3_gage { + c3_w rtt_w; // rtt + c3_w rto_w; // rto + c3_w rtv_w; // rttvar + c3_w wnd_w; // cwnd + c3_w wnf_w; // cwnd fraction + c3_w sst_w; // ssthresh + c3_w con_w; // counter + // +} u3_gage; + +typedef enum _u3_peer_live { + u3_peer_lane = 1 << 0, + u3_peer_lamp = 1 << 1, + u3_peer_full = (1 << 0) | (1 << 1) +} u3_peer_live; + +typedef struct _u3_peer { + void* mes_u; // backpointer + u3_ship her_u; // who is this peer + u3_peer_live liv_e; // has this been initialized? + sockaddr_in dan_u; // direct lane (nullable) + u3_lane_state dir_u; // direct lane state + c3_o lam_o; + c3_o log_o; // dns log + u3_ship lam_u; // galaxy @p + u3_lane_state ind_u; // indirect lane state + c3_c** dns_c; + u3_gage gag_u; +} u3_peer; + +#define NAME per_map +#define KEY_TY u3_ship +#define HASH_FN u3_hash_ship +#define CMPR_FN u3_cmpr_ship +#define VAL_TY u3_peer* +#define HEADER_MODE +#include "verstable.h" + #endif diff --git a/pkg/vere/io/mesa/pact.c b/pkg/vere/io/mesa/pact.c index 1b2940c2be..71bba8671e 100644 --- a/pkg/vere/io/mesa/pact.c +++ b/pkg/vere/io/mesa/pact.c @@ -536,15 +536,15 @@ _etch_ship(u3_etcher* ech_u, u3_ship who_u, c3_y len_y) } static void -_sift_ship(u3_sifter* sif_u, u3_ship who_u, c3_y len_y) +_sift_ship(u3_sifter* sif_u, u3_ship* who_u, c3_y len_y) { assert ( len_y <= 16 ); c3_y *res_y = _sift_next(sif_u, len_y); if ( NULL == res_y ) { - who_u[0] = who_u[1] = 0; + who_u->hed_d = who_u->tel_d = 0; return; } - u3_ship_of_bytes(who_u, len_y, res_y); + *who_u = u3_ship_of_bytes(len_y, res_y); } static void @@ -642,7 +642,7 @@ _mesa_sift_name(u3_sifter* sif_u, u3_mesa_name* nam_u) nam_u->nit_o = __( met_u.nit_y == 1 ); nam_u->aut_o = __( met_u.tau_y == 1 ); - _sift_ship(sif_u, nam_u->her_u, 2 << met_u.ran_y); + _sift_ship(sif_u, &nam_u->her_u, 2 << met_u.ran_y); nam_u->rif_w = _sift_var_word(sif_u, met_u.rif_y + 1); nam_u->boq_y = _sift_byte(sif_u); diff --git a/pkg/vere/king.c b/pkg/vere/king.c index 33e730dcc7..cdc404cb1a 100644 --- a/pkg/vere/king.c +++ b/pkg/vere/king.c @@ -70,9 +70,9 @@ :: Should require auth to the daemon itself [%dawn p=seed] :: boot with fake keys :: - :: p: identity + :: seed for fake comets, @p for others :: - [%fake p=ship] + [%fake $@(=ship [~ =feed])] == :: +pill: boot-sequence ingredients :: @@ -86,12 +86,10 @@ :: q: optional %into ovum overriding that of .p void _king_doom(u3_noun doom); void _king_boot(u3_noun boot); void _king_come(u3_noun star, u3_noun pill, u3_noun path); - void _king_dawn(u3_noun feed, u3_noun pill, u3_noun path); - void _king_fake(u3_noun ship, u3_noun pill, u3_noun path); + void _king_dawn(u3_noun seed, u3_noun pill, u3_noun path); + void _king_fake(u3_noun farg, u3_noun pill, u3_noun path); void _king_pier(u3_noun pier); -static u3_noun _king_get_atom(c3_c* url_c); - /* _king_defy_fate(): invalid fate */ void @@ -204,7 +202,7 @@ _king_prop() case 2: { // url u3l_log("boot: downloading prop %s", vex_u->loc_c); - u3_atom jam = _king_get_atom(vex_u->loc_c); + u3_atom jam = u3_king_get_atom(vex_u->loc_c); mor = u3nc(u3ke_cue(jam), mor); } break; @@ -216,7 +214,7 @@ _king_prop() "https://bootstrap.urbit.org/props/" URBIT_VERSION "/%s.jam", vex_u->loc_c); u3l_log("boot: downloading prop %s", url_c); - u3_atom jam = _king_get_atom(url_c); + u3_atom jam = u3_king_get_atom(url_c); mor = u3nc(u3ke_cue(jam), mor); } break; @@ -234,9 +232,9 @@ _king_prop() /* _king_fake(): boot with fake keys */ void -_king_fake(u3_noun ship, u3_noun pill, u3_noun path) +_king_fake(u3_noun farg, u3_noun pill, u3_noun path) { - u3_noun vent = u3nc(c3__fake, u3k(ship)); + u3_noun vent = u3nc(c3__fake, u3k(farg)); // XX pass kelvin // @@ -415,10 +413,10 @@ king_curl_bytes(c3_c* url_c, c3_w* len_w, c3_y** hun_y, c3_t veb_t, c3_y tri_y) return ret_i; } -/* _king_get_atom(): HTTP GET url_c, produce response body as atom. +/* u3_king_get_atom(): HTTP GET url_c, produce response body as atom. */ -static u3_noun -_king_get_atom(c3_c* url_c) +u3_atom +u3_king_get_atom(c3_c* url_c) { c3_w len_w; c3_y* hun_y; @@ -434,6 +432,28 @@ _king_get_atom(c3_c* url_c) return pro; } +u3_noun +u3_king_get_noun(c3_c* url_c) { + c3_w len_w; + c3_y* byt_y; + + if ( king_curl_bytes(url_c, &len_w, &byt_y, 1, 5) ) { + u3_king_bail(); + exit(1); + } + + u3_cue_xeno* sil_u = u3s_cue_xeno_init_with(ur_fib27, ur_fib28); + u3_weak pro; + + if ( u3_none == (pro = u3s_cue_xeno_with(sil_u, len_w, byt_y)) ) { + u3l_log("u3_king_get_noun: unable to cue noun"); + exit(1); + } + + u3s_cue_xeno_done(sil_u); + return pro; +} + /* _king_get_pace(): get "pace" (release channel name). */ static c3_c* @@ -547,10 +567,10 @@ u3_king_next(c3_c* pac_c, c3_c** out_c) /* _get_cmd_output(): Run a shell command and capture its output. Exits with an error if the command fails or produces no output. The 'out_c' parameter should be an array of sufficient length to hold - the command's output, up to a max of len_c characters. + the command's output, up to a max of len_w characters. */ static void -_get_cmd_output(c3_c *cmd_c, c3_c *out_c, c3_w len_c) +_get_cmd_output(c3_c *cmd_c, c3_c *out_c, c3_w len_w) { FILE *fp = popen(cmd_c, "r"); if ( NULL == fp ) { @@ -558,7 +578,7 @@ _get_cmd_output(c3_c *cmd_c, c3_c *out_c, c3_w len_c) exit(1); } - if ( NULL == fgets(out_c, len_c, fp) ) { + if ( NULL == fgets(out_c, len_w, fp) ) { u3l_log("'%s' produced no output", cmd_c); exit(1); } @@ -626,7 +646,7 @@ _boothack_pill(void) } u3l_log("boot: downloading pill %s", url_c); - pil = _king_get_atom(url_c); + pil = u3_king_get_atom(url_c); } if ( 0 != u3_Host.ops_u.arv_c ) { @@ -678,23 +698,39 @@ _boothack_key(u3_noun kef) u3z(kef); } - if ( 0 != u3_Host.ops_u.who_c ) { - u3_noun woh = u3i_string(u3_Host.ops_u.who_c); + if ( 0 != u3_Host.ops_u.who_c || + ( 0 != u3_Host.ops_u.fak_c && + 28 < strlen(u3_Host.ops_u.fak_c) ) ) { + u3_noun woh; + + if ( 0 != u3_Host.ops_u.fak_c ) + woh = u3i_string(u3_Host.ops_u.fak_c); + else + woh = u3i_string(u3_Host.ops_u.who_c); + u3_noun whu = u3dc("slaw", 'p', u3k(woh)); if ( u3_nul == whu ) { - u3l_log("dawn: invalid ship specified with -w %s", - u3_Host.ops_u.who_c); + if ( 0 != u3_Host.ops_u.fak_c ) + u3l_log("boot: malformed -F ship %s", + u3_Host.ops_u.fak_c); + else + u3l_log("dawn: invalid ship specified with -w %s", + u3_Host.ops_u.who_c); exit(1); } if ( (u3_none != ship) && - (c3n == u3r_sing(ship, u3t(whu))) ) - { + (c3n == u3r_sing(ship, u3t(whu))) ) { u3_noun how = u3dc("scot", 'p', u3k(ship)); c3_c* how_c = u3r_string(u3k(how)); - u3l_log("dawn: mismatch between -w %s and -K %s", - u3_Host.ops_u.who_c, how_c); + + if ( 0 != u3_Host.ops_u.fak_c ) + u3l_log("boot: mismatch between -F %s and -K %s", + u3_Host.ops_u.fak_c, how_c); + else + u3l_log("dawn: mismatch between -w %s and -K %s", + u3_Host.ops_u.who_c, how_c); u3z(how); c3_free(how_c); @@ -719,7 +755,8 @@ _boothack_doom(void) if ( c3n == u3_Host.ops_u.nuu ) { return u3nt(c3__pier, u3_nul, pax); } - else if ( 0 != u3_Host.ops_u.fak_c ) { + else if ( 0 != u3_Host.ops_u.fak_c && + 28 > strlen(u3_Host.ops_u.fak_c) ) { u3_noun fak = u3i_string(u3_Host.ops_u.fak_c); u3_noun whu = u3dc("slaw", 'p', u3k(fak)); @@ -733,7 +770,9 @@ _boothack_doom(void) u3z(whu); u3z(fak); } - else if ( 0 != u3_Host.ops_u.who_c ) { + else if ( 0 != u3_Host.ops_u.who_c || + ( 0 != u3_Host.ops_u.fak_c && + 28 < strlen(u3_Host.ops_u.fak_c) ) ) { u3_noun kef; if ( 0 != u3_Host.ops_u.key_c ) { @@ -762,7 +801,11 @@ _boothack_doom(void) exit(1); } - bot = u3nc(c3__dawn, _boothack_key(kef)); + if ( 0 != u3_Host.ops_u.fak_c ) { + bot = u3nc(c3__fake, u3nc(u3_nul, _boothack_key(kef))); + } + else + bot = u3nc(c3__dawn, _boothack_key(kef)); } else { // XX allow parent star to be specified? diff --git a/pkg/vere/main.c b/pkg/vere/main.c index a547e23167..65c94a6ceb 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -259,7 +259,7 @@ _main_getopt(c3_i argc, c3_c** argv) { "pier", required_argument, NULL, 'c' }, { "replay", no_argument, NULL, 'D' }, { "daemon", no_argument, NULL, 'd' }, - { "ethereum", required_argument, NULL, 'e' }, + { "gateway", required_argument, NULL, 'g' }, { "fake", required_argument, NULL, 'F' }, { "key-string", required_argument, NULL, 'G' }, { "gc", no_argument, NULL, 'g' }, @@ -308,6 +308,7 @@ _main_getopt(c3_i argc, c3_c** argv) { "behn-allow-blocked", no_argument, NULL, 10 }, { "serf-bin", required_argument, NULL, 11 }, { "lmdb-map-size", required_argument, NULL, 12 }, + { "jael-sources", required_argument, NULL, 13 }, // { NULL, 0, NULL, 0 }, }; @@ -359,7 +360,10 @@ _main_getopt(c3_i argc, c3_c** argv) if ( 1 != sscanf(optarg, "%" SCNuMAX, &u3_Host.ops_u.siz_i) ) { return c3n; } - + break; + } + case 13: { // jael-sources + u3_Host.ops_u.src_c = strdup(optarg); break; } // special args @@ -435,10 +439,6 @@ _main_getopt(c3_i argc, c3_c** argv) u3_Host.ops_u.nuu = c3y; break; } - case 'e': { - u3_Host.ops_u.eth_c = strdup(optarg); - break; - } case 'F': { u3_Host.ops_u.fak_c = _main_presig(optarg); u3_Host.ops_u.net = c3n; @@ -505,6 +505,10 @@ _main_getopt(c3_i argc, c3_c** argv) u3_Host.ops_u.nuu = c3y; break; } + case 'W': { + u3_Host.ops_u.gat_c = strdup(optarg); + break; + } case 'X': { u3_Host.ops_u.pek_c = strdup(optarg); break; @@ -552,8 +556,10 @@ _main_getopt(c3_i argc, c3_c** argv) #endif if ( 0 != u3_Host.ops_u.fak_c ) { - if ( 28 < strlen(u3_Host.ops_u.fak_c) ) { - fprintf(stderr, "fake comets are forbidden\r\n"); + if ( 28 < strlen(u3_Host.ops_u.fak_c) && + ( 0 == u3_Host.ops_u.key_c && + 0 == u3_Host.ops_u.gen_c ) ) { + fprintf(stderr, "fake comets require a key file or key string\r\n"); return c3n; } if ( 0 != u3_Host.ops_u.who_c ) { @@ -625,13 +631,18 @@ _main_getopt(c3_i argc, c3_c** argv) return c3n; } - if ( u3_Host.ops_u.nuu != c3y && u3_Host.ops_u.dns_c != 0 ) { - fprintf(stderr, "-H only makes sense when creating a new ship\n"); + if ( u3_Host.ops_u.nuu != c3y && u3_Host.ops_u.key_c != 0 ) { + fprintf(stderr, "-k only makes sense when creating a new ship\n"); return c3n; } - if ( u3_Host.ops_u.nuu != c3y && u3_Host.ops_u.key_c != 0 ) { - fprintf(stderr, "-k only makes sense when creating a new ship\n"); + if ( u3_Host.ops_u.gen_c != 0 && u3_Host.ops_u.key_c != 0 ) { + fprintf(stderr, "-G and -k cannot be used together\n"); + return c3n; + } + + if ( u3_Host.ops_u.nuu != c3y && u3_Host.ops_u.dns_c != 0 ) { + fprintf(stderr, "-H only makes sense when creating a new ship\n"); return c3n; } @@ -644,6 +655,11 @@ _main_getopt(c3_i argc, c3_c** argv) fprintf(stderr, "-B and -u cannot be used together\n"); return c3n; } + + if (u3_Host.ops_u.nuu != c3y && u3_Host.ops_u.src_c != 0 ) { + fprintf(stderr, "--jael-sources only makes sense when creating a new ship\n"); + return c3n; + } else if ( u3_Host.ops_u.nuu == c3y && u3_Host.ops_u.url_c == 0 && u3_Host.ops_u.git == c3n ) { @@ -844,7 +860,6 @@ u3_ve_usage(c3_i argc, c3_c** argv) "-c, --pier PIER Create a new urbit in /\n", "-D, --replay Recompute from events\n", "-d, --daemon Daemon mode; implies -t\n", - "-e, --ethereum URL Ethereum gateway\n", "-F, --fake SHIP Boot fake urbit; also disables networking\n", "-G, --key-string STRING Private key string (@uw, see also -k)\n" "-g, --gc Set GC flag\n", @@ -874,6 +889,7 @@ u3_ve_usage(c3_i argc, c3_c** argv) "-u, --bootstrap-url URL URL from which to download pill\n", "-v, --verbose Verbose\n", "-w, --name NAME Initial boot as ~name (with ticket)\n", + "-W, --cards CARDS PKI init cards\n", "-X, --scry PATH Scry, write to file, then exit\n", "-x, --exit Exit immediately\n", "-Y, --scry-into FILE Optional name of file (for -X)\n", diff --git a/pkg/vere/mars.c b/pkg/vere/mars.c index c3036143df..1f22362cee 100644 --- a/pkg/vere/mars.c +++ b/pkg/vere/mars.c @@ -1496,7 +1496,7 @@ u3_mars_work(u3_mars* mar_u) u3_noun wyn = u3_nul; u3_noun msg = u3nq(c3__ripe, u3nc(2, wyn), - u3nc(u3i_chubs(2, mar_u->met_u.who_d), + u3nc(u3_ship_to_noun(mar_u->met_u.who_u), mar_u->met_u.fak_o), u3nc(u3i_chub(mar_u->dun_d), mar_u->mug_l)); @@ -1721,8 +1721,7 @@ _mars_boot_make(u3_boot_opts* inp_u, return c3n; } - u3r_chubs(0, 2, met_u->who_d, who); - + met_u->who_u = u3_ship_of_noun(who); { u3_noun bot, mod, use, cax; diff --git a/pkg/vere/mdns.c b/pkg/vere/mdns.c index 64243607d9..6947820f97 100644 --- a/pkg/vere/mdns.c +++ b/pkg/vere/mdns.c @@ -197,7 +197,7 @@ void mdns_init(uint16_t port, bool fake, char* our, mdns_cb* cb, void* context) } err = DNSServiceRegister(&sref, 0, 0, domain, "_ames._udp", - NULL, NULL, htons(port), 0, NULL, register_cb, (void*)register_payload); + NULL, NULL, port, 0, NULL, register_cb, (void*)register_payload); if (err != kDNSServiceErr_NoError) { if (err == kDNSServiceErr_Unknown) { diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 80c16624c3..05512e4538 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -369,9 +369,9 @@ _pier_on_scry_done(void* ptr_v, u3_noun nun) } static c3_c* -_resolve_czar(c3_d chu_d, c3_c* who_c) +_resolve_czar(u3_ship who_u, c3_c* who_c) { - u3_noun czar = u3dc("scot", 'p', chu_d & ((1 << 8) - 1)); + u3_noun czar = u3dc("scot", 'p', who_u.hed_d & ((1 << 8) - 1)); c3_c* czar_c = u3r_string(czar); c3_c url[256]; @@ -391,14 +391,14 @@ _resolve_czar(c3_d chu_d, c3_c* who_c) } static c3_o -_czar_boot_data(c3_c* czar_c, - c3_c* who_c, - c3_w* bone_w, - c3_w* czar_glx_w, - c3_w* czar_ryf_w, - c3_w* czar_lyf_w, - c3_w* czar_bon_w, - c3_w* czar_ack_w) +_czar_boot_data(c3_c* czar_c, + c3_c* who_c, + c3_w* bone_w, + u3_ship* czar_glx_u, + c3_w* czar_ryf_w, + c3_w* czar_lyf_w, + c3_w* czar_bon_w, + c3_w* czar_ack_w) { c3_c url[256]; c3_w len_w; @@ -421,9 +421,9 @@ _czar_boot_data(c3_c* czar_c, if ( (c3y == u3r_hext(cued, 0, &czar_glx, &czar_ryf, &czar_lyf, &czar_bon, &czar_ack)) && - (c3y == u3r_safe_word(czar_glx, czar_glx_w)) && (c3y == u3r_safe_word(czar_ryf, czar_ryf_w)) && (c3y == u3r_safe_word(czar_lyf, czar_lyf_w)) ) { + *czar_glx_u = u3_ship_of_noun(czar_glx); if ( c3y == u3du(czar_bon) ) u3r_safe_word(u3t(czar_bon), czar_bon_w); if ( c3y == u3du(czar_ack) ) u3r_safe_word(u3t(czar_ack), czar_ack_w); ret_o = c3y; @@ -511,14 +511,16 @@ _boot_scry_cb(void* vod_p, u3_noun nun) { u3_pier* pir_u = (u3_pier*)vod_p; - u3_atom who = u3dc("scot", c3__p, u3i_chubs(2, pir_u->who_d)); + u3_atom who = u3_ship_to_noun(pir_u->who_u); c3_c* who_c = u3r_string(who); u3_noun rem, glx, ryf, bon, cur, nex; - c3_w glx_w, ryf_w, bon_w, cur_w, nex_w; + c3_w ryf_w, bon_w, cur_w, nex_w; + u3_ship glx_u; - c3_w czar_glx_w, czar_ryf_w, czar_lyf_w, czar_bon_w, czar_ack_w; - czar_glx_w = czar_ryf_w = czar_lyf_w = czar_bon_w = czar_ack_w = u3_none; + c3_w czar_ryf_w, czar_lyf_w, czar_bon_w, czar_ack_w; + czar_ryf_w = czar_lyf_w = czar_bon_w = czar_ack_w = u3_none; + u3_ship czar_glx_u; if ( (c3y == u3r_qual(nun, 0, 0, 0, &rem)) && (c3y == u3r_hext(rem, &glx, &ryf, 0, &bon, &cur, &nex)) ) { @@ -526,15 +528,14 @@ _boot_scry_cb(void* vod_p, u3_noun nun) * Boot scry succeeded. Proceed to cross reference networking state against * sponsoring galaxy. */ - glx_w = u3r_word(0, glx); ryf_w = u3r_word(0, ryf); + glx_u = u3_ship_of_noun(glx); ryf_w = u3r_word(0, ryf); bon_w = u3r_word(0, bon); cur_w = u3r_word(0, cur); nex_w = u3r_word(0, nex); - u3_atom czar = u3dc("scot", c3__p, glx_w); - c3_c* czar_c = u3r_string(czar); + c3_c* czar_c = u3_ship_to_string(glx_u); if ( c3n == _czar_boot_data(czar_c, who_c, &bon_w, - &czar_glx_w, &czar_ryf_w, + &czar_glx_u, &czar_ryf_w, &czar_lyf_w, &czar_bon_w, &czar_ack_w) ) { u3l_log("boot: peer-state unvailable on czar, cannot protect from double-boot"); @@ -567,18 +568,20 @@ _boot_scry_cb(void* vod_p, u3_noun nun) } } - u3z(czar); c3_free(czar_c); - } else if ( c3y == u3r_trel(nun, 0, 0, &rem) && rem == 0 ) { + } else if ( c3y == u3r_trel(nun, 0, 0, &rem) && + c3y == u3r_cell(rem, 0, &glx) ) { /* * Data not available for boot scry. Check against sponsoring galaxy. * If peer state exists exit(1) unless ship has breached, * otherwise continue boot. */ - c3_c* czar_c = _resolve_czar(pir_u->who_d[0], who_c); + + glx_u = u3_ship_of_noun(glx); ryf_w = u3r_word(0, ryf); + c3_c* czar_c = u3_ship_to_string(glx_u); if ( c3n == _czar_boot_data(czar_c, who_c, 0, - &czar_glx_w, &czar_ryf_w, + &czar_glx_u, &czar_ryf_w, &czar_lyf_w, &czar_bon_w, 0) ) { c3_free(czar_c); _pier_wyrd_init(pir_u); @@ -624,8 +627,8 @@ static void _pier_double_boot_init(u3_pier* pir_u) { pir_u->sat_e = u3_psat_wyrd; - c3_d pi_d = pir_u->who_d[0]; - c3_d pt_d = pir_u->who_d[1]; + c3_d pi_d = pir_u->who_u.hed_d; + c3_d pt_d = pir_u->who_u.tel_d; if ( (pi_d < 256 && pt_d == 0) || (c3n == u3_Host.ops_u.net) ) { // Skip double boot protection for galaxies and local mode ships @@ -952,7 +955,7 @@ _pier_on_lord_live(void* ptr_v, u3_atom who, c3_o fak_o) // XX validate // - u3r_chubs(0, 2, pir_u->who_d, who); + pir_u->who_u = u3_ship_of_noun(who); pir_u->fak_o = fak_o; // early exit, preparing for upgrade diff --git a/pkg/vere/vere.h b/pkg/vere/vere.h index 07bd3049d6..1a227e976a 100644 --- a/pkg/vere/vere.h +++ b/pkg/vere/vere.h @@ -45,10 +45,7 @@ /* u3_lane: ames lane (IP address and port) */ - typedef struct _u3_lane { - c3_w pip_w; // target IPv4 address - c3_s por_s; // target port - } u3_lane; + typedef struct sockaddr_in sockaddr_in; /* u3_moor_poke: poke callback function. */ @@ -271,7 +268,7 @@ c3_w hap_w; // -C, cap transient memo cache c3_o dry; // -D, dry compute, no checkpoint c3_o dem; // -d, daemon - c3_c* eth_c; // -e, ethereum node url + c3_c* gat_c; // -g, PKI gateway node url c3_c* fak_c; // -F, fake ship c3_c* gen_c; // -G, czar generator c3_o gab; // -g, test garbage collection @@ -312,6 +309,7 @@ c3_o eph; // --swap, use ephemeral file c3_o tos; // --toss, discard ephemeral u3_even* vex_u; // --prop-*, boot enhancements + c3_c* src_c; // --jael-sources c3_o beb; // --behn-allow-blocked c3_z siz_i; // --lmdb-map-size @@ -339,9 +337,6 @@ c3_o pep_o; // prep for upgrade c3_i xit_i; // exit code for shutdown void (*bot_f)(); // call when chis is up - void* sam_u; // old ames, "unified driver" hack - uv_udp_t wax_u; // "unified driver" udp send handle - c3_w* imp_u; // "unified driver" galaxy IP:s } u3_host; // host == computer == process /** Pier system. @@ -351,7 +346,8 @@ typedef enum { u3_ovum_drop = 0, // unplanned u3_ovum_work = 1, // begun - u3_ovum_done = 2 // complete + u3_ovum_done = 2, // complete + u3_ovum_exit = 3 // exit } u3_ovum_news; struct _u3_ovum; @@ -573,10 +569,10 @@ /* u3_meta: pier metadata. */ typedef struct _u3_meta { - c3_w ver_w; // version - c3_d who_d[2]; // identity - c3_o fak_o; // fake bit - c3_w lif_w; // lifecycle length + c3_w ver_w; // version + u3_ship who_u; // identity + c3_o fak_o; // fake bit + c3_w lif_w; // lifecycle length } u3_meta; /* u3_boot_opts: bootstrap parameters. @@ -631,7 +627,7 @@ typedef struct _u3_pier { c3_c* pax_c; // pier directory c3_w lif_w; // lifecycle barrier - c3_d who_d[2]; // identity + u3_ship who_u; // identity c3_o fak_o; // yes iff fake security c3_o liv_o; // fully live u3_disk* log_u; // event log @@ -813,6 +809,16 @@ c3_w u3_mcut_host(c3_c* buf_c, c3_w len_w, u3_noun hot); + /* u3_mcut_hosts(): measure/cut host list. + */ + c3_w + u3_mcut_hosts(c3_c* buf_c, c3_w len_w, u3_noun hot); + + /* u3_mpef_turf(): measure/cut string list, prefixing. + */ + c3_w + u3_mpef_turfs(c3_c* buf_c, c3_w len_w, c3_c* pef_c, c3_c** tuf_c); + /** IO drivers. **/ /* u3_auto_mark(): mark drivers for gc. @@ -829,6 +835,11 @@ u3_noun u3_auto_info(u3_auto* car_u); + /* u3_auto_link(): validate and link initalized [car_u] + */ + u3_auto* + u3_auto_link(u3_auto* car_u, u3_pier* pir_u, u3_auto* nex_u); + /* u3_auto_slog(): print status info. */ void @@ -1182,20 +1193,16 @@ /** Ames, packet networking. **/ - /* u3_ames_io_init(): initialize ames I/O. - */ - u3_auto* - u3_ames_io_init(u3_pier* pir_u); /* u3_ames_decode_lane(): destructure lane from noun */ - u3_lane + sockaddr_in u3_ames_decode_lane(u3_noun); /* u3_ames_encode_lane(): encode lane as noun */ u3_noun - u3_ames_encode_lane(u3_lane); + u3_ames_encode_lane(sockaddr_in); /** mesa **/ @@ -1496,6 +1503,13 @@ c3_c* dir_c, // output directory c3_t lin_t); // link to $pier/.run + + u3_atom + u3_king_get_atom(c3_c* url_c); + + u3_noun + u3_king_get_noun(c3_c* url_c); + /* u3_daemon_init(): platform-specific daemon mode initialization. */ void diff --git a/pkg/vere/ward.c b/pkg/vere/ward.c index 9289535695..967126af18 100644 --- a/pkg/vere/ward.c +++ b/pkg/vere/ward.c @@ -220,3 +220,84 @@ u3_mcut_host(c3_c* buf_c, c3_w len_w, u3_noun hot) u3z(hot); return len_w; } + +/* u3_mcut_hosts(): measure/cut host list. +*/ +c3_w +u3_mcut_hosts(c3_c* buf_c, c3_w len_w, u3_noun hot) +{ + c3_c** dst_c = NULL; + hot = u3kdi_tap(u3kdb_gas(u3_nul, hot)); + c3_w hots_w = u3qb_lent(hot); + if (hots_w == 0) return len_w; + if (buf_c) { + dst_c = (void*)(buf_c + len_w); + dst_c[hots_w] = 0; + } + len_w += (hots_w + 1) * sizeof(c3_c*); + + u3_noun oth = hot; + c3_w i = 0; + while ( u3_nul != oth ) { + if (dst_c) dst_c[i] = (void*)(buf_c + len_w); + u3_noun h_oth = u3h(oth); + + len_w = u3_mcut_path(buf_c, len_w, '.', u3kb_flop(u3k(h_oth))); + len_w = u3_mcut_char(buf_c, len_w, '.'); + len_w = u3_mcut_char(buf_c, len_w, '\0'); + oth = u3t(oth); + + i++; + } + u3z(hot); + return len_w; +} + +/* u3_mcut_str(): measure/cut string. +*/ +c3_w +u3_mcut_str(c3_c* buf_c, c3_w len_w, c3_c* str) +{ + c3_w ten_w = strlen(str); + + if ( buf_c ) { + memcpy((c3_y*)(buf_c + len_w), str, ten_w); + } + return (len_w + ten_w); +} + +/* u3_mpef_turf(): measure/cut string list, prefixing. +*/ +c3_w +u3_mpef_turfs(c3_c* buf_c, c3_w len_w, c3_c* pef_c, c3_c** tuf_c) +{ + c3_c** dst_c = NULL; + + c3_w tufs_w = 0; + { + c3_c** uft_c = tuf_c; + while (NULL != *uft_c) { + tufs_w++; + uft_c++; + } + } + + if (buf_c) { + dst_c = (void*)(buf_c + len_w); + dst_c[tufs_w] = 0; + } + len_w += (tufs_w + 1) * sizeof(c3_c*); + + c3_w i = 0; + while ( NULL != tuf_c[i] ) { + if (dst_c) dst_c[i] = (void*)(buf_c + len_w); + len_w = u3_mcut_str(buf_c, len_w, pef_c); + len_w = u3_mcut_char(buf_c, len_w, '.'); + len_w = u3_mcut_str(buf_c, len_w, tuf_c[i]); + len_w = u3_mcut_char(buf_c, len_w, '\0'); + + i++; + } + return len_w; +} +