- Add libutun.a (noinst) containing all src/*.c except utun.c - utun binary now links libutun.a + libuasync.a - tests/Makefile.am simplified: all tests link libutun.a instead of manual .o file lists (removed ~70 lines of boilerplate) - Add db_sync module: distributed content-addressed DB with LMDB backend, peer-to-peer sync via etcp_router (svc 0x20) - etcp API: etcp_send_in_order(), etcp_clear_inflight_queues(), verify_packet_signature(), BBR getters - BBR: adaptive threshold (1/4 of pipe-min instead of hardcoded) - route_bgp/etcp_connect: STCP transport support in NODEINFO - conn_mgr: NODEINFO_ADDRS doc for nat_type/transport/proto fields - Cleanup: removed AUDIT_FINDINGS.txt, filelist.txt, nat.txt
112 lines
4.9 KiB
C
112 lines
4.9 KiB
C
/**
|
|
* @file etcp_api.c
|
|
* @brief ETCP API — send/bind/recv dispatch
|
|
*/
|
|
#include "etcp_api.h"
|
|
#include "etcp.h"
|
|
#include "pkt_normalizer.h"
|
|
#include "utun_instance.h"
|
|
#include "../lib/debug_config.h"
|
|
#include "../lib/mem.h"
|
|
#include <string.h>
|
|
|
|
#define DEBUG_CATEGORY_ETCP_API DEBUG_CATEGORY_ETCP
|
|
|
|
void etcp_conn_set_ready_cbk(struct ETCP_CONN* e, etcp_cbk_fn fn, void* arg) {
|
|
if (!e) return;
|
|
struct etcp_cbk_entry* entry = e->ready_cbks;
|
|
while (entry) { struct etcp_cbk_entry* next = entry->next; u_free(entry); entry = next; }
|
|
e->ready_cbks = NULL;
|
|
if (fn) etcp_conn_add_ready_cbk(e, fn, arg);
|
|
}
|
|
void etcp_conn_set_up_cbk(struct ETCP_CONN* e, etcp_cbk_fn fn, void* arg) {
|
|
if (!e) return;
|
|
struct etcp_cbk_entry* entry = e->up_cbks;
|
|
while (entry) { struct etcp_cbk_entry* next = entry->next; u_free(entry); entry = next; }
|
|
e->up_cbks = NULL;
|
|
if (fn) etcp_conn_add_up_cbk(e, fn, arg);
|
|
}
|
|
void etcp_conn_set_down_cbk(struct ETCP_CONN* e, etcp_cbk_fn fn, void* arg) {
|
|
if (!e) return;
|
|
struct etcp_cbk_entry* entry = e->down_cbks;
|
|
while (entry) { struct etcp_cbk_entry* next = entry->next; u_free(entry); entry = next; }
|
|
e->down_cbks = NULL;
|
|
if (fn) etcp_conn_add_down_cbk(e, fn, arg);
|
|
}
|
|
void etcp_set_new_conn_cbk(struct UTUN_INSTANCE* inst, etcp_cbk_fn fn, void* arg) {
|
|
if (!inst) return;
|
|
struct etcp_cbk_entry* entry = inst->new_conn_cbks;
|
|
while (entry) { struct etcp_cbk_entry* next = entry->next; u_free(entry); entry = next; }
|
|
inst->new_conn_cbks = NULL;
|
|
if (fn) etcp_add_new_conn_cbk(inst, fn, arg);
|
|
}
|
|
|
|
static void etcp_cbk_add_to_chain(struct etcp_cbk_entry** head, etcp_cbk_fn fn, void* arg) {
|
|
if (!head || !fn) return;
|
|
struct etcp_cbk_entry* e = u_malloc(sizeof(struct etcp_cbk_entry));
|
|
if (!e) return;
|
|
e->fn = fn; e->arg = arg; e->next = *head;
|
|
*head = e;
|
|
}
|
|
static void etcp_cbk_remove_from_chain(struct etcp_cbk_entry** head, etcp_cbk_fn fn, void* arg) {
|
|
if (!head || !fn) return;
|
|
struct etcp_cbk_entry** p = head;
|
|
while (*p) {
|
|
if ((*p)->fn == fn && (*p)->arg == arg) {
|
|
struct etcp_cbk_entry* rm = *p;
|
|
*p = rm->next; u_free(rm); return;
|
|
}
|
|
p = &(*p)->next;
|
|
}
|
|
}
|
|
|
|
void etcp_conn_add_ready_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg) { if (conn) etcp_cbk_add_to_chain(&conn->ready_cbks, fn, arg); }
|
|
void etcp_conn_remove_ready_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg) { if (conn) etcp_cbk_remove_from_chain(&conn->ready_cbks, fn, arg); }
|
|
void etcp_conn_add_up_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg) { if (conn) etcp_cbk_add_to_chain(&conn->up_cbks, fn, arg); }
|
|
void etcp_conn_remove_up_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg) { if (conn) etcp_cbk_remove_from_chain(&conn->up_cbks, fn, arg); }
|
|
void etcp_conn_add_down_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg) { if (conn) etcp_cbk_add_to_chain(&conn->down_cbks, fn, arg); }
|
|
void etcp_conn_remove_down_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg) { if (conn) etcp_cbk_remove_from_chain(&conn->down_cbks, fn, arg); }
|
|
void etcp_add_new_conn_cbk(struct UTUN_INSTANCE* inst, etcp_cbk_fn fn, void* arg) { if (inst) etcp_cbk_add_to_chain(&inst->new_conn_cbks, fn, arg); }
|
|
void etcp_remove_new_conn_cbk(struct UTUN_INSTANCE* inst, etcp_cbk_fn fn, void* arg) { if (inst) etcp_cbk_remove_from_chain(&inst->new_conn_cbks, fn, arg); }
|
|
|
|
void etcp_set_routing_exchange_state(struct ETCP_CONN* conn, uint8_t new_state) {
|
|
if (!conn) return;
|
|
conn->routing_exchange_active = new_state;
|
|
if (new_state >= 3 && conn->bgp_ready_cbk)
|
|
conn->bgp_ready_cbk(conn);
|
|
}
|
|
|
|
int etcp_bind(struct UTUN_INSTANCE* inst, uint8_t id, etcp_recv_fn callback) {
|
|
if (!inst || !callback || (unsigned)id >= ETCP_MAX_BINDINGS) return -1;
|
|
inst->api_bindings.callbacks[id] = callback;
|
|
return 0;
|
|
}
|
|
|
|
int etcp_unbind(struct UTUN_INSTANCE* inst, uint8_t id) {
|
|
if (!inst || (unsigned)id >= ETCP_MAX_BINDINGS) return -1;
|
|
inst->api_bindings.callbacks[id] = NULL;
|
|
return 0;
|
|
}
|
|
|
|
int etcp_send(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
|
if (!conn || !entry || !conn->send_input_q) return -1;
|
|
return queue_data_put(conn->send_input_q, entry);
|
|
}
|
|
|
|
void etcp_int_recv(struct ll_queue* queue, void* arg) {
|
|
struct ETCP_CONN* conn = (struct ETCP_CONN*)arg;
|
|
if (!queue || !conn) return;
|
|
struct ll_entry* e = queue_data_get(queue);
|
|
if (!e) { queue_resume_callback(queue); return; }
|
|
if (!e->dgram || e->len == 0) { queue_dgram_free(e); queue_entry_free(e); queue_resume_callback(queue); return; }
|
|
uint8_t id = e->dgram[0];
|
|
struct UTUN_INSTANCE* inst = conn->instance;
|
|
if (!inst) { queue_dgram_free(e); queue_entry_free(e); queue_resume_callback(queue); return; }
|
|
if (inst->api_bindings.callbacks[id])
|
|
inst->api_bindings.callbacks[id](conn, e);
|
|
else if (inst->api_bindings.callbacks[0])
|
|
inst->api_bindings.callbacks[0](conn, e);
|
|
else { queue_dgram_free(e); queue_entry_free(e); }
|
|
queue_resume_callback(queue);
|
|
}
|