Files
cKit/Foundation/c_TcpServer.h
T
2026-09-08 10:35:16 +08:00

185 lines
6.6 KiB
C

#ifndef INCLUDED_C_TCPSERVER_H
#define INCLUDED_C_TCPSERVER_H
#ifndef INCLUDED_C_TYPES_H
#include <c_Types.h>
#endif /*INCLUDED_C_TYPES_H*/
#ifndef INCLUDED_C_ALLOCATOR_H
#include <c_Allocator.h>
#endif /*INCLUDED_C_ALLOCATOR_H*/
#ifndef INCLUDED_C_INSTREAM_H
#include <c_InStream.h>
#endif /*INCLUDED_C_INSTREAM_H*/
#ifndef INCLUDED_C_OUTSTREAM_H
#include <c_OutStream.h>
#endif /*INCLUDED_C_OUTSTREAM_H*/
#ifndef INCLUDED_C_SOCKET_H
#include <c_Socket.h>
#endif /*INCLUDED_C_SOCKET_H*/
#ifndef INCLUDED_C_SOCKETUTIL_H
#include <c_SocketUtil.h>
#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*/