From 2e573a3be2e4ecf2d2ad38c7fa4bc8c52791d5d6 Mon Sep 17 00:00:00 2001 From: Sebastien Sikora Date: Tue, 30 Nov 2021 20:29:03 +0000 Subject: [PATCH] Added catch out_of_range and invalid_argument to the client code to parse argv in case arguments get garbled in transmission. --- src/satellite_terminal.h | 12 +++--- src/satterm_client.cpp | 70 ++++++++++++++++++++++----------- src/satterm_component.cpp | 13 +++--- src/satterm_server.cpp | 83 +++++++++++++++++++-------------------- 4 files changed, 102 insertions(+), 76 deletions(-) diff --git a/src/satellite_terminal.h b/src/satellite_terminal.h index fb53dfc..b9a2748 100644 --- a/src/satellite_terminal.h +++ b/src/satellite_terminal.h @@ -83,16 +83,18 @@ class SatTerm_Component { // Server derived class. class SatTerm_Server : public SatTerm_Component { public: - SatTerm_Server(std::string const& identifier, std::string const& path_to_client_binary, bool display_messages = true, size_t stop_fifo_index = 0, + SatTerm_Server(std::string const& identifier, std::string const& path_to_client_binary, bool display_messages = true, + std::string const& terminal_emulator_paths = "./terminal_emulator_paths.txt", size_t stop_fifo_index = 0, size_t sc_fifo_count = 1, size_t cs_fifo_count = 1, char end_char = 3, std::string const& stop_message = "q"); ~SatTerm_Server(); private: - std::vector LoadTerminalEmulatorPaths(std::string const& file_path); - pid_t StartClient(std::string const& path_to_terminal_emulator_paths); + std::string GetWorkingPath(void); bool CreateFifos(size_t sc_fifo_count, size_t cs_fifo_count); + std::vector __CreateFifos(size_t fifo_count, std::string const& fifo_identifier_prefix); + pid_t StartClient(std::string const& path_to_terminal_emulator_paths); + std::vector LoadTerminalEmulatorPaths(std::string const& file_path); bool OpenFifos(unsigned long timeout_seconds); - std::string GetWorkingPath(void); std::string m_path_to_client_binary = ""; }; @@ -104,7 +106,7 @@ class SatTerm_Client : public SatTerm_Component { ~SatTerm_Client(); private: - size_t ParseVarargs(int argc, char* argv[]); + size_t GetArgStartIndex(int argc, char* argv[]); std::vector ParseFifoPaths(size_t argv_start_index, size_t argv_count, char* argv[]); bool OpenFifos(unsigned long timeout_seconds); }; diff --git a/src/satterm_client.cpp b/src/satterm_client.cpp index a4eda32..9e8d512 100644 --- a/src/satterm_client.cpp +++ b/src/satterm_client.cpp @@ -25,6 +25,7 @@ #include // std::string. #include // std::vector. #include // std::cout, std::cerr, std::endl. +#include // std::out_of_range, std::invalid_argument. #include // SIGPIPE, SIG_IGN. #include // write(), read(), close(). @@ -45,36 +46,61 @@ SatTerm_Client::SatTerm_Client(std::string const& identifier, int argc, char* ar // before/if writing again. m_component_type = "Client"; - size_t argv_start_index = ParseVarargs(argc, argv); + size_t argv_start_index = GetArgStartIndex(argc, argv); if (argv_start_index != 0) { - m_working_path = std::string(argv[argv_start_index]); - m_stop_fifo_index = std::stoi(std::string(argv[argv_start_index + 1])); - m_end_char = (char)(std::stoi(std::string(argv[argv_start_index + 2]))); - m_stop_message = std::string(argv[argv_start_index + 3]); - size_t tx_fifo_count = std::stoi(std::string(argv[argv_start_index + 4])); - size_t rx_fifo_count = std::stoi(std::string(argv[argv_start_index + 5])); - m_tx_fifo_paths = ParseFifoPaths(argv_start_index + 6, tx_fifo_count, argv); - m_rx_fifo_paths = ParseFifoPaths(argv_start_index + 6 + tx_fifo_count, rx_fifo_count, argv); - - if (m_display_messages) { - std::string message = "Fifo working path is " + m_working_path; - std::cerr << message << std::endl; + // Parse argv - Parameters are sanity checked by server but we'll try and catch appropriate exceptions in case the args became garbled in transmission. + bool success = true; + try { + m_working_path = std::string(argv[argv_start_index]); + m_stop_fifo_index = std::stoi(std::string(argv[argv_start_index + 1])); + m_end_char = (char)(std::stoi(std::string(argv[argv_start_index + 2]))); + m_stop_message = std::string(argv[argv_start_index + 3]); + size_t tx_fifo_count = std::stoi(std::string(argv[argv_start_index + 4])); + size_t rx_fifo_count = std::stoi(std::string(argv[argv_start_index + 5])); + m_tx_fifo_paths = ParseFifoPaths(argv_start_index + 6, tx_fifo_count, argv); + m_rx_fifo_paths = ParseFifoPaths(argv_start_index + 6 + tx_fifo_count, rx_fifo_count, argv); + } + catch (const std::invalid_argument& ia) { + success = false; + m_error_code = {-1, "invalid_argument"}; + if (m_display_messages) { + std::string error_message = "An invalid command-line argument was passed to the client."; + std::cerr << error_message << std::endl; + } + } + catch (const std::out_of_range& oor) { + success = false; + m_error_code = {-1, "out_of_range_argument"}; + if (m_display_messages) { + std::string error_message = "An out-of-range command-line argument was passed to the client."; + std::cerr << error_message << std::endl; + } } - unsigned long timeout_seconds = 5; - bool success = OpenFifos(timeout_seconds); if (success) { if (m_display_messages) { - std::string message = "Client " + m_identifier + " initialised successfully."; + std::string message = "Fifo working path is " + m_working_path; std::cerr << message << std::endl; } - m_connected = true; - } else { - if (m_display_messages) { - std::string message = "Client " + m_identifier + " unable to intialise connection."; - std::cerr << message << std::endl; + + unsigned long timeout_seconds = 5; + success = OpenFifos(timeout_seconds); + if (success) { + if (m_display_messages) { + std::string message = "Client " + m_identifier + " initialised successfully."; + std::cerr << message << std::endl; + } + m_connected = true; + } else { + // m_error_code already set in OpenFifos(). + if (m_display_messages) { + std::string error_message = "Client " + m_identifier + " unable to intialise connection."; + std::cerr << error_message << std::endl; + } + m_connected = false; } + } else { m_connected = false; } } else { @@ -96,7 +122,7 @@ SatTerm_Client::~SatTerm_Client() { } } -size_t SatTerm_Client::ParseVarargs(int argc, char* argv[]) { +size_t SatTerm_Client::GetArgStartIndex(int argc, char* argv[]) { size_t argument_index = 1; bool failed = false; while (std::string(argv[argument_index]) != "client_args") { diff --git a/src/satterm_component.cpp b/src/satterm_component.cpp index e11b5f7..e5cf751 100644 --- a/src/satterm_component.cpp +++ b/src/satterm_component.cpp @@ -50,8 +50,8 @@ bool SatTerm_Component::OpenRxFifos(unsigned long timeout_seconds) { int fifo = open(fifo_path.c_str(), O_RDONLY | O_NONBLOCK); if (!(fifo < 0)) { - m_rx_fifo_descriptors.emplace_back(fifo); - m_current_messages.emplace_back(""); + m_rx_fifo_descriptors.emplace_back(fifo); // GetMessage() expects fifo index into m_rx_fifo_descriptors, so we'll add it speculatively + m_current_messages.emplace_back(""); // prior to checking for the 'init' message from the server. std::string init_message = GetMessage(rx_fifo_index, false, timeout_seconds); @@ -63,6 +63,7 @@ bool SatTerm_Component::OpenRxFifos(unsigned long timeout_seconds) { } } else { m_rx_fifo_descriptors.pop_back(); // Failed to receive 'init' message so do not store descriptor. + m_current_messages.pop_back(); if (m_error_code == error_descriptor{-1, "GetMessage()_tx_unconn_timeout"}) { if (m_display_messages) { @@ -104,7 +105,7 @@ bool SatTerm_Component::OpenTxFifos(unsigned long timeout_seconds) { std::cerr << message << std::endl; } - m_tx_fifo_descriptors.emplace_back(fifo); + m_tx_fifo_descriptors.emplace_back(fifo); // SendMessage() expects fifo index into m_rx_fifo_descriptors, so we'll add it speculatively. std::string init_message = "init"; init_message = SendMessage(init_message, fifo_index); @@ -160,7 +161,7 @@ std::string SatTerm_Component::GetMessage(size_t rx_fifo_index, bool capture_end std::string message; if (rx_fifo_index >= m_rx_fifo_descriptors.size()) { - m_error_code = {-1, "rx_fifo_index_OOR"}; + m_error_code = {-1, "GetMessage()_fifo_index_OOR"}; if (m_display_messages) { std::string error_message = "RX fifo index " + std::to_string(rx_fifo_index) + " Out Of Range."; std::cerr << error_message << std::endl; @@ -254,7 +255,7 @@ size_t SatTerm_Component::SendBytes(const char* bytes, size_t byte_count, size_t size_t bytes_remaining = byte_count; if (tx_fifo_index >= m_tx_fifo_descriptors.size()) { - m_error_code = {-1, "tx_fifo_index_OOR"}; + m_error_code = {-1, "SendBytes()_fifo_index_OOR"}; if (m_display_messages) { std::string error_message = "TX fifo index " + std::to_string(tx_fifo_index) + " Out Of Range."; std::cerr << error_message << std::endl; @@ -278,7 +279,7 @@ size_t SatTerm_Component::SendBytes(const char* bytes, size_t byte_count, size_t bytes_remaining -= (size_t)(status); } else { switch (errno) { - case EAGAIN: // Erro - thread would block (buffer full, etc). Try again unless timeout. + case EAGAIN: // Erro - thread would block (reader currently reading, etc). Try again unless timeout. finished = ((time(0) - start_time) > timeout_seconds); if ((finished) && (timeout_seconds == 0)) { m_error_code = {errno, "write()_thread_block"}; diff --git a/src/satterm_server.cpp b/src/satterm_server.cpp index 938605e..6ec6ad9 100644 --- a/src/satterm_server.cpp +++ b/src/satterm_server.cpp @@ -35,12 +35,15 @@ #include // std::cout, std::cerr, std::endl. #include // std::ifstream. #include // remove(). +#include // #include "satellite_terminal.h" // Class constructor and member function definitions for derived Server class. -SatTerm_Server::SatTerm_Server(std::string const& identifier, std::string const& path_to_client_binary, bool display_messages, size_t stop_fifo_index, size_t tx_fifo_count, size_t rx_fifo_count, char end_char, std::string const& stop_message) { +SatTerm_Server::SatTerm_Server(std::string const& identifier, std::string const& path_to_client_binary, bool display_messages, + std::string const& terminal_emulator_paths, size_t stop_fifo_index, size_t tx_fifo_count, size_t rx_fifo_count, + char end_char, std::string const& stop_message) { m_identifier = identifier; m_display_messages = display_messages; @@ -70,7 +73,7 @@ SatTerm_Server::SatTerm_Server(std::string const& identifier, std::string const& success = CreateFifos(tx_fifo_count, rx_fifo_count); if (success) { - if (StartClient("./terminal_emulator_paths.txt") < 0) { + if (StartClient(terminal_emulator_paths) < 0) { m_error_code = {1, "fork()"}; if (m_display_messages) { std::string message = "Unable to start client process."; @@ -168,49 +171,43 @@ std::string SatTerm_Server::GetWorkingPath(void) { bool SatTerm_Server::CreateFifos(size_t tx_fifo_count, size_t rx_fifo_count) { m_error_code = {0, ""}; - bool success = true; - int status = 0; + bool success = false; - for (size_t tx_fifo_index = 0; tx_fifo_index < tx_fifo_count; tx_fifo_index ++) { - std::string fifo_path = m_identifier + "_fifo_sc_" + std::to_string(tx_fifo_index); - remove(fifo_path.c_str()); // If temporary file already exists, delete it. + m_tx_fifo_paths = __CreateFifos(tx_fifo_count, m_identifier + "_fifo_sc_"); + if (m_error_code.err_no == 0) { + m_rx_fifo_paths = __CreateFifos(rx_fifo_count, m_identifier + "_fifo_cs_"); + if (m_error_code.err_no == 0) { + success = true; + } else { + success = false; + } + } else { + success = false; + } + return success; +} + +std::vector SatTerm_Server::__CreateFifos(size_t fifo_count, std::string const& fifo_identifier_prefix) { + m_error_code = {0, ""}; + std::vector fifo_identifiers = {}; + for (size_t fifo_index = 0; fifo_index < fifo_count; fifo_index ++) { + std::string fifo_identifier = fifo_identifier_prefix + std::to_string(fifo_index); + remove(fifo_identifier.c_str()); // If temporary file already exists, delete it. - status = mkfifo(fifo_path.c_str(), S_IFIFO|0666); + int status = mkfifo(fifo_identifier.c_str(), S_IFIFO|0666); if (status < 0) { m_error_code = {errno, "mkfifo()"}; if (m_display_messages) { - std::string error_message = "Unable to open fifo at path " + fifo_path; + std::string error_message = "Server mkfifo() error trying to open fifo at path " + m_working_path + fifo_identifier; perror(error_message.c_str()); } - success = false; break; } else { - m_tx_fifo_paths.emplace_back(fifo_path); + fifo_identifiers.emplace_back(fifo_identifier); } } - - if (success) { - for (size_t rx_fifo_index = 0; rx_fifo_index < rx_fifo_count; rx_fifo_index ++) { - std::string fifo_path = m_identifier + "_fifo_cs_" + std::to_string(rx_fifo_index); - remove(fifo_path.c_str()); // If temporary file already exists, delete it. - - status = mkfifo(fifo_path.c_str(), S_IFIFO|0666); - - if (status < 0) { - m_error_code = {errno, "mkfifo()"}; - if (m_display_messages) { - std::string error_message = "Unable to open fifo at path " + fifo_path; - perror(error_message.c_str()); - } - success = false; - break; - } else { - m_rx_fifo_paths.emplace_back(fifo_path); - } - } - } - return success; + return fifo_identifiers; } pid_t SatTerm_Server::StartClient(std::string const& path_to_terminal_emulator_paths) { @@ -269,16 +266,6 @@ pid_t SatTerm_Server::StartClient(std::string const& path_to_terminal_emulator_p return process; } -bool SatTerm_Server::OpenFifos(unsigned long timeout_seconds) { - bool success = false; - success = OpenRxFifos(timeout_seconds); - - if (success) { // Only attempt to open fifos for writing if we were able to open the fifos for reading. - success = OpenTxFifos(timeout_seconds); - } - return success; -} - std::vector SatTerm_Server::LoadTerminalEmulatorPaths(std::string const& file_path) { m_error_code = {0, ""}; @@ -299,3 +286,13 @@ std::vector SatTerm_Server::LoadTerminalEmulatorPaths(std::string c } return terminal_emulator_paths; } + +bool SatTerm_Server::OpenFifos(unsigned long timeout_seconds) { + bool success = false; + success = OpenRxFifos(timeout_seconds); + + if (success) { // Only attempt to open fifos for writing if we were able to open the fifos for reading. + success = OpenTxFifos(timeout_seconds); + } + return success; +}