created directory ./include/
This commit is contained in:
248
src/cli/ClientCLI/ClientCLI.c
Normal file
248
src/cli/ClientCLI/ClientCLI.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user