diff --git a/include/cosms-core/networking/server.h b/include/cosms-core/networking/server.h index 6873339..9cc9a38 100644 --- a/include/cosms-core/networking/server.h +++ b/include/cosms-core/networking/server.h @@ -16,10 +16,13 @@ #endif typedef enum { + COSMS_CORE_SERVER_CONNECTION_CLOSED = 1, 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 + COSMS_CORE_SERVER_UNKNOWN_ERROR = -3, + COSMS_CORE_SERVER_TYPE_NOT_SUPPORTED = -4, + COSMS_CORE_SERVER_FAILED_TO_RECEIVE = -5 } CosmsCoreServerError; struct cosms_core_server { @@ -33,6 +36,17 @@ struct cosms_core_server { #endif }; +struct cosms_core_server_client { + struct sockaddr_in address; + int address_length; + + #if defined(__linux__) + int socket; + #elif defined(_WIN32) + SOCKET socket; + #endif +}; + /** * @brief Creates a new server of specified type. * @@ -51,6 +65,18 @@ CosmsCoreServerError cosms_core_server_create(struct cosms_core_server *new_serv */ CosmsCoreServerError cosms_core_server_destroy(struct cosms_core_server *current_server); +/** + * @brief Receives message from client. + * + * @param current_server Pointer to active server struct (must not be NULL) + * @param client Pointer to client struct (must be connected to server when using tcp) + * @param buffer to store the received message in (must not be NULL) + * @param buffer_size the size of the buffer to store the message in + * @param received_bytes the amount of bytes received from the client (can be NULL) + * @return COSMS_CORE_SERVER_OK or COSMS_CORE_SERVER_CONNECTION_CLOSED on success, or negative error code + */ +CosmsCoreServerError cosms_core_server_receive(struct cosms_core_server *current_server, struct cosms_core_server_client *client, char *buffer, unsigned int buffer_size, unsigned int *received_bytes); + /** * @brief Converts error code to a string that can be used for printing/logging errors. * diff --git a/src/networking/server.c b/src/networking/server.c index d107912..5ea9207 100644 --- a/src/networking/server.c +++ b/src/networking/server.c @@ -7,6 +7,7 @@ * http://www.apache.org/licenses/LICENSE-2.0 */ #include "cosms-core/networking/server.h" +#include #if defined(__linux__) #include @@ -27,17 +28,7 @@ CosmsCoreServerError cosms_core_server_create(struct cosms_core_server *new_serv 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 defined(_WIN32) if (cosms_core_server_initialized_winsock_instances == 0) { WSADATA data; if (WSAStartup(MAKEWORD(2, 2), &data) == 0) { @@ -46,6 +37,7 @@ CosmsCoreServerError cosms_core_server_create(struct cosms_core_server *new_serv } cosms_core_server_initialized_winsock_instances += 1; + #endif new_server->listening_socket = socket(domain, type, 0); if (new_server->listening_socket == INVALID_SOCKET) { @@ -53,10 +45,9 @@ CosmsCoreServerError cosms_core_server_create(struct cosms_core_server *new_serv } int result = bind(new_server->listening_socket, (struct sockaddr*)&address, sizeof(address)); - if (result == SOCKET_ERROR) { + if (result == -1) { return COSMS_CORE_SERVER_COULD_NOT_BIND_ADDRESS; } - #endif return COSMS_CORE_SERVER_OK; } @@ -85,11 +76,40 @@ CosmsCoreServerError cosms_core_server_destroy(struct cosms_core_server *current return COSMS_CORE_SERVER_OK; } +/** + * @brief Receives message from client. + */ +CosmsCoreServerError cosms_core_server_receive(struct cosms_core_server *current_server, struct cosms_core_server_client *client, char *buffer, unsigned int buffer_size, unsigned int *received_bytes) { + int bytes_received = 0; + if (current_server->type == SOCK_STREAM) { + bytes_received = recv(client->socket, buffer, buffer_size, 0); + } else { + bytes_received = recvfrom(current_server->listening_socket, buffer, buffer_size, 0, (struct sockaddr*)&client->address, &client->address_length); + } + + if (bytes_received == -1) { + return COSMS_CORE_SERVER_FAILED_TO_RECEIVE; + } + + if (bytes_received == 0) { + return COSMS_CORE_SERVER_CONNECTION_CLOSED; + } + + if (received_bytes != NULL) { + (*received_bytes) = bytes_received; + } + + 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_CONNECTION_CLOSED: + return "cosms-core-server connection was closed"; + case COSMS_CORE_SERVER_OK: return "cosms-core-server everything ok";