tcp-chat/src/server/responses/Register.c

85 lines
2.6 KiB
C

#include "responses.h"
#define LOGGER conn->server->logger
#define LOG_FUNC conn->server->log_func
declare_RequestHandler(Register)
{
Deferral(4);
logInfo(log_ctx, "requested %s", req_type_name);
// receive request
RegisterRequest req;
try_void(PacketHeader_validateContentSize(req_head, sizeof(req)));
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
if(conn->authorized){
try_void(sendErrorMessage(log_ctx, conn, res_head,
LogSeverity_Warn,
STR("is authorized in already")
));
Return RESULT_VOID;
}
// validate username
str username_str = str_null;
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,
name_error_str
));
Return RESULT_VOID;
}
// lock users cache
try_stderrcode(pthread_mutex_lock(&conn->server->users_cache_mutex));
bool unlocked_users_cache_mutex = false;
// unlock mutex on error catch
Defer(
if(!unlocked_users_cache_mutex)
pthread_mutex_unlock(&conn->server->users_cache_mutex)
);
// check if name is taken
if(HashMap_tryGetPtr(&conn->server->users_name_id_map, username_str) != NULL){
try_void(sendErrorMessage_f(log_ctx, conn, res_head,
LogSeverity_Warn,
"Username '%s' already exists",
username_str.data));
Return RESULT_VOID;
}
// initialize new user
UserInfo user;
memset(&user, 0, sizeof(UserInfo));
user.name_len = username_str.size;
memcpy(user.name, username_str.data, user.name_len);
memcpy(user.token, req.token, sizeof(req.token));
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));
try_assert(user_id == List_len(conn->server->users_cache_list, UserInfo));
List_pushMany(&conn->server->users_cache_list, UserInfo, &user, 1);
try_assert(HashMap_tryPush(&conn->server->users_name_id_map, username_str, &user_id));
// manually unlock mutex
pthread_mutex_unlock(&conn->server->users_cache_mutex);
unlocked_users_cache_mutex = true;
logInfo(log_ctx, "registered user '%s'", username_str.data);
// send response
RegisterResponse res;
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;
}