diff --git a/src/log.h b/src/log.h index 184450a..36fc033 100644 --- a/src/log.h +++ b/src/log.h @@ -1,8 +1,8 @@ #pragma once #include -#define log(context, severity, format, ...) printf("[%s][" severity "]: " format "\n", context ,##__VA_ARGS__) +#define log(context, severity, format, ...) printf("[%s/" severity "]: " format "\n", context ,##__VA_ARGS__) #define logDebug(context, format, ...) log(context, "DEBUG", format ,##__VA_ARGS__) #define logInfo(context, format, ...) log(context, "INFO", format ,##__VA_ARGS__) -#define logWarning(context, format, ...) log(context, "WARNING", format ,##__VA_ARGS__) +#define logWarn(context, format, ...) log(context, "WARN", format ,##__VA_ARGS__) #define logError(context, format, ...) log(context, "ERROR", format ,##__VA_ARGS__) diff --git a/src/server/ClientConnection.c b/src/server/ClientConnection.c index c4425b9..069d657 100644 --- a/src/server/ClientConnection.c +++ b/src/server/ClientConnection.c @@ -10,7 +10,7 @@ void ClientConnection_close(ClientConnection* conn){ } Result(ClientConnection*) ClientConnection_accept(ServerCredentials* server_credentials, - Socket sock_tcp, EndpointIPv4 client_end, u64 session_id) + ConnectionHandlerArgs* args) { Deferral(32); @@ -22,13 +22,14 @@ Result(ClientConnection*) ClientConnection_accept(ServerCredentials* server_cred ClientConnection_close(conn); ); - conn->client_end = client_end; - conn->session_id = session_id; + conn->client_end = args->client_end; + conn->session_id = args->session_id; + conn->authorized = false; conn->session_key = Array_alloc_size(AES_SESSION_KEY_SIZE); // correct session key will be received from client later Array_memset(conn->session_key, 0); - EncryptedSocketTCP_construct(&conn->sock, sock_tcp, NETWORK_BUFFER_SIZE, conn->session_key); - try_void(socket_TCP_enableAliveChecks_default(sock_tcp)); + EncryptedSocketTCP_construct(&conn->sock, args->accepted_socket, NETWORK_BUFFER_SIZE, conn->session_key); + try_void(socket_TCP_enableAliveChecks_default(args->accepted_socket)); // decrypt the rsa messages using server private key RSADecryptor rsa_dec; @@ -52,7 +53,7 @@ Result(ClientConnection*) ClientConnection_accept(ServerCredentials* server_cred // send PacketHeader and ServerHandshake over encrypted TCP socket ServerHandshake server_handshake = {0}; ServerHandshake_construct(&server_handshake, &packet_header, - session_id); + conn->session_id); try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &packet_header)); try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &server_handshake)); diff --git a/src/server/request_handlers/Login.c b/src/server/request_handlers/Login.c new file mode 100644 index 0000000..67fcdb7 --- /dev/null +++ b/src/server/request_handlers/Login.c @@ -0,0 +1,25 @@ +#include "request_handlers.h" + + +declare_RequestHandler(Login) +{ + Deferral(4); + logDebug(log_ctx, "requested %s", req_type_name); + + LoginRequest req = {0}; + try_void(PacketHeader_validateContentSize(req_head, sizeof(req))); + try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req)); + + //TODO: try authorize client + u64 user_id; + u64 landing_channel_id; + + LoginResponse res = {0}; + LoginResponse_construct(&res, res_head, user_id, landing_channel_id); + try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head)); + try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res)); + conn->authorized = true; + logInfo(log_ctx, "client authorized"); + + Return RESULT_VOID; +} diff --git a/src/server/request_handlers/Register.c b/src/server/request_handlers/Register.c new file mode 100644 index 0000000..a18c9eb --- /dev/null +++ b/src/server/request_handlers/Register.c @@ -0,0 +1,21 @@ +#include "request_handlers.h" + +declare_RequestHandler(Register) +{ + Deferral(4); + logDebug(log_ctx, "requested %s", req_type_name); + + RegisterRequest req = {0}; + try_void(PacketHeader_validateContentSize(req_head, sizeof(req))); + try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req)); + + //TODO: try register client + u64 user_id; + + RegisterResponse res = {0}; + RegisterResponse_construct(&res, res_head, user_id); + try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head)); + try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res)); + + Return RESULT_VOID; +} diff --git a/src/server/request_handlers/ServerPublicInfo.c b/src/server/request_handlers/ServerPublicInfo.c new file mode 100644 index 0000000..82d46c0 --- /dev/null +++ b/src/server/request_handlers/ServerPublicInfo.c @@ -0,0 +1,21 @@ +#include "request_handlers.h" + +declare_RequestHandler(ServerPublicInfo) +{ + Deferral(4); + logDebug(log_ctx, "requested %s", req_type_name); + + ServerPublicInfoRequest req = {0}; + try_void(PacketHeader_validateContentSize(req_head, sizeof(req))); + try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req)); + + //TODO: try find requested info + Array(u8) content; + + PacketHeader_construct(res_head, + PROTOCOL_VERSION, PacketType_ServerPublicInfoResponse, content.size); + try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head)); + try_void(EncryptedSocketTCP_send(&conn->sock, content)); + + Return RESULT_VOID; +} diff --git a/src/server/request_handlers/request_handlers.h b/src/server/request_handlers/request_handlers.h new file mode 100644 index 0000000..75528b2 --- /dev/null +++ b/src/server/request_handlers/request_handlers.h @@ -0,0 +1,27 @@ +#pragma once +#include "network/tcp-chat-protocol/v1.h" +#include "server/server.h" +#include "log.h" + + +Result(char*) __sendErrorMessage(ClientConnection* conn, PacketHeader* req_head, PacketHeader* res_head, + u32 msg_buf_size, cstr format, va_list argv); +Result(char*) sendErrorMessage(ClientConnection* conn, PacketHeader* req_head, PacketHeader* res_head, + u32 msg_buf_size, cstr format, ...) ATTRIBUTE_CHECK_FORMAT_PRINTF(5, 6); + + +#define declare_RequestHandler(TYPE) \ + Result(void) handleRequest_##TYPE( \ + cstr log_ctx, cstr req_type_name, \ + ClientConnection* conn, PacketHeader* req_head, PacketHeader* res_head) + +#define case_handleRequest(TYPE) \ + case PacketType_##TYPE##Request:\ + try_void(handleRequest_##TYPE(log_ctx, #TYPE, conn, &req_head, &res_head));\ + break; + +declare_RequestHandler(ServerPublicInfo); +declare_RequestHandler(Login); +declare_RequestHandler(Register); + + diff --git a/src/server/request_handlers/send_error.c b/src/server/request_handlers/send_error.c new file mode 100644 index 0000000..9c73583 --- /dev/null +++ b/src/server/request_handlers/send_error.c @@ -0,0 +1,31 @@ +#include "request_handlers.h" + +Result(char*) __sendErrorMessage(ClientConnection* conn, PacketHeader* req_head, PacketHeader* res_head, + u32 msg_buf_size, cstr format, va_list argv) +{ + Deferral(4); + //TODO: limit ErrorMessage size to fit into EncryptedSocketTCP.internal_buffer_size + Array(u8) err_buf = Array_alloc(u8, msg_buf_size); + bool err_complete = false; + Defer(if(!err_complete) free(err_buf.data)); + vsprintf(err_buf.data, format, argv); + err_buf.size = strlen(err_buf.data); + + PacketHeader_construct(res_head, + PROTOCOL_VERSION, PacketType_ErrorMessage, err_buf.size); + try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head)); + try_void(EncryptedSocketTCP_send(&conn->sock, err_buf)); + + err_complete = true; + Return RESULT_VALUE(p, err_buf.data); +} + +Result(char*) sendErrorMessage(ClientConnection* conn, PacketHeader* req_head, PacketHeader* res_head, + u32 msg_buf_size, cstr format, ...) +{ + va_list argv; + va_start(argv, format); + ResultVar(char*) err_msg = __sendErrorMessage(conn, req_head, res_head, msg_buf_size, format, argv); + va_end(argv); + return err_msg; +} diff --git a/src/server/request_handlers/template b/src/server/request_handlers/template new file mode 100644 index 0000000..360a4dc --- /dev/null +++ b/src/server/request_handlers/template @@ -0,0 +1,9 @@ +#include "request_handlers.h" + +declare_RequestHandler(T) +{ + Deferral(4); + logDebug(log_ctx, "requested %s", req_type_name); + + Return RESULT_VOID; +} diff --git a/src/server/server.c b/src/server/server.c index bd57f09..6bceb11 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -6,12 +6,7 @@ #include "config.h" #include "log.h" #include "network/tcp-chat-protocol/v1.h" - -typedef struct ConnectionHandlerArgs { - Socket accepted_socket; - EndpointIPv4 client_end; - u64 session_id; -} ConnectionHandlerArgs; +#include "server/request_handlers/request_handlers.h" static void* handle_connection(void* _args); static Result(void) try_handle_connection(ConnectionHandlerArgs* args, cstr log_ctx); @@ -50,7 +45,7 @@ static Result(void) parseConfig(cstr config_path){ Result(void) server_run(cstr server_endpoint_cstr, cstr config_path){ Deferral(32); - cstr log_ctx = "Server/MainThread"; + cstr log_ctx = "MainThread"; logInfo(log_ctx, "starting server"); logDebug(log_ctx, "parsing config"); try_void(parseConfig(config_path)); @@ -104,100 +99,39 @@ static Result(void) try_handle_connection(ConnectionHandlerArgs* args, cstr log_ logInfo(log_ctx, "session closed"); ); // establish encrypted connection - try(conn, p, - ClientConnection_accept( - _server_credentials, - args->accepted_socket, - args->client_end, - args->session_id - ) - ); + try(conn, p, ClientConnection_accept(_server_credentials, args)); logInfo(log_ctx, "session accepted"); - // handle unauthorized requests - bool ahtorized = false; - PacketHeader req_header = {0}; - PacketHeader res_header = {0}; - while(!ahtorized){ - sleepMsec(50); + // handle requests + PacketHeader req_head = {0}; + PacketHeader res_head = {0}; + while(true){ + sleepMsec(20); //TODO: implement some additional check if socket is dead or not - try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req_header)); - try_void(PacketHeader_validateMagic(&req_header)); - //TODO: move request handlers to separate functions - switch(req_header.type){ - default:{ - Array(u8) err_buf = Array_alloc(u8, 128); - bool err_complete = false; - Defer(if(!err_complete) free(err_buf.data)); - sprintf(err_buf.data, "Received unexpected packet of type %u", - req_header.type); - err_buf.size = strlen(err_buf.data); - - PacketHeader_construct(&res_header, - PROTOCOL_VERSION, PacketType_ErrorMessage, err_buf.size); - try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res_header)); - //TODO: limit ErrorMessage size to fit into EncryptedSocketTCP.internal_buffer_size - try_void(EncryptedSocketTCP_send(&conn->sock, err_buf)); - - err_complete = true; - Return RESULT_ERROR(err_buf.data, true); - } - - case PacketType_ServerPublicInfoRequest:{ - ServerPublicInfoRequest req = {0}; - try_void(PacketHeader_validateContentSize(&req_header, sizeof(req))); - try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req)); - - //TODO: try find requested info - Array(u8) content; - - PacketHeader_construct(&res_header, - PROTOCOL_VERSION, PacketType_ServerPublicInfoResponse, content.size); - try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res_header)); - try_void(EncryptedSocketTCP_send(&conn->sock, content)); - break; - } - - case PacketType_LoginRequest:{ - LoginRequest req = {0}; - try_void(PacketHeader_validateContentSize(&req_header, sizeof(req))); - try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req)); - - //TODO: try authorize client - u64 user_id; - u64 landing_channel_id; - - LoginResponse res = {0}; - LoginResponse_construct(&res, &res_header, user_id, landing_channel_id); - try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res_header)); - try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res)); - ahtorized = true; - logInfo(log_ctx, "client authorized"); - break; - } - - case PacketType_RegisterRequest:{ - RegisterRequest req = {0}; - try_void(PacketHeader_validateContentSize(&req_header, sizeof(req))); - try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req)); - - //TODO: try register client - u64 user_id; - - RegisterResponse res = {0}; - RegisterResponse_construct(&res, &res_header, user_id); - try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res_header)); - try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res)); - break; - } + try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req_head)); + try_void(PacketHeader_validateMagic(&req_head)); + + switch(req_head.type){ + // send error message and close connection + default: + try(char* err_msg, p, + sendErrorMessage( + conn, &req_head, &res_head, + 128, "Received unexpected packet of type %u", + req_head.type + ) + ); + logWarn(log_ctx, "%s", err_msg); + Return RESULT_VOID; + + // unauthorized requests + case_handleRequest(ServerPublicInfo); + case_handleRequest(Login); + case_handleRequest(Register); + // authorized requests } } - // handle authorized requests - while(true){ - sleepMsec(50); - } - Return RESULT_VOID; } diff --git a/src/server/server.h b/src/server/server.h index b4200a3..a3de4ae 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -16,10 +16,10 @@ Result(ServerCredentials*) ServerCredentials_create(cstr rsa_sk_base64, cstr rsa void ServerCredentials_free(ServerCredentials* cred); -typedef struct ServerMetadata { +typedef struct ServerInfo { str name; str description; -} ServerMetadata; +} ServerInfo; typedef struct ClientConnection { @@ -27,9 +27,17 @@ typedef struct ClientConnection { EndpointIPv4 client_end; Array(u8) session_key; EncryptedSocketTCP sock; + bool authorized; } ClientConnection; -Result(ClientConnection*) ClientConnection_accept(ServerCredentials* server_credentials, - Socket sock, EndpointIPv4 client_end, u64 session_id); + +typedef struct ConnectionHandlerArgs { + Socket accepted_socket; + EndpointIPv4 client_end; + u64 session_id; +} ConnectionHandlerArgs; + +Result(ClientConnection*) ClientConnection_accept(ServerCredentials* server_credentials, + ConnectionHandlerArgs* args); void ClientConnection_close(ClientConnection* conn); \ No newline at end of file