#pragma once #include "tlibc/errors.h" /// requires tlibc and tlibtoml init Result(void) TcpChat_init(); void TcpChat_deinit(); #define USERNAME_SIZE_MIN 2 #define USERNAME_SIZE_MAX 31 #define PASSWORD_SIZE_MIN 8 #define PASSWORD_SIZE_MAX 31 #define PASSWORD_HASH_SIZE 32 #define HOSTADDR_SIZE_MIN 4 #define HOSTADDR_SIZE_MAX 255 #define PRIVATE_KEY_BASE64_SIZE_MAX 1724 #define PUBLIC_KEY_BASE64_SIZE_MAX 699 #define SERVER_NAME_SIZE_MIN 1 #define SERVER_NAME_SIZE_MAX 127 #define SERVER_DESC_SIZE_MAX 1023 #define CHANNEL_NAME_SIZE_MIN 1 #define CHANNEL_NAME_SIZE_MAX 127 #define CHANNEL_DESC_SIZE_MAX 1023 #define MESSAGE_SIZE_MIN 1 #define MESSAGE_SIZE_MAX 4000 #define MESSAGE_BLOCK_COUNT_MAX 50 #define MESSAGE_TIMESTAMP_FMT_SQL "%Y.%m.%d-%H:%M:%f" ////////////////////////////////////////////////////////////////////////////// // // // Logging // // // ////////////////////////////////////////////////////////////////////////////// ErrorCodePage_declare(WINSOCK2); ErrorCodePage_declare(TcpChat); typedef enum TcpChatError { TcpChatError_Unknown, TcpChatError_RejectIncoming, } TcpChatError; typedef enum LogSeverity { LogSeverity_Debug, LogSeverity_Info, LogSeverity_Warn, LogSeverity_Error, } LogSeverity; typedef void (*LogFunction_t)(void* logger, cstr context, LogSeverity severity, cstr msg); // requires defined LOGGER, LOG_FUNC, LOG_CONTEXT #define log(severity, format, ...) { \ if(LOG_FUNC) { \ char* ___log_msg = sprintf_malloc(format ,##__VA_ARGS__); \ LOG_FUNC(LOGGER, LOG_CONTEXT, severity, ___log_msg); \ free(___log_msg); \ } \ } #define logDebug(format, ...) log(LogSeverity_Debug, format ,##__VA_ARGS__) #define logInfo(format, ...) log(LogSeverity_Info, format ,##__VA_ARGS__) #define logWarn(format, ...) log(LogSeverity_Warn, format ,##__VA_ARGS__) #define logError(format, ...) log(LogSeverity_Error, format ,##__VA_ARGS__) ////////////////////////////////////////////////////////////////////////////// // // // Server // // // ////////////////////////////////////////////////////////////////////////////// typedef struct Server Server; /// @param config_file_content config in toml format /// @param config_file_name to use in error messages /// @param logger some shared data for your log function /// @param log_func log function that you have to implement /// @return Result(Server*) Server_create(str config_file_content, cstr config_file_name, void* logger, LogFunction_t log_func); void Server_free(Server* server); Result(void) Server_run(Server* server); ////////////////////////////////////////////////////////////////////////////// // // // Client // // // ////////////////////////////////////////////////////////////////////////////// typedef struct Client Client; Result(Client*) Client_create(str username, str password); void Client_free(Client* client); /// @return username saved during client initialization str Client_getUserName(Client* client); /// @return AES key calculated from password that can be used to encrypt user data Array(u8) Client_getUserDataKey(Client* client); /// @param server_addr_cstr ip:port /// @param server_pk_base64 public key encoded by `RSA_serializePublicKey_base64()` Result(void) Client_connect(Client* client, cstr server_addr_cstr, cstr server_pk_base64); /// disconnect from current server void Client_disconnect(Client* client); /// @param self connected client /// @param out_str heap-allocated string Result(void) Client_getServerName(Client* self, str* out_str); /// @param self connected client /// @param out_str heap-allocated string Result(void) Client_getServerDescription(Client* self, str* out_str); /// Create new account on connected server Result(void) Client_register(Client* self, i64* out_user_id); /// Authorize on connected server Result(void) Client_login(Client* self, i64* out_user_id, i64* out_landing_channel_id);