diff --git a/src/cli/ClientCLI/ClientCLI.c b/src/cli/ClientCLI/ClientCLI.c index a2357c9..5f6bbcc 100644 --- a/src/cli/ClientCLI/ClientCLI.c +++ b/src/cli/ClientCLI/ClientCLI.c @@ -1,8 +1,8 @@ +#include "tlibc/filesystem.h" +#include "tcp-chat/common_constants.h" #include "cli/ClientCLI/ClientCLI.h" #include "cli/term.h" -#include "tcp-chat/common_constants.h" -#include "tlibc/time.h" -#include "tlibc/filesystem.h" +#include "network/tcp-chat-protocol/v1.h" static const str greeting_art = STR( " ^,,^ ╱|\n" @@ -108,11 +108,11 @@ static Result(void) ClientCLI_askUserNameAndPassword(str* username_out, str* pas try_void(term_readLine(username_buf.data, username_buf.size)); username = str_from_cstr(username_buf.data); str_trim(&username, true); - if(username.size < USERNAME_SIZE_MIN || username.size > USERNAME_SIZE_MAX){ - printf("ERROR: username length (in bytes) must be >= %i and <= %i\n", - USERNAME_SIZE_MIN, USERNAME_SIZE_MAX); + str name_error_str = validateUsername_str(username); + if(name_error_str.data){ + printf("ERROR: "FMT_str"\n", + name_error_str.size, name_error_str.data); } - //TODO: validate username characters else break; } diff --git a/src/cli/ClientCLI/ClientCLI.h b/src/cli/ClientCLI/ClientCLI.h index 02b8f7d..e6b7570 100644 --- a/src/cli/ClientCLI/ClientCLI.h +++ b/src/cli/ClientCLI/ClientCLI.h @@ -4,7 +4,7 @@ #include "tlibc/collections/List.h" #include "tcp-chat/client.h" #include "db/idb.h" -#include "cli/ClientCLI/db_tables.h" +#include "db/tables.h" typedef struct ClientCLI { Client* client; diff --git a/src/cli/ClientCLI/db_tables.h b/src/cli/ClientCLI/db_tables.h deleted file mode 100644 index 6f7ff61..0000000 --- a/src/cli/ClientCLI/db_tables.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "tcp-chat/common_constants.h" -#include "tlibc/time.h" - -typedef struct ServerInfo { - u16 address_len; - char address[HOSTADDR_SIZE_MAX + 1]; - u32 pk_base64_len; - char pk_base64[PUBLIC_KEY_BASE64_SIZE_MAX + 1]; - u16 name_len; - char name[SERVER_NAME_SIZE_MAX + 1]; - u16 desc_len; - char desc[SERVER_DESC_SIZE_MAX + 1]; -} ATTRIBUTE_ALIGNED(16*1024) ServerInfo; diff --git a/src/db/tables.h b/src/db/tables.h new file mode 100644 index 0000000..036f008 --- /dev/null +++ b/src/db/tables.h @@ -0,0 +1,44 @@ +#pragma once +#include "tcp-chat/common_constants.h" +#include "tlibc/time.h" + + +typedef struct UserInfo { + u16 name_len; + char name[USERNAME_SIZE_MAX + 1]; // null-terminated + u8 token[PASSWORD_HASH_SIZE]; // token is hashed again on server side + DateTime registration_time_utc; +} ATTRIBUTE_ALIGNED(256) UserInfo; + + +typedef struct ServerInfo { + u16 address_len; + char address[HOSTADDR_SIZE_MAX + 1]; + u32 pk_base64_len; + char pk_base64[PUBLIC_KEY_BASE64_SIZE_MAX + 1]; + u16 name_len; + char name[SERVER_NAME_SIZE_MAX + 1]; + u16 desc_len; + char desc[SERVER_DESC_SIZE_MAX + 1]; +} ATTRIBUTE_ALIGNED(16*1024) ServerInfo; + + +typedef struct ChannelInfo { + u16 name_len; + char name[CHANNEL_NAME_SIZE_MAX + 1]; + u16 desc_len; + char desc[CHANNEL_DESC_SIZE_MAX + 1]; +} ATTRIBUTE_ALIGNED(4*1024) ChannelInfo; + + +typedef struct MessageMetadata { + DateTime receiving_time_utc; + u64 sender_id; + u16 data_size; +} ATTRIBUTE_ALIGNED(64) MessageMetadata; + + +typedef struct MessageBlock { + /* sequence of messages (MessageMetadata, byte[]) */ + u8 data[16*1024]; +} MessageBlock; diff --git a/src/network/tcp-chat-protocol/constant.h b/src/network/tcp-chat-protocol/constant.h index f9ac1f6..8a58448 100644 --- a/src/network/tcp-chat-protocol/constant.h +++ b/src/network/tcp-chat-protocol/constant.h @@ -14,6 +14,7 @@ typedef struct PacketHeader { u8 _reserved1; u16 type; u32 _reserved4; + /* size of request/response struct */ u64 content_size; } ATTRIBUTE_ALIGNED(64) PacketHeader; diff --git a/src/network/tcp-chat-protocol/v1.c b/src/network/tcp-chat-protocol/v1.c index ef7a2a2..663eccd 100644 --- a/src/network/tcp-chat-protocol/v1.c +++ b/src/network/tcp-chat-protocol/v1.c @@ -3,7 +3,7 @@ str validateUsername_cstr(char username[USERNAME_SIZE_MAX+1], str* out_username_str){ // must end with 0 if(username[USERNAME_SIZE_MAX] != '\0'){ - return STR("Username string doesn't end correctly"); + return str_copy(STR("Username string doesn't end correctly")); } str u = str_from_cstr(username); @@ -16,8 +16,13 @@ str validateUsername_cstr(char username[USERNAME_SIZE_MAX+1], str* out_username_ } str validateUsername_str(str username){ - if(username.size < USERNAME_SIZE_MIN){ - return STR("Username length is too small"); + if(username.size < USERNAME_SIZE_MIN || username.size > USERNAME_SIZE_MAX){ + return str_from_cstr( + sprintf_malloc( + "username length (in bytes) must be >= %i and <= %i\n", + USERNAME_SIZE_MIN, USERNAME_SIZE_MAX + ) + ); } for(u32 i = 0; i < username.size; i++){ @@ -28,8 +33,8 @@ str validateUsername_str(str username){ c == '.' || c == '_' || c == '-') continue; - return STR("Username contains restricted characters. " - "Allowed characters: latin, digits, ._-"); + return str_copy(STR("Username contains restricted characters. " + "Allowed characters: latin, digits, ._-")); } return str_null; @@ -88,9 +93,9 @@ Result(void) LoginRequest_tryConstruct(LoginRequest *ptr, PacketHeader* header, _PacketHeader_construct(LoginRequest); memset(ptr, 0, sizeof(*ptr)); - str username_check_error = validateUsername_str(username); - if(username_check_error.data){ - Return RESULT_ERROR(username_check_error.data, false); + str name_error_str = validateUsername_str(username); + if(name_error_str.data){ + Return RESULT_ERROR(name_error_str.data, true); } memcpy(ptr->username, username.data, username.size); @@ -117,9 +122,9 @@ Result(void) RegisterRequest_tryConstruct(RegisterRequest *ptr, PacketHeader* he _PacketHeader_construct(RegisterRequest); memset(ptr, 0, sizeof(*ptr)); - str username_check_error = validateUsername_str(username); - if(username_check_error.data){ - Return RESULT_ERROR(username_check_error.data, false); + str name_error_str = validateUsername_str(username); + if(name_error_str.data){ + Return RESULT_ERROR(name_error_str.data, true); } memcpy(ptr->username, username.data, username.size); diff --git a/src/network/tcp-chat-protocol/v1.h b/src/network/tcp-chat-protocol/v1.h index 19d9618..a403efe 100644 --- a/src/network/tcp-chat-protocol/v1.h +++ b/src/network/tcp-chat-protocol/v1.h @@ -1,6 +1,7 @@ #pragma once #include "tlibc/errors.h" #include "tlibc/string/str.h" +#include "tlibc/time.h" #include "network/tcp-chat-protocol/constant.h" #define PROTOCOL_VERSION 1 /* 1.0.0 */ @@ -15,7 +16,7 @@ Valid username: - allowed characters: latin, digits, ._- */ /// validates username char[] and constructs str from it -/// @return str_null on success, stack-allocated error message on fail +/// @return str_null on success, heap-allocated error message on fail str validateUsername_cstr(char username[USERNAME_SIZE_MAX+1], str* out_username_str) ATTRIBUTE_WARN_UNUSED_RESULT; str validateUsername_str(str username) ATTRIBUTE_WARN_UNUSED_RESULT; @@ -119,3 +120,38 @@ void RegisterResponse_construct(RegisterResponse* ptr, PacketHeader* header, u64 user_id); +typedef struct SendMessageRequest { + u64 channel_id; + u16 data_size; + /* stream of size data_size */ +} ALIGN_PACKET_STRUCT SendMessageRequest; + +void SendMessageRequest_construct(SendMessageRequest* ptr, PacketHeader* header, + u64 channel_id, u16 data_size); + + +typedef struct SendMessageResponse { + u64 message_id; + DateTime receiving_time_utc; +} ALIGN_PACKET_STRUCT SendMessageResponse; + +void SendMessageResponse_construct(SendMessageResponse* ptr, PacketHeader* header, + u64 message_id, DateTime receiving_time_utc); + + +typedef struct GetMessageBlockRequest { + u64 message_block_id; +} ALIGN_PACKET_STRUCT GetMessageBlockRequest; + +void GetMessageBlockRequest_construct(GetMessageBlockRequest* ptr, PacketHeader* header, + u64 message_block_id); + + +typedef struct GetMessageBlockResponse { + u32 data_size; + /* stream of size data_size */ +} ALIGN_PACKET_STRUCT GetMessageBlockResponse; + +void GetMessageBlockResponse_construct(GetMessageBlockResponse* ptr, PacketHeader* header, + u32 data_size); + diff --git a/src/server/db_tables.h b/src/server/db_tables.h deleted file mode 100644 index a3ec148..0000000 --- a/src/server/db_tables.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "tcp-chat/common_constants.h" -#include "tlibc/time.h" - -typedef struct UserInfo { - u16 name_len; - char name[USERNAME_SIZE_MAX + 1]; // null-terminated - u8 token[PASSWORD_HASH_SIZE]; // token is hashed again on server side - DateTime registration_time; -} ATTRIBUTE_ALIGNED(256) UserInfo; - -typedef struct ChannelInfo { - u16 name_len; - char name[CHANNEL_NAME_SIZE_MAX + 1]; - u16 desc_len; - char desc[CHANNEL_DESC_SIZE_MAX + 1]; -} ATTRIBUTE_ALIGNED(4*1024) ChannelInfo; diff --git a/src/server/responses/GetMessageBlock.c b/src/server/responses/GetMessageBlock.c new file mode 100644 index 0000000..1c9f5de --- /dev/null +++ b/src/server/responses/GetMessageBlock.c @@ -0,0 +1,23 @@ +#include "responses.h" + +#define LOGGER conn->server->logger +#define LOG_FUNC conn->server->log_func + +declare_RequestHandler(GetMessageBlock) +{ + Deferral(4); + logInfo(log_ctx, "requested %s", req_type_name); + + // receive request + GetMessageBlockRequest req; + try_void(PacketHeader_validateContentSize(req_head, sizeof(req))); + try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req)); + + // send response + GetMessageBlockResponse res; + GetMessageBlockResponse_construct(&res, res_head, ); + 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/Login.c b/src/server/responses/Login.c similarity index 92% rename from src/server/request_handlers/Login.c rename to src/server/responses/Login.c index 1a5be35..869f00c 100644 --- a/src/server/request_handlers/Login.c +++ b/src/server/responses/Login.c @@ -1,4 +1,4 @@ -#include "request_handlers.h" +#include "responses.h" #define LOGGER conn->server->logger #define LOG_FUNC conn->server->log_func @@ -23,11 +23,12 @@ declare_RequestHandler(Login) // validate username str username_str = str_null; - str username_check_error = validateUsername_cstr(req.username, &username_str); - if(username_check_error.data){ + str name_error_str = validateUsername_cstr(req.username, &username_str); + if(name_error_str.data){ + Defer(str_free(name_error_str)); try_void(sendErrorMessage(log_ctx, conn, res_head, LogSeverity_Warn, - username_check_error + name_error_str )); Return RESULT_VOID; } diff --git a/src/server/request_handlers/Register.c b/src/server/responses/Register.c similarity index 90% rename from src/server/request_handlers/Register.c rename to src/server/responses/Register.c index e60e1a4..c8a432e 100644 --- a/src/server/request_handlers/Register.c +++ b/src/server/responses/Register.c @@ -1,4 +1,4 @@ -#include "request_handlers.h" +#include "responses.h" #define LOGGER conn->server->logger #define LOG_FUNC conn->server->log_func @@ -23,11 +23,12 @@ declare_RequestHandler(Register) // validate username str username_str = str_null; - str username_check_error = validateUsername_cstr(req.username, &username_str); - if(username_check_error.data){ + str name_error_str = validateUsername_cstr(req.username, &username_str); + if(name_error_str.data){ + Defer(str_free(name_error_str)); try_void(sendErrorMessage(log_ctx, conn, res_head, LogSeverity_Warn, - username_check_error + name_error_str )); Return RESULT_VOID; } @@ -59,7 +60,7 @@ declare_RequestHandler(Register) memcpy(user.token, req.token, sizeof(req.token)); - DateTime_getUTC(&user.registration_time); + DateTime_getUTC(&user.registration_time_utc); // save new user to db and cache try(u64 user_id, u, idb_pushRow(conn->server->db_users_table, &user)); diff --git a/src/server/responses/SendMessage.c b/src/server/responses/SendMessage.c new file mode 100644 index 0000000..796567c --- /dev/null +++ b/src/server/responses/SendMessage.c @@ -0,0 +1,23 @@ +#include "responses.h" + +#define LOGGER conn->server->logger +#define LOG_FUNC conn->server->log_func + +declare_RequestHandler(SendMessage) +{ + Deferral(4); + logInfo(log_ctx, "requested %s", req_type_name); + + // receive request + SendMessageRequest req; + try_void(PacketHeader_validateContentSize(req_head, sizeof(req))); + try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req)); + + // send response + SendMessageResponse res; + SendMessageResponse_construct(&res, res_head, ); + 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/responses/ServerPublicInfo.c similarity index 97% rename from src/server/request_handlers/ServerPublicInfo.c rename to src/server/responses/ServerPublicInfo.c index b8dc0d8..86a88ed 100644 --- a/src/server/request_handlers/ServerPublicInfo.c +++ b/src/server/responses/ServerPublicInfo.c @@ -1,4 +1,4 @@ -#include "request_handlers.h" +#include "responses.h" #define LOGGER conn->server->logger #define LOG_FUNC conn->server->log_func diff --git a/src/server/request_handlers/request_handlers.h b/src/server/responses/responses.h similarity index 100% rename from src/server/request_handlers/request_handlers.h rename to src/server/responses/responses.h diff --git a/src/server/request_handlers/send_error.c b/src/server/responses/send_error.c similarity index 98% rename from src/server/request_handlers/send_error.c rename to src/server/responses/send_error.c index e19a838..1532bd4 100644 --- a/src/server/request_handlers/send_error.c +++ b/src/server/responses/send_error.c @@ -1,4 +1,4 @@ -#include "request_handlers.h" +#include "responses.h" #define LOGGER conn->server->logger #define LOG_FUNC conn->server->log_func diff --git a/src/server/request_handlers/template b/src/server/responses/template similarity index 95% rename from src/server/request_handlers/template rename to src/server/responses/template index 5ff1a88..48fc380 100644 --- a/src/server/request_handlers/template +++ b/src/server/responses/template @@ -1,4 +1,4 @@ -#include "request_handlers.h" +#include "responses.h" #define LOGGER conn->server->logger #define LOG_FUNC conn->server->log_func diff --git a/src/server/server.c b/src/server/server.c index a9eb513..d58d54c 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -5,7 +5,7 @@ #include "server/server_internal.h" #include "config.h" #include "network/tcp-chat-protocol/v1.h" -#include "server/request_handlers/request_handlers.h" +#include "server/responses/responses.h" static void* handleConnection(void* _args); static Result(void) try_handleConnection(ConnectionHandlerArgs* args, cstr log_ctx); diff --git a/src/server/server_internal.h b/src/server/server_internal.h index 0c033f0..2593b31 100644 --- a/src/server/server_internal.h +++ b/src/server/server_internal.h @@ -7,7 +7,7 @@ #include "cryptography/RSA.h" #include "network/encrypted_sockets.h" #include "db/idb.h" -#include "server/db_tables.h" +#include "db/tables.h" typedef struct ClientConnection ClientConnection;