2025-12-21 15:16:09 +01:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) Tristan Franssen, <tristanfranssen@strawhats.nl>.
|
|
|
|
|
*
|
|
|
|
|
* 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"
|
|
|
|
|
|
2025-12-21 20:39:41 +01:00
|
|
|
#if defined(__linux__)
|
2025-12-21 15:16:09 +01:00
|
|
|
#include <unistd.h>
|
|
|
|
|
#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);
|
|
|
|
|
|
2025-12-21 20:39:41 +01:00
|
|
|
#if defined(__linux__)
|
2025-12-21 15:28:02 +01:00
|
|
|
new_server->listening_socket = socket(domain, type, 0);
|
2025-12-21 15:16:09 +01:00
|
|
|
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;
|
|
|
|
|
|
2025-12-21 15:28:02 +01:00
|
|
|
new_server->listening_socket = socket(domain, type, 0);
|
2025-12-21 15:16:09 +01:00
|
|
|
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) {
|
2025-12-21 20:39:41 +01:00
|
|
|
#if defined(__linux__)
|
2025-12-21 15:16:09 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|