From b608007a6f648f352ecfb8320da3761b807e7e4d Mon Sep 17 00:00:00 2001 From: Ted Blackman Date: Fri, 1 Sep 2023 17:18:42 -0400 Subject: [PATCH 01/53] stun: WIP but compiles --- pkg/c3/motes.h | 1 + pkg/vere/io/ames.c | 215 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 212 insertions(+), 4 deletions(-) diff --git a/pkg/c3/motes.h b/pkg/c3/motes.h index a9fd4b701e..4f06492e37 100644 --- a/pkg/c3/motes.h +++ b/pkg/c3/motes.h @@ -996,6 +996,7 @@ # define c3__sard c3_s4('s','a','r','d') # define c3__sav c3_s3('s','a','v') # define c3__save c3_s4('s','a','v','e') +# define c3__saxo c3_s4('s','a','x','o') # define c3__scam c3_s4('s','c','a','m') # define c3__scan c3_s4('s','c','a','n') # define c3__scry c3_s4('s','c','r','y') diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 185afad073..ba0774e1f1 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -17,6 +17,12 @@ #define QUEUE_MAX 30 // max number of packets in queue +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 { @@ -45,6 +51,16 @@ c3_w imp_w[256]; // imperial IPs time_t imp_t[256]; // imperial IP timestamps c3_o imp_o[256]; // imperial print status + struct { // stun client state: + u3_stun_state sat_y; // formal state + c3_y tid_y[16]; // last transaction id + c3_d dad_d[2]; // sponsoring ship @p + u3_lane lan_u; // sponsoring ship IP and port + uv_timer_t tim_u; // keepalive timer handle + struct timeval las_u; // last sent date + struct timeval sar_u; // date we started trying to send + u3_lane sef_u; // our lane, if we know it + } sun_u; // struct { // config: c3_o net_o; // can send c3_o see_o; // can scry @@ -1173,6 +1189,193 @@ _fine_put_cache(u3_ames* sam_u, u3_noun pax, c3_w lop_w, u3_noun lis) } } +static void +_stun_stop(u3_ames* sam_u) +{ + switch ( sam_u->sun_u.sat_y ) { + case STUN_OFF: break; // ignore; already stopped + case STUN_TRYING: { + uv_timer_stop(&sam_u->sun_u.tim_u); + } break; + case STUN_KEEPALIVE: { + uv_timer_stop(&sam_u->sun_u.tim_u); + } break; + default: u3_assert(!"programmer error"); + } + sam_u->sun_u.sat_y = STUN_OFF; +} + +static void _stun_send_request(u3_ames*); // forward declaration + +static void +_stun_timer_cb(uv_timer_t* tim_u) +{ + u3_ames* sam_u = (u3_ames*)(tim_u->data); + 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: { + sam_u->sun_u.sat_y = STUN_TRYING; + _stun_send_request(sam_u); + } break; + case STUN_TRYING: { + c3_d gap_d; + { + struct timeval tim_tv; + gettimeofday(&tim_tv, 0); + u3_noun now = u3_time_in_tv(&tim_tv); + u3_noun den = u3_time_in_tv(&sam_u->sun_u.sar_u); + gap_d = u3_time_gap_ms(den, now); + } + if ( gap_d >= (5 * 1000) ) { + _stun_stop(sam_u); + // TODO inject event into arvo to ping repeatedly + } + else { + sam_u->sun_u.tim_u.data = sam_u; + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 1*1000, 0); + } + } break; + default: u3_assert(!"programmer error"); + } +} + +typedef struct _u3_stun_send { + uv_udp_send_t req_u; // uv udp request handle + u3_ames* sam_u; // backpointer to driver state +} u3_stun_send; + +static void +_stun_send_cb(uv_udp_send_t *req_u, c3_i sas_i) +{ + u3_stun_send* snd_u = (u3_stun_send*)req_u; + if ( sas_i ) { + // TODO take error handling action + } + else { + u3_ames* sam_u = snd_u->sam_u; + gettimeofday(&sam_u->sun_u.las_u, 0); // overwrite last sent date + } +} + +static void +_stun_on_response(u3_ames* sam_u) // TODO read arg +{ + u3_stun_state old_y = sam_u->sun_u.sat_y; + switch ( sam_u->sun_u.sat_y ) { + case STUN_OFF: break; // ignore; stray response + case STUN_KEEPALIVE: break; // ignore; duplicate response + case STUN_TRYING: { + sam_u->sun_u.sat_y = STUN_KEEPALIVE; + sam_u->sun_u.tid_y[1]++; + uv_timer_stop(&sam_u->sun_u.tim_u); + sam_u->sun_u.tim_u.data = sam_u; + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); + } break; + default: assert("programmer error"); + } +} + +static void +_stun_send_request(u3_ames* sam_u) +{ + u3_assert( STUN_OFF != sam_u->sun_u.sat_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); + + c3_y buf_y[20] = {0}; + buf_y[1] = 0x1; // message type "binding request" + memcpy(buf_y + 4, sam_u->sun_u.tid_y, 16); // TODO convert byte order? + + uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 20); + u3_stun_send* snd_u = c3_calloc(sizeof(*snd_u)); + snd_u->sam_u = sam_u; + c3_i sas_i = uv_udp_send( + (uv_udp_send_t*)snd_u, &sam_u->wax_u, &buf_u, 1, + (const struct sockaddr*)&add_u, _stun_send_cb + ); + + if ( sas_i ) { + u3l_log("stun: send fail_sync: %s", uv_strerror(sas_i)); + // TODO take error handling actions + } +} + +static void +_stun_czar_cb(uv_getaddrinfo_t* adr_u, + c3_i sas_i, + struct addrinfo* aif_u) +{ + u3_ames* sam_u; // TODO get sam_u from args + gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now + _stun_send_request(sam_u); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 1, 0); + +} + +static void +_stun_czar(u3_ames* sam_u) +{ + // TODO rip off _ames_czar() +} + +static void +_stun_start(u3_ames* sam_u, u3_noun dad) +{ + sam_u->sun_u.sat_y = STUN_TRYING; + u3r_chubs(0, 2, sam_u->sun_u.dad_d, dad); + u3z(dad); + + // initialize STUN transaction id to mug of now + { + u3_noun mug; + struct timeval tim_u; + gettimeofday(&tim_u, 0); + + mug = u3r_mug(u3_time_in_tv(&tim_u)); + memcpy(sam_u->sun_u.tid_y, (c3_y*)&mug, 4); + u3z(mug); + } + + _stun_czar(sam_u); +} + +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"); + return; + } + + dad = u3k(u3h(daz)); + if ( c3y == _ames_is_czar(dad) ) { + _stun_stop(sam_u); + _stun_start(sam_u, u3k(dad)); + } + + u3z(zad); u3z(daz); u3z(dad); +} /* _ames_ef_send(): send packet to network (v4). */ @@ -2064,10 +2267,11 @@ _ames_io_start(u3_ames* sam_u) { c3_s por_s = sam_u->pir_u->por_s; u3_noun who = u3i_chubs(2, sam_u->pir_u->who_d); - u3_noun rac = u3do("clan:title", u3k(who)); + c3_o zar_o = _ames_is_czar(who); c3_i ret_i; - if ( c3__czar == rac ) { + + 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); @@ -2097,7 +2301,7 @@ _ames_io_start(u3_ames* sam_u) { u3l_log("ames: bind: %s", uv_strerror(ret_i)); - if ( (c3__czar == rac) && + if ( (c3y == zar_o) && (UV_EADDRINUSE == ret_i) ) { u3l_log(" ...perhaps you've got two copies of vere running?"); @@ -2124,7 +2328,6 @@ _ames_io_start(u3_ames* sam_u) uv_udp_recv_start(&sam_u->wax_u, _ames_alloc, _ames_recv_cb); sam_u->car_u.liv_o = c3y; - u3z(rac); u3z(who); } @@ -2273,6 +2476,10 @@ _ames_kick_newt(u3_ames* sam_u, u3_noun tag, u3_noun dat) _ames_ef_turf(sam_u, u3k(dat)); ret_o = c3y; } break; + + case c3__saxo: { + _ames_ef_saxo(sam_u, u3k(dat)); + } break; } u3z(tag); u3z(dat); From ad238b55529f5178f45cd459fbfe2bfa2095936b Mon Sep 17 00:00:00 2001 From: Ted Blackman Date: Tue, 19 Sep 2023 18:27:50 -0400 Subject: [PATCH 02/53] stun: use later RFC for packet format --- pkg/vere/io/ames.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index ba0774e1f1..e66762c127 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1289,9 +1289,21 @@ _stun_send_request(u3_ames* sam_u) 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); + // see STUN RFC 8489 + // https://datatracker.ietf.org/doc/html/rfc8489#section-5 c3_y buf_y[20] = {0}; - buf_y[1] = 0x1; // message type "binding request" - memcpy(buf_y + 4, sam_u->sun_u.tid_y, 16); // TODO convert byte order? + + // STUN message type: "binding request" + buf_y[1] = 0x01; + + // STUN message length: 0 (header-only) + // (implicit in initialization) + + // STUN "magic cookie" 0x2112A442 in network byte order + buf_y[4] = 0x21; buf_y[5] = 0x12; buf_y[6] = 0xa4; buf_y[7] = 0x42; + + // STUN "transaction id" + memcpy(buf_y + 8, sam_u->sun_u.tid_y, 12); uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 20); u3_stun_send* snd_u = c3_calloc(sizeof(*snd_u)); From 2666d30b71d16796b9ff07db6e7bc31041a07e3e Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 20 Jun 2023 18:37:39 -0400 Subject: [PATCH 03/53] vere: bumps hoon kelvin to %138 --- pkg/vere/pier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index bba434c4fd..9d854e5280 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -815,7 +815,7 @@ _pier_wyrd_card(u3_pier* pir_u) u3_noun kel = u3nl(u3nc(c3__zuse, VERE_ZUSE), // XX from both king and serf? u3nc(c3__lull, VERE_LULL), // XX from both king and serf? u3nc(c3__arvo, 237), // XX from both king and serf? - u3nc(c3__hoon, 139), // god_u->hon_y + u3nc(c3__hoon, 138), // god_u->hon_y u3nc(c3__nock, 4), // god_u->noc_y u3_none); u3_noun wir = u3nc(c3__arvo, u3_nul); From 66208fe8e6a8b96210710d0b7c8749fda026b251 Mon Sep 17 00:00:00 2001 From: Alex Shelkovnykov Date: Sun, 4 Jun 2023 13:38:11 +0000 Subject: [PATCH 04/53] jets: match hoon changes to bif:by --- pkg/noun/jets/d/by_bif.c | 6 ++---- pkg/noun/jets/d/by_dif.c | 5 +++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pkg/noun/jets/d/by_bif.c b/pkg/noun/jets/d/by_bif.c index d9e27d1756..0a2f23a666 100644 --- a/pkg/noun/jets/d/by_bif.c +++ b/pkg/noun/jets/d/by_bif.c @@ -17,19 +17,17 @@ _b_bif_putroot(u3_noun a, else { u3_noun n_a, l_a, r_a; u3_noun p_n_a, q_n_a; - u3_noun p_b, q_b; u3x_trel(a, &n_a, &l_a, &r_a); - u3x_cell(b, &p_b, &q_b); u3x_cell(n_a, &p_n_a, &q_n_a); - if ( c3y == u3r_sing(p_b, p_n_a) ) { + if ( c3y == u3r_sing(b, p_n_a) ) { return u3nt(u3k(b), u3k(l_a), u3k(r_a)); } else { u3_noun c, n_c, l_c, r_c; u3_noun d; - if ( c3y == u3qc_gor(p_b, p_n_a) ) { + if ( c3y == u3qc_gor(b, p_n_a) ) { c = _b_bif_putroot(l_a, b); u3r_trel(c, &n_c, &l_c, &r_c); d = u3nt(u3k(n_c), diff --git a/pkg/noun/jets/d/by_dif.c b/pkg/noun/jets/d/by_dif.c index a3f35f3cde..44dcd1ad1b 100644 --- a/pkg/noun/jets/d/by_dif.c +++ b/pkg/noun/jets/d/by_dif.c @@ -61,11 +61,12 @@ u3qdb_dif(u3_noun a, return u3k(a); } else { - u3_noun n_b, l_b, r_b; + u3_noun n_b, p_n_b, q_n_b, l_b, r_b; u3_noun c, l_c, r_c; u3x_trel(b, &n_b, &l_b, &r_b); + u3x_cell(n_b, &p_n_b, &q_n_b); - c = u3qdb_bif(a, n_b); + c = u3qdb_bif(a, p_n_b); u3x_cell(c, &l_c, &r_c); u3_noun d = u3qdb_dif(l_c, l_b); From ca3612b08bf3c0e22afceb133a52566914a9f8a5 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Tue, 1 Aug 2023 12:09:44 -0400 Subject: [PATCH 05/53] vere: bump %lull kelvin to %322 --- pkg/vere/pier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 9d854e5280..535e492cb4 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -676,7 +676,7 @@ _pier_wyrd_fail(u3_pier* pir_u, u3_ovum* egg_u, u3_noun lud) // #define VERE_NAME "vere" #define VERE_ZUSE 412 -#define VERE_LULL 323 +#define VERE_LULL 322 /* _pier_wyrd_aver(): check for %wend effect and version downgrade. RETAIN */ From 9e01dcf09e11a5133887d77d742d126bb784ee6a Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Tue, 1 Aug 2023 12:10:18 -0400 Subject: [PATCH 06/53] vere: decrement zuse to %411 --- pkg/vere/pier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 535e492cb4..1065b59623 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -675,7 +675,7 @@ _pier_wyrd_fail(u3_pier* pir_u, u3_ovum* egg_u, u3_noun lud) // XX organizing version constants // #define VERE_NAME "vere" -#define VERE_ZUSE 412 +#define VERE_ZUSE 411 #define VERE_LULL 322 /* _pier_wyrd_aver(): check for %wend effect and version downgrade. RETAIN From 97826cb790273fcf26f1abb0498ec05bdcabe068 Mon Sep 17 00:00:00 2001 From: Pyry Kovanen Date: Wed, 23 Aug 2023 23:05:34 +0300 Subject: [PATCH 07/53] pier: decrement arvo kelvin --- pkg/vere/pier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/pier.c b/pkg/vere/pier.c index 1065b59623..5c5b047f3e 100644 --- a/pkg/vere/pier.c +++ b/pkg/vere/pier.c @@ -814,7 +814,7 @@ _pier_wyrd_card(u3_pier* pir_u) u3_nul); u3_noun kel = u3nl(u3nc(c3__zuse, VERE_ZUSE), // XX from both king and serf? u3nc(c3__lull, VERE_LULL), // XX from both king and serf? - u3nc(c3__arvo, 237), // XX from both king and serf? + u3nc(c3__arvo, 236), // XX from both king and serf? u3nc(c3__hoon, 138), // god_u->hon_y u3nc(c3__nock, 4), // god_u->noc_y u3_none); From 021054db6bab33d1b9121d1436f6ec3a1e622c58 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 22 Sep 2022 11:31:38 -0400 Subject: [PATCH 08/53] u3: rewrites jam atom encoding to maximize its range --- pkg/noun/serial.c | 54 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/pkg/noun/serial.c b/pkg/noun/serial.c index 698a959d66..f994814fe1 100644 --- a/pkg/noun/serial.c +++ b/pkg/noun/serial.c @@ -36,7 +36,7 @@ struct _cs_jam_fib { /* _cs_jam_fib_grow(): reallocate buffer with fibonacci growth */ -static void +static inline void _cs_jam_fib_grow(struct _cs_jam_fib* fib_u, c3_w mor_w) { c3_w wan_w = fib_u->bit_w + mor_w; @@ -45,6 +45,7 @@ _cs_jam_fib_grow(struct _cs_jam_fib* fib_u, c3_w mor_w) // if ( wan_w < mor_w ) { u3m_bail(c3__fail); + return; } if ( wan_w > fib_u->a_w ) { @@ -64,7 +65,7 @@ _cs_jam_fib_grow(struct _cs_jam_fib* fib_u, c3_w mor_w) /* _cs_jam_fib_chop(): chop [met_w] bits of [a] into [fib_u] */ -static void +static inline void _cs_jam_fib_chop(struct _cs_jam_fib* fib_u, c3_w met_w, u3_noun a) { c3_w bit_w = fib_u->bit_w; @@ -86,12 +87,51 @@ _cs_jam_fib_mat(struct _cs_jam_fib* fib_u, u3_noun a) _cs_jam_fib_chop(fib_u, 1, 1); } else { - c3_w a_w = u3r_met(0, a); - c3_w b_w = c3_bits_word(a_w); + c3_w a_w = u3r_met(0, a); + c3_w b_w = c3_bits_word(a_w); + c3_w bit_w = fib_u->bit_w; + + // amortize overflow checks and reallocation + // + { + c3_w met_w = a_w + (2 * b_w); + + if ( a_w > (UINT32_MAX - 64) ) { + u3m_bail(c3__fail); + return; + } + + _cs_jam_fib_grow(fib_u, met_w); + fib_u->bit_w += met_w; + } - _cs_jam_fib_chop(fib_u, b_w+1, 1 << b_w); - _cs_jam_fib_chop(fib_u, b_w-1, a_w & ((1 << (b_w-1)) - 1)); - _cs_jam_fib_chop(fib_u, a_w, a); + { + c3_w src_w[2]; + c3_w* buf_w = fib_u->sab_u->buf_w; + + // _cs_jam_fib_chop(fib_u, b_w+1, 1 << b_w); + // + { + c3_d dat_d = (c3_d)1 << b_w; + src_w[0] = (c3_w)dat_d; + src_w[1] = dat_d >> 32; + + u3r_chop_words(0, 0, b_w + 1, bit_w, buf_w, 2, src_w); + bit_w += b_w + 1; + } + + // _cs_jam_fib_chop(fib_u, b_w-1, a_w); + // + { + src_w[0] = a_w; + u3r_chop_words(0, 0, b_w - 1, bit_w, buf_w, 1, src_w); + bit_w += b_w - 1; + } + + // _cs_jam_fib_chop(fib_u, a_w, a); + // + u3r_chop(0, 0, a_w, bit_w, buf_w, a); + } } } From c0f563c1f42a96d32ec7e9b7f9fff3d6fdcca6a5 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 4 Oct 2023 22:14:29 -0400 Subject: [PATCH 09/53] vere: minimal jet dashboard compat for hoon %138 --- pkg/noun/jets/tree.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/pkg/noun/jets/tree.c b/pkg/noun/jets/tree.c index b0264327d1..86f6803ec5 100644 --- a/pkg/noun/jets/tree.c +++ b/pkg/noun/jets/tree.c @@ -1825,11 +1825,15 @@ static c3_c* _140_two__in_ha[] = { "1f0a6f8b945b243520b77069060589938d9e651e34b24924db9528d02a98014f", 0 }; - static u3j_harm _140_two__by_bif_a[] = {{".2", u3wdb_bif, c3y}, {}}; - static c3_c* _140_two__by_bif_ha[] = { - "d377a032a3866e76f6f5217c7c0ed0519b768d8b1c5107e35f7dbf18d8f60880", - 0 - }; + + // disabled for all due sharing, interface changed in hoon %138 + // + // static u3j_harm _140_two__by_bif_a[] = {{".2", u3wdb_bif, c3y}, {}}; + // static c3_c* _140_two__by_bif_ha[] = { + // "d377a032a3866e76f6f5217c7c0ed0519b768d8b1c5107e35f7dbf18d8f60880", + // 0 + // }; + static u3j_harm _140_two__by_del_a[] = {{".2", u3wdb_del, c3y}, {}}; static c3_c* _140_two__by_del_ha[] = { "09f78d6235d3fce8303c7bc663988349b7d4592abdacfb09b833d2f43629b6b6", @@ -1909,7 +1913,7 @@ static u3j_core _140_two__by_d[] = { { "all", 7, _140_two__by_all_a, 0, _140_two__by_all_ha }, { "any", 7, _140_two__by_any_a, 0, _140_two__by_any_ha }, { "apt", 7, _140_two__by_apt_a, 0, _140_two__by_apt_ha }, - { "bif", 7, _140_two__by_bif_a, 0, _140_two__by_bif_ha }, + // { "bif", 7, _140_two__by_bif_a, 0, _140_two__by_bif_ha }, { "del", 7, _140_two__by_del_a, 0, _140_two__by_del_ha }, { "dif", 7, _140_two__by_dif_a, 0, _140_two__by_dif_ha }, { "gas", 7, _140_two__by_gas_a, 0, _140_two__by_gas_ha }, @@ -2356,6 +2360,11 @@ u3j_core _k139_d[] = {} }; +u3j_core _k138_d[] = +{ { "one", 3, 0, _139_one_d, no_hashes }, + {} +}; + // TODO: probably need different ha hashes @@ -2425,6 +2434,7 @@ u3j_core _a50_d[] = static u3j_core _d[] = { { "k140", 0, 0, _k140_d, _k140_ha, 0, (u3j_core*) 140, 0 }, { "k139", 0, 0, _k139_d, no_hashes, 0, (u3j_core*) 139, 0 }, + { "k138", 0, 0, _k138_d, no_hashes, 0, (u3j_core*) 138, 0 }, { "a50", 0, 0, _a50_d, _k140_ha, 0, (u3j_core*) c3__a50, 0 }, {} }; From 50b62cd2cbc67e70c6c8c2989440e72dc0cbc562 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 25 Oct 2023 08:41:20 +0200 Subject: [PATCH 10/53] stun: inject %stun task into %ames --- pkg/c3/motes.h | 1 + pkg/vere/io/ames.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/pkg/c3/motes.h b/pkg/c3/motes.h index 45dd096479..f5ad370ef0 100644 --- a/pkg/c3/motes.h +++ b/pkg/c3/motes.h @@ -1112,6 +1112,7 @@ # define c3__ston c3_s4('s','t','o','n') # define c3__stop c3_s4('s','t','o','p') # define c3__stub c3_s4('s','t','u','b') +# define c3__stun c3_s4('s','t','u','n') # define c3__stur c3_s4('s','t','u','r') # define c3__sub c3_s3('s','u','b') # define c3__sunt c3_s4('s','u','n','t') diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index f7ee59886a..b96f54ec62 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1270,6 +1270,11 @@ _stun_on_response(u3_ames* sam_u) // TODO read arg uv_timer_stop(&sam_u->sun_u.tim_u); sam_u->sun_u.tim_u.data = sam_u; uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); + // inject %stun task into arvo + u3_noun wir = u3nc(c3__ames, u3_nul); + u3_noun cad = u3nc(c3__stun, c3n); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); } break; default: assert("programmer error"); } From af0ca4fb233be87d917d0d15255ef7596ba229b8 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 25 Oct 2023 08:42:26 +0200 Subject: [PATCH 11/53] stun: init timer in stun callback --- pkg/vere/io/ames.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index b96f54ec62..ccedac2d15 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1326,11 +1326,14 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, c3_i sas_i, struct addrinfo* aif_u) { - u3_ames* sam_u; // TODO get sam_u from args + u3_ames* sam_u = (u3_ames*)(adr_u->data); gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now + _stun_send_request(sam_u); - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 1, 0); + sam_u->sun_u.tim_u.data = sam_u; + uv_timer_init(u3L, &sam_u->sun_u.tim_u); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 1, 0); } static void From ff1466972ff1ca0139cee1dd748df9ff7f9740e4 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 25 Oct 2023 08:43:14 +0200 Subject: [PATCH 12/53] stun: don't stun if we are a galaxy --- pkg/vere/io/ames.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index ccedac2d15..b0419c4c5f 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1386,7 +1386,11 @@ _ames_ef_saxo(u3_ames* sam_u, u3_noun zad) } dad = u3k(u3h(daz)); - if ( c3y == _ames_is_czar(dad) ) { + u3_noun our = u3i_chubs(2, sam_u->pir_u->who_d); + + if ( c3y == _ames_is_czar(dad) && c3n == _ames_is_czar(our)) { + // if we are a galaxy, don't STUN + u3l_log("ames: start STUN"); _stun_stop(sam_u); _stun_start(sam_u, u3k(dad)); } From 27bbc7897a589204ebfaa5baa7566e9f302a8a57 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 25 Oct 2023 08:44:50 +0200 Subject: [PATCH 13/53] stun: stun sponsor galaxy note: will need to be refactored -- copied from _ames_czar --- pkg/vere/io/ames.c | 102 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index b0419c4c5f..285000f00d 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1339,7 +1339,107 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, static void _stun_czar(u3_ames* sam_u) { - // TODO rip off _ames_czar() + // TODO rip off _ames_czar() + c3_y imp_y = sam_u->sun_u.dad_d[0]; + + u3l_log("stun : %i", imp_y); + + sam_u->sun_u.lan_u.por_s = _ames_czar_port(imp_y); + + if (c3n == u3_Host.ops_u.net) { + // XX remove/fix + sam_u->sun_u.lan_u.pip_w = 0x7f000001; + u3l_log("sending"); + + _stun_send_request(sam_u); + + // XX timer stuff to be removed + // XX maybe enabled with a flag? + + u3l_log("start timer"); + uv_timer_t* tim_u = c3_malloc(sizeof(*tim_u)); + sam_u->sun_u.tim_u.data = sam_u; + gettimeofday(&sam_u->sun_u.sar_u, 0); + uv_timer_init(u3L, &sam_u->sun_u.tim_u); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 1, 0); + + return; + } + + // if we don't have a galaxy domain, no-op + // + if (!sam_u->dns_c) { + u3_noun nam = u3dc("scot", 'p', imp_y); + c3_c *nam_c = u3r_string(nam); + u3l_log("ames: no galaxy domain for %s, no-op\r", nam_c); + + c3_free(nam_c); + u3z(nam); + return; + } + + { + c3_w pip_w = sam_u->imp_w[imp_y]; + time_t wen = sam_u->imp_t[imp_y]; + time_t now = time(0); + + // XX keep the same 5 minutes as ames? + // backoff for 5 minutes after failed lookup + // + if ((now < wen) // time shenanigans! + || ((0xffffffff == pip_w) // sentinal ip address + && ((now - wen) < 300))) { + return; + } + // cached addresses have a 5 minute TTL + // + else if ((0 != pip_w) && ((now - wen) < 300)) { + sam_u->sun_u.lan_u.pip_w = pip_w; + _stun_send_request(sam_u); + return; + } else { + c3_i sas_i; + c3_c dns_c[255]; + + { + u3_noun nam = u3dc("scot", 'p', imp_y); + c3_c *nam_c = u3r_string(nam); + + // NB: . separator not counted, as [nam_c] includes a ~ that we skip + // + // dns_c = + // c3_malloc(1 + strlen(nam_c) + strlen(sam_u->dns_c)); + + sas_i = + snprintf(dns_c, 255, "%s.%s", nam_c + 1, sam_u->dns_c); + + c3_free(nam_c); + u3z(nam); + } + + if (255 <= sas_i) { + u3l_log("ames: czar: galaxy domain %s truncated", sam_u->dns_c); + return; + } + + { + + uv_getaddrinfo_t* adr_u = c3_malloc(sizeof(*adr_u)); + adr_u->data = sam_u; + + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; // only IPv4 addresses + + if (0 != (sas_i = uv_getaddrinfo(u3L, adr_u, _stun_czar_cb, + dns_c, 0, &hints))) { + u3l_log("stun: %s", uv_strerror(sas_i)); + // XX TODO handle error + return; + } + } + } + } } static void From 5bc1013418b25261d08970dfd9946535f55300a1 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 25 Oct 2023 08:48:06 +0200 Subject: [PATCH 14/53] stun: handle stun requests & responses --- pkg/vere/io/ames.c | 75 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 285000f00d..ee96d078d3 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1257,6 +1257,63 @@ _stun_send_cb(uv_udp_send_t *req_u, c3_i sas_i) } } +static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], + const struct sockaddr* adr_u) { + // XX TODO + + c3_y buf_y[36] = {0}; + + // copy STUN request header + memcpy(buf_y, buf_r, 0); + + // 0x0101 SUCCESS RESPONSE + buf_y[0] = 0x01; + buf_y[1] = 0x01; + + // XX TODO: add sponsee's IP Addres (32 bits) + // use _ames_etch functions + // + buf_y[22] = 0x01; // 21-22 STUN attribute type 0x0001 + buf_y[24] = 0x10; // 23-24 STUN attribute length + buf_y[26] = 0x01; // 25-26 family 0x01:IPv4 + buf_y[27] = 0x01; // 27-28 family 0x01:IPv4 + // Port + //buf_y[27] = (adr_u.sin_port >> 8); // Most significant byte + //buf_y[28] = adr_u.sin_port & 0xFF; // Least significant byte + _ames_etch_short(buf_y + 16, adr_u.sin_port); + + buf_y[29] = adr_u.sin_addr.s_addr >> 24; + buf_y[28] = adr_u.sin_addr.s_addr >> 16; + buf_y[28] = adr_u.sin_addr.s_addr >> 8; + buf_y[28] = adr_u.sin_addr.s_addr & 0xFFFF; + + u3l_log("hear request"); + 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(lan_u.pip_w); + // add_u.sin_port = htons(lan_u.por_s); + + // u3l_log("(%d %d)", add_u.sin_addr.s_addr, add_u.sin_port); + + uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 20); + u3_stun_send* snd_u = c3_calloc(sizeof(*snd_u)); + snd_u->sam_u = sam_u; + c3_i sas_i = uv_udp_send( + (uv_udp_send_t*)snd_u, &sam_u->wax_u, &buf_u, 1, + adr_u, _stun_send_cb + ); + + u3l_log("sas %d", sas_i); + + if ( sas_i != 0) { + u3l_log("stun: send response fail_sync: %s", uv_strerror(sas_i)); + // TODO take error handling actions + // XX sam_u->fig_u.net_o = c3n; + } +} + static void _stun_on_response(u3_ames* sam_u) // TODO read arg { @@ -1315,7 +1372,7 @@ _stun_send_request(u3_ames* sam_u) (const struct sockaddr*)&add_u, _stun_send_cb ); - if ( sas_i ) { + if ( sas_i != 0) { u3l_log("stun: send fail_sync: %s", uv_strerror(sas_i)); // TODO take error handling actions } @@ -2369,6 +2426,22 @@ _ames_recv_cb(uv_udp_t* wax_u, } c3_free(buf_u->base); } + else if ( nrd_i == 20 ) { + // STUN resquest/response + // TODO sanity checks + // TODO check STUN cookie + u3_ames* sam_u = wax_u->data; + + if (buf_u->base[0] == 0x0 && buf_u->base[1] == 0x01) { + // STUN request + _stun_on_request(sam_u, (c3_y *)buf_u->base, adr_u); + } else if ((buf_u->base[0] == 0x01 && buf_u->base[1] == 0x01)) { + // STUN response + _stun_on_response(sam_u); + } else { + // TODO STUN error + } + } else { u3_ames* sam_u = wax_u->data; struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; From b7c2b41d1c2434eeeaf100687cf2efc2ebf987f1 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 26 Oct 2023 06:21:20 +0200 Subject: [PATCH 15/53] stun: send heard lane to requester --- pkg/vere/io/ames.c | 87 +++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 51 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index ee96d078d3..7e75afac81 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1260,44 +1260,26 @@ _stun_send_cb(uv_udp_send_t *req_u, c3_i sas_i) static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], const struct sockaddr* adr_u) { // XX TODO - - c3_y buf_y[36] = {0}; + struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; + c3_y buf_y[32] = {0}; // copy STUN request header - memcpy(buf_y, buf_r, 0); - - // 0x0101 SUCCESS RESPONSE - buf_y[0] = 0x01; - buf_y[1] = 0x01; - - // XX TODO: add sponsee's IP Addres (32 bits) - // use _ames_etch functions - // - buf_y[22] = 0x01; // 21-22 STUN attribute type 0x0001 - buf_y[24] = 0x10; // 23-24 STUN attribute length - buf_y[26] = 0x01; // 25-26 family 0x01:IPv4 - buf_y[27] = 0x01; // 27-28 family 0x01:IPv4 - // Port - //buf_y[27] = (adr_u.sin_port >> 8); // Most significant byte - //buf_y[28] = adr_u.sin_port & 0xFF; // Least significant byte - _ames_etch_short(buf_y + 16, adr_u.sin_port); - - buf_y[29] = adr_u.sin_addr.s_addr >> 24; - buf_y[28] = adr_u.sin_addr.s_addr >> 16; - buf_y[28] = adr_u.sin_addr.s_addr >> 8; - buf_y[28] = adr_u.sin_addr.s_addr & 0xFFFF; - - u3l_log("hear request"); - 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(lan_u.pip_w); - // add_u.sin_port = htons(lan_u.por_s); - - // u3l_log("(%d %d)", add_u.sin_addr.s_addr, add_u.sin_port); - - uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 20); + memcpy(buf_y, buf_r, 20); + + c3_w cur_w = 20; // STUN header is 20 bytes + buf_y[0] = 0x01; buf_y[1] = 0x01; // 0x0101 SUCCESS RESPONSE + buf_y[2] = 0x00; buf_y[3] = 0x0c; // 12 bytes + buf_y[cur_w] = 0x00; buf_y[cur_w + 1] = 0x01; // STUN attribute type 0x0001 + buf_y[cur_w + 2] = 0x00; buf_y[cur_w + 3] = 0x08; // STUN attribute length + // extra reserved 0x0 byte + // XX use memcpy instead? + _ames_etch_short(buf_y + cur_w+ 5, 0x01); // family 0x01:IPv4 + _ames_etch_short(buf_y + cur_w+ 6, add_u->sin_port); // Port + _ames_etch_word(buf_y + cur_w+ 8, htonl(add_u->sin_addr.s_addr)); // IP Addres + + uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 32); + u3l_log("hear request on %u", add_u->sin_addr.s_addr); + u3l_log("send ip: %u", _ames_sift_word(buf_y + 28)); u3_stun_send* snd_u = c3_calloc(sizeof(*snd_u)); snd_u->sam_u = sam_u; c3_i sas_i = uv_udp_send( @@ -1305,8 +1287,6 @@ static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], adr_u, _stun_send_cb ); - u3l_log("sas %d", sas_i); - if ( sas_i != 0) { u3l_log("stun: send response fail_sync: %s", uv_strerror(sas_i)); // TODO take error handling actions @@ -2426,23 +2406,27 @@ _ames_recv_cb(uv_udp_t* wax_u, } c3_free(buf_u->base); } - else if ( nrd_i == 20 ) { - // STUN resquest/response - // TODO sanity checks - // TODO check STUN cookie - u3_ames* sam_u = wax_u->data; - - if (buf_u->base[0] == 0x0 && buf_u->base[1] == 0x01) { + // STUN resquest/response + // TODO sanity checks + // TODO check STUN cookie + else if (buf_u->base[0] == 0x0 && buf_u->base[1] == 0x01) { // STUN request + u3_ames* sam_u = wax_u->data; _stun_on_request(sam_u, (c3_y *)buf_u->base, adr_u); - } else if ((buf_u->base[0] == 0x01 && buf_u->base[1] == 0x01)) { + } else if ((buf_u->base[0] == 0x01 && buf_u->base[1] == 0x01)) { // STUN response + u3_ames* sam_u = wax_u->data; + + c3_w ip_addr = _ames_sift_word(buf_u->base + 28); + c3_s port = _ames_sift_short(buf_u->base + 26); + + u3l_log("ip: %u", ntohl(ip_addr)); + u3l_log("port: %u", ntohs(port)); + // Cache lane + sam_u->sun_u.sef_u.por_s = ntohs(port); + sam_u->sun_u.sef_u.pip_w = ntohs(ip_addr); _stun_on_response(sam_u); - } else { - // TODO STUN error - } - } - else { + } else { u3_ames* sam_u = wax_u->data; struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; u3_lane lan_u; @@ -2675,6 +2659,7 @@ _ames_kick_newt(u3_ames* sam_u, u3_noun tag, u3_noun dat) case c3__saxo: { _ames_ef_saxo(sam_u, u3k(dat)); + ret_o = c3y; } break; } From 98ce42f5adbcee6b678d354b4d6b84300f740432 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 26 Oct 2023 14:15:00 +0200 Subject: [PATCH 16/53] stun: add sanity checks on response --- pkg/vere/io/ames.c | 61 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 7e75afac81..8f1c449f29 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1272,10 +1272,9 @@ static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], buf_y[cur_w] = 0x00; buf_y[cur_w + 1] = 0x01; // STUN attribute type 0x0001 buf_y[cur_w + 2] = 0x00; buf_y[cur_w + 3] = 0x08; // STUN attribute length // extra reserved 0x0 byte - // XX use memcpy instead? - _ames_etch_short(buf_y + cur_w+ 5, 0x01); // family 0x01:IPv4 - _ames_etch_short(buf_y + cur_w+ 6, add_u->sin_port); // Port - _ames_etch_word(buf_y + cur_w+ 8, htonl(add_u->sin_addr.s_addr)); // IP Addres + buf_y[cur_w + 5] = 0x01; // family 0x01:IPv4 + memcpy(buf_y + cur_w + 6, &add_u->sin_port, 2); // Port + memcpy(buf_y + cur_w + 8, &add_u->sin_addr.s_addr, 4); // IP Addres uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 32); u3l_log("hear request on %u", add_u->sin_addr.s_addr); @@ -1307,11 +1306,7 @@ _stun_on_response(u3_ames* sam_u) // TODO read arg uv_timer_stop(&sam_u->sun_u.tim_u); sam_u->sun_u.tim_u.data = sam_u; uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); - // inject %stun task into arvo - u3_noun wir = u3nc(c3__ames, u3_nul); - u3_noun cad = u3nc(c3__stun, c3n); - u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); - u3_auto_plan(&sam_u->car_u, ovo_u); + } break; default: assert("programmer error"); } @@ -1500,6 +1495,18 @@ _stun_start(u3_ames* sam_u, u3_noun dad) _stun_czar(sam_u); } +static c3_o +_stun_is_our_response(c3_y buf_y[32], c3_y tid_y[12], c3_w buf_len) +{ + c3_w cookie = htonl(0x2112A442); + + return !(buf_len == 32 && + buf_y[0] == 0x01 && buf_y[1] == 0x01 && + memcmp(&cookie, buf_y + 4, 4) == 0 && + memcmp(tid_y, buf_y + 8, 12) == 0 + ); +} + static c3_o _ames_is_czar(u3_noun who) { @@ -2391,6 +2398,8 @@ _ames_recv_cb(uv_udp_t* wax_u, const struct sockaddr* adr_u, unsigned flg_i) { + u3_ames* 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)); @@ -2406,25 +2415,41 @@ _ames_recv_cb(uv_udp_t* wax_u, } c3_free(buf_u->base); } - // STUN resquest/response - // TODO sanity checks - // TODO check STUN cookie else if (buf_u->base[0] == 0x0 && buf_u->base[1] == 0x01) { // STUN request + // TODO more sanity checks on proper STUN requests? u3_ames* sam_u = wax_u->data; _stun_on_request(sam_u, (c3_y *)buf_u->base, adr_u); - } else if ((buf_u->base[0] == 0x01 && buf_u->base[1] == 0x01)) { + } else if (_stun_is_our_response(buf_u->base, sam_u->sun_u.tid_y, nrd_i) + == c3y) { // STUN response - u3_ames* sam_u = wax_u->data; - c3_w ip_addr = _ames_sift_word(buf_u->base + 28); c3_s port = _ames_sift_short(buf_u->base + 26); u3l_log("ip: %u", ntohl(ip_addr)); u3l_log("port: %u", ntohs(port)); - // Cache lane - sam_u->sun_u.sef_u.por_s = ntohs(port); - sam_u->sun_u.sef_u.pip_w = ntohs(ip_addr); + // New lane + u3_lane lan_u; + lan_u.por_s = ntohs(port); + lan_u.pip_w = ntohs(ip_addr); + + u3_noun wir = u3nc(c3__ames, u3_nul); + if (sam_u->sun_u.sef_u.por_s == 0 && sam_u->sun_u.sef_u.pip_w == 0) { + // inject %stun task into arvo + u3l_log("First STUN response"); + u3_noun cad = u3nc(c3__stun, c3n); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + } + else 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) { + // inject %once task into arvo + u3l_log("IP port changed"); + u3_noun cad = u3nc(c3__once, u3_nul); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + } + sam_u->sun_u.sef_u = lan_u; _stun_on_response(sam_u); } else { u3_ames* sam_u = wax_u->data; From e70f06a0212e2d67344ceab9438df0c5a04add17 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 8 Nov 2023 12:19:34 +0100 Subject: [PATCH 17/53] stun: encode ip in xor-mapped-address attribute --- pkg/vere/io/ames.c | 89 +++++++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 32 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 8f1c449f29..dc770a4f68 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1258,27 +1258,38 @@ _stun_send_cb(uv_udp_send_t *req_u, c3_i sas_i) } static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], - const struct sockaddr* adr_u) { + const struct sockaddr* adr_u) { // XX TODO struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; - c3_y buf_y[32] = {0}; + c3_y buf_y[44] = {0}; + c3_w cookie = 0x2112A442; - // copy STUN request header - memcpy(buf_y, buf_r, 20); + c3_w cur_w = 20; // STUN header is 20 bytes + memcpy(buf_y, buf_r, cur_w); // copy STUN request header + buf_y[0] = 0x01; buf_y[1] = 0x01; // 0x0101 SUCCESS RESPONSE + buf_y[2] = 0x00; buf_y[3] = 0x18; // Length: 24 bytes - c3_w cur_w = 20; // STUN header is 20 bytes - buf_y[0] = 0x01; buf_y[1] = 0x01; // 0x0101 SUCCESS RESPONSE - buf_y[2] = 0x00; buf_y[3] = 0x0c; // 12 bytes - buf_y[cur_w] = 0x00; buf_y[cur_w + 1] = 0x01; // STUN attribute type 0x0001 + // MAPPED-ADDRESS + buf_y[cur_w] = 0x00; buf_y[cur_w + 1] = 0x01; // attribute type 0x0001 buf_y[cur_w + 2] = 0x00; buf_y[cur_w + 3] = 0x08; // STUN attribute length // extra reserved 0x0 byte - buf_y[cur_w + 5] = 0x01; // family 0x01:IPv4 - memcpy(buf_y + cur_w + 6, &add_u->sin_port, 2); // Port + buf_y[cur_w + 5] = 0x01; // family 0x01:IPv4 + memcpy(buf_y + cur_w + 6, &add_u->sin_port, 2); // Port memcpy(buf_y + cur_w + 8, &add_u->sin_addr.s_addr, 4); // IP Addres - uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 32); - u3l_log("hear request on %u", add_u->sin_addr.s_addr); - u3l_log("send ip: %u", _ames_sift_word(buf_y + 28)); + // XOR-MAPPED-ADDRESS + buf_y[cur_w + 12] = 0x00; buf_y[cur_w + 13] = 0x20; // attribute type 0x00020 + buf_y[cur_w + 14] = 0x00; buf_y[cur_w + 15] = 0x08; // STUN attribute length + // extra reserved 0x0 byte + buf_y[cur_w + 17] = 0x01; // family 0x01:IPv4 + + c3_s x_port = htons(ntohs(add_u->sin_port) ^ cookie >> 16); + c3_w x_ip = htonl(ntohl(add_u->sin_addr.s_addr) ^ cookie); + memcpy(buf_y + cur_w + 18, &x_port, 2); // X-Port + memcpy(buf_y + cur_w + 20, &x_ip, 4); // X-IP Addres + + uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 44); + u3_stun_send* snd_u = c3_calloc(sizeof(*snd_u)); snd_u->sam_u = sam_u; c3_i sas_i = uv_udp_send( @@ -1496,17 +1507,29 @@ _stun_start(u3_ames* sam_u, u3_noun dad) } static c3_o -_stun_is_our_response(c3_y buf_y[32], c3_y tid_y[12], c3_w buf_len) +_stun_is_our_response(c3_y buf_y[44], c3_y tid_y[12], c3_w buf_len) { c3_w cookie = htonl(0x2112A442); - return !(buf_len == 32 && + return !(buf_len == 44 && buf_y[0] == 0x01 && buf_y[1] == 0x01 && memcmp(&cookie, buf_y + 4, 4) == 0 && memcmp(tid_y, buf_y + 8, 12) == 0 ); } +static c3_o +_stun_is_request(c3_y buf_y[32], c3_w buf_len) +{ + c3_w cookie = htonl(0x2112A442); + + return !(buf_len >= 20 && // at least the STUN header + buf_y[0] == 0x0 && buf_y[1] == 0x01 && + memcmp(&cookie, buf_y + 4, 4) == 0 + ); + +} + static c3_o _ames_is_czar(u3_noun who) { @@ -2415,37 +2438,39 @@ _ames_recv_cb(uv_udp_t* wax_u, } c3_free(buf_u->base); } - else if (buf_u->base[0] == 0x0 && buf_u->base[1] == 0x01) { - // STUN request - // TODO more sanity checks on proper STUN requests? + else if (_stun_is_request(buf_u->base, nrd_i) == c3y) { u3_ames* sam_u = wax_u->data; _stun_on_request(sam_u, (c3_y *)buf_u->base, adr_u); } else if (_stun_is_our_response(buf_u->base, sam_u->sun_u.tid_y, nrd_i) == c3y) { - // STUN response - c3_w ip_addr = _ames_sift_word(buf_u->base + 28); - c3_s port = _ames_sift_short(buf_u->base + 26); + c3_w cookie = 0x2112A442; + c3_w ip_addr_map = _ames_sift_word(buf_u->base + 28); + c3_s port_map = _ames_sift_short(buf_u->base + 26); + + c3_w ip_addr_xor = _ames_sift_word(buf_u->base + 28 + 12); + c3_s port_xor = _ames_sift_short(buf_u->base + 26 + 12); u3l_log("ip: %u", ntohl(ip_addr)); u3l_log("port: %u", ntohs(port)); // New lane u3_lane lan_u; - lan_u.por_s = ntohs(port); - lan_u.pip_w = ntohs(ip_addr); + lan_u.por_s = ntohs(htons(port_xor) ^ cookie >> 16); + lan_u.pip_w = ntohl(htonl(ip_addr_xor) ^ cookie); u3_noun wir = u3nc(c3__ames, u3_nul); - if (sam_u->sun_u.sef_u.por_s == 0 && sam_u->sun_u.sef_u.pip_w == 0) { - // inject %stun task into arvo - u3l_log("First STUN response"); - u3_noun cad = u3nc(c3__stun, c3n); - u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); - u3_auto_plan(&sam_u->car_u, ovo_u); - } - else if (sam_u->sun_u.sef_u.por_s != lan_u.por_s || + 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) { // inject %once task into arvo u3l_log("IP port changed"); - u3_noun cad = u3nc(c3__once, u3_nul); + u3_noun cad = u3nt(c3__stun, c3__once, u3_nul); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + } else { + // XX previously, only the first STUN response would stop the ping app + // now, every successful response injects the %stop task, and %ping + // takes care of handling that appropiatedly + // inject %stun task into arvo + u3_noun cad = u3nt(c3__stun, c3__stop, u3_nul); u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); u3_auto_plan(&sam_u->car_u, ovo_u); } From 0f934da564d9b4eed008c84ba5580682af3d7fdd Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 8 Nov 2023 12:26:36 +0100 Subject: [PATCH 18/53] stun: better resend times and error handling --- pkg/vere/io/ames.c | 118 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 20 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index dc770a4f68..515a167eb1 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1202,7 +1202,33 @@ _stun_stop(u3_ames* sam_u) sam_u->sun_u.sat_y = STUN_OFF; } -static void _stun_send_request(u3_ames*); // forward declaration +// forward declaration(s) +static void _stun_send_request(u3_ames*); +static void _stun_on_lost(uv_timer_t* tim_u); +static void _stun_czar_gone(u3_ames* sam_u, time_t now); +static void _stun_czar(u3_ames* sam_u); + +/* _stun_on_reset(): wrapper callback to resolve DNS again after STUN failure +*/ +static void +_stun_on_reset(uv_timer_t* tim_u) +{ + u3_ames* sam_u = (u3_ames*)(tim_u->data); + _stun_czar(sam_u); +} + +/* _stun_reset(): stun failed. stop STUNing and re-start DNS resolution + */ +static void +_stun_reset(u3_ames* sam_u, c3_w when) +{ + sam_u->fig_u.net_o = c3n; + _stun_stop(sam_u); + gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now + sam_u->sun_u.sat_y = STUN_TRYING; + sam_u->sun_u.tim_u.data = sam_u; + uv_timer_start(&sam_u->sun_u.tim_u, _stun_on_reset, when, 0); +} static void _stun_timer_cb(uv_timer_t* tim_u) @@ -1216,8 +1242,12 @@ _stun_timer_cb(uv_timer_t* tim_u) case STUN_KEEPALIVE: { sam_u->sun_u.sat_y = STUN_TRYING; _stun_send_request(sam_u); + sam_u->sun_u.tim_u.data = sam_u; + gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now + uv_timer_start(&sam_u->sun_u.tim_u, _stun_on_lost, 500, 0); } break; case STUN_TRYING: { + c3_w rto = 500; c3_d gap_d; { struct timeval tim_tv; @@ -1226,13 +1256,15 @@ _stun_timer_cb(uv_timer_t* tim_u) u3_noun den = u3_time_in_tv(&sam_u->sun_u.sar_u); gap_d = u3_time_gap_ms(den, now); } - if ( gap_d >= (5 * 1000) ) { - _stun_stop(sam_u); - // TODO inject event into arvo to ping repeatedly - } - else { + if ( gap_d >= (31500) ) { + u3l_log("stun: more than 31 seconds passed..."); + _stun_on_lost(&sam_u->sun_u.tim_u); + _stun_send_request(sam_u); + } else { sam_u->sun_u.tim_u.data = sam_u; - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 1*1000, 0); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, + ((gap_d * 2) + rto - gap_d), 0); + _stun_send_request(sam_u); } } break; default: u3_assert(!"programmer error"); @@ -1249,7 +1281,8 @@ _stun_send_cb(uv_udp_send_t *req_u, c3_i sas_i) { u3_stun_send* snd_u = (u3_stun_send*)req_u; if ( sas_i ) { - // TODO take error handling action + u3l_log("stun: send callback fail_async: %s", uv_strerror(sas_i)); + _stun_reset(snd_u->sam_u, 1*1000); // XX } else { u3_ames* sam_u = snd_u->sam_u; @@ -1299,8 +1332,7 @@ static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], if ( sas_i != 0) { u3l_log("stun: send response fail_sync: %s", uv_strerror(sas_i)); - // TODO take error handling actions - // XX sam_u->fig_u.net_o = c3n; + _stun_reset(sam_u, 1*1000); } } @@ -1323,6 +1355,23 @@ _stun_on_response(u3_ames* sam_u) // TODO read arg } } +static void +_stun_on_lost(uv_timer_t* tim_u) +{ + u3_ames* sam_u = (u3_ames*)(tim_u->data); + u3l_log("stun: waited too long..."); + uv_timer_stop(&sam_u->sun_u.tim_u); + // inject event into arvo to %kick ping app + u3_noun wir = u3nc(c3__ames, u3_nul); + u3_noun cad = u3nt(c3__stun, c3__fail, u3_nul); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + sam_u->sun_u.sat_y = STUN_TRYING; + gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now + // resolve DNS again, and (re)start STUNing + uv_timer_start(&sam_u->sun_u.tim_u, _stun_on_reset, 1, 0); +} + static void _stun_send_request(u3_ames* sam_u) { @@ -1359,8 +1408,8 @@ _stun_send_request(u3_ames* sam_u) ); if ( sas_i != 0) { - u3l_log("stun: send fail_sync: %s", uv_strerror(sas_i)); - // TODO take error handling actions + u3l_log("stun: send request fail_sync: %s", uv_strerror(sas_i)); + _stun_reset(sam_u, 1*1000); // XX } } @@ -1372,18 +1421,22 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, u3_ames* sam_u = (u3_ames*)(adr_u->data); gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now - _stun_send_request(sam_u); + if (sas_i != 0) { + u3l_log("stun: _stun_czar_cb request fail_sync: %s", uv_strerror(sas_i)); + _stun_reset(sam_u, 1*1000); // XX + } else { + _stun_send_request(sam_u); - sam_u->sun_u.tim_u.data = sam_u; - uv_timer_init(u3L, &sam_u->sun_u.tim_u); - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 1, 0); + sam_u->sun_u.tim_u.data = sam_u; + uv_timer_init(u3L, &sam_u->sun_u.tim_u); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); + } } static void _stun_czar(u3_ames* sam_u) { - // TODO rip off _ames_czar() - c3_y imp_y = sam_u->sun_u.dad_d[0]; + c3_d imp_y = sam_u->sun_u.dad_d[0]; u3l_log("stun : %i", imp_y); @@ -1404,7 +1457,7 @@ _stun_czar(u3_ames* sam_u) sam_u->sun_u.tim_u.data = sam_u; gettimeofday(&sam_u->sun_u.sar_u, 0); uv_timer_init(u3L, &sam_u->sun_u.tim_u); - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 1, 0); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); return; } @@ -1477,7 +1530,8 @@ _stun_czar(u3_ames* sam_u) if (0 != (sas_i = uv_getaddrinfo(u3L, adr_u, _stun_czar_cb, dns_c, 0, &hints))) { u3l_log("stun: %s", uv_strerror(sas_i)); - // XX TODO handle error + _stun_czar_gone(sam_u, now); + _stun_reset(sam_u, 1*1000); // try again in XX return; } } @@ -1485,6 +1539,30 @@ _stun_czar(u3_ames* sam_u) } } +// XX refactor (see _ames_czar_gone) +/* _stun_czar_gone(): galaxy address resolution failed. +*/ +static void +_stun_czar_gone(u3_ames* sam_u, time_t now) +{ + c3_d imp_y = sam_u->sun_u.dad_d[0]; + + if ( c3y == sam_u->imp_o[imp_y] ) { + u3l_log("stun: czar at %s: not found (b)", sam_u->dns_c); // XX + sam_u->imp_o[imp_y] = c3n; + } + + if ( (0 == sam_u->imp_w[imp_y]) || + (0xffffffff == sam_u->imp_w[imp_y]) ) + { + sam_u->imp_w[imp_y] = 0xffffffff; + } + + // keep existing ip for 5 more minutes + // + sam_u->imp_t[imp_y] = now; +} + static void _stun_start(u3_ames* sam_u, u3_noun dad) { From 81c10526ca8b860165d670dfb52de2f29df2ce3c Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 8 Nov 2023 12:44:19 +0100 Subject: [PATCH 19/53] stun: remove logs --- pkg/vere/io/ames.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 515a167eb1..d40bdfbfd5 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -2522,14 +2522,9 @@ _ames_recv_cb(uv_udp_t* wax_u, } else if (_stun_is_our_response(buf_u->base, sam_u->sun_u.tid_y, nrd_i) == c3y) { c3_w cookie = 0x2112A442; - c3_w ip_addr_map = _ames_sift_word(buf_u->base + 28); - c3_s port_map = _ames_sift_short(buf_u->base + 26); - c3_w ip_addr_xor = _ames_sift_word(buf_u->base + 28 + 12); c3_s port_xor = _ames_sift_short(buf_u->base + 26 + 12); - u3l_log("ip: %u", ntohl(ip_addr)); - u3l_log("port: %u", ntohs(port)); // New lane u3_lane lan_u; lan_u.por_s = ntohs(htons(port_xor) ^ cookie >> 16); From 97c3099207c4b64c8ff437247bf33add9b67c092 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Sun, 12 Nov 2023 15:30:51 +0100 Subject: [PATCH 20/53] stun: add global 5 minute dns resolution timer note: loom: external fault after DNS timer is called again --- pkg/vere/io/ames.c | 305 +++++++++++++++++++++++++++------------------ 1 file changed, 183 insertions(+), 122 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index d40bdfbfd5..17beb0dfed 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -57,7 +57,8 @@ typedef enum u3_stun_state { c3_d dad_d[2]; // sponsoring ship @p u3_lane lan_u; // sponsoring ship IP and port uv_timer_t tim_u; // keepalive timer handle - struct timeval las_u; // last sent date + uv_timer_t dns_u; // DNS resolution timer handle + struct timeval las_u; // XX last sent date (not used?) struct timeval sar_u; // date we started trying to send u3_lane sef_u; // our lane, if we know it } sun_u; // @@ -981,6 +982,21 @@ _ames_czar_port(c3_y imp_y) } } +static c3_c* +_ames_czar_dns(c3_c dns_c[255], c3_y imp_y, c3_c* czar_c) +{ + u3_noun nam = u3dc("scot", 'p', imp_y); + u3m_p("imp", nam); + c3_c* nam_c = u3r_string(nam); + u3l_log("stun: 1"); + c3_i sas_i = snprintf(dns_c, 255, "%s.%s", nam_c + 1, czar_c); + u3l_log("stun: 2"); + c3_free(nam_c); + u3z(nam); + + return sas_i; +} + /* _ames_czar_gone(): galaxy address resolution failed. */ static void @@ -1009,29 +1025,29 @@ _ames_czar_gone(u3_pact* pac_u, time_t now) /* _ames_czar_here(): galaxy address resolution succeeded. */ -static void -_ames_czar_here(u3_pact* pac_u, time_t now, struct sockaddr_in* add_u) +static c3_w +_ames_czar_here(u3_ames* sam_u, time_t now, struct sockaddr_in* add_u) { - u3_ames* sam_u = pac_u->sam_u; - c3_y imp_y = pac_u->rut_u.imp_y; - c3_w old_w = sam_u->imp_w[imp_y]; - c3_w pip_w = ntohl(add_u->sin_addr.s_addr); + c3_y imp_y = sam_u->sun_u.dad_d[0]; + c3_w old_w = sam_u->imp_w[imp_y]; + c3_w pip_w = ntohl(add_u->sin_addr.s_addr); if ( pip_w != old_w ) { u3_noun nam = u3dc("scot", c3__if, u3i_word(pip_w)); c3_c* nam_c = u3r_string(nam); - u3l_log("ames: czar %s: ip %s", pac_u->rut_u.dns_c, nam_c); + u3l_log("ames: czar %s: ip %s", sam_u->dns_c, nam_c); c3_free(nam_c); u3z(nam); } + sam_u->sun_u.lan_u.pip_w = pip_w; sam_u->imp_w[imp_y] = pip_w; sam_u->imp_t[imp_y] = now; sam_u->imp_o[imp_y] = c3y; - pac_u->rut_u.lan_u.pip_w = pip_w; + return pip_w; } /* _ames_czar_cb(): galaxy address resolution callback. @@ -1042,12 +1058,13 @@ _ames_czar_cb(uv_getaddrinfo_t* adr_u, struct addrinfo* aif_u) { { - u3_pact* pac_u = (u3_pact*)adr_u->data; - struct addrinfo* rai_u = aif_u; - time_t now = time(0); + u3_pact* pac_u = (u3_pact*)adr_u->data; + struct addrinfo* rai_u = aif_u; + struct sockaddr_in* aid_u = (struct sockaddr_in *)rai_u->ai_addr; + time_t now = time(0); if ( sas_i == 0 ) { - _ames_czar_here(pac_u, now, (struct sockaddr_in *)rai_u->ai_addr); + pac_u->rut_u.lan_u.pip_w = _ames_czar_here(pac_u->sam_u, now, aid_u); } else { _ames_czar_gone(pac_u, now); } @@ -1193,46 +1210,58 @@ _stun_stop(u3_ames* sam_u) case STUN_OFF: break; // ignore; already stopped case STUN_TRYING: { uv_timer_stop(&sam_u->sun_u.tim_u); + uv_timer_stop(&sam_u->sun_u.dns_u); } break; case STUN_KEEPALIVE: { uv_timer_stop(&sam_u->sun_u.tim_u); + uv_timer_stop(&sam_u->sun_u.dns_u); } break; default: u3_assert(!"programmer error"); } sam_u->sun_u.sat_y = STUN_OFF; } -// forward declaration(s) +// XX (code reordering?) forward declarations static void _stun_send_request(u3_ames*); static void _stun_on_lost(uv_timer_t* tim_u); static void _stun_czar_gone(u3_ames* sam_u, time_t now); static void _stun_czar(u3_ames* sam_u); +static void _stun_resolve_dns_cb(uv_timer_t* tim_u); +static void _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i); -/* _stun_on_reset(): wrapper callback to resolve DNS again after STUN failure -*/ -static void -_stun_on_reset(uv_timer_t* tim_u) +static c3_d +_stun_time_gap(struct timeval start) { - u3_ames* sam_u = (u3_ames*)(tim_u->data); - _stun_czar(sam_u); + struct timeval tim_tv; + gettimeofday(&tim_tv, 0); + u3_noun now = u3_time_in_tv(&tim_tv); + u3_noun den = u3_time_in_tv(&start); + return u3_time_gap_ms(den, now); } -/* _stun_reset(): stun failed. stop STUNing and re-start DNS resolution +/* _stun_reset(): stun failed. stop STUN and re-start DNS resolution */ static void -_stun_reset(u3_ames* sam_u, c3_w when) +_stun_reset(uv_timer_t* tim_u) { + u3_ames* sam_u = (u3_ames*)(tim_u->data); + sam_u->fig_u.net_o = c3n; - _stun_stop(sam_u); - gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now - sam_u->sun_u.sat_y = STUN_TRYING; - sam_u->sun_u.tim_u.data = sam_u; - uv_timer_start(&sam_u->sun_u.tim_u, _stun_on_reset, when, 0); + c3_d gap_d = _stun_time_gap(sam_u->sun_u.sar_u); + + if ( gap_d >= 5*1000 ) { + gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now + sam_u->sun_u.sat_y = STUN_TRYING; + _stun_czar(sam_u); + } else { + uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); + } } static void _stun_timer_cb(uv_timer_t* tim_u) { + c3_w rto = 500; u3_ames* sam_u = (u3_ames*)(tim_u->data); switch ( sam_u->sun_u.sat_y ) { case STUN_OFF: { @@ -1244,22 +1273,17 @@ _stun_timer_cb(uv_timer_t* tim_u) _stun_send_request(sam_u); sam_u->sun_u.tim_u.data = sam_u; gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now - uv_timer_start(&sam_u->sun_u.tim_u, _stun_on_lost, 500, 0); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, rto, 0); } break; case STUN_TRYING: { - c3_w rto = 500; - c3_d gap_d; - { - struct timeval tim_tv; - gettimeofday(&tim_tv, 0); - u3_noun now = u3_time_in_tv(&tim_tv); - u3_noun den = u3_time_in_tv(&sam_u->sun_u.sar_u); - gap_d = u3_time_gap_ms(den, now); - } - if ( gap_d >= (31500) ) { - u3l_log("stun: more than 31 seconds passed..."); + c3_d gap_d = _stun_time_gap(sam_u->sun_u.sar_u); + if ( gap_d >= (39500) ) { + u3l_log("stun: more than 39 seconds passed..."); _stun_on_lost(&sam_u->sun_u.tim_u); + } else if ( gap_d >= (31500) ) { _stun_send_request(sam_u); + // wait ~s8 for the last STUN request + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 8000 , 0); } else { sam_u->sun_u.tim_u.data = sam_u; uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, @@ -1277,22 +1301,36 @@ typedef struct _u3_stun_send { } u3_stun_send; static void -_stun_send_cb(uv_udp_send_t *req_u, c3_i sas_i) +_stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i) { u3_stun_send* snd_u = (u3_stun_send*)req_u; + u3_ames* sam_u = snd_u->sam_u; + if ( sas_i ) { u3l_log("stun: send callback fail_async: %s", uv_strerror(sas_i)); - _stun_reset(snd_u->sam_u, 1*1000); // XX + sam_u->sun_u.tim_u.data = sam_u; + gettimeofday(&sam_u->sun_u.sar_u, 0); // reset timer to now + sam_u->sun_u.sat_y = STUN_TRYING; + // retry sending the failed request in 500ms + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); } else { - u3_ames* sam_u = snd_u->sam_u; + // XX curently not used gettimeofday(&sam_u->sun_u.las_u, 0); // overwrite last sent date } } +static void +_stun_send_response_cb(uv_udp_send_t *req_u, c3_i sas_i) +{ + if ( sas_i != 0 ) { + u3l_log("stun: _stun_send_response_cb fail_sync: %s", uv_strerror(sas_i)); + } +} + static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], - const struct sockaddr* adr_u) { - // XX TODO + const struct sockaddr* adr_u) +{ struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; c3_y buf_y[44] = {0}; c3_w cookie = 0x2112A442; @@ -1327,12 +1365,11 @@ static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], snd_u->sam_u = sam_u; c3_i sas_i = uv_udp_send( (uv_udp_send_t*)snd_u, &sam_u->wax_u, &buf_u, 1, - adr_u, _stun_send_cb + adr_u, _stun_send_response_cb ); if ( sas_i != 0) { u3l_log("stun: send response fail_sync: %s", uv_strerror(sas_i)); - _stun_reset(sam_u, 1*1000); } } @@ -1349,7 +1386,6 @@ _stun_on_response(u3_ames* sam_u) // TODO read arg uv_timer_stop(&sam_u->sun_u.tim_u); sam_u->sun_u.tim_u.data = sam_u; uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); - } break; default: assert("programmer error"); } @@ -1361,6 +1397,7 @@ _stun_on_lost(uv_timer_t* tim_u) u3_ames* sam_u = (u3_ames*)(tim_u->data); u3l_log("stun: waited too long..."); uv_timer_stop(&sam_u->sun_u.tim_u); + uv_timer_stop(&sam_u->sun_u.dns_u); // inject event into arvo to %kick ping app u3_noun wir = u3nc(c3__ames, u3_nul); u3_noun cad = u3nt(c3__stun, c3__fail, u3_nul); @@ -1368,8 +1405,8 @@ _stun_on_lost(uv_timer_t* tim_u) u3_auto_plan(&sam_u->car_u, ovo_u); sam_u->sun_u.sat_y = STUN_TRYING; gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now - // resolve DNS again, and (re)start STUNing - uv_timer_start(&sam_u->sun_u.tim_u, _stun_on_reset, 1, 0); + // resolve DNS again, and (re)start STUN + uv_timer_start(&sam_u->sun_u.tim_u, _stun_reset, 1, 0); } static void @@ -1404,12 +1441,15 @@ _stun_send_request(u3_ames* sam_u) snd_u->sam_u = sam_u; c3_i sas_i = uv_udp_send( (uv_udp_send_t*)snd_u, &sam_u->wax_u, &buf_u, 1, - (const struct sockaddr*)&add_u, _stun_send_cb + (const struct sockaddr*)&add_u, _stun_send_request_cb ); if ( sas_i != 0) { u3l_log("stun: send request fail_sync: %s", uv_strerror(sas_i)); - _stun_reset(sam_u, 1*1000); // XX + sam_u->sun_u.tim_u.data = sam_u; + gettimeofday(&sam_u->sun_u.sar_u, 0); + sam_u->sun_u.sat_y = STUN_TRYING; + uv_timer_start(&sam_u->sun_u.tim_u, _stun_send_request_cb, 500, 0); } } @@ -1418,49 +1458,61 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, c3_i sas_i, struct addrinfo* aif_u) { - u3_ames* sam_u = (u3_ames*)(adr_u->data); - gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now - - if (sas_i != 0) { - u3l_log("stun: _stun_czar_cb request fail_sync: %s", uv_strerror(sas_i)); - _stun_reset(sam_u, 1*1000); // XX - } else { - _stun_send_request(sam_u); + { + u3_ames* sam_u = (u3_ames*)(adr_u->data); + struct addrinfo* rai_u = aif_u; + struct sockaddr_in* aid_u = (struct sockaddr_in *)rai_u->ai_addr; + time_t now = time(0); - sam_u->sun_u.tim_u.data = sam_u; uv_timer_init(u3L, &sam_u->sun_u.tim_u); - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); + sam_u->sun_u.tim_u.data = sam_u; + sam_u->sun_u.dns_u.data = sam_u; + gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now + + if (sas_i == 0) { + _ames_czar_here(sam_u, now, aid_u); + _stun_send_request(sam_u); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); + // resolve DNS again in five minutes + uv_timer_start(&sam_u->sun_u.dns_u, _stun_resolve_dns_cb, 5*60*1000, 0); + } else { + u3l_log("stun: _stun_czar_cb request fail_sync: %s", uv_strerror(sas_i)); + _stun_stop(sam_u); + _stun_czar_gone(sam_u, now); + sam_u->sun_u.dns_u.data = sam_u; + gettimeofday(&sam_u->sun_u.sar_u, 0); + uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 1, 0); + } } + u3l_log("free"); + c3_free(adr_u); + uv_freeaddrinfo(aif_u); } static void _stun_czar(u3_ames* sam_u) { c3_d imp_y = sam_u->sun_u.dad_d[0]; - - u3l_log("stun : %i", imp_y); - sam_u->sun_u.lan_u.por_s = _ames_czar_port(imp_y); - if (c3n == u3_Host.ops_u.net) { - // XX remove/fix - sam_u->sun_u.lan_u.pip_w = 0x7f000001; - u3l_log("sending"); - - _stun_send_request(sam_u); + // Enable STUN using -L + // XX remove/fix + // XX maybe enabled with a flag, for development? + // if (c3n == u3_Host.ops_u.net) { + // sam_u->sun_u.lan_u.pip_w = 0x7f000001; + // u3l_log("sending"); - // XX timer stuff to be removed - // XX maybe enabled with a flag? + // _stun_send_request(sam_u); - u3l_log("start timer"); - uv_timer_t* tim_u = c3_malloc(sizeof(*tim_u)); - sam_u->sun_u.tim_u.data = sam_u; - gettimeofday(&sam_u->sun_u.sar_u, 0); - uv_timer_init(u3L, &sam_u->sun_u.tim_u); - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); + // u3l_log("start timer"); + // uv_timer_t* tim_u = c3_malloc(sizeof(*tim_u)); + // sam_u->sun_u.tim_u.data = sam_u; + // gettimeofday(&sam_u->sun_u.sar_u, 0); + // uv_timer_init(u3L, &sam_u->sun_u.tim_u); + // uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); - return; - } + // return; + // } // if we don't have a galaxy domain, no-op // @@ -1479,7 +1531,7 @@ _stun_czar(u3_ames* sam_u) time_t wen = sam_u->imp_t[imp_y]; time_t now = time(0); - // XX keep the same 5 minutes as ames? + // XX keep same as ames? // backoff for 5 minutes after failed lookup // if ((now < wen) // time shenanigans! @@ -1492,49 +1544,13 @@ _stun_czar(u3_ames* sam_u) else if ((0 != pip_w) && ((now - wen) < 300)) { sam_u->sun_u.lan_u.pip_w = pip_w; _stun_send_request(sam_u); + gettimeofday(&sam_u->sun_u.sar_u, 0); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); return; } else { - c3_i sas_i; - c3_c dns_c[255]; - - { - u3_noun nam = u3dc("scot", 'p', imp_y); - c3_c *nam_c = u3r_string(nam); - - // NB: . separator not counted, as [nam_c] includes a ~ that we skip - // - // dns_c = - // c3_malloc(1 + strlen(nam_c) + strlen(sam_u->dns_c)); - - sas_i = - snprintf(dns_c, 255, "%s.%s", nam_c + 1, sam_u->dns_c); - - c3_free(nam_c); - u3z(nam); - } - - if (255 <= sas_i) { - u3l_log("ames: czar: galaxy domain %s truncated", sam_u->dns_c); - return; - } - - { - - uv_getaddrinfo_t* adr_u = c3_malloc(sizeof(*adr_u)); - adr_u->data = sam_u; - - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; // only IPv4 addresses - - if (0 != (sas_i = uv_getaddrinfo(u3L, adr_u, _stun_czar_cb, - dns_c, 0, &hints))) { - u3l_log("stun: %s", uv_strerror(sas_i)); - _stun_czar_gone(sam_u, now); - _stun_reset(sam_u, 1*1000); // try again in XX - return; - } - } + // call callback right away first time we resolve the sponsor's DNS + sam_u->sun_u.dns_u.data = sam_u; + _stun_resolve_dns_cb(&sam_u->sun_u.dns_u); } } } @@ -1569,12 +1585,15 @@ _stun_start(u3_ames* sam_u, u3_noun dad) sam_u->sun_u.sat_y = STUN_TRYING; u3r_chubs(0, 2, sam_u->sun_u.dad_d, dad); u3z(dad); + // initialize global ~m5 timer to resolve sponsors DNS + uv_timer_init(u3L, &sam_u->sun_u.dns_u); // initialize STUN transaction id to mug of now { u3_noun mug; struct timeval tim_u; gettimeofday(&tim_u, 0); + uv_timer_init(u3L, &sam_u->sun_u.tim_u); mug = u3r_mug(u3_time_in_tv(&tim_u)); memcpy(sam_u->sun_u.tid_y, (c3_y*)&mug, 4); @@ -1584,6 +1603,46 @@ _stun_start(u3_ames* sam_u, u3_noun dad) _stun_czar(sam_u); } +static void +_stun_resolve_dns_cb(uv_timer_t* tim_u) +{ + u3_ames* sam_u = (u3_ames*)(tim_u->data); + + c3_i sas_i; + c3_c dns_c[255]; + + c3_d imp_y = sam_u->sun_u.dad_d[0]; + u3l_log("ames: imp %d", imp_y); + sam_u->sun_u.lan_u.por_s = _ames_czar_port(imp_y); + + sas_i = _ames_czar_dns(dns_c, imp_y, sam_u->dns_c); + u3l_log("stun: %u %s", sas_i, dns_c); + if (255 <= sas_i) { + u3l_log("stun: czar: galaxy domain %s truncated", sam_u->dns_c); + return; + } + + { + uv_getaddrinfo_t* adr_u = c3_malloc(sizeof(*adr_u)); + adr_u->data = sam_u; + + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; // only IPv4 addresses + + if (0 != (sas_i = uv_getaddrinfo(u3L, adr_u, _stun_czar_cb, + dns_c, 0, &hints))) { + u3l_log("stun: uv_getaddrinfo failed %s", uv_strerror(sas_i)); + _stun_stop(sam_u); + _stun_czar_gone(sam_u, time(0)); + sam_u->sun_u.dns_u.data = sam_u; + gettimeofday(&sam_u->sun_u.sar_u, 0); + uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 1, 0); + return; + } + } +} + static c3_o _stun_is_our_response(c3_y buf_y[44], c3_y tid_y[12], c3_w buf_len) { @@ -1638,6 +1697,8 @@ _ames_ef_saxo(u3_ames* sam_u, u3_noun zad) u3l_log("ames: start STUN"); _stun_stop(sam_u); _stun_start(sam_u, u3k(dad)); + // XX TODO on new saxo reset the timers for the DNS resolution and restart + // STUN } u3z(zad); u3z(daz); u3z(dad); From a81c1474b7df5864811f68b9a5256e14e0caab31 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 13 Nov 2023 10:55:56 +0100 Subject: [PATCH 21/53] stun: better reset stun timer calls --- pkg/vere/io/ames.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 17beb0dfed..2a8d6cf895 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1246,16 +1246,11 @@ _stun_reset(uv_timer_t* tim_u) { u3_ames* sam_u = (u3_ames*)(tim_u->data); - sam_u->fig_u.net_o = c3n; - c3_d gap_d = _stun_time_gap(sam_u->sun_u.sar_u); + sam_u->fig_u.net_o = c3n; // XX needed? - if ( gap_d >= 5*1000 ) { - gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now - sam_u->sun_u.sat_y = STUN_TRYING; - _stun_czar(sam_u); - } else { - uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); - } + gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now + sam_u->sun_u.sat_y = STUN_TRYING; + _stun_czar(sam_u); } static void @@ -1396,17 +1391,14 @@ _stun_on_lost(uv_timer_t* tim_u) { u3_ames* sam_u = (u3_ames*)(tim_u->data); u3l_log("stun: waited too long..."); - uv_timer_stop(&sam_u->sun_u.tim_u); - uv_timer_stop(&sam_u->sun_u.dns_u); + _stun_stop(sam_u); // inject event into arvo to %kick ping app u3_noun wir = u3nc(c3__ames, u3_nul); u3_noun cad = u3nt(c3__stun, c3__fail, u3_nul); u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); u3_auto_plan(&sam_u->car_u, ovo_u); - sam_u->sun_u.sat_y = STUN_TRYING; - gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now // resolve DNS again, and (re)start STUN - uv_timer_start(&sam_u->sun_u.tim_u, _stun_reset, 1, 0); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_reset, 5*1000, 0); } static void @@ -1480,8 +1472,7 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, _stun_stop(sam_u); _stun_czar_gone(sam_u, now); sam_u->sun_u.dns_u.data = sam_u; - gettimeofday(&sam_u->sun_u.sar_u, 0); - uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 1, 0); + uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); } } u3l_log("free"); @@ -1636,8 +1627,7 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) _stun_stop(sam_u); _stun_czar_gone(sam_u, time(0)); sam_u->sun_u.dns_u.data = sam_u; - gettimeofday(&sam_u->sun_u.sar_u, 0); - uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 1, 0); + uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); return; } } From 588ba281a0f96b80558e07a01b3305dd455791ea Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 13 Nov 2023 11:22:47 +0100 Subject: [PATCH 22/53] stun: remove warnings --- pkg/vere/io/ames.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 2a8d6cf895..72ecc89baa 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -982,7 +982,7 @@ _ames_czar_port(c3_y imp_y) } } -static c3_c* +static c3_i _ames_czar_dns(c3_c dns_c[255], c3_y imp_y, c3_c* czar_c) { u3_noun nam = u3dc("scot", 'p', imp_y); @@ -1441,7 +1441,7 @@ _stun_send_request(u3_ames* sam_u) sam_u->sun_u.tim_u.data = sam_u; gettimeofday(&sam_u->sun_u.sar_u, 0); sam_u->sun_u.sat_y = STUN_TRYING; - uv_timer_start(&sam_u->sun_u.tim_u, _stun_send_request_cb, 500, 0); + _stun_send_request_cb((uv_udp_send_t*)snd_u, sas_i); } } @@ -1646,7 +1646,7 @@ _stun_is_our_response(c3_y buf_y[44], c3_y tid_y[12], c3_w buf_len) } static c3_o -_stun_is_request(c3_y buf_y[32], c3_w buf_len) +_stun_is_request(c3_y buf_y[32], c3_w buf_len) // buf_y[20] ? { c3_w cookie = htonl(0x2112A442); @@ -2567,14 +2567,14 @@ _ames_recv_cb(uv_udp_t* wax_u, } c3_free(buf_u->base); } - else if (_stun_is_request(buf_u->base, nrd_i) == c3y) { + else if (_stun_is_request((c3_y*)buf_u->base, nrd_i) == c3y) { u3_ames* sam_u = wax_u->data; _stun_on_request(sam_u, (c3_y *)buf_u->base, adr_u); - } else if (_stun_is_our_response(buf_u->base, sam_u->sun_u.tid_y, nrd_i) + } else if (_stun_is_our_response((c3_y*)buf_u->base, sam_u->sun_u.tid_y, nrd_i) == c3y) { c3_w cookie = 0x2112A442; - c3_w ip_addr_xor = _ames_sift_word(buf_u->base + 28 + 12); - c3_s port_xor = _ames_sift_short(buf_u->base + 26 + 12); + c3_w ip_addr_xor = _ames_sift_word((c3_y *)buf_u->base + 28 + 12); + c3_s port_xor = _ames_sift_short((c3_y *)buf_u->base + 26 + 12); // New lane u3_lane lan_u; From 215d4e45092897b270b09761a56a6835bd933533 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 13 Nov 2023 13:00:54 +0100 Subject: [PATCH 23/53] stun: send req after first successful dns resolve --- pkg/vere/io/ames.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 72ecc89baa..2c09e72559 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1247,9 +1247,6 @@ _stun_reset(uv_timer_t* tim_u) u3_ames* sam_u = (u3_ames*)(tim_u->data); sam_u->fig_u.net_o = c3n; // XX needed? - - gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now - sam_u->sun_u.sat_y = STUN_TRYING; _stun_czar(sam_u); } @@ -1463,8 +1460,11 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, if (sas_i == 0) { _ames_czar_here(sam_u, now, aid_u); - _stun_send_request(sam_u); - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); + if (sam_u->sun_u.sat_y == STUN_OFF) { + sam_u->sun_u.sat_y = STUN_TRYING; + _stun_send_request(sam_u); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); + } // resolve DNS again in five minutes uv_timer_start(&sam_u->sun_u.dns_u, _stun_resolve_dns_cb, 5*60*1000, 0); } else { @@ -1573,7 +1573,6 @@ _stun_czar_gone(u3_ames* sam_u, time_t now) static void _stun_start(u3_ames* sam_u, u3_noun dad) { - sam_u->sun_u.sat_y = STUN_TRYING; u3r_chubs(0, 2, sam_u->sun_u.dad_d, dad); u3z(dad); // initialize global ~m5 timer to resolve sponsors DNS From fedccd0fb65a1ac85c3bfa42513263704a0130da Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 13 Nov 2023 13:26:52 +0100 Subject: [PATCH 24/53] stun: if cached ip switch to trying --- pkg/vere/io/ames.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 2c09e72559..fdce0d36cb 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1533,6 +1533,7 @@ _stun_czar(u3_ames* sam_u) // cached addresses have a 5 minute TTL // else if ((0 != pip_w) && ((now - wen) < 300)) { + sam_u->sun_u.sat_y = STUN_TRYING; sam_u->sun_u.lan_u.pip_w = pip_w; _stun_send_request(sam_u); gettimeofday(&sam_u->sun_u.sar_u, 0); From de7bd9e5e558db5127fc2c8947f79c3045ac6d6b Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Tue, 14 Nov 2023 14:54:34 +0100 Subject: [PATCH 25/53] stun: better retry logic on error --- pkg/vere/io/ames.c | 199 ++++++++++++++++++++++++++------------------- 1 file changed, 117 insertions(+), 82 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index fdce0d36cb..e1a8d916db 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -54,13 +54,14 @@ typedef enum u3_stun_state { struct { // stun client state: u3_stun_state sat_y; // formal state c3_y tid_y[16]; // last transaction id - c3_d dad_d[2]; // sponsoring ship @p - u3_lane lan_u; // sponsoring ship IP and port + c3_y dad_y; // sponsoring galaxy + u3_lane lan_u; // sponsoring galaxy IP and port uv_timer_t tim_u; // keepalive timer handle uv_timer_t dns_u; // DNS resolution timer handle struct timeval las_u; // XX last sent date (not used?) 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 { // config: c3_o net_o; // can send @@ -1028,7 +1029,7 @@ _ames_czar_gone(u3_pact* pac_u, time_t now) static c3_w _ames_czar_here(u3_ames* sam_u, time_t now, struct sockaddr_in* add_u) { - c3_y imp_y = sam_u->sun_u.dad_d[0]; + c3_y imp_y = sam_u->sun_u.dad_y; c3_w old_w = sam_u->imp_w[imp_y]; c3_w pip_w = ntohl(add_u->sin_addr.s_addr); @@ -1096,7 +1097,7 @@ _ames_czar(u3_pact* pac_u) if ( !sam_u->dns_c ) { u3_noun nam = u3dc("scot", 'p', pac_u->rut_u.imp_y); c3_c* nam_c = u3r_string(nam); - u3l_log("ames: no galaxy domain for %s, no-op\r", nam_c); + u3l_log("ames: no galaxy domain for %s, no-op", nam_c); c3_free(nam_c); u3z(nam); @@ -1208,10 +1209,7 @@ _stun_stop(u3_ames* sam_u) { switch ( sam_u->sun_u.sat_y ) { case STUN_OFF: break; // ignore; already stopped - case STUN_TRYING: { - uv_timer_stop(&sam_u->sun_u.tim_u); - uv_timer_stop(&sam_u->sun_u.dns_u); - } break; + case STUN_TRYING: case STUN_KEEPALIVE: { uv_timer_stop(&sam_u->sun_u.tim_u); uv_timer_stop(&sam_u->sun_u.dns_u); @@ -1225,9 +1223,10 @@ _stun_stop(u3_ames* sam_u) static void _stun_send_request(u3_ames*); static void _stun_on_lost(uv_timer_t* tim_u); static void _stun_czar_gone(u3_ames* sam_u, time_t now); -static void _stun_czar(u3_ames* sam_u); +static void _stun_czar(u3_ames* sam_u, c3_d tim_d); static void _stun_resolve_dns_cb(uv_timer_t* tim_u); static void _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i); +static void _stun_on_failure(u3_ames* sam_u); static c3_d _stun_time_gap(struct timeval start) @@ -1239,22 +1238,26 @@ _stun_time_gap(struct timeval start) return u3_time_gap_ms(den, now); } -/* _stun_reset(): stun failed. stop STUN and re-start DNS resolution +/* _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); - sam_u->fig_u.net_o = c3n; // XX needed? - _stun_czar(sam_u); + // sam_u->fig_u.net_o = c3n; // XX needed? + c3_d tim_d = 39500; + + _stun_start(sam_u, c3y); } static void _stun_timer_cb(uv_timer_t* tim_u) { c3_w rto = 500; + u3_ames* sam_u = (u3_ames*)(tim_u->data); + switch ( sam_u->sun_u.sat_y ) { case STUN_OFF: { // ignore; stray timer (although this shouldn't happen) @@ -1269,6 +1272,8 @@ _stun_timer_cb(uv_timer_t* tim_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 - gap_d; + if ( gap_d >= (39500) ) { u3l_log("stun: more than 39 seconds passed..."); _stun_on_lost(&sam_u->sun_u.tim_u); @@ -1277,10 +1282,10 @@ _stun_timer_cb(uv_timer_t* tim_u) // wait ~s8 for the last STUN request uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 8000 , 0); } else { - sam_u->sun_u.tim_u.data = sam_u; uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, - ((gap_d * 2) + rto - gap_d), 0); + (nex_d >= 31500) ? 31500 : nex_d, 0); _stun_send_request(sam_u); + u3l_log("stun: set RTO + last_timer * 2 %llu next: %llu", gap_d, (gap_d * 2) + rto); } } break; default: u3_assert(!"programmer error"); @@ -1289,22 +1294,31 @@ _stun_timer_cb(uv_timer_t* tim_u) typedef struct _u3_stun_send { uv_udp_send_t req_u; // uv udp request handle - u3_ames* sam_u; // backpointer to driver state + u3_ames* sam_u; // backpointer to driver state + c3_y* hun_y; // buffer + } u3_stun_send; static void _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i) { u3_stun_send* snd_u = (u3_stun_send*)req_u; - u3_ames* sam_u = snd_u->sam_u; + u3_ames* sam_u = snd_u->sam_u; if ( sas_i ) { u3l_log("stun: send callback fail_async: %s", uv_strerror(sas_i)); - sam_u->sun_u.tim_u.data = sam_u; + + if (sam_u->sun_u.wok_o == c3y) { + _stun_on_failure(sam_u); // %kick ping app + } + sam_u->sun_u.wok_o = c3n; + gettimeofday(&sam_u->sun_u.sar_u, 0); // reset timer to now sam_u->sun_u.sat_y = STUN_TRYING; // retry sending the failed request in 500ms uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); + c3_free(snd_u->hun_y); + c3_free(snd_u); } else { // XX curently not used @@ -1313,10 +1327,13 @@ _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i) } static void -_stun_send_response_cb(uv_udp_send_t *req_u, c3_i sas_i) +_stun_send_response_cb(uv_udp_send_t *rep_u, c3_i sas_i) { + u3_stun_send* snd_u = (u3_stun_send*)rep_u; if ( sas_i != 0 ) { u3l_log("stun: _stun_send_response_cb fail_sync: %s", uv_strerror(sas_i)); + c3_free(snd_u->hun_y); + c3_free(snd_u); } } @@ -1332,6 +1349,7 @@ static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], buf_y[0] = 0x01; buf_y[1] = 0x01; // 0x0101 SUCCESS RESPONSE buf_y[2] = 0x00; buf_y[3] = 0x18; // Length: 24 bytes + // XX REMOVE // MAPPED-ADDRESS buf_y[cur_w] = 0x00; buf_y[cur_w + 1] = 0x01; // attribute type 0x0001 buf_y[cur_w + 2] = 0x00; buf_y[cur_w + 3] = 0x08; // STUN attribute length @@ -1352,9 +1370,10 @@ static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], memcpy(buf_y + cur_w + 20, &x_ip, 4); // X-IP Addres uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 44); - u3_stun_send* snd_u = c3_calloc(sizeof(*snd_u)); + snd_u->sam_u = sam_u; + snd_u->hun_y = buf_r; c3_i sas_i = uv_udp_send( (uv_udp_send_t*)snd_u, &sam_u->wax_u, &buf_u, 1, adr_u, _stun_send_response_cb @@ -1362,6 +1381,8 @@ static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], if ( sas_i != 0) { u3l_log("stun: send response fail_sync: %s", uv_strerror(sas_i)); + c3_free(buf_r); + c3_free(snd_u); } } @@ -1369,6 +1390,7 @@ static void _stun_on_response(u3_ames* sam_u) // TODO read arg { u3_stun_state old_y = sam_u->sun_u.sat_y; + switch ( sam_u->sun_u.sat_y ) { case STUN_OFF: break; // ignore; stray response case STUN_KEEPALIVE: break; // ignore; duplicate response @@ -1376,7 +1398,8 @@ _stun_on_response(u3_ames* sam_u) // TODO read arg sam_u->sun_u.sat_y = STUN_KEEPALIVE; sam_u->sun_u.tid_y[1]++; uv_timer_stop(&sam_u->sun_u.tim_u); - sam_u->sun_u.tim_u.data = sam_u; + + sam_u->sun_u.wok_o = c3y; uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); } break; default: assert("programmer error"); @@ -1384,16 +1407,26 @@ _stun_on_response(u3_ames* sam_u) // TODO read arg } static void -_stun_on_lost(uv_timer_t* tim_u) +_stun_on_failure(u3_ames* sam_u) { - u3_ames* sam_u = (u3_ames*)(tim_u->data); - u3l_log("stun: waited too long..."); - _stun_stop(sam_u); - // inject event into arvo to %kick ping app u3_noun wir = u3nc(c3__ames, u3_nul); u3_noun cad = u3nt(c3__stun, c3__fail, u3_nul); u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); u3_auto_plan(&sam_u->car_u, ovo_u); +} + +static void +_stun_on_lost(uv_timer_t* tim_u) +{ + u3_ames* sam_u = (u3_ames*)(tim_u->data); + + u3l_log("stun: waited too long..."); + _stun_stop(sam_u); + // only inject event into arvo to %kick ping app on first failure + if (sam_u->sun_u.wok_o == c3y) { + _stun_on_failure(sam_u); + } + sam_u->sun_u.wok_o = c3n; // resolve DNS again, and (re)start STUN uv_timer_start(&sam_u->sun_u.tim_u, _stun_reset, 5*1000, 0); } @@ -1411,7 +1444,7 @@ _stun_send_request(u3_ames* sam_u) // see STUN RFC 8489 // https://datatracker.ietf.org/doc/html/rfc8489#section-5 - c3_y buf_y[20] = {0}; + c3_y *buf_y = c3_calloc(20); // STUN message type: "binding request" buf_y[1] = 0x01; @@ -1428,6 +1461,8 @@ _stun_send_request(u3_ames* sam_u) uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 20); u3_stun_send* snd_u = c3_calloc(sizeof(*snd_u)); snd_u->sam_u = sam_u; + snd_u->hun_y = buf_y; + c3_i sas_i = uv_udp_send( (uv_udp_send_t*)snd_u, &sam_u->wax_u, &buf_u, 1, (const struct sockaddr*)&add_u, _stun_send_request_cb @@ -1435,10 +1470,17 @@ _stun_send_request(u3_ames* sam_u) if ( sas_i != 0) { u3l_log("stun: send request fail_sync: %s", uv_strerror(sas_i)); - sam_u->sun_u.tim_u.data = sam_u; + + if (sam_u->sun_u.wok_o == c3y) { + _stun_on_failure(sam_u); // %kick ping app + } + sam_u->sun_u.wok_o = c3n; + gettimeofday(&sam_u->sun_u.sar_u, 0); sam_u->sun_u.sat_y = STUN_TRYING; _stun_send_request_cb((uv_udp_send_t*)snd_u, sas_i); + c3_free(buf_y); + c3_free(snd_u); } } @@ -1453,14 +1495,12 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, struct sockaddr_in* aid_u = (struct sockaddr_in *)rai_u->ai_addr; time_t now = time(0); - uv_timer_init(u3L, &sam_u->sun_u.tim_u); - sam_u->sun_u.tim_u.data = sam_u; - sam_u->sun_u.dns_u.data = sam_u; gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now if (sas_i == 0) { _ames_czar_here(sam_u, now, aid_u); if (sam_u->sun_u.sat_y == STUN_OFF) { + u3l_log("stun: was OFF, start TRYING"); sam_u->sun_u.sat_y = STUN_TRYING; _stun_send_request(sam_u); uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); @@ -1471,46 +1511,39 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, u3l_log("stun: _stun_czar_cb request fail_sync: %s", uv_strerror(sas_i)); _stun_stop(sam_u); _stun_czar_gone(sam_u, now); - sam_u->sun_u.dns_u.data = sam_u; + sam_u->sun_u.wok_o = c3n; uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); } } - u3l_log("free"); c3_free(adr_u); uv_freeaddrinfo(aif_u); } static void -_stun_czar(u3_ames* sam_u) +_stun_czar(u3_ames* sam_u, c3_d tim_d) { - c3_d imp_y = sam_u->sun_u.dad_d[0]; + c3_d imp_y = sam_u->sun_u.dad_y; sam_u->sun_u.lan_u.por_s = _ames_czar_port(imp_y); // Enable STUN using -L - // XX remove/fix // XX maybe enabled with a flag, for development? - // if (c3n == u3_Host.ops_u.net) { - // sam_u->sun_u.lan_u.pip_w = 0x7f000001; - // u3l_log("sending"); - - // _stun_send_request(sam_u); + if (c3n == u3_Host.ops_u.net) { + sam_u->sun_u.lan_u.pip_w = 0x7f000001; + sam_u->sun_u.sat_y = STUN_TRYING; + _stun_send_request(sam_u); - // u3l_log("start timer"); - // uv_timer_t* tim_u = c3_malloc(sizeof(*tim_u)); - // sam_u->sun_u.tim_u.data = sam_u; - // gettimeofday(&sam_u->sun_u.sar_u, 0); - // uv_timer_init(u3L, &sam_u->sun_u.tim_u); - // uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); + gettimeofday(&sam_u->sun_u.sar_u, 0); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, tim_d, 0); - // return; - // } + return; + } // if we don't have a galaxy domain, no-op // if (!sam_u->dns_c) { u3_noun nam = u3dc("scot", 'p', imp_y); c3_c *nam_c = u3r_string(nam); - u3l_log("ames: no galaxy domain for %s, no-op\r", nam_c); + u3l_log("ames: no galaxy domain for %s, no-op", nam_c); c3_free(nam_c); u3z(nam); @@ -1535,14 +1568,16 @@ _stun_czar(u3_ames* sam_u) else if ((0 != pip_w) && ((now - wen) < 300)) { sam_u->sun_u.sat_y = STUN_TRYING; sam_u->sun_u.lan_u.pip_w = pip_w; + _stun_send_request(sam_u); + gettimeofday(&sam_u->sun_u.sar_u, 0); - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, tim_d, 0); return; } else { // call callback right away first time we resolve the sponsor's DNS sam_u->sun_u.dns_u.data = sam_u; - _stun_resolve_dns_cb(&sam_u->sun_u.dns_u); + uv_timer_start(&sam_u->sun_u.dns_u, _stun_resolve_dns_cb, tim_d, 0); } } } @@ -1553,7 +1588,7 @@ _stun_czar(u3_ames* sam_u) static void _stun_czar_gone(u3_ames* sam_u, time_t now) { - c3_d imp_y = sam_u->sun_u.dad_d[0]; + c3_y imp_y = sam_u->sun_u.dad_y; if ( c3y == sam_u->imp_o[imp_y] ) { u3l_log("stun: czar at %s: not found (b)", sam_u->dns_c); // XX @@ -1572,42 +1607,36 @@ _stun_czar_gone(u3_ames* sam_u, time_t now) } static void -_stun_start(u3_ames* sam_u, u3_noun dad) +_stun_start(u3_ames* sam_u, c3_o fail) { - u3r_chubs(0, 2, sam_u->sun_u.dad_d, dad); - u3z(dad); - // initialize global ~m5 timer to resolve sponsors DNS - uv_timer_init(u3L, &sam_u->sun_u.dns_u); // initialize STUN transaction id to mug of now { u3_noun mug; struct timeval tim_u; gettimeofday(&tim_u, 0); - uv_timer_init(u3L, &sam_u->sun_u.tim_u); mug = u3r_mug(u3_time_in_tv(&tim_u)); memcpy(sam_u->sun_u.tid_y, (c3_y*)&mug, 4); u3z(mug); } - _stun_czar(sam_u); + c3_d tim_d = (fail == c3n) ? 500 : 39500; + + _stun_czar(sam_u, tim_d); } static void _stun_resolve_dns_cb(uv_timer_t* tim_u) { u3_ames* sam_u = (u3_ames*)(tim_u->data); - c3_i sas_i; c3_c dns_c[255]; - c3_d imp_y = sam_u->sun_u.dad_d[0]; - u3l_log("ames: imp %d", imp_y); + c3_y imp_y = sam_u->sun_u.dad_y; sam_u->sun_u.lan_u.por_s = _ames_czar_port(imp_y); - sas_i = _ames_czar_dns(dns_c, imp_y, sam_u->dns_c); - u3l_log("stun: %u %s", sas_i, dns_c); + if (255 <= sas_i) { u3l_log("stun: czar: galaxy domain %s truncated", sam_u->dns_c); return; @@ -1622,11 +1651,11 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) hints.ai_family = AF_INET; // only IPv4 addresses if (0 != (sas_i = uv_getaddrinfo(u3L, adr_u, _stun_czar_cb, - dns_c, 0, &hints))) { + dns_c, 0, &hints))) { u3l_log("stun: uv_getaddrinfo failed %s", uv_strerror(sas_i)); _stun_stop(sam_u); _stun_czar_gone(sam_u, time(0)); - sam_u->sun_u.dns_u.data = sam_u; + sam_u->sun_u.wok_o = c3n; uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); return; } @@ -1646,7 +1675,7 @@ _stun_is_our_response(c3_y buf_y[44], c3_y tid_y[12], c3_w buf_len) } static c3_o -_stun_is_request(c3_y buf_y[32], c3_w buf_len) // buf_y[20] ? +_stun_is_request(c3_y buf_y[20], c3_w buf_len) { c3_w cookie = htonl(0x2112A442); @@ -1679,19 +1708,18 @@ _ames_ef_saxo(u3_ames* sam_u, u3_noun zad) return; } - dad = u3k(u3h(daz)); + dad = u3h(daz); u3_noun our = u3i_chubs(2, sam_u->pir_u->who_d); if ( c3y == _ames_is_czar(dad) && c3n == _ames_is_czar(our)) { // if we are a galaxy, don't STUN - u3l_log("ames: start STUN"); + sam_u->sun_u.dad_y = u3r_byte(0, dad); + sam_u->sun_u.wok_o = c3n; _stun_stop(sam_u); - _stun_start(sam_u, u3k(dad)); - // XX TODO on new saxo reset the timers for the DNS resolution and restart - // STUN + _stun_start(sam_u, c3n); } - u3z(zad); u3z(daz); u3z(dad); + u3z(zad); u3z(daz); u3z(our); } /* _ames_ef_send(): send packet to network (v4). @@ -2570,7 +2598,8 @@ _ames_recv_cb(uv_udp_t* wax_u, else if (_stun_is_request((c3_y*)buf_u->base, nrd_i) == c3y) { u3_ames* sam_u = wax_u->data; _stun_on_request(sam_u, (c3_y *)buf_u->base, adr_u); - } else if (_stun_is_our_response((c3_y*)buf_u->base, sam_u->sun_u.tid_y, nrd_i) + } + else if (_stun_is_our_response((c3_y*)buf_u->base, sam_u->sun_u.tid_y, nrd_i) == c3y) { c3_w cookie = 0x2112A442; c3_w ip_addr_xor = _ames_sift_word((c3_y *)buf_u->base + 28 + 12); @@ -2583,23 +2612,23 @@ _ames_recv_cb(uv_udp_t* wax_u, u3_noun wir = u3nc(c3__ames, u3_nul); 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) { + sam_u->sun_u.sef_u.pip_w != lan_u.pip_w) { // inject %once task into arvo u3l_log("IP port changed"); u3_noun cad = u3nt(c3__stun, c3__once, u3_nul); u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); u3_auto_plan(&sam_u->car_u, ovo_u); } else { - // XX previously, only the first STUN response would stop the ping app - // now, every successful response injects the %stop task, and %ping - // takes care of handling that appropiatedly - // inject %stun task into arvo - u3_noun cad = u3nt(c3__stun, c3__stop, u3_nul); - u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); - u3_auto_plan(&sam_u->car_u, ovo_u); + if (sam_u->sun_u.wok_o == c3n) { + // inject %stun task into arvo + u3_noun cad = u3nt(c3__stun, c3__stop, u3_nul); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + } } sam_u->sun_u.sef_u = lan_u; _stun_on_response(sam_u); + c3_free(buf_u->base); } else { u3_ames* sam_u = wax_u->data; struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; @@ -3020,6 +3049,12 @@ u3_ames_io_init(u3_pier* pir_u) sam_u->fig_u.see_o = c3y; sam_u->fig_u.fit_o = c3n; + // initialize STUN timers + uv_timer_init(u3L, &sam_u->sun_u.dns_u); + uv_timer_init(u3L, &sam_u->sun_u.tim_u); + sam_u->sun_u.tim_u.data = sam_u; + sam_u->sun_u.dns_u.data = sam_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); From 064c31343abf493fd020c8af9574b46434dfa6a8 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 15 Nov 2023 09:26:16 +0100 Subject: [PATCH 26/53] stun: backoff sending fail stun request --- pkg/vere/io/ames.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index e1a8d916db..544db3d90c 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1227,6 +1227,7 @@ static void _stun_czar(u3_ames* sam_u, c3_d tim_d); static void _stun_resolve_dns_cb(uv_timer_t* tim_u); static void _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i); static void _stun_on_failure(u3_ames* sam_u); +static void _stun_start(u3_ames* sam_u, c3_o fail); static c3_d _stun_time_gap(struct timeval start) @@ -1313,10 +1314,9 @@ _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i) } sam_u->sun_u.wok_o = c3n; - gettimeofday(&sam_u->sun_u.sar_u, 0); // reset timer to now sam_u->sun_u.sat_y = STUN_TRYING; - // retry sending the failed request in 500ms - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); + // retry sending the failed request + _stun_timer_cb(&sam_u->sun_u.tim_u); c3_free(snd_u->hun_y); c3_free(snd_u); } @@ -1476,9 +1476,9 @@ _stun_send_request(u3_ames* sam_u) } sam_u->sun_u.wok_o = c3n; - gettimeofday(&sam_u->sun_u.sar_u, 0); sam_u->sun_u.sat_y = STUN_TRYING; - _stun_send_request_cb((uv_udp_send_t*)snd_u, sas_i); + // retry sending the failed request + _stun_timer_cb(&sam_u->sun_u.tim_u); c3_free(buf_y); c3_free(snd_u); } From 37d9289eb448bd119d10e81c9cd66cee53a2b042 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 15 Nov 2023 09:29:00 +0100 Subject: [PATCH 27/53] stun: refactor _stun_on_failure --- pkg/vere/io/ames.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 544db3d90c..5e0c137038 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1309,10 +1309,7 @@ _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i) if ( sas_i ) { u3l_log("stun: send callback fail_async: %s", uv_strerror(sas_i)); - if (sam_u->sun_u.wok_o == c3y) { - _stun_on_failure(sam_u); // %kick ping app - } - sam_u->sun_u.wok_o = c3n; + _stun_on_failure(sam_u); // %kick ping app sam_u->sun_u.sat_y = STUN_TRYING; // retry sending the failed request @@ -1409,10 +1406,14 @@ _stun_on_response(u3_ames* sam_u) // TODO read arg static void _stun_on_failure(u3_ames* sam_u) { - u3_noun wir = u3nc(c3__ames, u3_nul); - u3_noun cad = u3nt(c3__stun, c3__fail, u3_nul); - u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); - u3_auto_plan(&sam_u->car_u, ovo_u); + // only inject event into arvo to %kick ping app on first failure + if (sam_u->sun_u.wok_o == c3y) { + u3_noun wir = u3nc(c3__ames, u3_nul); + u3_noun cad = u3nt(c3__stun, c3__fail, u3_nul); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + } + sam_u->sun_u.wok_o = c3n; } static void @@ -1423,10 +1424,7 @@ _stun_on_lost(uv_timer_t* tim_u) u3l_log("stun: waited too long..."); _stun_stop(sam_u); // only inject event into arvo to %kick ping app on first failure - if (sam_u->sun_u.wok_o == c3y) { - _stun_on_failure(sam_u); - } - sam_u->sun_u.wok_o = c3n; + _stun_on_failure(sam_u); // resolve DNS again, and (re)start STUN uv_timer_start(&sam_u->sun_u.tim_u, _stun_reset, 5*1000, 0); } @@ -1471,10 +1469,7 @@ _stun_send_request(u3_ames* sam_u) if ( sas_i != 0) { u3l_log("stun: send request fail_sync: %s", uv_strerror(sas_i)); - if (sam_u->sun_u.wok_o == c3y) { - _stun_on_failure(sam_u); // %kick ping app - } - sam_u->sun_u.wok_o = c3n; + _stun_on_failure(sam_u); // %kick ping app sam_u->sun_u.sat_y = STUN_TRYING; // retry sending the failed request @@ -1511,7 +1506,7 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, u3l_log("stun: _stun_czar_cb request fail_sync: %s", uv_strerror(sas_i)); _stun_stop(sam_u); _stun_czar_gone(sam_u, now); - sam_u->sun_u.wok_o = c3n; + _stun_on_failure(sam_u); // %kick ping app uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); } } From 597985afef918c9f846523bbed35ad395d44890d Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 15 Nov 2023 09:58:59 +0100 Subject: [PATCH 28/53] stun: stop timer on stun request sending failure --- pkg/vere/io/ames.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 5e0c137038..53a1dc784d 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1266,10 +1266,10 @@ _stun_timer_cb(uv_timer_t* tim_u) } break; case STUN_KEEPALIVE: { sam_u->sun_u.sat_y = STUN_TRYING; - _stun_send_request(sam_u); sam_u->sun_u.tim_u.data = sam_u; 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, 0); + _stun_send_request(sam_u); } break; case STUN_TRYING: { c3_d gap_d = _stun_time_gap(sam_u->sun_u.sar_u); @@ -1279,9 +1279,9 @@ _stun_timer_cb(uv_timer_t* tim_u) u3l_log("stun: more than 39 seconds passed..."); _stun_on_lost(&sam_u->sun_u.tim_u); } else if ( gap_d >= (31500) ) { - _stun_send_request(sam_u); // wait ~s8 for the last STUN request uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 8000 , 0); + _stun_send_request(sam_u); } else { uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, (nex_d >= 31500) ? 31500 : nex_d, 0); @@ -1312,8 +1312,8 @@ _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i) _stun_on_failure(sam_u); // %kick ping app sam_u->sun_u.sat_y = STUN_TRYING; - // retry sending the failed request - _stun_timer_cb(&sam_u->sun_u.tim_u); + uv_timer_stop(&sam_u->sun_u.tim_u); // stop any active timers + _stun_timer_cb(&sam_u->sun_u.tim_u); // retry sending the failed request c3_free(snd_u->hun_y); c3_free(snd_u); } @@ -1472,8 +1472,8 @@ _stun_send_request(u3_ames* sam_u) _stun_on_failure(sam_u); // %kick ping app sam_u->sun_u.sat_y = STUN_TRYING; - // retry sending the failed request - _stun_timer_cb(&sam_u->sun_u.tim_u); + uv_timer_stop(&sam_u->sun_u.tim_u); // stop any active timers XX needed? + _stun_timer_cb(&sam_u->sun_u.tim_u); // retry sending the failed request c3_free(buf_y); c3_free(snd_u); } From 154a33e3589723f2a9f3d5cd9b38b282b8682776 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 15 Nov 2023 10:01:34 +0100 Subject: [PATCH 29/53] stun: %kick ping app on dns failure --- pkg/vere/io/ames.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 53a1dc784d..d9c78e9a3b 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1650,7 +1650,7 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) u3l_log("stun: uv_getaddrinfo failed %s", uv_strerror(sas_i)); _stun_stop(sam_u); _stun_czar_gone(sam_u, time(0)); - sam_u->sun_u.wok_o = c3n; + _stun_on_failure(sam_u); // %kick ping app uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); return; } From ab893e8b5b1a6eea1c60f91ce42486b832b89cd3 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 15 Nov 2023 12:15:55 +0100 Subject: [PATCH 30/53] stun: removed logs --- pkg/vere/io/ames.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index d9c78e9a3b..1588626adc 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1276,7 +1276,6 @@ _stun_timer_cb(uv_timer_t* tim_u) c3_d nex_d = (gap_d * 2) + rto - gap_d; if ( gap_d >= (39500) ) { - u3l_log("stun: more than 39 seconds passed..."); _stun_on_lost(&sam_u->sun_u.tim_u); } else if ( gap_d >= (31500) ) { // wait ~s8 for the last STUN request @@ -1286,7 +1285,6 @@ _stun_timer_cb(uv_timer_t* tim_u) uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, (nex_d >= 31500) ? 31500 : nex_d, 0); _stun_send_request(sam_u); - u3l_log("stun: set RTO + last_timer * 2 %llu next: %llu", gap_d, (gap_d * 2) + rto); } } break; default: u3_assert(!"programmer error"); @@ -1421,9 +1419,7 @@ _stun_on_lost(uv_timer_t* tim_u) { u3_ames* sam_u = (u3_ames*)(tim_u->data); - u3l_log("stun: waited too long..."); _stun_stop(sam_u); - // only inject event into arvo to %kick ping app on first failure _stun_on_failure(sam_u); // resolve DNS again, and (re)start STUN uv_timer_start(&sam_u->sun_u.tim_u, _stun_reset, 5*1000, 0); @@ -2600,7 +2596,7 @@ _ames_recv_cb(uv_udp_t* wax_u, c3_w ip_addr_xor = _ames_sift_word((c3_y *)buf_u->base + 28 + 12); c3_s port_xor = _ames_sift_short((c3_y *)buf_u->base + 26 + 12); - // New lane + // new lane u3_lane lan_u; lan_u.por_s = ntohs(htons(port_xor) ^ cookie >> 16); lan_u.pip_w = ntohl(htonl(ip_addr_xor) ^ cookie); @@ -2608,14 +2604,13 @@ _ames_recv_cb(uv_udp_t* wax_u, u3_noun wir = u3nc(c3__ames, u3_nul); 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) { - // inject %once task into arvo - u3l_log("IP port changed"); + // IP:PORT changed u3_noun cad = u3nt(c3__stun, c3__once, u3_nul); u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); u3_auto_plan(&sam_u->car_u, ovo_u); } else { if (sam_u->sun_u.wok_o == c3n) { - // inject %stun task into arvo + // stop %ping app u3_noun cad = u3nt(c3__stun, c3__stop, u3_nul); u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); u3_auto_plan(&sam_u->car_u, ovo_u); From 3b67bdb4949508085c0e487f6ce84731836935a0 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 15 Nov 2023 12:18:00 +0100 Subject: [PATCH 31/53] stun: refactor logic after dns failure --- pkg/vere/io/ames.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 1588626adc..5d64603954 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1500,10 +1500,8 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, uv_timer_start(&sam_u->sun_u.dns_u, _stun_resolve_dns_cb, 5*60*1000, 0); } else { u3l_log("stun: _stun_czar_cb request fail_sync: %s", uv_strerror(sas_i)); - _stun_stop(sam_u); - _stun_czar_gone(sam_u, now); - _stun_on_failure(sam_u); // %kick ping app - uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); + _stun_czar_gone(sam_u, time(0)); + _stun_on_lost(&sam_u->sun_u.dns_u); } } c3_free(adr_u); @@ -1644,10 +1642,8 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) if (0 != (sas_i = uv_getaddrinfo(u3L, adr_u, _stun_czar_cb, dns_c, 0, &hints))) { u3l_log("stun: uv_getaddrinfo failed %s", uv_strerror(sas_i)); - _stun_stop(sam_u); _stun_czar_gone(sam_u, time(0)); - _stun_on_failure(sam_u); // %kick ping app - uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); + _stun_on_lost(&sam_u->sun_u.dns_u); return; } } From 78f752a80427210c59bdaa83bac04f2ef1e0e486 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 15 Nov 2023 12:35:35 +0100 Subject: [PATCH 32/53] stun: remove legacy mapped-address attribute --- pkg/vere/io/ames.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 5d64603954..60b58129cc 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1336,39 +1336,30 @@ static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], const struct sockaddr* adr_u) { struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; - c3_y buf_y[44] = {0}; + c3_y *buf_y = c3_calloc(32); c3_w cookie = 0x2112A442; c3_w cur_w = 20; // STUN header is 20 bytes memcpy(buf_y, buf_r, cur_w); // copy STUN request header buf_y[0] = 0x01; buf_y[1] = 0x01; // 0x0101 SUCCESS RESPONSE - buf_y[2] = 0x00; buf_y[3] = 0x18; // Length: 24 bytes - - // XX REMOVE - // MAPPED-ADDRESS - buf_y[cur_w] = 0x00; buf_y[cur_w + 1] = 0x01; // attribute type 0x0001 - buf_y[cur_w + 2] = 0x00; buf_y[cur_w + 3] = 0x08; // STUN attribute length - // extra reserved 0x0 byte - buf_y[cur_w + 5] = 0x01; // family 0x01:IPv4 - memcpy(buf_y + cur_w + 6, &add_u->sin_port, 2); // Port - memcpy(buf_y + cur_w + 8, &add_u->sin_addr.s_addr, 4); // IP Addres + buf_y[2] = 0x00; buf_y[3] = 0x0c; // Length: 12 bytes // XOR-MAPPED-ADDRESS - buf_y[cur_w + 12] = 0x00; buf_y[cur_w + 13] = 0x20; // attribute type 0x00020 - buf_y[cur_w + 14] = 0x00; buf_y[cur_w + 15] = 0x08; // STUN attribute length + buf_y[cur_w] = 0x00; buf_y[cur_w + 1] = 0x20; // attribute type 0x00020 + buf_y[cur_w + 2] = 0x00; buf_y[cur_w + 3] = 0x08; // STUN attribute length // extra reserved 0x0 byte - buf_y[cur_w + 17] = 0x01; // family 0x01:IPv4 + buf_y[cur_w + 5] = 0x01; // family 0x01:IPv4 c3_s x_port = htons(ntohs(add_u->sin_port) ^ cookie >> 16); c3_w x_ip = htonl(ntohl(add_u->sin_addr.s_addr) ^ cookie); - memcpy(buf_y + cur_w + 18, &x_port, 2); // X-Port - memcpy(buf_y + cur_w + 20, &x_ip, 4); // X-IP Addres + memcpy(buf_y + cur_w + 6, &x_port, 2); // X-Port + memcpy(buf_y + cur_w + 8, &x_ip, 4); // X-IP Addres - uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 44); + uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 32); u3_stun_send* snd_u = c3_calloc(sizeof(*snd_u)); snd_u->sam_u = sam_u; - snd_u->hun_y = buf_r; + snd_u->hun_y = buf_y; c3_i sas_i = uv_udp_send( (uv_udp_send_t*)snd_u, &sam_u->wax_u, &buf_u, 1, adr_u, _stun_send_response_cb @@ -1376,7 +1367,7 @@ static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], if ( sas_i != 0) { u3l_log("stun: send response fail_sync: %s", uv_strerror(sas_i)); - c3_free(buf_r); + c3_free(buf_y); c3_free(snd_u); } } @@ -2585,6 +2576,7 @@ _ames_recv_cb(uv_udp_t* wax_u, else if (_stun_is_request((c3_y*)buf_u->base, nrd_i) == c3y) { u3_ames* sam_u = wax_u->data; _stun_on_request(sam_u, (c3_y *)buf_u->base, adr_u); + c3_free(buf_u->base); } else if (_stun_is_our_response((c3_y*)buf_u->base, sam_u->sun_u.tid_y, nrd_i) == c3y) { From 28d5aefdd7ecc4baf9f797b854cac4d64b570610 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 16 Nov 2023 10:46:04 +0100 Subject: [PATCH 33/53] stun: fix check for stun response --- pkg/vere/io/ames.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 60b58129cc..5b335d364d 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1221,7 +1221,7 @@ _stun_stop(u3_ames* sam_u) // XX (code reordering?) forward declarations static void _stun_send_request(u3_ames*); -static void _stun_on_lost(uv_timer_t* tim_u); +static void _stun_on_lost(u3_ames* sam_u); static void _stun_czar_gone(u3_ames* sam_u, time_t now); static void _stun_czar(u3_ames* sam_u, c3_d tim_d); static void _stun_resolve_dns_cb(uv_timer_t* tim_u); @@ -1247,7 +1247,6 @@ _stun_reset(uv_timer_t* tim_u) u3_ames* sam_u = (u3_ames*)(tim_u->data); // sam_u->fig_u.net_o = c3n; // XX needed? - c3_d tim_d = 39500; _stun_start(sam_u, c3y); } @@ -1276,7 +1275,7 @@ _stun_timer_cb(uv_timer_t* tim_u) c3_d nex_d = (gap_d * 2) + rto - gap_d; if ( gap_d >= (39500) ) { - _stun_on_lost(&sam_u->sun_u.tim_u); + _stun_on_lost(sam_u); } else if ( gap_d >= (31500) ) { // wait ~s8 for the last STUN request uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 8000 , 0); @@ -1384,8 +1383,6 @@ _stun_on_response(u3_ames* sam_u) // TODO read arg sam_u->sun_u.sat_y = STUN_KEEPALIVE; sam_u->sun_u.tid_y[1]++; uv_timer_stop(&sam_u->sun_u.tim_u); - - sam_u->sun_u.wok_o = c3y; uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); } break; default: assert("programmer error"); @@ -1406,14 +1403,13 @@ _stun_on_failure(u3_ames* sam_u) } static void -_stun_on_lost(uv_timer_t* tim_u) +_stun_on_lost(u3_ames* sam_u) { - u3_ames* sam_u = (u3_ames*)(tim_u->data); - _stun_stop(sam_u); _stun_on_failure(sam_u); // resolve DNS again, and (re)start STUN - uv_timer_start(&sam_u->sun_u.tim_u, _stun_reset, 5*1000, 0); + // XX call _stun_start(sam_u, c3y) directly? + uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); } static void @@ -1492,7 +1488,7 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, } else { u3l_log("stun: _stun_czar_cb request fail_sync: %s", uv_strerror(sas_i)); _stun_czar_gone(sam_u, time(0)); - _stun_on_lost(&sam_u->sun_u.dns_u); + _stun_on_lost(sam_u); } } c3_free(adr_u); @@ -1634,18 +1630,17 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) dns_c, 0, &hints))) { u3l_log("stun: uv_getaddrinfo failed %s", uv_strerror(sas_i)); _stun_czar_gone(sam_u, time(0)); - _stun_on_lost(&sam_u->sun_u.dns_u); + _stun_on_lost(sam_u); return; } } } static c3_o -_stun_is_our_response(c3_y buf_y[44], c3_y tid_y[12], c3_w buf_len) +_stun_is_our_response(c3_y buf_y[32], c3_y tid_y[12], c3_w buf_len) { c3_w cookie = htonl(0x2112A442); - - return !(buf_len == 44 && + return !(buf_len == 32 && buf_y[0] == 0x01 && buf_y[1] == 0x01 && memcmp(&cookie, buf_y + 4, 4) == 0 && memcmp(tid_y, buf_y + 8, 12) == 0 @@ -2581,9 +2576,8 @@ _ames_recv_cb(uv_udp_t* wax_u, else if (_stun_is_our_response((c3_y*)buf_u->base, sam_u->sun_u.tid_y, nrd_i) == c3y) { c3_w cookie = 0x2112A442; - c3_w ip_addr_xor = _ames_sift_word((c3_y *)buf_u->base + 28 + 12); - c3_s port_xor = _ames_sift_short((c3_y *)buf_u->base + 26 + 12); - + c3_w ip_addr_xor = _ames_sift_word((c3_y *)buf_u->base + 28); + c3_s port_xor = _ames_sift_short((c3_y *)buf_u->base + 26); // new lane u3_lane lan_u; lan_u.por_s = ntohs(htons(port_xor) ^ cookie >> 16); @@ -2596,13 +2590,13 @@ _ames_recv_cb(uv_udp_t* wax_u, u3_noun cad = u3nt(c3__stun, c3__once, u3_nul); u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); u3_auto_plan(&sam_u->car_u, ovo_u); - } else { - if (sam_u->sun_u.wok_o == c3n) { - // stop %ping app - u3_noun cad = u3nt(c3__stun, c3__stop, u3_nul); - u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); - u3_auto_plan(&sam_u->car_u, ovo_u); - } + } + else if (sam_u->sun_u.wok_o == c3n) { + // stop %ping app + u3_noun cad = u3nt(c3__stun, c3__stop, u3_nul); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + sam_u->sun_u.wok_o = c3y; } sam_u->sun_u.sef_u = lan_u; _stun_on_response(sam_u); From 692bc305468a94441b0c2095eda8e48f51ee54d6 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 16 Nov 2023 13:33:51 +0100 Subject: [PATCH 34/53] stun: refactor _ames_czar_gone --- pkg/vere/io/ames.c | 53 +++++++++++++--------------------------------- 1 file changed, 15 insertions(+), 38 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 5b335d364d..ddf4844daf 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1001,13 +1001,10 @@ _ames_czar_dns(c3_c dns_c[255], c3_y imp_y, c3_c* czar_c) /* _ames_czar_gone(): galaxy address resolution failed. */ static void -_ames_czar_gone(u3_pact* pac_u, time_t now) +_ames_czar_gone(u3_ames* sam_u, time_t now, c3_d imp_y, c3_c* dns_c) { - u3_ames* sam_u = pac_u->sam_u; - c3_d imp_y = pac_u->rut_u.imp_y; - if ( c3y == sam_u->imp_o[imp_y] ) { - u3l_log("ames: czar at %s: not found (b)", pac_u->rut_u.dns_c); + u3l_log("ames: czar at %s: not found (b)", dns_c); sam_u->imp_o[imp_y] = c3n; } @@ -1020,8 +1017,6 @@ _ames_czar_gone(u3_pact* pac_u, time_t now) // keep existing ip for 5 more minutes // sam_u->imp_t[imp_y] = now; - - _ames_pact_free(pac_u); } /* _ames_czar_here(): galaxy address resolution succeeded. @@ -1063,11 +1058,14 @@ _ames_czar_cb(uv_getaddrinfo_t* adr_u, struct addrinfo* rai_u = aif_u; struct sockaddr_in* aid_u = (struct sockaddr_in *)rai_u->ai_addr; time_t now = time(0); + c3_d imp_y = pac_u->rut_u.imp_y; + c3_c* dns_c = pac_u->rut_u.dns_c; if ( sas_i == 0 ) { - pac_u->rut_u.lan_u.pip_w = _ames_czar_here(pac_u->sam_u, now, aid_u); + pac_u->rut_u.lan_u.pip_w = _ames_czar_here(pac_u->sam_u, now, aid_u); } else { - _ames_czar_gone(pac_u, now); + _ames_czar_gone(pac_u->sam_u, now, imp_y, dns_c); + _ames_pact_free(pac_u); } } @@ -1153,7 +1151,8 @@ _ames_czar(u3_pact* pac_u) { uv_getaddrinfo_t* adr_u = c3_malloc(sizeof(*adr_u)); adr_u->data = pac_u; - + c3_d imp_y = pac_u->rut_u.imp_y; + c3_c* dns_c = pac_u->rut_u.dns_c; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; // only IPv4 addresses @@ -1163,7 +1162,8 @@ _ames_czar(u3_pact* pac_u) pac_u->rut_u.dns_c, 0, &hints)) ) { u3l_log("ames: %s", uv_strerror(sas_i)); - _ames_czar_gone(pac_u, now); + _ames_czar_gone(pac_u->sam_u, now, imp_y, dns_c); + _ames_pact_free(pac_u); return; } } @@ -1222,7 +1222,6 @@ _stun_stop(u3_ames* sam_u) // XX (code reordering?) forward declarations static void _stun_send_request(u3_ames*); static void _stun_on_lost(u3_ames* sam_u); -static void _stun_czar_gone(u3_ames* sam_u, time_t now); static void _stun_czar(u3_ames* sam_u, c3_d tim_d); static void _stun_resolve_dns_cb(uv_timer_t* tim_u); static void _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i); @@ -1472,6 +1471,8 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, struct addrinfo* rai_u = aif_u; struct sockaddr_in* aid_u = (struct sockaddr_in *)rai_u->ai_addr; time_t now = time(0); + c3_d imp_y = sam_u->sun_u.dad_y; + c3_c* dns_c = sam_u->dns_c; gettimeofday(&sam_u->sun_u.sar_u, 0); // set start time to now @@ -1487,7 +1488,7 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, uv_timer_start(&sam_u->sun_u.dns_u, _stun_resolve_dns_cb, 5*60*1000, 0); } else { u3l_log("stun: _stun_czar_cb request fail_sync: %s", uv_strerror(sas_i)); - _stun_czar_gone(sam_u, time(0)); + _ames_czar_gone(sam_u, time(0), imp_y, dns_c); _stun_on_lost(sam_u); } } @@ -1558,30 +1559,6 @@ _stun_czar(u3_ames* sam_u, c3_d tim_d) } } -// XX refactor (see _ames_czar_gone) -/* _stun_czar_gone(): galaxy address resolution failed. -*/ -static void -_stun_czar_gone(u3_ames* sam_u, time_t now) -{ - c3_y imp_y = sam_u->sun_u.dad_y; - - if ( c3y == sam_u->imp_o[imp_y] ) { - u3l_log("stun: czar at %s: not found (b)", sam_u->dns_c); // XX - sam_u->imp_o[imp_y] = c3n; - } - - if ( (0 == sam_u->imp_w[imp_y]) || - (0xffffffff == sam_u->imp_w[imp_y]) ) - { - sam_u->imp_w[imp_y] = 0xffffffff; - } - - // keep existing ip for 5 more minutes - // - sam_u->imp_t[imp_y] = now; -} - static void _stun_start(u3_ames* sam_u, c3_o fail) { @@ -1629,7 +1606,7 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) if (0 != (sas_i = uv_getaddrinfo(u3L, adr_u, _stun_czar_cb, dns_c, 0, &hints))) { u3l_log("stun: uv_getaddrinfo failed %s", uv_strerror(sas_i)); - _stun_czar_gone(sam_u, time(0)); + _ames_czar_gone(sam_u, time(0), sam_u->sun_u.dad_y, sam_u->dns_c); _stun_on_lost(sam_u); return; } From fd32d716531a03f87a004bbd418e83f567d14908 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 16 Nov 2023 14:10:04 +0100 Subject: [PATCH 35/53] stun: refactor _ames_czar_dns --- pkg/vere/io/ames.c | 38 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index ddf4844daf..800616bfef 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -58,6 +58,7 @@ typedef enum u3_stun_state { u3_lane lan_u; // sponsoring galaxy IP and port uv_timer_t tim_u; // keepalive timer handle uv_timer_t dns_u; // DNS resolution timer handle + c3_c* dns_c; // sponsoring galaxy fqdn struct timeval las_u; // XX last sent date (not used?) struct timeval sar_u; // date we started trying to send u3_lane sef_u; // our lane, if we know it @@ -984,14 +985,13 @@ _ames_czar_port(c3_y imp_y) } static c3_i -_ames_czar_dns(c3_c dns_c[255], c3_y imp_y, c3_c* czar_c) +_ames_czar_dns(c3_c** dns_c, c3_y imp_y, c3_c* czar_c) { u3_noun nam = u3dc("scot", 'p', imp_y); - u3m_p("imp", nam); c3_c* nam_c = u3r_string(nam); - u3l_log("stun: 1"); - c3_i sas_i = snprintf(dns_c, 255, "%s.%s", nam_c + 1, czar_c); - u3l_log("stun: 2"); + *dns_c = c3_malloc(1 + strlen(nam_c) + strlen(czar_c)); + + c3_i sas_i = snprintf(*dns_c, 255, "%s.%s", nam_c + 1, czar_c); c3_free(nam_c); u3z(nam); @@ -1124,23 +1124,7 @@ _ames_czar(u3_pact* pac_u) return; } else { - c3_i sas_i; - - { - u3_noun nam = u3dc("scot", 'p', imp_y); - c3_c* nam_c = u3r_string(nam); - - // NB: . separator not counted, as [nam_c] includes a ~ that we skip - // - pac_u->rut_u.dns_c = - c3_malloc(1 + strlen(nam_c) + strlen(sam_u->dns_c)); - - sas_i = - snprintf(pac_u->rut_u.dns_c, 255, "%s.%s", nam_c + 1, sam_u->dns_c); - - c3_free(nam_c); - u3z(nam); - } + c3_i sas_i = _ames_czar_dns(&pac_u->rut_u.dns_c, imp_y, sam_u->dns_c); if ( 255 <= sas_i ) { u3l_log("ames: czar: galaxy domain %s truncated", sam_u->dns_c); @@ -1153,6 +1137,7 @@ _ames_czar(u3_pact* pac_u) adr_u->data = pac_u; c3_d imp_y = pac_u->rut_u.imp_y; c3_c* dns_c = pac_u->rut_u.dns_c; + struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; // only IPv4 addresses @@ -1479,7 +1464,6 @@ _stun_czar_cb(uv_getaddrinfo_t* adr_u, if (sas_i == 0) { _ames_czar_here(sam_u, now, aid_u); if (sam_u->sun_u.sat_y == STUN_OFF) { - u3l_log("stun: was OFF, start TRYING"); sam_u->sun_u.sat_y = STUN_TRYING; _stun_send_request(sam_u); uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 500, 0); @@ -1515,6 +1499,7 @@ _stun_czar(u3_ames* sam_u, c3_d tim_d) return; } + // if we don't have a galaxy domain, no-op // if (!sam_u->dns_c) { @@ -1584,11 +1569,10 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) { u3_ames* sam_u = (u3_ames*)(tim_u->data); c3_i sas_i; - c3_c dns_c[255]; c3_y imp_y = sam_u->sun_u.dad_y; sam_u->sun_u.lan_u.por_s = _ames_czar_port(imp_y); - sas_i = _ames_czar_dns(dns_c, imp_y, sam_u->dns_c); + sas_i = _ames_czar_dns(&sam_u->sun_u.dns_c, imp_y, sam_u->dns_c); if (255 <= sas_i) { u3l_log("stun: czar: galaxy domain %s truncated", sam_u->dns_c); @@ -1604,8 +1588,8 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) hints.ai_family = AF_INET; // only IPv4 addresses if (0 != (sas_i = uv_getaddrinfo(u3L, adr_u, _stun_czar_cb, - dns_c, 0, &hints))) { - u3l_log("stun: uv_getaddrinfo failed %s", uv_strerror(sas_i)); + sam_u->sun_u.dns_c, 0, &hints))) { + u3l_log("stun: uv_getaddrinfo failed %s %s", uv_strerror(sas_i), sam_u->sun_u.dns_c); _ames_czar_gone(sam_u, time(0), sam_u->sun_u.dad_y, sam_u->dns_c); _stun_on_lost(sam_u); return; From 42e672c12315caa58120ec05badc9d40c01b96fd Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 16 Nov 2023 14:56:38 +0100 Subject: [PATCH 36/53] stun: pass in expression in _stun_czar --- pkg/vere/io/ames.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 800616bfef..d5cf86ed10 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1559,9 +1559,7 @@ _stun_start(u3_ames* sam_u, c3_o fail) u3z(mug); } - c3_d tim_d = (fail == c3n) ? 500 : 39500; - - _stun_czar(sam_u, tim_d); + _stun_czar(sam_u, (fail == c3n) ? 500 : 39500); } static void From c44041f219bc9676a1909cadb9d50bd581c103d3 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Fri, 17 Nov 2023 10:35:28 +0100 Subject: [PATCH 37/53] stun: refactor --- pkg/vere/io/ames.c | 148 +++++++++++++++++++++++++-------------------- 1 file changed, 81 insertions(+), 67 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index d5cf86ed10..87a00e82ba 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -984,18 +984,23 @@ _ames_czar_port(c3_y imp_y) } } -static c3_i -_ames_czar_dns(c3_c** dns_c, c3_y imp_y, c3_c* czar_c) +static c3_c* +_ames_czar_dns(c3_y imp_y, c3_c* czar_c) { u3_noun nam = u3dc("scot", 'p', imp_y); c3_c* nam_c = u3r_string(nam); - *dns_c = c3_malloc(1 + strlen(nam_c) + strlen(czar_c)); + c3_w len_w = 3 + strlen(nam_c) + strlen(czar_c); + u3l_log("len %u", len_w); + u3_assert(len_w <= 256); + c3_c* dns_c = c3_malloc(len_w); + + c3_i sas_i = snprintf(dns_c, len_w, "%s.%s.", nam_c + 1, czar_c); + u3_assert(sas_i <= 255); - c3_i sas_i = snprintf(*dns_c, 255, "%s.%s", nam_c + 1, czar_c); c3_free(nam_c); u3z(nam); - return sas_i; + return dns_c; } /* _ames_czar_gone(): galaxy address resolution failed. @@ -1124,19 +1129,14 @@ _ames_czar(u3_pact* pac_u) return; } else { - c3_i sas_i = _ames_czar_dns(&pac_u->rut_u.dns_c, imp_y, sam_u->dns_c); - - if ( 255 <= sas_i ) { - u3l_log("ames: czar: galaxy domain %s truncated", sam_u->dns_c); - _ames_pact_free(pac_u); - return; - } + pac_u->rut_u.dns_c = _ames_czar_dns(imp_y, sam_u->dns_c); { uv_getaddrinfo_t* adr_u = c3_malloc(sizeof(*adr_u)); adr_u->data = pac_u; c3_d imp_y = pac_u->rut_u.imp_y; c3_c* dns_c = pac_u->rut_u.dns_c; + c3_i sas_i; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); @@ -1230,8 +1230,6 @@ _stun_reset(uv_timer_t* tim_u) { u3_ames* sam_u = (u3_ames*)(tim_u->data); - // sam_u->fig_u.net_o = c3n; // XX needed? - _stun_start(sam_u, c3y); } @@ -1281,6 +1279,17 @@ typedef struct _u3_stun_send { } u3_stun_send; +static void +_stun_on_request_fail(u3_ames* sam_u, c3_i sas_i) +{ + u3l_log("stun: send callback fail_async: %s", uv_strerror(sas_i)); + + _stun_on_failure(sam_u); // %kick ping app + + sam_u->sun_u.sat_y = STUN_TRYING; + _stun_timer_cb(&sam_u->sun_u.tim_u); // retry sending the failed request +} + static void _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i) { @@ -1288,20 +1297,14 @@ _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i) u3_ames* sam_u = snd_u->sam_u; if ( sas_i ) { - u3l_log("stun: send callback fail_async: %s", uv_strerror(sas_i)); - - _stun_on_failure(sam_u); // %kick ping app - - sam_u->sun_u.sat_y = STUN_TRYING; - uv_timer_stop(&sam_u->sun_u.tim_u); // stop any active timers - _stun_timer_cb(&sam_u->sun_u.tim_u); // retry sending the failed request - c3_free(snd_u->hun_y); - c3_free(snd_u); + _stun_on_request_fail(sam_u, sas_i); } else { // XX curently not used gettimeofday(&sam_u->sun_u.las_u, 0); // overwrite last sent date } + c3_free(snd_u->hun_y); + c3_free(snd_u); } static void @@ -1315,7 +1318,7 @@ _stun_send_response_cb(uv_udp_send_t *rep_u, c3_i sas_i) } } -static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], +static void _stun_on_request(u3_ames *sam_u, c3_y* buf_r, const struct sockaddr* adr_u) { struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; @@ -1356,16 +1359,46 @@ static void _stun_on_request(u3_ames *sam_u, c3_y buf_r[20], } static void -_stun_on_response(u3_ames* sam_u) // TODO read arg +_stun_on_response(u3_ames* sam_u, c3_y* buf_y) { u3_stun_state old_y = sam_u->sun_u.sat_y; + c3_w cookie = 0x2112A442; + // XX check attribute tags (see RFC) + c3_w ip_addr_xor = _ames_sift_word(buf_y + 28); + c3_s port_xor = _ames_sift_short(buf_y + 26); + // new lane + u3_lane lan_u; + lan_u.por_s = ntohs(htons(port_xor) ^ cookie >> 16); + lan_u.pip_w = ntohl(htonl(ip_addr_xor) ^ cookie); + + u3_noun wir = u3nc(c3__ames, u3_nul); + + if (sam_u->sun_u.wok_o == c3n) { + // stop %ping app + u3_noun cad = u3nt(c3__stun, c3__stop, u3_nul); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + sam_u->sun_u.wok_o = c3y; + } + else 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) { + // IP:PORT changed + u3_noun cad = u3nt(c3__stun, c3__once, u3_nul); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + } + else { + u3z(wir); + } + sam_u->sun_u.sef_u = lan_u; + switch ( sam_u->sun_u.sat_y ) { case STUN_OFF: break; // ignore; stray response case STUN_KEEPALIVE: break; // ignore; duplicate response case STUN_TRYING: { sam_u->sun_u.sat_y = STUN_KEEPALIVE; - sam_u->sun_u.tid_y[1]++; + sam_u->sun_u.tid_y[1]++; // XX needs to be random every time uv_timer_stop(&sam_u->sun_u.tim_u); uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); } break; @@ -1434,13 +1467,7 @@ _stun_send_request(u3_ames* sam_u) ); if ( sas_i != 0) { - u3l_log("stun: send request fail_sync: %s", uv_strerror(sas_i)); - - _stun_on_failure(sam_u); // %kick ping app - - sam_u->sun_u.sat_y = STUN_TRYING; - uv_timer_stop(&sam_u->sun_u.tim_u); // stop any active timers XX needed? - _stun_timer_cb(&sam_u->sun_u.tim_u); // retry sending the failed request + _stun_on_request_fail(sam_u, sas_i); c3_free(buf_y); c3_free(snd_u); } @@ -1555,6 +1582,7 @@ _stun_start(u3_ames* sam_u, c3_o fail) gettimeofday(&tim_u, 0); mug = u3r_mug(u3_time_in_tv(&tim_u)); + // XX doesn't work, revisit memcpy(sam_u->sun_u.tid_y, (c3_y*)&mug, 4); u3z(mug); } @@ -1570,11 +1598,9 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) c3_y imp_y = sam_u->sun_u.dad_y; sam_u->sun_u.lan_u.por_s = _ames_czar_port(imp_y); - sas_i = _ames_czar_dns(&sam_u->sun_u.dns_c, imp_y, sam_u->dns_c); - if (255 <= sas_i) { - u3l_log("stun: czar: galaxy domain %s truncated", sam_u->dns_c); - return; + if (!sam_u->sun_u.dns_c) { + sam_u->sun_u.dns_c = _ames_czar_dns(imp_y, sam_u->dns_c); } { @@ -1596,7 +1622,7 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) } static c3_o -_stun_is_our_response(c3_y buf_y[32], c3_y tid_y[12], c3_w buf_len) +_stun_is_our_response(c3_y* buf_y, c3_y tid_y[12], c3_w buf_len) { c3_w cookie = htonl(0x2112A442); return !(buf_len == 32 && @@ -1607,7 +1633,7 @@ _stun_is_our_response(c3_y buf_y[32], c3_y tid_y[12], c3_w buf_len) } static c3_o -_stun_is_request(c3_y buf_y[20], c3_w buf_len) +_stun_is_request(c3_y* buf_y, c3_w buf_len) { c3_w cookie = htonl(0x2112A442); @@ -1637,6 +1663,7 @@ _ames_ef_saxo(u3_ames* sam_u, u3_noun zad) daz = u3qb_flop(zad); if ( u3_nul == daz ) { u3l_log("ames: empty sponsorship chain"); + u3z(zad); u3z(daz); return; } @@ -2527,39 +2554,20 @@ _ames_recv_cb(uv_udp_t* wax_u, } c3_free(buf_u->base); } + // 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 + // else if (_stun_is_request((c3_y*)buf_u->base, nrd_i) == c3y) { - u3_ames* sam_u = wax_u->data; _stun_on_request(sam_u, (c3_y *)buf_u->base, adr_u); c3_free(buf_u->base); } else if (_stun_is_our_response((c3_y*)buf_u->base, sam_u->sun_u.tid_y, nrd_i) == c3y) { - c3_w cookie = 0x2112A442; - c3_w ip_addr_xor = _ames_sift_word((c3_y *)buf_u->base + 28); - c3_s port_xor = _ames_sift_short((c3_y *)buf_u->base + 26); - // new lane - u3_lane lan_u; - lan_u.por_s = ntohs(htons(port_xor) ^ cookie >> 16); - lan_u.pip_w = ntohl(htonl(ip_addr_xor) ^ cookie); - - u3_noun wir = u3nc(c3__ames, u3_nul); - 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) { - // IP:PORT changed - u3_noun cad = u3nt(c3__stun, c3__once, u3_nul); - u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); - u3_auto_plan(&sam_u->car_u, ovo_u); - } - else if (sam_u->sun_u.wok_o == c3n) { - // stop %ping app - u3_noun cad = u3nt(c3__stun, c3__stop, u3_nul); - u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); - u3_auto_plan(&sam_u->car_u, ovo_u); - sam_u->sun_u.wok_o = c3y; - } - sam_u->sun_u.sef_u = lan_u; - _stun_on_response(sam_u); - c3_free(buf_u->base); + _stun_on_response(sam_u, (c3_y*)buf_u->base); + c3_free(buf_u->base); } else { u3_ames* sam_u = wax_u->data; struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; @@ -2660,8 +2668,14 @@ _ames_ef_turf(u3_ames* sam_u, u3_noun tuf) u3_mcut_host(sam_u->dns_c, 0, hot); sam_u->dns_c[len_w] = 0; + if (len_w <= 250) { + // 3 char for the galaxy (e.g. zod) and two dots + u3l_log("ames: galaxy domain too big %s len=%u", sam_u->dns_c, len_w); + u3_pier_bail(u3_king_stub()); + } + // XX invalidate sam_u->imp_w &c ? - // + // also invalidate sun_u.dns_c u3z(tuf); } From d72087d679908e6aae86f6390643ab53c68c482a Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Fri, 17 Nov 2023 11:26:41 +0100 Subject: [PATCH 38/53] stun: use 12 bytes of entropy for transaction id --- pkg/vere/io/ames.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 87a00e82ba..48c44ab3ff 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -53,7 +53,7 @@ typedef enum u3_stun_state { c3_o imp_o[256]; // imperial print status struct { // stun client state: u3_stun_state sat_y; // formal state - c3_y tid_y[16]; // last transaction id + 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 @@ -990,7 +990,6 @@ _ames_czar_dns(c3_y imp_y, c3_c* czar_c) u3_noun nam = u3dc("scot", 'p', imp_y); c3_c* nam_c = u3r_string(nam); c3_w len_w = 3 + strlen(nam_c) + strlen(czar_c); - u3l_log("len %u", len_w); u3_assert(len_w <= 256); c3_c* dns_c = c3_malloc(len_w); @@ -1398,9 +1397,16 @@ _stun_on_response(u3_ames* sam_u, c3_y* buf_y) case STUN_KEEPALIVE: break; // ignore; duplicate response case STUN_TRYING: { sam_u->sun_u.sat_y = STUN_KEEPALIVE; - sam_u->sun_u.tid_y[1]++; // XX needs to be random every time - uv_timer_stop(&sam_u->sun_u.tim_u); - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); + c3_y buf_y[12] = {0}; + c3_i sas_i = uv_random(NULL, NULL, buf_y, 12, 0, NULL); + if (sas_i != 0) { + u3l_log("stun: can't STUN uv_random fail: %s", uv_strerror(sas_i)); + _stun_on_lost(sam_u); + } + else { + memcpy(sam_u->sun_u.tid_y, buf_y, 12); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); + } } break; default: assert("programmer error"); } @@ -1574,20 +1580,17 @@ _stun_czar(u3_ames* sam_u, c3_d tim_d) static void _stun_start(u3_ames* sam_u, c3_o fail) { + c3_y buf_y[12] = {0}; + // XX uv_random may block indefinitely when not enough entropy is available. + c3_i sas_i = uv_random(NULL, NULL, buf_y, 12, 0, NULL); - // initialize STUN transaction id to mug of now - { - u3_noun mug; - struct timeval tim_u; - gettimeofday(&tim_u, 0); - - mug = u3r_mug(u3_time_in_tv(&tim_u)); - // XX doesn't work, revisit - memcpy(sam_u->sun_u.tid_y, (c3_y*)&mug, 4); - u3z(mug); + if (sas_i != 0) { + u3l_log("stun: can't STUN uv_random fail: %s", uv_strerror(sas_i)); + _stun_on_lost(sam_u); + } else { + memcpy(sam_u->sun_u.tid_y, buf_y, 12); + _stun_czar(sam_u, (fail == c3n) ? 500 : 39500); } - - _stun_czar(sam_u, (fail == c3n) ? 500 : 39500); } static void From c07b3158b91fc2a568b349512d48cd729d4ab52a Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 20 Nov 2023 11:55:51 +0100 Subject: [PATCH 39/53] stun: add fingerprint attribute and check --- pkg/vere/io/ames.c | 129 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 116 insertions(+), 13 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 48c44ab3ff..c2ac755c9d 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1211,6 +1211,7 @@ static void _stun_resolve_dns_cb(uv_timer_t* tim_u); static void _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i); static void _stun_on_failure(u3_ames* sam_u); static void _stun_start(u3_ames* sam_u, c3_o fail); +static c3_y* _stun_add_fingerprint(c3_y *message, c3_w index); static c3_d _stun_time_gap(struct timeval start) @@ -1321,13 +1322,13 @@ static void _stun_on_request(u3_ames *sam_u, c3_y* buf_r, const struct sockaddr* adr_u) { struct sockaddr_in* add_u = (struct sockaddr_in*)adr_u; - c3_y *buf_y = c3_calloc(32); + c3_y *buf_y = c3_calloc(40); c3_w cookie = 0x2112A442; c3_w cur_w = 20; // STUN header is 20 bytes memcpy(buf_y, buf_r, cur_w); // copy STUN request header buf_y[0] = 0x01; buf_y[1] = 0x01; // 0x0101 SUCCESS RESPONSE - buf_y[2] = 0x00; buf_y[3] = 0x0c; // Length: 12 bytes + buf_y[2] = 0x00; buf_y[3] = 0x14; // Length: 20 bytes // XOR-MAPPED-ADDRESS buf_y[cur_w] = 0x00; buf_y[cur_w + 1] = 0x20; // attribute type 0x00020 @@ -1337,10 +1338,13 @@ static void _stun_on_request(u3_ames *sam_u, c3_y* buf_r, c3_s x_port = htons(ntohs(add_u->sin_port) ^ cookie >> 16); c3_w x_ip = htonl(ntohl(add_u->sin_addr.s_addr) ^ cookie); - memcpy(buf_y + cur_w + 6, &x_port, 2); // X-Port - memcpy(buf_y + cur_w + 8, &x_ip, 4); // X-IP Addres + memcpy(buf_y + cur_w + 6, &x_port, 2); // X-Port + memcpy(buf_y + cur_w + 8, &x_ip, 4); // X-IP Addres - uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 32); + // FINGERPRINT + buf_y = _stun_add_fingerprint(buf_y, cur_w + 12); + + uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 40); u3_stun_send* snd_u = c3_calloc(sizeof(*snd_u)); snd_u->sam_u = sam_u; @@ -1435,6 +1439,28 @@ _stun_on_lost(u3_ames* sam_u) uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); } +/* Adapted from: +https://web.archive.org/web/20190108202303/http://www.hackersdelight.org/hdcodetxt/crc.c.txt +*/ +static c3_w crc32b(c3_y *message, c3_w len) { + c3_w i, j; + c3_y byte; + c3_w crc, mask; + + i = 0; + crc = 0xFFFFFFFF; + while (len--) { + byte = message[i]; // Get next byte. + crc = crc ^ byte; + for (j = 0; j < 8; j++) { // Do eight times. + mask = -(crc & 1); + crc = (crc >> 1) ^ (0xEDB88320 & mask); + } + i = i + 1; + } + return ~crc; +} + static void _stun_send_request(u3_ames* sam_u) { @@ -1448,13 +1474,14 @@ _stun_send_request(u3_ames* sam_u) // see STUN RFC 8489 // https://datatracker.ietf.org/doc/html/rfc8489#section-5 - c3_y *buf_y = c3_calloc(20); + c3_y *buf_y = c3_calloc(28); // STUN message type: "binding request" buf_y[1] = 0x01; - // STUN message length: 0 (header-only) - // (implicit in initialization) + // STUN message length: 8 (header and 32-bit FINGERPRINT) + buf_y[2] = 0x00; buf_y[3] = 0x08; + // STUN "magic cookie" 0x2112A442 in network byte order buf_y[4] = 0x21; buf_y[5] = 0x12; buf_y[6] = 0xa4; buf_y[7] = 0x42; @@ -1462,7 +1489,10 @@ _stun_send_request(u3_ames* sam_u) // STUN "transaction id" memcpy(buf_y + 8, sam_u->sun_u.tid_y, 12); - uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 20); + // FINGERPRINT + buf_y = _stun_add_fingerprint(buf_y, 20); + + uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, 28); u3_stun_send* snd_u = c3_calloc(sizeof(*snd_u)); snd_u->sam_u = sam_u; snd_u->hun_y = buf_y; @@ -1623,15 +1653,85 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) } } } +static c3_o +_stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) +{ + c3_w i, header, len, index; + c3_y finger[4]; + c3_o stop = c3n; + i = 0; + header = 20; + + if (buf_len < 28) { + return c3n; + } + else { + len = buf_len - header + 1; + // search for FINGERPRINT attribute type 0x8028 + c3_o found_attr = c3n; + while (len-- && stop == c3n) { + if (len < 8) { + found_attr = c3n; + stop = c3y; + } + else if (buf_y[header + i] == 0x80 && buf_y[header + i + 1] == 0x28 && + buf_y[header + i + 2] == 0x00 && buf_y[header + i + 3] == 0x04) { + found_attr = c3y; + stop = c3y; + index = header + i + 4; + } + else { + i = i + 1; + } + } + if (found_attr == c3n) { + return c3n; + } + else { + finger[0] = buf_y[index]; finger[1] = buf_y[index + 1]; + finger[2] = buf_y[index + 2]; finger[3] = buf_y[index + 3]; + + c3_w fingerprint = _ames_sift_word(finger); + c3_w crc = htonl(crc32b(buf_y, index - 4) ^ 0x5354554e); + + return fingerprint == crc; + } + } +} + +static c3_y* +_stun_add_fingerprint(c3_y *message, c3_w index) +{ + // Compute FINGERPRINT value as CRC-32 of the STUN message + // up to (but excluding) the FINGERPRINT attribute itself, + // XOR'ed with the 32-bit value 0x5354554e + c3_w crc = htonl(crc32b(message, index) ^ 0x5354554e); + + // STUN attribute type: "FINGERPRINT" + message[index] = 0x80; message[index + 1] = 0x28; + // STUN attribute length: 4 bytes + message[index + 2] = 0x00; message[index + 3] = 0x04; + // FINGERPRINT dummy value XX needed? see https://datatracker.ietf.org/doc/html/rfc5389#section-15.5 + message[index + 4] = 0xAB; message[index + 5] = 0xCD; + message[index + 6] = 0xCD; message[index + 7] = 0xAB; + + memcpy(message + index + 4, &crc, 4); + + return message; +} static c3_o _stun_is_our_response(c3_y* buf_y, c3_y tid_y[12], c3_w buf_len) { c3_w cookie = htonl(0x2112A442); - return !(buf_len == 32 && + + // Expects at least: + // STUN header, 12 byte XOR-MAPPED-ADDRESS and 8 byte FINGERPRINT + return !(buf_len == 40 && buf_y[0] == 0x01 && buf_y[1] == 0x01 && memcmp(&cookie, buf_y + 4, 4) == 0 && - memcmp(tid_y, buf_y + 8, 12) == 0 + memcmp(tid_y, buf_y + 8, 12) == 0 && + _stun_has_fingerprint(buf_y, buf_len) ); } @@ -1640,9 +1740,12 @@ _stun_is_request(c3_y* buf_y, c3_w buf_len) { c3_w cookie = htonl(0x2112A442); - return !(buf_len >= 20 && // at least the STUN header + // Expects at least: + // STUN header and 8 byte FINGERPRINT + return !(buf_len >= 28 && buf_y[0] == 0x0 && buf_y[1] == 0x01 && - memcmp(&cookie, buf_y + 4, 4) == 0 + memcmp(&cookie, buf_y + 4, 4) == 0 && + _stun_has_fingerprint(buf_y, buf_len) ); } From 5af451b4adea1910f31ac1fd25b2b0147bdf4d2d Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 20 Nov 2023 12:17:42 +0100 Subject: [PATCH 40/53] stun: search for xor-mapped-address attribute --- pkg/vere/io/ames.c | 135 +++++++++++++++++++++++++++++---------------- 1 file changed, 87 insertions(+), 48 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index c2ac755c9d..172410bc4d 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1212,6 +1212,7 @@ static void _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i); static void _stun_on_failure(u3_ames* sam_u); static void _stun_start(u3_ames* sam_u, c3_o fail); static c3_y* _stun_add_fingerprint(c3_y *message, c3_w index); +static c3_w _stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len); static c3_d _stun_time_gap(struct timeval start) @@ -1362,57 +1363,63 @@ static void _stun_on_request(u3_ames *sam_u, c3_y* buf_r, } static void -_stun_on_response(u3_ames* sam_u, c3_y* buf_y) +_stun_on_response(u3_ames* sam_u, c3_y* buf_y, c3_w buf_len) { u3_stun_state old_y = sam_u->sun_u.sat_y; c3_w cookie = 0x2112A442; // XX check attribute tags (see RFC) - c3_w ip_addr_xor = _ames_sift_word(buf_y + 28); - c3_s port_xor = _ames_sift_short(buf_y + 26); - // new lane - u3_lane lan_u; - lan_u.por_s = ntohs(htons(port_xor) ^ cookie >> 16); - lan_u.pip_w = ntohl(htonl(ip_addr_xor) ^ cookie); + c3_w xor_index = _stun_find_xor_mapped_address(buf_y, buf_len); - u3_noun wir = u3nc(c3__ames, u3_nul); + // Ignore STUN responses that dont' have the XOR-MAPPED-ADDRESS attribute + if (xor_index != 0) { + c3_w ip_addr_xor = _ames_sift_word(buf_y + xor_index + 2); + c3_s port_xor = _ames_sift_short(buf_y + xor_index); - if (sam_u->sun_u.wok_o == c3n) { - // stop %ping app - u3_noun cad = u3nt(c3__stun, c3__stop, u3_nul); - u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); - u3_auto_plan(&sam_u->car_u, ovo_u); - sam_u->sun_u.wok_o = c3y; - } - else 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) { - // IP:PORT changed - u3_noun cad = u3nt(c3__stun, c3__once, u3_nul); - u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); - u3_auto_plan(&sam_u->car_u, ovo_u); - } - else { - u3z(wir); - } - sam_u->sun_u.sef_u = lan_u; + // new lane + u3_lane lan_u; + lan_u.por_s = ntohs(htons(port_xor) ^ cookie >> 16); + lan_u.pip_w = ntohl(htonl(ip_addr_xor) ^ cookie); - switch ( sam_u->sun_u.sat_y ) { - case STUN_OFF: break; // ignore; stray response - case STUN_KEEPALIVE: break; // ignore; duplicate response - case STUN_TRYING: { - sam_u->sun_u.sat_y = STUN_KEEPALIVE; - c3_y buf_y[12] = {0}; - c3_i sas_i = uv_random(NULL, NULL, buf_y, 12, 0, NULL); - if (sas_i != 0) { - u3l_log("stun: can't STUN uv_random fail: %s", uv_strerror(sas_i)); - _stun_on_lost(sam_u); - } - else { - memcpy(sam_u->sun_u.tid_y, buf_y, 12); - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); - } - } break; - default: assert("programmer error"); + u3_noun wir = u3nc(c3__ames, u3_nul); + + if (sam_u->sun_u.wok_o == c3n) { + // stop %ping app + u3_noun cad = u3nt(c3__stun, c3__stop, u3_nul); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + sam_u->sun_u.wok_o = c3y; + } + else 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) { + // IP:PORT changed + u3_noun cad = u3nt(c3__stun, c3__once, u3_nul); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + } + else { + u3z(wir); + } + sam_u->sun_u.sef_u = lan_u; + + switch ( sam_u->sun_u.sat_y ) { + case STUN_OFF: break; // ignore; stray response + case STUN_KEEPALIVE: break; // ignore; duplicate response + case STUN_TRYING: { + sam_u->sun_u.sat_y = STUN_KEEPALIVE; + c3_y buf_y[12] = {0}; + c3_i sas_i = uv_random(NULL, NULL, buf_y, 12, 0, NULL); + if (sas_i != 0) { + u3l_log("stun: can't STUN uv_random fail: %s", uv_strerror(sas_i)); + _stun_on_lost(sam_u); + } + else { + memcpy(sam_u->sun_u.tid_y, buf_y, 12); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); + } + } break; + default: assert("programmer error"); + } } } @@ -1653,6 +1660,40 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) } } } + +static c3_w +_stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len) +{ + c3_w i, header, len, index; + c3_y finger[4]; + c3_o stop = c3n; + i = 0; + header = 20; + index = 0; + + if (buf_len < 40) { // At least STUN header, XOR-MAPPED-ADDRESS & FINGERPRINT + return c3n; + } + else { + len = buf_len - header + 1; + // search for XOR-MAPPED-ADDRESS attribute type 0x0020 + while (len-- && stop == c3n) { + if (len < 8) { + stop = c3y; + } + else if (buf_y[header + i] == 0x00 && buf_y[header + i + 1] == 0x20 && + buf_y[header + i + 2] == 0x00 && buf_y[header + i + 3] == 0x08) { + stop = c3y; + index = header + i + 6; // Skip reserved byte and IPv4 family + } + else { + i = i + 1; + } + } + return index; + } +} + static c3_o _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) { @@ -1660,6 +1701,7 @@ _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) c3_y finger[4]; c3_o stop = c3n; i = 0; + index = 0; header = 20; if (buf_len < 28) { @@ -1668,15 +1710,12 @@ _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) else { len = buf_len - header + 1; // search for FINGERPRINT attribute type 0x8028 - c3_o found_attr = c3n; while (len-- && stop == c3n) { if (len < 8) { - found_attr = c3n; stop = c3y; } else if (buf_y[header + i] == 0x80 && buf_y[header + i + 1] == 0x28 && buf_y[header + i + 2] == 0x00 && buf_y[header + i + 3] == 0x04) { - found_attr = c3y; stop = c3y; index = header + i + 4; } @@ -1684,7 +1723,7 @@ _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) i = i + 1; } } - if (found_attr == c3n) { + if (index == 0) { return c3n; } else { @@ -2672,7 +2711,7 @@ _ames_recv_cb(uv_udp_t* wax_u, } else if (_stun_is_our_response((c3_y*)buf_u->base, sam_u->sun_u.tid_y, nrd_i) == c3y) { - _stun_on_response(sam_u, (c3_y*)buf_u->base); + _stun_on_response(sam_u, (c3_y*)buf_u->base, nrd_i); c3_free(buf_u->base); } else { u3_ames* sam_u = wax_u->data; From a6569f101c905df2628ddd3bd326d17463a576f6 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 20 Nov 2023 12:41:59 +0100 Subject: [PATCH 41/53] stun: refactor stun attribute parser --- pkg/vere/io/ames.c | 84 +++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 172410bc4d..071b1e9274 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1662,71 +1662,71 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) } static c3_w -_stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len) +_stun_find_attribute(c3_y* buf_y, c3_w len, + c3_y atr[2], c3_y atr_len[2], + c3_w min_len) { - c3_w i, header, len, index; - c3_y finger[4]; + c3_w i, header, index, cur; + c3_o stop = c3n; i = 0; header = 20; index = 0; + cur = 0; - if (buf_len < 40) { // At least STUN header, XOR-MAPPED-ADDRESS & FINGERPRINT - return c3n; + while (len-- && stop == c3n) { + cur = header + i; + if (len < min_len) { + stop = c3y; + } + else if (buf_y[cur] == atr[0] && buf_y[cur + 1] == atr[1]&& + buf_y[cur + 2] == atr_len[0] && buf_y[cur + 3] == atr_len[1] ) { + stop = c3y; + index = cur; + } + else { + i = i + 1; + } + } + return index; +} + +static c3_w +_stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len) +{ + c3_y xor_buf[2]; xor_buf[0]= 0x00; xor_buf[1]= 0x20; + c3_y atr_len[2]; atr_len[0]= 0x00; atr_len[1]= 0x08; + + if (buf_len < 40) { // At least STUN header, XOR-MAPPED-ADDRESS & FINGERPRINT + return 0; } else { - len = buf_len - header + 1; - // search for XOR-MAPPED-ADDRESS attribute type 0x0020 - while (len-- && stop == c3n) { - if (len < 8) { - stop = c3y; - } - else if (buf_y[header + i] == 0x00 && buf_y[header + i + 1] == 0x20 && - buf_y[header + i + 2] == 0x00 && buf_y[header + i + 3] == 0x08) { - stop = c3y; - index = header + i + 6; // Skip reserved byte and IPv4 family - } - else { - i = i + 1; - } - } - return index; + c3_w len = buf_len - 20 + 1; + c3_w index = _stun_find_attribute(buf_y, len, xor_buf, atr_len, 9); + // If non-zero, skip attribute type, length, reserved byte and IP family + return (index == 0) ? 0 : index + 6; } } static c3_o _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) { - c3_w i, header, len, index; c3_y finger[4]; - c3_o stop = c3n; - i = 0; - index = 0; - header = 20; - if (buf_len < 28) { + c3_y finger_buf[2]; finger_buf[0]= 0x80; finger_buf[0]= 0x28; + c3_y atr_len[2]; atr_len[0]= 0x00; atr_len[0]= 0x04; + + if (buf_len < 28) { // At least STUN header and FINGERPRINT return c3n; } else { - len = buf_len - header + 1; - // search for FINGERPRINT attribute type 0x8028 - while (len-- && stop == c3n) { - if (len < 8) { - stop = c3y; - } - else if (buf_y[header + i] == 0x80 && buf_y[header + i + 1] == 0x28 && - buf_y[header + i + 2] == 0x00 && buf_y[header + i + 3] == 0x04) { - stop = c3y; - index = header + i + 4; - } - else { - i = i + 1; - } - } + c3_w len = buf_len - 20 + 1; + c3_w index = _stun_find_attribute(buf_y, len, finger_buf, atr_len, 8); if (index == 0) { return c3n; } else { + index += 4; // Skip attribute type and length finger[0] = buf_y[index]; finger[1] = buf_y[index + 1]; finger[2] = buf_y[index + 2]; finger[3] = buf_y[index + 3]; From 71bb1ec03ed557d46bef3c502ddc120b4a0564a2 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 20 Nov 2023 14:18:05 +0100 Subject: [PATCH 42/53] stun: fix error --- pkg/vere/io/ames.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 071b1e9274..9294e84d8c 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1713,8 +1713,8 @@ _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) { c3_y finger[4]; - c3_y finger_buf[2]; finger_buf[0]= 0x80; finger_buf[0]= 0x28; - c3_y atr_len[2]; atr_len[0]= 0x00; atr_len[0]= 0x04; + c3_y finger_buf[2]; finger_buf[0]= 0x80; finger_buf[1]= 0x28; + c3_y atr_len[2]; atr_len[0]= 0x00; atr_len[1]= 0x04; if (buf_len < 28) { // At least STUN header and FINGERPRINT return c3n; From 6c174c033fa250289c164d26b36ea71db93be13b Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 20 Nov 2023 14:54:40 +0100 Subject: [PATCH 43/53] stun: remove custom crc32 function --- pkg/vere/io/ames.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 9294e84d8c..81205fb73d 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -5,6 +5,8 @@ #include "noun.h" #include "ur.h" +#include "zlib.h" + #define FINE_PAGE 4096 // packets per page #define FINE_FRAG 1024 // bytes per fragment packet #define FINE_PATH_MAX 384 // longest allowed scry path @@ -1446,28 +1448,6 @@ _stun_on_lost(u3_ames* sam_u) uv_timer_start(&sam_u->sun_u.dns_u, _stun_reset, 5*1000, 0); } -/* Adapted from: -https://web.archive.org/web/20190108202303/http://www.hackersdelight.org/hdcodetxt/crc.c.txt -*/ -static c3_w crc32b(c3_y *message, c3_w len) { - c3_w i, j; - c3_y byte; - c3_w crc, mask; - - i = 0; - crc = 0xFFFFFFFF; - while (len--) { - byte = message[i]; // Get next byte. - crc = crc ^ byte; - for (j = 0; j < 8; j++) { // Do eight times. - mask = -(crc & 1); - crc = (crc >> 1) ^ (0xEDB88320 & mask); - } - i = i + 1; - } - return ~crc; -} - static void _stun_send_request(u3_ames* sam_u) { @@ -1731,7 +1711,7 @@ _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) finger[2] = buf_y[index + 2]; finger[3] = buf_y[index + 3]; c3_w fingerprint = _ames_sift_word(finger); - c3_w crc = htonl(crc32b(buf_y, index - 4) ^ 0x5354554e); + c3_w crc = htonl(crc32(0, buf_y, index - 4) ^ 0x5354554e); return fingerprint == crc; } @@ -1744,7 +1724,7 @@ _stun_add_fingerprint(c3_y *message, c3_w index) // Compute FINGERPRINT value as CRC-32 of the STUN message // up to (but excluding) the FINGERPRINT attribute itself, // XOR'ed with the 32-bit value 0x5354554e - c3_w crc = htonl(crc32b(message, index) ^ 0x5354554e); + c3_w crc = htonl(crc32(0, message, index) ^ 0x5354554e); // STUN attribute type: "FINGERPRINT" message[index] = 0x80; message[index + 1] = 0x28; From 7d7f4d236b4d6de4d9e0bd61d7b3956b63ea3984 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 20 Nov 2023 14:59:35 +0100 Subject: [PATCH 44/53] stun: use required initial value for the crc --- pkg/vere/io/ames.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 81205fb73d..3c70c5bea0 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1711,7 +1711,8 @@ _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) finger[2] = buf_y[index + 2]; finger[3] = buf_y[index + 3]; c3_w fingerprint = _ames_sift_word(finger); - c3_w crc = htonl(crc32(0, buf_y, index - 4) ^ 0x5354554e); + c3_w init = crc32(0L, Z_NULL, 0); + c3_w crc = htonl(crc32(init, buf_y, index - 4) ^ 0x5354554e); return fingerprint == crc; } @@ -1724,7 +1725,8 @@ _stun_add_fingerprint(c3_y *message, c3_w index) // Compute FINGERPRINT value as CRC-32 of the STUN message // up to (but excluding) the FINGERPRINT attribute itself, // XOR'ed with the 32-bit value 0x5354554e - c3_w crc = htonl(crc32(0, message, index) ^ 0x5354554e); + c3_w init = crc32(0L, Z_NULL, 0); + c3_w crc = htonl(crc32(init, message, index) ^ 0x5354554e); // STUN attribute type: "FINGERPRINT" message[index] = 0x80; message[index + 1] = 0x28; From 2a3ca0edc848fb7e03371514e6ebf12a4363aca1 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Tue, 21 Nov 2023 10:29:30 +0100 Subject: [PATCH 45/53] stun: add ship and lane to %arvo task --- pkg/vere/io/ames.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 3c70c5bea0..3e4b5a08e8 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1384,18 +1384,19 @@ _stun_on_response(u3_ames* sam_u, c3_y* buf_y, c3_w buf_len) lan_u.pip_w = ntohl(htonl(ip_addr_xor) ^ cookie); u3_noun wir = u3nc(c3__ames, u3_nul); - if (sam_u->sun_u.wok_o == c3n) { // stop %ping app - u3_noun cad = u3nt(c3__stun, c3__stop, 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_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); u3_auto_plan(&sam_u->car_u, ovo_u); sam_u->sun_u.wok_o = c3y; } else 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) { - // IP:PORT changed - u3_noun cad = u3nt(c3__stun, c3__once, u3_nul); + // lane changed + u3_noun cad = u3nq(c3__stun, c3__once, sam_u->sun_u.dad_y, + u3nc(c3n, u3_ames_encode_lane(lan_u))); u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); u3_auto_plan(&sam_u->car_u, ovo_u); } @@ -1431,7 +1432,8 @@ _stun_on_failure(u3_ames* sam_u) // only inject event into arvo to %kick ping app on first failure if (sam_u->sun_u.wok_o == c3y) { u3_noun wir = u3nc(c3__ames, u3_nul); - u3_noun cad = u3nt(c3__stun, c3__fail, 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_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); u3_auto_plan(&sam_u->car_u, ovo_u); } From 8de9d8d8fffa11eb9588d00386cf7838a93fd4bd Mon Sep 17 00:00:00 2001 From: pkova Date: Thu, 30 Nov 2023 18:57:54 +0200 Subject: [PATCH 46/53] stun: misc fixes --- pkg/vere/io/ames.c | 125 +++++++++++++++++---------------------------- 1 file changed, 46 insertions(+), 79 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 3e4b5a08e8..af3efeb52e 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -7,6 +7,8 @@ #include "zlib.h" +#include + #define FINE_PAGE 4096 // packets per page #define FINE_FRAG 1024 // bytes per fragment packet #define FINE_PATH_MAX 384 // longest allowed scry path @@ -1316,9 +1318,9 @@ _stun_send_response_cb(uv_udp_send_t *rep_u, c3_i sas_i) u3_stun_send* snd_u = (u3_stun_send*)rep_u; if ( sas_i != 0 ) { u3l_log("stun: _stun_send_response_cb fail_sync: %s", uv_strerror(sas_i)); - c3_free(snd_u->hun_y); - c3_free(snd_u); } + c3_free(snd_u->hun_y); + c3_free(snd_u); } static void _stun_on_request(u3_ames *sam_u, c3_y* buf_r, @@ -1410,14 +1412,11 @@ _stun_on_response(u3_ames* sam_u, c3_y* buf_y, c3_w buf_len) case STUN_KEEPALIVE: break; // ignore; duplicate response case STUN_TRYING: { sam_u->sun_u.sat_y = STUN_KEEPALIVE; - c3_y buf_y[12] = {0}; - c3_i sas_i = uv_random(NULL, NULL, buf_y, 12, 0, NULL); - if (sas_i != 0) { - u3l_log("stun: can't STUN uv_random fail: %s", uv_strerror(sas_i)); + if ( ent_getentropy(sam_u->sun_u.tid_y, 12) ) { + u3l_log("stun: getentropy fail: %s", strerror(errno)); _stun_on_lost(sam_u); } else { - memcpy(sam_u->sun_u.tid_y, buf_y, 12); uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); } } break; @@ -1599,15 +1598,10 @@ _stun_czar(u3_ames* sam_u, c3_d tim_d) static void _stun_start(u3_ames* sam_u, c3_o fail) { - c3_y buf_y[12] = {0}; - // XX uv_random may block indefinitely when not enough entropy is available. - c3_i sas_i = uv_random(NULL, NULL, buf_y, 12, 0, NULL); - - if (sas_i != 0) { - u3l_log("stun: can't STUN uv_random fail: %s", uv_strerror(sas_i)); + if ( ent_getentropy(sam_u->sun_u.tid_y, 12) ) { + u3l_log("stun: getentropy fail: %s", strerror(errno)); _stun_on_lost(sam_u); } else { - memcpy(sam_u->sun_u.tid_y, buf_y, 12); _stun_czar(sam_u, (fail == c3n) ? 500 : 39500); } } @@ -1621,7 +1615,7 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) c3_y imp_y = sam_u->sun_u.dad_y; sam_u->sun_u.lan_u.por_s = _ames_czar_port(imp_y); - if (!sam_u->sun_u.dns_c) { + if ( !sam_u->sun_u.dns_c ) { sam_u->sun_u.dns_c = _ames_czar_dns(imp_y, sam_u->dns_c); } @@ -1634,7 +1628,8 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) hints.ai_family = AF_INET; // only IPv4 addresses if (0 != (sas_i = uv_getaddrinfo(u3L, adr_u, _stun_czar_cb, - sam_u->sun_u.dns_c, 0, &hints))) { + sam_u->sun_u.dns_c, 0, &hints))) + { u3l_log("stun: uv_getaddrinfo failed %s %s", uv_strerror(sas_i), sam_u->sun_u.dns_c); _ames_czar_gone(sam_u, time(0), sam_u->sun_u.dad_y, sam_u->dns_c); _stun_on_lost(sam_u); @@ -1643,80 +1638,46 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) } } -static c3_w -_stun_find_attribute(c3_y* buf_y, c3_w len, - c3_y atr[2], c3_y atr_len[2], - c3_w min_len) -{ - c3_w i, header, index, cur; - - c3_o stop = c3n; - i = 0; - header = 20; - index = 0; - cur = 0; - - while (len-- && stop == c3n) { - cur = header + i; - if (len < min_len) { - stop = c3y; - } - else if (buf_y[cur] == atr[0] && buf_y[cur + 1] == atr[1]&& - buf_y[cur + 2] == atr_len[0] && buf_y[cur + 3] == atr_len[1] ) { - stop = c3y; - index = cur; - } - else { - i = i + 1; - } - } - return index; -} - static c3_w _stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len) { - c3_y xor_buf[2]; xor_buf[0]= 0x00; xor_buf[1]= 0x20; - c3_y atr_len[2]; atr_len[0]= 0x00; atr_len[1]= 0x08; + c3_y xor_y[4] = {0x00, 0x20, 0x00, 0x08}; if (buf_len < 40) { // At least STUN header, XOR-MAPPED-ADDRESS & FINGERPRINT return 0; } else { - c3_w len = buf_len - 20 + 1; - c3_w index = _stun_find_attribute(buf_y, len, xor_buf, atr_len, 9); + c3_y* fin_y = memmem(buf_y + 20, buf_len - 20, xor_y, sizeof(xor_y)); // If non-zero, skip attribute type, length, reserved byte and IP family - return (index == 0) ? 0 : index + 6; + return (fin_y) ? 0 : (c3_w)(fin_y - buf_y) + 6; } } static c3_o _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) { - c3_y finger[4]; - - c3_y finger_buf[2]; finger_buf[0]= 0x80; finger_buf[1]= 0x28; - c3_y atr_len[2]; atr_len[0]= 0x00; atr_len[1]= 0x04; + c3_y ned_y[4] = {0x80, 0x28, 0x00, 0x04}; - if (buf_len < 28) { // At least STUN header and FINGERPRINT + if ( buf_len < 28 ) { // At least STUN header and FINGERPRINT return c3n; } - else { - c3_w len = buf_len - 20 + 1; - c3_w index = _stun_find_attribute(buf_y, len, finger_buf, atr_len, 8); - if (index == 0) { + + { + c3_y* fin_y = memmem(buf_y + 20, buf_len - 20, ned_y, sizeof(ned_y)); + + if ( !fin_y ) { return c3n; } else { - index += 4; // Skip attribute type and length - finger[0] = buf_y[index]; finger[1] = buf_y[index + 1]; - finger[2] = buf_y[index + 2]; finger[3] = buf_y[index + 3]; - c3_w fingerprint = _ames_sift_word(finger); + c3_w len_w = (buf_len - (fin_y - buf_y)); + + // Skip attribute type and length + c3_w fingerprint = _ames_sift_word(fin_y + sizeof(ned_y)); c3_w init = crc32(0L, Z_NULL, 0); - c3_w crc = htonl(crc32(init, buf_y, index - 4) ^ 0x5354554e); + c3_w crc = htonl(crc32(init, buf_y, len_w) ^ 0x5354554e); - return fingerprint == crc; + return fingerprint == crc ? c3y : c3n; } } } @@ -1750,12 +1711,15 @@ _stun_is_our_response(c3_y* buf_y, c3_y tid_y[12], c3_w buf_len) // Expects at least: // STUN header, 12 byte XOR-MAPPED-ADDRESS and 8 byte FINGERPRINT - return !(buf_len == 40 && - buf_y[0] == 0x01 && buf_y[1] == 0x01 && - memcmp(&cookie, buf_y + 4, 4) == 0 && - memcmp(tid_y, buf_y + 8, 12) == 0 && - _stun_has_fingerprint(buf_y, buf_len) - ); + if ( (buf_len == 40) && + (buf_y[0] == 0x01 && buf_y[1] == 0x01) && + (memcmp(&cookie, buf_y + 4, 4) == 0) && + (memcmp(tid_y, buf_y + 8, 12) == 0) && + (c3y == _stun_has_fingerprint(buf_y, buf_len)) ) + { + return c3y; + } + return c3n; } static c3_o @@ -1765,12 +1729,14 @@ _stun_is_request(c3_y* buf_y, c3_w buf_len) // Expects at least: // STUN header and 8 byte FINGERPRINT - return !(buf_len >= 28 && - buf_y[0] == 0x0 && buf_y[1] == 0x01 && - memcmp(&cookie, buf_y + 4, 4) == 0 && - _stun_has_fingerprint(buf_y, buf_len) - ); - + if ( (buf_len >= 28) && + (buf_y[0] == 0x0 && buf_y[1] == 0x01) && + (memcmp(&cookie, buf_y + 4, 4) == 0) && + (c3y == _stun_has_fingerprint(buf_y, buf_len)) ) + { + return c3y; + } + return c3n; } static c3_o @@ -2804,7 +2770,8 @@ _ames_ef_turf(u3_ames* sam_u, u3_noun tuf) } // XX invalidate sam_u->imp_w &c ? - // also invalidate sun_u.dns_c + c3_free(sam_u->sun_u.dns_c); + sam_u->sun_u.dns_c = 0; u3z(tuf); } From 9bbd71c57cc062a1724bebe178001dda375ef131 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Fri, 1 Dec 2023 12:27:16 +0100 Subject: [PATCH 47/53] stunL fix wrong fingerprint length --- pkg/vere/io/ames.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index af3efeb52e..e8501ace83 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1670,7 +1670,7 @@ _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) } else { - c3_w len_w = (buf_len - (fin_y - buf_y)); + c3_w len_w = buf_len - sizeof(fin_y); // Skip attribute type and length c3_w fingerprint = _ames_sift_word(fin_y + sizeof(ned_y)); From 6f8e718c824e7a9c15b93f474d60fca604918843 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Fri, 1 Dec 2023 13:07:50 +0100 Subject: [PATCH 48/53] stun: check if found attribute is correct ...and if not, keep trying until we go over the whole buffer (Note: the parsde port is wrong) --- pkg/vere/io/ames.c | 61 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index e8501ace83..1d63c55552 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -9,6 +9,8 @@ #include +#include + #define FINE_PAGE 4096 // packets per page #define FINE_FRAG 1024 // bytes per fragment packet #define FINE_PATH_MAX 384 // longest allowed scry path @@ -1647,7 +1649,33 @@ _stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len) return 0; } else { - c3_y* fin_y = memmem(buf_y + 20, buf_len - 20, xor_y, sizeof(xor_y)); + c3_y* fin_y = 0; + c3_w i = 20; // start after the header + c3_w cookie = 0x2112A442; + + while ( fin_y == 0 && i < buf_len ) { + fin_y = memmem(buf_y + i, buf_len - i, xor_y, sizeof(xor_y)); + if ( fin_y != 0 ) { + c3_w cur = (c3_w)(fin_y - buf_y) + 6; + + c3_s port = ntohs(htons(_ames_sift_short(buf_y + cur)) ^ cookie >> 16); // XX wrong + c3_w ip = ntohl(htonl(_ames_sift_word(buf_y + cur + 2)) ^ cookie); + + char ip_str[INET_ADDRSTRLEN]; + + if ( (inet_ntop(AF_INET, &ip, ip_str, INET_ADDRSTRLEN) == NULL) || + port > 65535 ) { + fin_y = 0; + i = buf_len; + } else { + if ( u3o_verbose && 1) { + u3l_log("ip:port %s:%u", ip_str, port); + } + } + } + i += 1; + } + // If non-zero, skip attribute type, length, reserved byte and IP family return (fin_y) ? 0 : (c3_w)(fin_y - buf_y) + 6; } @@ -1657,28 +1685,29 @@ static c3_o _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) { c3_y ned_y[4] = {0x80, 0x28, 0x00, 0x04}; - if ( buf_len < 28 ) { // At least STUN header and FINGERPRINT return c3n; } { - c3_y* fin_y = memmem(buf_y + 20, buf_len - 20, ned_y, sizeof(ned_y)); - - if ( !fin_y ) { - return c3n; + c3_y* fin_y = 0; + c3_w i = 20; // start after the header + c3_o not_found = c3n; + + while ( fin_y == 0 && i < buf_len && not_found == c3n) { + fin_y = memmem(buf_y + i, buf_len - i, ned_y, sizeof(ned_y)); + if ( fin_y != 0 ) { + c3_w len_w = buf_len - sizeof(fin_y); + // Skip attribute type and length + c3_w fingerprint = _ames_sift_word(fin_y + sizeof(ned_y)); + c3_w init = crc32(0L, Z_NULL, 0); + c3_w crc = htonl(crc32(init, buf_y, len_w) ^ 0x5354554e); + not_found = (fingerprint == crc) ? c3y : c3n; + } + i += 1; } - else { - c3_w len_w = buf_len - sizeof(fin_y); - - // Skip attribute type and length - c3_w fingerprint = _ames_sift_word(fin_y + sizeof(ned_y)); - c3_w init = crc32(0L, Z_NULL, 0); - c3_w crc = htonl(crc32(init, buf_y, len_w) ^ 0x5354554e); - - return fingerprint == crc ? c3y : c3n; - } + return not_found; } } From 9578d356738697348f3585b085128fac063d8c4f Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Fri, 1 Dec 2023 14:15:21 +0100 Subject: [PATCH 49/53] stun: fix logging received port --- pkg/vere/io/ames.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 1d63c55552..9817d063ba 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1361,7 +1361,7 @@ static void _stun_on_request(u3_ames *sam_u, c3_y* buf_r, adr_u, _stun_send_response_cb ); - if ( sas_i != 0) { + if ( sas_i != 0 ) { u3l_log("stun: send response fail_sync: %s", uv_strerror(sas_i)); c3_free(buf_y); c3_free(snd_u); @@ -1378,7 +1378,7 @@ _stun_on_response(u3_ames* sam_u, c3_y* buf_y, c3_w buf_len) c3_w xor_index = _stun_find_xor_mapped_address(buf_y, buf_len); // Ignore STUN responses that dont' have the XOR-MAPPED-ADDRESS attribute - if (xor_index != 0) { + if ( xor_index != 0 ) { c3_w ip_addr_xor = _ames_sift_word(buf_y + xor_index + 2); c3_s port_xor = _ames_sift_short(buf_y + xor_index); @@ -1658,18 +1658,17 @@ _stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len) if ( fin_y != 0 ) { c3_w cur = (c3_w)(fin_y - buf_y) + 6; - c3_s port = ntohs(htons(_ames_sift_short(buf_y + cur)) ^ cookie >> 16); // XX wrong + c3_s port = htons(_ames_sift_short(buf_y + cur)) ^ cookie >> 16; c3_w ip = ntohl(htonl(_ames_sift_word(buf_y + cur + 2)) ^ cookie); char ip_str[INET_ADDRSTRLEN]; - if ( (inet_ntop(AF_INET, &ip, ip_str, INET_ADDRSTRLEN) == NULL) || - port > 65535 ) { + if (inet_ntop(AF_INET, &ip, ip_str, INET_ADDRSTRLEN) == NULL) { fin_y = 0; i = buf_len; } else { - if ( u3o_verbose && 1) { - u3l_log("ip:port %s:%u", ip_str, port); + if ( u3o_verbose ) { + u3l_log("stun: hear ip:port %s:%u", ip_str, port); } } } @@ -1677,7 +1676,7 @@ _stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len) } // If non-zero, skip attribute type, length, reserved byte and IP family - return (fin_y) ? 0 : (c3_w)(fin_y - buf_y) + 6; + return ( !fin_y ) ? 0 : (c3_w)(fin_y - buf_y) + 6; } } From 0acaf10aeab82046367fb6e4baa245bf20389bb4 Mon Sep 17 00:00:00 2001 From: pkova Date: Tue, 5 Dec 2023 17:57:39 +0200 Subject: [PATCH 50/53] stun: more fixes from joe --- pkg/vere/io/ames.c | 137 +++++++++++++++++++++------------------------ 1 file changed, 64 insertions(+), 73 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 9817d063ba..cab98dadb3 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1218,7 +1218,7 @@ static void _stun_send_request_cb(uv_udp_send_t *req_u, c3_i sas_i); static void _stun_on_failure(u3_ames* sam_u); static void _stun_start(u3_ames* sam_u, c3_o fail); static c3_y* _stun_add_fingerprint(c3_y *message, c3_w index); -static c3_w _stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len); +static c3_o _stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len, u3_lane* lan_u); static c3_d _stun_time_gap(struct timeval start) @@ -1373,57 +1373,49 @@ _stun_on_response(u3_ames* sam_u, c3_y* buf_y, c3_w buf_len) { u3_stun_state old_y = sam_u->sun_u.sat_y; - c3_w cookie = 0x2112A442; - // XX check attribute tags (see RFC) - c3_w xor_index = _stun_find_xor_mapped_address(buf_y, buf_len); + u3_lane lan_u; // Ignore STUN responses that dont' have the XOR-MAPPED-ADDRESS attribute - if ( xor_index != 0 ) { - c3_w ip_addr_xor = _ames_sift_word(buf_y + xor_index + 2); - c3_s port_xor = _ames_sift_short(buf_y + xor_index); - - // new lane - u3_lane lan_u; - lan_u.por_s = ntohs(htons(port_xor) ^ cookie >> 16); - lan_u.pip_w = ntohl(htonl(ip_addr_xor) ^ cookie); + if ( c3n == _stun_find_xor_mapped_address(buf_y, buf_len, &lan_u) ) { + return; + } + u3_noun wir = u3nc(c3__ames, u3_nul); + if (sam_u->sun_u.wok_o == c3n) { + // stop %ping app + u3_noun cad = u3nq(c3__stun, c3__stop, sam_u->sun_u.dad_y, + u3nc(c3n, u3_ames_encode_lane(lan_u))); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + sam_u->sun_u.wok_o = c3y; + } + else 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 cad = u3nq(c3__stun, c3__once, sam_u->sun_u.dad_y, + u3nc(c3n, u3_ames_encode_lane(lan_u))); + u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); + u3_auto_plan(&sam_u->car_u, ovo_u); + } + else { + u3z(wir); + } + sam_u->sun_u.sef_u = lan_u; - u3_noun wir = u3nc(c3__ames, u3_nul); - if (sam_u->sun_u.wok_o == c3n) { - // stop %ping app - u3_noun cad = u3nq(c3__stun, c3__stop, sam_u->sun_u.dad_y, - u3nc(c3n, u3_ames_encode_lane(lan_u))); - u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); - u3_auto_plan(&sam_u->car_u, ovo_u); - sam_u->sun_u.wok_o = c3y; - } - else 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 cad = u3nq(c3__stun, c3__once, sam_u->sun_u.dad_y, - u3nc(c3n, u3_ames_encode_lane(lan_u))); - u3_ovum *ovo_u = u3_ovum_init(0, c3__ames, wir, cad); - u3_auto_plan(&sam_u->car_u, ovo_u); + switch ( sam_u->sun_u.sat_y ) { + case STUN_OFF: break; // ignore; stray response + case STUN_KEEPALIVE: break; // ignore; duplicate response + case STUN_TRYING: { + sam_u->sun_u.sat_y = STUN_KEEPALIVE; + if ( ent_getentropy(sam_u->sun_u.tid_y, 12) ) { + u3l_log("stun: getentropy fail: %s", strerror(errno)); + _stun_on_lost(sam_u); } else { - u3z(wir); - } - sam_u->sun_u.sef_u = lan_u; - - switch ( sam_u->sun_u.sat_y ) { - case STUN_OFF: break; // ignore; stray response - case STUN_KEEPALIVE: break; // ignore; duplicate response - case STUN_TRYING: { - sam_u->sun_u.sat_y = STUN_KEEPALIVE; - if ( ent_getentropy(sam_u->sun_u.tid_y, 12) ) { - u3l_log("stun: getentropy fail: %s", strerror(errno)); - _stun_on_lost(sam_u); - } - else { - uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); - } - } break; - default: assert("programmer error"); + uv_timer_start(&sam_u->sun_u.tim_u, _stun_timer_cb, 25*1000, 0); } + } break; + default: assert("programmer error"); } } @@ -1640,44 +1632,43 @@ _stun_resolve_dns_cb(uv_timer_t* tim_u) } } -static c3_w -_stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len) +static c3_o +_stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len, u3_lane* lan_u) { c3_y xor_y[4] = {0x00, 0x20, 0x00, 0x08}; + c3_w cookie = 0x2112A442; if (buf_len < 40) { // At least STUN header, XOR-MAPPED-ADDRESS & FINGERPRINT - return 0; + return c3n; } - else { - c3_y* fin_y = 0; - c3_w i = 20; // start after the header - c3_w cookie = 0x2112A442; - while ( fin_y == 0 && i < buf_len ) { - fin_y = memmem(buf_y + i, buf_len - i, xor_y, sizeof(xor_y)); - if ( fin_y != 0 ) { - c3_w cur = (c3_w)(fin_y - buf_y) + 6; + // start after header + for (c3_w i = 20; i < buf_len; i++) { + c3_y* fin_y = memmem(buf_y + i, buf_len - i, xor_y, sizeof(xor_y)); + if ( fin_y != 0 ) { + c3_w cur = (c3_w)(fin_y - buf_y) + sizeof(xor_y); - c3_s port = htons(_ames_sift_short(buf_y + cur)) ^ cookie >> 16; - c3_w ip = ntohl(htonl(_ames_sift_word(buf_y + cur + 2)) ^ cookie); + if ( (buf_y[cur] != 0x0) && (buf_y[cur+1] != 0x1) ) { + return c3n; + } - char ip_str[INET_ADDRSTRLEN]; + cur += 2; - if (inet_ntop(AF_INET, &ip, ip_str, INET_ADDRSTRLEN) == NULL) { - fin_y = 0; - i = buf_len; - } else { - if ( u3o_verbose ) { - u3l_log("stun: hear ip:port %s:%u", ip_str, port); - } - } + c3_s port = ntohs(htons(_ames_sift_short(buf_y + cur)) ^ cookie >> 16); + c3_w ip = ntohl(htonl(_ames_sift_word(buf_y + cur + 2)) ^ cookie); + + lan_u->por_s = port; + lan_u->pip_w = ip; + + if ( u3o_verbose ) { + c3_c ip_str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &ip, ip_str, INET_ADDRSTRLEN); + u3l_log("stun: hear ip:port %s:%u", ip_str, port); } - i += 1; + return c3y; } - - // If non-zero, skip attribute type, length, reserved byte and IP family - return ( !fin_y ) ? 0 : (c3_w)(fin_y - buf_y) + 6; } + return c3n; } static c3_o @@ -1696,7 +1687,7 @@ _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) while ( fin_y == 0 && i < buf_len && not_found == c3n) { fin_y = memmem(buf_y + i, buf_len - i, ned_y, sizeof(ned_y)); if ( fin_y != 0 ) { - c3_w len_w = buf_len - sizeof(fin_y); + c3_w len_w = fin_y - buf_y; // Skip attribute type and length c3_w fingerprint = _ames_sift_word(fin_y + sizeof(ned_y)); c3_w init = crc32(0L, Z_NULL, 0); From c55b9d223e04e421ff873cbe48fb5631f40b04ba Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 6 Dec 2023 13:27:36 +0100 Subject: [PATCH 51/53] stun: fix hear ip:port log message --- pkg/vere/io/ames.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index cab98dadb3..7da4e4c60f 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1660,7 +1660,7 @@ _stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len, u3_lane* lan_u) lan_u->por_s = port; lan_u->pip_w = ip; - if ( u3o_verbose ) { + if ( u3C.wag_w & u3o_verbose ) { c3_c ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &ip, ip_str, INET_ADDRSTRLEN); u3l_log("stun: hear ip:port %s:%u", ip_str, port); From 2901a1823000008b198b013823cd9a79d17d1327 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 6 Dec 2023 13:31:17 +0100 Subject: [PATCH 52/53] stun: log port in network byte order --- pkg/vere/io/ames.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index 7da4e4c60f..eaa9dffef7 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1654,10 +1654,10 @@ _stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len, u3_lane* lan_u) cur += 2; - c3_s port = ntohs(htons(_ames_sift_short(buf_y + cur)) ^ cookie >> 16); + c3_s port = htons(_ames_sift_short(buf_y + cur)) ^ cookie >> 16; c3_w ip = ntohl(htonl(_ames_sift_word(buf_y + cur + 2)) ^ cookie); - lan_u->por_s = port; + lan_u->por_s = ntohs(port); lan_u->pip_w = ip; if ( u3C.wag_w & u3o_verbose ) { From c343fc83bed5a57d6a01e6c2f850d8eaa1e52768 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Wed, 6 Dec 2023 14:03:44 +0100 Subject: [PATCH 53/53] stun: stop when finding first attribute --- pkg/vere/io/ames.c | 64 +++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/pkg/vere/io/ames.c b/pkg/vere/io/ames.c index d74e8d3159..3c8cd803c5 100644 --- a/pkg/vere/io/ames.c +++ b/pkg/vere/io/ames.c @@ -1652,31 +1652,30 @@ _stun_find_xor_mapped_address(c3_y* buf_y, c3_w buf_len, u3_lane* lan_u) return c3n; } - // start after header - for (c3_w i = 20; i < buf_len; i++) { - c3_y* fin_y = memmem(buf_y + i, buf_len - i, xor_y, sizeof(xor_y)); - if ( fin_y != 0 ) { - c3_w cur = (c3_w)(fin_y - buf_y) + sizeof(xor_y); + c3_w i = 20; // start after header - if ( (buf_y[cur] != 0x0) && (buf_y[cur+1] != 0x1) ) { - return c3n; - } + c3_y* fin_y = memmem(buf_y + i, buf_len - i, xor_y, sizeof(xor_y)); + if ( fin_y != 0 ) { + c3_w cur = (c3_w)(fin_y - buf_y) + sizeof(xor_y); - cur += 2; + if ( (buf_y[cur] != 0x0) && (buf_y[cur+1] != 0x1) ) { + return c3n; + } - c3_s port = htons(_ames_sift_short(buf_y + cur)) ^ cookie >> 16; - c3_w ip = ntohl(htonl(_ames_sift_word(buf_y + cur + 2)) ^ cookie); + cur += 2; - lan_u->por_s = ntohs(port); - lan_u->pip_w = ip; + c3_s port = htons(_ames_sift_short(buf_y + cur)) ^ cookie >> 16; + c3_w ip = ntohl(htonl(_ames_sift_word(buf_y + cur + 2)) ^ cookie); - if ( u3C.wag_w & u3o_verbose ) { - c3_c ip_str[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &ip, ip_str, INET_ADDRSTRLEN); - u3l_log("stun: hear ip:port %s:%u", ip_str, port); - } - return c3y; + lan_u->por_s = ntohs(port); + lan_u->pip_w = ip; + + if ( u3C.wag_w & u3o_verbose ) { + c3_c ip_str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &ip, ip_str, INET_ADDRSTRLEN); + u3l_log("stun: hear ip:port %s:%u", ip_str, port); } + return c3y; } return c3n; } @@ -1692,22 +1691,20 @@ _stun_has_fingerprint(c3_y* buf_y, c3_w buf_len) { c3_y* fin_y = 0; c3_w i = 20; // start after the header - c3_o not_found = c3n; - - while ( fin_y == 0 && i < buf_len && not_found == c3n) { - fin_y = memmem(buf_y + i, buf_len - i, ned_y, sizeof(ned_y)); - if ( fin_y != 0 ) { - c3_w len_w = fin_y - buf_y; - // Skip attribute type and length - c3_w fingerprint = _ames_sift_word(fin_y + sizeof(ned_y)); - c3_w init = crc32(0L, Z_NULL, 0); - c3_w crc = htonl(crc32(init, buf_y, len_w) ^ 0x5354554e); - not_found = (fingerprint == crc) ? c3y : c3n; + + fin_y = memmem(buf_y + i, buf_len - i, ned_y, sizeof(ned_y)); + if ( fin_y != 0 ) { + c3_w len_w = fin_y - buf_y; + // Skip attribute type and length + c3_w fingerprint = _ames_sift_word(fin_y + sizeof(ned_y)); + c3_w init = crc32(0L, Z_NULL, 0); + c3_w crc = htonl(crc32(init, buf_y, len_w) ^ 0x5354554e); + if ((fingerprint == crc) && (fin_y - buf_y + 8) == buf_len) { + return c3y; } - i += 1; } - return not_found; + return c3n; } } @@ -1724,9 +1721,6 @@ _stun_add_fingerprint(c3_y *message, c3_w index) message[index] = 0x80; message[index + 1] = 0x28; // STUN attribute length: 4 bytes message[index + 2] = 0x00; message[index + 3] = 0x04; - // FINGERPRINT dummy value XX needed? see https://datatracker.ietf.org/doc/html/rfc5389#section-15.5 - message[index + 4] = 0xAB; message[index + 5] = 0xCD; - message[index + 6] = 0xCD; message[index + 7] = 0xAB; memcpy(message + index + 4, &crc, 4);