Skip to content

Commit

Permalink
Added catch out_of_range and invalid_argument to the client code to p…
Browse files Browse the repository at this point in the history
…arse argv in case arguments get garbled in transmission.
  • Loading branch information
Sebastien Sikora committed Nov 30, 2021
1 parent 7a66a84 commit 2e573a3
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 76 deletions.
12 changes: 7 additions & 5 deletions src/satellite_terminal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string> 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<std::string> __CreateFifos(size_t fifo_count, std::string const& fifo_identifier_prefix);
pid_t StartClient(std::string const& path_to_terminal_emulator_paths);
std::vector<std::string> LoadTerminalEmulatorPaths(std::string const& file_path);
bool OpenFifos(unsigned long timeout_seconds);
std::string GetWorkingPath(void);

std::string m_path_to_client_binary = "";
};
Expand All @@ -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<std::string> ParseFifoPaths(size_t argv_start_index, size_t argv_count, char* argv[]);
bool OpenFifos(unsigned long timeout_seconds);
};
70 changes: 48 additions & 22 deletions src/satterm_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <string> // std::string.
#include <vector> // std::vector.
#include <iostream> // std::cout, std::cerr, std::endl.
#include <stdexcept> // std::out_of_range, std::invalid_argument.

#include <signal.h> // SIGPIPE, SIG_IGN.
#include <unistd.h> // write(), read(), close().
Expand All @@ -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 {
Expand All @@ -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") {
Expand Down
13 changes: 7 additions & 6 deletions src/satterm_component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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"};
Expand Down
83 changes: 40 additions & 43 deletions src/satterm_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@
#include <iostream> // std::cout, std::cerr, std::endl.
#include <fstream> // std::ifstream.
#include <cstdio> // remove().
#include <stdexcept> //

#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;

Expand Down Expand Up @@ -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.";
Expand Down Expand Up @@ -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<std::string> SatTerm_Server::__CreateFifos(size_t fifo_count, std::string const& fifo_identifier_prefix) {
m_error_code = {0, ""};
std::vector<std::string> 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) {
Expand Down Expand Up @@ -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<std::string> SatTerm_Server::LoadTerminalEmulatorPaths(std::string const& file_path) {
m_error_code = {0, ""};

Expand All @@ -299,3 +286,13 @@ std::vector<std::string> 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;
}

0 comments on commit 2e573a3

Please sign in to comment.