#include #include "c_SocketStream.h" c_err_t c_TcpServer_Init(c_TcpServer_t* self, int family, uint16_t port, int backlog, c_Allocator_t* allocator) { if (!self) return C_ERR_PARAM; self->allocator = allocator ? *allocator : c_DefaultAllocator; self->listen_sock = C_INVALID_SOCKET; self->reactor = NULL; self->is_running = C_FALSE; /* 2. Instantiate the listening socket descriptor using the explicit parameter map */ self->listen_sock = socket(family, SOCK_STREAM, IPPROTO_IP); if (self->listen_sock == C_INVALID_SOCKET) return C_ERR_FAIL; /* 3. Enable SO_REUSEADDR to avoid socket bind crashes on rapid restarts */ c_Socket_SetReuseAddr(self->listen_sock, true); /* 4. Configure dual-stack sockaddr union variants based on the address family */ c_SockAddr_t bind_addr; if (c_SockAddr_Init(&bind_addr, family, 0, port)!=C_ERR_OK) { c_TcpServer_Destroy(self); return C_ERR_FAIL; } if (family == AF_INET6) { /* Optional optimization: allow dual-stack IPv4 mapping on the IPv6 socket if supported */ c_Socket_SetIPV6Only(self->listen_sock, false); } /* 6. Bind the structural endpoint socket down to the network stack */ if (c_SocketUtil_BindWithSockAddr(self->listen_sock, &bind_addr) != C_ERR_OK) { c_TcpServer_Destroy(self); return C_ERR_FAIL; } /* 7. Switch the socket handle to listener mode with a generous backlog size */ if (listen(self->listen_sock, backlog) == C_SOCKET_ERROR) { c_TcpServer_Destroy(self); return C_ERR_FAIL; } self->is_running = C_TRUE; return C_SUCCESS; } c_err_t c_TcpServer_SetReactor(c_TcpServer_t* self, c_TcpReactor_t* reactor) { if (!self || !reactor) return C_ERR_PARAM; self->reactor = reactor; /* Automatically add our master listener socket to watch for read/inbound events */ return c_TcpReactor_Add(self->reactor, self->listen_sock, 1); } c_err_t c_TcpServer_Run(c_TcpServer_t* self, long timeout_ms, void* args) { if (!self || !self->reactor || !self->is_running) return C_ERR_PARAM; return c_TcpReactor_Poll(self->reactor, timeout_ms, self, args); } void c_TcpServer_Destroy(c_TcpServer_t* self) { if (!self) return; self->is_running = C_FALSE; if (self->reactor) { c_TcpReactor_Destroy(self->reactor); self->reactor = NULL; } if (self->listen_sock != C_INVALID_SOCKET) { c_Socket_Close(self->listen_sock); } } const char* c_TcpServer_GetErrorString(int code) { switch (code) { case C_ERR_OK: { return "OK"; } case C_TCPSERVER_ERR_ON_ACCEPT: { return "ACCEPT"; } case C_TCPSERVER_ERR_ON_POLL: { return "POLL"; } case C_TCPSERVER_ERR_ON_POLLERR: { return "POLLERR"; } case C_TCPSERVER_ERR_ON_RECV: { return "RECV"; } default: { return "UNKNOWN"; } } }