#include "system_client.h" system_client::system_client(const std::string & unix_file, std::function log_func) : clt(io_context, unix_file, std::bind(&system_client::data_received, this, std::placeholders::_1)) , log(log_func) , ctx_thread([&] { io_context.run(); } ) , cmd_id(0) , current_state(state::connected) { } system_client::~system_client() { io_context.stop(); ctx_thread.join(); } state system_client::get_current_state() const { return current_state; } response_type system_client::send_login_cmd(const std::string & username, const std::string & pass, access_rights & access) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header login_cmd_hdr { curr_id, cmd_type::login }; login_cmd log_req { username, pass }; send_to_socket(login_cmd_hdr, log_req); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::login, data_from_serv); access = access_rights::not_allowed; if (data_from_serv.has_value()) access = std::any_cast(data_from_serv); return result; } response_type system_client::send_copy_cmd(const fm::side_description & src, const fm::side_description & dst) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header copy_cmd_hdr { curr_id, cmd_type::copy }; copy_cmd copy_req { src, dst }; send_to_socket(copy_cmd_hdr, copy_req); return wait_for_progressing_response(curr_id, cmd_type::copy); } response_type system_client::send_ping_cmd(const std::string & ip, size_t count) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header ping_cmd_hdr { curr_id, cmd_type::ping }; ping_cmd ping_req { ip, count }; send_to_socket(ping_cmd_hdr, ping_req); return wait_for_progressing_response(curr_id, cmd_type::ping); } response_type system_client::send_traceroute_cmd(const std::string & ip) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header tracert_cmd_hdr { curr_id, cmd_type::tracert }; tracert_cmd tracert_req { ip }; send_to_socket(tracert_cmd_hdr, tracert_req); return wait_for_progressing_response(curr_id, cmd_type::tracert); } response_type system_client::send_show_interface_cmd(const interface_value & interface) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header interface_cmd_hdr { curr_id, cmd_type::interface }; interface_cmd interface_req { interface }; send_to_socket(interface_cmd_hdr, interface_req); return wait_for_progressing_response(curr_id, cmd_type::interface); } response_type system_client::wait_for_progressing_response(uint32_t c_id, const cmd_type & cmd_t) { auto result = response_type::in_progress; while (result != response_type::ok && result != response_type::error && result != response_type::abort) { std::any data_from_serv; result = wait_for_response(c_id, cmd_t, data_from_serv); if (data_from_serv.has_value() && stdout_cb) { auto & text_bytes = std::any_cast&>(data_from_serv); std::scoped_lock lock(cb_mtx); stdout_cb(reinterpret_cast(text_bytes.data()), text_bytes.size()); } } if (result == response_type::abort) { std::scoped_lock lock_1(responses_mtx); responses.erase(c_id); responses_data.erase(c_id); } return result; } void system_client::abort() { send_abort(cmd_id); process_response(cmd_id, response_type::abort, {}); } void system_client::send_abort(uint32_t id) { std::stringstream s; cmd_header abort_cmd { id, cmd_type::abort }; { cereal::BinaryOutputArchive oarchive(s); oarchive(abort_cmd); } std::vector data((std::istream_iterator(s)), std::istream_iterator()); clt.write(data); } response_type system_client::send_logout_cmd() { if (current_state != state::logged_in) return response_type::error; std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { cmd_id++ }; cmd_header logout_cmd_hdr { curr_id, cmd_type::exit }; std::stringstream s; { cereal::BinaryOutputArchive oarchive(s); oarchive(logout_cmd_hdr); } std::vector data((std::istream_iterator(s)), std::istream_iterator()); clt.write(data); std::any data_from_serv; return wait_for_response(curr_id, cmd_type::exit, data_from_serv); } response_type system_client::wait_for_response(uint32_t id, const cmd_type & type, std::any & data) { std::unique_lock lock(responses_mtx); cv_resp.wait(lock, [&] { return responses.find(id) != responses.end(); } ); auto result = std::move(responses[id].front()); data = std::move(responses_data[id].front()); responses[id].pop(); responses_data[id].pop(); if (result != response_type::abort && responses[id].empty()) { responses.erase(id); responses_data.erase(id); } if (result == response_type::ok) { switch (type) { case cmd_type::login: { current_state = state::logged_in; break; } case cmd_type::exit: { current_state = state::disconnected; clt.do_close(); break; } default: break; } } return result; } void system_client::process_response(uint32_t id, response_type resp, std::any && data) { { std::scoped_lock lock(responses_mtx); if (responses.find(id) != responses.end() && responses[id].empty() && responses[id].front() == response_type::abort) return; responses[id].push(resp); responses_data[id].push(std::move(data)); } cv_resp.notify_all(); } void system_client::data_received(const std::vector & data) { std::stringstream ss; std::copy(data.begin(), data.end(), std::ostream_iterator(ss)); cereal::BinaryInputArchive iarchive(ss); response_header cmd; iarchive(cmd); std::any data_from_serv; switch (cmd.cmd) { case cmd_type::login: { if (cmd.rsp == response_type::ok) { access_rights access; iarchive(access); data_from_serv = access; } break; } case cmd_type::ping: case cmd_type::tracert: case cmd_type::interface: { if (cmd.rsp == response_type::in_progress) { std::vector data_rsp; iarchive(data_rsp); data_from_serv = std::move(data_rsp); } break; } case cmd_type::get_demodulator_frequency: { if (cmd.rsp == response_type::ok) { uint32_t freq; iarchive(freq); data_from_serv = freq; } break; } case cmd_type::get_gain_param: { if (cmd.rsp == response_type::ok) { double gain; iarchive(gain); data_from_serv = gain; } break; } case cmd_type::zynq_param: { if (cmd.rsp == response_type::ok) { double value; iarchive(value); data_from_serv = value; } break; } case cmd_type::get_demodulator_param: { if (cmd.rsp == response_type::ok) { uint32_t value; iarchive(value); data_from_serv = value; } break; } case cmd_type::get_modulator_param: { if (cmd.rsp == response_type::ok) { uint32_t value; iarchive(value); data_from_serv = value; } break; } case cmd_type::get_level_dmd: { if (cmd.rsp == response_type::ok) { double value; iarchive(value); data_from_serv = value; } break; } case cmd_type::get_acm_params: { if(cmd.rsp == response_type::ok) { cmd_get_acm_param value; iarchive(value); data_from_serv = value; } break; } case cmd_type::get_dma_debugg: { if (cmd.rsp == response_type::ok) { std::string value; iarchive(value); data_from_serv = value; } break; } case cmd_type::get_params_dpdi: { if (cmd.rsp == response_type::ok) { dpdi_parameters value; iarchive(value); data_from_serv = value; } break; } case cmd_type::get_network: { if (cmd.rsp == response_type::ok) { std::string value; iarchive(value); data_from_serv = value; } break; } case cmd_type::get_qos_settings: { if (cmd.rsp == response_type::ok) { std::string value; iarchive(value); data_from_serv = value; } break; } default: break; } process_response(cmd.id, cmd.rsp, std::move(data_from_serv)); } void system_client::set_stdout_callback(std::function cb) { std::scoped_lock lock(cb_mtx); stdout_cb = cb; } response_type system_client::send_set_dem_freq_cmd(uint32_t freq) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header set_dem_freq_cmd_hdr { curr_id, cmd_type::set_demodulator_frequency }; set_dem_freq_cmd freq_set { freq }; send_to_socket(set_dem_freq_cmd_hdr, freq_set); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::set_demodulator_frequency , data_from_serv); return result; } response_type system_client::send_get_dem_freq_cmd(uint32_t & freq) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header get_dem_freq_cmd_hdr { curr_id, cmd_type::get_demodulator_frequency }; send_to_socket(get_dem_freq_cmd_hdr); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::get_demodulator_frequency , data_from_serv); if (data_from_serv.has_value()) freq = std::any_cast(data_from_serv); return result; } response_type system_client::send_get_gain_param(const gain_value & interface_gain, double & gain) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header get_gain_cmd_hdr{curr_id,cmd_type::get_gain_param}; get_gain_par get_gain_cmd{interface_gain}; send_to_socket(get_gain_cmd_hdr,get_gain_cmd); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::get_gain_param , data_from_serv); if (data_from_serv.has_value()) gain = std::any_cast(data_from_serv); return result; } response_type system_client::send_get_demodulator_param(const getdemodulator_value & demod_val, uint32_t & value) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header get_demod_param{curr_id,cmd_type::get_demodulator_param}; cmd_get_demodulator_param get_dmd_param{demod_val, 0}; send_to_socket(get_demod_param,get_dmd_param); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::get_demodulator_param , data_from_serv); if (data_from_serv.has_value()) value = std::any_cast(data_from_serv); return result; } response_type system_client::send_get_modulator_param(const modulator_value & mod_val, uint32_t & value) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header get_mod_param{curr_id,cmd_type::get_modulator_param}; cmd_get_modulator_param cmd_get_mod_param{mod_val, 0}; send_to_socket(get_mod_param,cmd_get_mod_param); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::get_modulator_param , data_from_serv); if (data_from_serv.has_value()) value = std::any_cast(data_from_serv); return result; } response_type system_client::send_set_gain_param(const gain_value & interface_gain, double gain) { std::scoped_lock lock (cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header set_gain_cmd_hdr{curr_id, cmd_type::set_gain_param}; set_gain_par set_gain_cmd{interface_gain, gain}; send_to_socket(set_gain_cmd_hdr,set_gain_cmd); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::set_gain_param , data_from_serv); return result; } response_type system_client::send_radio_enable(const cmd_radio & enable_choice, bool enbl_) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header radio_enable_cmd_hdr{curr_id, cmd_type::radio_on_of}; radio_enable radio_enable_cmd{enable_choice, enbl_}; send_to_socket(radio_enable_cmd_hdr, radio_enable_cmd); std::any data_to_serv; auto result = wait_for_response(curr_id, cmd_type::radio_on_of, data_to_serv); return result; } response_type system_client::send_set_demodulator_param(const demodulator_value & demod_val, uint32_t value) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header demodulator_cmd_hdr{curr_id, cmd_type::set_demodulator_param}; cmd_set_demodulator_param demodulator_cmd{demod_val, value}; send_to_socket(demodulator_cmd_hdr, demodulator_cmd); std::any data_to_serv; auto result = wait_for_response(curr_id, cmd_type::set_demodulator_param, data_to_serv); return result; } response_type system_client::send_modulator_param(const modulator_value & mod_val, uint32_t value) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header modulator_cmd_hdr{curr_id, cmd_type::modulator_param}; cmd_set_modulator_param modulator_cmd{mod_val, value}; send_to_socket(modulator_cmd_hdr, modulator_cmd); std::any data_to_serv; auto result = wait_for_response(curr_id, cmd_type::modulator_param, data_to_serv); return result; } response_type system_client::send_zynq_cmd(const zynq_value & zynq_val, double & value) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header zynq_cmd_hdr{curr_id, cmd_type::zynq_param}; cmd_zynq_param zynq_cmd{zynq_val}; send_to_socket(zynq_cmd_hdr, zynq_cmd); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::zynq_param, data_from_serv); if (data_from_serv.has_value()) value = std::any_cast(data_from_serv); return result; } response_type system_client::send_rollof_and_baudrate(double & rollof, double &baudrate) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header roll_baud_cmd_hdr{curr_id, cmd_type::set_baudrate_rollof_dmd}; cmd_set_rollof_and_demod cmd_roll_baud{baudrate, rollof}; send_to_socket(roll_baud_cmd_hdr, cmd_roll_baud); std::any data_to_serv; auto result = wait_for_response(curr_id, cmd_type::set_baudrate_rollof_dmd, data_to_serv); return result; } response_type system_client::send_get_dma_debug(const cmd_get_dma_debugg_enum & dma_debug, std::string &value) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header get_dma_debug_header{curr_id, cmd_type::get_dma_debugg}; cmd_get_dma_debug val_cmd{value, dma_debug}; send_to_socket(get_dma_debug_header, val_cmd); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::get_dma_debugg, data_from_serv); if (data_from_serv.has_value()) value = std::any_cast(data_from_serv); return result; } response_type system_client::send_get_level_dem(const cmd_level_dem & lvl_dem_val, double &value) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header snr_cmd_hdr{curr_id, cmd_type::get_level_dmd}; cmd_get_level_dem val_cmd{value, lvl_dem_val}; send_to_socket(snr_cmd_hdr, val_cmd); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::get_level_dmd, data_from_serv); if (data_from_serv.has_value()) value = std::any_cast(data_from_serv); return result; } response_type system_client::send_get_acm_params(cmd_get_acm_param &acm_params) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header cmd_acm_header{curr_id, cmd_type::get_acm_params}; send_to_socket(cmd_acm_header, acm_params); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::get_acm_params, data_from_serv); if (data_from_serv.has_value()) acm_params = std::any_cast(data_from_serv); return result; } response_type system_client::send_set_qos_params(const std::string &node, const name_classes_qos & class_qos) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header cmd_qos_header{curr_id, cmd_type::set_qos_settings}; cmd_set_qos_settings qos_settings{node, class_qos}; send_to_socket(cmd_qos_header, qos_settings); std::any data_to_serv; auto result = wait_for_response(curr_id, cmd_type::set_qos_settings, data_to_serv); return result; } response_type system_client::send_get_qos_params(std::string &node, const name_classes_qos & class_qos) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header cmd_qos_header{curr_id, cmd_type::get_qos_settings}; cmd_get_qos_settings qos_settings{node, class_qos}; send_to_socket(cmd_qos_header, qos_settings); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::get_qos_settings, data_from_serv); if (data_from_serv.has_value()) node = std::any_cast(data_from_serv); return result; } response_type system_client::send_set_10g_config(const cmd_10g_config & _10g_config, std::string &value) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header _10g_config_header{curr_id, cmd_type::set_10g_config}; cmd_set_10g_config _10g_config_cmd{value, _10g_config}; send_to_socket(_10g_config_header, _10g_config_cmd); std::any data_to_serv; auto result = wait_for_response(curr_id, cmd_type::set_10g_config, data_to_serv); return result; } response_type system_client::send_set_dma_debug(const cmd_dma_debugg & dma_debugg, std::string &value) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header dma_debug_header{curr_id, cmd_type::set_dma_debugg}; cmd_set_dma_debug cmd_dma_debug{value, dma_debugg}; send_to_socket(dma_debug_header, cmd_dma_debug); std::any data_to_serv; auto result = wait_for_response(curr_id, cmd_type::set_dma_debugg, data_to_serv); return result; } response_type system_client::send_set_lbq_params(const uint32_t & tick_ms, const uint32_t & bucket_size) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header lbq_debug_header{curr_id, cmd_type::set_lbq_params}; cmd_lbq_params params{tick_ms, bucket_size}; send_to_socket(lbq_debug_header, params); std::any data_to_serv; auto result = wait_for_response(curr_id, cmd_type::set_lbq_params, data_to_serv); return result; } response_type system_client::send_set_acm_params(const ACM_parameters_serv &acm_params) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header cmd_acm_header{curr_id, cmd_type::set_acm_params}; cmd_set_acm_param cmd_set_acm{acm_params}; send_to_socket(cmd_acm_header, cmd_set_acm); std::any data_to_serv; auto result = wait_for_response(curr_id, cmd_type::set_acm_params, data_to_serv); return result; } response_type system_client::send_set_dpdi_params(dpdi_parameters &dpdi_params) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header cmd_dpdi_header{curr_id, cmd_type::set_params_dpdi}; dpdi_parameters cmd_set_dpdi{dpdi_params}; send_to_socket(cmd_dpdi_header, cmd_set_dpdi); std::any data_to_serv; auto result = wait_for_response(curr_id, cmd_type::set_params_dpdi, data_to_serv); return result; } response_type system_client::send_get_dpdi_params(dpdi_parameters &dpdi_params) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header cmd_dpdi_header{curr_id, cmd_type::get_params_dpdi}; send_to_socket(cmd_dpdi_header, dpdi_params); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::get_params_dpdi, data_from_serv); if (data_from_serv.has_value()) dpdi_params = std::any_cast(data_from_serv); return result; } response_type system_client::send_network_settings(const network_value & cmd_netw, const std::string & value) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header network_cmd_hdr{curr_id, cmd_type::set_network}; cmd_set_network cmd_network{value, cmd_netw}; send_to_socket(network_cmd_hdr, cmd_network); std::any data_to_serv; auto result = wait_for_response(curr_id, cmd_type::set_network, data_to_serv); return result; } response_type system_client::send_get_network_settings(const network_value & cmd_netw, std::string & value) { std::scoped_lock lock(cmd_in_progress_mtx); uint32_t curr_id { ++cmd_id }; cmd_header cmd_network_hdr{curr_id, cmd_type::get_network}; cmd_get_network cmd_network{value, cmd_netw}; send_to_socket(cmd_network_hdr, cmd_network); std::any data_from_serv; auto result = wait_for_response(curr_id, cmd_type::get_network, data_from_serv); if (data_from_serv.has_value()) value = std::any_cast(data_from_serv); return result; }