@ -1,11 +1,12 @@
/**
* @ file etcp_api . c
* @ brief Р е а л и з а ц и я API д л я п р и ё м а - п е р е д а ч и п а к е т о в ч е р е з ETCP
* @ brief Р е а л и з а ц и я API д л я п р и ё м а - п е р е д а ч и п а к е т о в ч е р е з ETCP ( per - instance bindings )
*/
# include "etcp_api.h"
# include "etcp.h"
# include "pkt_normalizer.h"
# include "utun_instance.h"
# include "../lib/debug_config.h"
# include <string.h>
@ -13,43 +14,14 @@
# define ETCP_MAX_BINDINGS 256 /**< Максимальное количество bindings (по одному на каждый ID 0-255) */
/**
* @ brief С т р у к т у р а binding д л я ID
*/
struct ETCP_BINDING {
etcp_recv_fn callback ; /**< Коллбэк для обработки пакетов */
uint8_t active ; /**< Флаг активности binding */
} ;
// Таблица bindings (индекс = ID пакета)
static struct ETCP_BINDING g_bindings [ ETCP_MAX_BINDINGS ] ;
static int g_api_initialized = 0 ;
void etcp_api_init ( void ) {
if ( g_api_initialized ) {
return ;
}
memset ( g_bindings , 0 , sizeof ( g_bindings ) ) ;
g_api_initialized = 1 ;
DEBUG_INFO ( DEBUG_CATEGORY_ETCP_API , " ETCP API initialized " ) ;
}
void etcp_api_deinit ( void ) {
if ( ! g_api_initialized ) {
return ;
}
memset ( g_bindings , 0 , sizeof ( g_bindings ) ) ;
g_api_initialized = 0 ;
DEBUG_INFO ( DEBUG_CATEGORY_ETCP_API , " ETCP API deinitialized " ) ;
int etcp_bind ( struct UTUN_INSTANCE * inst , uint8_t id , etcp_recv_fn callback ) {
if ( ! inst ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP_API , " etcp_bind: NULL instance " ) ;
return - 1 ;
}
int etcp_bind ( uint8_t id , etcp_recv_fn callback ) {
if ( ! g_api_initialized ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP_API , " etcp_bind: API not initialized " ) ;
if ( id > = ETCP_MAX_BINDINGS ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP_API , " etcp_bind: Invalid ID %u (max=%d) " , id , ETCP_MAX_BINDINGS ) ;
return - 1 ;
}
@ -58,32 +30,36 @@ int etcp_bind(uint8_t id, etcp_recv_fn callback) {
return - 1 ;
}
if ( g _bindings[ id ] . active ) {
if ( inst - > api _bindings. callbacks [ id ] ! = NULL ) {
DEBUG_WARN ( DEBUG_CATEGORY_ETCP_API , " etcp_bind: ID %u already bound, overwriting " , id ) ;
}
g_bindings [ id ] . callback = callback ;
g_bindings [ id ] . active = 1 ;
inst - > api_bindings . callbacks [ id ] = callback ;
DEBUG_INFO ( DEBUG_CATEGORY_ETCP_API , " etcp_bind: Bound ID %u to callback %p " , id , ( void * ) callback ) ;
DEBUG_INFO ( DEBUG_CATEGORY_ETCP_API , " etcp_bind: Bound ID %u to callback %p for instance %p " ,
id , ( void * ) callback , ( void * ) inst ) ;
return 0 ;
}
int etcp_unbind ( uint8_t id ) {
if ( ! g_api_initialized ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP_API , " etcp_unbind: API not initialized " ) ;
int etcp_unbind ( struct UTUN_INSTANCE * inst , uint8_t id ) {
if ( ! inst ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP_API , " etcp_unbind: NULL instance " ) ;
return - 1 ;
}
if ( id > = ETCP_MAX_BINDINGS ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP_API , " etcp_unbind: Invalid ID %u " , id ) ;
return - 1 ;
}
if ( ! g_bindings [ id ] . active ) {
if ( inst - > api_bindings . callbacks [ id ] = = NULL ) {
DEBUG_WARN ( DEBUG_CATEGORY_ETCP_API , " etcp_unbind: ID %u not bound " , id ) ;
return - 1 ;
}
g_bindings [ id ] . callback = NULL ;
g_bindings [ id ] . active = 0 ;
inst - > api_bindings . callbacks [ id ] = NULL ;
DEBUG_INFO ( DEBUG_CATEGORY_ETCP_API , " etcp_unbind: Unbound ID %u " , id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_ETCP_API , " etcp_unbind: Unbound ID %u for instance %p " , id , ( void * ) inst ) ;
return 0 ;
}
@ -119,7 +95,7 @@ int etcp_send(struct ETCP_CONN* conn, struct ll_entry* entry) {
return - 1 ;
}
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP_API , " etcp_send: Packet queued for sending " ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP_API , " etcp_send: Packet queued for sending to [%s] " , conn - > log_name ) ;
return 0 ;
}
@ -152,20 +128,30 @@ void etcp_int_recv(struct ll_queue* queue, void* arg) {
// Получаем ID пакета (первый байт кодограммы)
uint8_t id = entry - > dgram [ 0 ] ;
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP_API , " etcp_recv: Received packet with ID %u from conn %p " ,
id , ( void * ) conn ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP_API , " etcp_recv: Received packet with ID %u from conn [%s] %p " ,
id , conn - > log_name , ( void * ) conn ) ;
// Получаем instance из соединения
struct UTUN_INSTANCE * inst = conn - > instance ;
if ( ! inst ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP_API , " etcp_recv: Connection has no instance " ) ;
queue_entry_free ( entry ) ;
queue_dgram_free ( entry ) ;
queue_resume_callback ( queue ) ;
return ;
}
// Ищем binding для этого ID
if ( id < ETCP_MAX_BINDINGS & & g_bindings [ id ] . active & & g_bindings [ id ] . callback ) {
// Ищем binding для этого ID в instance
if ( id < ETCP_MAX_BINDINGS & & inst - > api_bindings . callbacks [ id ] ! = NULL ) {
// Вызываем коллбэк
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP_API , " etcp_recv: Delivering packet ID %u to callback %p " ,
id , ( void * ) g_bindings [ id ] . callback ) ;
g_bindings [ id ] . callback ( conn , entry ) ;
id , ( void * ) inst - > api_bindings . callbacks [ id ] ) ;
inst - > api_bindings . callbacks [ id ] ( conn , entry ) ;
} else {
// Нет binding для этого ID - по умолчанию считаем что это данные (ID=0)
if ( g_bindings [ 0 ] . active & & g_bindings [ 0 ] . callback ) {
if ( inst - > api_bindings . callbacks [ 0 ] ! = NULL ) {
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCP_API , " etcp_recv: No binding for ID %u, routing to default (ID=0) " , id ) ;
g_bindings [ 0 ] . callback ( conn , entry ) ;
inst - > api_bindings . callbacks [ 0 ] ( conn , entry ) ;
} else {
// Нет default binding - освобождаем пакет
DEBUG_WARN ( DEBUG_CATEGORY_ETCP_API , " etcp_recv: No binding for ID %u and no default handler, dropping packet " , id ) ;