Refactor etcp_api: per-instance bindings with struct ETCP_BINDINGS

Changed from global bindings to per-instance bindings:

1. Added struct ETCP_BINDINGS in etcp_api.h:
   - Contains array of callbacks[ETCP_MAX_BINDINGS]
   - NULL means not bound

2. Updated UTUN_INSTANCE (utun_instance.h):
   - Added field: struct ETCP_BINDINGS api_bindings
   - Initialized to NULL by calloc in utun_instance_create

3. Updated API functions (etcp_api.h/c):
   - etcp_bind(inst, id, callback) - per-instance binding
   - etcp_unbind(inst, id) - per-instance unbinding
   - Removed etcp_api_init/etcp_api_deinit (not needed)
   - etcp_int_recv now uses conn->instance->api_bindings.callbacks[id]

4. Updated test_etcp_api.c:
   - Separate callbacks for server and client
   - Register via etcp_bind(server_instance, ...) and etcp_bind(client_instance, ...)
   - Removed global etcp_api_init/etcp_api_deinit calls

Test passes: All 100 packets transmitted in each direction.
This commit is contained in:
Evgeny committed 2026-02-14 01:39:55 +03:00
1 parent 1a7356e923
commit d694c92b1f
4 files changed
+124 -126

No files matched your search

+58 -48
View File
@@ -143,11 +143,12 @@ static int verify_packet_data(uint8_t* buffer, int size, int expected_seq) {
return 1;
}
// Универсальный callback для получения пакетов
// Определяет направление по соединению (client_conn vs server_conn)
static void recv_callback(struct ETCP_CONN* conn, struct ll_entry* entry) {
// Callback для получения пакетов на сервере (forward direction)
static void server_recv_callback(struct ETCP_CONN* conn, struct ll_entry* entry) {
(void)conn;
if (!entry || !entry->dgram || entry->len < PACKET_HEADER_SIZE + 1) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Received invalid packet");
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Server received invalid packet");
if (entry) {
queue_entry_free(entry);
queue_dgram_free(entry);
@@ -155,30 +156,39 @@ static void recv_callback(struct ETCP_CONN* conn, struct ll_entry* entry) {
return;
}
// Определяем направление по соединению
if (conn == server_conn) {
// Пакет пришел на сервер (forward direction: client->server)
if (verify_packet_data(entry->dgram, entry->len, packets_received_fwd)) {
packets_received_fwd++;
} else {
int seq = entry->dgram[1] | (entry->dgram[2] << 8);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Server packet verification failed, seq=%d, expected=%d",
seq, packets_received_fwd);
}
} else if (conn == client_conn) {
// Пакет пришел на клиент (backward direction: server->client)
if (verify_packet_data(entry->dgram, entry->len, packets_received_back)) {
packets_received_back++;
} else {
int seq = entry->dgram[1] | (entry->dgram[2] << 8);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Client packet verification failed, seq=%d, expected=%d",
seq, packets_received_back);
}
if (verify_packet_data(entry->dgram, entry->len, packets_received_fwd)) {
packets_received_fwd++;
} else {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Unknown connection %p", (void*)conn);
int seq = entry->dgram[1] | (entry->dgram[2] << 8);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Server packet verification failed, seq=%d, expected=%d",
seq, packets_received_fwd);
}
queue_entry_free(entry);
queue_dgram_free(entry);
}
// Callback для получения пакетов на клиенте (backward direction)
static void client_recv_callback(struct ETCP_CONN* conn, struct ll_entry* entry) {
(void)conn;
if (!entry || !entry->dgram || entry->len < PACKET_HEADER_SIZE + 1) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Client received invalid packet");
if (entry) {
queue_entry_free(entry);
queue_dgram_free(entry);
}
return;
}
if (verify_packet_data(entry->dgram, entry->len, packets_received_back)) {
packets_received_back++;
} else {
int seq = entry->dgram[1] | (entry->dgram[2] << 8);
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Client packet verification failed, seq=%d, expected=%d",
seq, packets_received_back);
}
// Освобождаем entry и dgram
queue_entry_free(entry);
queue_dgram_free(entry);
}
@@ -456,26 +466,12 @@ int main() {
debug_set_categories(DEBUG_CATEGORY_ALL);
utun_instance_set_tun_init_enabled(0);
// Инициализация ETCP API
etcp_api_init();
// Регистрируем callback для получения пакетов (один на все соединения)
if (etcp_bind(DATA_PACKET_ID, recv_callback) != 0) {
printf("Failed to bind callback\n");
etcp_api_deinit();
return 1;
}
printf("Callback registered for ID=%d\n", DATA_PACKET_ID);
printf("Creating server...\n");
ua = uasync_create();
server_instance = utun_instance_create(ua, "test_pkt_normalizer_etcp_server.conf");
if (!server_instance || init_connections(server_instance) < 0) {
printf("Failed to create server\n");
etcp_unbind(DATA_PACKET_ID);
etcp_api_deinit();
return 1;
}
printf("Server created, waiting for connection...\n\n");
@@ -484,11 +480,23 @@ int main() {
client_instance = utun_instance_create(ua, "test_pkt_normalizer_etcp_client.conf");
if (!client_instance || init_connections(client_instance) < 0) {
printf("Failed to create client\n");
etcp_unbind(DATA_PACKET_ID);
etcp_api_deinit();
return 1;
}
printf("Client created\n\n");
// Регистрируем callbacks для получения пакетов (per-instance)
if (etcp_bind(server_instance, DATA_PACKET_ID, server_recv_callback) != 0) {
printf("Failed to bind server callback\n");
return 1;
}
if (etcp_bind(client_instance, DATA_PACKET_ID, client_recv_callback) != 0) {
printf("Failed to bind client callback\n");
return 1;
}
printf("Callbacks registered for ID=%d (server=%p, client=%p)\n",
DATA_PACKET_ID, (void*)server_recv_callback, (void*)client_recv_callback);
printf("Sending %d packets in each direction via etcp_send...\n", TOTAL_PACKETS);
packet_timeout_id = uasync_set_timeout(ua, 1000, NULL, monitor_and_send);
@@ -499,16 +507,18 @@ int main() {
}
printf("\nCleaning up...\n");
if (packet_timeout_id) uasync_cancel_timeout(ua, packet_timeout_id);
if (global_timeout_id) uasync_cancel_timeout(ua, global_timeout_id);
// Отписываемся от callbacks
etcp_unbind(DATA_PACKET_ID);
// Деинициализация ETCP API
etcp_api_deinit();
if (server_instance) {
etcp_unbind(server_instance, DATA_PACKET_ID);
}
if (client_instance) {
etcp_unbind(client_instance, DATA_PACKET_ID);
}
if (server_instance) {
server_instance->running = 0;
utun_instance_destroy(server_instance);