From b854c4d6ac06c4a39006a086766deb90096c2998 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Mon, 20 May 2024 11:44:29 +0200 Subject: WIP CLI --- client/rl.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 client/rl.h (limited to 'client/rl.h') diff --git a/client/rl.h b/client/rl.h new file mode 100644 index 0000000..7eef4da --- /dev/null +++ b/client/rl.h @@ -0,0 +1,18 @@ +#pragma once + +#define COLOR_OFF "\x1B[0m" +#define COLOR_BLUE "\x1B[0;94m" + +#define CLI_PROMPT COLOR_BLUE "pbc" COLOR_OFF "% " + +#ifdef __cplusplus +extern "C" { +#endif + +int cli_main(); +void rl_printf(const char *fmt, ...); + +#ifdef __cplusplus +} +#endif + -- cgit v1.2.3 From 41ed6fa61a65432843feb596726026bc5772ae19 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Mon, 20 May 2024 13:24:13 +0200 Subject: socket connect working (sorta) --- client/main.cpp | 10 ++++++-- client/rl.h | 6 ++--- client/sock.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++------- client/sock.h | 17 +++++++++---- 4 files changed, 89 insertions(+), 19 deletions(-) (limited to 'client/rl.h') diff --git a/client/main.cpp b/client/main.cpp index 6aad0e3..36fc7bb 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "rl.h" #include "sock.h" @@ -16,8 +17,13 @@ int main(int argc, char** argv) { uint16_t port = 9191; if (argc >= 3) port = atoi(argv[2]); - // connect to TCP socket (automatically spawns thread) - PBSocket sock(addr, port); + try { + // connect to TCP socket (automatically spawns thread) + PBSocket sock(addr, port); + } catch (const std::exception& e) { + printf("error: %s\n", e.what()); + return EXIT_FAILURE; + } // enter main CLI (using GNU readline for comfyness) return cli_main(); diff --git a/client/rl.h b/client/rl.h index 7eef4da..313a8fe 100644 --- a/client/rl.h +++ b/client/rl.h @@ -1,9 +1,9 @@ #pragma once -#define COLOR_OFF "\x1B[0m" -#define COLOR_BLUE "\x1B[0;94m" +#define COLOR_OFF "\x1b[0m" +#define COLOR_BOLD "\x1b[1m" -#define CLI_PROMPT COLOR_BLUE "pbc" COLOR_OFF "% " +#define CLI_PROMPT "(" COLOR_BOLD "pbc" COLOR_OFF ") " #ifdef __cplusplus extern "C" { diff --git a/client/sock.cpp b/client/sock.cpp index 703ee24..17d9e35 100644 --- a/client/sock.cpp +++ b/client/sock.cpp @@ -1,29 +1,86 @@ +#include +#include +#include #include #include +#include +#include +#include +#include #include #include "sock.h" #include "rl.h" -PBSocket::PBSocket() { - printf("Init PBSocket!\n"); -} +using std::logic_error; +using std::thread; +PBSocket::PBSocket() { } PBSocket::PBSocket(char* addr, uint16_t port) : PBSocket() { - connect(addr, port); + set_server(addr, port); + sock_connect(); +} + +PBSocket::~PBSocket() { + // stop TCP listen thread + if (_thread != nullptr) { + _thread->detach(); + delete _thread; + } + + sock_close(); +} + +void PBSocket::set_server(char* addr, uint16_t port) { + _addr = addr; + _port = port; } -void PBSocket::connect(char* addr, uint16_t port) { - printf("Connect to %s on port %d\n", addr, port); +void PBSocket::sock_connect() { + if (_addr == NULL) throw logic_error("no server address defined"); + if (_port == 0) throw logic_error("no server port defined"); - this->_thread = std::thread(&PBSocket::sock_task, this); + if (_thread != nullptr) throw logic_error("already connected"); + + rl_printf("connecting to %s on port %d...\n", _addr, _port); + + _fd = socket(AF_INET, SOCK_STREAM, 0); + if (_fd < 0) throw logic_error("socket create failed"); + + struct sockaddr_in server = { + .sin_family = AF_INET, + .sin_port = htons(_port), + .sin_addr = { + .s_addr = inet_addr(_addr), + }, + }; + int ret = connect(_fd, (struct sockaddr*) &server, sizeof(server)); + if (ret != 0) throw logic_error(strerror(errno)); + + this->_thread = new thread(&PBSocket::sock_task, this); +} + +void PBSocket::sock_close() { + if (_fd < 0) return; // already closed + close(_fd); + _fd = -1; } void PBSocket::sock_task() { while(1) { - sleep(3); - rl_printf("Testing asynchronous messages in prompt...\n"); + char buf[80]; + ssize_t bytes = read(_fd, buf, sizeof(buf)); + + if (bytes == -1) { + rl_printf("error: %s (%d)\n", strerror(errno), errno); + sock_close(); + break; + } + + if (bytes > 0) { + rl_printf("received %d bytes\n", bytes); + } } } diff --git a/client/sock.h b/client/sock.h index e3d7ec8..0f9a3fc 100644 --- a/client/sock.h +++ b/client/sock.h @@ -5,17 +5,24 @@ class PBSocket { public: + PBSocket(); PBSocket(char* addr, uint16_t port); + virtual ~PBSocket(); - void connect(char* addr, uint16_t port); + void set_server(char* addr, uint16_t port); -private: - PBSocket(); + void sock_connect(); +private: void sock_task(); + void sock_close(); - std::thread _thread; + std::thread* _thread = nullptr; -}; + char* _addr = NULL; + uint16_t _port = 0; + + int _fd = -1; +}; -- cgit v1.2.3 From db8906d54cd9afbc57f0b40a0d618335c552f704 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Mon, 20 May 2024 13:47:37 +0200 Subject: back-and-forth in C++ w/o netcat --- client/CMakeLists.txt | 2 +- client/main.cpp | 12 ++++++--- client/rl.c | 55 ----------------------------------------- client/rl.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ client/rl.h | 8 ------ client/sock.cpp | 46 +++++++++++++++++++++++++++++++--- client/sock.h | 7 ++++++ 7 files changed, 128 insertions(+), 70 deletions(-) delete mode 100644 client/rl.c create mode 100644 client/rl.cpp (limited to 'client/rl.h') diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index e4990d7..cae0111 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -10,7 +10,7 @@ include(../proto/include.cmake) add_executable(main main.cpp - rl.c + rl.cpp sock.cpp ) diff --git a/client/main.cpp b/client/main.cpp index c01dbb5..5c26107 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -6,6 +6,8 @@ #include "rl.h" #include "sock.h" +PBSocket* sock; + int main(int argc, char** argv) { if (argc < 2) { printf("usage: %s addr [port]\n", argv[0]); @@ -17,16 +19,20 @@ int main(int argc, char** argv) { uint16_t port = 9191; if (argc >= 3) port = atoi(argv[2]); - PBSocket sock(addr, port); + sock = new PBSocket(addr, port); try { // connect to TCP socket (automatically spawns thread) - sock.sock_connect(); + sock->sock_connect(); } catch (const std::exception& e) { printf("error: %s\n", e.what()); return EXIT_FAILURE; } // enter main CLI (using GNU readline for comfyness) - return cli_main(); + int ret = cli_main(); + + delete sock; + + return ret; } diff --git a/client/rl.c b/client/rl.c deleted file mode 100644 index fb26057..0000000 --- a/client/rl.c +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include -#include -#include - -#include -#include - -#include "rl.h" - -void rl_printf(const char *fmt, ...) { - // save line - char* saved_line = rl_copy_text(0, rl_end); - int saved_point = rl_point; - int saved_end = rl_end; - - // clear line - rl_save_prompt(); - rl_replace_line("", 0); - rl_redisplay(); - - // printf - va_list args; - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); - - // restore line - rl_restore_prompt(); - rl_replace_line(saved_line, 0); - rl_point = saved_point; - rl_end = saved_end; - rl_redisplay(); - - free(saved_line); -} - -int cli_main() { - char* input = NULL; - while (1) { - if (input != NULL) free(input); - input = readline(CLI_PROMPT); - - // exit on ^D or ^C (EOF) - if (input == NULL) return EXIT_SUCCESS; - - // add non-empty line to history - if (*input) add_history(input); - - if (strcmp(input, "exit") == 0) return EXIT_SUCCESS; - } - - return EXIT_SUCCESS; -} - diff --git a/client/rl.cpp b/client/rl.cpp new file mode 100644 index 0000000..32a4df0 --- /dev/null +++ b/client/rl.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +#include +#include + +#include "rl.h" +#include "sock.h" + +void rl_printf(const char *fmt, ...) { + // save line + char* saved_line = rl_copy_text(0, rl_end); + int saved_point = rl_point; + int saved_end = rl_end; + + // clear line + rl_save_prompt(); + rl_replace_line("", 0); + rl_redisplay(); + + // printf + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + + // restore line + rl_restore_prompt(); + rl_replace_line(saved_line, 0); + rl_point = saved_point; + rl_end = saved_end; + rl_redisplay(); + + free(saved_line); +} + +void cmd_test() { + const char* data = "Hello world!"; + i2c_send(0x39, (char*) data, strlen(data)); +} + +int cli_main() { + char* input = NULL; + while (1) { + if (input != NULL) free(input); + input = readline(CLI_PROMPT); + + // exit on ^D or ^C (EOF) + if (input == NULL) return EXIT_SUCCESS; + + // add non-empty line to history + if (*input) add_history(input); + + if (strcmp(input, "exit") == 0) return EXIT_SUCCESS; + + if (strcmp(input, "test") == 0) { + cmd_test(); + continue; + } + + printf("unknown command!\n"); + } + + return EXIT_SUCCESS; +} + diff --git a/client/rl.h b/client/rl.h index 313a8fe..503225f 100644 --- a/client/rl.h +++ b/client/rl.h @@ -5,14 +5,6 @@ #define CLI_PROMPT "(" COLOR_BOLD "pbc" COLOR_OFF ") " -#ifdef __cplusplus -extern "C" { -#endif - int cli_main(); void rl_printf(const char *fmt, ...); -#ifdef __cplusplus -} -#endif - diff --git a/client/sock.cpp b/client/sock.cpp index c10fba0..cc18a69 100644 --- a/client/sock.cpp +++ b/client/sock.cpp @@ -10,6 +10,7 @@ #include +#include "puzbusv1.h" #include "sock.h" #include "rl.h" @@ -66,20 +67,59 @@ void PBSocket::sock_close() { _fd = -1; } +void PBSocket::send(char* buf, size_t buf_sz) { + write(_fd, buf, buf_sz); +} + void PBSocket::sock_task() { + struct pb_msg input; + while(1) { char buf[80]; ssize_t bytes = read(_fd, buf, sizeof(buf)); if (bytes == -1) { rl_printf("error: %s (%d)\n", strerror(errno), errno); - sock_close(); break; } - if (bytes > 0) { - rl_printf("received %d bytes\n", bytes); + // skip empty frames + if (bytes == 0) continue; + + int ret = pb_read(&input, buf, bytes); + + // header read error + if (ret < 0) { + rl_printf("pb_read error!\n"); + break; } + + // continue reading if more bytes needed... + if (ret > 0) continue; + + // message read completely! + i2c_recv(input.addr, input.data, input.length); + free(input.data); } + + sock_close(); +} + +void i2c_send(uint16_t addr, char* data, size_t data_size) { + struct pb_msg msg = { + .addr = addr, + .data = data, + .length = data_size, + }; + + char* packed; + size_t size; + if (!pb_write(&msg, &packed, &size)) return; + + sock->send(packed, size); +} + +void i2c_recv(uint16_t addr, char* data, size_t data_size) { + rl_printf("[0x%02x]: %.*s\n", addr, data_size, data); } diff --git a/client/sock.h b/client/sock.h index 0f9a3fc..818ea72 100644 --- a/client/sock.h +++ b/client/sock.h @@ -13,6 +13,8 @@ public: void sock_connect(); + void send(char* buf, size_t buf_sz); + private: void sock_task(); void sock_close(); @@ -26,3 +28,8 @@ private: }; +extern PBSocket* sock; + +void i2c_send(uint16_t addr, char* data, size_t data_size); +void i2c_recv(uint16_t addr, char* data, size_t data_size); + -- cgit v1.2.3