diff options
-rw-r--r-- | src/RemoteControl.cpp | 121 | ||||
-rw-r--r-- | src/RemoteControl.h | 68 |
2 files changed, 110 insertions, 79 deletions
diff --git a/src/RemoteControl.cpp b/src/RemoteControl.cpp index 18c74b7..b32c21a 100644 --- a/src/RemoteControl.cpp +++ b/src/RemoteControl.cpp @@ -3,7 +3,7 @@ Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2019 Matthias P. Braendli, matthias.braendli@mpb.li http://www.opendigitalradio.org @@ -52,7 +52,7 @@ RemoteControllerTelnet::~RemoteControllerTelnet() } } -void RemoteControllerTelnet::internal_restart() +void RemoteControllerTelnet::restart() { if (m_restarter_thread.joinable()) { m_restarter_thread.join(); @@ -75,8 +75,53 @@ std::list<std::string> RemoteControllable::get_supported_parameters() const { return parameterlist; } -RemoteControllable* RemoteControllers::get_controllable_( - const std::string& name) +void RemoteControllers::add_controller(std::shared_ptr<BaseRemoteController> rc) { + m_controllers.push_back(rc); +} + +void RemoteControllers::enrol(RemoteControllable *rc) { + controllables.push_back(rc); +} + +void RemoteControllers::remove_controllable(RemoteControllable *rc) { + controllables.remove(rc); +} + +std::list< std::vector<std::string> > RemoteControllers::get_param_list_values(const std::string& name) { + RemoteControllable* controllable = get_controllable_(name); + + std::list< std::vector<std::string> > allparams; + for (auto ¶m : controllable->get_supported_parameters()) { + std::vector<std::string> item; + item.push_back(param); + try { + item.push_back(controllable->get_parameter(param)); + } + catch (const ParameterError &e) { + item.push_back(std::string("error: ") + e.what()); + } + + allparams.push_back(item); + } + return allparams; +} + +std::string RemoteControllers::get_param(const std::string& name, const std::string& param) { + RemoteControllable* controllable = get_controllable_(name); + return controllable->get_parameter(param); +} + +void RemoteControllers::check_faults() { + for (auto &controller : m_controllers) { + if (controller->fault_detected()) { + etiLog.level(warn) << + "Detected Remote Control fault, restarting it"; + controller->restart(); + } + } +} + +RemoteControllable* RemoteControllers::get_controllable_(const std::string& name) { auto rc = std::find_if(controllables.begin(), controllables.end(), [&](RemoteControllable* r) { return r->get_rc_name() == name; }); @@ -97,7 +142,14 @@ void RemoteControllers::set_param( etiLog.level(info) << "RC: Setting " << name << " " << param << " to " << value; RemoteControllable* controllable = get_controllable_(name); - return controllable->set_parameter(param, value); + try { + return controllable->set_parameter(param, value); + } + catch (const ios_base::failure& e) { + etiLog.level(info) << "RC: Failed to set " << name << " " << param + << " to " << value << ": " << e.what(); + throw ParameterError("Cannot understand value"); + } } // This runs in a separate thread, because @@ -129,8 +181,7 @@ void RemoteControllerTelnet::handle_accept( std::string in_message; size_t length; - if (boost_error) - { + if (boost_error) { etiLog.level(error) << "RC: Error accepting connection"; return; } @@ -179,7 +230,7 @@ void RemoteControllerTelnet::handle_accept( etiLog.level(info) << "RC: Closing socket"; socket->close(); } - catch (std::exception& e) + catch (const std::exception& e) { etiLog.level(error) << "Remote control caught exception: " << e.what(); } @@ -218,9 +269,21 @@ void RemoteControllerTelnet::process(long) m_fault = true; } +static std::vector<std::string> tokenise(const std::string& message) { + stringstream ss(message); + std::vector<std::string> all_tokens; + std::string item; + + while (std::getline(ss, item, ' ')) { + all_tokens.push_back(move(item)); + } + return all_tokens; +} + + void RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string command) { - vector<string> cmd = tokenise_(command); + vector<string> cmd = tokenise(command); if (cmd[0] == "help") { reply(socket, @@ -267,7 +330,7 @@ void RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string comman reply(socket, ss.str()); } - catch (ParameterError &e) { + catch (const ParameterError &e) { reply(socket, e.what()); } } @@ -281,7 +344,7 @@ void RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string comman string r = rcs.get_param(cmd[1], cmd[2]); reply(socket, r); } - catch (ParameterError &e) { + catch (const ParameterError &e) { reply(socket, e.what()); } } @@ -304,10 +367,10 @@ void RemoteControllerTelnet::dispatch_command(tcp::socket& socket, string comman rcs.set_param(cmd[1], cmd[2], new_param_value.str()); reply(socket, "ok"); } - catch (ParameterError &e) { + catch (const ParameterError &e) { reply(socket, e.what()); } - catch (exception &e) { + catch (const exception &e) { reply(socket, "Error: Invalid parameter value. "); } } @@ -406,6 +469,8 @@ void RemoteControllerZmq::send_fail_reply(zmq::socket_t &pSocket, const std::str void RemoteControllerZmq::process() { + m_fault = false; + // create zmq reply socket for receiving ctrl parameters try { zmq::socket_t repSocket(m_zmqContext, ZMQ_REP); @@ -436,7 +501,23 @@ void RemoteControllerZmq::process() size_t cohort_size = rcs.controllables.size(); for (auto &controllable : rcs.controllables) { std::stringstream ss; - ss << controllable->get_rc_name(); + ss << "{ \"name\": \"" << controllable->get_rc_name() << "\"," << + " \"params\": { "; + + list< vector<string> > params = controllable->get_parameter_descriptions(); + size_t i = 0; + for (auto ¶m : params) { + if (i > 0) { + ss << ", "; + } + + ss << "\"" << param[0] << "\": " << + "\"" << param[1] << "\""; + + i++; + } + + ss << " } }"; std::string msg_s = ss.str(); @@ -462,8 +543,8 @@ void RemoteControllerZmq::process() repSocket.send(zmsg, flag); } } - catch (ParameterError &e) { - send_fail_reply(repSocket, e.what()); + catch (const ParameterError &err) { + send_fail_reply(repSocket, err.what()); } } else if (msg.size() == 3 && command == "get") { @@ -476,7 +557,7 @@ void RemoteControllerZmq::process() memcpy ((void*) zmsg.data(), value.data(), value.size()); repSocket.send(zmsg, 0); } - catch (ParameterError &err) { + catch (const ParameterError &err) { send_fail_reply(repSocket, err.what()); } } @@ -489,7 +570,7 @@ void RemoteControllerZmq::process() rcs.set_param(module, parameter, value); send_ok_reply(repSocket); } - catch (ParameterError &err) { + catch (const ParameterError &err) { send_fail_reply(repSocket, err.what()); } } @@ -501,10 +582,10 @@ void RemoteControllerZmq::process() } repSocket.close(); } - catch (zmq::error_t &e) { + catch (const zmq::error_t &e) { etiLog.level(error) << "ZMQ RC error: " << std::string(e.what()); } - catch (std::exception& e) { + catch (const std::exception& e) { etiLog.level(error) << "ZMQ RC caught exception: " << e.what(); m_fault = true; } diff --git a/src/RemoteControl.h b/src/RemoteControl.h index 7fc8e04..0726b28 100644 --- a/src/RemoteControl.h +++ b/src/RemoteControl.h @@ -3,7 +3,7 @@ Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2019 Matthias P. Braendli, matthias.braendli@mpb.li http://www.opendigitalradio.org @@ -134,48 +134,12 @@ class RemoteControllable { */ class RemoteControllers { public: - void add_controller(std::shared_ptr<BaseRemoteController> rc) { - m_controllers.push_back(rc); - } - - void enrol(RemoteControllable *rc) { - controllables.push_back(rc); - } - - void remove_controllable(RemoteControllable *rc) { - controllables.remove(rc); - } - - void check_faults() { - for (auto &controller : m_controllers) { - if (controller->fault_detected()) - { - etiLog.level(warn) << - "Detected Remote Control fault, restarting it"; - controller->restart(); - } - } - } - - std::list< std::vector<std::string> > - get_param_list_values(const std::string& name) { - RemoteControllable* controllable = get_controllable_(name); - - std::list< std::vector<std::string> > allparams; - for (auto ¶m : controllable->get_supported_parameters()) { - std::vector<std::string> item; - item.push_back(param); - item.push_back(controllable->get_parameter(param)); - - allparams.push_back(item); - } - return allparams; - } - - std::string get_param(const std::string& name, const std::string& param) { - RemoteControllable* controllable = get_controllable_(name); - return controllable->get_parameter(param); - } + void add_controller(std::shared_ptr<BaseRemoteController> rc); + void enrol(RemoteControllable *rc); + void remove_controllable(RemoteControllable *rc); + void check_faults(); + std::list< std::vector<std::string> > get_param_list_values(const std::string& name); + std::string get_param(const std::string& name, const std::string& param); void set_param( const std::string& name, @@ -192,7 +156,6 @@ class RemoteControllers { extern RemoteControllers rcs; - /* Implements a Remote controller based on a simple telnet CLI * that listens on localhost */ @@ -210,9 +173,7 @@ class RemoteControllerTelnet : public BaseRemoteController { m_fault(false), m_port(port) { - // Don't call virtual functions from the ctor - // https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctors - internal_restart(); + restart(); } @@ -223,10 +184,9 @@ class RemoteControllerTelnet : public BaseRemoteController { virtual bool fault_detected() { return m_fault; } - virtual void restart() { internal_restart(); } + virtual void restart(); private: - void internal_restart(); void restart_thread(long); void process(long); @@ -240,16 +200,6 @@ class RemoteControllerTelnet : public BaseRemoteController { const boost::system::error_code& boost_error, boost::shared_ptr< boost::asio::ip::tcp::socket > socket, boost::asio::ip::tcp::acceptor& acceptor); - std::vector<std::string> tokenise_(std::string message) { - std::vector<std::string> all_tokens; - - boost::char_separator<char> sep(" "); - boost::tokenizer< boost::char_separator<char> > tokens(message, sep); - BOOST_FOREACH (const std::string& t, tokens) { - all_tokens.push_back(t); - } - return all_tokens; - } std::atomic<bool> m_active; |