Compare commits

..

No commits in common. "e03c651cef03225df056e97c9edfd14027b28828" and "ea4a649e00bf8f46dd9834158fc8e0f531d1dd48" have entirely different histories.

22 changed files with 285 additions and 412 deletions

2
dependencies/tlibc vendored

@ -1 +1 @@
Subproject commit 2c8e6fc601a868851d8ce50f77b391e6a9b7e656 Subproject commit d6436d08338a0a762e727f0c816dd5a09782b180

View File

@ -0,0 +1,49 @@
#include "client.h"
#include "tlibc/string/StringBuilder.h"
void ClientCredentials_free(ClientCredentials* cred){
if(cred == NULL)
return;
free(cred->username.data);
free(cred->aes_key.data);
free(cred);
}
Result(ClientCredentials*) ClientCredentials_create(str username, str password){
Deferral(8);
ClientCredentials* cred = (ClientCredentials*)malloc(sizeof(ClientCredentials));
memset(cred, 0, sizeof(ClientCredentials));
bool success = false;
Defer(
if(!success)
free(cred);
);
cred->username = str_copy(username);
Defer(
if(!success)
free(cred->username.data);
);
// concat password and username
StringBuilder sb = StringBuilder_alloc(username.size + password.size + 1);
Defer(StringBuilder_destroy(&sb));
StringBuilder_append_str(&sb, password);
StringBuilder_append_str(&sb, username);
Array(u8) password_and_username = str_castTo_Array(StringBuilder_getStr(&sb));
cred->aes_key = Array_alloc(u8, PASSWORD_HASH_SIZE);
Defer(
if(!success){
free(cred->aes_key.data);
}
);
// lvl 1 hash - is used as AES key for user data
hash_password(password_and_username, cred->aes_key.data, __PASSWORD_HASH_LVL_ITERATIONS);
AESBlockEncryptor_construct(&cred->user_data_aes_enc, cred->aes_key, AESBlockEncryptor_DEFAULT_CLASS);
AESBlockDecryptor_construct(&cred->user_data_aes_dec, cred->aes_key, AESBlockDecryptor_DEFAULT_CLASS);
success = true;
Return RESULT_VALUE(p, cred);
}

View File

@ -1,43 +0,0 @@
#include "client.h"
#include "tlibc/string/StringBuilder.h"
void ClientCredentials_destroy(ClientCredentials* cred){
if(!cred)
return;
free(cred->username.data);
free(cred->user_data_key.data);
free(cred->token.data);
}
Result(void) ClientCredentials_tryConstruct(ClientCredentials* cred,
str username, str password)
{
Deferral(8);
memset(cred, 0, sizeof(ClientCredentials));
bool success = false;
Defer(if(!success) ClientCredentials_destroy(cred));
cred->username = str_copy(username);
// concat password and username
StringBuilder sb = StringBuilder_alloc(username.size + password.size + 1);
Defer(StringBuilder_destroy(&sb));
StringBuilder_append_str(&sb, password);
StringBuilder_append_str(&sb, username);
Array(u8) password_and_username = str_castTo_Array(StringBuilder_getStr(&sb));
// lvl 1 hash - is used as AES key for user data
cred->user_data_key = Array_alloc(u8, PASSWORD_HASH_SIZE);
hash_password(password_and_username, cred->user_data_key.data, __PASSWORD_HASH_LVL_ITERATIONS);
// lvl 2 hash - is used for authentification
cred->token = Array_alloc(u8, PASSWORD_HASH_SIZE);
hash_password(cred->user_data_key, cred->token.data, __PASSWORD_HASH_LVL_ITERATIONS);
AESBlockEncryptor_construct(&cred->user_data_aes_enc, cred->user_data_key, AESBlockEncryptor_DEFAULT_CLASS);
AESBlockDecryptor_construct(&cred->user_data_aes_dec, cred->user_data_key, AESBlockDecryptor_DEFAULT_CLASS);
success = true;
Return RESULT_VOID;
}

View File

@ -2,7 +2,7 @@
#include "network/tcp-chat-protocol/v1.h" #include "network/tcp-chat-protocol/v1.h"
void ServerConnection_close(ServerConnection* conn){ void ServerConnection_close(ServerConnection* conn){
if(!conn) if(conn == NULL)
return; return;
RSA_destroyPublicKey(&conn->server_pk); RSA_destroyPublicKey(&conn->server_pk);
EncryptedSocketTCP_destroy(&conn->sock); EncryptedSocketTCP_destroy(&conn->sock);
@ -42,12 +42,15 @@ Result(void) ServerLink_parse(cstr server_link_cstr, EndpointIPv4* server_end_ou
} }
Result(ServerConnection*) ServerConnection_open(ClientCredentials* client_credentials, cstr server_link_cstr){ Result(ServerConnection*) ServerConnection_open(ClientCredentials* client_credentials, cstr server_link_cstr){
Deferral(16); Deferral(64);
ServerConnection* conn = (ServerConnection*)malloc(sizeof(ServerConnection)); ServerConnection* conn = (ServerConnection*)malloc(sizeof(ServerConnection));
memset(conn, 0, sizeof(*conn)); memset(conn, 0, sizeof(*conn));
bool success = false; bool success = false;
Defer(if(!success) ServerConnection_close(conn)); Defer(
if(!success)
ServerConnection_close(conn);
);
try_void(ServerLink_parse(server_link_cstr, &conn->server_end, &conn->server_pk)); try_void(ServerLink_parse(server_link_cstr, &conn->server_end, &conn->server_pk));
RSAEncryptor_construct(&conn->rsa_enc, &conn->server_pk); RSAEncryptor_construct(&conn->rsa_enc, &conn->server_pk);

View File

@ -17,30 +17,12 @@ static const str farewell_art = STR(
"\\(_,J J L l`,)/\n" "\\(_,J J L l`,)/\n"
); );
Result(void) Client_createFromConfig(cstr config_path){ static ClientCredentials* _client_credentials = NULL;
Deferral(16); static ServerConnection* _server_connection = NULL;
Client* client = (Client*)malloc(sizeof(Client)); static Result(void) commandExec(str command, bool* stop);
memset(client, 0, sizeof(Client));
bool success = false;
Defer(if(!success) Client_free(client));
success = true; static Result(void) askUserNameAndPassword(ClientCredentials** cred){
Return RESULT_VALUE(p, client);
}
void Client_free(Client* client){
if(!client)
return;
ClientCredentials_destroy(&client->cred);
ServerConnection_close(client->server_connection);
free(client);
}
static Result(void) commandExec(Client* client, str command, bool* stop);
static Result(void) askUserNameAndPassword(ClientCredentials* cred){
Deferral(8); Deferral(8);
char username_buf[128]; char username_buf[128];
@ -51,7 +33,6 @@ static Result(void) askUserNameAndPassword(ClientCredentials* cred){
Return RESULT_ERROR("STDIN is closed", false); Return RESULT_ERROR("STDIN is closed", false);
} }
username = str_from_cstr(username_buf); username = str_from_cstr(username_buf);
str_trim(&username, true);
if(username.size < USERNAME_SIZE_MIN || username.size > USERNAME_SIZE_MAX){ if(username.size < USERNAME_SIZE_MIN || username.size > USERNAME_SIZE_MAX){
printf("ERROR: username length (in bytes) must be >= %i and <= %i\n", printf("ERROR: username length (in bytes) must be >= %i and <= %i\n",
USERNAME_SIZE_MIN, USERNAME_SIZE_MAX); USERNAME_SIZE_MIN, USERNAME_SIZE_MAX);
@ -68,7 +49,6 @@ static Result(void) askUserNameAndPassword(ClientCredentials* cred){
Return RESULT_ERROR("STDIN is closed", false); Return RESULT_ERROR("STDIN is closed", false);
} }
password = str_from_cstr(password_buf); password = str_from_cstr(password_buf);
str_trim(&password, true);
if(password.size < PASSWORD_SIZE_MIN || password.size > PASSWORD_SIZE_MAX){ if(password.size < PASSWORD_SIZE_MIN || password.size > PASSWORD_SIZE_MAX){
printf("ERROR: password length (in bytes) must be >= %i and <= %i\n", printf("ERROR: password length (in bytes) must be >= %i and <= %i\n",
PASSWORD_SIZE_MIN, PASSWORD_SIZE_MAX); PASSWORD_SIZE_MIN, PASSWORD_SIZE_MAX);
@ -76,18 +56,23 @@ static Result(void) askUserNameAndPassword(ClientCredentials* cred){
else break; else break;
} }
try_void(ClientCredentials_tryConstruct(cred, username, password)); try(*cred, p, ClientCredentials_create(username, password));
Return RESULT_VOID; Return RESULT_VOID;
} }
Result(void) Client_run(Client* client) { Result(void) client_run() {
Deferral(16); Deferral(32);
if(!term_init()){ if(!term_init()){
Return RESULT_ERROR("can't init terminal", false); Return RESULT_ERROR("can't init terminal", false);
} }
fputs(greeting_art.data, stdout); fputs(greeting_art.data, stdout);
try_void(askUserNameAndPassword(&client->cred));
Defer(
ClientCredentials_free(_client_credentials);
ServerConnection_close(_server_connection);
);
try_void(askUserNameAndPassword(&_client_credentials));
Array(char) input_buf = Array_alloc(char, 10000); Array(char) input_buf = Array_alloc(char, 10000);
Defer(free(input_buf.data)); Defer(free(input_buf.data));
@ -105,7 +90,7 @@ Result(void) Client_run(Client* client) {
if(command_input.size == 0) if(command_input.size == 0)
continue; continue;
ResultVar(void) com_result = commandExec(client, command_input, &stop); ResultVar(void) com_result = commandExec(command_input, &stop);
if(com_result.error){ if(com_result.error){
str e_str = Error_toStr(com_result.error); str e_str = Error_toStr(com_result.error);
printf("%s\n", e_str.data); printf("%s\n", e_str.data);
@ -119,7 +104,7 @@ Result(void) Client_run(Client* client) {
#define is_alias(LITERAL) str_equals(command, STR(LITERAL)) #define is_alias(LITERAL) str_equals(command, STR(LITERAL))
static Result(void) commandExec(Client* client, str command, bool* stop){ static Result(void) commandExec(str command, bool* stop){
Deferral(64); Deferral(64);
char answer_buf[10000]; char answer_buf[10000];
const u32 answer_buf_size = sizeof(answer_buf); const u32 answer_buf_size = sizeof(answer_buf);
@ -141,7 +126,7 @@ static Result(void) commandExec(Client* client, str command, bool* stop){
); );
} }
else if (is_alias("j") || is_alias("join")){ else if (is_alias("j") || is_alias("join")){
ServerConnection_close(client->server_connection); ServerConnection_close(_server_connection);
puts("Enter server address (ip:port:public_key): "); puts("Enter server address (ip:port:public_key): ");
if(fgets(answer_buf, answer_buf_size, stdin) == NULL){ if(fgets(answer_buf, answer_buf_size, stdin) == NULL){
@ -151,8 +136,7 @@ static Result(void) commandExec(Client* client, str command, bool* stop){
str_trim(&new_server_link, true); str_trim(&new_server_link, true);
printf("connecting to server...\n"); printf("connecting to server...\n");
try(client->server_connection, p, try(_server_connection, p, ServerConnection_open(_client_credentials, new_server_link.data));
ServerConnection_open(&client->cred, new_server_link.data));
printf("connection established\n"); printf("connection established\n");
// TODO: request server info // TODO: request server info
@ -161,7 +145,7 @@ static Result(void) commandExec(Client* client, str command, bool* stop){
// try log in // try log in
// if not registered, request registration and then log in // if not registered, request registration and then log in
// call Client_runIO(): // call serverConnection_run():
// function with infinite loop which sends and receives messages // function with infinite loop which sends and receives messages
// with navigation across server channels // with navigation across server channels
// //
@ -175,8 +159,9 @@ static Result(void) commandExec(Client* client, str command, bool* stop){
// regiser and then log in // regiser and then log in
} }
else { else {
printf("ERROR: unknown command.\n" Return RESULT_ERROR_FMT("unknown kommand: '%s'\n"
"Use 'h' to see list of avaliable commands\n"); "Use 'h' to see list of avaliable commands",
command.data);
} }
Return RESULT_VOID; Return RESULT_VOID;

View File

@ -3,21 +3,17 @@
#include "cryptography/RSA.h" #include "cryptography/RSA.h"
#include "network/encrypted_sockets.h" #include "network/encrypted_sockets.h"
typedef struct Client Client; Result(void) client_run();
typedef struct ClientCredentials { typedef struct ClientCredentials {
str username; str username;
Array(u8) user_data_key; Array(u8) aes_key;
Array(u8) token;
AESBlockEncryptor user_data_aes_enc; AESBlockEncryptor user_data_aes_enc;
AESBlockDecryptor user_data_aes_dec; AESBlockDecryptor user_data_aes_dec;
} ClientCredentials; } ClientCredentials;
Result(void) ClientCredentials_tryConstruct(ClientCredentials* cred, Result(ClientCredentials*) ClientCredentials_create(str username, str password);
str username, str password); void ClientCredentials_free(ClientCredentials* cred);
void ClientCredentials_destroy(ClientCredentials* cred);
typedef struct ServerConnection { typedef struct ServerConnection {
u64 session_id; u64 session_id;
@ -28,17 +24,5 @@ typedef struct ServerConnection {
EncryptedSocketTCP sock; EncryptedSocketTCP sock;
} ServerConnection; } ServerConnection;
Result(ServerConnection*) ServerConnection_open(ClientCredentials* client_credentials, Result(ServerConnection*) ServerConnection_open(ClientCredentials* client_credentials, cstr server_link_cstr);
cstr server_link_cstr);
void ServerConnection_close(ServerConnection* conn); void ServerConnection_close(ServerConnection* conn);
typedef struct Client {
ClientCredentials cred;
ServerConnection* server_connection;
} Client;
Result(void) Client_createFromConfig(cstr config_path);
void Client_free(Client* client);
Result(void) Client_run(Client* client);

View File

@ -11,7 +11,7 @@ Result(void) RSA_generateKeyPair(u32 key_size,
br_rsa_private_key* sk, br_rsa_public_key* pk, br_rsa_private_key* sk, br_rsa_public_key* pk,
const br_prng_class** rng_vtable_ptr) const br_prng_class** rng_vtable_ptr)
{ {
Deferral(4); Deferral(8);
bool success = false; bool success = false;
void* sk_buf = malloc(BR_RSA_KBUF_PRIV_SIZE(key_size)); void* sk_buf = malloc(BR_RSA_KBUF_PRIV_SIZE(key_size));
@ -34,7 +34,7 @@ Result(void) RSA_generateKeyPair(u32 key_size,
Result(void) RSA_generateKeyPairFromSystemRandom(u32 key_size, Result(void) RSA_generateKeyPairFromSystemRandom(u32 key_size,
br_rsa_private_key* sk, br_rsa_public_key* pk) br_rsa_private_key* sk, br_rsa_public_key* pk)
{ {
Deferral(4); Deferral(8);
br_hmac_drbg_context time_based_rng = { .vtable = &br_hmac_drbg_vtable }; br_hmac_drbg_context time_based_rng = { .vtable = &br_hmac_drbg_vtable };
rng_init_sha256_seedFromSystem(&time_based_rng.vtable); rng_init_sha256_seedFromSystem(&time_based_rng.vtable);
try_void(RSA_generateKeyPair(key_size, sk, pk, &time_based_rng.vtable)); try_void(RSA_generateKeyPair(key_size, sk, pk, &time_based_rng.vtable));
@ -44,7 +44,7 @@ Result(void) RSA_generateKeyPairFromSystemRandom(u32 key_size,
Result(void) RSA_generateKeyPairFromPassword(u32 key_size, Result(void) RSA_generateKeyPairFromPassword(u32 key_size,
br_rsa_private_key* sk, br_rsa_public_key* pk, str password) br_rsa_private_key* sk, br_rsa_public_key* pk, str password)
{ {
Deferral(4); Deferral(8);
br_hmac_drbg_context password_based_rng = { .vtable = &br_hmac_drbg_vtable }; br_hmac_drbg_context password_based_rng = { .vtable = &br_hmac_drbg_vtable };
br_hmac_drbg_init(&password_based_rng, &br_sha256_vtable, password.data, password.size); br_hmac_drbg_init(&password_based_rng, &br_sha256_vtable, password.data, password.size);
try_void(RSA_generateKeyPair(key_size, sk, pk, &password_based_rng.vtable)); try_void(RSA_generateKeyPair(key_size, sk, pk, &password_based_rng.vtable));
@ -52,7 +52,7 @@ Result(void) RSA_generateKeyPairFromPassword(u32 key_size,
} }
Result(void) RSA_computePublicKey(const br_rsa_private_key* sk, br_rsa_public_key* pk){ Result(void) RSA_computePublicKey(const br_rsa_private_key* sk, br_rsa_public_key* pk){
Deferral(4); Deferral(8);
br_rsa_compute_modulus compute_modulus = br_rsa_i31_compute_modulus; br_rsa_compute_modulus compute_modulus = br_rsa_i31_compute_modulus;
br_rsa_compute_pubexp compute_pubexp = br_rsa_i31_compute_pubexp; br_rsa_compute_pubexp compute_pubexp = br_rsa_i31_compute_pubexp;
@ -112,7 +112,7 @@ str RSA_serializePublicKey_base64(const br_rsa_public_key* pk){
} }
Result(void) RSA_parsePublicKey_base64(cstr src, br_rsa_public_key* pk){ Result(void) RSA_parsePublicKey_base64(cstr src, br_rsa_public_key* pk){
Deferral(4); Deferral(8);
u32 n_bitlen = 0; u32 n_bitlen = 0;
if(sscanf(src, "RSA-Public-%u:", &n_bitlen) != 1){ if(sscanf(src, "RSA-Public-%u:", &n_bitlen) != 1){
Return RESULT_ERROR("can't parse key size", false); Return RESULT_ERROR("can't parse key size", false);
@ -142,7 +142,7 @@ Result(void) RSA_parsePublicKey_base64(cstr src, br_rsa_public_key* pk){
} }
Result(void) RSA_parsePrivateKey_base64(cstr src, br_rsa_private_key* sk){ Result(void) RSA_parsePrivateKey_base64(cstr src, br_rsa_private_key* sk){
Deferral(4); Deferral(8);
u32 n_bitlen = 0; u32 n_bitlen = 0;
if(sscanf(src, "RSA-Private-%u:", &n_bitlen) != 1){ if(sscanf(src, "RSA-Private-%u:", &n_bitlen) != 1){
Return RESULT_ERROR("can't parse key size", false); Return RESULT_ERROR("can't parse key size", false);

View File

@ -63,7 +63,7 @@ Result(void) validateTableName(str name){
} }
Result(void) Table_readHeader(Table* t){ Result(void) Table_readHeader(Table* t){
Deferral(4); Deferral(8);
// seek for start of the file // seek for start of the file
try_void(file_seek(t->table_file, 0, SeekOrigin_Start)); try_void(file_seek(t->table_file, 0, SeekOrigin_Start));
// read header // read header
@ -72,7 +72,7 @@ Result(void) Table_readHeader(Table* t){
} }
Result(void) Table_writeHeader(Table* t){ Result(void) Table_writeHeader(Table* t){
Deferral(4); Deferral(8);
// seek for start of the file // seek for start of the file
try_void(file_seek(t->table_file, 0, SeekOrigin_Start)); try_void(file_seek(t->table_file, 0, SeekOrigin_Start));
// write header // write header
@ -81,20 +81,20 @@ Result(void) Table_writeHeader(Table* t){
} }
Result(void) Table_setDirtyBit(Table* t, bool val){ Result(void) Table_setDirtyBit(Table* t, bool val){
Deferral(4); Deferral(8);
t->header._dirty_bit = val; t->header._dirty_bit = val;
try_void(Table_writeHeader(t)); try_void(Table_writeHeader(t));
Return RESULT_VOID; Return RESULT_VOID;
} }
Result(bool) Table_getDirtyBit(Table* t){ Result(bool) Table_getDirtyBit(Table* t){
Deferral(4); Deferral(8);
try_void(Table_readHeader(t)); try_void(Table_readHeader(t));
Return RESULT_VALUE(i, t->header._dirty_bit); Return RESULT_VALUE(i, t->header._dirty_bit);
} }
Result(void) Table_calculateRowCount(Table* t){ Result(void) Table_calculateRowCount(Table* t){
Deferral(4); Deferral(8);
try(i64 file_size, i, file_getSize(t->table_file)); try(i64 file_size, i, file_getSize(t->table_file));
i64 data_size = file_size - sizeof(t->header); i64 data_size = file_size - sizeof(t->header);
if(data_size % t->header.row_size != 0){ if(data_size % t->header.row_size != 0){
@ -109,7 +109,7 @@ Result(void) Table_calculateRowCount(Table* t){
} }
Result(void) Table_validateHeader(Table* t){ Result(void) Table_validateHeader(Table* t){
Deferral(4); Deferral(8);
if(t->header.magic.n != TABLE_FILE_MAGIC.n if(t->header.magic.n != TABLE_FILE_MAGIC.n
|| t->header.row_size == 0) || t->header.row_size == 0)
{ {
@ -147,7 +147,10 @@ Result(IncrementalDB*) idb_open(str db_dir){
IncrementalDB* db = (IncrementalDB*)malloc(sizeof(IncrementalDB)); IncrementalDB* db = (IncrementalDB*)malloc(sizeof(IncrementalDB));
// if object construction fails, destroy incomplete object // if object construction fails, destroy incomplete object
bool success = false; bool success = false;
Defer(if(!success) idb_close(db)); Defer({
if(!success)
idb_close(db);
});
// value of *db must be set to zero or behavior of idb_close will be undefined // value of *db must be set to zero or behavior of idb_close will be undefined
memset(db, 0, sizeof(IncrementalDB)); memset(db, 0, sizeof(IncrementalDB));
@ -168,7 +171,7 @@ void idb_close(IncrementalDB* db){
} }
Result(Table*) idb_getOrCreateTable(IncrementalDB* db, str _table_name, u32 row_size){ Result(Table*) idb_getOrCreateTable(IncrementalDB* db, str _table_name, u32 row_size){
Deferral(16); Deferral(64);
// db lock // db lock
try_stderrcode(pthread_mutex_lock(&db->mutex)); try_stderrcode(pthread_mutex_lock(&db->mutex));
Defer(pthread_mutex_unlock(&db->mutex)); Defer(pthread_mutex_unlock(&db->mutex));
@ -185,7 +188,10 @@ Result(Table*) idb_getOrCreateTable(IncrementalDB* db, str _table_name, u32 row_
Table* t = (Table*)malloc(sizeof(Table)); Table* t = (Table*)malloc(sizeof(Table));
// if object construction fails, destroy incomplete object // if object construction fails, destroy incomplete object
bool success = false; bool success = false;
Defer(if(!success) Table_close(t)); Defer({
if(!success)
Table_close(t);
});
// value of *t must be set to zero or behavior of Table_close will be undefined // value of *t must be set to zero or behavior of Table_close will be undefined
memset(t, 0, sizeof(Table)); memset(t, 0, sizeof(Table));
@ -231,7 +237,7 @@ Result(Table*) idb_getOrCreateTable(IncrementalDB* db, str _table_name, u32 row_
} }
Result(void) idb_getRows(Table* t, u64 id, void* dst, u64 count){ Result(void) idb_getRows(Table* t, u64 id, void* dst, u64 count){
Deferral(8); Deferral(16);
// table lock // table lock
try_stderrcode(pthread_mutex_lock(&t->mutex)); try_stderrcode(pthread_mutex_lock(&t->mutex));
Defer(pthread_mutex_unlock(&t->mutex)); Defer(pthread_mutex_unlock(&t->mutex));
@ -254,7 +260,7 @@ Result(void) idb_getRows(Table* t, u64 id, void* dst, u64 count){
} }
Result(void) idb_updateRows(Table* t, u64 id, const void* src, u64 count){ Result(void) idb_updateRows(Table* t, u64 id, const void* src, u64 count){
Deferral(8); Deferral(16);
// table lock // table lock
try_stderrcode(pthread_mutex_lock(&t->mutex)); try_stderrcode(pthread_mutex_lock(&t->mutex));
Defer(pthread_mutex_unlock(&t->mutex)); Defer(pthread_mutex_unlock(&t->mutex));
@ -283,7 +289,7 @@ Result(void) idb_updateRows(Table* t, u64 id, const void* src, u64 count){
} }
Result(u64) idb_pushRows(Table* t, const void* src, u64 count){ Result(u64) idb_pushRows(Table* t, const void* src, u64 count){
Deferral(8); Deferral(16);
// table lock // table lock
try_stderrcode(pthread_mutex_lock(&t->mutex)); try_stderrcode(pthread_mutex_lock(&t->mutex));
Defer(pthread_mutex_unlock(&t->mutex)); Defer(pthread_mutex_unlock(&t->mutex));
@ -303,7 +309,7 @@ Result(u64) idb_pushRows(Table* t, const void* src, u64 count){
} }
Result(u64) idb_getRowCount(Table* t){ Result(u64) idb_getRowCount(Table* t){
Deferral(4); Deferral(8);
// table lock // table lock
try_stderrcode(pthread_mutex_lock(&t->mutex)); try_stderrcode(pthread_mutex_lock(&t->mutex));
Defer(pthread_mutex_unlock(&t->mutex)); Defer(pthread_mutex_unlock(&t->mutex));

View File

@ -1,8 +1,8 @@
#pragma once #pragma once
#include <stdio.h> #include <stdio.h>
#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 logDebug(context, format, ...) log(context, "DEBUG", format ,##__VA_ARGS__)
#define logInfo(context, format, ...) log(context, "INFO", format ,##__VA_ARGS__) #define logInfo(context, format, ...) log(context, "INFO", format ,##__VA_ARGS__)
#define logWarn(context, format, ...) log(context, "WARN", format ,##__VA_ARGS__) #define logWarning(context, format, ...) log(context, "WARNING", format ,##__VA_ARGS__)
#define logError(context, format, ...) log(context, "ERROR", format ,##__VA_ARGS__) #define logError(context, format, ...) log(context, "ERROR", format ,##__VA_ARGS__)

View File

@ -6,8 +6,8 @@
#define _DEFAULT_CONFIG_PATH_SERVER "tcp-chat-server.config" #define _DEFAULT_CONFIG_PATH_SERVER "tcp-chat-server.config"
typedef enum ProgramMode { typedef enum ProgramMode {
ClientMode, Client,
ServerMode, Server,
RsaGenStdin, RsaGenStdin,
RsaGenRandom, RsaGenRandom,
} ProgramMode; } ProgramMode;
@ -22,7 +22,7 @@ int main(const int argc, cstr const* argv){
return 1; return 1;
} }
ProgramMode mode = ClientMode; ProgramMode mode = Client;
cstr server_endpoint_cstr = NULL; cstr server_endpoint_cstr = NULL;
cstr config_path = NULL; cstr config_path = NULL;
u32 key_size = 0; u32 key_size = 0;
@ -46,12 +46,12 @@ int main(const int argc, cstr const* argv){
Return 0; Return 0;
} }
if(arg_is("-l") || arg_is("--listen")){ if(arg_is("-l") || arg_is("--listen")){
if(mode != ClientMode){ if(mode != Client){
printf("program mode is set already\n"); printf("program mode is set already\n");
Return 1; Return 1;
} }
mode = ServerMode; mode = Server;
if(++argi >= argc){ if(++argi >= argc){
printfe("ERROR: no endpoint specified\n"); printfe("ERROR: no endpoint specified\n");
Return 1; Return 1;
@ -66,7 +66,7 @@ int main(const int argc, cstr const* argv){
config_path = argv[argi]; config_path = argv[argi];
} }
else if(arg_is("--rsa-gen-stdin")){ else if(arg_is("--rsa-gen-stdin")){
if(mode != ClientMode){ if(mode != Client){
printf("program mode is set already\n"); printf("program mode is set already\n");
Return 1; Return 1;
} }
@ -81,7 +81,7 @@ int main(const int argc, cstr const* argv){
} }
else if(arg_is("--rsa-gen-random")){ else if(arg_is("--rsa-gen-random")){
if(mode != ClientMode){ if(mode != Client){
printf("program mode is set already\n"); printf("program mode is set already\n");
Return 1; Return 1;
} }
@ -106,23 +106,17 @@ int main(const int argc, cstr const* argv){
Defer(network_deinit()); Defer(network_deinit());
switch(mode){ switch(mode){
case ClientMode: { case Client: {
if(!config_path) if(config_path == NULL)
config_path = _DEFAULT_CONFIG_PATH_CLIENT; config_path = _DEFAULT_CONFIG_PATH_CLIENT;
try_fatal_void(client_run());
try_fatal(Client* client, p, Client_createFromConfig(config_path));
Defer(Client_free(client));
try_fatal_void(Client_run(client));
break; break;
} }
case ServerMode: { case Server: {
if(!config_path) if(config_path == NULL)
config_path = _DEFAULT_CONFIG_PATH_SERVER; config_path = _DEFAULT_CONFIG_PATH_SERVER;
try_fatal_void(server_run(server_endpoint_cstr, config_path));
try_fatal(Server* server, p, Server_createFromConfig(config_path));
Defer(Server_free(server));
try_fatal_void(Server_run(server, server_endpoint_cstr));
break; break;
} }

View File

@ -15,8 +15,6 @@ void EncryptedSocketTCP_construct(EncryptedSocketTCP* ptr,
} }
void EncryptedSocketTCP_destroy(EncryptedSocketTCP* ptr){ void EncryptedSocketTCP_destroy(EncryptedSocketTCP* ptr){
if(!ptr)
return;
socket_close(ptr->sock); socket_close(ptr->sock);
free(ptr->recv_buf.data); free(ptr->recv_buf.data);
free(ptr->send_buf.data); free(ptr->send_buf.data);
@ -163,9 +161,6 @@ void EncryptedSocketUDP_construct(EncryptedSocketUDP* ptr,
} }
void EncryptedSocketUDP_destroy(EncryptedSocketUDP* ptr){ void EncryptedSocketUDP_destroy(EncryptedSocketUDP* ptr){
if(!ptr)
return;
socket_close(ptr->sock); socket_close(ptr->sock);
free(ptr->recv_buf.data); free(ptr->recv_buf.data);
free(ptr->send_buf.data); free(ptr->send_buf.data);

View File

@ -21,7 +21,6 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/time.h> #include <sys/time.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <unistd.h> #include <unistd.h>

View File

@ -2,34 +2,37 @@
#include "network/tcp-chat-protocol/v1.h" #include "network/tcp-chat-protocol/v1.h"
void ClientConnection_close(ClientConnection* conn){ void ClientConnection_close(ClientConnection* conn){
if(!conn) if(conn == NULL)
return; return;
EncryptedSocketTCP_destroy(&conn->sock); EncryptedSocketTCP_destroy(&conn->sock);
free(conn->session_key.data); free(conn->session_key.data);
free(conn); free(conn);
} }
Result(ClientConnection*) ClientConnection_accept(ConnectionHandlerArgs* args) Result(ClientConnection*) ClientConnection_accept(ServerCredentials* server_credentials,
Socket sock_tcp, EndpointIPv4 client_end, u64 session_id)
{ {
Deferral(8); Deferral(32);
ClientConnection* conn = (ClientConnection*)malloc(sizeof(ClientConnection)); ClientConnection* conn = (ClientConnection*)malloc(sizeof(ClientConnection));
memset(conn, 0, sizeof(*conn)); memset(conn, 0, sizeof(*conn));
bool success = false; bool success = false;
Defer(if(!success) ClientConnection_close(conn)); Defer(
if(!success)
ClientConnection_close(conn);
);
conn->client_end = args->client_end; conn->client_end = client_end;
conn->session_id = args->session_id; conn->session_id = session_id;
conn->authorized = false;
conn->session_key = Array_alloc_size(AES_SESSION_KEY_SIZE); conn->session_key = Array_alloc_size(AES_SESSION_KEY_SIZE);
// correct session key will be received from client later // correct session key will be received from client later
Array_memset(conn->session_key, 0); Array_memset(conn->session_key, 0);
EncryptedSocketTCP_construct(&conn->sock, args->accepted_socket, NETWORK_BUFFER_SIZE, conn->session_key); EncryptedSocketTCP_construct(&conn->sock, sock_tcp, NETWORK_BUFFER_SIZE, conn->session_key);
try_void(socket_TCP_enableAliveChecks_default(args->accepted_socket)); try_void(socket_TCP_enableAliveChecks_default(sock_tcp));
// decrypt the rsa messages using server private key // decrypt the rsa messages using server private key
RSADecryptor rsa_dec; RSADecryptor rsa_dec;
RSADecryptor_construct(&rsa_dec, &args->server->cred.rsa_sk); RSADecryptor_construct(&rsa_dec, &server_credentials->rsa_sk);
// receive PacketHeader // receive PacketHeader
PacketHeader packet_header = {0}; PacketHeader packet_header = {0};
@ -49,7 +52,7 @@ Result(ClientConnection*) ClientConnection_accept(ConnectionHandlerArgs* args)
// send PacketHeader and ServerHandshake over encrypted TCP socket // send PacketHeader and ServerHandshake over encrypted TCP socket
ServerHandshake server_handshake = {0}; ServerHandshake server_handshake = {0};
ServerHandshake_construct(&server_handshake, &packet_header, ServerHandshake_construct(&server_handshake, &packet_header,
conn->session_id); session_id);
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &packet_header)); try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &packet_header));
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &server_handshake)); try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &server_handshake));

View File

@ -1,26 +1,26 @@
#include "server.h" #include "server.h"
Result(ServerCredentials*) ServerCredentials_create(cstr rsa_sk_base64, cstr rsa_pk_base64){
Result(void) ServerCredentials_tryConstruct(ServerCredentials* cred,
cstr rsa_sk_base64, cstr rsa_pk_base64)
{
Deferral(4); Deferral(4);
ServerCredentials* cred = (ServerCredentials*)malloc(sizeof(ServerCredentials));
memset(cred, 0, sizeof(*cred)); memset(cred, 0, sizeof(*cred));
bool success = false; bool success = false;
Defer(if(!success) ServerCredentials_destroy(cred)); Defer(
if(!success)
ServerCredentials_free(cred);
);
try_void(RSA_parsePrivateKey_base64(rsa_sk_base64, &cred->rsa_sk)); try_void(RSA_parsePrivateKey_base64(rsa_sk_base64, &cred->rsa_sk));
try_void(RSA_parsePublicKey_base64(rsa_pk_base64, &cred->rsa_pk)); try_void(RSA_parsePublicKey_base64(rsa_pk_base64, &cred->rsa_pk));
success = true; success = true;
Return RESULT_VOID; Return RESULT_VALUE(p, cred);
} }
void ServerCredentials_destroy(ServerCredentials* cred){ void ServerCredentials_free(ServerCredentials* cred){
if(!cred)
return;
RSA_destroyPrivateKey(&cred->rsa_sk); RSA_destroyPrivateKey(&cred->rsa_sk);
RSA_destroyPublicKey(&cred->rsa_pk); RSA_destroyPublicKey(&cred->rsa_pk);
free(cred);
} }

View File

@ -1,25 +0,0 @@
#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;
}

View File

@ -1,21 +0,0 @@
#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;
}

View File

@ -1,21 +0,0 @@
#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;
}

View File

@ -1,27 +0,0 @@
#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);

View File

@ -1,31 +0,0 @@
#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;
}

View File

@ -1,9 +0,0 @@
#include "request_handlers.h"
declare_RequestHandler(T)
{
Deferral(4);
logDebug(log_ctx, "requested %s", req_type_name);
Return RESULT_VOID;
}

View File

@ -6,28 +6,22 @@
#include "config.h" #include "config.h"
#include "log.h" #include "log.h"
#include "network/tcp-chat-protocol/v1.h" #include "network/tcp-chat-protocol/v1.h"
#include "server/request_handlers/request_handlers.h"
static void* handleConnection(void* _args); typedef struct ConnectionHandlerArgs {
static Result(void) try_handleConnection(ConnectionHandlerArgs* args, cstr log_ctx); Socket accepted_socket;
EndpointIPv4 client_end;
u64 session_id;
} ConnectionHandlerArgs;
void Server_free(Server* server){ static void* handle_connection(void* _args);
if(!server) static Result(void) try_handle_connection(ConnectionHandlerArgs* args, cstr log_ctx);
return;
free(server->name.data);
free(server->description.data);
ServerCredentials_destroy(&server->cred);
}
Result(Server*) Server_createFromConfig(cstr config_path){
Deferral(16); static ServerCredentials* _server_credentials = NULL;
cstr log_ctx = "ServerInit";
logInfo(log_ctx, "parsing config");
static Result(void) parseConfig(cstr config_path){
Server* server = (Server*)malloc(sizeof(Server)); Deferral(8);
memset(server, 0, sizeof(Server));
bool success = false;
Defer(if(!success) Server_free(server));
// open file // open file
try(FILE* config_file, p, file_open(config_path, FO_ReadExisting)); try(FILE* config_file, p, file_open(config_path, FO_ReadExisting));
@ -39,40 +33,32 @@ Result(Server*) Server_createFromConfig(cstr config_path){
try_void(file_readBytesArray(config_file, config_buf)); try_void(file_readBytesArray(config_file, config_buf));
str config_str = Array_castTo_str(config_buf, false); str config_str = Array_castTo_str(config_buf, false);
// parse name str sk_base64;
str tmp_str = str_null; str pk_base64;
try_void(config_findValue(config_str, STR("name"), &tmp_str, true)); try_void(config_findValue(config_str, STR("rsa_private_key"), &sk_base64, true));
server->name = str_copy(tmp_str); try_void(config_findValue(config_str, STR("rsa_public_key"), &pk_base64, true));
char* sk_base64_cstr = str_copy(sk_base64).data;
// parse description char* pk_base64_cstr = str_copy(pk_base64).data;
try_void(config_findValue(config_str, STR("description"), &tmp_str, true)); Defer(
server->description = str_copy(tmp_str); free(sk_base64_cstr);
free(pk_base64_cstr);
);
try(_server_credentials, p, ServerCredentials_create(sk_base64_cstr, pk_base64_cstr));
// parse rsa_private_key Return RESULT_VOID;
try_void(config_findValue(config_str, STR("rsa_private_key"), &tmp_str, true));
char* sk_base64_cstr = str_copy(tmp_str).data;
Defer(free(sk_base64_cstr));
// parse rsa_public_key
try_void(config_findValue(config_str, STR("rsa_public_key"), &tmp_str, true));
char* pk_base64_cstr = str_copy(tmp_str).data;
Defer(free(pk_base64_cstr));
try_void(ServerCredentials_tryConstruct(&server->cred, sk_base64_cstr, pk_base64_cstr));
success = true;
Return RESULT_VALUE(p, server);
} }
Result(void) Server_run(Server* server, cstr server_endpoint_cstr){ Result(void) server_run(cstr server_endpoint_cstr, cstr config_path){
Deferral(16); Deferral(32);
cstr log_ctx = "ListenerThread"; cstr log_ctx = "Server/MainThread";
logInfo(log_ctx, "starting server"); logInfo(log_ctx, "starting server");
logDebug(log_ctx, "parsing config");
EndpointIPv4 server_end; try_void(parseConfig(config_path));
try_void(EndpointIPv4_parse(server_endpoint_cstr, &server_end)); Defer(ServerCredentials_free(_server_credentials));
logDebug(log_ctx, "initializing main socket"); logDebug(log_ctx, "initializing main socket");
EndpointIPv4 server_end;
try_void(EndpointIPv4_parse(server_endpoint_cstr, &server_end));
try(Socket main_socket, i, socket_open_TCP()); try(Socket main_socket, i, socket_open_TCP());
try_void(socket_bind(main_socket, server_end)); try_void(socket_bind(main_socket, server_end));
try_void(socket_listen(main_socket, 512)); try_void(socket_listen(main_socket, 512));
@ -81,26 +67,24 @@ Result(void) Server_run(Server* server, cstr server_endpoint_cstr){
u64 session_id = 1; u64 session_id = 1;
while(true){ while(true){
ConnectionHandlerArgs* args = (ConnectionHandlerArgs*)malloc(sizeof(ConnectionHandlerArgs)); ConnectionHandlerArgs* args = (ConnectionHandlerArgs*)malloc(sizeof(ConnectionHandlerArgs));
args->server = server; try(args->accepted_socket, i, socket_accept(main_socket, &args->client_end));
try(args->accepted_socket, i,
socket_accept(main_socket, &args->client_end));
args->session_id = session_id++; args->session_id = session_id++;
pthread_t conn_thread = {0}; pthread_t conn_thread = {0};
//TODO: use async IO instead of threads to not waste system resources //TODO: use async IO instead of threads to not waste system resources
// while waiting for incoming data in 100500 threads // while waiting for incoming data in 100500 threads
try_stderrcode(pthread_create(&conn_thread, NULL, handleConnection, args)); try_stderrcode(pthread_create(&conn_thread, NULL, handle_connection, args));
try_stderrcode(pthread_detach(conn_thread)); try_stderrcode(pthread_detach(conn_thread));
} }
Return RESULT_VOID; Return RESULT_VOID;
} }
static void* handleConnection(void* _args){ static void* handle_connection(void* _args){
ConnectionHandlerArgs* args = (ConnectionHandlerArgs*)_args; ConnectionHandlerArgs* args = (ConnectionHandlerArgs*)_args;
char log_ctx[64]; char log_ctx[64];
sprintf(log_ctx, "Session-" IFWIN("%llx", "%lx"), args->session_id); sprintf(log_ctx, "Session-" IFWIN("%llx", "%lx"), args->session_id);
ResultVar(void) r = try_handleConnection(args, log_ctx); ResultVar(void) r = try_handle_connection(args, log_ctx);
if(r.error){ if(r.error){
str error_s = Error_toStr(r.error); str error_s = Error_toStr(r.error);
logError(log_ctx, "%s", error_s.data); logError(log_ctx, "%s", error_s.data);
@ -110,8 +94,8 @@ static void* handleConnection(void* _args){
return NULL; return NULL;
} }
static Result(void) try_handleConnection(ConnectionHandlerArgs* args, cstr log_ctx){ static Result(void) try_handle_connection(ConnectionHandlerArgs* args, cstr log_ctx){
Deferral(16); Deferral(64);
Defer(free(args)); Defer(free(args));
ClientConnection* conn = NULL; ClientConnection* conn = NULL;
@ -120,39 +104,100 @@ static Result(void) try_handleConnection(ConnectionHandlerArgs* args, cstr log_c
logInfo(log_ctx, "session closed"); logInfo(log_ctx, "session closed");
); );
// establish encrypted connection // establish encrypted connection
try(conn, p, ClientConnection_accept(args)); try(conn, p,
ClientConnection_accept(
_server_credentials,
args->accepted_socket,
args->client_end,
args->session_id
)
);
logInfo(log_ctx, "session accepted"); logInfo(log_ctx, "session accepted");
// handle requests // handle unauthorized requests
PacketHeader req_head = {0}; bool ahtorized = false;
PacketHeader res_head = {0}; PacketHeader req_header = {0};
while(true){ PacketHeader res_header = {0};
sleepMsec(20); while(!ahtorized){
sleepMsec(50);
//TODO: implement some additional check if socket is dead or not //TODO: implement some additional check if socket is dead or not
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req_head)); try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req_header));
try_void(PacketHeader_validateMagic(&req_head)); try_void(PacketHeader_validateMagic(&req_header));
//TODO: move request handlers to separate functions
switch(req_head.type){ switch(req_header.type){
// send error message and close connection default:{
default: Array(u8) err_buf = Array_alloc(u8, 128);
try(char* err_msg, p, bool err_complete = false;
sendErrorMessage( Defer(if(!err_complete) free(err_buf.data));
conn, &req_head, &res_head, sprintf(err_buf.data, "Received unexpected packet of type %u",
128, "Received unexpected packet of type %u", req_header.type);
req_head.type err_buf.size = strlen(err_buf.data);
)
); PacketHeader_construct(&res_header,
logWarn(log_ctx, "%s", err_msg); PROTOCOL_VERSION, PacketType_ErrorMessage, err_buf.size);
Return RESULT_VOID; try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res_header));
//TODO: limit ErrorMessage size to fit into EncryptedSocketTCP.internal_buffer_size
// unauthorized requests try_void(EncryptedSocketTCP_send(&conn->sock, err_buf));
case_handleRequest(ServerPublicInfo);
case_handleRequest(Login); err_complete = true;
case_handleRequest(Register); Return RESULT_ERROR(err_buf.data, true);
// authorized requests }
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;
}
} }
} }
// handle authorized requests
while(true){
sleepMsec(50);
}
Return RESULT_VOID; Return RESULT_VOID;
} }

View File

@ -3,17 +3,23 @@
#include "cryptography/RSA.h" #include "cryptography/RSA.h"
#include "network/encrypted_sockets.h" #include "network/encrypted_sockets.h"
typedef struct Server Server; Result(void) server_run(cstr server_endpoint_cstr, cstr config_path);
typedef struct ServerCredentials { typedef struct ServerCredentials {
br_rsa_private_key rsa_sk; br_rsa_private_key rsa_sk;
br_rsa_public_key rsa_pk; br_rsa_public_key rsa_pk;
} ServerCredentials; } ServerCredentials;
Result(void) ServerCredentials_tryConstruct(ServerCredentials* cred, Result(ServerCredentials*) ServerCredentials_create(cstr rsa_sk_base64, cstr rsa_pk_base64);
cstr rsa_sk_base64, cstr rsa_pk_base64);
void ServerCredentials_destroy(ServerCredentials* cred); void ServerCredentials_free(ServerCredentials* cred);
typedef struct ServerMetadata {
str name;
str description;
} ServerMetadata;
typedef struct ClientConnection { typedef struct ClientConnection {
@ -21,28 +27,9 @@ typedef struct ClientConnection {
EndpointIPv4 client_end; EndpointIPv4 client_end;
Array(u8) session_key; Array(u8) session_key;
EncryptedSocketTCP sock; EncryptedSocketTCP sock;
bool authorized;
} ClientConnection; } ClientConnection;
Result(ClientConnection*) ClientConnection_accept(ServerCredentials* server_credentials,
Socket sock, EndpointIPv4 client_end, u64 session_id);
typedef struct ConnectionHandlerArgs { void ClientConnection_close(ClientConnection* conn);
Server* server;
Socket accepted_socket;
EndpointIPv4 client_end;
u64 session_id;
} ConnectionHandlerArgs;
Result(ClientConnection*) ClientConnection_accept(ConnectionHandlerArgs* args);
void ClientConnection_close(ClientConnection* conn);
typedef struct Server {
str name;
str description;
ServerCredentials cred;
} Server;
Result(Server*) Server_createFromConfig(cstr config_path);
void Server_free(Server* server);
Result(void) Server_run(Server* server, cstr server_endpoint_cstr);