fix: re-index conn_queue_entry after setting peer_node_id
tcp_server_on_link sets conn->peer_node_id after etcp_connection_create which adds the entry with peer_node_id=0. instance_find_conn couldnt find TCP connections until the queue entry was re-indexed.
This commit is contained in:
1 parent
adac854c94
commit
a3783b5f55
5 files changed
+1
-2685
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -60,6 +60,7 @@ static void tcp_server_on_link(struct stcp_link *link, void *arg) {
|
||||
conn->peer_node_id = node_id;
|
||||
sc_set_peer_public_key(&conn->crypto_ctx, pubkey, SC_PEER_PUBKEY_BIN);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,286 +0,0 @@
|
||||
// stcp_link.c — STCP link management implementation
|
||||
#include "stcp_link.h"
|
||||
#include "stcp.h"
|
||||
#include "stcp_server.h"
|
||||
#include "stcp_client.h"
|
||||
#include "secure_channel.h"
|
||||
#include "etcp.h"
|
||||
#include "etcp_connections.h"
|
||||
#include "etcp_router.h"
|
||||
#include "utun_instance.h"
|
||||
#include "../lib/debug_config.h"
|
||||
#include "../lib/ll_queue.h"
|
||||
#include "../lib/mem.h"
|
||||
#include "../lib/memory_pool.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
stcp_server_on_link_cb on_link;
|
||||
void *on_link_arg;
|
||||
};
|
||||
|
||||
struct stcp_link {
|
||||
struct stcp_link_config cfg;
|
||||
struct stcp_client *cli;
|
||||
struct stcp_conn *conn;
|
||||
|
||||
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)
|
||||
|
||||
uint8_t ready;
|
||||
uint8_t closing;
|
||||
|
||||
stcp_link_cb on_ready_cb;
|
||||
void *ready_arg;
|
||||
void (*on_close_cb)(struct stcp_link *link, int err, void *arg);
|
||||
void *close_arg;
|
||||
|
||||
struct ll_queue *tx_queue; // owned by this link
|
||||
};
|
||||
|
||||
// ====== rx dispatch ======
|
||||
|
||||
static void link_rx_cb(struct ll_queue *q, void *arg) {
|
||||
struct stcp_link *link = (struct stcp_link *)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 (e->len >= 1 && e->dgram[0] == ETCP_KEEPALIVE) {
|
||||
struct ETCP_LINK *l = link->etcp_link;
|
||||
if (e->len >= 3) { uint16_t pp = e->dgram[1] | ((uint16_t)e->dgram[2] << 8); l->keepalive_timeout = (uint32_t)pp * KA_TIMEOUT_MULT; }
|
||||
l->recv_keepalive = 1; l->remote_keepalive = 1; l->link_status = 1; l->keepalive_recv_count++;
|
||||
l->last_recv_local_time = get_time_tb();
|
||||
queue_dgram_free(e); queue_entry_free(e);
|
||||
} else {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "stcp_link rx → etcp_conn_input len=%zu link=%p", e->len, (void*)link->etcp_link);
|
||||
struct ETCP_DGRAM *pkt = memory_pool_alloc(link->cfg.inst->pkt_pool);
|
||||
if (pkt) {
|
||||
pkt->link = link->etcp_link; pkt->data_len = (uint16_t)e->len; pkt->noencrypt_len = 0;
|
||||
if (e->len > 0) memcpy(pkt->data, e->dgram, e->len);
|
||||
etcp_conn_input(pkt);
|
||||
}
|
||||
queue_dgram_free(e); queue_entry_free(e);
|
||||
}
|
||||
} else {
|
||||
struct UTUN_INSTANCE *inst = link->cfg.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);
|
||||
else if (inst && inst->api_bindings.callbacks[0])
|
||||
inst->api_bindings.callbacks[0](link->etcp_conn ? link->etcp_conn : NULL, e);
|
||||
else { queue_dgram_free(e); queue_entry_free(e); }
|
||||
}
|
||||
queue_resume_callback(q);
|
||||
}
|
||||
|
||||
// ====== server accept → link ======
|
||||
|
||||
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->ready = 1;
|
||||
link->conn = conn;
|
||||
|
||||
struct ll_queue *rx = queue_new(conn->ua, 0, 0, 0, "srx");
|
||||
queue_set_callback(rx, link_rx_cb, link);
|
||||
stcp_conn_set_rx_queue(conn, rx);
|
||||
link->tx_queue = queue_new(conn->ua, 0, 0, 0, "stx");
|
||||
queue_set_threshold(link->tx_queue, 0, 0);
|
||||
queue_set_waiter_defer(link->tx_queue, 1);
|
||||
stcp_conn_set_tx_queue(conn, link->tx_queue);
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_link: server accepted connection");
|
||||
if (ss->on_link) ss->on_link(link, ss->on_link_arg);
|
||||
}
|
||||
|
||||
// ====== client connect → link ======
|
||||
|
||||
static void client_ready_cb(struct stcp_conn *conn, void *arg) {
|
||||
struct stcp_link *link = (struct stcp_link *)arg;
|
||||
if (!conn) return;
|
||||
link->ready = 1;
|
||||
link->conn = conn;
|
||||
|
||||
struct ll_queue *rx = queue_new(conn->ua, 0, 0, 0, "crx");
|
||||
queue_set_callback(rx, link_rx_cb, link);
|
||||
stcp_conn_set_rx_queue(conn, rx);
|
||||
link->tx_queue = queue_new(conn->ua, 0, 0, 0, "ctx");
|
||||
queue_set_threshold(link->tx_queue, 0, 0);
|
||||
queue_set_waiter_defer(link->tx_queue, 1);
|
||||
stcp_conn_set_tx_queue(conn, link->tx_queue);
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_link: client handshake OK, link=%p etcp_link=%p",
|
||||
(void*)link, (void*)link->etcp_link);
|
||||
if (link->etcp_link) etcp_link_enter_ready_tcp(link->etcp_link);
|
||||
if (link->on_ready_cb) link->on_ready_cb(link, link->ready_arg);
|
||||
}
|
||||
|
||||
// ====== API ======
|
||||
|
||||
struct stcp_server *stcp_server_listen(struct stcp_link_config *cfg, uint16_t port,
|
||||
stcp_server_on_link_cb on_link, void *arg) {
|
||||
if (!cfg || !cfg->ua || !cfg->my_keys) return NULL;
|
||||
struct stcp_server *ss = u_calloc(1, sizeof(struct stcp_server));
|
||||
if (!ss) return NULL;
|
||||
ss->cfg = *cfg;
|
||||
ss->on_link = on_link;
|
||||
ss->on_link_arg = arg;
|
||||
ss->srv = stcp_server_create(cfg->ua, port, cfg->my_keys, 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;
|
||||
}
|
||||
|
||||
void stcp_link_server_destroy(struct stcp_server *ss) {
|
||||
if (!ss) return;
|
||||
if (ss->srv) stcp_server_destroy(ss->srv);
|
||||
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)
|
||||
return NULL;
|
||||
|
||||
int family = cfg->remote_addr->ss_family;
|
||||
char addr_str[64];
|
||||
uint16_t port;
|
||||
if (family == AF_INET) {
|
||||
struct sockaddr_in *sa = (struct sockaddr_in *)cfg->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);
|
||||
} else if (family == AF_INET6) {
|
||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)cfg->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);
|
||||
} else {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "stcp_link: unsupported address family %d", family);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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->cli = stcp_client_connect(cfg->ua, addr_str, port, cfg->my_keys, pubkey,
|
||||
client_ready_cb, link, NULL, NULL);
|
||||
if (!link->cli) { u_free(link); return NULL; }
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_link: connecting to %s:%u pubkey=%016llx",
|
||||
addr_str, port, (unsigned long long)*(const uint64_t*)pubkey);
|
||||
return link;
|
||||
}
|
||||
|
||||
static void stcp_link_close_impl(void *arg) {
|
||||
struct stcp_link *link = (struct stcp_link *)arg;
|
||||
if (link->on_close_cb) link->on_close_cb(link, 0, link->close_arg);
|
||||
if (link->conn) {
|
||||
if (link->conn->rx_queue) queue_free(link->conn->rx_queue);
|
||||
if (link->tx_queue) queue_free(link->tx_queue);
|
||||
stcp_conn_free(link->conn);
|
||||
}
|
||||
if (link->cli) stcp_client_destroy(link->cli);
|
||||
u_free(link);
|
||||
}
|
||||
|
||||
void stcp_link_close(struct stcp_link *link) {
|
||||
if (!link) return;
|
||||
if (link->closing) return;
|
||||
link->closing = 1;
|
||||
uasync_call_soon(link->cfg.ua, link, stcp_link_close_impl);
|
||||
}
|
||||
|
||||
int stcp_link_send(struct stcp_link *link, const uint8_t *data, size_t len) {
|
||||
if (!link || !link->ready) return -1;
|
||||
struct ll_entry *e = queue_entry_new(0);
|
||||
if (!e) return -1;
|
||||
e->dgram = u_malloc(len ? len : 1);
|
||||
if (!e->dgram) { queue_entry_free(e); return -1; }
|
||||
if (len) memcpy(e->dgram, data, len);
|
||||
e->len = (uint16_t)len;
|
||||
queue_data_put(link->conn->tx_queue, e);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stcp_link_is_ready(struct stcp_link *link) {
|
||||
return link ? link->ready : 0;
|
||||
}
|
||||
|
||||
struct ETCP_CONN *stcp_link_get_etcp_conn(struct stcp_link *link) {
|
||||
return link ? link->etcp_conn : NULL;
|
||||
}
|
||||
|
||||
void stcp_link_set_etcp_conn(struct stcp_link *link, struct ETCP_CONN *conn) {
|
||||
if (!link) return;
|
||||
link->etcp_conn = conn;
|
||||
}
|
||||
|
||||
void stcp_link_set_etcp_link(struct stcp_link *link, struct ETCP_LINK *elink) {
|
||||
if (!link) return;
|
||||
link->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;
|
||||
}
|
||||
|
||||
void stcp_link_set_on_ready(struct stcp_link *link, stcp_link_cb cb, void *arg) {
|
||||
if (!link) return;
|
||||
link->on_ready_cb = cb;
|
||||
link->ready_arg = arg;
|
||||
}
|
||||
|
||||
void stcp_link_set_on_close(struct stcp_link *link, void (*cb)(struct stcp_link *link, int err, void *arg), void *arg) {
|
||||
if (!link) return;
|
||||
link->on_close_cb = cb;
|
||||
link->close_arg = arg;
|
||||
}
|
||||
|
||||
const uint8_t *stcp_link_get_peer_pubkey(struct stcp_link *link) {
|
||||
return link && link->conn ? link->conn->peer_pubkey : NULL;
|
||||
}
|
||||
|
||||
void stcp_server_list_add(struct UTUN_INSTANCE *inst, struct stcp_server *srv) {
|
||||
if (!inst || !srv) return;
|
||||
srv->next = inst->stcp_servers;
|
||||
inst->stcp_servers = srv;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_server_list_add: %p total=%d", (void*)srv, stcp_server_list_count(inst));
|
||||
}
|
||||
|
||||
void stcp_server_list_destroy_all(struct UTUN_INSTANCE *inst) {
|
||||
if (!inst) return;
|
||||
int count = 0;
|
||||
while (inst->stcp_servers) {
|
||||
struct stcp_server *next = inst->stcp_servers->next;
|
||||
stcp_link_server_destroy(inst->stcp_servers);
|
||||
inst->stcp_servers = next;
|
||||
count++;
|
||||
}
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "stcp_server_list_destroy_all: destroyed %d servers", count);
|
||||
}
|
||||
|
||||
int stcp_server_list_count(struct UTUN_INSTANCE *inst) {
|
||||
if (!inst) return 0;
|
||||
int n = 0;
|
||||
for (struct stcp_server *s = inst->stcp_servers; s; s = s->next) n++;
|
||||
return n;
|
||||
}
|
||||
Reference in new issue
Block a user