diff --git a/src/transport_layer/auto_socket.c b/src/transport_layer/auto_socket.c index ebb509db..49417b1d 100644 --- a/src/transport_layer/auto_socket.c +++ b/src/transport_layer/auto_socket.c @@ -373,8 +373,6 @@ static struct stcp_server* create_iface_tcp_socket(struct AUTO_SOCKET* as, uint3 struct stcp_link_config scfg; memset(&scfg, 0, sizeof(scfg)); - scfg.ua = inst->ua; - scfg.my_keys = &inst->my_keys; scfg.inst = inst; scfg.listen_family = family; diff --git a/src/transport_layer/etcp_connections.c b/src/transport_layer/etcp_connections.c index b68c4507..f619581e 100644 --- a/src/transport_layer/etcp_connections.c +++ b/src/transport_layer/etcp_connections.c @@ -56,32 +56,18 @@ void tcp_server_on_link(struct stcp_link *link, struct ETCP_SOCKET *tcp_sock) { DEBUG_INFO(DEBUG_CATEGORY_ETCP, "tcp_server_on_link: %s conn=%p peer=0x%016llx pubkey=%016llx", conn ? "existing" : "NEW", (void*)conn, (unsigned long long)node_id, *(const uint64_t*)pubkey); - /* Синхронизация got_initial_pkt и session_id: если грязный/другой → сбросить */ - { - uint8_t client_gop = stcp_link_get_peer_got_initial_pkt(link); - uint32_t client_sid = stcp_link_get_peer_session_id(link); - DEBUG_INFO(DEBUG_CATEGORY_ETCP, "tcp_server_on_link: server_gop=%d server_sid=%08x client_gop=%d client_sid=%08x conn=%p", - conn ? conn->got_initial_pkt : 0, conn ? conn->session_id : 0, - client_gop, client_sid, (void*)conn); - if (conn) { - if (conn->got_initial_pkt == 1 && client_gop == 0) { - DEBUG_INFO(DEBUG_CATEGORY_ETCP, "tcp_server_on_link: server dirty (gop=1) client clean (gop=0) → reinit"); - etcp_conn_reinit(conn, "stcp client clean"); - } - if (conn->session_id != client_sid) { - DEBUG_INFO(DEBUG_CATEGORY_ETCP, "tcp_server_on_link: session_id changed my=%08x client=%08x → reinit", - conn->session_id, client_sid); - etcp_conn_reinit(conn, "stcp session changed"); - } - conn->session_id = client_sid; - } - } - if (!conn) { conn = etcp_connection_create(inst, NULL); if (!conn) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "tcp_server_on_link: etcp_connection_create failed"); return; } conn->peer_node_id = node_id; - sc_set_peer_public_key(&conn->crypto_ctx, pubkey, SC_PEER_PUBKEY_BIN); + if (sc_init_ctx(&conn->crypto_ctx, &inst->my_keys) != SC_OK) { + DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "tcp_server_on_link: sc_init_ctx failed"); + etcp_connection_close(conn); return; + } + if (sc_set_peer_public_key(&conn->crypto_ctx, pubkey, SC_PEER_PUBKEY_BIN) != SC_OK) { + DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "tcp_server_on_link: sc_set_peer_public_key failed"); + etcp_connection_close(conn); return; + } etcp_update_log_name(conn); { struct conn_queue_entry* ce = (struct conn_queue_entry*)conn->conn_queue_entry->data; ce->peer_node_id = node_id; queue_remove_data(conn->conn_queue, conn->conn_queue_entry); queue_data_put_with_index(conn->conn_queue, conn->conn_queue_entry); } DEBUG_INFO(DEBUG_CATEGORY_ETCP, "tcp_server_on_link: new ETCP_CONN peer=0x%016llx", (unsigned long long)node_id); @@ -1062,11 +1048,9 @@ void etcp_link_enter_ready_tcp(struct ETCP_LINK *link) { link->recv_keepalive = 1; link->last_recv_local_time = get_time_tb(); if (!link->mtu_remote) link->mtu_remote = link->mtu; - etcp->got_initial_pkt = 1; - etcp->reset_done = 1; - etcp->initialized = 1; etcp->links_up = 1; etcp->tcp_link_count++; - if (etcp->tx_state == 0) etcp->tx_state = ETCP_TX_STATE_DATA_WAIT; + etcp->tcp_link_count++; if (link->tcp_link) { const uint8_t* ed = stcp_link_get_peer_ed25519_pubkey(link->tcp_link); if (ed) memcpy(etcp->peer_ed25519_pubkey, ed, SC_PUBKEY_SIZE); } + if (etcp->initialized == 0) etcp_conn_ready(etcp); etcp_link_send_keepalive(link); start_keepalive_timer(link); loadbalancer_link_ready(link); @@ -1074,8 +1058,6 @@ void etcp_link_enter_ready_tcp(struct ETCP_LINK *link) { DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[%s] TCP link %d UP (mtu=%d init=%d up=%d tcp_links=%d)", etcp->log_name, link->local_link_id, link->mtu, etcp->initialized, etcp->links_up, etcp->tcp_link_count); - etcp_fire_conn_status(etcp, ETCP_CONN_STATUS_UP); - etcp_cbk_fire(etcp, ETCP_CBK_EVENT_INIT); } static void tcp_link_reconnect_cb(void *arg) { @@ -1085,19 +1067,10 @@ static void tcp_link_reconnect_cb(void *arg) { if (link->tcp_reconnect_delay_ms == 0) link->tcp_reconnect_delay_ms = 1000; DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[%s] TCP link %d reconnect attempt (delay=%ums)", link->etcp->log_name, link->local_link_id, link->tcp_reconnect_delay_ms); uint16_t port = ntohs(((struct sockaddr_in *)&link->remote_addr)->sin_port); - struct sockaddr_storage bind_addr; const struct sockaddr_storage *laddr = NULL; - if (link->conn && link->conn->interface_addr.ss_family) { - memcpy(&bind_addr, &link->conn->interface_addr, sizeof(bind_addr)); - if (bind_addr.ss_family == AF_INET6) ((struct sockaddr_in6*)&bind_addr)->sin6_port = 0; - else ((struct sockaddr_in*)&bind_addr)->sin_port = 0; - laddr = &bind_addr; - } - struct stcp_link_config tcp_cfg = {.ua = link->etcp->instance->ua, .my_keys = &link->etcp->instance->my_keys, .inst = link->etcp->instance, .peer_pubkey = link->etcp->crypto_ctx.peer_public_key, - .peer_pubkey_mode = 0, .remote_addr = &link->remote_addr, .remote_port = port, .local_addr = laddr, .got_initial_pkt = link->etcp->got_initial_pkt, .session_id = link->etcp->session_id}; - struct stcp_link *sl = stcp_link_connect(&tcp_cfg); + struct stcp_link *sl = stcp_link_connect(link, &link->remote_addr, port); if (!sl) { link->tcp_reconnect_delay_ms *= 2; if (link->tcp_reconnect_delay_ms > 30000) link->tcp_reconnect_delay_ms = 30000; link->tcp_reconnect_timer = uasync_set_timeout(link->etcp->instance->ua, (int)(link->tcp_reconnect_delay_ms * 10), link, tcp_link_reconnect_cb, "tcp_rct"); return; } - link->tcp_link = sl; stcp_link_set_etcp_conn(sl, link->etcp); stcp_link_set_etcp_link(sl, link); + link->tcp_link = sl; stcp_link_set_on_close(sl, tcp_link_close_cb, link); } @@ -1106,25 +1079,9 @@ void etcp_tcp_link_start_connect(struct ETCP_LINK *link, struct sockaddr_storage if (!link->conn) { for (struct ETCP_SOCKET *s = link->etcp->instance->etcp_sockets; s; s = s->next) { if (s->is_tcp) { link->conn = s; break; } } if (!link->conn) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[%s] no TCP socket in instance, cannot start TCP link %d", link->etcp->log_name, link->local_link_id); return; } } memcpy(&link->remote_addr, addr, sizeof(*addr)); - struct sockaddr_storage bind_addr; const struct sockaddr_storage *laddr = NULL; - if (link->conn->interface_addr.ss_family) { - memcpy(&bind_addr, &link->conn->interface_addr, sizeof(bind_addr)); - if (bind_addr.ss_family == AF_INET6) ((struct sockaddr_in6*)&bind_addr)->sin6_port = 0; - else ((struct sockaddr_in*)&bind_addr)->sin_port = 0; - laddr = &bind_addr; - } - struct stcp_link_config tcp_cfg = { - .ua = link->etcp->instance->ua, - .my_keys = &link->etcp->instance->my_keys, - .inst = link->etcp->instance, - .peer_pubkey = link->etcp->crypto_ctx.peer_public_key, - .peer_pubkey_mode = 0, .remote_addr = &link->remote_addr, .remote_port = port, - .local_addr = laddr, - .got_initial_pkt = link->etcp->got_initial_pkt, - .session_id = link->etcp->session_id}; - struct stcp_link *sl = stcp_link_connect(&tcp_cfg); + struct stcp_link *sl = stcp_link_connect(link, &link->remote_addr, port); if (!sl) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "etcp_tcp_link_start_connect: stcp_link_connect failed"); return; } - link->tcp_link = sl; stcp_link_set_etcp_conn(sl, link->etcp); stcp_link_set_etcp_link(sl, link); + link->tcp_link = sl; if (link->is_server == 0) stcp_link_set_on_close(sl, tcp_link_close_cb, link); DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[%s] TCP link %d → stcp_link_connect %s:%u rc=%p", link->etcp->log_name, link->local_link_id, addr, port, (void*)sl); @@ -2380,8 +2337,7 @@ int init_sockets(struct UTUN_INSTANCE* instance) { struct ETCP_SOCKET* ts = tcp_socket_add(instance, server); if (!ts) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "tcp_socket_add failed for %s", server->name); fail_count++; server = server->next; continue; } - struct stcp_link_config scfg = {.ua = instance->ua, .my_keys = &instance->my_keys, .inst = instance, - .listen_family = server->ip.ss_family}; + struct stcp_link_config scfg = {.inst = instance, .listen_family = server->ip.ss_family}; struct stcp_server *tsrv = stcp_server_listen(&scfg, port, tcp_server_on_link, ts); if (!tsrv) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create TCP server for %s", server->name); diff --git a/src/transport_layer/etcp_keepalive.c b/src/transport_layer/etcp_keepalive.c index c9741d94..abf9b76a 100644 --- a/src/transport_layer/etcp_keepalive.c +++ b/src/transport_layer/etcp_keepalive.c @@ -181,6 +181,10 @@ static void apply_link_ka_mode(struct ETCP_LINK* link, uint8_t mode) { static void etcp_keepalive_send_mode_pkt(struct ETCP_LINK* link, uint8_t code, uint8_t mode) { if (!link || !link->etcp || !link->etcp->instance) return; + DEBUG_INFO(DEBUG_CATEGORY_KEEPALIVE, "[%s] keepalive %s send: mode=%s", + link->etcp->log_name, + code == ETCP_KEEPALIVE_REQ ? "REQ" : "RESP", + mode == KA_MODE_STANDBY ? "standby" : "normal"); struct ETCP_DGRAM* dgram = u_malloc(sizeof(struct ETCP_DGRAM) + 4); if (!dgram) { diff --git a/src/transport_layer/stcp.h b/src/transport_layer/stcp.h index 4dd51386..41be6c2a 100644 --- a/src/transport_layer/stcp.h +++ b/src/transport_layer/stcp.h @@ -16,6 +16,7 @@ extern "C" { #include struct UTUN_INSTANCE; +struct ETCP_CONN; #define STCP_MAX_MSG_SIZE 65535 #define STCP_RECV_BUF_INIT 8192 @@ -55,6 +56,7 @@ struct stcp_conn { void *socket_id; struct UTUN_INSTANCE *inst; // для lookup ETCP_CONN при хендшейке (сервер) + struct ETCP_CONN *etcp_conn; // клиент: родительский conn для live-чтения gop/session_id при handshake enum stcp_state state; uint8_t is_server; diff --git a/src/transport_layer/stcp_client.c b/src/transport_layer/stcp_client.c index 173b2281..1cec671d 100644 --- a/src/transport_layer/stcp_client.c +++ b/src/transport_layer/stcp_client.c @@ -2,6 +2,7 @@ #include "stcp_client.h" #include "secure_channel.h" #include "crc32.h" +#include "etcp.h" #include "../lib/u_async.h" #include "../lib/socket_compat.h" #include "../lib/ll_queue.h" @@ -54,9 +55,11 @@ static void client_send_handshake(struct stcp_conn *c, const uint8_t *server_pub memcpy(hs, salt, SC_PUBKEY_ENC_SALT_SIZE); sc_obfuscate_pubkey(salt, server_pubkey, c->my_keys.public_key, hs + SC_PUBKEY_ENC_SALT_SIZE); + uint8_t gop = c->etcp_conn ? c->etcp_conn->got_initial_pkt : c->got_initial_pkt; + uint32_t sid = c->etcp_conn ? c->etcp_conn->session_id : c->session_id; uint8_t plain[42]; memcpy(plain, my_ed25519, 32); - plain[32] = c->got_initial_pkt; - memcpy(plain + 33, &c->session_id, 4); + plain[32] = gop; + memcpy(plain + 33, &sid, 4); plain[37] = (uint8_t)padding; plain[38] = (uint8_t)(padding >> 8); plain[39] = c->device_type; *(uint16_t*)(plain + 40) = htobe16(c->keepalive_interval); @@ -68,7 +71,7 @@ static void client_send_handshake(struct stcp_conn *c, const uint8_t *server_pub for (int i = 0; i < padding; i++) hs[SC_PUBKEY_ENC_SIZE + STCP_HS_ENC_CLIENT + i] = (uint8_t)(salt[0] ^ i); c->state = STCP_STATE_HS_CLIENT_SENT; - DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_client: handshake sent (%zu bytes), entering HS_CLIENT_SENT", total); + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_client: handshake sent (%zu bytes) gop=%d sid=%08x, entering HS_CLIENT_SENT", total, gop, sid); c->send_buf = hs; c->send_len = total; c->send_offset = 0; uasync_set_socket_write(c->ua, c->socket_id, 1); } @@ -149,6 +152,7 @@ struct stcp_client *stcp_client_connect(struct UASYNC *ua, const char *addr, uin struct SC_MYKEYS *keys, const uint8_t *peer_pubkey, const uint8_t *my_ed25519_pubkey, uint8_t got_initial_pkt, uint32_t session_id, + struct ETCP_CONN *etcp_conn, uint8_t device_type, uint16_t keepalive_interval, stcp_ready_cb ready_cb, void *arg, stcp_close_cb close_cb, void *close_arg, @@ -167,6 +171,7 @@ struct stcp_client *stcp_client_connect(struct UASYNC *ua, const char *addr, uin c->tx_cb = stcp_tx_queue_cb; c->got_initial_pkt = got_initial_pkt; c->session_id = session_id; + c->etcp_conn = etcp_conn; c->device_type = device_type; c->keepalive_interval = keepalive_interval; diff --git a/src/transport_layer/stcp_client.h b/src/transport_layer/stcp_client.h index 82726641..7f0a23a3 100644 --- a/src/transport_layer/stcp_client.h +++ b/src/transport_layer/stcp_client.h @@ -16,6 +16,7 @@ struct stcp_client *stcp_client_connect(struct UASYNC *ua, const char *addr, uin struct SC_MYKEYS *keys, const uint8_t *peer_pubkey, const uint8_t *my_ed25519_pubkey, uint8_t got_initial_pkt, uint32_t session_id, + struct ETCP_CONN *etcp_conn, uint8_t device_type, uint16_t keepalive_interval, stcp_ready_cb ready_cb, void *arg, stcp_close_cb close_cb, void *close_arg, diff --git a/src/transport_layer/stcp_link.c b/src/transport_layer/stcp_link.c index 21606a4c..4b4a9280 100644 --- a/src/transport_layer/stcp_link.c +++ b/src/transport_layer/stcp_link.c @@ -18,16 +18,18 @@ struct stcp_server { struct stcp_server *next; // linked list in UTUN_INSTANCE struct stcp_server *srv; // stcp_server from stcp_server.h - struct stcp_link_config cfg; + struct UTUN_INSTANCE *inst; stcp_server_on_link_cb on_link; struct ETCP_SOCKET *tcp_sock; }; struct stcp_link { - struct stcp_link_config cfg; struct stcp_client *cli; struct stcp_conn *conn; + struct UTUN_INSTANCE *inst; // для rx-диспатча (из etcp_conn->instance) + struct UASYNC *ua; // event loop (из inst->ua) + struct ETCP_CONN *etcp_conn; // parent ETCP_CONN (for rx dispatch / etcp_send compat) struct ETCP_LINK *etcp_link; // owning ETCP_LINK (for etcp_conn_input pkt->link) @@ -57,7 +59,7 @@ static void link_rx_cb(struct ll_queue *q, void *arg) { struct ll_entry *e = queue_data_get(q); if (!e) { queue_resume_callback(q); return; } - if (link->etcp_conn && link->etcp_link && link->cfg.inst) { + if (link->etcp_conn && link->etcp_link && link->inst) { DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[%s] stcp_rx: len=%u hdr=%02x%02x%02x sock=%p", link->etcp_conn->log_name, e->len, e->dgram && e->len>=3 ? e->dgram[0] : 0, @@ -72,7 +74,7 @@ static void link_rx_cb(struct ll_queue *q, void *arg) { return; } if (e->len < 3) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "stcp_link rx too short: %u bytes", e->len); queue_dgram_free(e); queue_entry_free(e); queue_resume_callback(q); return; } - struct ETCP_DGRAM *pkt = memory_pool_alloc(link->cfg.inst->pkt_pool); + struct ETCP_DGRAM *pkt = memory_pool_alloc(link->inst->pkt_pool); if (!pkt) { queue_dgram_free(e); queue_entry_free(e); queue_resume_callback(q); return; } pkt->timestamp = ((uint16_t*)e->dgram)[0]; pkt->flag_up = e->dgram[2] & 1; @@ -84,7 +86,7 @@ static void link_rx_cb(struct ll_queue *q, void *arg) { etcp_packet_decrypted(sock, pkt, link->etcp_link, e->len); queue_dgram_free(e); queue_entry_free(e); } else { - struct UTUN_INSTANCE *inst = link->cfg.inst; + struct UTUN_INSTANCE *inst = link->inst; uint8_t id = (e->dgram && e->len > 0) ? e->dgram[0] : 0; if (inst && inst->api_bindings.callbacks[id]) inst->api_bindings.callbacks[id](link->etcp_conn ? link->etcp_conn : NULL, e); @@ -112,7 +114,8 @@ static void server_accept_cb(struct stcp_conn *conn, void *arg) { struct stcp_server *ss = (struct stcp_server *)arg; struct stcp_link *link = u_calloc(1, sizeof(struct stcp_link)); if (!link) { stcp_conn_free(conn); return; } - link->cfg = ss->cfg; + link->inst = ss->inst; + link->ua = ss->inst->ua; link->ready = 1; link->conn = conn; link->peer_got_initial_pkt = conn->peer_got_initial_pkt; @@ -158,16 +161,12 @@ static void client_ready_cb(struct stcp_conn *conn, void *arg) { queue_set_waiter_defer(link->tx_queue, 1); stcp_conn_set_tx_queue(conn, link->tx_queue); - if (link->cfg.remote_addr) { + { + const struct sockaddr_storage *ra = link->etcp_link ? &link->etcp_link->remote_addr : NULL; DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_link: client handshake OK [%s] link=%d addr=%s gop=%d sid=%08x", link->etcp_conn ? link->etcp_conn->log_name : "?", link->etcp_link ? link->etcp_link->local_link_id : -1, - sockaddr_storage_to_str(link->cfg.remote_addr).str, - link->peer_got_initial_pkt, link->peer_session_id); - } else { - DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_link: client handshake OK [%s] link=%d addr=? gop=%d sid=%08x", - link->etcp_conn ? link->etcp_conn->log_name : "?", - link->etcp_link ? link->etcp_link->local_link_id : -1, + ra ? sockaddr_storage_to_str(ra).str : "?", link->peer_got_initial_pkt, link->peer_session_id); } if (link->etcp_link) etcp_link_enter_ready_tcp(link->etcp_link); @@ -178,13 +177,14 @@ static void client_ready_cb(struct stcp_conn *conn, void *arg) { struct stcp_server *stcp_server_listen(struct stcp_link_config *cfg, uint16_t port, stcp_server_on_link_cb on_link, struct ETCP_SOCKET *tcp_sock) { - if (!cfg || !cfg->ua || !cfg->my_keys) return NULL; + if (!cfg || !cfg->inst) return NULL; struct stcp_server *ss = u_calloc(1, sizeof(struct stcp_server)); if (!ss) return NULL; - ss->cfg = *cfg; + ss->inst = cfg->inst; ss->on_link = on_link; ss->tcp_sock = tcp_sock; - ss->srv = stcp_server_create(cfg->ua, port, cfg->my_keys, cfg->inst ? cfg->inst->my_ed25519_pubkey : NULL, cfg->inst, server_accept_cb, ss, NULL, NULL, cfg->listen_family); + ss->srv = stcp_server_create(cfg->inst->ua, port, &cfg->inst->my_keys, cfg->inst->my_ed25519_pubkey, + cfg->inst, server_accept_cb, ss, NULL, NULL, cfg->listen_family); if (!ss->srv) { u_free(ss); return NULL; } DEBUG_INFO(DEBUG_CATEGORY_ETCP, "port=%u", port); return ss; @@ -196,21 +196,24 @@ void stcp_link_server_destroy(struct stcp_server *ss) { u_free(ss); } -struct stcp_link *stcp_link_connect(struct stcp_link_config *cfg) { - if (!cfg || !cfg->ua || !cfg->my_keys || !cfg->peer_pubkey || !cfg->remote_addr) +struct stcp_link *stcp_link_connect(struct ETCP_LINK *etcp_link, + struct sockaddr_storage *remote_addr, uint16_t port) { + if (!etcp_link || !etcp_link->etcp || !remote_addr) return NULL; + struct ETCP_CONN *etcp = etcp_link->etcp; + struct UTUN_INSTANCE *inst = etcp->instance; - int family = cfg->remote_addr->ss_family; + int family = remote_addr->ss_family; char addr_str[64]; - uint16_t port; + uint16_t rport = port; if (family == AF_INET) { - struct sockaddr_in *sa = (struct sockaddr_in *)cfg->remote_addr; + struct sockaddr_in *sa = (struct sockaddr_in *)remote_addr; inet_ntop(AF_INET, &sa->sin_addr, addr_str, sizeof(addr_str)); - port = cfg->remote_port ? cfg->remote_port : ntohs(sa->sin_port); + if (!rport) rport = ntohs(sa->sin_port); } else if (family == AF_INET6) { - struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)cfg->remote_addr; + struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)remote_addr; getnameinfo((struct sockaddr*)sa6, sizeof(*sa6), addr_str, sizeof(addr_str), NULL, 0, NI_NUMERICHOST); - port = cfg->remote_port ? cfg->remote_port : ntohs(sa6->sin6_port); + if (!rport) rport = ntohs(sa6->sin6_port); } else { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "stcp_link: unsupported address family %d", family); return NULL; @@ -218,32 +221,32 @@ struct stcp_link *stcp_link_connect(struct stcp_link_config *cfg) { struct stcp_link *link = u_calloc(1, sizeof(struct stcp_link)); if (!link) return NULL; - link->cfg = *cfg; - - uint8_t pubkey[SC_PUBKEY_SIZE]; - if (cfg->peer_pubkey_mode) { - struct secure_channel sc_tmp; - sc_init_ctx(&sc_tmp, cfg->my_keys); - if (sc_set_peer_public_key(&sc_tmp, cfg->peer_pubkey, 1) != SC_OK) { - DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "invalid peer pubkey hex"); - u_free(link); return NULL; - } - memcpy(pubkey, sc_tmp.peer_public_key, SC_PUBKEY_SIZE); - } else { - memcpy(pubkey, cfg->peer_pubkey, SC_PUBKEY_SIZE); + link->inst = inst; + link->ua = inst->ua; + link->etcp_conn = etcp; + link->etcp_link = etcp_link; + + struct sockaddr_storage bind_addr; + const struct sockaddr_storage *local_addr = NULL; + if (etcp_link->conn && etcp_link->conn->interface_addr.ss_family) { + memcpy(&bind_addr, &etcp_link->conn->interface_addr, sizeof(bind_addr)); + if (bind_addr.ss_family == AF_INET6) ((struct sockaddr_in6*)&bind_addr)->sin6_port = 0; + else ((struct sockaddr_in*)&bind_addr)->sin_port = 0; + local_addr = &bind_addr; } - link->cli = stcp_client_connect(cfg->ua, addr_str, port, cfg->my_keys, pubkey, - cfg->inst ? cfg->inst->my_ed25519_pubkey : NULL, - cfg->got_initial_pkt, cfg->session_id, - cfg->inst ? cfg->inst->client_type : 0, - cfg->inst ? cfg->inst->keepalive_interval : 200, - client_ready_cb, link, NULL, NULL, cfg->local_addr); + const uint8_t *pubkey = etcp->crypto_ctx.peer_public_key; + + link->cli = stcp_client_connect(inst->ua, addr_str, rport, &inst->my_keys, pubkey, + inst->my_ed25519_pubkey, + etcp->got_initial_pkt, etcp->session_id, etcp, + inst->client_type, inst->keepalive_interval, + client_ready_cb, link, NULL, NULL, local_addr); if (!link->cli) { u_free(link); return NULL; } DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_link: connecting to %s:%u pubkey=%016llx bind=%s", - addr_str, port, (unsigned long long)*(const uint64_t*)pubkey, - cfg->local_addr ? sockaddr_storage_to_str(cfg->local_addr).str : "auto"); + addr_str, rport, (unsigned long long)*(const uint64_t*)pubkey, + local_addr ? sockaddr_storage_to_str(local_addr).str : "auto"); return link; } @@ -281,13 +284,13 @@ void stcp_link_close(struct stcp_link *link) { if (link->cli) { struct stcp_conn *c = stcp_client_get_conn(link->cli); if (c) { - if (c->hs_timer) { uasync_cancel_timeout(link->cfg.ua, c->hs_timer); c->hs_timer = NULL; } + if (c->hs_timer) { uasync_cancel_timeout(link->ua, c->hs_timer); c->hs_timer = NULL; } if (c->state == STCP_STATE_CLOSED || c->state == STCP_STATE_ERROR) { link->saved_rx_queue = c->rx_queue; c->rx_queue = NULL; link->conn_pre_closed = 1; } } } - uasync_call_soon(link->cfg.ua, link, stcp_link_close_impl); + uasync_call_soon(link->ua, link, stcp_link_close_impl); } int stcp_link_send(struct stcp_link *link, const uint8_t *data, size_t len) { @@ -321,7 +324,7 @@ void stcp_link_set_etcp_link(struct stcp_link *link, struct ETCP_LINK *elink) { } const struct sockaddr_storage *stcp_link_get_remote_addr(struct stcp_link *link) { - return link && link->cfg.remote_addr ? link->cfg.remote_addr : NULL; + return link && link->etcp_link ? &link->etcp_link->remote_addr : NULL; } static struct sockaddr_storage g_peer_addr; diff --git a/src/transport_layer/stcp_link.h b/src/transport_layer/stcp_link.h index f358b0c5..4b57f3b8 100644 --- a/src/transport_layer/stcp_link.h +++ b/src/transport_layer/stcp_link.h @@ -22,17 +22,8 @@ struct UTUN_INSTANCE; // ====== Link config ====== struct stcp_link_config { - struct UASYNC *ua; - struct SC_MYKEYS *my_keys; // ключи этой стороны - struct UTUN_INSTANCE *inst; // для диспатча через api_bindings - const uint8_t *peer_pubkey; // pubkey пира (клиент) - int peer_pubkey_mode; // 0=binary, 1=hex - const struct sockaddr_storage *local_addr; // локальный адрес/интерфейс для bind (клиент, NULL=авто) - const struct sockaddr_storage *remote_addr; // адрес пира (клиент) - uint16_t remote_port; // порт пира (клиент) + struct UTUN_INSTANCE *inst; // rx-диспатч + instance_find_conn; ua/my_keys/ed25519 выводятся отсюда int listen_family; // AF_INET или AF_INET6 для сервера (0 = v4) - uint8_t got_initial_pkt; // моё значение, отправляется пиру при handshake - uint32_t session_id; // мой ETCP session_id, отправляется пиру при handshake }; // ====== TCP server ====== @@ -51,7 +42,8 @@ int stcp_server_list_count(struct UTUN_INSTANCE *inst); // ====== TCP client link ====== -struct stcp_link *stcp_link_connect(struct stcp_link_config *cfg); +struct stcp_link *stcp_link_connect(struct ETCP_LINK *etcp_link, + struct sockaddr_storage *remote_addr, uint16_t port); void stcp_link_close(struct stcp_link *link); int stcp_link_send(struct stcp_link *link, const uint8_t *data, size_t len); int stcp_link_is_ready(struct stcp_link *link); diff --git a/tests/test_etcp_link_stress.c b/tests/test_etcp_link_stress.c index 8d6e6c93..173493f6 100644 --- a/tests/test_etcp_link_stress.c +++ b/tests/test_etcp_link_stress.c @@ -296,7 +296,7 @@ static int add_tcp_pair(struct ETCP_CONN* conn) { struct ETCP_SOCKET* ts = tcp_socket_add(server_instance, &cfg); if (!ts) { release_tcp_port(port); return -1; } - struct stcp_link_config scfg = {.ua = ua, .my_keys = &server_instance->my_keys, .inst = server_instance, .listen_family = AF_INET}; + struct stcp_link_config scfg = {.inst = server_instance, .listen_family = AF_INET}; struct stcp_server* srv = stcp_server_listen(&scfg, port, (stcp_server_on_link_cb)tcp_server_on_link, ts); if (!srv) { tcp_socket_remove(ts); release_tcp_port(port); return -1; } stcp_server_list_add(server_instance, srv); diff --git a/tests/test_stcp.c b/tests/test_stcp.c index d977c60f..762e5547 100644 --- a/tests/test_stcp.c +++ b/tests/test_stcp.c @@ -104,7 +104,7 @@ static int test1_sizes(void) { uint16_t port = BASE_PORT + 1; struct stcp_server *ss = stcp_server_create(ua, port, &s_keys, NULL, NULL, server_connect_cb, &srv, peer_close_cb, &srv, AF_INET); TASSERT(ss); - struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); + struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, NULL, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); size_t sizes[] = {0, 1, 16, 17, 255, 256, 1000, 65535}; int n_sizes = 8; @@ -144,7 +144,7 @@ static int test2_many(void) { uint16_t port = BASE_PORT + 2; struct stcp_server *ss = stcp_server_create(ua, port, &s_keys, NULL, NULL, server_connect_cb, &srv, peer_close_cb, &srv, AF_INET); TASSERT(ss); - struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); + struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, NULL, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); int sent = 0, ticks = 0; while (srv.msg_count < 200 && ticks < 200) { @@ -185,7 +185,7 @@ static int test3_wrong_key(void) { struct SC_MYKEYS rogue; TASSERT(sc_generate_keypair(&rogue) == SC_OK); - struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, rogue.public_key, NULL, 0, 0, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); + struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, rogue.public_key, NULL, 0, 0, NULL, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); int ticks = 0; while (ticks < 200) { @@ -210,7 +210,7 @@ static int test4_close(void) { uint16_t port = BASE_PORT + 4; struct stcp_server *ss = stcp_server_create(ua, port, &s_keys, NULL, NULL, server_connect_cb, &srv, peer_close_cb, &srv, AF_INET); TASSERT(ss); - struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); + struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, NULL, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); int closed = 0, ticks = 0; while (!srv.closed && ticks < 200) { @@ -260,7 +260,7 @@ static int test5_multi(void) { struct stcp_client *clients[NCLI] = {0}; for (int i = 0; i < NCLI; i++) { - clients[i] = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, 0, 200, client_ready_cb, &clip[i], peer_close_cb, &clip[i], NULL); + clients[i] = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, NULL, 0, 200, client_ready_cb, &clip[i], peer_close_cb, &clip[i], NULL); TASSERT(clients[i]); } @@ -309,7 +309,7 @@ static int test6_interleaved(void) { uint16_t port = BASE_PORT + 6; struct stcp_server *ss = stcp_server_create(ua, port, &s_keys, NULL, NULL, server_connect_cb, &srv, peer_close_cb, &srv, AF_INET); TASSERT(ss); - struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); + struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, NULL, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); int round = 0, ticks = 0; while (srv.msg_count < 50 || cli.msg_count < 50) { @@ -343,7 +343,7 @@ static int test7_bulk_4mb(void) { uint16_t port = BASE_PORT + 7; struct stcp_server *ss = stcp_server_create(ua, port, &s_keys, NULL, NULL, server_connect_cb, &srv, peer_close_cb, &srv, AF_INET); TASSERT(ss); - struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); + struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, NULL, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); #define N_BULK 64 #define SZ_BULK 65535 @@ -382,7 +382,7 @@ static int test8_srv_recv_close(void) { uint16_t port = BASE_PORT + 8; struct stcp_server *ss = stcp_server_create(ua, port, &s_keys, NULL, NULL, server_connect_cb, &srv, peer_close_cb, &srv, AF_INET); TASSERT(ss); - struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); + struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", port, &c_keys, s_keys.public_key, NULL, 0, 0, NULL, 0, 200, client_ready_cb, &cli, peer_close_cb, &cli, NULL); TASSERT(sc); int ticks = 0; while ((!srv.ready || !cli.ready) && ticks < 200) { uasync_poll(ua, 10); ticks++; } diff --git a/tests/test_stcp_link.c b/tests/test_stcp_link.c index 19779933..47329014 100644 --- a/tests/test_stcp_link.c +++ b/tests/test_stcp_link.c @@ -1,8 +1,9 @@ -// test_stcp_link.c — integration test for stcp_link API (TCP via STCP) +// test_stcp_link.c — STCP link layer: server listen/accept (slim config) + client connect (raw stcp_client) #include "stcp_link.h" +#include "stcp_client.h" #include "secure_channel.h" +#include "utun_instance.h" #include "../lib/u_async.h" -#include "../lib/ll_queue.h" #include "../lib/debug_config.h" #include "../lib/mem.h" #include @@ -18,88 +19,78 @@ static int test_failed = 0; if (!(cond)) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, " FAIL: %s", #cond); test_failed = 1; return test_failed; } \ } while(0) -struct recv_ctx { uint8_t *data; size_t len, cap; int count; }; - -static void recv_cb(struct ll_queue *q, void *arg) { - struct recv_ctx *r = (struct recv_ctx *)arg; - struct ll_entry *e = queue_data_get(q); - if (!e) { queue_resume_callback(q); return; } - r->count++; - size_t need = r->len + e->len; - if (need > r->cap) { r->cap = need + 256; r->data = u_realloc(r->data, r->cap); } - if (e->dgram && e->len) memcpy(r->data + r->len, e->dgram, e->len); - r->len += e->len; - queue_entry_free(e); - queue_resume_callback(q); -} - static struct stcp_link *g_on_srv_link = NULL; static void on_srv_link(struct stcp_link *link, struct ETCP_SOCKET *tcp_sock) { (void)tcp_sock; g_on_srv_link = link; } -static void on_cli_ready(struct stcp_link *link, void *arg) { +static void on_cli_ready(struct stcp_conn *conn, void *arg) { + (void)conn; int *ready = (int *)arg; *ready = 1; - (void)link; +} + +static struct UTUN_INSTANCE *make_inst(struct UASYNC *ua, struct SC_MYKEYS *keys) { + struct UTUN_INSTANCE *inst = u_calloc(1, sizeof(struct UTUN_INSTANCE)); + if (!inst) return NULL; + inst->ua = ua; + inst->my_keys = *keys; + inst->keepalive_interval = 200; + return inst; } static int test1_basic(void) { struct UASYNC *ua = uasync_create(); TASSERT(ua); + struct UTUN_INSTANCE *inst = make_inst(ua, &s_keys); TASSERT(inst); - struct stcp_link_config cfg = {.ua = ua, .my_keys = &s_keys, .inst = NULL}; + struct stcp_link_config cfg = {.inst = inst, .listen_family = AF_INET}; g_on_srv_link = NULL; - struct stcp_server *ss = stcp_server_listen(&cfg, BASE_PORT + 1, (stcp_server_on_link_cb)on_srv_link, NULL); + struct stcp_server *ss = stcp_server_listen(&cfg, BASE_PORT + 1, on_srv_link, NULL); TASSERT(ss); - struct sockaddr_in raddr; memset(&raddr, 0, sizeof(raddr)); - raddr.sin_family = AF_INET; raddr.sin_port = htons(BASE_PORT + 1); - raddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - struct stcp_link_config cli_cfg = {.ua = ua, .my_keys = &c_keys, .inst = NULL, - .peer_pubkey = s_keys.public_key, .remote_addr = (struct sockaddr_storage *)&raddr}; int cli_ready = 0; - struct stcp_link *cli_link = stcp_link_connect(&cli_cfg); TASSERT(cli_link); - stcp_link_set_on_ready(cli_link, on_cli_ready, &cli_ready); + struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", BASE_PORT + 1, &c_keys, + s_keys.public_key, NULL, + 0, 0, NULL, + 0, 200, on_cli_ready, &cli_ready, NULL, NULL, NULL); + TASSERT(sc); int ticks = 0; while ((!g_on_srv_link || !cli_ready) && ticks < 5000) { uasync_poll(ua, 10); ticks++; } TASSERT(g_on_srv_link != NULL); TASSERT(cli_ready); - // Verify send works (no crash, data goes through TCP) - const char *msg = "hello link!"; - int r = stcp_link_send(cli_link, (const uint8_t *)msg, strlen(msg)); - TASSERT(r == 0); - - stcp_link_close(cli_link); + stcp_client_destroy(sc); + stcp_link_close(g_on_srv_link); stcp_link_server_destroy(ss); + u_free(inst); uasync_destroy(ua, 1); return 0; } static int test2_wrong_key(void) { struct UASYNC *ua = uasync_create(); TASSERT(ua); + struct UTUN_INSTANCE *inst = make_inst(ua, &s_keys); TASSERT(inst); - struct stcp_link_config cfg = {.ua = ua, .my_keys = &s_keys, .inst = NULL}; + struct stcp_link_config cfg = {.inst = inst, .listen_family = AF_INET}; g_on_srv_link = NULL; - struct stcp_server *ss = stcp_server_listen(&cfg, BASE_PORT + 2, (stcp_server_on_link_cb)on_srv_link, NULL); + struct stcp_server *ss = stcp_server_listen(&cfg, BASE_PORT + 2, on_srv_link, NULL); TASSERT(ss); struct SC_MYKEYS rogue; TASSERT(sc_generate_keypair(&rogue) == SC_OK); - struct sockaddr_in raddr; memset(&raddr, 0, sizeof(raddr)); - raddr.sin_family = AF_INET; raddr.sin_port = htons(BASE_PORT + 2); - raddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - struct stcp_link_config cli_cfg = {.ua = ua, .my_keys = &c_keys, .inst = NULL, - .peer_pubkey = rogue.public_key, .remote_addr = (struct sockaddr_storage *)&raddr}; - struct stcp_link *cli_link = stcp_link_connect(&cli_cfg); TASSERT(cli_link); + int cli_ready = 0; + struct stcp_client *sc = stcp_client_connect(ua, "127.0.0.1", BASE_PORT + 2, &c_keys, + rogue.public_key, NULL, + 0, 0, NULL, + 0, 200, on_cli_ready, &cli_ready, NULL, NULL, NULL); + TASSERT(sc); int ticks = 0; - while (!g_on_srv_link && ticks < 2000) { uasync_poll(ua, 10); ticks++; } + while (ticks < 2000) { uasync_poll(ua, 10); ticks++; } TASSERT(!g_on_srv_link); // should NOT connect with wrong key - stcp_link_close(cli_link); + stcp_client_destroy(sc); stcp_link_server_destroy(ss); + u_free(inst); uasync_destroy(ua, 1); return 0; }