diff --git a/.github/workflows/conf-build-test.yml b/.github/workflows/conf-build-test.yml index f42376c..fad795b 100644 --- a/.github/workflows/conf-build-test.yml +++ b/.github/workflows/conf-build-test.yml @@ -21,7 +21,7 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install -y cmake ninja-build doxygen clang-tidy python3-pip libglib2.0-dev + sudo apt-get install -y cmake ninja-build doxygen clang-tidy python3-pip libglib2.0-dev libreadline-dev - name: Check if formatted_code branch exists if: ${{ github.event_name == 'pull_request' && startsWith(github.base_ref, 'main') && github.head_ref == 'develop' }} diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c0a2070..cbba90c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,6 +1,8 @@ if(BUILD_CONNMAN) add_executable(connmanctl_dbus connmanctl.cpp) target_link_libraries(connmanctl_dbus PRIVATE GConnmanDbus) + pkg_check_modules(READLINE REQUIRED IMPORTED_TARGET readline) + target_link_libraries(connmanctl_dbus PRIVATE PkgConfig::READLINE) install( TARGETS connmanctl_dbus diff --git a/examples/connmanctl.cpp b/examples/connmanctl.cpp index 74b1965..64cac59 100644 --- a/examples/connmanctl.cpp +++ b/examples/connmanctl.cpp @@ -1,3 +1,10 @@ +// clang-format off +#include +#include +#include +#include +// clang-format on + #include #include #include @@ -13,39 +20,236 @@ using Amarula::DBus::G::Connman::Connman; using Amarula::DBus::G::Connman::TechProperties; using State = Amarula::DBus::G::Connman::ServProperties::State; +using TechnologyType = TechProperties::Type; + +std::atomic has_message{false}; +std::ostringstream message; +std::mutex message_mutex; +std::mutex hash_mutex; +std::mutex cin_mutex; +std::condition_variable cin_cv; + +std::string passphrase; +std::string connecting_name; +std::atomic connecting = false; + +auto event_hook() -> int { + if (has_message.exchange(false)) { + rl_clear_visible_line(); + { + std::lock_guard lock(message_mutex); + std::cout << message.str(); + message.str(""); + message.clear(); + } + rl_on_new_line(); + rl_redisplay(); + } + + if (connecting) { + std::string prompt = "Enter passphrase for " + connecting_name + ": "; + + rl_set_prompt(prompt.c_str()); + rl_redisplay(); + } + return 0; +} + +enum class Command : std::uint8_t { + Technologies, + Services, + Scan, + Enable, + Disable, + Connect, + Disconnect, + Remove, + Agent, + Quit +}; + +inline const std::unordered_map command_map = { + {Command::Technologies, "technologies"}, + {Command::Services, "services"}, + {Command::Scan, "scan"}, + {Command::Enable, "enable"}, + {Command::Disable, "disable"}, + {Command::Connect, "connect"}, + {Command::Disconnect, "disconnect"}, + {Command::Remove, "remove"}, + {Command::Agent, "agent"}, + {Command::Quit, "quit"}}; + +inline const std::unordered_map tech_map = { + {TechnologyType::Ethernet, "ethernet"}, + {TechnologyType::Wifi, "wifi"}, + {TechnologyType::Cellular, "cellular"}, + {TechnologyType::Bluetooth, "bluetooth"}, + {TechnologyType::Vpn, "vpn"}, + {TechnologyType::Wired, "wired"}, + {TechnologyType::P2p, "p2p"}, + {TechnologyType::Gps, "gps"}, + {TechnologyType::Gadget, "gadget"}}; + +inline const std::vector commands_container = [] { + std::vector string_vector; + string_vector.reserve(command_map.size()); + + for (const auto& [cmd, name] : command_map) { + string_vector.emplace_back(name); + } + + return string_vector; +}(); + +inline const std::vector on_off_container{"on", "off"}; +inline const std::vector enable_disable_container{"enable", + "disable"}; + +inline std::vector services_container; +inline std::vector technologies_container; + +void printContainer(const std::vector& container) { + for (size_t i = 0; i < container.size(); ++i) { + std::cout << container[i]; + if (i + 1 < container.size()) { + std::cout << ", "; + } + } + std::cout << "\n"; +} + +enum class Mode : std::uint8_t { Command, ServiceHash, TechHash, OnOff }; + +inline Mode completion_mode = Mode::Command; + +auto command_generator(const char* text, int state) -> char* { + static size_t index; + static size_t len; + static std::vector variable_container; + + if (state == 0) { + index = 0; + len = strlen(text); + if (completion_mode == Mode::Command) { + variable_container = commands_container; + } else if (completion_mode == Mode::ServiceHash) { + std::lock_guard lock(hash_mutex); + variable_container = services_container; + } else if (completion_mode == Mode::TechHash) { + std::lock_guard lock(hash_mutex); + variable_container = technologies_container; + } else if (completion_mode == Mode::OnOff) { + variable_container = on_off_container; + } + } + + while (index < variable_container.size()) { + const auto cmd = variable_container[index++]; + + if (cmd.compare(0, len, text) == 0) { + return strdup(cmd.c_str()); + } + } + + return nullptr; +} + +auto completion(const char* text, int start, int end) -> char** { + (void)start; + (void)end; + if (start == 0) { + completion_mode = Mode::Command; + } else { + std::string line = rl_line_buffer; + std::istringstream iss(line); + std::string command; + std::string arg; + iss >> command >> arg; + if (command == command_map.at(Command::Agent)) { + completion_mode = Mode::OnOff; + } else if (command == command_map.at(Command::Enable) || + command == command_map.at(Command::Disable) || + command == command_map.at(Command::Scan)) { + completion_mode = Mode::TechHash; + } else if (command == command_map.at(Command::Connect) || + command == command_map.at(Command::Disconnect) || + command == command_map.at(Command::Remove) || + command == command_map.at(Command::Services)) { + completion_mode = Mode::ServiceHash; + } else { + return nullptr; + } + if (!arg.empty() && rl_point > 0 && rl_point == line.size() && + line[rl_point - 1] == ' ') { + return nullptr; + } + } + + return rl_completion_matches(text, command_generator); +} auto main() -> int { - std::mutex cin_mutex; - std::condition_variable cin_cv; - bool connecting = false; - Amarula::Log::enable(true); + rl_event_hook = event_hook; + rl_attempted_completion_function = completion; Connman connman; const auto manager = connman.manager(); manager->onRequestInputPassphrase([&](const auto& service) -> auto { const auto name = service->properties().getName(); - - std::string passphrase; - { - const std::unique_lock lock(cin_mutex); - std::cout << "Enter passphrase for " << name << " service\n"; - std::getline(std::cin, passphrase); - connecting = false; - } - cin_cv.notify_one(); + std::unique_lock lock(cin_mutex); + connecting = true; + connecting_name = name; + cin_cv.wait(lock, [] { return !connecting; }); return std::pair{true, passphrase}; }); - constexpr int CIN_WAIT_TIMEOUT_SECONDS = 30; + manager->onServicesChanged([](const auto& services) { + std::lock_guard lock(hash_mutex); + services_container.clear(); + for (const auto& serv : services) { + const auto path = serv->objPath(); + services_container.push_back( + path.substr(path.find_last_of('/') + 1)); + const auto props = serv->properties(); + const auto name = props.getName(); + if (!name.empty()) { + services_container.push_back(name); + } + } + }); + manager->onTechnologiesChanged([](const auto& technologies) { + std::lock_guard lock(hash_mutex); + technologies_container.clear(); + for (const auto& tech : technologies) { + const auto props = tech->properties(); + technologies_container.push_back( + tech_map.at(props.getType()).data()); + } + }); + std::string line; while (true) { - std::cout << "connmanctl> "; - { - std::unique_lock lock(cin_mutex); - cin_cv.wait_for(lock, - std::chrono::seconds(CIN_WAIT_TIMEOUT_SECONDS), - [&connecting] { return !connecting; }); - if (!std::getline(std::cin, line)) { - break; // EOF or error + char* raw_line = readline("connmanctl> "); + if (raw_line == nullptr) { + break; + } + + line = std::string(raw_line); + free(raw_line); + + if (connecting) { + { + std::lock_guard lock(cin_mutex); + passphrase = line; + connecting = false; + cin_cv.notify_all(); } + rl_set_prompt("connmanctl> "); + cin_cv.notify_all(); + continue; + } + + if (!line.empty()) { + add_history(line.c_str()); } // Trim whitespace line.erase(line.begin(), std::ranges::find_if(line, [](int character) { @@ -57,16 +261,23 @@ auto main() -> int { }) .base(), line.end()); - std::istringstream iss(line); std::string cmd; std::string arg; iss >> cmd >> arg; + auto match_service = [&arg](const auto& service) { + const auto props = service->properties(); + const auto name = props.getName(); + const auto path = service->objPath(); + const auto last = path.substr(path.find_last_of('/') + 1); + + return last == arg || name == arg; + }; - if (cmd == "exit" || cmd == "quit") { + if (cmd == command_map.at(Command::Quit)) { break; } - if (cmd == "technologies") { + if (cmd == command_map.at(Command::Technologies)) { const auto techs = manager->technologies(); if (techs.empty()) { std::cout << "No technologies available.\n"; @@ -75,17 +286,20 @@ auto main() -> int { const auto props = tech->properties(); std::cout << "Technology: " << props.getName() << " " << tech->objPath() << "\n"; - props.print(); + std::cout << props; } } - } - if (cmd == "agent") { + } else if (cmd == command_map.at(Command::Agent)) { auto on_register = [arg](const auto success) { if (success) { - std::cout << "Agent " - << ((arg == "on") ? "registered" : "unregistered") - << "\n"; + std::lock_guard lock(message_mutex); + message + << "Agent " + << ((arg == on_off_container.at(0)) ? "registered" + : "unregistered") + << "\n"; } + has_message = true; }; if (arg == "on") { manager->registerAgent(manager->internalAgentPath(), @@ -94,9 +308,10 @@ auto main() -> int { manager->unregisterAgent(manager->internalAgentPath(), on_register); } else { - std::cout << "Usage: agent on/off\n"; + std::cout << "Usage: agent " << on_off_container.at(0) << "/" + << on_off_container.at(1) << "\n"; } - } else if (cmd == "services") { + } else if (cmd == command_map.at(Command::Services)) { const auto services = manager->services(); if (services.empty()) { std::cout << "No services available.\n"; @@ -115,101 +330,105 @@ auto main() -> int { } else if (props.getState() == State::Ready) { std::cout << "R"; } + const auto path = service->objPath(); std::cout << " " << props.getName() << " " - << service->objPath() << "\n"; + << path.substr(path.find_last_of('/') + 1) + << "\n"; } } else { - auto iterator = std::ranges::find_if( - services, [&arg](const auto& service) { - return service->objPath() == arg || - service->properties().getName() == arg; - }); + auto iterator = + std::ranges::find_if(services, match_service); if (iterator != services.end()) { const auto props = (*iterator)->properties(); std::cout << "Service: " << props.getName() << " " << (*iterator)->objPath() << "\n"; - props.print(); + std::cout << props; } else { std::cout << "Service not found: " << arg << "\n"; } } } - } else if (cmd == "scan") { - if (arg.empty() || - (arg != "wifi" && arg != "ethernet" && arg != "bluetooth" && - arg != "cellular" && arg != "vpn")) { - std::cout << "Usage: scan \n"; - std::cout << "Available technologies: wifi, ethernet, " - "bluetooth, cellular, vpn\n"; - continue; + } else if (cmd == command_map.at(Command::Scan)) { + { + std::lock_guard lock(hash_mutex); + if (arg.empty() || + std::find(technologies_container.begin(), + technologies_container.end(), + arg) == technologies_container.end()) { + std::cout << "Usage: scan \n"; + std::cout << "Available technologies: "; + printContainer(technologies_container); + continue; + } } const auto techs = manager->technologies(); for (const auto& tech : techs) { const auto props = tech->properties(); const auto name = props.getName(); - if ((props.getType() == TechProperties::Type::Wifi && - arg == "wifi") || - (props.getType() == TechProperties::Type::Ethernet && - arg == "ethernet") || - (props.getType() == TechProperties::Type::Bluetooth && - arg == "bluetooth") || - (props.getType() == TechProperties::Type::Cellular && - arg == "cellular") || - (props.getType() == TechProperties::Type::Vpn && - arg == "vpn")) { + if (tech_map.at(props.getType()) == arg) { std::cout << "Scanning " << name << "...\n"; tech->scan([name](bool success) { - if (success) { - std::cout << "Technology " << name - << " scanned successfully.\n"; - } else { - std::cout << "Failed to scan technology " << name - << ".\n"; + { + std::lock_guard lock(message_mutex); + if (success) { + message << "Technology " << name + << " scanned successfully.\n"; + } else { + message << "Failed to scan technology " << name + << ".\n"; + } } + has_message = true; }); break; } } - } else if (cmd == "enable" || cmd == "disable") { - if (arg.empty() || - (arg != "wifi" && arg != "ethernet" && arg != "bluetooth" && - arg != "cellular" && arg != "vpn")) { - std::cout << "Usage: enable/disable \n"; - std::cout << "Available technologies: wifi, ethernet, " - "bluetooth, cellular, vpn\n"; - continue; + } else if (cmd == command_map.at(Command::Enable) || + cmd == command_map.at(Command::Disable)) { + { + std::lock_guard lock(hash_mutex); + if (arg.empty() || + std::find(technologies_container.begin(), + technologies_container.end(), + arg) == technologies_container.end()) { + std::cout << "Usage: " << enable_disable_container[0] << "/" + << enable_disable_container[1] + << " \n"; + std::cout << "Available technologies:"; + printContainer(technologies_container); + continue; + } } - const bool enable = (cmd == "enable"); + const bool enable = (cmd == enable_disable_container.at(0)); std::cout << (enable ? "Enabling" : "Disabling") << " technology: " << arg << "\n"; const auto techs = manager->technologies(); for (const auto& tech : techs) { const auto props = tech->properties(); const auto name = props.getName(); - if ((props.getType() == TechProperties::Type::Wifi && - arg == "wifi") || - (props.getType() == TechProperties::Type::Ethernet && - arg == "ethernet") || - (props.getType() == TechProperties::Type::Bluetooth && - arg == "bluetooth") || - (props.getType() == TechProperties::Type::Cellular && - arg == "cellular") || - (props.getType() == TechProperties::Type::Vpn && - arg == "vpn")) { - if ((!props.isPowered() && cmd == "enable") || - (props.isPowered() && cmd == "disable")) { + if (tech_map.at(props.getType()) == arg) { + if ((!props.isPowered() && + cmd == enable_disable_container.at(0)) || + (props.isPowered() && + cmd == enable_disable_container.at(1))) { std::cout << (enable ? "Enabling " : "Disabling ") << name << "...\n"; tech->setPowered(enable, [name, enable](bool success) { - if (success) { - std::cout << "Technology " << name - << (enable ? " enabled" : " disabled") - << " successfully.\n"; - } else { - std::cout << "Failed to " - << (enable ? " enable" : " disable") - << " technology " << name << "\n"; + { + std::lock_guard lock(message_mutex); + if (success) { + message + << "Technology " << name + << (enable ? " enabled" : " disabled") + << " successfully.\n"; + } else { + message << "Failed to " + << (enable ? " enable" : " disable") + << " technology " << name << "\n"; + } } + + has_message = true; }); } else { @@ -218,18 +437,15 @@ auto main() -> int { } } } - } else if (cmd == "connect" || cmd == "disconnect") { + } else if (cmd == command_map.at(Command::Connect) || + cmd == command_map.at(Command::Disconnect)) { if (arg.empty()) { std::cout << "Usage: connect/disconnect \n"; continue; } - const bool connect = (cmd == "connect"); + const bool connect = (cmd == command_map.at(Command::Connect)); const auto services = manager->services(); - auto iterator = - std::ranges::find_if(services, [&arg](const auto& service) { - return service->objPath() == arg || - service->properties().getName() == arg; - }); + auto iterator = std::ranges::find_if(services, match_service); if (iterator != services.end()) { const auto name = (*iterator)->properties().getName(); @@ -240,28 +456,23 @@ auto main() -> int { !connect) { std::cout << (connect ? "Connecting" : "Disconnecting") << " to service: " << name << "\n"; - const auto on_connect = [name, connect, &connecting, - &cin_mutex, - &cin_cv](bool success) { + const auto on_connect = [name, connect](bool success) { + std::lock_guard lock_message(message_mutex); if (success) { - std::cout + message << "Service " << name << (connect ? " connected" : " disconnected") << " successfully.\n"; } else { - std::cout << "Failed to " - << (connect ? " connect" : " disconnect") - << " to service " << name << "\n"; - } - { - const std::unique_lock lock(cin_mutex); - connecting = false; + message << "Failed to " + << (connect ? " connect" : " disconnect") + << " to service " << name << "\n"; } - cin_cv.notify_one(); + has_message = true; }; if (connect) { (*iterator)->connect(on_connect); - connecting = true; + } else { (*iterator)->disconnect(on_connect); } @@ -273,39 +484,38 @@ auto main() -> int { } else { std::cout << "Service " << arg << " not available.\n"; } - } else if (cmd == "remove") { + } else if (cmd == command_map.at(Command::Remove)) { if (arg.empty()) { std::cout << "Usage: remove \n"; continue; } const auto services = manager->services(); - auto iterator = - std::ranges::find_if(services, [&arg](const auto& service) { - return service->objPath() == arg || - service->properties().getName() == arg; - }); + auto iterator = std::ranges::find_if(services, match_service); if (iterator != services.end()) { const auto name = (*iterator)->properties().getName(); std::cout << "Removing service: " << name << "\n"; (*iterator)->remove([name](bool success) { - if (success) { - std::cout << "Service " << name - << " removed successfully.\n"; - } else { - std::cout << "Failed to remove service " << name - << "\n"; + { + std::lock_guard lock(message_mutex); + if (success) { + message << "Service " << name + << " removed successfully.\n"; + } else { + message << "Failed to remove service " << name + << "\n"; + } } + has_message = true; }); } else { std::cout << "Service " << arg << " not available.\n"; } } else { if (!cmd.empty()) { - std::cout - << "Unknown command: " << cmd - << ". Available commands: technologies, services, " - "scan, enable, disable, connect, disconnect, remove.\n"; + std::cout << "Unknown command: " << cmd + << ".\n Available commands: "; + printContainer(commands_container); } } } diff --git a/include/amarula/dbus/connman/gclock.hpp b/include/amarula/dbus/connman/gclock.hpp index 18d005d..1c8787f 100644 --- a/include/amarula/dbus/connman/gclock.hpp +++ b/include/amarula/dbus/connman/gclock.hpp @@ -25,7 +25,8 @@ struct ClockProperties { return time_server_synced_; } - void print() const; + friend auto operator<<(std::ostream& ostr, + const ClockProperties& object) -> std::ostream&; private: uint64_t time_{0}; diff --git a/include/amarula/dbus/connman/gservice.hpp b/include/amarula/dbus/connman/gservice.hpp index 56b696e..dd4d9e9 100644 --- a/include/amarula/dbus/connman/gservice.hpp +++ b/include/amarula/dbus/connman/gservice.hpp @@ -37,7 +37,8 @@ class IPv4 : public GVariantParser { Auto, }; - void print() const; + friend auto operator<<(std::ostream& ostr, + const IPv4& object) -> std::ostream&; [[nodiscard]] auto getMethod() const { return method_; } [[nodiscard]] auto getAddress() const { return address_; } @@ -65,7 +66,8 @@ struct IPv6 : public GVariantParser { Auto, }; enum class Privacy : uint8_t { Disabled = 0, Enabled, Preferred }; - void print() const; + friend auto operator<<(std::ostream& ostr, + const IPv6& object) -> std::ostream&; [[nodiscard]] auto getMethod() const { return method_; } [[nodiscard]] auto getAddress() const { return address_; } [[nodiscard]] auto getGateway() const { return gateway_; } @@ -87,7 +89,8 @@ struct IPv6 : public GVariantParser { struct Ethernet : public GVariantParser { public: enum class Method : uint8_t { Manual = 0, Auto }; - void print() const; + friend auto operator<<(std::ostream& ostr, + const Ethernet& object) -> std::ostream&; [[nodiscard]] auto getMethod() const { return method_; } [[nodiscard]] auto getInterface() const { return interface_; } [[nodiscard]] auto getAddress() const { return address_; } @@ -106,7 +109,8 @@ struct Ethernet : public GVariantParser { struct Provider : public GVariantParser { public: - void print() const; + friend auto operator<<(std::ostream& ostr, + const Provider& object) -> std::ostream&; [[nodiscard]] auto getHost() const { return host_; } [[nodiscard]] auto getDomain() const { return domain_; } [[nodiscard]] auto getName() const { return name_; } @@ -126,7 +130,8 @@ struct Provider : public GVariantParser { struct Proxy : public GVariantParser { public: enum class Method : uint8_t { Direct = 0, Auto, Manual }; - void print() const; + friend auto operator<<(std::ostream& ostr, + const Proxy& object) -> std::ostream&; [[nodiscard]] auto getMethod() const { return method_; } [[nodiscard]] auto getUrl() const { return url_; } [[nodiscard]] auto getServers() const { return servers_; } @@ -186,7 +191,8 @@ struct ServProperties { OnlineCheckFailed }; - void print() const; + friend auto operator<<(std::ostream& ostr, + const ServProperties& object) -> std::ostream&; [[nodiscard]] auto getState() const { return state_; } [[nodiscard]] auto getType() const { return type_; } [[nodiscard]] auto getSecurity() const { return security_; } diff --git a/include/amarula/dbus/connman/gtechnology.hpp b/include/amarula/dbus/connman/gtechnology.hpp index c11e24f..53010a2 100644 --- a/include/amarula/dbus/connman/gtechnology.hpp +++ b/include/amarula/dbus/connman/gtechnology.hpp @@ -29,7 +29,8 @@ struct TechProperties { [[nodiscard]] auto isConnected() const { return connected_; } [[nodiscard]] auto isTethering() const { return tethering_; } [[nodiscard]] auto getTetheringFreq() const { return tethering_freq_; } - void print() const; + friend auto operator<<(std::ostream& ostr, + const TechProperties& object) -> std::ostream&; private: bool powered_ = false; diff --git a/include/amarula/dbus/gproxy.hpp b/include/amarula/dbus/gproxy.hpp index 57ef01e..95940c5 100644 --- a/include/amarula/dbus/gproxy.hpp +++ b/include/amarula/dbus/gproxy.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/src/dbus/gconnman_agent.cpp b/src/dbus/gconnman_agent.cpp index e032070..7d36400 100644 --- a/src/dbus/gconnman_agent.cpp +++ b/src/dbus/gconnman_agent.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include diff --git a/src/dbus/gconnman_clock.cpp b/src/dbus/gconnman_clock.cpp index 2cc45a9..45ee737 100644 --- a/src/dbus/gconnman_clock.cpp +++ b/src/dbus/gconnman_clock.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -97,26 +96,25 @@ void Clock::setTimeServers(const std::vector& servers, g_variant_builder_clear(&builder); } -void ClockProperties::print() const { - LCM_LOG("@@@@@@@@@@ ClockProperties: @@@@@@@@@@@@@@@\n"); - LCM_LOG(TIME_STR << ": " << time_ << " ("); - const auto time_value = static_cast(time_); - LCM_LOG(std::put_time(std::localtime(&time_value), "%Y-%m-%d %H:%M:%S") - << ")\n"); - LCM_LOG(TIMEUPDATES_STR << ": " << TIME_UPDATE_MAP.toString(time_updates_) - << '\n'); - LCM_LOG(TIMEZONE_STR << ": " << timezone_ << '\n'); - LCM_LOG(TIMEZONEUPDATES_STR - << ": " << TIME_ZONE_UPDATE_MAP.toString(timezone_updates_) - << '\n'); - LCM_LOG(TIMESERVERSYNCED_STR << ": " << std::boolalpha - << time_server_synced_ << '\n'); - LCM_LOG(TIMESERVERS_STR << ": "); - for (const auto& server : time_servers_) { - LCM_LOG(server << ' '); +auto operator<<(std::ostream& ost, + const ClockProperties& obj) -> std::ostream& { + ost << TIME_STR << ": " << obj.time_ << " ("; + const auto time_value = static_cast(obj.time_); + ost << std::put_time(std::localtime(&time_value), "%Y-%m-%d %H:%M:%S") + << ")\n"; + ost << TIMEUPDATES_STR << ": " + << TIME_UPDATE_MAP.toString(obj.time_updates_) << '\n'; + ost << TIMEZONE_STR << ": " << obj.timezone_ << '\n'; + ost << TIMEZONEUPDATES_STR << ": " + << TIME_ZONE_UPDATE_MAP.toString(obj.timezone_updates_) << '\n'; + ost << TIMESERVERSYNCED_STR << ": " << std::boolalpha + << obj.time_server_synced_ << '\n'; + ost << TIMESERVERS_STR << ": "; + for (const auto& server : obj.time_servers_) { + ost << server << ' '; } - LCM_LOG('\n'); - LCM_LOG("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); + ost << '\n'; + return ost; } } // namespace Amarula::DBus::G::Connman diff --git a/src/dbus/gconnman_service.cpp b/src/dbus/gconnman_service.cpp index f5fbcd3..2da369b 100644 --- a/src/dbus/gconnman_service.cpp +++ b/src/dbus/gconnman_service.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -79,10 +78,11 @@ static constexpr EnumStringMap IPV6_METHOD_MAP{ {IPv6::Method::Fixed, "fixed"}, {IPv6::Method::Auto, "auto"}}}}; -static constexpr EnumStringMap IPV6_PRIVACY_MAP{ +static constexpr EnumStringMap IPV6_PRIVACY_MAP{ {{{IPv6::Privacy::Disabled, "disabled"}, {IPv6::Privacy::Enabled, "enabled"}, - {IPv6::Privacy::Preferred, "preferred"}}}}; + {IPv6::Privacy::Preferred, "preferred"}, + {IPv6::Privacy::Preferred, "prefered"}}}}; Service::Service(DBus* dbus, const gchar* obj_path) : DBusProxy(dbus, SERVICE, obj_path, SERVICE_INTERFACE) {} @@ -287,132 +287,136 @@ void ServProperties::update(const gchar* key, GVariant* value) { } } -void ServProperties::print() const { - LCM_LOG("@@@@@@@@@@ ServProperties: @@@@@@@@@@@@@@@\n"); - LCM_LOG("State: " << STATE_MAP.toString(state_) << '\n'); - if (error_ != Error::None) { - LCM_LOG("Error: " << ERROR_MAP.toString(error_) << '\n'); +auto operator<<(std::ostream& ost, const ServProperties& obj) -> std::ostream& { + ost << "State: " << STATE_MAP.toString(obj.state_) << '\n'; + if (obj.error_ != Error::None) { + ost << "Error: " << ERROR_MAP.toString(obj.error_) << '\n'; } - LCM_LOG("Name: " << name_ << '\n'); - LCM_LOG("Type: " << TYPE_MAP.toString(type_) << '\n'); - LCM_LOG("Strength: " << static_cast(strength_) << '\n'); - LCM_LOG("AutoConnect: " << std::boolalpha << autoconnect_ << '\n'); - LCM_LOG("mDNS: " << mdns_ << '\n'); - LCM_LOG("Favorite: " << favorite_ << '\n'); - LCM_LOG("Immutable: " << immutable_ << '\n'); - LCM_LOG("Roaming: " << roaming_ << '\n'); - - if (security_) { - LCM_LOG("Security: "); - for (const auto& sec : security_.value()) { - LCM_LOG(SECURITY_MAP.toString(sec) << ' '); + ost << "Name: " << obj.name_ << '\n'; + ost << "Type: " << TYPE_MAP.toString(obj.type_) << '\n'; + ost << "Strength: " << static_cast(obj.strength_) << '\n'; + ost << "AutoConnect: " << std::boolalpha << obj.autoconnect_ << '\n'; + ost << "mDNS: " << obj.mdns_ << '\n'; + ost << "Favorite: " << obj.favorite_ << '\n'; + ost << "Immutable: " << obj.immutable_ << '\n'; + ost << "Roaming: " << obj.roaming_ << '\n'; + + if (obj.security_) { + ost << "Security: "; + for (const auto& sec : obj.security_.value()) { + ost << SECURITY_MAP.toString(sec) << ' '; } - LCM_LOG('\n'); + ost << '\n'; } - if (name_servers_) { - LCM_LOG("Nameservers: "); - for (const auto& nserver : name_servers_.value()) { - LCM_LOG(nserver << ' '); + if (obj.name_servers_) { + ost << "Nameservers: "; + for (const auto& nserver : obj.name_servers_.value()) { + ost << nserver << ' '; } - LCM_LOG('\n'); + ost << '\n'; } - if (name_servers_conf_) { - LCM_LOG("Nameservers.Configuration: "); - for (const auto& nserver : name_servers_conf_.value()) { - LCM_LOG(nserver << ' '); + if (obj.name_servers_conf_) { + ost << "Nameservers.Configuration: "; + for (const auto& nserver : obj.name_servers_conf_.value()) { + ost << nserver << ' '; } - LCM_LOG('\n'); + ost << '\n'; } - if (domains_) { - LCM_LOG("Domains: "); - for (const auto& domain : domains_.value()) { - LCM_LOG(domain << ' '); + if (obj.domains_) { + ost << "Domains: "; + for (const auto& domain : obj.domains_.value()) { + ost << domain << ' '; } - LCM_LOG('\n'); + ost << '\n'; } - if (time_servers_) { - LCM_LOG("TimeServers: "); - for (const auto& tserver : time_servers_.value()) { - LCM_LOG(tserver << ' '); + if (obj.time_servers_) { + ost << "TimeServers: "; + for (const auto& tserver : obj.time_servers_.value()) { + ost << tserver << ' '; } - LCM_LOG('\n'); + ost << '\n'; } - if (ipv4_) { - ipv4_.value().print(); + if (obj.ipv4_) { + ost << obj.ipv4_.value(); } - if (ipv6_) { - ipv6_.value().print(); + if (obj.ipv6_) { + ost << obj.ipv6_.value(); } - if (ethernet_) { - ethernet_.value().print(); + if (obj.ethernet_) { + ost << obj.ethernet_.value(); } - if (provider_) { - provider_.value().print(); + if (obj.provider_) { + ost << obj.provider_.value(); } - if (proxy_) { - proxy_.value().print(); + if (obj.proxy_) { + ost << obj.proxy_.value(); } - LCM_LOG("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); + return ost; } -void Ethernet::print() const { - LCM_LOG("Ethernet:\n"); - LCM_LOG(" Method: " << ETHERNET_METHOD_MAP.toString(method_) << '\n'); - LCM_LOG(" Interface: " << interface_ << '\n'); - LCM_LOG(" Address: " << address_ << '\n'); - LCM_LOG(" MTU: " << mtu_ << '\n'); +auto operator<<(std::ostream& ost, const Ethernet& obj) -> std::ostream& { + ost << "Ethernet:\n"; + ost << " Method: " << ETHERNET_METHOD_MAP.toString(obj.method_) << '\n'; + ost << " Interface: " << obj.interface_ << '\n'; + ost << " Address: " << obj.address_ << '\n'; + ost << " MTU: " << obj.mtu_ << '\n'; + return ost; } -void IPv4::print() const { - LCM_LOG("IPv4:\n"); - LCM_LOG(" Method: " << IPV4_METHOD_MAP.toString(method_) << '\n'); - LCM_LOG(" Address: " << address_ << '\n'); - LCM_LOG(" Netmask: " << netmask_ << '\n'); - LCM_LOG(" Gateway: " << gateway_ << '\n'); +auto operator<<(std::ostream& ost, const IPv4& obj) -> std::ostream& { + ost << "IPv4:\n"; + ost << " Method: " << IPV4_METHOD_MAP.toString(obj.method_) << '\n'; + ost << " Address: " << obj.address_ << '\n'; + ost << " Netmask: " << obj.netmask_ << '\n'; + ost << " Gateway: " << obj.gateway_ << '\n'; + return ost; } -void Provider::print() const { - LCM_LOG("Provider:\n"); - LCM_LOG(" Host: " << host_ << '\n'); - LCM_LOG(" Domain: " << domain_ << '\n'); - LCM_LOG(" Name: " << name_ << '\n'); - LCM_LOG(" Type: " << type_ << '\n'); +auto operator<<(std::ostream& ost, const Provider& obj) -> std::ostream& { + ost << "Provider:\n"; + ost << " Host: " << obj.host_ << '\n'; + ost << " Domain: " << obj.domain_ << '\n'; + ost << " Name: " << obj.name_ << '\n'; + ost << " Type: " << obj.type_ << '\n'; + return ost; } -void IPv6::print() const { - LCM_LOG("IPv6:\n"); - LCM_LOG(" Method: " << IPV6_METHOD_MAP.toString(method_) << '\n'); - LCM_LOG(" Address: " << address_ << '\n'); - LCM_LOG(" Gateway: " << gateway_ << '\n'); - LCM_LOG(" Privacy: " << static_cast(privacy_) << '\n'); - LCM_LOG(" Prefix Length: " << static_cast(prefix_length_) << '\n'); +auto operator<<(std::ostream& ost, const IPv6& obj) -> std::ostream& { + ost << "IPv6:\n"; + ost << " Method: " << IPV6_METHOD_MAP.toString(obj.method_) << '\n'; + ost << " Address: " << obj.address_ << '\n'; + ost << " Gateway: " << obj.gateway_ << '\n'; + ost << " Privacy: " << static_cast(obj.privacy_) << '\n'; + ost << " Prefix Length: " << static_cast(obj.prefix_length_) << '\n'; + return ost; } -void Proxy::print() const { - LCM_LOG("Proxy:\n"); - LCM_LOG(" Method: " << PROXY_METHOD_MAP.toString(method_) << '\n'); - LCM_LOG(" URL: " << url_ << '\n'); - LCM_LOG(" Servers: "); - for (const auto& server : servers_) { - LCM_LOG(server << ' '); +auto operator<<(std::ostream& ost, const Proxy& obj) -> std::ostream& { + ost << "Proxy:\n"; + ost << " Method: " << PROXY_METHOD_MAP.toString(obj.method_) << '\n'; + ost << " URL: " << obj.url_ << '\n'; + ost << " Servers: "; + for (const auto& server : obj.servers_) { + ost << server << ' '; } - LCM_LOG('\n'); + ost << '\n'; - LCM_LOG(" Excludes: "); - for (const auto& exclude : excludes_) { - LCM_LOG(exclude << ' '); + ost << " Excludes: "; + for (const auto& exclude : obj.excludes_) { + ost << exclude << ' '; } - LCM_LOG('\n'); + ost << '\n'; + return ost; } } // namespace Amarula::DBus::G::Connman diff --git a/src/dbus/gconnman_technology.cpp b/src/dbus/gconnman_technology.cpp index d94a80b..15359ef 100644 --- a/src/dbus/gconnman_technology.cpp +++ b/src/dbus/gconnman_technology.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include "gconnman_private.hpp" @@ -60,15 +59,14 @@ void TechProperties::update(const gchar* key, GVariant* value) { } } -void TechProperties::print() const { - LCM_LOG("@@@@@@@@@@ TechProperties: @@@@@@@@@@@@@@@\n"); - LCM_LOG(NAME_STR << ": " << name_ << '\n'); - LCM_LOG(TYPE_STR << ": " << TYPE_MAP.toString(type_) << '\n'); - LCM_LOG(POWERED_STR << ": " << std::boolalpha << powered_ << '\n'); - LCM_LOG(CONNECTED_STR << ": " << std::boolalpha << connected_ << '\n'); - LCM_LOG(TETHERING_STR << ": " << std::boolalpha << tethering_ << '\n'); - LCM_LOG(TETHERINGFREQ_STR << ": " << tethering_freq_ << " \n"); - LCM_LOG("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); +auto operator<<(std::ostream& ost, const TechProperties& obj) -> std::ostream& { + ost << NAME_STR << ": " << obj.name_ << '\n'; + ost << TYPE_STR << ": " << TYPE_MAP.toString(obj.type_) << '\n'; + ost << POWERED_STR << ": " << std::boolalpha << obj.powered_ << '\n'; + ost << CONNECTED_STR << ": " << std::boolalpha << obj.connected_ << '\n'; + ost << TETHERING_STR << ": " << std::boolalpha << obj.tethering_ << '\n'; + ost << TETHERINGFREQ_STR << ": " << obj.tethering_freq_ << " \n"; + return ost; } } // namespace Amarula::DBus::G::Connman diff --git a/tests/gconnman_clock_test.cpp b/tests/gconnman_clock_test.cpp index c34ac0e..c76a6ef 100644 --- a/tests/gconnman_clock_test.cpp +++ b/tests/gconnman_clock_test.cpp @@ -27,7 +27,7 @@ TEST(Connman, ClockSetTimeUpdates) { EXPECT_NE(callback_tid, main_tid); EXPECT_NE(callback_tid, loop_tid); std::cout << "onPropertyChanged:\n"; - props.print(); + std::cout << props; }); connman.clock()->setTimeUpdates( TimeUpdate::Auto, [main_tid = thread_bundle.main_tid, @@ -45,7 +45,7 @@ TEST(Connman, ClockSetTime) { const guint time = TEST_TIME; connman.clock()->onPropertyChanged([](auto& props) { std::cout << "onPropertyChanged:\n"; - props.print(); + std::cout << props; }); connman.clock()->setTimeUpdates( TimeUpdate::Manual, [&connman](auto success) { @@ -54,7 +54,7 @@ TEST(Connman, ClockSetTime) { EXPECT_TRUE(success); connman.clock()->getProperties([](auto& props) { std::cout << "getProperties:\n"; - props.print(); + std::cout << props; }); }); }); @@ -65,7 +65,7 @@ TEST(Connman, ClockSetTimeServers1) { const Connman connman; connman.clock()->onPropertyChanged([](auto& props) { std::cout << "onPropertyChanged:\n"; - props.print(); + std::cout << props; }); const std::vector servers = {"time1.google.com", "time2.google.com"}; @@ -78,7 +78,7 @@ TEST(Connman, ClockSetTimeServers2) { const Connman connman; connman.clock()->onPropertyChanged([](auto& props) { std::cout << "onPropertyChanged:\n"; - props.print(); + std::cout << props; }); const std::vector servers = {"time1.example.com", "time2.example.com"}; @@ -86,7 +86,7 @@ TEST(Connman, ClockSetTimeServers2) { EXPECT_TRUE(success); connman.clock()->getProperties([](auto& props) { std::cout << "getProperties:\n"; - props.print(); + std::cout << props; }); }); } @@ -96,7 +96,7 @@ TEST(Connman, ClockSetTimeZoneUpdates) { const Connman connman; connman.clock()->onPropertyChanged([](auto& props) { std::cout << "onPropertyChanged:\n"; - props.print(); + std::cout << props; }); connman.clock()->setTimeZoneUpdates( TimeZoneUpdate::Auto, @@ -108,7 +108,7 @@ TEST(Connman, ClockSetTimeZone) { const Connman connman; connman.clock()->onPropertyChanged([](auto& props) { std::cout << "onPropertyChanged:\n"; - props.print(); + std::cout << props; }); connman.clock()->setTimeZoneUpdates( TimeZoneUpdate::Manual, [&connman](auto success) { @@ -118,7 +118,7 @@ TEST(Connman, ClockSetTimeZone) { EXPECT_TRUE(success); connman.clock()->getProperties([](auto& props) { std::cout << "getProperties:\n"; - props.print(); + std::cout << props; }); }); }); @@ -145,6 +145,6 @@ TEST(Connman, ClockGetProperties) { const auto callback_tid = std::this_thread::get_id(); EXPECT_NE(callback_tid, main_tid); EXPECT_NE(callback_tid, loop_tid); - props.print(); + std::cout << props; }); } diff --git a/tests/gconnman_serv_test.cpp b/tests/gconnman_serv_test.cpp index 580e1eb..0f9e5e4 100644 --- a/tests/gconnman_serv_test.cpp +++ b/tests/gconnman_serv_test.cpp @@ -40,7 +40,7 @@ TEST(Connman, getServs) { << "Technology " << prop.getName() << " was not powered ON"; std::cout << "onPropertyChanged:\n"; - prop.print(); + std::cout << prop; }); const auto prop = tech->properties(); const auto name = prop.getName(); @@ -67,7 +67,7 @@ TEST(Connman, getServs) { ASSERT_FALSE(services.empty()); for (const auto& serv : services) { const auto props = serv->properties(); - props.print(); + std::cout << props; } }); } @@ -92,10 +92,10 @@ TEST(Connman, setNameServers) { for (const auto& serv : services) { const auto props = serv->properties(); const auto name = props.getName(); - props.print(); + std::cout << props; serv->onPropertyChanged([](const auto& properties) { std::cout << "onPropertyChange:\n"; - properties.print(); + std::cout << properties; }); serv->setNameServers( {"8.8.8.8", "4.4.4.4"}, @@ -143,7 +143,7 @@ TEST(Connman, ForgetAndDisconnectService) { EXPECT_NE(callback_tid, loop_tid); EXPECT_TRUE(success); std::cout << "Service removed: " << name << '\n'; - serv->properties().print(); + std::cout << serv->properties(); }); } else if (state == State::Ready || state == State::Online) { std::cout << "Disconnecting service: " << name << '\n'; @@ -154,7 +154,7 @@ TEST(Connman, ForgetAndDisconnectService) { EXPECT_TRUE(success); std::cout << "Service disconnected: " << serv->objPath() << '\n'; - serv->properties().print(); + std::cout << serv->properties(); }); } } @@ -207,7 +207,7 @@ TEST(Connman, ConnectWifi) { if (state == State::Idle) { std::cout << "Connecting to service: " << name << '\n'; - props.print(); + std::cout << props; serv->onPropertyChanged( [main_tid, loop_tid](const auto& properties) { const auto callback_tid = @@ -215,7 +215,7 @@ TEST(Connman, ConnectWifi) { EXPECT_NE(callback_tid, main_tid); EXPECT_NE(callback_tid, loop_tid); std::cout << "onPropertyChange:\n"; - properties.print(); + std::cout << properties; }); manager->registerAgent( manager->internalAgentPath(), @@ -236,7 +236,7 @@ TEST(Connman, ConnectWifi) { std::cout << "Service connected successfully: " << success << '\n'; - serv->properties().print(); + std::cout << serv->properties(); manager->unregisterAgent( manager->internalAgentPath()); }); diff --git a/tests/gconnman_tech_test.cpp b/tests/gconnman_tech_test.cpp index 8c9ba7a..419e486 100644 --- a/tests/gconnman_tech_test.cpp +++ b/tests/gconnman_tech_test.cpp @@ -30,7 +30,7 @@ TEST(Connman, getTechs) { EXPECT_TRUE(props.isPowered()) << "Technology is connected but not powered"; } - props.print(); + std::cout << props; } }); } @@ -63,7 +63,7 @@ TEST(Connman, PowerOnAllTechnologies) { EXPECT_NE(callback_tid, main_tid); EXPECT_NE(callback_tid, loop_tid); std::cout << "onPropertyChanged:\n"; - prop.print(); + std::cout << prop; }); const auto prop = tech->properties(); const auto name = prop.getName(); @@ -141,7 +141,7 @@ TEST(Connman, PowerOffAllTechnologies) { << "Technology " << prop.getName() << " was not powered OFF"; std::cout << "onPropertyChanged:\n"; - prop.print(); + std::cout << prop; }); const auto prop = tech->properties(); const auto name = prop.getName(); @@ -160,4 +160,4 @@ TEST(Connman, PowerOffAllTechnologies) { }); } ASSERT_TRUE(called) << "setPowered callback was never called"; -} \ No newline at end of file +}