Compare commits
2 Commits
9942d94c94
...
85c0736c8d
| Author | SHA1 | Date | |
|---|---|---|---|
| 85c0736c8d | |||
| 0ea241c5db |
29
README.md
Normal file
29
README.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# tcp-chat
|
||||||
|
|
||||||
|
## Build
|
||||||
|
1. Clone the repository with submodules.
|
||||||
|
```
|
||||||
|
git clone --recurse-submodules --depth 0 https://timerix.ddns.net/git/Timerix/tcp-chat.git
|
||||||
|
```
|
||||||
|
2. Install [cbuild](https://timerix.ddns.net/git/Timerix/cbuild).
|
||||||
|
3. Build executable
|
||||||
|
```
|
||||||
|
cd tcp-chat
|
||||||
|
cbuild build_exec
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
**Client:**
|
||||||
|
```sh
|
||||||
|
cd bin
|
||||||
|
./tcp-chat
|
||||||
|
```
|
||||||
|
**Server:**
|
||||||
|
1. ```sh
|
||||||
|
cp tcp-chat-server.config.default bin/tcp-chat-server.config
|
||||||
|
```
|
||||||
|
2. Edit config
|
||||||
|
3. ```sh
|
||||||
|
cd bin
|
||||||
|
./tcp-chat -l
|
||||||
|
```
|
||||||
2
dependencies/tlibc
vendored
2
dependencies/tlibc
vendored
@ -1 +1 @@
|
|||||||
Subproject commit ae0fa95d6aee2a7427c3e3575d74af1ed360e6e5
|
Subproject commit 425794361bc52240bb50001becbb5fb6e9ebcf20
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "network/tcp-chat-protocol/v1.h"
|
#include "requests/requests.h"
|
||||||
|
|
||||||
void ServerConnection_close(ServerConnection* conn){
|
void ServerConnection_close(ServerConnection* conn){
|
||||||
if(!conn)
|
if(!conn)
|
||||||
@ -7,6 +7,8 @@ void ServerConnection_close(ServerConnection* conn){
|
|||||||
RSA_destroyPublicKey(&conn->server_pk);
|
RSA_destroyPublicKey(&conn->server_pk);
|
||||||
EncryptedSocketTCP_destroy(&conn->sock);
|
EncryptedSocketTCP_destroy(&conn->sock);
|
||||||
free(conn->session_key.data);
|
free(conn->session_key.data);
|
||||||
|
free(conn->name.data);
|
||||||
|
free(conn->description.data);
|
||||||
free(conn);
|
free(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,52 +66,38 @@ Result(ServerConnection*) ServerConnection_open(cstr server_link_cstr){
|
|||||||
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 ClientHandshake using server public key for encryption
|
||||||
// encryption by server public key
|
PacketHeader req_header;
|
||||||
PacketHeader packet_header;
|
|
||||||
ClientHandshake client_handshake;
|
ClientHandshake client_handshake;
|
||||||
try_void(ClientHandshake_tryConstruct(&client_handshake, &packet_header,
|
try_void(ClientHandshake_tryConstruct(&client_handshake, &req_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, &req_header));
|
||||||
try_void(EncryptedSocketTCP_sendStructRSA(&conn->sock, &conn->rsa_enc, &client_handshake));
|
try_void(EncryptedSocketTCP_sendStructRSA(&conn->sock, &conn->rsa_enc, &client_handshake));
|
||||||
|
|
||||||
// receive server response
|
// receive server response
|
||||||
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &packet_header));
|
PacketHeader res_header;
|
||||||
try_void(PacketHeader_validateMagic(&packet_header));
|
ServerHandshake server_handshake;
|
||||||
|
try_void(recvResponse(&conn->sock, &res_header, &server_handshake,
|
||||||
|
PacketType_ServerHandshake));
|
||||||
|
conn->session_id = server_handshake.session_id;
|
||||||
|
|
||||||
// handle server response
|
// get server name
|
||||||
switch(packet_header.type){
|
ServerPublicInfoRequest public_info_req;
|
||||||
case PacketType_ErrorMessage: {
|
ServerPublicInfoResponse public_info_res;
|
||||||
ErrorMessage err_msg;
|
ServerPublicInfoRequest_construct(&public_info_req, &req_header,
|
||||||
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &err_msg));
|
ServerPublicInfo_Name);
|
||||||
if(err_msg.msg_size > conn->sock.recv_buf.size)
|
try_void(sendRequest(&conn->sock, &req_header, &public_info_req));
|
||||||
err_msg.msg_size = conn->sock.recv_buf.size;
|
try_void(recvResponse(&conn->sock, &res_header, &public_info_res,
|
||||||
Array(u8) err_buf = Array_alloc_size(err_msg.msg_size + 1);
|
PacketType_ServerPublicInfoResponse));
|
||||||
bool err_msg_completed = false;
|
try_void(recvStr(&conn->sock, public_info_res.data_size, &conn->name));
|
||||||
Defer(if(!err_msg_completed) free(err_buf.data));
|
|
||||||
|
|
||||||
// receive message content
|
// get server description
|
||||||
try_void(
|
ServerPublicInfoRequest_construct(&public_info_req, &req_header,
|
||||||
EncryptedSocketTCP_recv(
|
ServerPublicInfo_Description);
|
||||||
&conn->sock,
|
try_void(sendRequest(&conn->sock, &req_header, &public_info_req));
|
||||||
Array_sliceTo(err_buf, err_msg.msg_size),
|
try_void(recvResponse(&conn->sock, &res_header, &public_info_res,
|
||||||
SocketRecvFlag_WholeBuffer
|
PacketType_ServerPublicInfoResponse));
|
||||||
)
|
try_void(recvStr(&conn->sock, public_info_res.data_size, &conn->description));
|
||||||
);
|
|
||||||
|
|
||||||
((u8*)err_buf.data)[err_msg.msg_size] = 0;
|
|
||||||
err_msg_completed = true;
|
|
||||||
Return RESULT_ERROR((char*)err_buf.data, true);
|
|
||||||
}
|
|
||||||
case PacketType_ServerHandshake: {
|
|
||||||
ServerHandshake server_handshake;
|
|
||||||
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &server_handshake));
|
|
||||||
conn->session_id = server_handshake.session_id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
Return RESULT_ERROR_FMT("unexpected response type: %i", packet_header.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
Return RESULT_VALUE(p, conn);
|
Return RESULT_VALUE(p, conn);
|
||||||
|
|||||||
@ -157,24 +157,18 @@ static Result(void) commandExec(Client* client, str command, bool* stop){
|
|||||||
ServerConnection_open(new_server_link.data));
|
ServerConnection_open(new_server_link.data));
|
||||||
printf("connection established\n");
|
printf("connection established\n");
|
||||||
|
|
||||||
// TODO: request server info
|
// TODO: show server info
|
||||||
// show server info
|
// TODO: save server info to user's db
|
||||||
// save server info to user's db
|
// TODO: ask in loop: log in / register
|
||||||
// try log in
|
|
||||||
// if not registered, request registration and then log in
|
|
||||||
|
|
||||||
// call Client_runIO():
|
//TODO: call Client_runIO():
|
||||||
// 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
|
||||||
//
|
|
||||||
}
|
}
|
||||||
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
|
// TODO: show scrollable list of servers, get selected one
|
||||||
// select one
|
// TODO: ask in loop: log in / register
|
||||||
// try log in
|
|
||||||
// if not registered, ask user if they want to register
|
|
||||||
// regiser and then log in
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("ERROR: unknown command.\n"
|
printf("ERROR: unknown command.\n"
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#include "cryptography/AES.h"
|
#include "cryptography/AES.h"
|
||||||
#include "cryptography/RSA.h"
|
#include "cryptography/RSA.h"
|
||||||
#include "network/encrypted_sockets.h"
|
#include "network/encrypted_sockets.h"
|
||||||
|
#include "tlibc/string/str.h"
|
||||||
|
|
||||||
typedef struct Client Client;
|
typedef struct Client Client;
|
||||||
|
|
||||||
@ -20,16 +21,17 @@ void ClientCredentials_destroy(ClientCredentials* cred);
|
|||||||
|
|
||||||
|
|
||||||
typedef struct ServerConnection {
|
typedef struct ServerConnection {
|
||||||
u64 session_id;
|
|
||||||
EndpointIPv4 server_end;
|
EndpointIPv4 server_end;
|
||||||
br_rsa_public_key server_pk;
|
br_rsa_public_key server_pk;
|
||||||
RSAEncryptor rsa_enc;
|
RSAEncryptor rsa_enc;
|
||||||
|
u64 session_id;
|
||||||
Array(u8) session_key;
|
Array(u8) session_key;
|
||||||
EncryptedSocketTCP sock;
|
EncryptedSocketTCP sock;
|
||||||
|
str name;
|
||||||
|
str description;
|
||||||
} ServerConnection;
|
} ServerConnection;
|
||||||
|
|
||||||
Result(ServerConnection*) ServerConnection_open(cstr server_link_cstr);
|
Result(ServerConnection*) ServerConnection_open(cstr server_link_cstr);
|
||||||
|
|
||||||
void ServerConnection_close(ServerConnection* conn);
|
void ServerConnection_close(ServerConnection* conn);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
43
src/client/requests/ErrorMessage.c
Normal file
43
src/client/requests/ErrorMessage.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include "requests.h"
|
||||||
|
|
||||||
|
Result(void) recvStr(EncryptedSocketTCP* sock, u32 size, str* out_s){
|
||||||
|
Deferral(4);
|
||||||
|
|
||||||
|
str s = str_construct(malloc(size + 1), size, true);
|
||||||
|
bool success = false;
|
||||||
|
Defer(if(!success) free(s.data));
|
||||||
|
|
||||||
|
// receive message content
|
||||||
|
try_void(
|
||||||
|
EncryptedSocketTCP_recv(
|
||||||
|
sock,
|
||||||
|
str_castTo_Array(s),
|
||||||
|
SocketRecvFlag_WholeBuffer
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
s.data[s.size] = 0;
|
||||||
|
*out_s = s;
|
||||||
|
success = true;
|
||||||
|
Return RESULT_VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result(void) recvErrorMessage(EncryptedSocketTCP* sock, PacketHeader* res_header,
|
||||||
|
str* out_err_msg)
|
||||||
|
{
|
||||||
|
Deferral(4);
|
||||||
|
|
||||||
|
ErrorMessage res;
|
||||||
|
try_void(PacketHeader_validateContentSize(res_header, sizeof(res)));
|
||||||
|
try_void(EncryptedSocketTCP_recvStruct(sock, &res));
|
||||||
|
// limit msg_size to fit in single EncryptedSocketTCP_recv call
|
||||||
|
// TODO: receive ErrorMessage content in a loop
|
||||||
|
if(res.msg_size > sock->recv_buf.size)
|
||||||
|
res.msg_size = sock->recv_buf.size;
|
||||||
|
|
||||||
|
str err_msg;
|
||||||
|
try_void(recvStr(sock, res.msg_size, &err_msg));
|
||||||
|
*out_err_msg = err_msg;
|
||||||
|
|
||||||
|
Return RESULT_VOID;
|
||||||
|
}
|
||||||
34
src/client/requests/requests.c
Normal file
34
src/client/requests/requests.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include "requests.h"
|
||||||
|
|
||||||
|
|
||||||
|
Result(void) _recvResponse(EncryptedSocketTCP* sock,
|
||||||
|
PacketHeader* res_header, Array(u8) res, PacketType res_type)
|
||||||
|
{
|
||||||
|
Deferral(4);
|
||||||
|
|
||||||
|
try_void(EncryptedSocketTCP_recvStruct(sock, res_header));
|
||||||
|
try_void(PacketHeader_validateMagic(res_header));
|
||||||
|
if(res_header->type == PacketType_ErrorMessage){
|
||||||
|
str err_msg;
|
||||||
|
try_void(recvErrorMessage(sock, res_header, &err_msg));
|
||||||
|
Return RESULT_ERROR(err_msg.data, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
try_void(PacketHeader_validateType(res_header, res_type));
|
||||||
|
try_void(PacketHeader_validateContentSize(res_header, res.size));
|
||||||
|
|
||||||
|
try_void(EncryptedSocketTCP_recv(sock, res, SocketRecvFlag_WholeBuffer));
|
||||||
|
|
||||||
|
Return RESULT_VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result(void) _sendRequest(EncryptedSocketTCP* sock,
|
||||||
|
PacketHeader* req_header, Array(u8) req)
|
||||||
|
{
|
||||||
|
Deferral(4);
|
||||||
|
|
||||||
|
try_void(EncryptedSocketTCP_sendStruct(sock, req_header));
|
||||||
|
try_void(EncryptedSocketTCP_send(sock, req));
|
||||||
|
|
||||||
|
Return RESULT_VOID;
|
||||||
|
}
|
||||||
20
src/client/requests/requests.h
Normal file
20
src/client/requests/requests.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "network/tcp-chat-protocol/v1.h"
|
||||||
|
#include "client/client.h"
|
||||||
|
|
||||||
|
|
||||||
|
Result(void) recvErrorMessage(EncryptedSocketTCP* sock, PacketHeader* res_header,
|
||||||
|
str* out_err_msg);
|
||||||
|
|
||||||
|
Result(void) recvStr(EncryptedSocketTCP* sock, u32 size, str* out_s);
|
||||||
|
|
||||||
|
Result(void) _recvResponse(EncryptedSocketTCP* sock,
|
||||||
|
PacketHeader* res_header, Array(u8) res, PacketType res_type);
|
||||||
|
#define recvResponse(sock, res_header_ptr, res_ptr, res_type) \
|
||||||
|
_recvResponse(sock, res_header_ptr, struct_castTo_Array(res_ptr), res_type)
|
||||||
|
|
||||||
|
|
||||||
|
Result(void) _sendRequest(EncryptedSocketTCP* sock,
|
||||||
|
PacketHeader* req_header, Array(u8) req);
|
||||||
|
#define sendRequest(sock, req_header_ptr, req_ptr) \
|
||||||
|
_sendRequest(sock, req_header_ptr, struct_castTo_Array(req_ptr))
|
||||||
@ -172,13 +172,14 @@ Result(u32) AESStreamEncryptor_encrypt(AESStreamEncryptor* ptr,
|
|||||||
Array(u8) src, Array(u8) dst)
|
Array(u8) src, Array(u8) dst)
|
||||||
{
|
{
|
||||||
Deferral(4);
|
Deferral(4);
|
||||||
u32 encrypted_size = AESStreamEncryptor_calcDstSize(src.size);
|
|
||||||
try_assert(dst.size >= encrypted_size);
|
|
||||||
|
|
||||||
|
u32 encrypted_size = src.size;
|
||||||
// if it is the beginning of the stream, write IV
|
// if it is the beginning of the stream, write IV
|
||||||
if(ptr->block_counter == 0){
|
if(ptr->block_counter == 0){
|
||||||
__Array_writeNext(&dst, ptr->iv, __AES_STREAM_IV_SIZE);
|
__Array_writeNext(&dst, ptr->iv, __AES_STREAM_IV_SIZE);
|
||||||
|
encrypted_size = AESStreamEncryptor_calcDstSize(encrypted_size);
|
||||||
}
|
}
|
||||||
|
try_assert(dst.size >= encrypted_size);
|
||||||
|
|
||||||
// encrypt full buffers
|
// encrypt full buffers
|
||||||
while(src.size > __AES_BUFFER_SIZE){
|
while(src.size > __AES_BUFFER_SIZE){
|
||||||
|
|||||||
@ -101,7 +101,7 @@ void AESStreamEncryptor_changeKey(AESStreamEncryptor* ptr, Array(u8) key);
|
|||||||
|
|
||||||
/// @brief If ptr->block_counter == 0, writes random IV to `dst`. After that writes encrypted data to dst.
|
/// @brief If ptr->block_counter == 0, writes random IV to `dst`. After that writes encrypted data to dst.
|
||||||
/// @param src array of any size
|
/// @param src array of any size
|
||||||
/// @param dst array of size >= AESStreamEncryptor_calcDstSize(src.size)
|
/// @param dst array of size >= `AESStreamEncryptor_calcDstSize(src.size)` for first block and `src.size `for other blocks
|
||||||
/// @return size of encrypted data
|
/// @return size of encrypted data
|
||||||
Result(u32) AESStreamEncryptor_encrypt(AESStreamEncryptor* ptr, Array(u8) src, Array(u8) dst);
|
Result(u32) AESStreamEncryptor_encrypt(AESStreamEncryptor* ptr, Array(u8) src, Array(u8) dst);
|
||||||
|
|
||||||
|
|||||||
10
src/db/idb.c
10
src/db/idb.c
@ -39,6 +39,8 @@ static const Magic32 TABLE_FILE_MAGIC = { .bytes = { 'I', 'D', 'B', 't' } };
|
|||||||
|
|
||||||
|
|
||||||
void Table_close(Table* t){
|
void Table_close(Table* t){
|
||||||
|
if(t == NULL)
|
||||||
|
return;
|
||||||
fclose(t->table_file);
|
fclose(t->table_file);
|
||||||
fclose(t->changes_file);
|
fclose(t->changes_file);
|
||||||
free(t->name.data);
|
free(t->name.data);
|
||||||
@ -164,10 +166,9 @@ static Result(void) Table_validateEncryption(Table* t){
|
|||||||
|
|
||||||
static Result(void) Table_validateRowSize(Table* t, u32 row_size){
|
static Result(void) Table_validateRowSize(Table* t, u32 row_size){
|
||||||
if(row_size != t->header.row_size){
|
if(row_size != t->header.row_size){
|
||||||
ResultVar(void) error_result = RESULT_ERROR_FMT(
|
return 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 RESULT_VOID;
|
return RESULT_VOID;
|
||||||
@ -198,6 +199,8 @@ Result(IncrementalDB*) idb_open(str db_dir, NULLABLE(Array(u8) aes_key)){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void idb_close(IncrementalDB* db){
|
void idb_close(IncrementalDB* db){
|
||||||
|
if(db == NULL)
|
||||||
|
return;
|
||||||
free(db->db_dir.data);
|
free(db->db_dir.data);
|
||||||
free(db->aes_key.data);
|
free(db->aes_key.data);
|
||||||
HashMap_destroy(&db->tables_map);
|
HashMap_destroy(&db->tables_map);
|
||||||
@ -268,10 +271,9 @@ Result(Table*) idb_getOrCreateTable(IncrementalDB* db, str table_name, u32 row_s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!HashMap_tryPush(&db->tables_map, t->name, &t)){
|
if(!HashMap_tryPush(&db->tables_map, t->name, &t)){
|
||||||
ResultVar(void) error_result = RESULT_ERROR_FMT(
|
Return RESULT_ERROR_FMT(
|
||||||
"Table '%s' is already open",
|
"Table '%s' is already open",
|
||||||
t->name.data);
|
t->name.data);
|
||||||
Return error_result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
|
|||||||
@ -46,6 +46,7 @@ Result(void) EncryptedSocketTCP_send(EncryptedSocketTCP* ptr,
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// printf("SEND data_size: %u, enc_size: %u\n", buffer.size, encrypted_size);
|
||||||
Return RESULT_VOID;
|
Return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,6 +75,7 @@ Result(u32) EncryptedSocketTCP_recv(EncryptedSocketTCP* ptr,
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// printf("RECV recv_size: %u, dec_size: %u\n", received_size, decrypted_size);
|
||||||
Return RESULT_VALUE(u, decrypted_size);
|
Return RESULT_VALUE(u, decrypted_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +98,7 @@ Result(void) EncryptedSocketTCP_sendRSA(EncryptedSocketTCP* ptr,
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// printf("SEND-RSA data_size: %u, enc_size: %u\n", buffer.size, encrypted_size);
|
||||||
Return RESULT_VOID;
|
Return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,6 +147,8 @@ Result(u32) EncryptedSocketTCP_recvRSA(EncryptedSocketTCP* ptr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy(buffer.data, ptr->recv_buf.data, decrypted_size);
|
memcpy(buffer.data, ptr->recv_buf.data, decrypted_size);
|
||||||
|
|
||||||
|
// printf("RECV-RSA recv_size: %u, dec_size: %u\n", received_size, decrypted_size);
|
||||||
Return RESULT_VALUE(u, decrypted_size);
|
Return RESULT_VALUE(u, decrypted_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +170,6 @@ void EncryptedSocketUDP_construct(EncryptedSocketUDP* ptr,
|
|||||||
void EncryptedSocketUDP_destroy(EncryptedSocketUDP* ptr){
|
void EncryptedSocketUDP_destroy(EncryptedSocketUDP* ptr){
|
||||||
if(!ptr)
|
if(!ptr)
|
||||||
return;
|
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);
|
||||||
|
|||||||
@ -40,7 +40,7 @@ typedef enum PacketType {
|
|||||||
typedef struct ErrorMessage {
|
typedef struct ErrorMessage {
|
||||||
u32 msg_size; // <= ERROR_MESSAGE_MAX_SIZE
|
u32 msg_size; // <= ERROR_MESSAGE_MAX_SIZE
|
||||||
/* stream of size msg_size */
|
/* stream of size msg_size */
|
||||||
} ErrorMessage;
|
} ALIGN_PACKET_STRUCT ErrorMessage;
|
||||||
|
|
||||||
void ErrorMessage_construct(ErrorMessage* ptr, PacketHeader* header,
|
void ErrorMessage_construct(ErrorMessage* ptr, PacketHeader* header,
|
||||||
u32 msg_size);
|
u32 msg_size);
|
||||||
@ -78,7 +78,7 @@ void ServerPublicInfoRequest_construct(ServerPublicInfoRequest* ptr, PacketHeade
|
|||||||
typedef struct ServerPublicInfoResponse {
|
typedef struct ServerPublicInfoResponse {
|
||||||
u32 data_size;
|
u32 data_size;
|
||||||
/* stream of size data_size */
|
/* stream of size data_size */
|
||||||
} ServerPublicInfoResponse;
|
} ALIGN_PACKET_STRUCT ServerPublicInfoResponse;
|
||||||
|
|
||||||
void ServerPublicInfoResponse_construct(ServerPublicInfoResponse* ptr, PacketHeader* header,
|
void ServerPublicInfoResponse_construct(ServerPublicInfoResponse* ptr, PacketHeader* header,
|
||||||
u32 data_size);
|
u32 data_size);
|
||||||
|
|||||||
@ -46,7 +46,7 @@ Result(ClientConnection*) ClientConnection_accept(ConnectionHandlerArgs* args)
|
|||||||
memcpy(conn->session_key.data, client_handshake.session_key, conn->session_key.size);
|
memcpy(conn->session_key.data, client_handshake.session_key, conn->session_key.size);
|
||||||
EncryptedSocketTCP_changeKey(&conn->sock, conn->session_key);
|
EncryptedSocketTCP_changeKey(&conn->sock, conn->session_key);
|
||||||
|
|
||||||
// send PacketHeader and ServerHandshake over encrypted TCP socket
|
// send ServerHandshake
|
||||||
ServerHandshake server_handshake;
|
ServerHandshake server_handshake;
|
||||||
ServerHandshake_construct(&server_handshake, &packet_header,
|
ServerHandshake_construct(&server_handshake, &packet_header,
|
||||||
conn->session_id);
|
conn->session_id);
|
||||||
|
|||||||
@ -23,7 +23,7 @@ declare_RequestHandler(ServerPublicInfo)
|
|||||||
content = str_castTo_Array(server->name);
|
content = str_castTo_Array(server->name);
|
||||||
break;
|
break;
|
||||||
case ServerPublicInfo_Description:
|
case ServerPublicInfo_Description:
|
||||||
content = str_castTo_Array(server->name);
|
content = str_castTo_Array(server->description);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -78,7 +78,7 @@ Result(Server*) Server_createFromConfig(cstr config_path){
|
|||||||
|
|
||||||
try_void(ServerCredentials_tryConstruct(&server->cred, sk_base64_cstr, pk_base64_cstr));
|
try_void(ServerCredentials_tryConstruct(&server->cred, sk_base64_cstr, pk_base64_cstr));
|
||||||
|
|
||||||
// parse db_key
|
// parse db_aes_key
|
||||||
try_void(config_findValue(config_str, STR("db_aes_key"), &tmp_str, true));
|
try_void(config_findValue(config_str, STR("db_aes_key"), &tmp_str, true));
|
||||||
Array(u8) db_aes_key = Array_alloc_size(base64_decodedSize(tmp_str.data, tmp_str.size));
|
Array(u8) db_aes_key = Array_alloc_size(base64_decodedSize(tmp_str.data, tmp_str.size));
|
||||||
base64_decode(tmp_str.data, tmp_str.size, db_aes_key.data);
|
base64_decode(tmp_str.data, tmp_str.size, db_aes_key.data);
|
||||||
@ -96,7 +96,7 @@ Result(Server*) Server_createFromConfig(cstr config_path){
|
|||||||
// load whole table to list
|
// load whole table to list
|
||||||
try_void(idb_getRows(server->db_users_table, 0, server->users_cache_list.data, users_count));
|
try_void(idb_getRows(server->db_users_table, 0, server->users_cache_list.data, users_count));
|
||||||
// build name-id map
|
// build name-id map
|
||||||
for(u64 id; id < users_count; id++){
|
for(u64 id = 0; id < users_count; id++){
|
||||||
User* u = &List_index(server->users_cache_list, User, id);
|
User* u = &List_index(server->users_cache_list, User, id);
|
||||||
str key = str_construct(u->name, u->name_len, true);
|
str key = str_construct(u->name, u->name_len, true);
|
||||||
if(!HashMap_tryPush(&server->users_name_id_map, key, &id)){
|
if(!HashMap_tryPush(&server->users_name_id_map, key, &id)){
|
||||||
@ -145,9 +145,10 @@ static void* handleConnection(void* _args){
|
|||||||
|
|
||||||
ResultVar(void) r = try_handleConnection(args, log_ctx);
|
ResultVar(void) r = try_handleConnection(args, log_ctx);
|
||||||
if(r.error){
|
if(r.error){
|
||||||
str error_s = Error_toStr(r.error);
|
str e_str = Error_toStr(r.error);
|
||||||
logError(log_ctx, "%s", error_s.data);
|
logError(log_ctx, "%s", e_str.data);
|
||||||
free(error_s.data);
|
free(e_str.data);
|
||||||
|
Error_free(r.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
9
tcp-chat-server.config.default
Normal file
9
tcp-chat-server.config.default
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name = test server
|
||||||
|
description = Lorem ipsum labuba aboba
|
||||||
|
landing_channel_id = 0
|
||||||
|
local_address = 127.0.0.1:9988
|
||||||
|
db_dir = server-db
|
||||||
|
db_aes_key = <generate with './tcp-chat --random-bytes-base64 32'>
|
||||||
|
|
||||||
|
rsa_private_key = <generate with './tcp-chat --rsa-gen-random'>
|
||||||
|
rsa_public_key =
|
||||||
Loading…
Reference in New Issue
Block a user