/* * 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 #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, 0); 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, 0); 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; } }