#ifndef INCLUDED_C_TCPSERVER_H #define INCLUDED_C_TCPSERVER_H #ifndef INCLUDED_C_TYPES_H #include #endif /*INCLUDED_C_TYPES_H*/ #ifndef INCLUDED_C_ALLOCATOR_H #include #endif /*INCLUDED_C_ALLOCATOR_H*/ #ifndef INCLUDED_C_INSTREAM_H #include #endif /*INCLUDED_C_INSTREAM_H*/ #ifndef INCLUDED_C_OUTSTREAM_H #include #endif /*INCLUDED_C_OUTSTREAM_H*/ #ifndef INCLUDED_C_SOCKET_H #include #endif /*INCLUDED_C_SOCKET_H*/ #ifndef INCLUDED_C_SOCKETUTIL_H #include #endif /*INCLUDED_C_SOCKETUTIL_H*/ /* ------------------------------------------------------------------------------------------------------------------ */ /* */ #define C_TCPSERVER_ERR_ON_POLL 1001 #define C_TCPSERVER_ERR_ON_ACCEPT 1002 #define C_TCPSERVER_ERR_ON_POLLERR 1003 #define C_TCPSERVER_ERR_ON_RECV 1004 /* ------------------------------------------------------------------------------------------------------------------ */ /* */ typedef struct c_TcpServer_t c_TcpServer_t; typedef struct c_TcpReactor_t c_TcpReactor_t; /** * @brief Unified event-driven user callback signature. * @param client_sock The accepted socket descriptor for the client. * @param peer_addr Unified dual-stack address structure containing client peer details. */ typedef bool (*c_TcpServer_OnConnect_t)(c_TcpServer_t* server, c_socket_t client_sock, const c_SockAddr_t* peer_addr, void* args); /** * @brief Event-driven user data processing callback matched exactly to your layout signature. * @param s The raw socket descriptor exhibiting unread data availability. * @return C_TRUE to keep monitoring the client; C_FALSE to break and close the connection. */ typedef bool (*c_TcpServer_OnRequest_t)(c_TcpServer_t* server, c_socket_t s, void* args); /** * @brief Event-driven user callback fired whenever an active client disconnects or encounters an error. * @param s The raw socket descriptor of the client being terminated. * @param args Custom user context parameters pointer. */ typedef void (*c_TcpServer_OnDisconnect_t)(c_TcpServer_t* server, c_socket_t s, void* args); /** * @brief Event-driven user callback fired whenever an operational network error is caught. * @param s The socket descriptor associated with the failure (Can be server->listen_sock or a client handle). * @param error_code Internal unified framework error mapping code. * @param args Custom user context parameters pointer. */ typedef void (*c_TcpServer_OnError_t)(c_TcpServer_t* server, c_socket_t s, c_err_t error_code, void* args); /* Virtual Interface Table for I/O Multiplexing Engines */ typedef struct { c_err_t (*add)(c_TcpReactor_t* self, c_socket_t sock, uint32_t events); c_err_t (*remove)(c_TcpReactor_t* self, c_socket_t sock); c_err_t (*poll)(c_TcpReactor_t* self, long timeout_ms, c_TcpServer_t* server, void* args); void (*destroy)(c_TcpReactor_t* self); } c_TcpReactorVtbl_t; struct c_TcpReactor_t { const c_TcpReactorVtbl_t* vtbl; }; struct c_TcpServer_t { c_socket_t listen_sock; /* Master server listening socket descriptor */ c_TcpReactor_t* reactor; /* Polymorphic multiplexing backend driver link */ c_TcpServer_OnConnect_t fnOnConnect; /* Connection accept callback hook */ c_TcpServer_OnRequest_t fnOnRequest; /* Data incoming available callback hook */ c_TcpServer_OnDisconnect_t fnOnDisconnect; /* Disconnect termination event hook */ c_TcpServer_OnError_t fnOnError; /* Network operational error event hook */ c_bool_t is_running; /* Server master thread loop state flag */ c_Allocator_t allocator; /* Deep copy of the user-provided allocator */ }; /* ------------------------------------------------------------------------------------------------------------------ */ /* */ C_STATIC_FORCE_INLINE c_err_t c_TcpReactor_Add(c_TcpReactor_t* self, c_socket_t sock, uint32_t events) { if (!self || !self->vtbl || !self->vtbl->add || !c_Socket_IsValid(sock)) return C_ERR_PARAM; return self->vtbl->add(self, sock, events); } C_STATIC_FORCE_INLINE c_err_t c_TcpReactor_Remove(c_TcpReactor_t* self, c_socket_t sock) { if (!self || !self->vtbl || !self->vtbl->remove || !c_Socket_IsValid(sock)) return C_ERR_PARAM; return self->vtbl->remove(self, sock); } C_STATIC_FORCE_INLINE c_err_t c_TcpReactor_Poll(c_TcpReactor_t* self, long timeout_ms, c_TcpServer_t* server, void* args) { if (!self || !self->vtbl || !self->vtbl->poll || !server) return C_ERR_PARAM; return self->vtbl->poll(self, timeout_ms, server, args); } C_STATIC_FORCE_INLINE void c_TcpReactor_Destroy(c_TcpReactor_t* self) { if (!self || !self->vtbl || !self->vtbl->destroy) return; self->vtbl->destroy(self); } /* ------------------------------------------------------------------------------------------------------------------ */ /* */ /* Core Lifecycle Primitives */ c_err_t c_TcpServer_Init(c_TcpServer_t* self, int family, uint16_t port, int backlog, c_Allocator_t* allocator) ; void c_TcpServer_Destroy(c_TcpServer_t* self); /** * @brief Explicitly binds a specific I/O multiplexing reactor back-end driver. */ c_err_t c_TcpServer_SetReactor(c_TcpServer_t* self, c_TcpReactor_t* reactor); C_STATIC_FORCE_INLINE c_err_t c_TcpServer_SetCallbacks(c_TcpServer_t* self , c_TcpServer_OnConnect_t on_connect , c_TcpServer_OnRequest_t on_data , c_TcpServer_OnDisconnect_t on_disconnect , c_TcpServer_OnError_t on_error) { if (!self) return C_ERR_PARAM; self->fnOnConnect = on_connect; self->fnOnRequest = on_data; self->fnOnDisconnect = on_disconnect; self->fnOnError = on_error; return C_SUCCESS; } C_STATIC_FORCE_INLINE void c_TcpServer_SetOnConnect(c_TcpServer_t* self, c_TcpServer_OnConnect_t on_connect) { if (!self) return; self->fnOnConnect = on_connect; } C_STATIC_FORCE_INLINE void c_TcpServer_SetOnData(c_TcpServer_t* self, c_TcpServer_OnRequest_t on_data) { if (!self) return; self->fnOnRequest = on_data; } C_STATIC_FORCE_INLINE void c_TcpServer_SetOnDisconnect(c_TcpServer_t* self, c_TcpServer_OnDisconnect_t on_disconnect) { if (!self) return; self->fnOnDisconnect = on_disconnect; } C_STATIC_FORCE_INLINE void c_TcpServer_SetOnError(c_TcpServer_t* self, c_TcpServer_OnError_t on_error) { if (!self) return; self->fnOnError = on_error; } /** * @brief Non-recursively runs the multiplexed event polling dispatcher loop layer. */ c_err_t c_TcpServer_Run(c_TcpServer_t* self, long timeout_ms, void* args); const char* c_TcpServer_GetErrorString(int code); #endif /*INCLUDED_C_TCPSERVER_H*/