added tlibtoml submodule

This commit is contained in:
Timerix 2025-11-27 01:46:44 +05:00
parent f5169e8a8f
commit c263d02b36
15 changed files with 108 additions and 95 deletions

3
.gitmodules vendored
View File

@ -4,3 +4,6 @@
[submodule "dependencies/tlibc"] [submodule "dependencies/tlibc"]
path = dependencies/tlibc path = dependencies/tlibc
url = https://timerix.ddns.net/git/timerix/tlibc.git url = https://timerix.ddns.net/git/timerix/tlibc.git
[submodule "dependencies/tlibtoml"]
path = dependencies/tlibtoml
url = https://timerix.ddns.net/git/Timerix/tlibtoml.git

View File

@ -7,8 +7,8 @@
"src", "src",
"include", "include",
"dependencies/BearSSL/inc", "dependencies/BearSSL/inc",
"dependencies/BearSSL/src",
"dependencies/tlibc/include", "dependencies/tlibc/include",
"dependencies/tlibtoml/include",
"${default}" "${default}"
], ],
"cStandard": "c99" "cStandard": "c99"

View File

@ -6,7 +6,10 @@
git clone --recurse-submodules --depth 0 https://timerix.ddns.net/git/Timerix/tcp-chat.git 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) version specified in `project.config`. 2. Install [cbuild](https://timerix.ddns.net/git/Timerix/cbuild/releases).
Select latest version compatible with the one in `project.config`.
Example: For `2.3.0` download latest `2.3.x`.
3. Build executable 3. Build executable
``` ```
@ -23,7 +26,7 @@ cd bin
``` ```
**Server:** **Server:**
1. ```sh 1. ```sh
cp tcp-chat-server.config.default bin/tcp-chat-server.config cp tcp-chat-server.toml.default bin/tcp-chat-server.toml
``` ```
2. Edit config 2. Edit config
3. ```sh 3. ```sh

2
dependencies/tlibc vendored

@ -1 +1 @@
Subproject commit 8a40caaf1044f9fe2c327c4d3c60a3310efd6142 Subproject commit ea6c20f430f4536631f379697ae56fc8b5fd5d17

1
dependencies/tlibtoml vendored Submodule

@ -0,0 +1 @@
Subproject commit a0e280d77b6d8967239b14915609eef422f6ba0b

30
dependencies/tlibtoml.config vendored Normal file
View File

@ -0,0 +1,30 @@
#!/usr/bin/env bash
# This is a dependency config.
# You can copy it to another project to add tlibtoml dependency.
DEP_WORKING_DIR="$DEPENDENCIES_DIR/tlibtoml"
user_config_path="project.config.user"
absolute_dep_dir=$(realpath "$DEPENDENCIES_DIR")
function setup_user_config(){
# Set variable `DEPENDENCIES_DIR`` in `tlibtoml/project.config.user`
# to the directory where `tlibc`` is installed
file_copy_default_if_not_present "$user_config_path" "$user_config_path.default"
replace_var_value_in_script "$user_config_path" "DEPENDENCIES_DIR" "$absolute_dep_dir"
}
if [[ "$TASK" = *_dbg ]]; then
dep_build_target="build_static_lib_dbg"
else
dep_build_target="build_static_lib"
fi
DEP_PRE_BUILD_COMMAND="setup_user_config"
DEP_BUILD_COMMAND="cbuild $dep_build_target"
DEP_POST_BUILD_COMMAND=""
DEP_CLEAN_COMMAND="cbuild clean"
DEP_DYNAMIC_OUT_FILES=""
DEP_STATIC_OUT_FILES="bin/tlibtoml.a"
DEP_OTHER_OUT_FILES=""
PRESERVE_OUT_DIRECTORY_STRUCTURE=false

View File

@ -5,6 +5,14 @@
typedef struct Server Server; typedef struct Server Server;
Result(Server*) Server_create(str config_str, void* logger, LogFunction_t log_func); /// @param config_file_content config in toml format
/// @param config_file_name to use in error messages
/// @param logger some shared data for your log function
/// @param log_func log function that you have to implement
/// @return
Result(Server*) Server_create(str config_file_content, cstr config_file_name,
void* logger, LogFunction_t log_func);
void Server_free(Server* server); void Server_free(Server* server);
Result(void) Server_run(Server* server); Result(void) Server_run(Server* server);

View File

@ -24,7 +24,7 @@ SRC_CPP="$(find src -name '*.cpp')"
# See cbuild/example_dependency_configs # See cbuild/example_dependency_configs
DEPENDENCY_CONFIGS_DIR='dependencies' DEPENDENCY_CONFIGS_DIR='dependencies'
# List of dependency config files in DEPENDENCY_CONFIGS_DIR separated by space. # List of dependency config files in DEPENDENCY_CONFIGS_DIR separated by space.
ENABLED_DEPENDENCIES='tlibc bearssl' ENABLED_DEPENDENCIES='bearssl tlibc tlibtoml'
# OBJDIR structure: # OBJDIR structure:
# ├── objects/ - Compiled object files. Cleans on each call of build task # ├── objects/ - Compiled object files. Cleans on each call of build task
@ -35,7 +35,10 @@ OBJDIR="obj"
OUTDIR="bin" OUTDIR="bin"
STATIC_LIB_FILE="$PROJECT.a" STATIC_LIB_FILE="$PROJECT.a"
INCLUDE="-Isrc -Iinclude -I$DEPENDENCIES_DIR/BearSSL/inc -I$DEPENDENCIES_DIR/tlibc/include" INCLUDE="-Isrc -Iinclude
-I$DEPENDENCIES_DIR/BearSSL/inc
-I$DEPENDENCIES_DIR/tlibc/include
-I$DEPENDENCIES_DIR/tlibtoml/include"
# OS-specific options # OS-specific options
case "$OS" in case "$OS" in

View File

@ -4,7 +4,7 @@
#include "modes/modes.h" #include "modes/modes.h"
#define _DEFAULT_CONFIG_PATH_CLIENT "tcp-chat-client.config" #define _DEFAULT_CONFIG_PATH_CLIENT "tcp-chat-client.config"
#define _DEFAULT_CONFIG_PATH_SERVER "tcp-chat-server.config" #define _DEFAULT_CONFIG_PATH_SERVER "tcp-chat-server.toml"
#define arg_is(LITERAL) str_equals(arg_str, STR(LITERAL)) #define arg_is(LITERAL) str_equals(arg_str, STR(LITERAL))

View File

@ -67,10 +67,9 @@ Result(void) run_ServerMode(cstr config_path) {
Defer(file_close(config_file)); Defer(file_close(config_file));
// read whole file into str // read whole file into str
Array(u8) config_buf = Array_u8_construct(NULL, 0); str config_file_content = str_null;
try_void(file_readWhole(config_file, &config_buf)); try_void(file_readWholeText(config_file, &config_file_content));
Defer(Array_u8_destroy(&config_buf)); Defer(str_destroy(config_file_content));
str config_str = Array_u8_castTo_str(config_buf, false);
// create logger // create logger
ServerLogger logger; ServerLogger logger;
@ -78,14 +77,19 @@ Result(void) run_ServerMode(cstr config_path) {
Defer(ServerLogger_destroy(&logger)); Defer(ServerLogger_destroy(&logger));
// init server // init server
try(Server* server, p, Server_create(config_str, &logger, log_func)); try(Server* server, p,
Server_create(
config_file_content, config_path,
&logger, log_func
)
);
Defer(Server_free(server)); Defer(Server_free(server));
// manually close file and free config_buf // manually close file and free config_buf
file_close(config_file); file_close(config_file);
config_file = NULL; config_file = NULL;
Array_u8_destroy(&config_buf); str_destroy(config_file_content);
config_buf.data = NULL; config_file_content.data = NULL;
// start infinite loop on main thread // start infinite loop on main thread
try_void(Server_run(server)); try_void(Server_run(server));

View File

@ -1,34 +0,0 @@
#include "config.h"
Result(void) config_findValue(str config_str, str key, str* value, bool throwNotFoundError){
u32 line_n = 0;
while(config_str.len > 0){
line_n++;
i32 line_end = str_seekChar(config_str, '\n', 0);
if(line_end < 0)
line_end = config_str.len - 1;
str line = str_sliceBefore(config_str, line_end);
config_str = str_sliceAfter(config_str, line_end + 1);
i32 sep_pos = str_seekChar(line, '=', 1);
if(sep_pos < 0){
//not a 'key = value' line
continue;
}
str line_key = str_sliceBefore(line, sep_pos - 1);
str_trim(&line_key, false);
if(str_equals(line_key, key)){
str line_value = str_sliceAfter(line, sep_pos + 1);
str_trim(&line_value, false);
*value = line_value;
return RESULT_VOID;
}
}
if(throwNotFoundError){
char* err_msg = sprintf_malloc("can't find key '"FMT_str"'", key.len, key.data);
return RESULT_ERROR(err_msg, true);
}
return RESULT_VOID;
}

View File

@ -1,6 +0,0 @@
#pragma once
#include "tlibc/errors.h"
#include "tlibc/string/str.h"
/// searches for pattern `key = value`
Result(void) config_findValue(str config_str, str key, str* value, bool throwNotFoundError);

View File

@ -3,9 +3,9 @@
#include "tlibc/time.h" #include "tlibc/time.h"
#include "tlibc/base64.h" #include "tlibc/base64.h"
#include "server/server_internal.h" #include "server/server_internal.h"
#include "config.h"
#include "network/tcp-chat-protocol/v1.h" #include "network/tcp-chat-protocol/v1.h"
#include "server/responses/responses.h" #include "server/responses/responses.h"
#include "tlibtoml.h"
static void* handleConnection(void* _args); static void* handleConnection(void* _args);
static Result(void) try_handleConnection(ConnectionHandlerArgs* args, cstr log_ctx); static Result(void) try_handleConnection(ConnectionHandlerArgs* args, cstr log_ctx);
@ -36,7 +36,9 @@ void Server_free(Server* self){
#define LOG_FUNC log_func #define LOG_FUNC log_func
#define LOG_CONTEXT log_ctx #define LOG_CONTEXT log_ctx
Result(Server*) Server_create(str config_str, void* logger, LogFunction_t log_func){ Result(Server*) Server_create(str config_file_content, cstr config_file_name,
void* logger, LogFunction_t log_func)
{
Deferral(16); Deferral(16);
cstr log_ctx = "ServerInit"; cstr log_ctx = "ServerInit";
@ -47,53 +49,48 @@ Result(Server*) Server_create(str config_str, void* logger, LogFunction_t log_fu
self->logger = logger; self->logger = logger;
self->log_func = log_func; self->log_func = log_func;
logDebug("parsing config"); logDebug("parsing config");
try(TomlTable* config_toml, p, toml_load_str_filename(config_file_content, config_file_name));
Defer(TomlTable_free(config_toml));
// parse name // parse name
str tmp_str = str_null; try(str* v_name, p, TomlTable_get_str(config_toml, STR("name")));
try_void(config_findValue(config_str, STR("name"), &tmp_str, true)); self->name = str_copy(*v_name);
self->name = str_copy(tmp_str);
// parse description // parse description
try_void(config_findValue(config_str, STR("description"), &tmp_str, true)); try(str* v_desc, p, TomlTable_get_str(config_toml, STR("description")));
self->description = str_copy(tmp_str); self->description = str_copy(*v_desc);
// parse landing_channel_id // parse landing_channel_id
try_void(config_findValue(config_str, STR("landing_channel_id"), &tmp_str, true)); try(i64 v_landing_channel_id, i, TomlTable_get_integer(config_toml, STR("landing_channel_id")));
char* lci_cstr = str_copy(tmp_str).data; self->landing_channel_id = v_landing_channel_id;
Defer(free(lci_cstr));
if(sscanf(lci_cstr, FMT_u64, &self->landing_channel_id) != 1){
Return RESULT_ERROR("can't parse 'landing_channel_id' value as number", false);
}
// parse local_address // parse local_address
try_void(config_findValue(config_str, STR("local_address"), &tmp_str, true)); try(str* v_local_address, p, TomlTable_get_str(config_toml, STR("local_address")));
char* local_end_cstr = str_copy(tmp_str).data; try_assert(v_local_address->isZeroTerminated);
Defer(free(local_end_cstr)); try_void(EndpointIPv4_parse(v_local_address->data, &self->local_end));
try_void(EndpointIPv4_parse(local_end_cstr, &self->local_end));
// parse rsa_private_key // parse rsa_private_key
try_void(config_findValue(config_str, STR("rsa_private_key"), &tmp_str, true)); try(str* v_rsa_sk, p, TomlTable_get_str(config_toml, STR("rsa_private_key")));
char* sk_base64_cstr = str_copy(tmp_str).data; try_assert(v_rsa_sk->isZeroTerminated);
Defer(free(sk_base64_cstr)); try_void(RSA_parsePrivateKey_base64(v_rsa_sk->data, &self->rsa_sk));
// parse rsa_public_key // parse rsa_public_key
try_void(config_findValue(config_str, STR("rsa_public_key"), &tmp_str, true)); try(str* v_rsa_pk, p, TomlTable_get_str(config_toml, STR("rsa_public_key")));
char* pk_base64_cstr = str_copy(tmp_str).data; try_assert(v_rsa_pk->isZeroTerminated);
Defer(free(pk_base64_cstr)); try_void(RSA_parsePublicKey_base64(v_rsa_pk->data, &self->rsa_pk));
try_void(RSA_parsePrivateKey_base64(sk_base64_cstr, &self->rsa_sk));
try_void(RSA_parsePublicKey_base64(pk_base64_cstr, &self->rsa_pk));
// parse db_aes_key // parse db_aes_key
try_void(config_findValue(config_str, STR("db_aes_key"), &tmp_str, true)); try(str* v_db_aes_key, p, TomlTable_get_str(config_toml, STR("db_aes_key")));
Array(u8) db_aes_key = Array_u8_alloc(base64_decodedSize(tmp_str.data, tmp_str.len)); str db_aes_key_s = *v_db_aes_key;
Array(u8) db_aes_key = Array_u8_alloc(base64_decodedSize(db_aes_key_s.data, db_aes_key_s.len));
Defer(free(db_aes_key.data)); Defer(free(db_aes_key.data));
base64_decode(tmp_str.data, tmp_str.len, db_aes_key.data); base64_decode(db_aes_key_s.data, db_aes_key_s.len, db_aes_key.data);
// parse db_dir and open db // parse db_dir and open db
try_void(config_findValue(config_str, STR("db_dir"), &tmp_str, true)); try(str* v_db_dir, p, TomlTable_get_str(config_toml, STR("db_dir")));
try(self->db, p, idb_open(tmp_str, db_aes_key)); try(self->db, p, idb_open(*v_db_dir, db_aes_key));
// build users cache // build users cache
logDebug("loading users..."); logDebug("loading users...");

View File

@ -1,9 +0,0 @@
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 =

View File

@ -0,0 +1,13 @@
name = "Test Server"
description = """\
Lorem ipsum labuba aboba.\n\
Qqqqq...\
"""
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 = '<copy from output of command above>'