cosms-core/src/networking/server.c

108 lines
No EOL
3.4 KiB
C

/*
* 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"
#if defined(__linux__)
#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);
#if defined(__linux__)
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(__linux__)
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;
}
}