Files

128 lines
4.0 KiB
C
Raw Permalink Normal View History

2026-09-08 10:35:16 +08:00
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "c_TcpServer.h"
#include "c_SocketStream.h"
#include "c_SockAddr.h"
#include "c_TcpSelectReactor.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 OnConnect(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, OnConnect, OnDataRequest, OnClose, OnError);
/* 2. Instantiate the Polymorphic POSIX poll Reactor multiplexer backend */
c_TcpReactor_t* reactor = NULL;
err = c_TcpSelectReactor_Create(&reactor, &server.allocator);
if (err != C_SUCCESS) {
fprintf(stderr, "[ERROR] Failed to instantiate c_TcpSelectReactor driver context\n");
c_TcpServer_Destroy(&server);
return -1;
}
/* 3. Bind poll multiplexer backend to server execution dispatcher context */
err = c_TcpServer_SetReactor(&server, 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;
}