From 968321ab30cc5977e0701bb91aaec43c76d0b77e Mon Sep 17 00:00:00 2001 From: Mineplay Date: Sun, 21 Dec 2025 15:16:09 +0100 Subject: [PATCH] feat(server): added server creation and destruction --- include/cosms-core/networking/server.h | 60 +++++++++++++ src/file.c | 24 +++--- src/networking/server.c | 111 +++++++++++++++++++++++++ 3 files changed, 183 insertions(+), 12 deletions(-) create mode 100644 include/cosms-core/networking/server.h create mode 100644 src/networking/server.c diff --git a/include/cosms-core/networking/server.h b/include/cosms-core/networking/server.h new file mode 100644 index 0000000..87cab42 --- /dev/null +++ b/include/cosms-core/networking/server.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) Tristan Franssen, . + * + * This software is licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License in the file LICENSE or at + * http://www.apache.org/licenses/LICENSE-2.0 + */ +#ifndef COSMS_CORE_SERVER +#define COSMS_CORE_SERVER + +#if defined(_WIN32) +#include +#endif + +typedef enum { + COSMS_CORE_SERVER_OK = 0, + COSMS_CORE_SERVER_FAILED_TO_CREATE_SOCKET = -1, + COSMS_CORE_SERVER_COULD_NOT_BIND_ADDRESS = -2, + COSMS_CORE_SERVER_UNKNOWN_ERROR = -3 +} CosmsCoreServerError; + +struct cosms_core_server { + unsigned short port, domain; + int type; + + #if defined(__GNUC__) + int listening_socket; + #elif defined(_WIN32) + SOCKET listening_socket; + #endif +}; + +/** + * @brief Creates a new server of specified type. + * + * @param new_server Pointer to server struct (must not be NULL) + * @param domain The communication domain the server should use + * @param type of communication sementics to use + * @param port to run the server on + * @return COSMS_CORE_SERVER_OK on success, or a negative error code + */ +CosmsCoreServerError cosms_core_server_create(struct cosms_core_server *new_server, unsigned short domain, int type, unsigned short port); +/** + * @brief Stops and destroy's the server. + * + * @param current_server Pointer to an active server struct (must not be NULL) + * @return COSMS_CORE_SERVER_OK on success, or negative error code + */ +CosmsCoreServerError cosms_core_server_destroy(struct cosms_core_server *current_server); + +/** + * @brief Converts error code to a string that can be used for printing/logging errors. + * + * @param error The error code to convert to a string message. + * @return The error as a string on success, or NULL + */ +const char *cosms_core_server_error_string(CosmsCoreServerError error); + +#endif /* COSMS_CORE_SERVER */ \ No newline at end of file diff --git a/src/file.c b/src/file.c index 6e77ec9..aefaa3f 100644 --- a/src/file.c +++ b/src/file.c @@ -417,40 +417,40 @@ CosmsCoreFileError cosms_core_file_delete(const char *path) { const char *cosms_core_file_error_string(CosmsCoreFileError error) { switch(error) { case COSMS_CORE_FILE_OK: - return "cosms-file everything ok"; + return "cosms-core-file everything ok"; case COSMS_CORE_FILE_NOT_FOUND: - return "cosms-file path not found"; + return "cosms-core-file path not found"; case COSMS_CORE_FILE_NO_ACCESS: - return "cosms-file no access"; + return "cosms-core-file no access"; case COSMS_CORE_FILE_LIMIT_REACHED: - return "cosms-file to many open files"; + return "cosms-core-file to many open files"; case COSMS_CORE_FILE_COULD_NOT_READ_SIZE: - return "cosms-file failed to read size"; + return "cosms-core-file failed to read size"; case COSMS_CORE_FILE_UNKOWN_ERROR: - return "cosms-file unkown error occured"; + return "cosms-core-file unkown error occured"; case COSMS_CORE_FILE_FAILED_TO_ALLOCATE: - return "cosms-file failed to allocate memory"; + return "cosms-core-file failed to allocate memory"; case COSMS_CORE_FILE_FAILED_TO_READ: - return "cosms-file failed to read content of file"; + return "cosms-core-file failed to read content of file"; case COSMS_CORE_FILE_FAILED_TO_WRITE: - return "cosms-file failed to write content to file"; + return "cosms-core-file failed to write content to file"; case COSMS_CORE_FILE_STILL_OPEN: - return "cosms-file still open"; + return "cosms-core-file still open"; case COSMS_CORE_FILE_INVALID_FILE: - return "cosms-file invalid native file given"; + return "cosms-core-file invalid native file given"; case COSMS_CORE_FILE_INVALID_OPERATION: - return "cosms-file invalid operation for current file"; + return "cosms-core-file invalid operation for current file"; default: return NULL; diff --git a/src/networking/server.c b/src/networking/server.c new file mode 100644 index 0000000..4c849ff --- /dev/null +++ b/src/networking/server.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) Tristan Franssen, . + * + * This software is licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License in the file LICENSE or at + * http://www.apache.org/licenses/LICENSE-2.0 + */ +#include "cosms-core/networking/server.h" + +#if defined(__GNUC__) +#include +#include +#include +#include +#elif defined(_WIN32) +static int cosms_core_server_initialized_winsock_instances = 0; +#endif + +/** + * @brief Creates a new server of specified type. + */ +CosmsCoreServerError cosms_core_server_create(struct cosms_core_server *new_server, unsigned short domain, int type, unsigned short port) { + new_server->domain = domain; + new_server->type = type; + new_server->port = port; + + struct sockaddr_in address; + address.sin_family = domain; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(port); + + #if defined(__GNUC__) + new_server->listening_socket = socket(domain, type, port); + if (new_server->listening_socket == -1) { + return COSMS_CORE_SERVER_FAILED_TO_CREATE_SOCKET; + } + + int result = bind(new_server->listening_socket, (struct sockaddr*)&address, sizeof(address)); + if (result == -1) { + return COSMS_CORE_SERVER_COULD_NOT_BIND_ADDRESS; + } + #elif defined(_WIN32) + if (cosms_core_server_initialized_winsock_instances == 0) { + WSADATA data; + if (WSAStartup(MAKEWORD(2, 2), &data) == 0) { + return COSMS_CORE_SERVER_FAILED_TO_CREATE_SOCKET; + } + } + + cosms_core_server_initialized_winsock_instances += 1; + + new_server->listening_socket = socket(domain, type, port); + if (new_server->listening_socket == INVALID_SOCKET) { + return COSMS_CORE_SERVER_FAILED_TO_CREATE_SOCKET; + } + + int result = bind(new_server->listening_socket, (struct sockaddr*)&address, sizeof(address)); + if (result == SOCKET_ERROR) { + return COSMS_CORE_SERVER_COULD_NOT_BIND_ADDRESS; + } + #endif + + return COSMS_CORE_SERVER_OK; +} + +/** + * @brief Stops and destroy's the server. + */ +CosmsCoreServerError cosms_core_server_destroy(struct cosms_core_server *current_server) { + #if defined(__GNUC__) + int result = close(current_server->listening_socket); + if (result == -1) { + return COSMS_CORE_SERVER_UNKNOWN_ERROR; + } + #elif defined(_WIN32) + int result = closesocket(current_server->listening_socket); + if (result == SOCKET_ERROR) { + return COSMS_CORE_SERVER_UNKNOWN_ERROR; + } + + cosms_core_server_initialized_winsock_instances -= 1; + if (cosms_core_server_initialized_winsock_instances == 0) { + WSACleanup(); + } + #endif + + return COSMS_CORE_SERVER_OK; +} + +/** + * @brief Converts error code to a string that can be used for printing/logging errors. + */ +const char *cosms_core_server_error_string(CosmsCoreServerError error) { + switch (error) { + case COSMS_CORE_SERVER_OK: + return "cosms-core-server everything ok"; + + case COSMS_CORE_SERVER_FAILED_TO_CREATE_SOCKET: + return "cosms-core-server failed to create new socket"; + + case COSMS_CORE_SERVER_COULD_NOT_BIND_ADDRESS: + return "cosms-core-server could not bind address to new socket"; + + case COSMS_CORE_SERVER_UNKNOWN_ERROR: + return "cosms-core-server unkown error occured"; + + default: + return NULL; + } +} \ No newline at end of file