added new packet types
This commit is contained in:
parent
13ccfc7ff9
commit
ea4a649e00
2
dependencies/tlibc
vendored
2
dependencies/tlibc
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 30c141f587ac8fa635812c6f4713dbc20b18d7c9
|
Subproject commit d6436d08338a0a762e727f0c816dd5a09782b180
|
||||||
@ -63,18 +63,16 @@ Result(ServerConnection*) ServerConnection_open(ClientCredentials* client_creden
|
|||||||
|
|
||||||
// connect to server address
|
// connect to server address
|
||||||
try(Socket _s, i, socket_open_TCP());
|
try(Socket _s, i, socket_open_TCP());
|
||||||
try_void(socket_setTimeout(_s, SOCKET_TIMEOUT_MS_DEFAULT));
|
try_void(socket_TCP_enableAliveChecks_default(_s));
|
||||||
try_void(socket_connect(_s, conn->server_end));
|
try_void(socket_connect(_s, conn->server_end));
|
||||||
EncryptedSocketTCP_construct(&conn->sock, _s, NETWORK_BUFFER_SIZE, conn->session_key);
|
EncryptedSocketTCP_construct(&conn->sock, _s, NETWORK_BUFFER_SIZE, conn->session_key);
|
||||||
|
|
||||||
// send PacketHeader and ClientHandshake
|
// send PacketHeader and ClientHandshake
|
||||||
// encryption by server public key
|
// encryption by server public key
|
||||||
PacketHeader packet_header = {0};
|
PacketHeader packet_header = {0};
|
||||||
PacketHeader_construct(&packet_header,
|
|
||||||
PROTOCOL_VERSION, PacketType_ClientHandshake, sizeof(ClientHandshake));
|
|
||||||
ClientHandshake client_handshake = {0};
|
ClientHandshake client_handshake = {0};
|
||||||
ClientHandshake_construct(&client_handshake,
|
try_void(ClientHandshake_tryConstruct(&client_handshake, &packet_header,
|
||||||
conn->session_key);
|
conn->session_key));
|
||||||
try_void(EncryptedSocketTCP_sendStructRSA(&conn->sock, &conn->rsa_enc, &packet_header));
|
try_void(EncryptedSocketTCP_sendStructRSA(&conn->sock, &conn->rsa_enc, &packet_header));
|
||||||
try_void(EncryptedSocketTCP_sendStructRSA(&conn->sock, &conn->rsa_enc, &client_handshake));
|
try_void(EncryptedSocketTCP_sendStructRSA(&conn->sock, &conn->rsa_enc, &client_handshake));
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "term.h"
|
#include "term.h"
|
||||||
#include "tlibc/time.h"
|
#include "tlibc/time.h"
|
||||||
|
#include "network/tcp-chat-protocol/v1.h"
|
||||||
|
|
||||||
static const str greeting_art = STR(
|
static const str greeting_art = STR(
|
||||||
" ^,,^ ╱|\n"
|
" ^,,^ ╱|\n"
|
||||||
@ -24,21 +25,22 @@ static Result(void) commandExec(str command, bool* stop);
|
|||||||
static Result(void) askUserNameAndPassword(ClientCredentials** cred){
|
static Result(void) askUserNameAndPassword(ClientCredentials** cred){
|
||||||
Deferral(8);
|
Deferral(8);
|
||||||
|
|
||||||
char username_buf[1024];
|
char username_buf[128];
|
||||||
str usrername = str_null;
|
str username = str_null;
|
||||||
while(true) {
|
while(true) {
|
||||||
printf("username: ");
|
printf("username: ");
|
||||||
if(fgets(username_buf, sizeof(username_buf), stdin) == NULL){
|
if(fgets(username_buf, sizeof(username_buf), stdin) == NULL){
|
||||||
Return RESULT_ERROR("STDIN is closed", false);
|
Return RESULT_ERROR("STDIN is closed", false);
|
||||||
}
|
}
|
||||||
usrername = str_from_cstr(username_buf);
|
username = str_from_cstr(username_buf);
|
||||||
if(usrername.size < 4){
|
if(username.size < USERNAME_SIZE_MIN || username.size > USERNAME_SIZE_MAX){
|
||||||
printf("ERROR: username length must be at least 4\n");
|
printf("ERROR: username length (in bytes) must be >= %i and <= %i\n",
|
||||||
|
USERNAME_SIZE_MIN, USERNAME_SIZE_MAX);
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
char password_buf[1024];
|
char password_buf[128];
|
||||||
str password = str_null;
|
str password = str_null;
|
||||||
while(true) {
|
while(true) {
|
||||||
printf("password: ");
|
printf("password: ");
|
||||||
@ -47,13 +49,14 @@ 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);
|
||||||
if(password.size < 8){
|
if(password.size < PASSWORD_SIZE_MIN || password.size > PASSWORD_SIZE_MAX){
|
||||||
printf("ERROR: password length must be at least 8\n");
|
printf("ERROR: password length (in bytes) must be >= %i and <= %i\n",
|
||||||
|
PASSWORD_SIZE_MIN, PASSWORD_SIZE_MAX);
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
try(*cred, p, ClientCredentials_create(usrername, password));
|
try(*cred, p, ClientCredentials_create(username, password));
|
||||||
Return RESULT_VOID;
|
Return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +90,7 @@ Result(void) client_run() {
|
|||||||
if(command_input.size == 0)
|
if(command_input.size == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Result(void) com_result = commandExec(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);
|
||||||
@ -139,11 +142,21 @@ static Result(void) commandExec(str command, bool* stop){
|
|||||||
// TODO: request server info
|
// TODO: request server info
|
||||||
// show server info
|
// show server info
|
||||||
// save server info to user's db
|
// save server info to user's db
|
||||||
// request log in
|
// try log in
|
||||||
// if not registered, request registration and then log in
|
// if not registered, request registration and then log in
|
||||||
|
|
||||||
|
// call serverConnection_run():
|
||||||
|
// function with infinite loop which sends and receives messages
|
||||||
|
// with navigation across server channels
|
||||||
|
//
|
||||||
}
|
}
|
||||||
else if(is_alias("c") || is_alias("connect")){
|
else if(is_alias("c") || is_alias("connect")){
|
||||||
// TODO: read saved servers from database
|
// TODO: read saved servers from database
|
||||||
|
// show scrollable list of them
|
||||||
|
// select one
|
||||||
|
// try log in
|
||||||
|
// if not registered, ask user if they want to register
|
||||||
|
// regiser and then log in
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Return RESULT_ERROR_FMT("unknown kommand: '%s'\n"
|
Return RESULT_ERROR_FMT("unknown kommand: '%s'\n"
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
//TODO: use PKS#7 instead of this garbage
|
//TODO: use PKS#7 instead of this garbage
|
||||||
typedef struct EncryptedBlockHeader {
|
typedef struct EncryptedBlockHeader {
|
||||||
u8 padding_size;
|
u8 padding_size;
|
||||||
} __attribute__((aligned(16))) EncryptedBlockHeader;
|
} ATTRIBUTE_ALIGNED(16) EncryptedBlockHeader;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// AESBlockEncryptor //
|
// AESBlockEncryptor //
|
||||||
|
|||||||
10
src/db/idb.c
10
src/db/idb.c
@ -9,7 +9,7 @@ typedef struct TableFileHeader {
|
|||||||
u16 version;
|
u16 version;
|
||||||
bool _dirty_bit;
|
bool _dirty_bit;
|
||||||
u32 row_size;
|
u32 row_size;
|
||||||
} __attribute__((aligned(256))) TableFileHeader;
|
} ATTRIBUTE_ALIGNED(256) TableFileHeader;
|
||||||
|
|
||||||
typedef struct Table {
|
typedef struct Table {
|
||||||
TableFileHeader header;
|
TableFileHeader header;
|
||||||
@ -133,7 +133,7 @@ Result(void) Table_validateHeader(Table* t){
|
|||||||
|
|
||||||
Result(void) Table_validateRowSize(Table* t, u32 row_size){
|
Result(void) Table_validateRowSize(Table* t, u32 row_size){
|
||||||
if(row_size != t->header.row_size){
|
if(row_size != t->header.row_size){
|
||||||
Result(void) error_result = RESULT_ERROR_FMT(
|
ResultVar(void) error_result = RESULT_ERROR_FMT(
|
||||||
"Requested row size (%u) doesn't match saved row size (%u)",
|
"Requested row size (%u) doesn't match saved row size (%u)",
|
||||||
row_size, t->header.row_size);
|
row_size, t->header.row_size);
|
||||||
return error_result;
|
return error_result;
|
||||||
@ -226,7 +226,7 @@ Result(Table*) idb_getOrCreateTable(IncrementalDB* db, str _table_name, u32 row_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!HashMap_tryPush(&db->tables_map, t->name, &t)){
|
if(!HashMap_tryPush(&db->tables_map, t->name, &t)){
|
||||||
Result(void) error_result = RESULT_ERROR_FMT(
|
ResultVar(void) error_result = RESULT_ERROR_FMT(
|
||||||
"Table '%s' is already open",
|
"Table '%s' is already open",
|
||||||
t->name.data);
|
t->name.data);
|
||||||
Return error_result;
|
Return error_result;
|
||||||
@ -273,7 +273,7 @@ Result(void) idb_updateRows(Table* t, u64 id, const void* src, u64 count){
|
|||||||
}
|
}
|
||||||
|
|
||||||
try_void(Table_setDirtyBit(t, true));
|
try_void(Table_setDirtyBit(t, true));
|
||||||
Defer(Table_setDirtyBit(t, false));
|
Defer(IGNORE_RESULT Table_setDirtyBit(t, false));
|
||||||
|
|
||||||
i64 file_pos = sizeof(t->header) + id * t->header.row_size;
|
i64 file_pos = sizeof(t->header) + id * t->header.row_size;
|
||||||
|
|
||||||
@ -295,7 +295,7 @@ Result(u64) idb_pushRows(Table* t, const void* src, u64 count){
|
|||||||
Defer(pthread_mutex_unlock(&t->mutex));
|
Defer(pthread_mutex_unlock(&t->mutex));
|
||||||
|
|
||||||
try_void(Table_setDirtyBit(t, true));
|
try_void(Table_setDirtyBit(t, true));
|
||||||
Defer(Table_setDirtyBit(t, false));
|
Defer(IGNORE_RESULT Table_setDirtyBit(t, false));
|
||||||
|
|
||||||
const u64 new_row_index = t->row_count;
|
const u64 new_row_index = t->row_count;
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,25 @@ Result(void) PacketHeader_validateMagic(PacketHeader* ptr){
|
|||||||
return RESULT_VOID;
|
return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result(void) PacketHeader_validateType(PacketHeader* ptr, u16 expected_type){
|
||||||
|
if(ptr->type != expected_type){
|
||||||
|
return RESULT_ERROR_FMT(
|
||||||
|
"expected message of type %u, but received of type %u",
|
||||||
|
expected_type, ptr->type);
|
||||||
|
}
|
||||||
|
return RESULT_VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_size, ptr->content_size);
|
||||||
|
}
|
||||||
|
return RESULT_VOID;
|
||||||
|
}
|
||||||
|
|
||||||
void PacketHeader_construct(PacketHeader* ptr, u8 protocol_version, u16 type, u64 content_size){
|
void PacketHeader_construct(PacketHeader* ptr, u8 protocol_version, u16 type, u64 content_size){
|
||||||
ptr->magic.n = PacketHeader_MAGIC.n;
|
ptr->magic.n = PacketHeader_MAGIC.n;
|
||||||
ptr->protocol_version = protocol_version;
|
ptr->protocol_version = protocol_version;
|
||||||
|
|||||||
@ -14,7 +14,9 @@ typedef struct PacketHeader {
|
|||||||
u16 type;
|
u16 type;
|
||||||
u32 _reserved4;
|
u32 _reserved4;
|
||||||
u64 content_size;
|
u64 content_size;
|
||||||
} __attribute__((aligned(64))) PacketHeader;
|
} ATTRIBUTE_ALIGNED(64) PacketHeader;
|
||||||
|
|
||||||
void PacketHeader_construct(PacketHeader* ptr, u8 protocol_version, u16 type, u64 content_size);
|
void PacketHeader_construct(PacketHeader* ptr, u8 protocol_version, u16 type, u64 content_size);
|
||||||
Result(void) PacketHeader_validateMagic(PacketHeader* ptr);
|
Result(void) PacketHeader_validateMagic(PacketHeader* ptr);
|
||||||
|
Result(void) PacketHeader_validateType(PacketHeader* ptr, u16 expected_type);
|
||||||
|
Result(void) PacketHeader_validateContentSize(PacketHeader* ptr, u64 expected_size);
|
||||||
|
|||||||
@ -1,9 +1,73 @@
|
|||||||
#include "v1.h"
|
#include "v1.h"
|
||||||
|
|
||||||
void ClientHandshake_construct(ClientHandshake* ptr, Array(u8) session_key){
|
#define _PacketHeader_construct(T) \
|
||||||
memcpy(ptr->session_key, session_key.data, sizeof(ptr->session_key));
|
PacketHeader_construct(header, PROTOCOL_VERSION, PacketType_##T, sizeof(T))
|
||||||
|
|
||||||
|
Result(void) ClientHandshake_tryConstruct(ClientHandshake* ptr, PacketHeader* header,
|
||||||
|
Array(u8) session_key)
|
||||||
|
{
|
||||||
|
Deferral(1);
|
||||||
|
_PacketHeader_construct(ClientHandshake);
|
||||||
|
|
||||||
|
try_assert(session_key.size == sizeof(ptr->session_key));
|
||||||
|
memcpy(ptr->session_key, session_key.data, session_key.size);
|
||||||
|
|
||||||
|
Return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerHandshake_construct(ServerHandshake* ptr, u64 session_id){
|
void ServerHandshake_construct(ServerHandshake* ptr, PacketHeader* header,
|
||||||
|
u64 session_id)
|
||||||
|
{
|
||||||
|
_PacketHeader_construct(ServerHandshake);
|
||||||
ptr->session_id = session_id;
|
ptr->session_id = session_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerPublicInfoRequest_construct(ServerPublicInfoRequest *ptr, PacketHeader* header,
|
||||||
|
ServerPublicInfo property)
|
||||||
|
{
|
||||||
|
_PacketHeader_construct(ServerPublicInfoRequest);
|
||||||
|
ptr->property = property;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result(void) LoginRequest_tryConstruct(LoginRequest *ptr, PacketHeader* header,
|
||||||
|
Array(u8) token)
|
||||||
|
{
|
||||||
|
Deferral(1);
|
||||||
|
_PacketHeader_construct(LoginRequest);
|
||||||
|
|
||||||
|
try_assert(token.size == sizeof(ptr->token));
|
||||||
|
memcpy(ptr->token, token.data, token.size);
|
||||||
|
|
||||||
|
Return RESULT_VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoginResponse_construct(LoginResponse* ptr, PacketHeader* header,
|
||||||
|
u64 user_id, u64 landing_channel_id)
|
||||||
|
{
|
||||||
|
_PacketHeader_construct(LoginResponse);
|
||||||
|
ptr->user_id = user_id;
|
||||||
|
ptr->landing_channel_id = landing_channel_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result(void) RegisterRequest_tryConstruct(RegisterRequest *ptr, PacketHeader* header,
|
||||||
|
str username, Array(u8) token)
|
||||||
|
{
|
||||||
|
Deferral(1);
|
||||||
|
_PacketHeader_construct(RegisterRequest);
|
||||||
|
|
||||||
|
try_assert(username.size >= USERNAME_SIZE_MIN && username.size <= USERNAME_SIZE_MAX);
|
||||||
|
ptr->username_size = username.size;
|
||||||
|
memcpy(ptr->username, username.data, username.size);
|
||||||
|
|
||||||
|
try_assert(token.size == sizeof(ptr->token));
|
||||||
|
memcpy(ptr->token, token.data, token.size);
|
||||||
|
|
||||||
|
Return RESULT_VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterResponse_construct(RegisterResponse *ptr, PacketHeader* header,
|
||||||
|
u64 user_id)
|
||||||
|
{
|
||||||
|
_PacketHeader_construct(RegisterResponse);
|
||||||
|
ptr->user_id = user_id;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,32 +1,105 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "tlibc/errors.h"
|
#include "tlibc/errors.h"
|
||||||
|
#include "tlibc/string/str.h"
|
||||||
#include "network/tcp-chat-protocol/constant.h"
|
#include "network/tcp-chat-protocol/constant.h"
|
||||||
|
#include "cryptography/cryptography.h"
|
||||||
|
|
||||||
#define PROTOCOL_VERSION 1 /* 1.0.0 */
|
#define PROTOCOL_VERSION 1 /* 1.0.0 */
|
||||||
#define NETWORK_BUFFER_SIZE 65536
|
#define NETWORK_BUFFER_SIZE 65536
|
||||||
|
|
||||||
|
#define ALIGN_PACKET_STRUCT ATTRIBUTE_ALIGNED(8)
|
||||||
|
|
||||||
|
|
||||||
typedef enum PacketType {
|
typedef enum PacketType {
|
||||||
PacketType_Invalid,
|
PacketType_Invalid,
|
||||||
PacketType_ErrorMessage,
|
PacketType_ErrorMessage,
|
||||||
PacketType_ClientHandshake,
|
PacketType_ClientHandshake,
|
||||||
PacketType_ServerHandshake,
|
PacketType_ServerHandshake,
|
||||||
} __attribute__((__packed__)) PacketType;
|
PacketType_ServerPublicInfoRequest,
|
||||||
|
PacketType_ServerPublicInfoResponse,
|
||||||
|
PacketType_LoginRequest,
|
||||||
|
PacketType_LoginResponse,
|
||||||
|
PacketType_RegisterRequest,
|
||||||
|
PacketType_RegisterResponse,
|
||||||
|
} ATTRIBUTE_PACKED PacketType;
|
||||||
|
|
||||||
|
|
||||||
typedef struct ErrorMessage {
|
// typedef struct ErrorMessage {
|
||||||
/* content stream of size `header.content_size` */
|
// /* stream of size header.content_size */
|
||||||
} ErrorMessage;
|
// } ErrorMessage;
|
||||||
|
|
||||||
|
|
||||||
typedef struct ClientHandshake {
|
typedef struct ClientHandshake {
|
||||||
u8 session_key[AES_SESSION_KEY_SIZE];
|
u8 session_key[AES_SESSION_KEY_SIZE];
|
||||||
} ClientHandshake;
|
} ALIGN_PACKET_STRUCT ClientHandshake;
|
||||||
|
|
||||||
void ClientHandshake_construct(ClientHandshake* ptr, Array(u8) session_key);
|
Result(void) ClientHandshake_tryConstruct(ClientHandshake* ptr, PacketHeader* header,
|
||||||
|
Array(u8) session_key);
|
||||||
|
|
||||||
|
|
||||||
typedef struct ServerHandshake {
|
typedef struct ServerHandshake {
|
||||||
u64 session_id;
|
u64 session_id;
|
||||||
} ServerHandshake;
|
} ALIGN_PACKET_STRUCT ServerHandshake;
|
||||||
|
|
||||||
|
void ServerHandshake_construct(ServerHandshake* ptr, PacketHeader* header,
|
||||||
|
u64 session_id);
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum ServerPublicInfo {
|
||||||
|
ServerPublicInfo_Name,
|
||||||
|
ServerPublicInfo_Description,
|
||||||
|
} ATTRIBUTE_PACKED ServerPublicInfo;
|
||||||
|
|
||||||
|
typedef struct ServerPublicInfoRequest {
|
||||||
|
u32 property;
|
||||||
|
} ALIGN_PACKET_STRUCT ServerPublicInfoRequest;
|
||||||
|
|
||||||
|
void ServerPublicInfoRequest_construct(ServerPublicInfoRequest* ptr, PacketHeader* header,
|
||||||
|
ServerPublicInfo property);
|
||||||
|
|
||||||
|
|
||||||
|
// typedef struct ServerPublicInfoResponse {
|
||||||
|
// /* stream of size header.content_size */
|
||||||
|
// } ServerPublicInfoResponse;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct LoginRequest {
|
||||||
|
u8 token[PASSWORD_HASH_SIZE];
|
||||||
|
} ALIGN_PACKET_STRUCT LoginRequest;
|
||||||
|
|
||||||
|
Result(void) LoginRequest_tryConstruct(LoginRequest* ptr, PacketHeader* header,
|
||||||
|
Array(u8) token);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct LoginResponse {
|
||||||
|
u64 user_id;
|
||||||
|
u64 landing_channel_id;
|
||||||
|
} ALIGN_PACKET_STRUCT LoginResponse;
|
||||||
|
|
||||||
|
void LoginResponse_construct(LoginResponse* ptr, PacketHeader* header,
|
||||||
|
u64 user_id, u64 landing_channel_id);
|
||||||
|
|
||||||
|
|
||||||
|
#define USERNAME_SIZE_MIN 4
|
||||||
|
#define USERNAME_SIZE_MAX 64
|
||||||
|
#define PASSWORD_SIZE_MIN 8
|
||||||
|
#define PASSWORD_SIZE_MAX 32
|
||||||
|
|
||||||
|
typedef struct RegisterRequest {
|
||||||
|
u32 username_size;
|
||||||
|
char username[USERNAME_SIZE_MAX];
|
||||||
|
u8 token[PASSWORD_HASH_SIZE];
|
||||||
|
} ALIGN_PACKET_STRUCT RegisterRequest;
|
||||||
|
|
||||||
|
Result(void) RegisterRequest_tryConstruct(RegisterRequest* ptr, PacketHeader* header,
|
||||||
|
str username, Array(u8) token);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct RegisterResponse {
|
||||||
|
u64 user_id;
|
||||||
|
} ALIGN_PACKET_STRUCT RegisterResponse;
|
||||||
|
|
||||||
|
void RegisterResponse_construct(RegisterResponse* ptr, PacketHeader* header,
|
||||||
|
u64 user_id);
|
||||||
|
|
||||||
|
|
||||||
void ServerHandshake_construct(ServerHandshake* ptr, u64 session_id);
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ Result(ClientConnection*) ClientConnection_accept(ServerCredentials* server_cred
|
|||||||
// 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, sock_tcp, NETWORK_BUFFER_SIZE, conn->session_key);
|
EncryptedSocketTCP_construct(&conn->sock, sock_tcp, NETWORK_BUFFER_SIZE, conn->session_key);
|
||||||
try_void(socket_setTimeout(sock_tcp, SOCKET_TIMEOUT_MS_DEFAULT));
|
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;
|
||||||
@ -38,12 +38,8 @@ Result(ClientConnection*) ClientConnection_accept(ServerCredentials* server_cred
|
|||||||
PacketHeader packet_header = {0};
|
PacketHeader packet_header = {0};
|
||||||
try_void(EncryptedSocketTCP_recvStructRSA(&conn->sock, &rsa_dec, &packet_header));
|
try_void(EncryptedSocketTCP_recvStructRSA(&conn->sock, &rsa_dec, &packet_header));
|
||||||
try_void(PacketHeader_validateMagic(&packet_header));
|
try_void(PacketHeader_validateMagic(&packet_header));
|
||||||
if(packet_header.type != PacketType_ClientHandshake){
|
try_void(PacketHeader_validateType(&packet_header, PacketType_ClientHandshake));
|
||||||
Return RESULT_ERROR_FMT(
|
try_void(PacketHeader_validateContentSize(&packet_header, sizeof(ClientHandshake)));
|
||||||
"received message of unexpected type: %u",
|
|
||||||
packet_header.type
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// receive ClientHandshake
|
// receive ClientHandshake
|
||||||
ClientHandshake client_handshake = {0};
|
ClientHandshake client_handshake = {0};
|
||||||
@ -54,10 +50,8 @@ Result(ClientConnection*) ClientConnection_accept(ServerCredentials* server_cred
|
|||||||
EncryptedSocketTCP_changeKey(&conn->sock, conn->session_key);
|
EncryptedSocketTCP_changeKey(&conn->sock, conn->session_key);
|
||||||
|
|
||||||
// send PacketHeader and ServerHandshake over encrypted TCP socket
|
// send PacketHeader and ServerHandshake over encrypted TCP socket
|
||||||
PacketHeader_construct(&packet_header,
|
|
||||||
PROTOCOL_VERSION, PacketType_ServerHandshake, sizeof(ServerHandshake));
|
|
||||||
ServerHandshake server_handshake = {0};
|
ServerHandshake server_handshake = {0};
|
||||||
ServerHandshake_construct(&server_handshake,
|
ServerHandshake_construct(&server_handshake, &packet_header,
|
||||||
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));
|
||||||
|
|||||||
@ -58,7 +58,7 @@ Result(void) server_run(cstr server_endpoint_cstr, cstr config_path){
|
|||||||
|
|
||||||
logDebug(log_ctx, "initializing main socket");
|
logDebug(log_ctx, "initializing main socket");
|
||||||
EndpointIPv4 server_end;
|
EndpointIPv4 server_end;
|
||||||
EndpointIPv4_parse(server_endpoint_cstr, &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));
|
||||||
@ -84,7 +84,7 @@ static void* handle_connection(void* _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);
|
||||||
|
|
||||||
Result(void) r = try_handle_connection(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);
|
||||||
@ -115,9 +115,88 @@ static Result(void) try_handle_connection(ConnectionHandlerArgs* args, cstr log_
|
|||||||
logInfo(log_ctx, "session accepted");
|
logInfo(log_ctx, "session accepted");
|
||||||
|
|
||||||
// handle unauthorized requests
|
// handle unauthorized requests
|
||||||
while(true){
|
bool ahtorized = false;
|
||||||
|
PacketHeader req_header = {0};
|
||||||
|
PacketHeader res_header = {0};
|
||||||
|
while(!ahtorized){
|
||||||
|
sleepMsec(50);
|
||||||
|
//TODO: implement some additional check if socket is dead or not
|
||||||
|
|
||||||
sleepMsec(10);
|
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req_header));
|
||||||
|
try_void(PacketHeader_validateMagic(&req_header));
|
||||||
|
//TODO: move request handlers to separate functions
|
||||||
|
switch(req_header.type){
|
||||||
|
default:{
|
||||||
|
Array(u8) err_buf = Array_alloc(u8, 128);
|
||||||
|
bool err_complete = false;
|
||||||
|
Defer(if(!err_complete) free(err_buf.data));
|
||||||
|
sprintf(err_buf.data, "Received unexpected packet of type %u",
|
||||||
|
req_header.type);
|
||||||
|
err_buf.size = strlen(err_buf.data);
|
||||||
|
|
||||||
|
PacketHeader_construct(&res_header,
|
||||||
|
PROTOCOL_VERSION, PacketType_ErrorMessage, err_buf.size);
|
||||||
|
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res_header));
|
||||||
|
//TODO: limit ErrorMessage size to fit into EncryptedSocketTCP.internal_buffer_size
|
||||||
|
try_void(EncryptedSocketTCP_send(&conn->sock, err_buf));
|
||||||
|
|
||||||
|
err_complete = true;
|
||||||
|
Return RESULT_ERROR(err_buf.data, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user