ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
server.h File Reference

Go to the source code of this file.

Data Structures

struct  tcp_server_config_t
struct  tcp_server
 The useful part of tcp server is in event_loop, listen_socket, listen_socket6, running: together they describe what is pending, who owns it, and how much data is valid. Keep the object with its parent operation and use the parent cleanup path. More...

Typedefs

typedef struct tcp_client_entry tcp_client_entry_t
typedef struct tcp_server tcp_server_t

Functions

asciichat_error_t tcp_server_init (tcp_server_t *server, const tcp_server_config_t *config)
asciichat_error_t tcp_server_run (tcp_server_t *server)
void tcp_server_destroy (tcp_server_t *server)

Typedef Documentation

◆ tcp_client_entry_t

typedef struct tcp_client_entry tcp_client_entry_t

Internal TCP listener backend. Application connections belong to network_server_t.

Definition at line 13 of file include/ascii-chat/network/tcp/server.h.

◆ tcp_server_t

typedef struct tcp_server tcp_server_t

Definition at line 14 of file include/ascii-chat/network/tcp/server.h.

Function Documentation

◆ tcp_server_destroy()

void tcp_server_destroy ( tcp_server_t * server)

Definition at line 203 of file lib/network/tcp/server.c.

203 {
204 if (!server) {
205 return;
206 }
207
208 log_debug("Shutting down TCP server...");
209
210 // Signal server to stop
211 atomic_store_bool(&server->running, false);
212
213 // Close listen sockets
214 if (server->listen_socket != INVALID_SOCKET_VALUE) {
215 log_debug("Closing IPv4 listen socket");
216 socket_close(server->listen_socket);
217 server->listen_socket = INVALID_SOCKET_VALUE;
218 }
219
220 if (server->listen_socket6 != INVALID_SOCKET_VALUE) {
221 log_debug("Closing IPv6 listen socket");
222 socket_close(server->listen_socket6);
223 server->listen_socket6 = INVALID_SOCKET_VALUE;
224 }
225
226 log_debug("TCP listener shutdown complete");
227 NAMED_UNREGISTER(&server->running);
228 NAMED_UNREGISTER(server);
229}
#define NAMED_UNREGISTER(ptr)
Unregister a pointer.
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:595
atomic_t running
Server running flag (set false to shutdown).
socket_t listen_socket
IPv4 listen socket.
socket_t listen_socket6
IPv6 listen socket.

References tcp_server::listen_socket, tcp_server::listen_socket6, log_debug, NAMED_UNREGISTER, and tcp_server::running.

Referenced by network_server_destroy().

◆ tcp_server_init()

asciichat_error_t tcp_server_init ( tcp_server_t * server,
const tcp_server_config_t * config )

Definition at line 108 of file lib/network/tcp/server.c.

108 {
109 if (!server || !config) {
110 return SET_ERRNO(ERROR_INVALID_PARAM, "server or config is NULL");
111 }
112
113 // Initialize server state
114 memset(server, 0, sizeof(*server));
115 server->listen_socket = INVALID_SOCKET_VALUE;
116 server->listen_socket6 = INVALID_SOCKET_VALUE;
117 atomic_store_bool(&server->running, true);
118 server->config = *config; // Copy config
119
120 // Determine which IP versions to bind
121 bool should_bind_ipv4 = config->bind_ipv4;
122 bool should_bind_ipv6 = config->bind_ipv6;
123
124 // Bind IPv4 socket if requested
125 if (should_bind_ipv4) {
126 const char *ipv4_addr = (config->ipv4_address && config->ipv4_address[0] != '\0') ? config->ipv4_address : NULL;
127 server->listen_socket = bind_and_listen(ipv4_addr, AF_INET, config->port);
128
129 if (server->listen_socket == INVALID_SOCKET_VALUE) {
130 log_warn("Failed to bind IPv4 socket");
131 }
132 }
133
134 // Bind IPv6 socket if requested
135 if (should_bind_ipv6) {
136 const char *ipv6_addr = (config->ipv6_address && config->ipv6_address[0] != '\0') ? config->ipv6_address : NULL;
137 server->listen_socket6 = bind_and_listen(ipv6_addr, AF_INET6, config->port);
138
139 if (server->listen_socket6 == INVALID_SOCKET_VALUE) {
140 log_warn("Failed to bind IPv6 socket");
141 }
142 }
143
144 // Ensure at least one socket bound successfully
145 if (server->listen_socket == INVALID_SOCKET_VALUE && server->listen_socket6 == INVALID_SOCKET_VALUE) {
146 NAMED_UNREGISTER(&server->running);
147 return SET_ERRNO(ERROR_NETWORK_BIND, "Failed to bind any sockets (IPv4 and IPv6 both failed)");
148 }
149
150 /* Register server with named registry, identified by port */
152 snprintf(port_name, sizeof(port_name), "server:%d", server->config.port);
153 NAMED_REGISTER(server, port_name, "tcp_server", "0x%tx", NULL);
154
155 /* Register server's sync primitives with hierarchical naming */
156 NAMED_REGISTER_ATOMIC(&server->running, "is_running", (uintptr_t)(const void *)(server));
157
158 return ASCIICHAT_OK;
159}
#define SET_ERRNO(code,...)
#define NAMED_REGISTER_ATOMIC(a, name, parent_ptr)
Register an atomic_t with automatic format specifier.
#define NAMED_REGISTER(ptr, name, type, fmt, parent_ptr)
Register any pointer with base name, type, format spec, and location (auto-suffix).
@ ERROR_NETWORK_BIND
Definition error_codes.h:73
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
#define log_warn(...)
Log a WARN message.
Definition log/log.h:621
#define NETWORK_TCP_SERVER_PORT_NAME_BUFFER_SIZE
bool bind_ipv6
Whether to bind IPv6 socket.
bool bind_ipv4
Whether to bind IPv4 socket.
const char * ipv4_address
IPv4 bind address (NULL or empty = don't bind).
const char * ipv6_address
IPv6 bind address (NULL or empty = don't bind).
tcp_server_config_t config
Server configuration.

References ASCIICHAT_OK, tcp_server_config_t::bind_ipv4, tcp_server_config_t::bind_ipv6, tcp_server::config, ERROR_INVALID_PARAM, ERROR_NETWORK_BIND, tcp_server_config_t::ipv4_address, tcp_server_config_t::ipv6_address, tcp_server::listen_socket, tcp_server::listen_socket6, log_warn, NAMED_REGISTER, NAMED_REGISTER_ATOMIC, NAMED_UNREGISTER, NETWORK_TCP_SERVER_PORT_NAME_BUFFER_SIZE, tcp_server_config_t::port, tcp_server::running, and SET_ERRNO.

Referenced by network_server_create().

◆ tcp_server_run()

asciichat_error_t tcp_server_run ( tcp_server_t * server)

Definition at line 193 of file lib/network/tcp/server.c.

193 {
194 if (!server) {
195 return SET_ERRNO(ERROR_INVALID_PARAM, "server is NULL");
196 }
197
198 if (!server->config.event_handler)
199 return SET_ERRNO(ERROR_INVALID_PARAM, "TCP event handler is required");
200 return tcp_server_run_events(server);
201}
platform_event_accept_fn event_handler
Required asynchronous accept handler.

References tcp_server::config, ERROR_INVALID_PARAM, tcp_server_config_t::event_handler, and SET_ERRNO.

Referenced by network_server_run().