#include #include #include #include "c_TcpServer.h" #include "c_SocketStream.h" #include "c_SockAddr.h" #include "c_TcpPollReactor.h" #if defined(_WIN32) || defined(_WIN64) #pragma comment(lib, "ws2_32.lib") #endif /** * @brief Reactor connection event callback. * Fired automatically by c_TcpPollReactor whenever an inbound client connects. */ static bool OnPollTimeServerConnect(c_TcpServer_t* server, c_socket_t client_sock, const c_SockAddr_t* peer_addr, void* args) { (void)args; char ip_str[INET6_ADDRSTRLEN] = {0}; uint16_t port = c_SockAddr_GetPort(peer_addr); if (c_SockAddr_ToString(peer_addr, ip_str, sizeof(ip_str)) == C_ERR_OK) { printf("[POLL INFO] Accepted client connection from: %s:%d\n", ip_str, (int)port); } return true; } static bool OnDataRequest(c_TcpServer_t* server, c_socket_t s , void* args) { (void)args; char host[32]={0}; char port[9]={0}; c_SocketUtil_GetNameInfoForSocket(s, host, sizeof(host), port, sizeof(port)); printf("Request from %s:%s\n", host, port); char buffer[1024] = {0}; int err = recv(s, buffer, sizeof(buffer), 0); printf("body: %.*s\n", err, buffer); /* 1. Wrap raw client socket inside polymorphic Output Stream pipeline */ time_t raw_time = time(NULL); struct tm* time_info = localtime(&raw_time); char time_buffer[64] = {0}; strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%d %H:%M:%S\n", time_info); /* 3. Flush plaintext string down into the polymorphic socket driver channel */ c_size_t bytes_written = 0; c_SocketUtil_Send(s, time_buffer, strlen(time_buffer), &bytes_written); if (strncmp(buffer, "STOP", 4)==0) { server->is_running = false; return false; } return true; } static void OnClose(c_TcpServer_t* server, c_socket_t s, void* args) { (void)args; char host[32]={0}; char port[9]={0}; c_SocketUtil_GetNameInfoForSocket(s, host, sizeof(host), port, sizeof(port)); printf("Client Closed from %s:%s\n", host, port); } static void OnError(c_TcpServer_t* server, c_socket_t s, int err, void* args) { (void)args; char host[32]={0}; char port[9]={0}; c_SocketUtil_GetNameInfoForSocket(s, host, sizeof(host), port, sizeof(port)); printf("[ERROR] Server %s:%s ON %s\n", host, port, c_TcpServer_GetErrorString(err)); } int main(void) { c_Socket_Init(); uint16_t server_port = 1313; c_TcpServer_t server; printf("[SERVER] Initializing Poll-driven Time Server on port %d...\n", server_port); /* 1. Spin up master server listener instance with your explicit flags signature layout */ c_err_t err = c_TcpServer_Init(&server, AF_INET, server_port, 512, NULL); if (err != C_SUCCESS) { fprintf(stderr, "[ERROR] Failed to open master server listening socket\n"); return -1; } c_TcpServer_SetCallbacks(&server, OnPollTimeServerConnect, OnDataRequest, OnClose, OnError); /* 2. Instantiate the Polymorphic POSIX poll Reactor multiplexer backend */ c_TcpReactor_t* poll_reactor = NULL; err = c_TcpPollReactor_Create(&poll_reactor, &server.allocator); if (err != C_SUCCESS) { fprintf(stderr, "[ERROR] Failed to instantiate c_TcpPollReactor driver context\n"); c_TcpServer_Destroy(&server); return -1; } /* 3. Bind poll multiplexer backend to server execution dispatcher context */ err = c_TcpServer_SetReactor(&server, poll_reactor); if (err != C_SUCCESS) { fprintf(stderr, "[ERROR] Failed to wire reactor driver onto dispatcher context\n"); c_TcpServer_Destroy(&server); return -1; } printf("[SERVER] Multiplexed Time Server is fully running via c_TcpPollReactor...\n"); /* 4. Non-recursive event loop dispatcher loop (Polled with 1000ms heartbeat intervals) */ while (server.is_running) { c_TcpServer_Run(&server, 1000, NULL); } /* 5. Complete cleanup resource teardowns */ c_TcpServer_Destroy(&server); printf("[SERVER] Time Server cleanly terminated.\n"); c_Socket_Destroy(); return 0; }