implemented LoginRequest handler, changed ErrorMessage and ServerPublicInfoResponse
This commit is contained in:
parent
ef2531c63b
commit
9942d94c94
2
dependencies/tlibc
vendored
2
dependencies/tlibc
vendored
@ -1 +1 @@
|
||||
Subproject commit adaf5cc31199b8b70404f30b51a0e4ef822d6fab
|
||||
Subproject commit ae0fa95d6aee2a7427c3e3575d74af1ed360e6e5
|
||||
@ -66,8 +66,8 @@ Result(ServerConnection*) ServerConnection_open(cstr server_link_cstr){
|
||||
|
||||
// send PacketHeader and ClientHandshake
|
||||
// encryption by server public key
|
||||
PacketHeader packet_header = {0};
|
||||
ClientHandshake client_handshake = {0};
|
||||
PacketHeader packet_header;
|
||||
ClientHandshake client_handshake;
|
||||
try_void(ClientHandshake_tryConstruct(&client_handshake, &packet_header,
|
||||
conn->session_key));
|
||||
try_void(EncryptedSocketTCP_sendStructRSA(&conn->sock, &conn->rsa_enc, &packet_header));
|
||||
@ -80,26 +80,24 @@ Result(ServerConnection*) ServerConnection_open(cstr server_link_cstr){
|
||||
// handle server response
|
||||
switch(packet_header.type){
|
||||
case PacketType_ErrorMessage: {
|
||||
u32 err_msg_size = packet_header.content_size;
|
||||
if(err_msg_size > conn->sock.recv_buf.size)
|
||||
err_msg_size = conn->sock.recv_buf.size;
|
||||
Array(u8) err_buf = Array_alloc_size(err_msg_size + 1);
|
||||
ErrorMessage err_msg;
|
||||
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &err_msg));
|
||||
if(err_msg.msg_size > conn->sock.recv_buf.size)
|
||||
err_msg.msg_size = conn->sock.recv_buf.size;
|
||||
Array(u8) err_buf = Array_alloc_size(err_msg.msg_size + 1);
|
||||
bool err_msg_completed = false;
|
||||
Defer(
|
||||
if(!err_msg_completed)
|
||||
free(err_buf.data);
|
||||
);
|
||||
Defer(if(!err_msg_completed) free(err_buf.data));
|
||||
|
||||
// receive error message
|
||||
// receive message content
|
||||
try_void(
|
||||
EncryptedSocketTCP_recv(
|
||||
&conn->sock,
|
||||
Array_sliceTo(err_buf, err_msg_size),
|
||||
Array_sliceTo(err_buf, err_msg.msg_size),
|
||||
SocketRecvFlag_WholeBuffer
|
||||
)
|
||||
);
|
||||
|
||||
((u8*)err_buf.data)[err_msg_size] = 0;
|
||||
((u8*)err_buf.data)[err_msg.msg_size] = 0;
|
||||
err_msg_completed = true;
|
||||
Return RESULT_ERROR((char*)err_buf.data, true);
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include "tlibc/std.h"
|
||||
|
||||
#define USERNAME_SIZE_MIN 2
|
||||
#define USERNAME_SIZE_MAX 63
|
||||
#define USERNAME_SIZE_MAX 31
|
||||
#define PASSWORD_SIZE_MIN 8
|
||||
#define PASSWORD_SIZE_MAX 31
|
||||
#define PASSWORD_HASH_SIZE 32
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
#define AESStream_DEFAULT_CLASS (&br_aes_big_ctr_vtable)
|
||||
|
||||
|
||||
//TODO: use PKS#7 instead of this garbage
|
||||
typedef struct EncryptedBlockHeader {
|
||||
u8 padding_size;
|
||||
} ATTRIBUTE_ALIGNED(16) EncryptedBlockHeader;
|
||||
|
||||
@ -286,8 +286,8 @@ Result(void) idb_getRows(Table* t, u64 id, void* dst, u64 count){
|
||||
|
||||
if(id + count > t->row_count){
|
||||
Return RESULT_ERROR_FMT(
|
||||
"Can't read " IFWIN("%llu", "%lu") " rows at index " IFWIN("%llu", "%lu")
|
||||
" because table '%s' has only " IFWIN("%llu", "%lu") " rows",
|
||||
"Can't read "FMT_u64" rows at index "FMT_u64
|
||||
" because table '%s' has only "FMT_u64" rows",
|
||||
count, id, t->name.data, t->row_count);
|
||||
}
|
||||
|
||||
@ -325,8 +325,8 @@ Result(void) idb_updateRows(Table* t, u64 id, const void* src, u64 count){
|
||||
|
||||
if(id + count >= t->row_count){
|
||||
Return RESULT_ERROR_FMT(
|
||||
"Can't update " IFWIN("%llu", "%lu") " rows at index " IFWIN("%llu", "%lu")
|
||||
" because table '%s' has only " IFWIN("%llu", "%lu") " rows",
|
||||
"Can't update "FMT_u64" rows at index "FMT_u64
|
||||
" because table '%s' has only "FMT_u64" rows",
|
||||
count, id, t->name.data, t->row_count);
|
||||
}
|
||||
|
||||
|
||||
@ -21,14 +21,15 @@ Result(void) PacketHeader_validateType(PacketHeader* ptr, u16 expected_type){
|
||||
Result(void) PacketHeader_validateContentSize(PacketHeader* ptr, u64 expected_size){
|
||||
if(ptr->content_size != expected_size){
|
||||
return RESULT_ERROR_FMT(
|
||||
"expected message with content_size " IFWIN("%llu", "%lu")
|
||||
", but received with content_size " IFWIN("%llu", "%lu"),
|
||||
"expected message with content_size "FMT_u64
|
||||
", but received with content_size "FMT_u64,
|
||||
expected_size, ptr->content_size);
|
||||
}
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
void PacketHeader_construct(PacketHeader* ptr, u8 protocol_version, u16 type, u64 content_size){
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
ptr->magic.n = PacketHeader_MAGIC.n;
|
||||
ptr->protocol_version = protocol_version;
|
||||
ptr->type = type;
|
||||
|
||||
@ -1,13 +1,55 @@
|
||||
#include "v1.h"
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
str u = str_from_cstr(username);
|
||||
str error_str = validateUsername_str(u);
|
||||
if(error_str.data)
|
||||
return error_str;
|
||||
|
||||
*out_username_str = u;
|
||||
return str_null;
|
||||
}
|
||||
|
||||
str validateUsername_str(str username){
|
||||
if(username.size < USERNAME_SIZE_MIN){
|
||||
return STR("Username length is too small");
|
||||
}
|
||||
|
||||
for(u32 i = 0; i < username.size; i++){
|
||||
char c = username.data[i];
|
||||
if (char_isLatinLower(c) ||
|
||||
char_isLatinUpper(c) ||
|
||||
char_isDigit(c) ||
|
||||
c == '.' || c == '_' || c == '-')
|
||||
continue;
|
||||
|
||||
return STR("Username contains restricted characters. "
|
||||
"Allowed characters: latin, digits, ._-");
|
||||
}
|
||||
|
||||
return str_null;
|
||||
}
|
||||
|
||||
#define _PacketHeader_construct(T) \
|
||||
PacketHeader_construct(header, PROTOCOL_VERSION, PacketType_##T, sizeof(T))
|
||||
|
||||
void ErrorMessage_construct(ErrorMessage* ptr, PacketHeader* header, u32 msg_size){
|
||||
_PacketHeader_construct(ErrorMessage);
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
ptr->msg_size = msg_size;
|
||||
}
|
||||
|
||||
Result(void) ClientHandshake_tryConstruct(ClientHandshake* ptr, PacketHeader* header,
|
||||
Array(u8) session_key)
|
||||
{
|
||||
Deferral(1);
|
||||
_PacketHeader_construct(ClientHandshake);
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
|
||||
try_assert(session_key.size == sizeof(ptr->session_key));
|
||||
memcpy(ptr->session_key, session_key.data, session_key.size);
|
||||
@ -19,6 +61,7 @@ void ServerHandshake_construct(ServerHandshake* ptr, PacketHeader* header,
|
||||
u64 session_id)
|
||||
{
|
||||
_PacketHeader_construct(ServerHandshake);
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
ptr->session_id = session_id;
|
||||
}
|
||||
|
||||
@ -26,14 +69,31 @@ void ServerPublicInfoRequest_construct(ServerPublicInfoRequest *ptr, PacketHeade
|
||||
ServerPublicInfo property)
|
||||
{
|
||||
_PacketHeader_construct(ServerPublicInfoRequest);
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
ptr->property = property;
|
||||
}
|
||||
|
||||
void ServerPublicInfoResponse_construct(ServerPublicInfoResponse* ptr, PacketHeader* header,
|
||||
u32 data_size)
|
||||
{
|
||||
_PacketHeader_construct(ServerPublicInfoResponse);
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
ptr->data_size = data_size;
|
||||
}
|
||||
|
||||
Result(void) LoginRequest_tryConstruct(LoginRequest *ptr, PacketHeader* header,
|
||||
Array(u8) token)
|
||||
str username, Array(u8) token)
|
||||
{
|
||||
Deferral(1);
|
||||
_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);
|
||||
}
|
||||
memcpy(ptr->username, username.data, username.size);
|
||||
ptr->username[username.size] = 0;
|
||||
|
||||
try_assert(token.size == sizeof(ptr->token));
|
||||
memcpy(ptr->token, token.data, token.size);
|
||||
@ -45,6 +105,8 @@ void LoginResponse_construct(LoginResponse* ptr, PacketHeader* header,
|
||||
u64 user_id, u64 landing_channel_id)
|
||||
{
|
||||
_PacketHeader_construct(LoginResponse);
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
|
||||
ptr->user_id = user_id;
|
||||
ptr->landing_channel_id = landing_channel_id;
|
||||
}
|
||||
@ -54,8 +116,12 @@ Result(void) RegisterRequest_tryConstruct(RegisterRequest *ptr, PacketHeader* he
|
||||
{
|
||||
Deferral(1);
|
||||
_PacketHeader_construct(RegisterRequest);
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
|
||||
try_assert(username.size >= USERNAME_SIZE_MIN && username.size <= USERNAME_SIZE_MAX);
|
||||
str username_check_error = validateUsername_str(username);
|
||||
if(username_check_error.data){
|
||||
Return RESULT_ERROR(username_check_error.data, false);
|
||||
}
|
||||
memcpy(ptr->username, username.data, username.size);
|
||||
ptr->username[username.size] = 0;
|
||||
|
||||
@ -69,5 +135,6 @@ void RegisterResponse_construct(RegisterResponse *ptr, PacketHeader* header,
|
||||
u64 user_id)
|
||||
{
|
||||
_PacketHeader_construct(RegisterResponse);
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
ptr->user_id = user_id;
|
||||
}
|
||||
|
||||
@ -8,6 +8,18 @@
|
||||
|
||||
#define ALIGN_PACKET_STRUCT ATTRIBUTE_ALIGNED(8)
|
||||
|
||||
/*
|
||||
Valid username:
|
||||
- must end with '\0'
|
||||
- USERNAME_SIZE_MIN <= size <= USERNAME_SIZE_MAX
|
||||
- allowed characters: latin, digits, ._-
|
||||
*/
|
||||
/// validates username char[] and constructs str from it
|
||||
/// @return str_null on success, stack-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;
|
||||
|
||||
|
||||
typedef enum PacketType {
|
||||
PacketType_Invalid,
|
||||
@ -23,9 +35,15 @@ typedef enum PacketType {
|
||||
} ATTRIBUTE_PACKED PacketType;
|
||||
|
||||
|
||||
// typedef struct ErrorMessage {
|
||||
// /* stream of size header.content_size */
|
||||
// } ErrorMessage;
|
||||
#define ERROR_MESSAGE_MAX_SIZE 8192
|
||||
|
||||
typedef struct ErrorMessage {
|
||||
u32 msg_size; // <= ERROR_MESSAGE_MAX_SIZE
|
||||
/* stream of size msg_size */
|
||||
} ErrorMessage;
|
||||
|
||||
void ErrorMessage_construct(ErrorMessage* ptr, PacketHeader* header,
|
||||
u32 msg_size);
|
||||
|
||||
|
||||
typedef struct ClientHandshake {
|
||||
@ -57,17 +75,22 @@ void ServerPublicInfoRequest_construct(ServerPublicInfoRequest* ptr, PacketHeade
|
||||
ServerPublicInfo property);
|
||||
|
||||
|
||||
// typedef struct ServerPublicInfoResponse {
|
||||
// /* stream of size header.content_size */
|
||||
// } ServerPublicInfoResponse;
|
||||
typedef struct ServerPublicInfoResponse {
|
||||
u32 data_size;
|
||||
/* stream of size data_size */
|
||||
} ServerPublicInfoResponse;
|
||||
|
||||
void ServerPublicInfoResponse_construct(ServerPublicInfoResponse* ptr, PacketHeader* header,
|
||||
u32 data_size);
|
||||
|
||||
|
||||
typedef struct LoginRequest {
|
||||
char username[USERNAME_SIZE_MAX + 1]; // null-terminated
|
||||
u8 token[PASSWORD_HASH_SIZE];
|
||||
} ALIGN_PACKET_STRUCT LoginRequest;
|
||||
|
||||
Result(void) LoginRequest_tryConstruct(LoginRequest* ptr, PacketHeader* header,
|
||||
Array(u8) token);
|
||||
str username, Array(u8) token);
|
||||
|
||||
|
||||
typedef struct LoginResponse {
|
||||
|
||||
@ -32,14 +32,14 @@ Result(ClientConnection*) ClientConnection_accept(ConnectionHandlerArgs* args)
|
||||
RSADecryptor_construct(&rsa_dec, &args->server->cred.rsa_sk);
|
||||
|
||||
// receive PacketHeader
|
||||
PacketHeader packet_header = {0};
|
||||
PacketHeader packet_header;
|
||||
try_void(EncryptedSocketTCP_recvStructRSA(&conn->sock, &rsa_dec, &packet_header));
|
||||
try_void(PacketHeader_validateMagic(&packet_header));
|
||||
try_void(PacketHeader_validateType(&packet_header, PacketType_ClientHandshake));
|
||||
try_void(PacketHeader_validateContentSize(&packet_header, sizeof(ClientHandshake)));
|
||||
|
||||
// receive ClientHandshake
|
||||
ClientHandshake client_handshake = {0};
|
||||
ClientHandshake client_handshake;
|
||||
try_void(EncryptedSocketTCP_recvStructRSA(&conn->sock, &rsa_dec, &client_handshake));
|
||||
|
||||
// use received session key
|
||||
@ -47,7 +47,7 @@ Result(ClientConnection*) ClientConnection_accept(ConnectionHandlerArgs* args)
|
||||
EncryptedSocketTCP_changeKey(&conn->sock, conn->session_key);
|
||||
|
||||
// send PacketHeader and ServerHandshake over encrypted TCP socket
|
||||
ServerHandshake server_handshake = {0};
|
||||
ServerHandshake server_handshake;
|
||||
ServerHandshake_construct(&server_handshake, &packet_header,
|
||||
conn->session_id);
|
||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &packet_header));
|
||||
|
||||
@ -4,22 +4,74 @@
|
||||
declare_RequestHandler(Login)
|
||||
{
|
||||
Deferral(4);
|
||||
logDebug(log_ctx, "requested %s", req_type_name);
|
||||
|
||||
LoginRequest req = {0};
|
||||
logInfo(log_ctx, "requested %s", req_type_name);
|
||||
|
||||
// receive request
|
||||
LoginRequest req;
|
||||
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;
|
||||
if(conn->authorized){
|
||||
try_void(sendErrorMessage(log_ctx, false, conn, res_head,
|
||||
STR("is logged in already")));
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
LoginResponse res = {0};
|
||||
LoginResponse_construct(&res, res_head, user_id, landing_channel_id);
|
||||
// validate username
|
||||
str username_str = str_null;
|
||||
str username_check_error = validateUsername_cstr(req.username, &username_str);
|
||||
if(username_check_error.data){
|
||||
try_void(sendErrorMessage(log_ctx, false, conn, res_head, username_check_error));
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
// cakculate hash of received token
|
||||
u8 token_hash[PASSWORD_HASH_SIZE];
|
||||
hash_password(
|
||||
Array_construct_size(req.token, sizeof(req.token)),
|
||||
token_hash,
|
||||
PASSWORD_HASH_LVL_ROUNDS
|
||||
);
|
||||
|
||||
// lock users cache
|
||||
try_stderrcode(pthread_mutex_lock(&server->users_cache_mutex));
|
||||
bool unlocked_users_cache_mutex = false;
|
||||
Defer(if(!unlocked_users_cache_mutex) pthread_mutex_unlock(&server->users_cache_mutex));
|
||||
|
||||
// try get id from name cache
|
||||
u64* id_ptr = HashMap_tryGetPtr(&server->users_name_id_map, username_str);
|
||||
if(id_ptr == NULL){
|
||||
try_void(sendErrorMessage_f(log_ctx, false, conn, res_head,
|
||||
"Username '%s' is not registered\n",
|
||||
username_str.data));
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
u64 user_id = *id_ptr;
|
||||
|
||||
// get user by id
|
||||
try_assert(List_len(server->users_cache_list, User) < user_id);
|
||||
User* u = &List_index(server->users_cache_list, User, user_id);
|
||||
|
||||
// validate token hash
|
||||
if(memcmp(token_hash, u->token_hash, sizeof(token_hash)) != 0){
|
||||
try_void(sendErrorMessage(log_ctx, false, conn, res_head,
|
||||
STR("wrong password")));
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
// manually unlock mutex
|
||||
pthread_mutex_unlock(&server->users_cache_mutex);
|
||||
unlocked_users_cache_mutex = true;
|
||||
|
||||
// authorize
|
||||
conn->authorized = true;
|
||||
logInfo(log_ctx, "authorized user '%s'", username_str.data);
|
||||
|
||||
// send response
|
||||
LoginResponse res;
|
||||
LoginResponse_construct(&res, res_head, user_id, server->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;
|
||||
}
|
||||
|
||||
@ -3,29 +3,18 @@
|
||||
declare_RequestHandler(Register)
|
||||
{
|
||||
Deferral(4);
|
||||
logDebug(log_ctx, "requested %s", req_type_name);
|
||||
logInfo(log_ctx, "requested %s", req_type_name);
|
||||
|
||||
RegisterRequest req = {0};
|
||||
// receive request
|
||||
RegisterRequest req;
|
||||
try_void(PacketHeader_validateContentSize(req_head, sizeof(req)));
|
||||
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
|
||||
|
||||
//TODO: reject usernames with restricted characters
|
||||
// must end with 0
|
||||
if(req.username[sizeof(req.username - 1)] != 0){
|
||||
try(char* err_msg, p, sendErrorMessage(conn, res_head,
|
||||
"Username is incorrect\n"));
|
||||
logWarn(log_ctx, "%s", err_msg);
|
||||
free(err_msg);
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
// check username size
|
||||
str username_str = str_from_cstr(req.username);
|
||||
if(username_str.size < USERNAME_SIZE_MIN){
|
||||
try(char* err_msg, p, sendErrorMessage(conn, res_head,
|
||||
"Username length (in bytes) must be >= %i and <= %i\n",
|
||||
USERNAME_SIZE_MIN, USERNAME_SIZE_MAX));
|
||||
logWarn(log_ctx, "%s", err_msg);
|
||||
free(err_msg);
|
||||
// validate username
|
||||
str username_str = str_null;
|
||||
str username_check_error = validateUsername_cstr(req.username, &username_str);
|
||||
if(username_check_error.data){
|
||||
try_void(sendErrorMessage(log_ctx, false, conn, res_head, username_check_error));
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
@ -36,11 +25,9 @@ declare_RequestHandler(Register)
|
||||
|
||||
// check if name is taken
|
||||
if(HashMap_tryGetPtr(&server->users_name_id_map, username_str) != NULL){
|
||||
try(char* err_msg, p, sendErrorMessage(conn, res_head,
|
||||
"User with name '%s' already exists\n",
|
||||
try_void(sendErrorMessage_f(log_ctx, false, conn, res_head,
|
||||
"Username'%s' already exists\n",
|
||||
username_str.data));
|
||||
logWarn(log_ctx, "%s", err_msg);
|
||||
free(err_msg);
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
@ -66,7 +53,10 @@ declare_RequestHandler(Register)
|
||||
pthread_mutex_unlock(&server->users_cache_mutex);
|
||||
unlocked_users_cache_mutex = true;
|
||||
|
||||
RegisterResponse res = {0};
|
||||
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));
|
||||
|
||||
@ -3,21 +3,20 @@
|
||||
declare_RequestHandler(ServerPublicInfo)
|
||||
{
|
||||
Deferral(4);
|
||||
logDebug(log_ctx, "requested %s", req_type_name);
|
||||
logInfo(log_ctx, "requested %s", req_type_name);
|
||||
|
||||
ServerPublicInfoRequest req = {0};
|
||||
// receive request
|
||||
ServerPublicInfoRequest req;
|
||||
try_void(PacketHeader_validateContentSize(req_head, sizeof(req)));
|
||||
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
|
||||
|
||||
//TODO: try find requested info
|
||||
// find requested info
|
||||
Array(u8) content;
|
||||
switch(req.property){
|
||||
default:{
|
||||
try(char* err_msg, p, sendErrorMessage(conn, res_head,
|
||||
try_void(sendErrorMessage_f(log_ctx, false, conn, res_head,
|
||||
"Unknown ServerPublicInfo property %u",
|
||||
req.property));
|
||||
logWarn(log_ctx, "%s", err_msg);
|
||||
free(err_msg);
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
case ServerPublicInfo_Name:
|
||||
@ -28,9 +27,11 @@ declare_RequestHandler(ServerPublicInfo)
|
||||
break;
|
||||
}
|
||||
|
||||
PacketHeader_construct(res_head,
|
||||
PROTOCOL_VERSION, PacketType_ServerPublicInfoResponse, content.size);
|
||||
// send response
|
||||
ServerPublicInfoResponse res;
|
||||
ServerPublicInfoResponse_construct(&res, res_head, content.size);
|
||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
|
||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
|
||||
try_void(EncryptedSocketTCP_send(&conn->sock, content));
|
||||
|
||||
Return RESULT_VOID;
|
||||
|
||||
@ -4,10 +4,17 @@
|
||||
#include "log.h"
|
||||
|
||||
|
||||
Result(char*) __sendErrorMessage_va(ClientConnection* conn, PacketHeader* res_head,
|
||||
Result(void) sendErrorMessage(cstr log_ctx, bool logAsError,
|
||||
ClientConnection* conn, PacketHeader* res_head,
|
||||
str msg);
|
||||
|
||||
Result(void) __sendErrorMessage_fv(cstr log_ctx, bool logAsError,
|
||||
ClientConnection* conn, PacketHeader* res_head,
|
||||
cstr format, va_list argv);
|
||||
Result(char*) sendErrorMessage(ClientConnection* conn, PacketHeader* res_head,
|
||||
cstr format, ...) ATTRIBUTE_CHECK_FORMAT_PRINTF(3, 4);
|
||||
|
||||
Result(void) sendErrorMessage_f(cstr log_ctx, bool logAsError,
|
||||
ClientConnection* conn, PacketHeader* res_head,
|
||||
cstr format, ...) ATTRIBUTE_CHECK_FORMAT_PRINTF(5, 6);
|
||||
|
||||
|
||||
#define declare_RequestHandler(TYPE) \
|
||||
|
||||
@ -1,34 +1,54 @@
|
||||
#include "request_handlers.h"
|
||||
#include "log.h"
|
||||
|
||||
Result(char*) __sendErrorMessage_va(ClientConnection* conn, PacketHeader* res_head,
|
||||
Result(void) sendErrorMessage(cstr log_ctx, bool logAsError,
|
||||
ClientConnection* conn, PacketHeader* res_head,
|
||||
str msg)
|
||||
{
|
||||
Deferral(1);
|
||||
|
||||
//limit ErrorMessage size to fit into EncryptedSocketTCP.internal_buffer_size
|
||||
if(msg.size > ERROR_MESSAGE_MAX_SIZE)
|
||||
msg.size = ERROR_MESSAGE_MAX_SIZE;
|
||||
|
||||
if(logAsError){
|
||||
logError(log_ctx, FMT_str, msg.size, msg.data);
|
||||
} else {
|
||||
logWarn(log_ctx, FMT_str, msg.size, msg.data);
|
||||
}
|
||||
|
||||
ErrorMessage res;
|
||||
ErrorMessage_construct(&res, res_head, msg.size);
|
||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
|
||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
|
||||
try_void(EncryptedSocketTCP_send(&conn->sock, str_castTo_Array(msg)));
|
||||
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) __sendErrorMessage_fv(cstr log_ctx, bool logAsError,
|
||||
ClientConnection* conn, PacketHeader* res_head,
|
||||
cstr format, va_list argv)
|
||||
{
|
||||
Deferral(4);
|
||||
|
||||
Array(u8) err_buf;
|
||||
err_buf.data = vsprintf_malloc(format, argv);
|
||||
err_buf.size = strlen(err_buf.data);
|
||||
//limit ErrorMessage size to fit into EncryptedSocketTCP.internal_buffer_size
|
||||
if(err_buf.size > NETWORK_BUFFER_SIZE)
|
||||
err_buf.size = NETWORK_BUFFER_SIZE;
|
||||
bool err_complete = false;
|
||||
Defer(if(!err_complete) free(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));
|
||||
str msg = str_from_cstr(vsprintf_malloc(format, argv));
|
||||
Defer(free(msg.data));
|
||||
try_void(sendErrorMessage(log_ctx, logAsError, conn, res_head, msg));
|
||||
|
||||
err_complete = true;
|
||||
Return RESULT_VALUE(p, err_buf.data);
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(char*) sendErrorMessage(ClientConnection* conn, PacketHeader* res_head,
|
||||
Result(void) sendErrorMessage_f(cstr log_ctx, bool logAsError,
|
||||
ClientConnection* conn, PacketHeader* res_head,
|
||||
cstr format, ...)
|
||||
{
|
||||
Deferral(1);
|
||||
|
||||
va_list argv;
|
||||
va_start(argv, format);
|
||||
ResultVar(char*) err_msg = __sendErrorMessage_va(conn, res_head, format, argv);
|
||||
va_end(argv);
|
||||
return err_msg;
|
||||
Defer(va_end(argv));
|
||||
try_void(__sendErrorMessage_fv(log_ctx, logAsError, conn, res_head, format, argv));
|
||||
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
@ -1,9 +1,20 @@
|
||||
#include "request_handlers.h"
|
||||
|
||||
declare_RequestHandler(T)
|
||||
declare_RequestHandler(NAME)
|
||||
{
|
||||
Deferral(4);
|
||||
logDebug(log_ctx, "requested %s", req_type_name);
|
||||
logInfo(log_ctx, "requested %s", req_type_name);
|
||||
|
||||
// receive request
|
||||
NAME##Request req;
|
||||
try_void(PacketHeader_validateContentSize(req_head, sizeof(req)));
|
||||
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
|
||||
|
||||
// send response
|
||||
NAME##Response res;
|
||||
NAME##Response_construct(&res, res_head, );
|
||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
|
||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
|
||||
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
@ -52,6 +52,14 @@ Result(Server*) Server_createFromConfig(cstr config_path){
|
||||
try_void(config_findValue(config_str, STR("description"), &tmp_str, true));
|
||||
server->description = str_copy(tmp_str);
|
||||
|
||||
// parse landing_channel_id
|
||||
try_void(config_findValue(config_str, STR("landing_channel_id"), &tmp_str, true));
|
||||
char* lci_cstr = str_copy(tmp_str).data;
|
||||
Defer(free(lci_cstr));
|
||||
if(sscanf(lci_cstr, FMT_u64, &server->landing_channel_id) != 1){
|
||||
Return RESULT_ERROR("can't parse 'landing_channel_id' value as number", false);
|
||||
}
|
||||
|
||||
// parse local_address
|
||||
try_void(config_findValue(config_str, STR("local_address"), &tmp_str, true));
|
||||
char* local_end_cstr = str_copy(tmp_str).data;
|
||||
@ -133,7 +141,7 @@ Result(void) Server_run(Server* server){
|
||||
static void* handleConnection(void* _args){
|
||||
ConnectionHandlerArgs* args = (ConnectionHandlerArgs*)_args;
|
||||
char log_ctx[64];
|
||||
sprintf(log_ctx, "Session-" IFWIN("%llx", "%lx"), args->session_id);
|
||||
sprintf(log_ctx, "Session-"FMT_x64, args->session_id);
|
||||
|
||||
ResultVar(void) r = try_handleConnection(args, log_ctx);
|
||||
if(r.error){
|
||||
@ -159,8 +167,8 @@ static Result(void) try_handleConnection(ConnectionHandlerArgs* args, cstr log_c
|
||||
logInfo(log_ctx, "session accepted");
|
||||
|
||||
// handle requests
|
||||
PacketHeader req_head = {0};
|
||||
PacketHeader res_head = {0};
|
||||
PacketHeader req_head;
|
||||
PacketHeader res_head;
|
||||
while(true){
|
||||
sleepMsec(20);
|
||||
//TODO: implement some additional check if socket is dead or not
|
||||
@ -171,12 +179,9 @@ static Result(void) try_handleConnection(ConnectionHandlerArgs* args, cstr log_c
|
||||
switch(req_head.type){
|
||||
// send error message and close connection
|
||||
default:
|
||||
try(char* err_msg, p,
|
||||
sendErrorMessage(conn, &res_head,
|
||||
"Received unexpected packet of type %u",
|
||||
req_head.type));
|
||||
logWarn(log_ctx, "%s", err_msg);
|
||||
free(err_msg);
|
||||
try_void(sendErrorMessage_f(log_ctx, false, conn, &res_head,
|
||||
"Received unexpected packet of type %u",
|
||||
req_head.type));
|
||||
Return RESULT_VOID;
|
||||
|
||||
// unauthorized requests
|
||||
|
||||
@ -45,6 +45,7 @@ void ClientConnection_close(ClientConnection* conn);
|
||||
typedef struct Server {
|
||||
str name;
|
||||
str description;
|
||||
u64 landing_channel_id;
|
||||
EndpointIPv4 local_end;
|
||||
ServerCredentials cred;
|
||||
IncrementalDB* db;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user