created directory ./include/

This commit is contained in:
2025-11-18 14:37:01 +05:00
parent eec45cac71
commit a1a11c10e2
20 changed files with 89 additions and 70 deletions

View File

@@ -0,0 +1,248 @@
#include "cli/ClientCLI/ClientCLI.h"
#include "cli/ClientCLI/db_tables.h"
#include "cli/term.h"
#include "tcp-chat/common_constants.h"
#include "tlibc/time.h"
#include "tlibc/filesystem.h"
static const str greeting_art = STR(
" ^,,^ |\n"
" ( •·•) Meum! (o.o`7\n"
" / ` | Meum... |`˜ \\\n"
"\\(_,J J L l`,)/\n"
);
static const str farewell_art = STR(
" ^,,^ |\n"
" ( -.-) (>,<`7\n"
" / ` | Goodbye! |`˜ \\\n"
"\\(_,J J L l`,)/\n"
);
#define is_alias(LITERAL) str_equals(command, STR(LITERAL))
static Result(void) ClientCLI_askUserNameAndPassword(str* username_out, str* password_out);
static Result(void) ClientCLI_commandExec(ClientCLI* self, str command, bool* stop);
static Result(void) ClientCLI_openUserDB(ClientCLI* self);
static Result(void) ClientCLI_saveServerInfo(ClientCLI* self,
cstr server_addr_cstr, cstr server_pk_base64,
str server_name, str server_description);
void ClientCLI_destroy(ClientCLI* self){
if(!self)
return;
Client_free(self->client);
idb_close(self->user_db);
}
void ClientCLI_construct(ClientCLI* self){
self->client = NULL;
self->user_db = NULL;
}
Result(void) ClientCLI_run(ClientCLI* self) {
Deferral(16);
try_void(term_init());
term_clear();
printf("%s\n", greeting_art.data);
// create Client
str username = str_null, password = str_null;
try_void(ClientCLI_askUserNameAndPassword(&username, &password));
Defer(
str_free(username);
str_free(password);
);
Client_free(self->client);
try(self->client, p, Client_create(username, password));
memset(password.data, 0, password.size);
// init db
try_void(ClientCLI_openUserDB(self));
char input_buf[1024];
str command_input = str_null;
bool stop = false;
while(!stop){
sleepMsec(50);
printf("> ");
try_void(term_readLine(input_buf, sizeof(input_buf)));
command_input = str_from_cstr(input_buf);
str_trim(&command_input, true);
if(command_input.size == 0)
continue;
ResultVar(void) com_result = ClientCLI_commandExec(self, command_input, &stop);
if(com_result.error){
Error_addCallPos(com_result.error, ErrorCallPos_here());
str e_str = Error_toStr(com_result.error);
printf("%s\n", e_str.data);
str_free(e_str);
Error_free(com_result.error);
}
}
Return RESULT_VOID;
}
static Result(void) ClientCLI_askUserNameAndPassword(str* username_out, str* password_out){
Deferral(8);
bool success = false;
// ask username
Array(char) username_buf = Array_alloc_size(128);
Defer(if(!success) Array_free(username_buf));
str username = str_null;
while(true) {
printf("username: ");
try_void(term_readLine(username_buf.data, username_buf.size));
username = str_from_cstr(username_buf.data);
str_trim(&username, true);
if(username.size < USERNAME_SIZE_MIN || username.size > USERNAME_SIZE_MAX){
printf("ERROR: username length (in bytes) must be >= %i and <= %i\n",
USERNAME_SIZE_MIN, USERNAME_SIZE_MAX);
}
else break;
}
// ask password
Array(char) password_buf = Array_alloc_size(128);
Defer(if(!success) Array_free(password_buf));
str password = str_null;
while(true) {
printf("password: ");
// TODO: hide password
try_void(term_readLineHidden(password_buf.data, password_buf.size));
password = str_from_cstr(password_buf.data);
str_trim(&password, true);
if(password.size < PASSWORD_SIZE_MIN || password.size > PASSWORD_SIZE_MAX){
printf("ERROR: password length (in bytes) must be >= %i and <= %i\n",
PASSWORD_SIZE_MIN, PASSWORD_SIZE_MAX);
}
else break;
}
*username_out = username;
*password_out = password;
success = true;
Return RESULT_VOID;
}
static Result(void) ClientCLI_commandExec(ClientCLI* self, str command, bool* stop){
Deferral(64);
if(is_alias("q") || is_alias("quit") || is_alias("exit")){
printf("%s\n", farewell_art.data);
*stop = true;
}
else if(is_alias("clear")){
term_clear();
}
else if(is_alias("h") || is_alias("help")){
printf(
"COMMANDS:\n"
"h, help Show this message.\n"
"q, quit, exit Close the program.\n"
"clear Clear the screen.\n"
"j, join Join a server.\n"
"c, connect Connect to a server you joined.\n"
);
}
else if (is_alias("j") || is_alias("join")){
// ask server address
printf("Enter server address (ip:port):\n");
char server_addr_cstr[HOSTADDR_SIZE_MAX + 1];
try_void(term_readLine(server_addr_cstr, sizeof(server_addr_cstr)));
str server_addr_str = str_from_cstr(server_addr_cstr);
str_trim(&server_addr_str, true);
// ask server public key
printf("Enter server public key (RSA-Public-<SIZE>:<DATA>):\n");
char server_pk_cstr[PUBLIC_KEY_BASE64_SIZE_MAX + 1];
try_void(term_readLine(server_pk_cstr, sizeof(server_pk_cstr)));
str server_pk_str = str_from_cstr(server_pk_cstr);
str_trim(&server_pk_str, true);
// connect to server
printf("connecting to server...\n");
try_void(Client_connect(self->client, server_addr_cstr, server_pk_cstr));
printf("connection established\n");
// show server info
str server_name = str_null;
str server_description = str_null;
try_void(Client_getServerName(self->client, &server_name));
try_void(Client_getServerName(self->client, &server_description));
printf("server name: %s\n", server_name.data);
printf("server description: %s\n", server_description.data);
try_void(ClientCLI_saveServerInfo(self, server_addr_cstr, server_pk_cstr,
server_name, server_description));
// TODO: ask in loop: log in / register
//TODO: call Client_runIO():
// function with infinite loop which sends and receives messages
// with navigation across server channels
}
else if(is_alias("c") || is_alias("connect")){
// TODO: read saved servers from database
// TODO: show scrollable list of servers, get selected one
// TODO: ask in loop: log in / register
}
else {
printf("ERROR: unknown command.\n"
"Use 'h' to see list of avaliable commands\n");
}
Return RESULT_VOID;
}
static Result(void) ClientCLI_openUserDB(ClientCLI* self){
Deferral(8);
str username = Client_getUserName(self->client);
Array(u8) user_data_key = Client_getUserDataKey(self->client);
str user_db_dir = str_from_cstr(strcat_malloc("client-db", path_seps, username.data));
Defer(free(user_db_dir.data));
try(self->user_db, p, idb_open(user_db_dir, user_data_key));
Return RESULT_VOID;
}
static Result(void) ClientCLI_saveServerInfo(ClientCLI* self,
cstr server_addr_cstr, cstr server_pk_base64,
str server_name, str server_description){
Deferral(8);
ServerInfo si;
memset(&si, 0, sizeof(ServerInfo));
// address
si.address_len = strlen(server_addr_cstr);
memcpy(si.address, server_addr_cstr, si.address_len);
si.address[si.address_len] = 0;
// public key
si.pk_base64_len = strlen(server_pk_base64);
memcpy(si.pk_base64, server_addr_cstr, si.pk_base64_len);
si.pk_base64[si.pk_base64_len] = 0;
// name
si.name_len = server_name.size;
memcpy(si.name, server_name.data, si.name_len);
si.name[si.name_len] = 0;
// description
si.desc_len = server_name.size;
memcpy(si.desc, server_description.data, si.desc_len);
si.desc[si.desc_len] = 0;
// TODO: check cred->server_address_id_cache_map
// TODO: save server info to user's db
Return RESULT_VOID;
}