etcp tcp: статус-флоу как в UDP + упрощение STCP API
- etcp_link_enter_ready_tcp: убраны прямые записи got_initial_pkt/initialized/ links_up/tx_state и fire UP/INIT; переход через etcp_conn_ready + loadbalancer_link_ready (как в UDP INIT-обработчиках) - tcp_server_on_link: убран дублирующий gop/session-блок (проверка в etcp_link_enter_ready_tcp единообразно), sc_init_ctx перед sc_set_peer_public_key (фикс ctx not initialized) - stcp_link_connect(etcp_link, addr, port) вместо config-структуры; stcp_conn.etcp_conn для live-чтения gop/session_id при handshake
This commit is contained in:
1 parent
867f48c125
commit
7a40a1b0a8
11 files changed
+129
-177
No files matched your search
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -16,6 +16,7 @@ extern "C" {
|
||||
#include <stdint.h>
|
||||
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
link->inst = inst;
|
||||
link->ua = inst->ua;
|
||||
link->etcp_conn = etcp;
|
||||
link->etcp_link = etcp_link;
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user