From 1cc2ef41d16ee9881def2cdc466c3b5400d04eac Mon Sep 17 00:00:00 2001 From: "Nikita Tyukalov, ASUS, Linux" Date: Tue, 24 Mar 2026 19:45:17 +0300 Subject: [PATCH] Implemented server --- main.c | 45 ++++++++++++++++++++++++++++++ server.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ server.h | 36 ++++++++++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 server.c create mode 100644 server.h diff --git a/main.c b/main.c index 55c36f2..665cdee 100644 --- a/main.c +++ b/main.c @@ -8,12 +8,14 @@ #include #include "event_loop.h" +#include "server.h" /* * Data */ static bool _to_work = true; static int _sig_fd = -1; +static int _server_fd = -1; /* * Private API @@ -58,10 +60,40 @@ static bool signals_init() { return true; } +// Finalize signals. static void signals_deinit() { close(_sig_fd); } +// Initialize the server. +// Returns: +// - true on success +static bool server_init() { + _server_fd = server_open("0.0.0.0", 20070); + if (_server_fd == -1) { + return false; + } + struct epoll_event ev; + ev.data.fd = _server_fd; + ev.events = EPOLLIN; + bool loop_res = loop_ctl( + EPOLL_CTL_ADD, + _server_fd, + &ev + ); + if (!loop_res) { + server_close(); + printf("[!] loop_ctl failed\n"); + return false; + } + return true; +} + +// Finalize the server. +static void server_deinit() { + server_close(); +} + /* * Callbacks and main */ @@ -71,6 +103,13 @@ static void on_fd_event(int fd, uint32_t events) { if (fd == _sig_fd) { _to_work = false; } + // Server event + else if (fd == _server_fd) { + if (!server_event(_server_fd)) { + printf("[!] server_event failed\n"); + _to_work = false; + } + } else { printf("[!] Event has happened on an unknown file descriptor\n"); } @@ -84,6 +123,11 @@ int main(int argc, char **argv) { loop_deinit(); return 1; } + if (!server_init()) { + signals_deinit(); + loop_deinit(); + return 1; + } while (_to_work) { if (!loop_wait()) { @@ -93,6 +137,7 @@ int main(int argc, char **argv) { printf("--- loop ---\n"); } + server_close(); signals_deinit(); loop_deinit(); return 0; diff --git a/server.c b/server.c new file mode 100644 index 0000000..8a2031a --- /dev/null +++ b/server.c @@ -0,0 +1,83 @@ +#include "server.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * Macros + */ +#define LISTEN_BACKLOG (2048) + +/* + * Data + */ +static int _fd = -1; + +/* + * Private API + */ +bool _accept() { + close(accept(_fd, 0, 0)); + return true; +} + +/* + * Public API + */ +int server_open(const char* host, int port) { + struct hostent *he = gethostbyname(host); + if (!he) { + printf("[!] gethostbyname failed: %d (h_errno)\n", h_errno); + return -1; + } + _fd = socket( + AF_INET, + SOCK_STREAM | SOCK_NONBLOCK, + IPPROTO_TCP + ); + if (_fd == -1) { + printf("[!] socket failed: %d\n", errno); + return -1; + } + const int opt = 1; + if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { + close(_fd); + printf("[!] setsockopt failed: %d\n", errno); + return -1; + } + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htobe16(port); + memcpy(&addr.sin_addr, he->h_addr, he->h_length); + if (bind(_fd, (const void *)&addr, sizeof(addr)) == -1) { + close(_fd); + printf("[!] bind failed: %d\n", errno); + return -1; + } + if (listen(_fd, LISTEN_BACKLOG) == -1) { + close(_fd); + printf("[!] listen failed: %d\n", errno); + return -1; + } + return _fd; +} + +void server_close() { + shutdown(_fd, SHUT_RDWR); + close(_fd); +} + +bool server_event(uint32_t events) { + if (events & EPOLLIN) { + return _accept(); + } + // we assume any event other than EPOLLIN is error + return false; +} diff --git a/server.h b/server.h new file mode 100644 index 0000000..0787b67 --- /dev/null +++ b/server.h @@ -0,0 +1,36 @@ +#ifndef __SERVER_H +#define __SERVER_H + +#include +#include + +// Open the server. +// Parameters: +// - host - hostname or IP address (domain names are OK) +// - port - port to use +// Returns: +// - -1 on failure +// - file descriptor of the server on success +// Remarks: +// - call only after server_init +// - you must add returned fd to epoll with EPOLLIN events +int server_open(const char* host, int port); + +// Close the server. +// Remarks: +// - the socket is automatically removed from epoll +void server_close(); + +// Notify the server that an event happened on its socket. +// Returns: +// - true on success +// - false on failure +// Remarks: +// - the server accepts the connection and starts managing +// it with connection.h +// - you should stop close the server if this function +// returns false +bool server_event(uint32_t events); + + +#endif