From 870279fc66b216062691cdfbe6490344da16a7de Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Tue, 10 Sep 2024 09:03:40 -0400 Subject: [PATCH 001/271] DELIA-66215 : Improve the event subscription Reason for change: The Events from Network Plugin is not posted on time due to the delay in internal subscription. Also, updated the component with more logs to identify any new issue Test Procedure: Verify reported devices Risks:Medium Signed-off-by: Karunakaran A --- LegacyPlugin_NetworkAPIs.cpp | 38 ++++++++++++++++++++++------ LegacyPlugin_NetworkAPIs.h | 5 ++-- LegacyPlugin_WiFiManagerAPIs.cpp | 43 ++++++++++++++++++++++++-------- LegacyPlugin_WiFiManagerAPIs.h | 5 ++-- NetworkManager.h | 14 +++++------ NetworkManagerImplementation.cpp | 8 +++++- 6 files changed, 84 insertions(+), 29 deletions(-) diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index 3227370f0..3b86f4758 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -26,7 +26,7 @@ using namespace WPEFramework::Plugin; #define API_VERSION_NUMBER_MINOR 0 #define API_VERSION_NUMBER_PATCH 0 #define NETWORK_MANAGER_CALLSIGN "org.rdk.NetworkManager.1" -#define SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS 5000 +#define SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS 500 #define LOGINFOMETHOD() { string json; parameters.ToString(json); NMLOG_TRACE("Legacy params=%s", json.c_str() ); } #define LOGTRACEMETHODFIN() { string json; response.ToString(json); NMLOG_TRACE("Legacy response=%s", json.c_str() ); } @@ -74,7 +74,7 @@ namespace WPEFramework _gNWInstance = this; m_defaultInterface = "wlan0"; m_timer.connect(std::bind(&Network::subscribeToEvents, this)); - RegisterLegacyMethods(); + registerLegacyMethods(); } Network::~Network() @@ -153,13 +153,13 @@ namespace WPEFramework Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); m_networkmanager = make_shared >(_T(NETWORK_MANAGER_CALLSIGN), _T(NETWORK_MANAGER_CALLSIGN), false, query); - m_timer.start(SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS); + doTheSubscriptions(); return string(); } void Network::Deinitialize(PluginHost::IShell* /* service */) { - UnregisterLegacyMethods(); + unregisterLegacyMethods(); m_service->Release(); m_service = nullptr; _gNWInstance = nullptr; @@ -179,7 +179,7 @@ namespace WPEFramework * * Method name * * Function that implements that method */ - void Network::RegisterLegacyMethods() + void Network::registerLegacyMethods(void) { CreateHandler({2}); @@ -209,7 +209,7 @@ namespace WPEFramework /** * Unregister all our JSON-RPC methods */ - void Network::UnregisterLegacyMethods() + void Network::unregisterLegacyMethods(void) { Unregister("getInterfaces"); Unregister("isInterfaceEnabled"); @@ -777,6 +777,21 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { } /** Private */ + void Network::doTheSubscriptions(void) + { + uint32_t result = Core::ERROR_ASYNC_FAILED; + Core::Event event(false, true); + Core::IWorkerPool::Instance().Submit(Core::ProxyType(Core::ProxyType::Create([&]() { + NMLOG_INFO ("Start Subscription %s", __FUNCTION__); + subscribeToEvents(); + m_timer.start(SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS); + event.SetEvent(); + }))); + event.Lock(); + + return; + } + void Network::subscribeToEvents(void) { uint32_t errCode = Core::ERROR_GENERAL; @@ -824,9 +839,14 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { } } } + else + NMLOG_ERROR("m_networkmanager is null"); if (m_subsIfaceStateChange && m_subsActIfaceChange && m_subsIPAddrChange && m_subsInternetChange) + { m_timer.stop(); + NMLOG_INFO("subscriber timer stoped"); + } } string Network::getInterfaceMapping(const string & interface) @@ -860,10 +880,12 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { if((state == "INTERFACE_ADDED") || (state == "INTERFACE_REMOVED")) { + NMLOG_INFO("Posting onInterfaceStatusChanged"); Notify("onInterfaceStatusChanged", legacyParams); } else if((state == "INTERFACE_LINK_UP") || (state == "INTERFACE_LINK_DOWN")) { + NMLOG_INFO("Posting onConnectionStatusChanged"); Notify("onConnectionStatusChanged", legacyParams); } @@ -879,6 +901,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { legacyParams["newInterfaceName"] = getInterfaceMapping(parameters["newInterfaceName"].String()); m_defaultInterface = parameters["newInterfaceName"].String(); + NMLOG_INFO("Posting onDefaultInterfaceChanged"); Notify("onDefaultInterfaceChanged", legacyParams); return; } @@ -901,7 +924,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { } legacyParams["status"] = parameters["status"]; - + NMLOG_INFO("Posting onIPAddressStatusChanged"); Notify("onIPAddressStatusChanged", legacyParams); if ("ACQUIRED" == parameters["status"].String()) @@ -912,6 +935,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { void Network::ReportonInternetStatusChange(const JsonObject& parameters) { + NMLOG_INFO("Posting onInternetStatusChange"); Notify("onInternetStatusChange", parameters); return; } diff --git a/LegacyPlugin_NetworkAPIs.h b/LegacyPlugin_NetworkAPIs.h index d662881da..dfadc062d 100644 --- a/LegacyPlugin_NetworkAPIs.h +++ b/LegacyPlugin_NetworkAPIs.h @@ -28,9 +28,10 @@ namespace WPEFramework { Network(const Network&) = delete; Network& operator=(const Network&) = delete; - void RegisterLegacyMethods(); - void UnregisterLegacyMethods(); + void registerLegacyMethods(void); + void unregisterLegacyMethods(void); void subscribeToEvents(void); + void doTheSubscriptions(void); static std::string getInterfaceMapping(const std::string &interface); void activatePrimaryPlugin(); diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index fb878db4f..170c7c8b3 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -26,7 +26,7 @@ using namespace WPEFramework::Plugin; #define API_VERSION_NUMBER_MINOR 0 #define API_VERSION_NUMBER_PATCH 0 #define NETWORK_MANAGER_CALLSIGN "org.rdk.NetworkManager.1" -#define SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS 5000 +#define SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS 500 #define LOGINFOMETHOD() { string json; parameters.ToString(json); NMLOG_TRACE("Legacy params=%s", json.c_str() ); } #define LOGTRACEMETHODFIN() { string json; response.ToString(json); NMLOG_TRACE("Legacy response=%s", json.c_str() ); } @@ -73,7 +73,7 @@ namespace WPEFramework { _gWiFiInstance = this; m_timer.connect(std::bind(&WiFiManager::subscribeToEvents, this)); - RegisterLegacyMethods(); + registerLegacyMethods(); } WiFiManager::~WiFiManager() @@ -150,13 +150,13 @@ namespace WPEFramework Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); m_networkmanager = make_shared >(_T(NETWORK_MANAGER_CALLSIGN), _T(NETWORK_MANAGER_CALLSIGN), false, query); - m_timer.start(SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS); + doTheSubscriptions(); return string(); } void WiFiManager::Deinitialize(PluginHost::IShell* /* service */) { - UnregisterLegacyMethods(); + unregisterLegacyMethods(); m_service->Release(); m_service = nullptr; _gWiFiInstance = nullptr; @@ -176,7 +176,7 @@ namespace WPEFramework * * Method name * * Function that implements that method */ - void WiFiManager::RegisterLegacyMethods() + void WiFiManager::registerLegacyMethods(void) { CreateHandler({2}); Register("cancelWPSPairing", &WiFiManager::cancelWPSPairing, this); @@ -199,7 +199,7 @@ namespace WPEFramework /** * Unregister all our JSON-RPC methods */ - void WiFiManager::UnregisterLegacyMethods() + void WiFiManager::unregisterLegacyMethods(void) { Unregister("cancelWPSPairing"); Unregister("clearSSID"); @@ -492,6 +492,21 @@ namespace WPEFramework } /** Private */ + void WiFiManager::doTheSubscriptions(void) + { + uint32_t result = Core::ERROR_ASYNC_FAILED; + Core::Event event(false, true); + Core::IWorkerPool::Instance().Submit(Core::ProxyType(Core::ProxyType::Create([&]() { + NMLOG_INFO ("Start Subscription %s", __FUNCTION__); + subscribeToEvents(); + m_timer.start(SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS); + event.SetEvent(); + }))); + event.Lock(); + + return; + } + void WiFiManager::subscribeToEvents(void) { uint32_t errCode = Core::ERROR_GENERAL; @@ -503,7 +518,7 @@ namespace WPEFramework if (Core::ERROR_NONE == errCode) m_subsWiFiStateChange = true; else - NMLOG_ERROR ("Subscribe to onInterfaceStateChange failed, errCode: %u", errCode); + NMLOG_ERROR ("Subscribe to onWiFiStateChange failed, errCode: %u", errCode); } if (!m_subsAvailableSSIDs) @@ -512,7 +527,7 @@ namespace WPEFramework if (Core::ERROR_NONE == errCode) m_subsAvailableSSIDs = true; else - NMLOG_ERROR("Subscribe to onIPAddressChange failed, errCode: %u", errCode); + NMLOG_ERROR("Subscribe to onAvailableSSIDs failed, errCode: %u", errCode); } if (!m_subsWiFiStrengthChange) @@ -521,12 +536,17 @@ namespace WPEFramework if (Core::ERROR_NONE == errCode) m_subsWiFiStrengthChange = true; else - NMLOG_ERROR("Subscribe to onActiveInterfaceChange failed, errCode: %u", errCode); + NMLOG_ERROR("Subscribe to onWiFiSignalStrengthChange failed, errCode: %u", errCode); } } + else + NMLOG_ERROR("m_subsWiFiStateChange is null"); if (m_subsWiFiStateChange && m_subsAvailableSSIDs && m_subsWiFiStrengthChange) + { m_timer.stop(); + NMLOG_INFO("subscriber timer stoped"); + } } bool WiFiManager::ErrorCodeMapping(const uint32_t ipvalue, uint32_t &opvalue) @@ -584,11 +604,13 @@ namespace WPEFramework { legacyErrorResult["code"] = errorCode; NMLOG_INFO("onError with errorcode as, %u", errorCode); + NMLOG_INFO("Posting onError"); _gWiFiInstance->Notify("onError", legacyErrorResult); } else { NMLOG_INFO("onWiFiStateChange with state as: %u", state); + NMLOG_INFO("Posting onWIFIStateChanged"); _gWiFiInstance->Notify("onWIFIStateChanged", legacyResult); } } @@ -599,6 +621,7 @@ namespace WPEFramework { LOGINFOMETHOD(); + NMLOG_INFO("Posting onAvailableSSIDs"); if(_gWiFiInstance) _gWiFiInstance->Notify("onAvailableSSIDs", parameters); @@ -611,7 +634,7 @@ namespace WPEFramework JsonObject legacyParams; legacyParams["signalStrength"] = parameters["signalQuality"]; legacyParams["strength"] = parameters["signalLevel"]; - + NMLOG_INFO("Posting onWifiSignalThresholdChanged"); if (_gWiFiInstance) _gWiFiInstance->Notify("onWifiSignalThresholdChanged", legacyParams); diff --git a/LegacyPlugin_WiFiManagerAPIs.h b/LegacyPlugin_WiFiManagerAPIs.h index 242355824..e455916d4 100644 --- a/LegacyPlugin_WiFiManagerAPIs.h +++ b/LegacyPlugin_WiFiManagerAPIs.h @@ -96,9 +96,10 @@ namespace WPEFramework { virtual string Information() const override; private: - void RegisterLegacyMethods(); - void UnregisterLegacyMethods(); + void registerLegacyMethods(void); + void unregisterLegacyMethods(void); void subscribeToEvents(void); + void doTheSubscriptions(void); static std::string getInterfaceMapping(const std::string &interface); static bool ErrorCodeMapping(const uint32_t ipvalue , uint32_t &opvalue); void activatePrimaryPlugin(); diff --git a/NetworkManager.h b/NetworkManager.h index a32ed8643..ddac4b759 100644 --- a/NetworkManager.h +++ b/NetworkManager.h @@ -119,7 +119,7 @@ namespace WPEFramework public: void onInterfaceStateChange(const Exchange::INetworkManager::InterfaceState event, const string interface) override { - NMLOG_TRACE("%s", __FUNCTION__); + NMLOG_INFO("%s", __FUNCTION__); JsonObject params; params["interface"] = interface; params["state"] = InterfaceStateToString(event); @@ -128,7 +128,7 @@ namespace WPEFramework void onIPAddressChange(const string interface, const bool isAcquired, const bool isIPv6, const string ipAddress) override { - NMLOG_TRACE("%s", __FUNCTION__); + NMLOG_INFO("%s", __FUNCTION__); JsonObject params; params["status"] = string (isAcquired ? "ACQUIRED" : "LOST"); params["interface"] = interface; @@ -139,7 +139,7 @@ namespace WPEFramework void onActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface) override { - NMLOG_TRACE("%s", __FUNCTION__); + NMLOG_INFO("%s", __FUNCTION__); JsonObject params; params["oldInterfaceName"] = prevActiveInterface; params["newInterfaceName"] = currentActiveinterface; @@ -149,7 +149,7 @@ namespace WPEFramework void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus oldState, const Exchange::INetworkManager::InternetStatus newstate) override { - NMLOG_TRACE("%s", __FUNCTION__); + NMLOG_INFO("%s", __FUNCTION__); JsonObject params; params["state"] = static_cast (newstate);; @@ -169,7 +169,7 @@ namespace WPEFramework // WiFi Notifications that other processes can subscribe to void onAvailableSSIDs(const string jsonOfWiFiScanResults) override { - NMLOG_TRACE("%s", __FUNCTION__); + NMLOG_INFO("%s", __FUNCTION__); JsonArray scanResults; JsonObject result; scanResults.FromString(jsonOfWiFiScanResults); @@ -180,7 +180,7 @@ namespace WPEFramework void onWiFiStateChange(const Exchange::INetworkManager::WiFiState state) override { - NMLOG_TRACE("%s", __FUNCTION__); + NMLOG_INFO("%s", __FUNCTION__); JsonObject result; result["state"] = static_cast (state); _parent.Notify("onWiFiStateChange", result); @@ -188,7 +188,7 @@ namespace WPEFramework void onWiFiSignalStrengthChange(const string ssid, const string signalLevel, const Exchange::INetworkManager::WiFiSignalQuality signalQuality) override { - NMLOG_TRACE("%s", __FUNCTION__); + NMLOG_INFO("%s", __FUNCTION__); JsonObject result; result["ssid"] = ssid; result["signalQuality"] = WiFiSignalQualityToString(signalQuality); diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 5208b16a0..2ae61301c 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -494,6 +494,7 @@ namespace WPEFramework connectivityMonitor.startConnectivityMonitor(false); } + NMLOG_INFO("Posting onInterfaceStateChange %s", interface.c_str()); _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onInterfaceStateChange(state, interface); @@ -510,6 +511,7 @@ namespace WPEFramework connectivityMonitor.startConnectivityMonitor(true); } + NMLOG_INFO("Posting onIPAddressChange %s", ipAddress.c_str()); _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onIPAddressChange(interface, isAcquired, isIPv6, ipAddress); @@ -520,6 +522,7 @@ namespace WPEFramework void NetworkManagerImplementation::ReportActiveInterfaceChangedEvent(const string prevActiveInterface, const string currentActiveinterface) { LOG_ENTRY_FUNCTION(); + NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); @@ -530,6 +533,7 @@ namespace WPEFramework void NetworkManagerImplementation::ReportInternetStatusChangedEvent(const InternetStatus oldState, const InternetStatus newstate) { LOG_ENTRY_FUNCTION(); + NMLOG_INFO("Posting onInternetStatusChange"); _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onInternetStatusChange(oldState, newstate); @@ -541,7 +545,7 @@ namespace WPEFramework { LOG_ENTRY_FUNCTION(); _notificationLock.Lock(); - NMLOG_INFO("scan result is, %s", jsonOfWiFiScanResults.c_str()); + NMLOG_INFO("Posting onAvailableSSIDs result is, %s", jsonOfWiFiScanResults.c_str()); for (const auto callback : _notificationCallbacks) { callback->onAvailableSSIDs(jsonOfWiFiScanResults); } @@ -555,6 +559,7 @@ namespace WPEFramework if(INetworkManager::WiFiState::WIFI_STATE_CONNECTED == state) m_wifiSignalMonitor.startWiFiSignalStrengthMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC); + NMLOG_INFO("Posting onWiFiStateChange"); _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onWiFiStateChange(state); @@ -565,6 +570,7 @@ namespace WPEFramework void NetworkManagerImplementation::ReportWiFiSignalStrengthChangedEvent(const string ssid, const string signalLevel, const WiFiSignalQuality signalQuality) { LOG_ENTRY_FUNCTION(); + NMLOG_INFO("Posting onWiFiSignalStrengthChange"); _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onWiFiSignalStrengthChange(ssid, signalLevel, signalQuality); From 233db907b7613ca08f2b024ff1b65dfb80595dab Mon Sep 17 00:00:00 2001 From: Gururaaja E S R Date: Tue, 10 Sep 2024 19:33:01 +0000 Subject: [PATCH 002/271] DELIA-66037 - Trace and Ping ERROR_TIMEOUT response Reason for change: Changed the default packet size of trace in the networkmanagerplugin.md to 5 and also added default packet size for ping in Legacynetworkplugin.cpp Test Procedure: Build and verified Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR --- LegacyPlugin_NetworkAPIs.cpp | 10 +++++++--- docs/NetworkManagerPlugin.md | 6 +++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index 3b86f4758..f916ced01 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -27,6 +27,7 @@ using namespace WPEFramework::Plugin; #define API_VERSION_NUMBER_PATCH 0 #define NETWORK_MANAGER_CALLSIGN "org.rdk.NetworkManager.1" #define SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS 500 +#define DEFAULT_PING_PACKETS 15 #define LOGINFOMETHOD() { string json; parameters.ToString(json); NMLOG_TRACE("Legacy params=%s", json.c_str() ); } #define LOGTRACEMETHODFIN() { string json; response.ToString(json); NMLOG_TRACE("Legacy response=%s", json.c_str() ); } @@ -577,12 +578,15 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { tmpParameters["ipversion"] = "IPv4"; else if (inet_pton(AF_INET6, endpoint.c_str(), &ipv6address) > 0) tmpParameters["ipversion"] = "IPv6"; - - tmpParameters["noOfRequest"] = parameters["packets"]; + + if (parameters.HasLabel("packets")) + tmpParameters["noOfRequest"] = parameters["packets"]; + else + tmpParameters["noOfRequest"] = DEFAULT_PING_PACKETS; tmpParameters["endpoint"] = parameters["endpoint"]; tmpParameters["timeout"] = 5; tmpParameters["guid"] = parameters["guid"]; - + if (m_networkmanager) rc = m_networkmanager->Invoke(15000, _T("Ping"), tmpParameters, response); else diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 9e09b777c..14060d40b 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -964,7 +964,7 @@ No Events | params | object | | | params.endpoint | string | The host name or IP address | | params.ipversion | string | either IPv4 or IPv6 | -| params.noOfRequest | integer | The number of packets to send. Default is 15 | +| params.noOfRequest | integer | *(optional)* The number of packets to send. Default is 3 | | params.timeout | integer | Timeout | | params.guid | string | The globally unique identifier | @@ -1042,7 +1042,7 @@ No Events | params | object | | | params.ipversion| string | *(optional)* The host name or IP address | | params.endpoint | string | The host name or IP address | -| params.packets | integer | *(optional)* The number of packets to send. Default is 10 | +| params.packets | integer | *(optional)* The number of packets to send. Default is 5 | | params.guid | string | *(optional)* The globally unique identifier | ### Result @@ -1065,7 +1065,7 @@ No Events "method": "org.rdk.NetworkManager.Trace", "params": { "endpoint": "45.57.221.20", - "packets": 10 + "packets": 5 } } ``` From e73604efb9877e1bc547385804f767933cf14ea5 Mon Sep 17 00:00:00 2001 From: rafi Date: Thu, 5 Sep 2024 14:57:01 +0530 Subject: [PATCH 003/271] DELIA-66248 Fix NetworkManager plugin crash in gnome platform --- NetworkManagerGnomeEvents.cpp | 41 +++--- NetworkManagerGnomeEvents.h | 4 +- NetworkManagerGnomeProxy.cpp | 242 ++++++++++++++++++++++++++-------- NetworkManagerGnomeUtils.cpp | 73 +++++++--- NetworkManagerGnomeUtils.h | 10 +- NetworkManagerGnomeWIFI.cpp | 87 ++++++++---- NetworkManagerGnomeWIFI.h | 25 +++- 7 files changed, 348 insertions(+), 134 deletions(-) diff --git a/NetworkManagerGnomeEvents.cpp b/NetworkManagerGnomeEvents.cpp index f4dfcce8a..6afd4f73e 100644 --- a/NetworkManagerGnomeEvents.cpp +++ b/NetworkManagerGnomeEvents.cpp @@ -40,9 +40,6 @@ namespace WPEFramework extern NetworkManagerImplementation* _instance; static GnomeNetworkManagerEvents *_nmEventInstance = nullptr; - // const char* ifnameEth = "enx207bd51e02ad"; - // const char* ifnameWlan = "wlp0s20f3"; - static void primaryConnectionCb(NMClient *client, GParamSpec *param, NMEvents *nmEvents) { NMActiveConnection *primaryConn; @@ -136,7 +133,7 @@ namespace WPEFramework wifiState = "WIFI_STATE_CONNECTING"; GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTING); break; - case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_IP_CHECK: GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP,"wlan0"); break; case NM_DEVICE_STATE_ACTIVATED: @@ -280,10 +277,7 @@ namespace WPEFramework else if(ifname == nmEvents->ifnameEth0) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, "eth0"); } - else { - // TODO Check and remove if not needed - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, ifname); - } + /* ip events added only for eth0 and wlan0 */ if((ifname == nmEvents->ifnameEth0) || (ifname == nmEvents->ifnameWlan0)) { @@ -317,10 +311,6 @@ namespace WPEFramework GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, "eth0"); g_signal_handlers_disconnect_by_func(device, (gpointer)deviceStateChangeCb, nmEvents); } - else { - // TODO Check and remove if not needed - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, ifname); - } } // guint disconnected_count = g_signal_handlers_disconnect_matched( _nmEventInstance->activeConn, @@ -463,6 +453,12 @@ namespace WPEFramework GnomeNetworkManagerEvents::GnomeNetworkManagerEvents() { NMLOG_TRACE("GnomeNetworkManagerEvents"); + std::string wifiInterface = "wlan0", ethernetInterface = "eth0"; + if(!nmUtils::GetInterfacesName(wifiInterface, ethernetInterface)) + { + NMLOG_FATAL("GetInterfacesName failed"); + return; + } GError *error = NULL; nmEvents.client = nm_client_new(NULL, &error); if(!nmEvents.client || error ) @@ -482,8 +478,6 @@ namespace WPEFramework return; } _nmEventInstance = this; - std::string wifiInterface = "wlan0", ethernetInterface = "eth0"; - nmUtils::GetInterfacesName(wifiInterface, ethernetInterface); nmEvents.ifnameEth0 = ethernetInterface; nmEvents.ifnameWlan0 = wifiInterface; } @@ -529,8 +523,8 @@ namespace WPEFramework default: state = "Unknown"; } - NMLOG_INFO("%s interface state changed - %s", iface.c_str(), state.c_str()); - if(_instance != nullptr) + NMLOG_TRACE("%s interface state changed - %s", iface.c_str(), state.c_str()); + if(_instance != nullptr && (iface == _nmEventInstance->nmEvents.ifnameWlan0 || iface == _nmEventInstance->nmEvents.ifnameEth0)) _instance->ReportInterfaceStateChangedEvent(static_cast(newState), iface); } @@ -576,7 +570,7 @@ namespace WPEFramework void GnomeNetworkManagerEvents::onAvailableSSIDsCb(NMDeviceWifi *wifiDevice, GParamSpec *pspec, gpointer userData) { - NMLOG_INFO("wifi scanning completed ..."); + NMLOG_TRACE("wifi scanning completed ..."); if(!NM_IS_DEVICE_WIFI(wifiDevice)) { NMLOG_ERROR("Not a wifi object "); @@ -597,21 +591,22 @@ namespace WPEFramework ssidList.ToString(ssidListJson); if(_nmEventInstance->debugLogs) { _nmEventInstance->debugLogs = false; - NMLOG_TRACE("Number of Access Points Available = %d", static_cast(accessPoints->len)); + NMLOG_INFO("Number of Access Points Available = %d", static_cast(accessPoints->len)); NMLOG_TRACE("Scanned APIs are = %s",ssidListJson.c_str()); } - if(!_nmEventInstance->stopWifiScan) { + if(_nmEventInstance->doScanNotify) { + _nmEventInstance->doScanNotify = false; _instance->ReportAvailableSSIDsEvent(ssidListJson); } } - void GnomeNetworkManagerEvents::setwifiScanOptions(bool doScan, bool enableLogs) + void GnomeNetworkManagerEvents::setwifiScanOptions(bool doNotify, bool enableLogs) { - stopWifiScan.store(doScan); - if(stopWifiScan) + doScanNotify.store(doNotify); + if(!doScanNotify) { - NMLOG_WARNING("stop periodic wifi scan result"); + NMLOG_TRACE("stop periodic wifi scan result notify"); } debugLogs = enableLogs; } diff --git a/NetworkManagerGnomeEvents.h b/NetworkManagerGnomeEvents.h index e63c1b1e9..d65354d8d 100644 --- a/NetworkManagerGnomeEvents.h +++ b/NetworkManagerGnomeEvents.h @@ -53,14 +53,14 @@ namespace WPEFramework static GnomeNetworkManagerEvents* getInstance(); bool startNetworkMangerEventMonitor(); void stopNetworkMangerEventMonitor(); - void setwifiScanOptions(bool doScan, bool enableLogs = false); + void setwifiScanOptions(bool doNotify, bool enableLogs = false); private: static void* networkMangerEventMonitor(void *arg); GnomeNetworkManagerEvents(); ~GnomeNetworkManagerEvents(); std::atomicisEventThrdActive = {false}; - std::atomicstopWifiScan = {false}; + std::atomicdoScanNotify = {false}; std::atomicdebugLogs = {false}; NMEvents nmEvents; GThread *eventThrdID; diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index d3114db80..5104d2ee6 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -6,14 +6,11 @@ #include #include -static NMClient *client; - +static NMClient *client = NULL; using namespace WPEFramework; using namespace WPEFramework::Plugin; using namespace std; -static std::vector interfaceList; - namespace WPEFramework { namespace Plugin @@ -50,24 +47,25 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::GetAvailableInterfaces (Exchange::INetworkManager::IInterfaceDetailsIterator*& interfacesItr/* @out */) { - // [Process.cpp:78](Dispatch)<1>: We still have living object [1]. uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - string interfaces[2]; - string wifiInterface; - string ethernetInterface; NMDeviceType type; - InterfaceDetails tmp; NMDeviceState state; NMDevice *device = NULL; + static std::vector interfaceList; if(interfaceList.empty()) { - nmUtils::GetInterfacesName(wifiInterface, ethernetInterface); - interfaces[0] = wifiInterface; - interfaces[1] = ethernetInterface; - for (size_t i = 0; i < 2; i++) { + std::string interfaces[2]; + if(!nmUtils::GetInterfacesName(interfaces[0], interfaces[1])) + { + NMLOG_WARNING("GetInterface Name Error !"); + return Core::ERROR_GENERAL; + } + for (size_t i = 0; i < 2; i++) + { if(!interfaces[i].empty()) { + Exchange::INetworkManager::InterfaceDetails tmp; device = nm_client_get_device_by_iface(client, interfaces[i].c_str()); if (device) { @@ -78,10 +76,10 @@ namespace WPEFramework tmp.m_name = interfaces[i].c_str(); tmp.m_mac = nm_device_get_hw_address(device); state = nm_device_get_state(device); - tmp.m_isEnabled = (state > NM_DEVICE_STATE_UNAVAILABLE) ? 1 : 0; - tmp.m_isConnected = (state > NM_DEVICE_STATE_DISCONNECTED) ? 1: 0; + tmp.m_isEnabled = (state > NM_DEVICE_STATE_UNAVAILABLE) ? true : false; + tmp.m_isConnected = (state > NM_DEVICE_STATE_DISCONNECTED) ? true : false; interfaceList.push_back(tmp); - g_clear_object(&device); + //g_clear_object(&device); } } } @@ -100,25 +98,70 @@ namespace WPEFramework GError *error = NULL; NMActiveConnection *activeConn = NULL; NMRemoteConnection *remoteConn = NULL; + if(client == nullptr) + { + NMLOG_WARNING("client connection null:"); + return Core::ERROR_GENERAL; + } activeConn = nm_client_get_primary_connection(client); if (activeConn == NULL) { - NMLOG_TRACE("Error getting primary connection: %s", error->message); - g_error_free(error); - return rc; - } + NMLOG_ERROR("No active activeConn Interface found"); + return Core::ERROR_GENERAL; + } remoteConn = nm_active_connection_get_connection(activeConn); - - interface = nm_connection_get_interface_name(NM_CONNECTION(remoteConn)); - if(!interface.empty()) + if(remoteConn == NULL) + { + NMLOG_WARNING("remote connection error"); + return Core::ERROR_GENERAL; + } + interface.clear(); + const char *ifacePtr = nm_connection_get_interface_name(NM_CONNECTION(remoteConn)); + if(ifacePtr == NULL) + { + NMLOG_ERROR("nm_connection_get_interface_name is failed"); + return Core::ERROR_GENERAL; + } + interface = ifacePtr; + if(interface != "eth0" && interface != "wlan0") + { + NMLOG_TRACE("interface name is unknow"); + interface.clear(); + } + else rc = Core::ERROR_NONE; + return rc; } /* @brief Set the active Interface used for external world communication */ uint32_t NetworkManagerImplementation::SetPrimaryInterface (const string& interface/* @in */) { - uint32_t rc = Core::ERROR_NONE; + uint32_t rc = Core::ERROR_RPC_CALL_FAILED; + if(client == nullptr) + { + NMLOG_WARNING("client connection null:"); + return Core::ERROR_RPC_CALL_FAILED; + } + + std::string iface = "eth0"; + std::string eth, wifi; + if(!nmUtils::GetInterfacesName(wifi, eth)) + { + NMLOG_WARNING("GetInterface Name Error !"); + return Core::ERROR_GENERAL; + } + + else if(interface == "wlan0" || nmUtils::caseInsensitiveCompare(interface,"WIFI")) + iface = wifi; + else if(interface == "eth0" || nmUtils::caseInsensitiveCompare(interface,"ETHERNET")) + iface = eth; + + NMDevice *device = nm_client_get_device_by_iface(client, iface.c_str()); + if (device == NULL) { + NMLOG_WARNING("no interface found "); + return Core::ERROR_GENERAL; + } const GPtrArray *connections = nm_client_get_connections(client); NMConnection *conn = NULL; NMSettingConnection *settings; @@ -128,11 +171,16 @@ namespace WPEFramework settings = nm_connection_get_setting_connection(connection); /* Check if the interface name matches */ - if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) { + if (g_strcmp0(nm_setting_connection_get_interface_name(settings), iface.c_str()) == 0) { conn = connection; break; } } + if(conn == NULL) + { + NMLOG_WARNING("no nm setting available for the interface"); + return Core::ERROR_GENERAL; + } g_object_set(settings, NM_SETTING_CONNECTION_AUTOCONNECT, true, @@ -149,26 +197,39 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool& enabled /* @in */) { uint32_t rc = Core::ERROR_NONE; + if(client == nullptr) + { + NMLOG_WARNING("client connection null:"); + return Core::ERROR_RPC_CALL_FAILED; + } + + std::string iface = "eth0"; + std::string eth, wifi; + if(!nmUtils::GetInterfacesName(wifi, eth)) + { + NMLOG_WARNING("GetInterface Name Error !"); + return Core::ERROR_GENERAL; + } + + else if(interface == "wlan0" || nmUtils::caseInsensitiveCompare(interface,"WIFI")) + iface = wifi; + else if(interface == "eth0" || nmUtils::caseInsensitiveCompare(interface,"ETHERNET")) + iface = eth; + const GPtrArray *devices = nm_client_get_devices(client); NMDevice *device = NULL; for (guint i = 0; i < devices->len; ++i) { device = NM_DEVICE(g_ptr_array_index(devices, i)); - - // Get the device details const char *name = nm_device_get_iface(device); - - // Check if the device name matches - if (g_strcmp0(name, interface.c_str()) == 0) { + if (g_strcmp0(name, iface.c_str()) == 0) { nm_device_set_managed(device, enabled); - - NMLOG_TRACE("Interface %s status set to %s", interface.c_str(), enabled ? "Enabled" : "Disabled"); + NMLOG_INFO("Interface %s status set to %s", iface.c_str(), enabled ? "Enabled" : "Disabled"); } } - // Cleanup - if(device) - g_clear_object(&device); + // if(device) + // g_clear_object(&device); return rc; } @@ -205,7 +266,6 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::GetIPSettings(const string& interface /* @in */, const string& ipversion /* @in */, IPAddressInfo& result /* @out */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - GError *error = NULL; NMActiveConnection *conn = NULL; NMIPConfig *ip4_config = NULL; NMIPConfig *ip6_config = NULL; @@ -215,27 +275,75 @@ namespace WPEFramework NMDhcpConfig *dhcp6_config = NULL; const char* dhcpserver; NMSettingConnection *settings; - NMIPAddress *address; + NMIPAddress *address = NULL; + NMDevice *device = NULL; - const GPtrArray *connections = nm_client_get_active_connections(client); + if(client == nullptr) + { + NMLOG_WARNING("client connection null:"); + return Core::ERROR_RPC_CALL_FAILED; + } - for (guint i = 0; i < connections->len; i++) { + std::string iface = "eth0"; + std::string ethIface, wifiIface; + if(!nmUtils::GetInterfacesName(wifiIface, ethIface)) + { + NMLOG_WARNING("GetInterface Name Error !"); + return Core::ERROR_GENERAL; + } + + else if(interface == "wlan0" || nmUtils::caseInsensitiveCompare(interface,"WIFI")) + iface = wifiIface; + else if(interface == "eth0" || nmUtils::caseInsensitiveCompare(interface,"ETHERNET")) + iface = ethIface; + else + { + if(Core::ERROR_NONE != GetPrimaryInterface(iface)) + { + NMLOG_WARNING("interface is not specified and default interface get failed"); + return Core::ERROR_GENERAL; + } + } + + device = nm_client_get_device_by_iface(client, iface.c_str()); + if (device == NULL) { + NMLOG_WARNING("no interface found / wifi not connected no ip found"); + return Core::ERROR_GENERAL; + } + + NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; + deviceState = nm_device_get_state(device); + if(deviceState != NM_DEVICE_STATE_ACTIVATED) + { + NMLOG_WARNING("device state is not activated state: (%d)", deviceState); + return Core::ERROR_GENERAL; + } + + if(ipversion.empty()) + NMLOG_WARNING("ipversion is empty default value IPV4"); + + const GPtrArray *connections = nm_client_get_active_connections(client); + if(connections == NULL) + { + NMLOG_WARNING("nm_client_get_active_connections error"); + return Core::ERROR_GENERAL; + } + for (guint i = 0; i < connections->len; i++){ NMActiveConnection *connection = NM_ACTIVE_CONNECTION(connections->pdata[i]); settings = nm_connection_get_setting_connection(NM_CONNECTION(nm_active_connection_get_connection(connection))); /* Check if the interface name matches */ - if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) { + if (g_strcmp0(nm_setting_connection_get_interface_name(settings), iface.c_str()) == 0) { conn = connection; break; } } if (conn == NULL) { - NMLOG_TRACE("Error getting primary connection: %s", error->message); - g_error_free(error); - return rc; - } + NMLOG_ERROR("no active connection found"); + return Core::ERROR_GENERAL; + } - if(0 == strcmp(ipversion.c_str(), "IPv4")) + if(ipversion.empty()||nmUtils::caseInsensitiveCompare(ipversion,"IPV4")) { ip4_config = nm_active_connection_get_ip4_config(conn); if (ip4_config != NULL) { @@ -252,8 +360,10 @@ namespace WPEFramework dhcp4_config = nm_active_connection_get_dhcp4_config(conn); dhcpserver = nm_dhcp_config_get_one_option (dhcp4_config, "dhcp_server_identifier"); - - result.m_ipAddrType = ipversion.c_str(); + if(!ipversion.empty()) + result.m_ipAddrType = ipversion.c_str(); + else + result.m_ipAddrType = "IPv4"; if(dhcpserver) result.m_dhcpServer = dhcpserver; result.m_v6LinkLocal = ""; @@ -267,7 +377,7 @@ namespace WPEFramework rc = Core::ERROR_NONE; } - else if(0 == strcmp(ipversion.c_str(), "IPv6")) + else if(nmUtils::caseInsensitiveCompare(ipversion,"IPV6")) { NMIPAddress *a; ip6_config = nm_active_connection_get_ip6_config(conn); @@ -300,10 +410,11 @@ namespace WPEFramework } rc = Core::ERROR_NONE; } + else + NMLOG_WARNING("ipversion is not IPV4 orIPV6"); return rc; } - // Callback for nm_client_deactivate_connection_async static void on_deactivate_complete(GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; @@ -339,6 +450,11 @@ namespace WPEFramework GMainLoop *g_loop; g_loop = g_main_loop_new(NULL, FALSE); uint32_t rc = Core::ERROR_NONE; + if(client == nullptr) + { + NMLOG_WARNING("client connection null"); + return Core::ERROR_GENERAL; + } const GPtrArray *connections = nm_client_get_connections(client); NMSettingIP4Config *s_ip4; NMSettingIP6Config *s_ip6; @@ -362,7 +478,7 @@ namespace WPEFramework } if (!address.m_autoConfig) { - if (strcasecmp("IPv4", ipversion.c_str()) == 0) + if (nmUtils::caseInsensitiveCompare("IPv4", ipversion)) { NMSettingIPConfig *ip4_config = nm_connection_get_setting_ip4_config(conn); if (ip4_config == NULL) @@ -393,7 +509,7 @@ namespace WPEFramework } else { - if (strcmp("IPv4", ipversion.c_str()) == 0) + if (nmUtils::caseInsensitiveCompare("IPv4", ipversion)) { s_ip4 = (NMSettingIP4Config *)nm_setting_ip4_config_new(); g_object_set(G_OBJECT(s_ip4), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); @@ -422,7 +538,7 @@ namespace WPEFramework break; } } - + spec_object = nm_object_get_path(NM_OBJECT(active_connection)); nm_remote_connection_commit_changes(remote_connection, false, NULL, NULL); nm_client_deactivate_connection_async(client, active_connection, NULL, on_deactivate_complete, NULL); @@ -434,7 +550,7 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::StartWiFiScan(const WiFiFrequency frequency /* @in */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - nmEvent->setwifiScanOptions(false, true); + nmEvent->setwifiScanOptions(true, true); if(wifi->wifiScanRequest(frequency)) rc = Core::ERROR_NONE; return rc; @@ -444,7 +560,7 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_NONE; // TODO explore wpa_supplicant stop - nmEvent->setwifiScanOptions(true); // This will stop periodic posting of onAvailableSSID event + nmEvent->setwifiScanOptions(false); // This will stop periodic posting of onAvailableSSID event NMLOG_INFO ("StopWiFiScan is success"); return rc; } @@ -489,7 +605,21 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::WiFiConnect(const WiFiConnectTo& ssid /* @in */) { - uint32_t rc = Core::ERROR_RPC_CALL_FAILED; + uint32_t rc = Core::ERROR_GENERAL; + if(ssid.m_ssid.empty() || ssid.m_ssid.size() > 32) + { + NMLOG_WARNING("ssid is invalied"); + return rc; + } + // Check the last scanning time and if it exceeds 10 sec do a rescanning + if(!wifi->isWifiScannedRecently()) + { + nmEvent->setwifiScanOptions(false, true); // not notify scan result but print logs + if(!wifi->wifiScanRequest(Exchange::INetworkManager::WiFiFrequency::WIFI_FREQUENCY_WHATEVER, ssid.m_ssid)) + { + NMLOG_WARNING("scanning failed but try to connect"); + } + } if(wifi->wifiConnect(ssid)) rc = Core::ERROR_NONE; return rc; @@ -497,7 +627,7 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::WiFiDisconnect(void) { - uint32_t rc = Core::ERROR_RPC_CALL_FAILED; + uint32_t rc = Core::ERROR_GENERAL; if(wifi->wifiDisconnect()) rc = Core::ERROR_NONE; return rc; diff --git a/NetworkManagerGnomeUtils.cpp b/NetworkManagerGnomeUtils.cpp index 7b562dc85..8e611b0da 100644 --- a/NetworkManagerGnomeUtils.cpp +++ b/NetworkManagerGnomeUtils.cpp @@ -17,6 +17,9 @@ namespace WPEFramework { namespace Plugin { + static const char* ifnameEth = "eth0"; + static const char* ifnameWlan = "wlan0"; + uint8_t nmUtils::wifiSecurityModeFromAp(guint32 flags, guint32 wpaFlags, guint32 rsnFlags) { uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; @@ -249,36 +252,66 @@ namespace WPEFramework } } + bool nmUtils::caseInsensitiveCompare(const std::string& str1, const std::string& str2) { + std::string upperStr1 = str1; + std::string upperStr2 = str2; + + // Convert both strings to uppercase + std::transform(upperStr1.begin(), upperStr1.end(), upperStr1.begin(), ::toupper); + std::transform(upperStr2.begin(), upperStr2.end(), upperStr2.begin(), ::toupper); + + return upperStr1 == upperStr2; + } - uint32_t nmUtils::GetInterfacesName(string &wifiInterface, string ðernetInterface) { - string line; - uint32_t rc = Core::ERROR_GENERAL; + bool nmUtils::GetInterfacesName(std::string &wifiIfname ,std::string ðIfname) + { + std::string line; + static bool fileParsingCompleted = false; + static std::string m_wifiIfname; + static std::string m_ethIfname; // cached interface name + wifiIfname.clear(); + ethIfname.clear(); + if(fileParsingCompleted) + { + if(!m_wifiIfname.empty()) + wifiIfname = m_wifiIfname; + if(!m_ethIfname.empty()) + ethIfname = m_ethIfname; + return true; + } - ifstream file("/etc/device.properties"); + std::ifstream file("/etc/device.properties"); if (!file.is_open()) { - NMLOG_WARNING("/etc/device.properties opening file Error "); - return rc; + NMLOG_FATAL("/etc/device.properties opening file Error"); + return false; } - while (std::getline(file, line)) { - // Remove newline character if present - if (!line.empty() && line.back() == '\n') { - line.pop_back(); + while (std::getline(file, line)) + { + if (line.empty()) { + continue; + } + if (line.find("ETHERNET_INTERFACE=") != std::string::npos) { + ethIfname = line.substr(line.find('=') + 1); + ethIfname.erase(ethIfname.find_last_not_of("\r\n\t") + 1); + ethIfname.erase(0, ethIfname.find_first_not_of("\r\n\t")); } - istringstream iss(line); - string token; - getline(iss, token, '='); - - if (token == "WIFI_INTERFACE") { - std::getline(iss, wifiInterface, '='); - } else if (token == "ETHERNET_INTERFACE") { - std::getline(iss, ethernetInterface, '='); + if (line.find("WIFI_INTERFACE=") != std::string::npos) { + wifiIfname = line.substr(line.find('=') + 1); + wifiIfname.erase(wifiIfname.find_last_not_of("\r\n\t") + 1); + wifiIfname.erase(0, wifiIfname.find_first_not_of("\r\n\t")); } } file.close(); - return Core::ERROR_NONE; + if (ethIfname.empty() && wifiIfname.empty()) { + NMLOG_FATAL("Could not find any interface name in /etc/device.properties"); + return false; + } + m_wifiIfname = wifiIfname; + m_ethIfname = ethIfname; + fileParsingCompleted = true; + return true; } - } // Plugin } // WPEFramework diff --git a/NetworkManagerGnomeUtils.h b/NetworkManagerGnomeUtils.h index a66d6643c..c52a5a733 100644 --- a/NetworkManagerGnomeUtils.h +++ b/NetworkManagerGnomeUtils.h @@ -33,7 +33,8 @@ namespace WPEFramework { public: - static uint32_t GetInterfacesName(string &wifiInterface, string ðernetInterface); + static bool GetInterfacesName(std::string &wifiIfname ,std::string ðIfname); + static bool caseInsensitiveCompare(const std::string& str1, const std::string& str2); static uint8_t wifiSecurityModeFromAp(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); static std::string wifiFrequencyFromAp(guint32 apFreq); static std::string getSecurityModeString(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); @@ -42,9 +43,4 @@ namespace WPEFramework }; } -} - -/* - // Set up a timer to check the device state reason every second - g_timeout_add_seconds(1, check_device_state_reason, NULL); - */ +} \ No newline at end of file diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 8ea90346c..4d45820d0 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -34,22 +34,8 @@ namespace WPEFramework namespace Plugin { - wifiManager* wifiManager::getInstance() - { - static wifiManager instance; - return &instance; - } - - wifiManager::~wifiManager() { - NMLOG_INFO("~wifiManager"); - g_main_context_pop_thread_default(nmContext); - if(loop != NULL) - g_main_loop_unref(loop); - if(client != NULL) - g_object_unref(client); - } - wifiManager::wifiManager() : client(nullptr), loop(nullptr), createNewConnection(false) { + NMLOG_INFO("wifiManager"); nmContext = g_main_context_new(); g_main_context_push_thread_default(nmContext); loop = g_main_loop_new(nmContext, FALSE); @@ -104,7 +90,7 @@ namespace WPEFramework NMLOG_WARNING("g_main_loop_is running"); return false; } - source = g_timeout_source_new(10000); // 10000ms interval + source = g_timeout_source_new(timeOutMs); // 10000ms interval g_source_set_callback(source, (GSourceFunc)gmainLoopTimoutCB, this, NULL); g_source_attach(source, NULL); g_main_loop_run(loop); @@ -143,6 +129,21 @@ namespace WPEFramework if (wifiDevice == NULL || !NM_IS_DEVICE_WIFI(wifiDevice)) { NMLOG_ERROR("Wireless Device not found !"); + return NULL; + } + + NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; + deviceState = nm_device_get_state(wifiDevice); + switch (deviceState) + { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_UNAVAILABLE: + NMLOG_WARNING("wifi device state is not vallied; state: (%d)", deviceState); + return NULL; + break; + default: + break; } return wifiDevice; @@ -187,9 +188,18 @@ namespace WPEFramework if (ssid) { gsize size; const guint8 *ssidData = static_cast(g_bytes_get_data(ssid, &size)); - std::string ssidTmp(reinterpret_cast(ssidData), size); - wifiInfo.m_ssid = ssidTmp; - NMLOG_INFO("ssid: %s", wifiInfo.m_ssid.c_str()); + if(size<=32) + { + std::string ssidTmp(reinterpret_cast(ssidData), size); + wifiInfo.m_ssid = ssidTmp; + NMLOG_INFO("ssid: %s", wifiInfo.m_ssid.c_str()); + } + else + { + NMLOG_ERROR("Invallied ssid length Error"); + wifiInfo.m_ssid.clear(); + return; + } } else { @@ -860,7 +870,7 @@ namespace WPEFramework isSuccess = false; if(!ssidReq.empty()) { - NMLOG_TRACE("staring wifi scanning .. %s", ssidReq.c_str()); + NMLOG_INFO("staring wifi scanning .. %s", ssidReq.c_str()); GVariantBuilder builder, array_builder; GVariant *options; g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); @@ -871,14 +881,47 @@ namespace WPEFramework g_variant_builder_add(&builder, "{sv}", "ssids", g_variant_builder_end(&array_builder)); g_variant_builder_add(&builder, "{sv}", "hidden", g_variant_new_boolean(TRUE)); options = g_variant_builder_end(&builder); - nm_device_wifi_request_scan_options_async(NM_DEVICE_WIFI(wifiDevice), options, NULL, wifiScanCb, this); + nm_device_wifi_request_scan_options_async(wifiDevice, options, NULL, wifiScanCb, this); } else { NMLOG_TRACE("staring normal wifi scanning"); - nm_device_wifi_request_scan_async(NM_DEVICE_WIFI(wifiDevice), NULL, wifiScanCb, this); + nm_device_wifi_request_scan_async(wifiDevice, NULL, wifiScanCb, this); } wait(loop); return isSuccess; } + + bool wifiManager::isWifiScannedRecently(int timelimitInSec) + { + if (!createClientNewConnection()) + return false; + + NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getNmDevice()); + if (wifiDevice == NULL) { + NMLOG_ERROR("Invalid Wi-Fi device."); + return false; + } + + gint64 last_scan_time = nm_device_wifi_get_last_scan(wifiDevice); + if (last_scan_time <= 0) { + NMLOG_INFO("No scan has been performed yet"); + return false; + } + + gint64 current_time_in_msec = nm_utils_get_timestamp_msec(); + gint64 time_difference_in_seconds = (current_time_in_msec - last_scan_time) / 1000; + + NMLOG_TRACE("Current time in milliseconds: %" G_GINT64_FORMAT, current_time_in_msec); + NMLOG_TRACE("Last scan time in milliseconds: %" G_GINT64_FORMAT, last_scan_time); + NMLOG_TRACE("Time difference in seconds: %" G_GINT64_FORMAT, time_difference_in_seconds); + + if (time_difference_in_seconds <= timelimitInSec) { + return true; + } + NMLOG_TRACE("Last Wi-Fi scan exceeded time limit."); + return false; + } + + } // namespace Plugin } // namespace WPEFramework diff --git a/NetworkManagerGnomeWIFI.h b/NetworkManagerGnomeWIFI.h index 0c4c4db03..ec17b4751 100644 --- a/NetworkManagerGnomeWIFI.h +++ b/NetworkManagerGnomeWIFI.h @@ -36,12 +36,18 @@ namespace WPEFramework class wifiManager { public: - static wifiManager* getInstance(); + static wifiManager* getInstance() + { + static wifiManager instance; + return &instance; + } + bool isWifiConnected(); bool wifiDisconnect(); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); bool wifiConnect(Exchange::INetworkManager::WiFiConnectTo wifiData); bool wifiScanRequest(const Exchange::INetworkManager::WiFiFrequency frequency, std::string ssidReq = ""); + bool isWifiScannedRecently(int timelimitInSec = 10); // default 10 sec as shotest scanning interval bool getKnownSSIDs(std::list& ssids); bool addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo ssidinfo); bool removeKnownSSID(const string& ssid); @@ -52,7 +58,18 @@ namespace WPEFramework private: wifiManager(); - ~wifiManager(); + ~wifiManager() { + NMLOG_INFO("~wifiManager"); + g_main_context_pop_thread_default(nmContext); + if(client != NULL) { + g_object_unref(client); + client = NULL; + } + if(loop != NULL) { + g_main_loop_unref(loop); + loop = NULL; + } + } wifiManager(wifiManager const&) = delete; void operator=(wifiManager const&) = delete; @@ -70,5 +87,5 @@ namespace WPEFramework guint wifiDeviceStateGsignal = 0; bool isSuccess = false; }; - } -} + } // Plugin +} // WPEFramework From 045be9daa22ad44a820508fe44232e84f6654060 Mon Sep 17 00:00:00 2001 From: rafi Date: Wed, 11 Sep 2024 11:40:04 +0530 Subject: [PATCH 004/271] caseInsensitiveComparison added --- LegacyPlugin_NetworkAPIs.cpp | 47 +++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index f916ced01..844dc560c 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -265,6 +265,13 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { "255.255.255.255", }; + static bool caseInsensitiveCompare(const std::string& str1, const char* str2) + { + std::string upperStr1 = str1; + std::transform(upperStr1.begin(), upperStr1.end(), upperStr1.begin(), ::toupper); + return upperStr1 == str2; + } + uint32_t Network::getInterfaces (const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; @@ -324,13 +331,13 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { uint32_t rc = Core::ERROR_GENERAL; string interface; JsonObject tmpParameters; - + LOGINFOMETHOD(); - if("WIFI" == parameters["interface"].String()) + if(caseInsensitiveCompare(parameters["interface"].String(),"WIFI")) interface = "wlan0"; - else if("ETHERNET" == parameters["interface"].String()) + else if(caseInsensitiveCompare(parameters["interface"].String(), "ETHERNET")) interface = "eth0"; - + tmpParameters["interface"] = interface; tmpParameters["enabled"] = parameters["enabled"]; @@ -375,9 +382,9 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { JsonObject tmpParameters; string interface; LOGINFOMETHOD(); - if("WIFI" == parameters["interface"].String()) + if(caseInsensitiveCompare(parameters["interface"].String(), "WIFI")) tmpParameters["interface"] = "wlan0"; - else if("ETHERNET" == parameters["interface"].String()) + else if(caseInsensitiveCompare(parameters["interface"].String(), "ETHERNET")) tmpParameters["interface"] = "eth0"; if (m_networkmanager) @@ -397,9 +404,9 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { JsonObject tmpParameters; LOGINFOMETHOD(); - if("WIFI" == parameters["interface"].String()) + if(caseInsensitiveCompare(parameters["interface"].String(), "WIFI")) tmpParameters["interface"] = "wlan0"; - else if("ETHERNET" == parameters["interface"].String()) + else if(caseInsensitiveCompare(parameters["interface"].String(), "ETHERNET")) tmpParameters["interface"] = "eth0"; tmpParameters["ipversion"] = parameters["ipversion"]; @@ -441,9 +448,9 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { tmpParameters["ipversion"] = parameters["ipversion"]; if (parameters.HasLabel("interface")) { - if ("WIFI" == parameters["interface"].String()) + if (caseInsensitiveCompare(parameters["interface"].String(), "WIFI")) tmpParameters["interface"] = "wlan0"; - else if("ETHERNET" == parameters["interface"].String()) + else if(caseInsensitiveCompare(parameters["interface"].String(), "ETHERNET")) tmpParameters["interface"] = "eth0"; } @@ -474,14 +481,14 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { response["ipaddr"] = tmpResponse["ipaddress"]; if(tmpResponse["ipaddress"].String().empty()) response["netmask"] = ""; - else if ("IPV4" == ipversion) + else if (caseInsensitiveCompare(ipversion, "IPV4")) { index = tmpResponse["prefix"].Number(); if(CIDR_NETMASK_IP_LEN <= index) return Core::ERROR_GENERAL; response["netmask"] = CIDR_PREFIXES[index]; } - else if ("IPV6" == ipversion) + else if (caseInsensitiveCompare(ipversion, "IPV6")) { response["netmask"] = tmpResponse["prefix"]; } @@ -510,7 +517,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { if (Core::ERROR_NONE == rc) { response["connectedToInternet"] = tmpResponse["isConnectedToInternet"]; - if(ipversion == "IPV4" || ipversion == "IPV6") + if(caseInsensitiveCompare(ipversion, "IPV4") || caseInsensitiveCompare(ipversion, "IPV6")) response["ipversion"] = ipversion.c_str(); response["success"] = true; } @@ -538,8 +545,8 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { if (Core::ERROR_NONE == rc) { status = tmpResponse["status"].String(); - NMLOG_TRACE("status = %s\n", status.c_str() ); - NMLOG_TRACE("tmpResponse[status].String() = %s\n", tmpResponse["status"].String().c_str() ); + NMLOG_TRACE("status = %s", status.c_str() ); + NMLOG_TRACE("tmpResponse[status].String() = %s", tmpResponse["status"].String().c_str() ); if(status == "LIMITED_INTERNET") response["state"] = static_cast(2); else if(status == "CAPTIVE_PORTAL") @@ -554,7 +561,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { else response["state"] = static_cast(0); - if(ipversion == "IPV4" || ipversion == "IPV6") + if(caseInsensitiveCompare(ipversion, "IPV4") || caseInsensitiveCompare(ipversion, "IPV6")) response["ipversion"] = ipversion.c_str(); response["success"] = true; } @@ -628,9 +635,9 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { JsonObject tmpResponse; LOGINFOMETHOD(); - if("WIFI" == parameters["iface"].String()) + if(caseInsensitiveCompare(parameters["iface"].String(), "WIFI")) interface = "wlan0"; - else if("ETHERNET" == parameters["iface"].String()) + else if(caseInsensitiveCompare(parameters["iface"].String(), "ETHERNET")) interface = "eth0"; if(parameters["ipv6"].Boolean()) @@ -664,9 +671,9 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { string interface = parameters["interface"].String(); string newInterface = ""; - if("WIFI" == interface) + if(caseInsensitiveCompare(interface, "WIFI")) newInterface = "wlan0"; - else if("ETHERNET" == interface) + else if(caseInsensitiveCompare(interface, "ETHERNET")) newInterface = "eth0"; tmpParameters["interface"] = newInterface; From d94f304e7e6a0d8ae8afeb0dccec1db6fa1cb47b Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Wed, 11 Sep 2024 10:59:33 -0400 Subject: [PATCH 005/271] Merge pull request #4 from gururaajar/develop DELIA-66037 - Trace and Ping ERROR_TIMEOUT response From 11306daa0f62609f44f91a14de34a97888b7d82d Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Thu, 12 Sep 2024 15:16:03 -0400 Subject: [PATCH 006/271] Merge pull request #5 from cmuhammedrafi/topic/nmEvent DELIA-66248, RDKTV-32911 : fix for Fix Network Manager plugin crash in gnome and RDK platform Error From 231c914c3210a605e18b6308a7d6d569b1886a03 Mon Sep 17 00:00:00 2001 From: Gururaaja E S R Date: Fri, 13 Sep 2024 21:04:55 +0000 Subject: [PATCH 007/271] DELIA-66281 - GetPariedSSID issue and aligning with the NetworkManagerPlugin.md documentation Reason for change: Changed GetPariedSSID to return the last paried SSID instead of array and made changes to align with the NetworkManagerplugin.md documentation Test Procedure: Build and verified Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR --- LegacyPlugin_NetworkAPIs.cpp | 1 - LegacyPlugin_WiFiManagerAPIs.cpp | 14 ++++++++++- NetworkManagerJsonRpc.cpp | 41 ++++++++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index 844dc560c..bcabd3883 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -462,7 +462,6 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { if (Core::ERROR_NONE == rc) { string ipversion = tmpResponse["ipversion"].String(); - std::transform(ipversion.begin(), ipversion.end(), ipversion.begin(), ::toupper); if (parameters.HasLabel("interface")) { diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index 170c7c8b3..44d0b69eb 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -321,12 +321,24 @@ namespace WPEFramework { LOGINFOMETHOD(); uint32_t rc = Core::ERROR_GENERAL; + JsonObject tmpResponse; if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetKnownSSIDs"), parameters, response); + rc = m_networkmanager->Invoke(5000, _T("GetKnownSSIDs"), parameters, tmpResponse); else rc = Core::ERROR_UNAVAILABLE; + JsonArray array = tmpResponse["ssids"].Array(); + if (0 == array.Length()) + { + response["ssid"] = NULL; + } + else + { + response["ssid"] = array[0]; + } + response["success"] = tmpResponse["success"]; + LOGTRACEMETHODFIN(); return rc; } diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 01c5b76ad..e5996a42c 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -199,6 +199,13 @@ namespace WPEFramework LOGINFOMETHOD(); uint32_t rc = Core::ERROR_GENERAL; string interface = parameters["interface"].String(); + + if ("wlan0" != interface && "eth0" != interface) + { + rc = Core::ERROR_BAD_REQUEST; + return rc; + } + if (_NetworkManager) rc = _NetworkManager->SetPrimaryInterface(interface); else @@ -218,6 +225,13 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; string interface = parameters["interface"].String(); bool enabled = parameters["enabled"].Boolean(); + + if ("wlan0" != interface && "eth0" != interface) + { + rc = Core::ERROR_BAD_REQUEST; + return rc; + } + if (_NetworkManager) rc = _NetworkManager->SetInterfaceState(interface, enabled); else @@ -238,6 +252,12 @@ namespace WPEFramework bool isEnabled = false; string interface = parameters["interface"].String(); + if ("wlan0" != interface && "eth0" != interface) + { + rc = Core::ERROR_BAD_REQUEST; + return rc; + } + if (_NetworkManager) rc = _NetworkManager->GetInterfaceState(interface, isEnabled); else @@ -264,6 +284,13 @@ namespace WPEFramework interface = parameters["interface"].String(); if (parameters.HasLabel("ipversion")) ipversion = parameters["ipversion"].String(); + + if ("wlan0" != interface && "eth0" != interface) + { + rc = Core::ERROR_BAD_REQUEST; + return rc; + } + if (_NetworkManager) rc = _NetworkManager->GetIPSettings(interface, ipversion, result); else @@ -272,8 +299,11 @@ namespace WPEFramework if (Core::ERROR_NONE == rc) { response["interface"] = interface; - if(result.m_ipAddrType == "IPV6" || result.m_ipAddrType == "IPV4") - result.m_ipAddrType[2] = tolower(result.m_ipAddrType[2]); + + if (strcasecmp (result.m_ipAddrType.c_str(), "IPv4") == 0) + result.m_ipAddrType = "IPv4"; + else if (strcasecmp (result.m_ipAddrType.c_str(), "IPv6") == 0) + result.m_ipAddrType = "IPv6"; response["ipversion"] = result.m_ipAddrType; response["autoconfig"] = result.m_autoConfig; response["ipaddress"] = result.m_ipAddress; @@ -302,6 +332,13 @@ namespace WPEFramework interface = parameters["interface"].String(); if (parameters.HasLabel("ipversion")) ipversion = parameters["ipversion"].String(); + + if ("wlan0" != interface && "eth0" != interface) + { + rc = Core::ERROR_BAD_REQUEST; + return rc; + } + result.m_autoConfig = parameters["autoconfig"].Boolean(); if (!result.m_autoConfig) { From bd5fae10d8e3cd18c90f0152c577a3447f7404e4 Mon Sep 17 00:00:00 2001 From: Gururaaja E S R Date: Fri, 13 Sep 2024 21:04:55 +0000 Subject: [PATCH 008/271] DELIA-66281 - GetPariedSSID issue and aligning with the NetworkManagerPlugin.md documentation Reason for change: Changed GetPariedSSID to return the last paried SSID instead of array and made changes to align with the NetworkManagerplugin.md documentation Test Procedure: Build and verified Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR --- LegacyPlugin_WiFiManagerAPIs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index 44d0b69eb..19cbb0e7d 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -331,7 +331,7 @@ namespace WPEFramework JsonArray array = tmpResponse["ssids"].Array(); if (0 == array.Length()) { - response["ssid"] = NULL; + response["ssid"] = ""; /* Assigning empty string when paired SSID is not available */ } else { From e38d917d3cd55e222999431247c5f91402bc6122 Mon Sep 17 00:00:00 2001 From: Gururaaja E S R Date: Fri, 13 Sep 2024 21:30:38 +0000 Subject: [PATCH 009/271] Merge branch 'develop' of github.com:gururaajar/networkmanager into develop From 7ad4a7defa175a9e4bbe18c8c59e55347cc6796d Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Mon, 16 Sep 2024 10:25:17 -0400 Subject: [PATCH 010/271] Merge pull request #6 from gururaajar/develop DELIA-66281 - GetPariedSSID issue and aligning with the NetworkManagerPlugin.md documentation From 1a7cdaa63de0fa04778ce5a651c789b6f223bf21 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Mon, 16 Sep 2024 11:16:50 -0400 Subject: [PATCH 011/271] DELIA-66215 : Release of 0.3.0 Reason for change: Release of 0.3.0 Test Procedure: Verify Network and WiFi Risks: Medium Signed-off-by: Karunakaran A --- CMakeLists.txt | 4 ++-- LegacyPlugin_WiFiManagerAPIs.cpp | 2 +- NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 911b2f12e..e49595609 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 2) -set(VERSION_PATCH 11) +set(VERSION_MINOR 3) +set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) add_compile_definitions(NETWORKMANAGER_MINOR_VERSION=${VERSION_MINOR}) diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index 19cbb0e7d..52201892f 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -552,7 +552,7 @@ namespace WPEFramework } } else - NMLOG_ERROR("m_subsWiFiStateChange is null"); + NMLOG_ERROR("m_networkmanager is null"); if (m_subsWiFiStateChange && m_subsAvailableSSIDs && m_subsWiFiStrengthChange) { diff --git a/NetworkManager.json b/NetworkManager.json index ed0bfba18..4fe9faf4a 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -8,7 +8,7 @@ "locator": "libWPEFrameworkNetworkManager.so", "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", - "version": "0.2.11" + "version": "0.3.0" }, "common": { "$ref": "../../common/common.json" diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 14060d40b..2073468ea 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: [0.2.11]()** +**Version: [0.3.0]()** A NetworkManager plugin for Thunder framework. From 1d3de28df8f1f3bf4754008c39555039af1e9e6a Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Mon, 16 Sep 2024 11:16:50 -0400 Subject: [PATCH 012/271] DELIA-66215 : Release of 0.3.0 Reason for change: Release of 0.3.0 Test Procedure: Verify Network and WiFi Risks: Medium Signed-off-by: Karunakaran A --- CHANGELOG.md | 8 ++++++++ CMakeLists.txt | 4 ++-- LegacyPlugin_WiFiManagerAPIs.cpp | 2 +- NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f731621cf..460e665b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,14 @@ All notable changes to this RDK Service will be documented in this file. * For more details, refer to [versioning](https://github.com/rdkcentral/rdkservices#versioning) section under Main README. +## [0.3.0] - 2024-09-16 +### Added +- Gnome Network Manager support +- Fixed the missing Error events +- Fixed activation & subscription flow +- Includes bug fixes + + ## [0.2.0] - 2024-05-27 ### Added - Restructured the NetworkManager folder organization diff --git a/CMakeLists.txt b/CMakeLists.txt index 911b2f12e..e49595609 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 2) -set(VERSION_PATCH 11) +set(VERSION_MINOR 3) +set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) add_compile_definitions(NETWORKMANAGER_MINOR_VERSION=${VERSION_MINOR}) diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index 19cbb0e7d..52201892f 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -552,7 +552,7 @@ namespace WPEFramework } } else - NMLOG_ERROR("m_subsWiFiStateChange is null"); + NMLOG_ERROR("m_networkmanager is null"); if (m_subsWiFiStateChange && m_subsAvailableSSIDs && m_subsWiFiStrengthChange) { diff --git a/NetworkManager.json b/NetworkManager.json index ed0bfba18..4fe9faf4a 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -8,7 +8,7 @@ "locator": "libWPEFrameworkNetworkManager.so", "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", - "version": "0.2.11" + "version": "0.3.0" }, "common": { "$ref": "../../common/common.json" diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 14060d40b..2073468ea 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: [0.2.11]()** +**Version: [0.3.0]()** A NetworkManager plugin for Thunder framework. From 9a242047f231bf8eaebd60a0d1e59a3cb8a251f7 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Wed, 18 Sep 2024 15:48:54 -0400 Subject: [PATCH 013/271] DELIA-66318 : Update NetworkManager Plugin Reason for change: Use of SmartLinkType Use IPluginImpl to release ComRPC instance upon Deactivate Setup Startup Order to ensure NetworkManager is up before legacy plugins are activated Test Procedure: Full Networking Verification Risks: Low Signed-off-by: Karunakaran A --- CMakeLists.txt | 5 ++ LegacyPlugin_NetworkAPIs.conf.in | 1 + LegacyPlugin_NetworkAPIs.config | 1 + LegacyPlugin_NetworkAPIs.cpp | 19 +--- LegacyPlugin_NetworkAPIs.h | 3 +- LegacyPlugin_WiFiManagerAPIs.conf.in | 1 + LegacyPlugin_WiFiManagerAPIs.config | 1 + LegacyPlugin_WiFiManagerAPIs.cpp | 19 +--- LegacyPlugin_WiFiManagerAPIs.h | 3 +- NetworkManager.conf.in | 2 +- NetworkManager.config | 2 +- NetworkManager.cpp | 44 ++++++--- NetworkManager.h | 5 +- NetworkManagerJsonRpc.cpp | 128 +++++++++++++-------------- 14 files changed, 117 insertions(+), 117 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e49595609..edb86edad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,11 @@ set(PLUGIN_LEGACY_DEPRECATED_WIFI ${NAMESPACE}WiFiManager) find_package(${NAMESPACE}Core REQUIRED) find_package(${NAMESPACE}Plugins REQUIRED) find_package(CURL) + +set(PLUGIN_NETWORKMANAGER_STARTUPORDER "55" CACHE STRING "To configure startup order of Unified NetworkManager plugin") +set(PLUGIN_LEGACY_NW_STARTUPORDER "56" CACHE STRING "To configure startup order of Legacy Network plugin") +set(PLUGIN_LEGACY_WIFI_STARTUPORDER "56" CACHE STRING "To configure startup order of Legacy WiFi plugin") + if(ENABLE_GNOME_NETWORKMANAGER) pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(LIBNM REQUIRED libnm) diff --git a/LegacyPlugin_NetworkAPIs.conf.in b/LegacyPlugin_NetworkAPIs.conf.in index 0519daf3d..c9e5db2c5 100644 --- a/LegacyPlugin_NetworkAPIs.conf.in +++ b/LegacyPlugin_NetworkAPIs.conf.in @@ -1,3 +1,4 @@ precondition = ["Platform"] callsign = "org.rdk.Network" autostart = "true" +startuporder = "@PLUGIN_LEGACY_NW_STARTUPORDER@" diff --git a/LegacyPlugin_NetworkAPIs.config b/LegacyPlugin_NetworkAPIs.config index fcec1be20..74572ce99 100644 --- a/LegacyPlugin_NetworkAPIs.config +++ b/LegacyPlugin_NetworkAPIs.config @@ -1,3 +1,4 @@ set (autostart true) set (preconditions Platform) set (callsign "org.rdk.Network") +set (startuporder ${PLUGIN_LEGACY_NW_STARTUPORDER}) diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index bcabd3883..9e689769a 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -152,9 +152,9 @@ namespace WPEFramework } Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); - m_networkmanager = make_shared >(_T(NETWORK_MANAGER_CALLSIGN), _T(NETWORK_MANAGER_CALLSIGN), false, query); + m_networkmanager = make_shared >(_T(NETWORK_MANAGER_CALLSIGN), _T("org.rdk.Network"), query); - doTheSubscriptions(); + subscribeToEvents(); return string(); } @@ -787,21 +787,6 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { } /** Private */ - void Network::doTheSubscriptions(void) - { - uint32_t result = Core::ERROR_ASYNC_FAILED; - Core::Event event(false, true); - Core::IWorkerPool::Instance().Submit(Core::ProxyType(Core::ProxyType::Create([&]() { - NMLOG_INFO ("Start Subscription %s", __FUNCTION__); - subscribeToEvents(); - m_timer.start(SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS); - event.SetEvent(); - }))); - event.Lock(); - - return; - } - void Network::subscribeToEvents(void) { uint32_t errCode = Core::ERROR_GENERAL; diff --git a/LegacyPlugin_NetworkAPIs.h b/LegacyPlugin_NetworkAPIs.h index dfadc062d..bbaa7eefb 100644 --- a/LegacyPlugin_NetworkAPIs.h +++ b/LegacyPlugin_NetworkAPIs.h @@ -31,7 +31,6 @@ namespace WPEFramework { void registerLegacyMethods(void); void unregisterLegacyMethods(void); void subscribeToEvents(void); - void doTheSubscriptions(void); static std::string getInterfaceMapping(const std::string &interface); void activatePrimaryPlugin(); @@ -83,7 +82,7 @@ namespace WPEFramework { private: PluginHost::IShell* m_service; - std::shared_ptr> m_networkmanager; + std::shared_ptr> m_networkmanager; string m_defaultInterface; NetworkManagerTimer m_timer; diff --git a/LegacyPlugin_WiFiManagerAPIs.conf.in b/LegacyPlugin_WiFiManagerAPIs.conf.in index 090ef0da5..80e3c699c 100644 --- a/LegacyPlugin_WiFiManagerAPIs.conf.in +++ b/LegacyPlugin_WiFiManagerAPIs.conf.in @@ -1,3 +1,4 @@ precondition = ["Platform"] callsign = "org.rdk.Wifi" autostart = "true" +startuporder = "@PLUGIN_LEGACY_WIFI_STARTUPORDER@" diff --git a/LegacyPlugin_WiFiManagerAPIs.config b/LegacyPlugin_WiFiManagerAPIs.config index 3428986fd..13a832da9 100644 --- a/LegacyPlugin_WiFiManagerAPIs.config +++ b/LegacyPlugin_WiFiManagerAPIs.config @@ -1,3 +1,4 @@ set (autostart true) set (preconditions Platform) set (callsign "org.rdk.Wifi") +set (startuporder ${PLUGIN_LEGACY_WIFI_STARTUPORDER}) diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index 52201892f..0aa9596ca 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -148,9 +148,9 @@ namespace WPEFramework } Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); - m_networkmanager = make_shared >(_T(NETWORK_MANAGER_CALLSIGN), _T(NETWORK_MANAGER_CALLSIGN), false, query); + m_networkmanager = make_shared >(_T(NETWORK_MANAGER_CALLSIGN), _T("org.rdk.Wifi"), query); - doTheSubscriptions(); + subscribeToEvents(); return string(); } @@ -504,21 +504,6 @@ namespace WPEFramework } /** Private */ - void WiFiManager::doTheSubscriptions(void) - { - uint32_t result = Core::ERROR_ASYNC_FAILED; - Core::Event event(false, true); - Core::IWorkerPool::Instance().Submit(Core::ProxyType(Core::ProxyType::Create([&]() { - NMLOG_INFO ("Start Subscription %s", __FUNCTION__); - subscribeToEvents(); - m_timer.start(SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS); - event.SetEvent(); - }))); - event.Lock(); - - return; - } - void WiFiManager::subscribeToEvents(void) { uint32_t errCode = Core::ERROR_GENERAL; diff --git a/LegacyPlugin_WiFiManagerAPIs.h b/LegacyPlugin_WiFiManagerAPIs.h index e455916d4..c4545d500 100644 --- a/LegacyPlugin_WiFiManagerAPIs.h +++ b/LegacyPlugin_WiFiManagerAPIs.h @@ -99,14 +99,13 @@ namespace WPEFramework { void registerLegacyMethods(void); void unregisterLegacyMethods(void); void subscribeToEvents(void); - void doTheSubscriptions(void); static std::string getInterfaceMapping(const std::string &interface); static bool ErrorCodeMapping(const uint32_t ipvalue , uint32_t &opvalue); void activatePrimaryPlugin(); private: PluginHost::IShell* m_service; - std::shared_ptr> m_networkmanager; + std::shared_ptr> m_networkmanager; NetworkManagerTimer m_timer; bool m_subsWiFiStateChange; bool m_subsAvailableSSIDs; diff --git a/NetworkManager.conf.in b/NetworkManager.conf.in index 22fca875b..cbfc0e53c 100644 --- a/NetworkManager.conf.in +++ b/NetworkManager.conf.in @@ -1,5 +1,5 @@ -autostart = "true" callsign= "org.rdk.NetworkManager" +startuporder = "@PLUGIN_NETWORKMANAGER_STARTUPORDER@" process= JSON() process.add("outofprocess", "true") diff --git a/NetworkManager.config b/NetworkManager.config index c11c09bd3..0019947d0 100644 --- a/NetworkManager.config +++ b/NetworkManager.config @@ -1,5 +1,5 @@ -set(autostart true) set(callsign "org.rdk.NetworkManager") +set (startuporder ${PLUGIN_NETWORKMANAGER_STARTUPORDER}) map() key(root) diff --git a/NetworkManager.cpp b/NetworkManager.cpp index 47a93053d..c7d57b870 100644 --- a/NetworkManager.cpp +++ b/NetworkManager.cpp @@ -39,7 +39,8 @@ namespace WPEFramework NetworkManager::NetworkManager() : _connectionId(0), _service(nullptr), - _NetworkManager(nullptr), + _networkManagerImpl(nullptr), + _networkManager(nullptr), _notification(this) { // Don't do any work in the constructor - all set up should be done in Initialize @@ -63,7 +64,7 @@ namespace WPEFramework { // Make sure everything is null as we expect ASSERT(_service == nullptr); - ASSERT(_NetworkManager == nullptr); + ASSERT(_networkManager == nullptr); // Syslog Startup messages are always printed by default SYSLOG(Logging::Startup, (_T("Initializing NetworkManager"))); @@ -81,20 +82,23 @@ namespace WPEFramework // // Ideally for large, complex plugins we would actually split the plugin into two libraries - a thin library that just calls // _service->Root to launch WPEProcess, and a larger library that is only ever run inside WPEProcess only (we do this for Cobalt and WebKitBrowser) - _NetworkManager = service->Root(_connectionId, 25000, _T("NetworkManagerImplementation")); + _networkManager = service->Root(_connectionId, 25000, _T("NetworkManagerImplementation")); // Still running inside the main WPEFramework process - the child process will have now been spawned and registered if necessary - if (_NetworkManager != nullptr) + if (_networkManager != nullptr) { // set the plugin configuration Exchange::INetworkManager::NMLogging _loglevel; - _NetworkManager->Configure(_service->ConfigLine(), _loglevel); + _networkManager->Configure(_service->ConfigLine(), _loglevel); // configure loglevel in libWPEFrameworkNetworkManager.so NetworkManagerLogger::SetLevel(static_cast (_loglevel)); - _NetworkManager->Register(&_notification); + _networkManager->Register(&_notification); // Register all custom JSON-RPC methods RegisterAllMethods(); + + // Get IPlugin interface for this plugin + _networkManagerImpl = _networkManager->QueryInterface(); } else { @@ -119,26 +123,44 @@ namespace WPEFramework void NetworkManager::Deinitialize(PluginHost::IShell *service) { ASSERT(_service == service); - ASSERT(_NetworkManager != nullptr); + ASSERT(_networkManager != nullptr); TRACE(Trace::Information, (_T("Deinitializing NetworkManager"))); TRACE(Trace::Information, (_T("Deinitialize running in process %d"), Core::ProcessInfo().Id())); - if (_NetworkManager != nullptr) + if (_networkManager != nullptr) { // TODO:: Work out exactly what triggers the shutdown of the out-of-process host _service->Unregister(&_notification); - _NetworkManager->Unregister(&_notification); + _networkManager->Unregister(&_notification); // Unregister all our JSON-RPC methods UnregisterAllMethods(); - _NetworkManager->Release(); + + // Release the IPlugin + if(_networkManagerImpl) + { + _networkManagerImpl->Release(); + _networkManagerImpl = nullptr; + } + + RPC::IRemoteConnection* connection = service->RemoteConnection(_connectionId); + _networkManager->Release(); + if (connection != nullptr) { + // Lets trigger the cleanup sequence for + // out-of-process code. Which will guard + // that unwilling processes, get shot if + // not stopped friendly :-) + connection->Terminate(); + connection->Release(); + } } // Set everything back to default _connectionId = 0; _service = nullptr; - _NetworkManager = nullptr; + _networkManagerImpl = nullptr; + _networkManager = nullptr; } string NetworkManager::Information() const diff --git a/NetworkManager.h b/NetworkManager.h index ddac4b759..ce4771cf2 100644 --- a/NetworkManager.h +++ b/NetworkManager.h @@ -247,7 +247,7 @@ namespace WPEFramework // find the real implementation // This allows other components to call QueryInterface() and // receive the actual implementation (which could be in-process or out-of-process) - INTERFACE_AGGREGATE(Exchange::INetworkManager, _NetworkManager) + INTERFACE_AGGREGATE(Exchange::INetworkManager, _networkManager) END_INTERFACE_MAP /* @@ -311,7 +311,8 @@ namespace WPEFramework private: uint32_t _connectionId; PluginHost::IShell *_service; - Exchange::INetworkManager *_NetworkManager; + PluginHost::IPlugin* _networkManagerImpl; + Exchange::INetworkManager *_networkManager; Core::Sink _notification; string m_publicIPAddress; string m_defaultInterface; diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index e5996a42c..ba156d301 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -125,8 +125,8 @@ namespace WPEFramework NetworkManagerLogger::SetLevel(level); const Exchange::INetworkManager::NMLogging log = static_cast (level); - if (_NetworkManager) - rc = _NetworkManager->SetLogLevel(log); + if (_networkManager) + rc = _networkManager->SetLogLevel(log); else rc = Core::ERROR_UNAVAILABLE; } @@ -144,8 +144,8 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::IInterfaceDetailsIterator* interfaces = NULL; - if (_NetworkManager) - rc = _NetworkManager->GetAvailableInterfaces(interfaces); + if (_networkManager) + rc = _networkManager->GetAvailableInterfaces(interfaces); else rc = Core::ERROR_UNAVAILABLE; @@ -179,8 +179,8 @@ namespace WPEFramework LOGINFOMETHOD(); uint32_t rc = Core::ERROR_GENERAL; string interface; - if (_NetworkManager) - rc = _NetworkManager->GetPrimaryInterface(interface); + if (_networkManager) + rc = _networkManager->GetPrimaryInterface(interface); else rc = Core::ERROR_UNAVAILABLE; @@ -206,8 +206,8 @@ namespace WPEFramework return rc; } - if (_NetworkManager) - rc = _NetworkManager->SetPrimaryInterface(interface); + if (_networkManager) + rc = _networkManager->SetPrimaryInterface(interface); else rc = Core::ERROR_UNAVAILABLE; @@ -232,8 +232,8 @@ namespace WPEFramework return rc; } - if (_NetworkManager) - rc = _NetworkManager->SetInterfaceState(interface, enabled); + if (_networkManager) + rc = _networkManager->SetInterfaceState(interface, enabled); else rc = Core::ERROR_UNAVAILABLE; @@ -258,8 +258,8 @@ namespace WPEFramework return rc; } - if (_NetworkManager) - rc = _NetworkManager->GetInterfaceState(interface, isEnabled); + if (_networkManager) + rc = _networkManager->GetInterfaceState(interface, isEnabled); else rc = Core::ERROR_UNAVAILABLE; @@ -291,8 +291,8 @@ namespace WPEFramework return rc; } - if (_NetworkManager) - rc = _NetworkManager->GetIPSettings(interface, ipversion, result); + if (_networkManager) + rc = _networkManager->GetIPSettings(interface, ipversion, result); else rc = Core::ERROR_UNAVAILABLE; @@ -349,8 +349,8 @@ namespace WPEFramework result.m_secondaryDns = parameters["secondarydns"]; } - if (_NetworkManager) - rc = _NetworkManager->SetIPSettings(interface, ipversion, result); + if (_networkManager) + rc = _networkManager->SetIPSettings(interface, ipversion, result); else rc = Core::ERROR_UNAVAILABLE; @@ -371,8 +371,8 @@ namespace WPEFramework uint32_t bindTimeout; uint32_t cacheTimeout; - if (_NetworkManager) - rc = _NetworkManager->GetStunEndpoint(endPoint, port, bindTimeout, cacheTimeout); + if (_networkManager) + rc = _networkManager->GetStunEndpoint(endPoint, port, bindTimeout, cacheTimeout); else rc = Core::ERROR_UNAVAILABLE; @@ -397,8 +397,8 @@ namespace WPEFramework uint32_t bindTimeout = parameters["bindTimeout"].Number(); uint32_t cacheTimeout = parameters["cacheTimeout"].Number(); - if (_NetworkManager) - rc = _NetworkManager->SetStunEndpoint(endPoint, port, bindTimeout, cacheTimeout); + if (_networkManager) + rc = _networkManager->SetStunEndpoint(endPoint, port, bindTimeout, cacheTimeout); else rc = Core::ERROR_UNAVAILABLE; @@ -417,8 +417,8 @@ namespace WPEFramework Exchange::INetworkManager::IStringIterator* endpoints = NULL; - if (_NetworkManager) - rc = _NetworkManager->GetConnectivityTestEndpoints(endpoints); + if (_networkManager) + rc = _networkManager->GetConnectivityTestEndpoints(endpoints); else rc = Core::ERROR_UNAVAILABLE; @@ -470,8 +470,8 @@ namespace WPEFramework } endpointsIter = (Core::Service::Create(endpoints)); - if (_NetworkManager) - rc = _NetworkManager->SetConnectivityTestEndpoints(endpointsIter); + if (_networkManager) + rc = _networkManager->SetConnectivityTestEndpoints(endpointsIter); else rc = Core::ERROR_UNAVAILABLE; @@ -495,8 +495,8 @@ namespace WPEFramework Exchange::INetworkManager::InternetStatus result; - if (_NetworkManager) - rc = _NetworkManager->IsConnectedToInternet(ipversion, result); + if (_networkManager) + rc = _networkManager->IsConnectedToInternet(ipversion, result); else rc = Core::ERROR_UNAVAILABLE; @@ -533,8 +533,8 @@ namespace WPEFramework LOGINFOMETHOD(); uint32_t rc = Core::ERROR_GENERAL; string endPoint; - if (_NetworkManager) - rc = _NetworkManager->GetCaptivePortalURI(endPoint); + if (_networkManager) + rc = _networkManager->GetCaptivePortalURI(endPoint); else rc = Core::ERROR_UNAVAILABLE; @@ -554,8 +554,8 @@ namespace WPEFramework uint32_t interval = parameters["interval"].Number(); NMLOG_TRACE("connectivity interval = %d", interval); - if (_NetworkManager) - rc = _NetworkManager->StartConnectivityMonitoring(interval); + if (_networkManager) + rc = _networkManager->StartConnectivityMonitoring(interval); else rc = Core::ERROR_UNAVAILABLE; @@ -572,8 +572,8 @@ namespace WPEFramework LOGINFOMETHOD(); uint32_t rc = Core::ERROR_GENERAL; - if (_NetworkManager) - rc = _NetworkManager->StopConnectivityMonitoring(); + if (_networkManager) + rc = _networkManager->StopConnectivityMonitoring(); else rc = Core::ERROR_UNAVAILABLE; @@ -601,8 +601,8 @@ namespace WPEFramework } else { - if (_NetworkManager) - rc = _NetworkManager->GetPublicIP(ipversion, ipAddress); + if (_networkManager) + rc = _networkManager->GetPublicIP(ipversion, ipAddress); else rc = Core::ERROR_UNAVAILABLE; } @@ -675,8 +675,8 @@ namespace WPEFramework if (parameters.HasLabel("guid")) guid = parameters["guid"].String(); - if (_NetworkManager) - rc = _NetworkManager->Ping(ipversion, endpoint, noOfRequest, timeOutInSeconds, guid, result); + if (_networkManager) + rc = _networkManager->Ping(ipversion, endpoint, noOfRequest, timeOutInSeconds, guid, result); else rc = Core::ERROR_UNAVAILABLE; } @@ -701,8 +701,8 @@ namespace WPEFramework const uint32_t noOfRequest = parameters["packets"].Number(); const string guid = parameters["guid"].String(); - if (_NetworkManager) - rc = _NetworkManager->Trace(ipversion, endpoint, noOfRequest, guid, result); + if (_networkManager) + rc = _networkManager->Trace(ipversion, endpoint, noOfRequest, guid, result); else rc = Core::ERROR_UNAVAILABLE; @@ -723,8 +723,8 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; const Exchange::INetworkManager::WiFiFrequency frequency = static_cast (parameters["frequency"].Number()); - if (_NetworkManager) - rc = _NetworkManager->StartWiFiScan(frequency); + if (_networkManager) + rc = _networkManager->StartWiFiScan(frequency); else rc = Core::ERROR_UNAVAILABLE; @@ -741,8 +741,8 @@ namespace WPEFramework LOGINFOMETHOD(); uint32_t rc = Core::ERROR_GENERAL; - if (_NetworkManager) - rc = _NetworkManager->StopWiFiScan(); + if (_networkManager) + rc = _networkManager->StopWiFiScan(); else rc = Core::ERROR_UNAVAILABLE; @@ -762,8 +762,8 @@ namespace WPEFramework JsonArray ssids; ::WPEFramework::RPC::IIteratorType* _ssids{}; - if (_NetworkManager) - rc = _NetworkManager->GetKnownSSIDs(_ssids); + if (_networkManager) + rc = _networkManager->GetKnownSSIDs(_ssids); if (Core::ERROR_NONE == rc) { @@ -797,8 +797,8 @@ namespace WPEFramework ssid.m_passphrase = parameters["passphrase"].String(); ssid.m_securityMode = static_cast (parameters["securityMode"].Number()); - if (_NetworkManager) - rc = _NetworkManager->AddToKnownSSIDs(ssid); + if (_networkManager) + rc = _networkManager->AddToKnownSSIDs(ssid); else rc = Core::ERROR_UNAVAILABLE; } @@ -820,8 +820,8 @@ namespace WPEFramework if (parameters.HasLabel("ssid")) { ssid = parameters["ssid"].String(); - if (_NetworkManager) - rc = _NetworkManager->RemoveKnownSSID(ssid); + if (_networkManager) + rc = _networkManager->RemoveKnownSSID(ssid); else rc = Core::ERROR_UNAVAILABLE; } @@ -861,8 +861,8 @@ namespace WPEFramework ssid.m_persistSSIDInfo = parameters["persistSSIDInfo"].Boolean(); else ssid.m_persistSSIDInfo = true; - if (_NetworkManager) - rc = _NetworkManager->WiFiConnect(ssid); + if (_networkManager) + rc = _networkManager->WiFiConnect(ssid); else rc = Core::ERROR_UNAVAILABLE; @@ -879,8 +879,8 @@ namespace WPEFramework LOGINFOMETHOD(); uint32_t rc = Core::ERROR_GENERAL; - if (_NetworkManager) - rc = _NetworkManager->WiFiDisconnect(); + if (_networkManager) + rc = _networkManager->WiFiDisconnect(); else rc = Core::ERROR_UNAVAILABLE; @@ -898,8 +898,8 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; - if (_NetworkManager) - rc = _NetworkManager->GetConnectedSSID(ssidInfo); + if (_networkManager) + rc = _networkManager->GetConnectedSSID(ssidInfo); else rc = Core::ERROR_UNAVAILABLE; @@ -937,8 +937,8 @@ namespace WPEFramework wps_pin = parameters["wps_pin"].String(); } - if (_NetworkManager) - rc = _NetworkManager->StartWPS(method, wps_pin); + if (_networkManager) + rc = _networkManager->StartWPS(method, wps_pin); else rc = Core::ERROR_UNAVAILABLE; @@ -955,8 +955,8 @@ namespace WPEFramework LOGINFOMETHOD(); uint32_t rc = Core::ERROR_GENERAL; - if (_NetworkManager) - rc = _NetworkManager->StopWPS(); + if (_networkManager) + rc = _networkManager->StopWPS(); else rc = Core::ERROR_UNAVAILABLE; @@ -974,8 +974,8 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; LOGINFOMETHOD(); - if (_NetworkManager) - rc = _NetworkManager->GetWifiState(state); + if (_networkManager) + rc = _networkManager->GetWifiState(state); else rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) @@ -995,8 +995,8 @@ namespace WPEFramework string signalStrength{}; Exchange::INetworkManager::WiFiSignalQuality quality; - if (_NetworkManager) - rc = _NetworkManager->GetWiFiSignalStrength(ssid, signalStrength, quality); + if (_networkManager) + rc = _networkManager->GetWiFiSignalStrength(ssid, signalStrength, quality); else rc = Core::ERROR_UNAVAILABLE; @@ -1017,8 +1017,8 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::ISecurityModeIterator* securityModes{}; - if (_NetworkManager) - rc = _NetworkManager->GetSupportedSecurityModes(securityModes); + if (_networkManager) + rc = _networkManager->GetSupportedSecurityModes(securityModes); else rc = Core::ERROR_UNAVAILABLE; From 1bffddfb02832d48ea17b3206dd9d53673696097 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:07:12 -0400 Subject: [PATCH 014/271] Merge pull request #7 from karuna2git/develop DELIA-66318 : Update NetworkManager Plugin From e903929e671a2b846e21c93653a77eeac2e05606 Mon Sep 17 00:00:00 2001 From: Gururaaja E S R Date: Thu, 19 Sep 2024 20:35:42 +0000 Subject: [PATCH 015/271] XIONE-15762 - [RDKE] [Xione]- Jumpserver access fails Reason for change: In the input of getIPsettings, NULL is being passed for interface. Allowing null interface also Test Procedure: NA Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR --- NetworkManagerJsonRpc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index ba156d301..4d2883caa 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -285,7 +285,7 @@ namespace WPEFramework if (parameters.HasLabel("ipversion")) ipversion = parameters["ipversion"].String(); - if ("wlan0" != interface && "eth0" != interface) + if ("wlan0" != interface && "eth0" != interface && "" != interface) { rc = Core::ERROR_BAD_REQUEST; return rc; From 58b4320a8b0a39e7e603d0f7ae064a1d05de44b6 Mon Sep 17 00:00:00 2001 From: Gururaaja E S R Date: Thu, 19 Sep 2024 20:37:24 +0000 Subject: [PATCH 016/271] Merge branch 'develop' of github.com:gururaajar/networkmanager into develop From 512b0e87b0a5ed42504573caa5119a0764021e9e Mon Sep 17 00:00:00 2001 From: Gururaaja E S R Date: Thu, 19 Sep 2024 20:37:24 +0000 Subject: [PATCH 017/271] Merge branch 'develop' of github.com:gururaajar/networkmanager into develop --- NetworkManagerJsonRpc.cpp | 2 +- docs/NetworkManagerPlugin.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 4d2883caa..c4ada38e7 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -285,7 +285,7 @@ namespace WPEFramework if (parameters.HasLabel("ipversion")) ipversion = parameters["ipversion"].String(); - if ("wlan0" != interface && "eth0" != interface && "" != interface) + if (!interface.empty() && ("wlan0" != interface) && ("eth0" != interface)) { rc = Core::ERROR_BAD_REQUEST; return rc; diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 2073468ea..ba8ef05a8 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -367,7 +367,7 @@ No Events | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | +| params.interface | string | *(optional)* An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface. If this is empty, default interface will be returned | | params?.ipversion | string | *(optional)* either IPv4 or IPv6 | ### Result From d185d1eb89bc5476fa16171cb8dbcb74759c795e Mon Sep 17 00:00:00 2001 From: Gururaaja E S R Date: Thu, 19 Sep 2024 20:47:02 +0000 Subject: [PATCH 018/271] Merge branch 'develop' of github.com:gururaajar/networkmanager into develop From ec74ceefd59c1f140b738b5e9928885f518b5662 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Thu, 19 Sep 2024 16:50:04 -0400 Subject: [PATCH 019/271] Merge pull request #8 from gururaajar/develop RDKTV-33219, XIONE-15762 - [RDKE] GetIPSettings without input arg is failing From b05e31b882b1edef11dc1e0f7f79d53d652f270c Mon Sep 17 00:00:00 2001 From: parvathika <131966254+parvathika@users.noreply.github.com> Date: Tue, 24 Sep 2024 20:41:01 +0530 Subject: [PATCH 020/271] work flow test initial commit (#10) Co-authored-by: rafi --- .github/workflows/gnome_unit_test.yml | 105 +++++++++++++++++++++++ .github/workflows/rdk_unit_test.yml | 118 ++++++++++++++++++++++++++ Tests/mocks/Iarm.h | 30 +++++++ 3 files changed, 253 insertions(+) create mode 100644 .github/workflows/gnome_unit_test.yml create mode 100644 .github/workflows/rdk_unit_test.yml create mode 100644 Tests/mocks/Iarm.h diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml new file mode 100644 index 000000000..6934e5528 --- /dev/null +++ b/.github/workflows/gnome_unit_test.yml @@ -0,0 +1,105 @@ +name: gnome_unit_test + +on: + push: + branches: [ main, develop, 'release/**'] + pull_request: + branches: [ main, develop, 'release/**'] + +env: + THUNDER_REF: "R4.4.1" + +jobs: + unit-tests: + name: Build and run unit tests + runs-on: ubuntu-latest + + steps: + - name: Configure cache + if: ${{ !env.ACT }} + id: cache + uses: actions/cache@v3 + with: + path: | + build/Thunder + build/ThunderInterfaces + build/ThunderTools + install + !install/etc/WPEFramework/plugins + !install/usr/lib/wpeframework/plugins + key: ${{ runner.os }}-${{ env.THUNDER_REF }} + + - name: Install packages + run: | + sudo apt update + sudo apt-get install -y pkg-config libglib2.0-dev libnm-dev libcurl4-openssl-dev ninja-build + + - name: Configure Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + - run: pip install jsonref + + - name: Configure CMake + uses: jwlawson/actions-setup-cmake@v1.13 + with: + cmake-version: '3.16.x' + + - name: Checkout thunder repositories + if: steps.cache.outputs.cache-hit != 'true' + run: | + git clone https://github.com/rdkcentral/ThunderTools ThunderTools --branch ${{ env.THUNDER_REF }} + git clone https://github.com/rdkcentral/Thunder Thunder --branch ${{ env.THUNDER_REF }} + git clone https://github.com/rdkcentral/ThunderInterfaces ThunderInterfaces --branch ${{ env.THUNDER_REF }} + + - name: Build ThunderTools + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake + -S "${{github.workspace}}/ThunderTools" -B build/ThunderTools + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DGENERIC_CMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + && + cmake --build build/ThunderTools --target install -j8 + + - name: Build Thunder + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake + -S "${{github.workspace}}/Thunder" -B build/Thunder + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DBUILD_TYPE=Debug + -DBINDING=127.0.0.1 + -DPORT=9998 + && + cmake --build build/Thunder --target install -j8 + + - name: Build ThunderInterfaces + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake + -S "${{github.workspace}}/ThunderInterfaces" -B build/ThunderInterfaces + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + && + cmake --build build/ThunderInterfaces --target install -j8 + + - name: Checkout networkmanager + uses: actions/checkout@v3 + with: + path: networkmanager + + - name: Build networkmanager with Gnome Proxy + run: > + cmake + -S "${{github.workspace}}/networkmanager" + -B build/GnomeNetworkmanager + -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DENABLE_GNOME_NETWORKMANAGER=ON + && + cmake --build build/GnomeNetworkmanager --target install -j8 + diff --git a/.github/workflows/rdk_unit_test.yml b/.github/workflows/rdk_unit_test.yml new file mode 100644 index 000000000..7a251b0a6 --- /dev/null +++ b/.github/workflows/rdk_unit_test.yml @@ -0,0 +1,118 @@ +name: rdk_unit_test + +on: + push: + branches: [ main, develop, 'release/**'] + pull_request: + branches: [ main, develop, 'release/**'] + +env: + THUNDER_REF: "R4.4.1" + +jobs: + unit-tests: + name: Build and run unit tests + runs-on: ubuntu-latest + + steps: + - name: Configure cache + if: ${{ !env.ACT }} + id: cache + uses: actions/cache@v3 + with: + path: | + build/Thunder + build/ThunderInterfaces + build/ThunderTools + install + !install/etc/WPEFramework/plugins + !install/usr/lib/wpeframework/plugins + key: ${{ runner.os }}-${{ env.THUNDER_REF }} + + - name: Install packages + run: | + sudo apt update + sudo apt-get install -y pkg-config libglib2.0-dev libnm-dev libcurl4-openssl-dev ninja-build + + - name: Configure Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + - run: pip install jsonref + + - name: Configure CMake + uses: jwlawson/actions-setup-cmake@v1.13 + with: + cmake-version: '3.16.x' + + - name: Checkout thunder repositories + if: steps.cache.outputs.cache-hit != 'true' + run: | + git clone https://github.com/rdkcentral/ThunderTools ThunderTools --branch ${{ env.THUNDER_REF }} + git clone https://github.com/rdkcentral/Thunder Thunder --branch ${{ env.THUNDER_REF }} + git clone https://github.com/rdkcentral/ThunderInterfaces ThunderInterfaces --branch ${{ env.THUNDER_REF }} + + - name: Build ThunderTools + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake + -S "${{github.workspace}}/ThunderTools" -B build/ThunderTools + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DGENERIC_CMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + && + cmake --build build/ThunderTools --target install -j8 + + - name: Build Thunder + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake + -S "${{github.workspace}}/Thunder" -B build/Thunder + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DBUILD_TYPE=Debug + -DBINDING=127.0.0.1 + -DPORT=9998 + && + cmake --build build/Thunder --target install -j8 + + - name: Build ThunderInterfaces + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake + -S "${{github.workspace}}/ThunderInterfaces" -B build/ThunderInterfaces + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + && + cmake --build build/ThunderInterfaces --target install -j8 + + - name: Checkout networkmanager + uses: actions/checkout@v3 + with: + path: networkmanager + + - name: Generate IARM headers + run: | + touch install/usr/lib/libIARMBus.so + mkdir -p install/usr/include/rdk/iarmbus + touch install/usr/include/rdk/iarmbus/libIARM.h + cd "${{github.workspace}}/networkmanager/Tests/" + mkdir -p headers/rdk/iarmbus + cd headers + touch rdk/iarmbus/libIARM.h rdk/iarmbus/libIBus.h + + - name: Build networkmanager with RDK Proxy + run: > + cmake + -S "${{github.workspace}}/networkmanager" + -B build/RDKNetworkmanager + -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DCMAKE_CXX_FLAGS=" + -I ${{github.workspace}}/networkmanager/Tests/headers + -I ${{github.workspace}}/networkmanager/Tests/headers/rdk/iarmbus + --include ${{github.workspace}}/networkmanager/Tests/mocks/Iarm.h + " + && + cmake --build build/RDKNetworkmanager --target install -j8 diff --git a/Tests/mocks/Iarm.h b/Tests/mocks/Iarm.h new file mode 100644 index 000000000..cf753c2b2 --- /dev/null +++ b/Tests/mocks/Iarm.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +typedef int IARM_EventId_t; + +typedef enum _IARM_Result_t { + IARM_RESULT_SUCCESS, + IARM_RESULT_INVALID_PARAM, + IARM_RESULT_INVALID_STATE, + IARM_RESULT_IPCCORE_FAIL, + IARM_RESULT_OOM, +} IARM_Result_t; + +#define IARM_BUS_DAEMON_NAME "Daemon" + +typedef IARM_Result_t (*IARM_BusCall_t)(void* arg); +typedef void (*IARM_EventHandler_t)(const char* owner, IARM_EventId_t eventId, void* data, size_t len); + +extern IARM_Result_t (*IARM_Bus_Init)(const char*); +extern IARM_Result_t (*IARM_Bus_Connect)(); +extern IARM_Result_t (*IARM_Bus_IsConnected)(const char*,int*); +extern IARM_Result_t (*IARM_Bus_RegisterEventHandler)(const char*,IARM_EventId_t,IARM_EventHandler_t); +extern IARM_Result_t (*IARM_Bus_UnRegisterEventHandler)(const char*,IARM_EventId_t); +extern IARM_Result_t (*IARM_Bus_RemoveEventHandler)(const char*,IARM_EventId_t,IARM_EventHandler_t); +extern IARM_Result_t (*IARM_Bus_Call)(const char*,const char*,void*,size_t); +extern IARM_Result_t (*IARM_Bus_BroadcastEvent)(const char *,IARM_EventId_t,void *,size_t); +extern IARM_Result_t (*IARM_Bus_RegisterCall)(const char*,IARM_BusCall_t); +extern IARM_Result_t (*IARM_Bus_Call_with_IPCTimeout)(const char*,const char*,void*,size_t,int); + From 26ec1fe48b2881d2b10248ec5b2e24da2242b11c Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Fri, 27 Sep 2024 13:31:21 -0400 Subject: [PATCH 021/271] DELIA-66407 : Add Legacy GetIPSettings2() in Unified NetworkManager Plugin (#12) Reason for change: Add Legacy GetIPSettings2() in Unified NetworkManager Plugin Test Procedure: As per DELIA-66407 Risks: Low Signed-off-by: Karunakaran A --- LegacyPlugin_NetworkAPIs.cpp | 58 +++++++++++++++++++++++++----------- LegacyPlugin_NetworkAPIs.h | 1 + NetworkManager.conf.in | 1 + NetworkManager.config | 1 + 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index 9e689769a..7ac3ca9ca 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -204,7 +204,7 @@ namespace WPEFramework Register("getCaptivePortalURI", &Network::getCaptivePortalURI, this); Register("stopConnectivityMonitoring", &Network::stopConnectivityMonitoring, this); GetHandler(2)->Register("setIPSettings", &Network::setIPSettings, this); - GetHandler(2)->Register("getIPSettings", &Network::getIPSettings, this); + GetHandler(2)->Register("getIPSettings", &Network::getIPSettings2, this); } /** @@ -436,6 +436,26 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { } uint32_t Network::getIPSettings (const JsonObject& parameters, JsonObject& response) + { + uint32_t rc = Core::ERROR_GENERAL; + JsonObject tmpResponse; + + LOGINFOMETHOD(); + rc = getIPSettings2(parameters, tmpResponse); + + if (tmpResponse.HasLabel("ipaddr")) + response = tmpResponse; + else + { + NMLOG_INFO("IP Address not assigned to the given interface yet"); + response["success"] = false; + } + + LOGTRACEMETHODFIN(); + return rc; + } + + uint32_t Network::getIPSettings2 (const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpResponse; @@ -475,31 +495,33 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { response["interface"] = "ETHERNET"; } - response["ipversion"] = tmpResponse["ipversion"]; response["autoconfig"] = tmpResponse["autoconfig"]; - response["ipaddr"] = tmpResponse["ipaddress"]; - if(tmpResponse["ipaddress"].String().empty()) - response["netmask"] = ""; - else if (caseInsensitiveCompare(ipversion, "IPV4")) - { - index = tmpResponse["prefix"].Number(); - if(CIDR_NETMASK_IP_LEN <= index) - return Core::ERROR_GENERAL; - response["netmask"] = CIDR_PREFIXES[index]; - } - else if (caseInsensitiveCompare(ipversion, "IPV6")) + if(!tmpResponse["ipaddress"].String().empty()) { - response["netmask"] = tmpResponse["prefix"]; + response["ipversion"] = tmpResponse["ipversion"]; + response["ipaddr"] = tmpResponse["ipaddress"]; + if (caseInsensitiveCompare(ipversion, "IPV4")) + { + index = tmpResponse["prefix"].Number(); + if(CIDR_NETMASK_IP_LEN <= index) + return Core::ERROR_GENERAL; + response["netmask"] = CIDR_PREFIXES[index]; + } + else if (caseInsensitiveCompare(ipversion, "IPV6")) + { + response["netmask"] = tmpResponse["prefix"]; + } + response["gateway"] = tmpResponse["gateway"]; + response["dhcpserver"] = tmpResponse["dhcpserver"]; + response["primarydns"] = tmpResponse["primarydns"]; + response["secondarydns"] = tmpResponse["secondarydns"]; } - response["gateway"] = tmpResponse["gateway"]; - response["dhcpserver"] = tmpResponse["dhcpserver"]; - response["primarydns"] = tmpResponse["primarydns"]; - response["secondarydns"] = tmpResponse["secondarydns"]; response["success"] = tmpResponse["success"]; } LOGTRACEMETHODFIN(); return rc; } + uint32_t Network::isConnectedToInternet(const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; diff --git a/LegacyPlugin_NetworkAPIs.h b/LegacyPlugin_NetworkAPIs.h index bbaa7eefb..037b91b0d 100644 --- a/LegacyPlugin_NetworkAPIs.h +++ b/LegacyPlugin_NetworkAPIs.h @@ -44,6 +44,7 @@ namespace WPEFramework { uint32_t doPing(const JsonObject& parameters, JsonObject& response); uint32_t setIPSettings(const JsonObject& parameters, JsonObject& response); uint32_t getIPSettings(const JsonObject& parameters, JsonObject& response); + uint32_t getIPSettings2(const JsonObject& parameters, JsonObject& response); uint32_t isConnectedToInternet(const JsonObject& parameters, JsonObject& response); uint32_t setConnectivityTestEndpoints(const JsonObject& parameters, JsonObject& response); uint32_t getInternetConnectionState(const JsonObject& parameters, JsonObject& response); diff --git a/NetworkManager.conf.in b/NetworkManager.conf.in index cbfc0e53c..49b18e465 100644 --- a/NetworkManager.conf.in +++ b/NetworkManager.conf.in @@ -1,5 +1,6 @@ callsign= "org.rdk.NetworkManager" startuporder = "@PLUGIN_NETWORKMANAGER_STARTUPORDER@" +autostart = "true" process= JSON() process.add("outofprocess", "true") diff --git a/NetworkManager.config b/NetworkManager.config index 0019947d0..c70241fcd 100644 --- a/NetworkManager.config +++ b/NetworkManager.config @@ -1,5 +1,6 @@ set(callsign "org.rdk.NetworkManager") set (startuporder ${PLUGIN_NETWORKMANAGER_STARTUPORDER}) +set (autostart true) map() key(root) From 91f5f4c54f59832e5fd4b27a555e2af2fa169e2a Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Fri, 27 Sep 2024 15:18:49 -0400 Subject: [PATCH 022/271] DELIA-66411 : Retry when subscription to an event failed (#13) Reason for change: In the reported ticket, it is noticed that WiFi Plugin failed to subscribe `onAvailableSSIDs` event but didnt retry. So when scan is called by application, the scan was success but it never posted any update as it never received `onAvailableSSIDs` event from unified networkmanager plugin Test Procedure: As per DELIA-66411 Risks: Medium Signed-off-by: Karunakaran A --- LegacyPlugin_NetworkAPIs.cpp | 5 +++++ LegacyPlugin_WiFiManagerAPIs.cpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index 7ac3ca9ca..482522d2a 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -864,6 +864,11 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { m_timer.stop(); NMLOG_INFO("subscriber timer stoped"); } + else + { + m_timer.start(SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS); + NMLOG_INFO("subscriber timer started"); + } } string Network::getInterfaceMapping(const string & interface) diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index 0aa9596ca..b003d60d0 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -544,6 +544,11 @@ namespace WPEFramework m_timer.stop(); NMLOG_INFO("subscriber timer stoped"); } + else + { + m_timer.start(SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS); + NMLOG_INFO("subscriber timer started"); + } } bool WiFiManager::ErrorCodeMapping(const uint32_t ipvalue, uint32_t &opvalue) From a8541e822c56eefac0bb087fe2458493bd9d2a88 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Wed, 2 Oct 2024 14:23:58 -0400 Subject: [PATCH 023/271] DELIA-66446 : Implement RDKLogger Support to NetworkManager Plugin (#14) Reason for change: Implement RDKLogger Support to NetworkManager Plugin Test Procedure: Verify logs are printed properly Risks: Low Signed-off-by: Karunakaran A --- CMakeLists.txt | 32 +++++++++++++++------- CONTRIBUTING.md | 4 +++ NetworkManagerImplementation.cpp | 4 +-- NetworkManagerLogger.cpp | 4 +-- NetworkManagerRDKProxy.cpp | 47 ++++++++++++++++---------------- README.md | 5 ++-- cmake/Findrdklogger.cmake | 38 ++++++++++++++++++++++++++ 7 files changed, 93 insertions(+), 41 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 cmake/Findrdklogger.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index edb86edad..9e55f9473 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,9 +14,10 @@ add_compile_definitions(NETWORKMANAGER_PATCH_VERSION=${VERSION_PATCH}) set(PROJECT_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) - include(CmakeHelperFunctions) +option(USE_RDK_LOGGER "Enable RDK Logger for logging" OFF ) + string(TOLOWER ${NAMESPACE} STORAGE_DIRECTORY) get_directory_property(SEVICES_DEFINES COMPILE_DEFINITIONS) @@ -60,6 +61,12 @@ message("Setup ${PROJECT_NAME} v${PROJECT_VERSION}") set(PLUGIN_NETWORKMANAGER_LOGLEVEL "5" CACHE STRING "To configure default loglevel NetworkManager plugin") +if (USE_RDK_LOGGER) + find_package(rdklogger REQUIRED) + add_definitions(-DUSE_RDK_LOGGER) + + include_directories(${RDKLOGGER_INCLUDE_DIRS}) +endif (USE_RDK_LOGGER) include_directories(${PROJECT_SOURCE_DIR}) # Build the main plugin that runs inside the WPEFramework daemon @@ -84,14 +91,6 @@ set_target_properties(${MODULE_NAME} PROPERTIES CXX_STANDARD_REQUIRED YES FRAMEWORK FALSE) -include_directories(${PROJECT_SOURCE_DIR}/interface) -include_directories(${PROJECT_SOURCE_DIR}/service) -include_directories(${PROJECT_SOURCE_DIR}/../helpers) - -install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) - - -# Build the implementation that runs out-of-process behind a COM-RPC interface if(ENABLE_GNOME_NETWORKMANAGER) target_sources(${MODULE_NAME} PRIVATE NetworkManagerGnomeProxy.cpp @@ -106,10 +105,15 @@ else() target_link_libraries(${MODULE_NAME} PRIVATE ${IARMBUS_LIBRARIES}) endif() - target_link_libraries(${MODULE_NAME} PRIVATE ${CURL_LIBRARIES}) target_include_directories(${MODULE_NAME} PRIVATE ${CURL_INCLUDE_DIRS}) +if (USE_RDK_LOGGER) + target_link_libraries(${MODULE_NAME} PRIVATE ${RDKLOGGER_LIBRARIES}) +endif (USE_RDK_LOGGER) + +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) + add_library(${PLUGIN_LEGACY_DEPRECATED_NETWORK} SHARED LegacyPlugin_NetworkAPIs.cpp NetworkManagerLogger.cpp @@ -121,6 +125,10 @@ target_link_libraries(${PLUGIN_LEGACY_DEPRECATED_NETWORK} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ) +if (USE_RDK_LOGGER) + target_link_libraries(${PLUGIN_LEGACY_DEPRECATED_NETWORK} PRIVATE ${RDKLOGGER_LIBRARIES}) +endif (USE_RDK_LOGGER) + set_target_properties(${PLUGIN_LEGACY_DEPRECATED_NETWORK} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES) @@ -138,6 +146,10 @@ target_link_libraries(${PLUGIN_LEGACY_DEPRECATED_WIFI} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ) +if (USE_RDK_LOGGER) + target_link_libraries(${PLUGIN_LEGACY_DEPRECATED_WIFI} PRIVATE ${RDKLOGGER_LIBRARIES}) +endif (USE_RDK_LOGGER) + set_target_properties(${PLUGIN_LEGACY_DEPRECATED_WIFI} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..161c09284 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,4 @@ +Contributing +============ + +If you would like to contribute code to this project you can do so through GitHub by forking the repository and sending a pull request. Before RDK accepts your code into the project you must sign the RDK Contributor License Agreement (CLA). \ No newline at end of file diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 2ae61301c..6c488573a 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -300,7 +300,7 @@ namespace WPEFramework snprintf(cmd, sizeof(cmd), "ping -c %d -W %d '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); } - NMLOG_INFO ("The Command is %s", cmd); + NMLOG_TRACE ("The Command is %s", cmd); string commandToExecute(cmd); executeExternally(NETMGR_PING, commandToExecute, response); @@ -321,7 +321,7 @@ namespace WPEFramework snprintf(cmd, 256, "traceroute -w 3 -m 6 -q %d %s 52 2>&1", noOfRequest, endpoint.c_str()); } - NMLOG_INFO ("The Command is %s", cmd); + NMLOG_TRACE ("The Command is %s", cmd); string commandToExecute(cmd); executeExternally(NETMGR_TRACE, commandToExecute, tempResult); diff --git a/NetworkManagerLogger.cpp b/NetworkManagerLogger.cpp index fe67d812f..0b118314e 100644 --- a/NetworkManagerLogger.cpp +++ b/NetworkManagerLogger.cpp @@ -34,7 +34,7 @@ #endif namespace NetworkManagerLogger { - static LogLevel gDefaultLogLevel = TRACE_LEVEL; + static LogLevel gDefaultLogLevel = INFO_LEVEL; const char* methodName(const std::string& prettyFunction) { @@ -72,7 +72,7 @@ namespace NetworkManagerLogger { } formattedLog[kFormatMessageSize - 1] = '\0'; #ifdef USE_RDK_LOGGER - RDK_LOG((int)level, "LOG.RDK.NETSRVMGER", "%s\n", formattedLog); + RDK_LOG(static_cast(level), "LOG.RDK.NETMGR", "%s\n", formattedLog); #else const char* levelMap[] = {"Fatal", "Error", "Warning", "Info", "Verbose", "Trace"}; struct timeval tv; diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 32316f398..9fd5ffdc7 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -399,8 +399,8 @@ namespace WPEFramework return Exchange::INetworkManager::WIFI_STATE_INVALID_CREDENTIALS; case WIFI_AUTH_FAILED: return Exchange::INetworkManager::WIFI_STATE_AUTHENTICATION_FAILED; - case WIFI_NO_SSID: - return Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND; + case WIFI_NO_SSID: + return Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND; case WIFI_UNKNOWN: return Exchange::INetworkManager::WIFI_STATE_ERROR; } @@ -818,10 +818,10 @@ namespace WPEFramework strncpy(iarmData.ipversion, ipversion.c_str(), 16); iarmData.isSupported = true; - NMLOG_INFO("NetworkManagerImplementation::GetIPSettings - Before Calling IARM"); + if (IARM_RESULT_SUCCESS == IARM_Bus_Call (IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_getIPSettings, (void *)&iarmData, sizeof(iarmData))) { - NMLOG_INFO("NetworkManagerImplementation::GetIPSettings - IARM Success.. Filling the data"); + NMLOG_TRACE("NetworkManagerImplementation::GetIPSettings - IARM Success.. Filling the data"); result.m_ipAddrType = string(iarmData.ipversion); result.m_autoConfig = iarmData.autoconfig; result.m_dhcpServer = string(iarmData.dhcpserver,MAX_IP_ADDRESS_LEN - 1); @@ -829,12 +829,11 @@ namespace WPEFramework result.m_ipAddress = string(iarmData.ipaddress,MAX_IP_ADDRESS_LEN - 1); if (0 == strcasecmp("ipv4", iarmData.ipversion)) result.m_prefix = NetmaskToPrefix(iarmData.netmask); - else if (0 == strcasecmp("ipv6", iarmData.ipversion)) + else if (0 == strcasecmp("ipv6", iarmData.ipversion)) result.m_prefix = std::atoi(iarmData.netmask); result.m_gateway = string(iarmData.gateway,MAX_IP_ADDRESS_LEN - 1); result.m_primaryDns = string(iarmData.primarydns,MAX_IP_ADDRESS_LEN - 1); result.m_secondaryDns = string(iarmData.secondarydns,MAX_IP_ADDRESS_LEN - 1); - NMLOG_INFO("NetworkManagerImplementation::GetIPSettings - IARM Success.. Filled the data"); rc = Core::ERROR_NONE; } else @@ -1214,36 +1213,36 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { signalStrength = ssidInfo.m_signalStrength; if (!signalStrength.empty()) - { + { signalStrengthOut = std::stof(signalStrength.c_str()); - NMLOG_INFO ("WiFiSignalStrength in dB = %s",signalStrengthOut); - } + NMLOG_INFO ("WiFiSignalStrength in dB = %s",signalStrengthOut); + } if (signalStrengthOut == 0) - { + { quality = WIFI_SIGNAL_DISCONNECTED; - signalStrength = "0"; - } + signalStrength = "0"; + } else if (signalStrengthOut >= signalStrengthThresholdExcellent && signalStrengthOut < 0) - { + { quality = WIFI_SIGNAL_EXCELLENT; - signalStrength = "100"; - } + signalStrength = "100"; + } else if (signalStrengthOut >= signalStrengthThresholdGood && signalStrengthOut < signalStrengthThresholdExcellent) - { + { quality = WIFI_SIGNAL_GOOD; - signalStrength = "75"; - } + signalStrength = "75"; + } else if (signalStrengthOut >= signalStrengthThresholdFair && signalStrengthOut < signalStrengthThresholdGood) - { + { quality = WIFI_SIGNAL_FAIR; - signalStrength = "50"; - } + signalStrength = "50"; + } else - { + { quality = WIFI_SIGNAL_WEAK; - signalStrength = "25"; - } + signalStrength = "25"; + } NMLOG_INFO ("GetWiFiSignalStrength success"); rc = Core::ERROR_NONE; diff --git a/README.md b/README.md index e7138355f..dbe077017 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,8 @@ The documentation for legacy [Network](https://github.com/rdkcentral/rdkservices ## Release ## There are 2 active branches namely `develop` and `main`. As the name conveys, `develop` branch is for active development and for contributions. -The Plugin workflow verifies every PR and also the team verifies the plugin on the RPi and RDK Device +The Plugin workflow verifies every PR and also the team verifies the plugin on the RPi and RDK Device. The verified changes are taken to `main` branch and releases will be made from there ## Questions? ## -If you have any questions or concerns reach out to [Jacob Gladish](mailto:Jacob_Gladish@cable.comcast.com) - and [Karunakaran Amirthalingam](mailto:karunakaran_amirthalingam@comcast.com). +If you have any questions or concerns reach out to [Jacob Gladish](mailto:Jacob_Gladish@cable.comcast.com) and [Karunakaran Amirthalingam](mailto:karunakaran_amirthalingam@comcast.com). diff --git a/cmake/Findrdklogger.cmake b/cmake/Findrdklogger.cmake new file mode 100644 index 000000000..3e08fb53d --- /dev/null +++ b/cmake/Findrdklogger.cmake @@ -0,0 +1,38 @@ +############################################################################# +# If not stated otherwise in this file or this component's Licenses.txt file +# the following copyright and licenses apply: +# +# Copyright 2016 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# + +find_package(PkgConfig) + +find_library(RDKLOGGER_LIBRARIES NAMES rdkloggers) +find_path(RDKLOGGER_INCLUDE_DIRS NAMES rdk_debug.h) + +set(RDKLOGGER_LIBRARIES ${RDKLOGGER_LIBRARIES} CACHE PATH "Path to rdkLogger library") +set(RDKLOGGER_INCLUDE_DIRS ${RDKLOGGER_INCLUDE_DIRS} ) +set(RDKLOGGER_INCLUDE_DIRS ${RDKLOGGER_INCLUDE_DIRS} CACHE PATH "Path to rdkLogger include") + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(RDKLOGGER DEFAULT_MSG RDKLOGGER_INCLUDE_DIRS RDKLOGGER_LIBRARIES) + +mark_as_advanced( + RDKLOGGER_FOUND + RDKLOGGER_INCLUDE_DIRS + RDKLOGGER_LIBRARIES + RDKLOGGER_LIBRARY_DIRS + RDKLOGGER_FLAGS) From be6a61d597dcd24f55ea24916fb40c369ced6305 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Thu, 3 Oct 2024 16:13:38 -0400 Subject: [PATCH 024/271] DELIA-66446 : Implement RDKLogger Support to NetworkManager Plugin Reason for change: Additional Changes to support RDKLogger Test Procedure: Verify logs are printed properly Risks: Low Signed-off-by: Karunakaran A --- INetworkManager.h | 3 +- LegacyPlugin_NetworkAPIs.cpp | 106 +++++++++++----------- LegacyPlugin_WiFiManagerAPIs.cpp | 66 +++++++------- NetworkManagerConnectivity.cpp | 14 ++- NetworkManagerGnomeEvents.cpp | 24 ++--- NetworkManagerGnomeProxy.cpp | 16 ++-- NetworkManagerGnomeUtils.cpp | 10 +-- NetworkManagerGnomeWIFI.cpp | 76 ++++++++-------- NetworkManagerImplementation.cpp | 24 ++--- NetworkManagerImplementation.h | 2 +- NetworkManagerJsonRpc.cpp | 145 ++++++++++++++++--------------- NetworkManagerLogger.cpp | 33 ++++++- NetworkManagerLogger.h | 7 +- NetworkManagerRDKProxy.cpp | 3 +- WiFiSignalStrengthMonitor.cpp | 4 +- 15 files changed, 278 insertions(+), 255 deletions(-) diff --git a/INetworkManager.h b/INetworkManager.h index 4e8ebe8d6..f50c6296d 100644 --- a/INetworkManager.h +++ b/INetworkManager.h @@ -167,8 +167,7 @@ namespace WPEFramework LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, LOG_LEVEL_INFO, - LOG_LEVEL_VERBOSE, - LOG_LEVEL_TRACE + LOG_LEVEL_DEBUG }; // The state of the interface diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index 482522d2a..d380f4e0f 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -29,8 +29,8 @@ using namespace WPEFramework::Plugin; #define SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS 500 #define DEFAULT_PING_PACKETS 15 -#define LOGINFOMETHOD() { string json; parameters.ToString(json); NMLOG_TRACE("Legacy params=%s", json.c_str() ); } -#define LOGTRACEMETHODFIN() { string json; response.ToString(json); NMLOG_TRACE("Legacy response=%s", json.c_str() ); } +#define LOG_INPARAM() { string json; parameters.ToString(json); NMLOG_INFO("%s : params=%s", __FUNCTION__, json.c_str() ); } +#define LOG_OUTPARAM() { string json; response.ToString(json); NMLOG_INFO("%s : response=%s", __FUNCTION__, json.c_str() ); } namespace WPEFramework { @@ -123,7 +123,7 @@ namespace WPEFramework reinterpret_cast(payload.c_str()), token) == Core::ERROR_NONE) { - NMLOG_TRACE("Network plugin got security token"); + NMLOG_DEBUG("Network plugin got security token"); } else { NMLOG_WARNING("Network plugin failed to get security token"); } @@ -278,7 +278,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { JsonObject tmpResponse; JsonArray array; - LOGINFOMETHOD(); + LOG_INPARAM(); if (m_networkmanager) rc = m_networkmanager->Invoke(5000, _T("GetAvailableInterfaces"), parameters, tmpResponse); @@ -303,13 +303,13 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { response["interfaces"] = array; response["success"] = tmpResponse["success"]; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t Network::setStunEndPoint(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpParameters; tmpParameters["endPoint"] = parameters["server"]; @@ -322,7 +322,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -332,7 +332,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { string interface; JsonObject tmpParameters; - LOGINFOMETHOD(); + LOG_INPARAM(); if(caseInsensitiveCompare(parameters["interface"].String(),"WIFI")) interface = "wlan0"; else if(caseInsensitiveCompare(parameters["interface"].String(), "ETHERNET")) @@ -348,7 +348,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -357,7 +357,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpResponse; - LOGINFOMETHOD(); + LOG_INPARAM(); if (m_networkmanager) rc = m_networkmanager->Invoke(5000, _T("GetPrimaryInterface"), parameters, tmpResponse); @@ -372,7 +372,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { response["interface"] = "ETHERNET"; response["success"] = tmpResponse["success"]; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -381,7 +381,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpParameters; string interface; - LOGINFOMETHOD(); + LOG_INPARAM(); if(caseInsensitiveCompare(parameters["interface"].String(), "WIFI")) tmpParameters["interface"] = "wlan0"; else if(caseInsensitiveCompare(parameters["interface"].String(), "ETHERNET")) @@ -392,7 +392,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -402,7 +402,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpResponse; JsonObject tmpParameters; - LOGINFOMETHOD(); + LOG_INPARAM(); if(caseInsensitiveCompare(parameters["interface"].String(), "WIFI")) tmpParameters["interface"] = "wlan0"; @@ -431,7 +431,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { response["supported"] = true; response["success"] = tmpResponse["success"]; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -440,7 +440,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpResponse; - LOGINFOMETHOD(); + LOG_INPARAM(); rc = getIPSettings2(parameters, tmpResponse); if (tmpResponse.HasLabel("ipaddr")) @@ -451,7 +451,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { response["success"] = false; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -462,7 +462,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { JsonObject tmpParameters; size_t index; - LOGINFOMETHOD(); + LOG_INPARAM(); if (parameters.HasLabel("ipversion")) tmpParameters["ipversion"] = parameters["ipversion"]; @@ -518,7 +518,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { } response["success"] = tmpResponse["success"]; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -527,7 +527,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpResponse; - LOGINFOMETHOD(); + LOG_INPARAM(); string ipversion = parameters["ipversion"].String(); if (m_networkmanager) @@ -542,7 +542,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { response["ipversion"] = ipversion.c_str(); response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t Network::getInternetConnectionState(const JsonObject& parameters, JsonObject& response) @@ -555,7 +555,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { JsonObject tmpParameters; string status; - LOGINFOMETHOD(); + LOG_INPARAM(); string ipversion = parameters["ipversion"].String(); if (m_networkmanager) @@ -566,8 +566,8 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { if (Core::ERROR_NONE == rc) { status = tmpResponse["status"].String(); - NMLOG_TRACE("status = %s", status.c_str() ); - NMLOG_TRACE("tmpResponse[status].String() = %s", tmpResponse["status"].String().c_str() ); + NMLOG_DEBUG("status = %s", status.c_str() ); + NMLOG_DEBUG("tmpResponse[status].String() = %s", tmpResponse["status"].String().c_str() ); if(status == "LIMITED_INTERNET") response["state"] = static_cast(2); else if(status == "CAPTIVE_PORTAL") @@ -586,7 +586,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { response["ipversion"] = ipversion.c_str(); response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t Network::doPing(const JsonObject& parameters, JsonObject& response) @@ -598,7 +598,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { JsonObject tmpResponse; string endpoint{}; - LOGINFOMETHOD(); + LOG_INPARAM(); endpoint = parameters["endpoint"].String(); @@ -625,13 +625,13 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { response["target"] = parameters["endpoint"]; response["guid"] = parameters["guid"]; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t Network::doTrace(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpParameters; tmpParameters["endpoint"] = parameters["endpoint"].String(); @@ -643,7 +643,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -655,7 +655,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { JsonObject tmpParameters; JsonObject tmpResponse; - LOGINFOMETHOD(); + LOG_INPARAM(); if(caseInsensitiveCompare(parameters["iface"].String(), "WIFI")) interface = "wlan0"; else if(caseInsensitiveCompare(parameters["iface"].String(), "ETHERNET")) @@ -679,7 +679,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { response["public_ip"] = tmpResponse["publicIP"]; response["success"] = tmpResponse["success"]; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -688,7 +688,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpParameters; - LOGINFOMETHOD(); + LOG_INPARAM(); string interface = parameters["interface"].String(); string newInterface = ""; @@ -704,44 +704,44 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t Network::setConnectivityTestEndpoints(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; if (m_networkmanager) rc = m_networkmanager->Invoke(5000, _T("SetConnectivityTestEndpoints"), parameters, response); else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t Network::startConnectivityMonitoring(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; uint32_t interval = parameters["interval"].Number(); - NMLOG_TRACE("connectivity interval = %d", interval); + NMLOG_DEBUG("connectivity interval = %d", interval); if (m_networkmanager) rc = m_networkmanager->Invoke(5000, _T("StartConnectivityMonitoring"), parameters, response); else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t Network::getCaptivePortalURI(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string endPoint; if (m_networkmanager) @@ -749,13 +749,13 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t Network::stopConnectivityMonitoring(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; if (m_networkmanager) @@ -763,14 +763,14 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t Network::getStbIp(const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; - LOGTRACEMETHODFIN(); + LOG_INPARAM(); JsonObject tmpResponse; if (m_networkmanager) @@ -783,13 +783,14 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { response["ip"] = tmpResponse["ipaddress"]; response["success"] = true; } + LOG_OUTPARAM(); return rc; } uint32_t Network::getSTBIPFamily(const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; - LOGTRACEMETHODFIN(); + LOG_INPARAM(); JsonObject tmpResponse; JsonObject tmpParameters; @@ -805,6 +806,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { response["ip"] = tmpResponse["ipaddress"]; response["success"] = true; } + LOG_OUTPARAM(); return rc; } @@ -883,7 +885,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { /** Event Handling and Publishing */ void Network::ReportonInterfaceStateChange(const JsonObject& parameters) { - LOGINFOMETHOD(); + LOG_INPARAM(); JsonObject legacyParams; string json; string state = parameters["state"].String(); @@ -916,7 +918,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { void Network::ReportonActiveInterfaceChange(const JsonObject& parameters) { - LOGINFOMETHOD(); + LOG_INPARAM(); JsonObject legacyParams; legacyParams["oldInterfaceName"] = getInterfaceMapping(parameters["oldInterfaceName"].String()); @@ -930,19 +932,17 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { void Network::ReportonIPAddressChange(const JsonObject& parameters) { - LOGINFOMETHOD(); + LOG_INPARAM(); JsonObject legacyParams; legacyParams["interface"] = getInterfaceMapping(parameters["interface"].String()); if (parameters["isIPv6"].Boolean()) { legacyParams["ip6Address"] = parameters["ipAddress"]; - legacyParams["ip4Address"] = ""; } else { legacyParams["ip4Address"] = parameters["ipAddress"]; - legacyParams["ip6Address"] = ""; } legacyParams["status"] = parameters["status"]; @@ -964,7 +964,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { void Network::onInterfaceStateChange(const JsonObject& parameters) { - LOGINFOMETHOD(); + LOG_INPARAM(); if(_gNWInstance) _gNWInstance->ReportonInterfaceStateChange(parameters); @@ -973,7 +973,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { void Network::onActiveInterfaceChange(const JsonObject& parameters) { - LOGINFOMETHOD(); + LOG_INPARAM(); if(_gNWInstance) _gNWInstance->ReportonActiveInterfaceChange(parameters); return; @@ -981,7 +981,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { void Network::onIPAddressChange(const JsonObject& parameters) { - LOGINFOMETHOD(); + LOG_INPARAM(); if(_gNWInstance) _gNWInstance->ReportonIPAddressChange(parameters); return; @@ -989,7 +989,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { void Network::onInternetStatusChange(const JsonObject& parameters) { - LOGINFOMETHOD(); + LOG_INPARAM(); if(_gNWInstance) _gNWInstance->ReportonInternetStatusChange(parameters); } diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index b003d60d0..ac2872432 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -28,8 +28,8 @@ using namespace WPEFramework::Plugin; #define NETWORK_MANAGER_CALLSIGN "org.rdk.NetworkManager.1" #define SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS 500 -#define LOGINFOMETHOD() { string json; parameters.ToString(json); NMLOG_TRACE("Legacy params=%s", json.c_str() ); } -#define LOGTRACEMETHODFIN() { string json; response.ToString(json); NMLOG_TRACE("Legacy response=%s", json.c_str() ); } +#define LOG_INPARAM() { string json; parameters.ToString(json); NMLOG_INFO("%s : params=%s", __FUNCTION__, json.c_str() ); } +#define LOG_OUTPARAM() { string json; response.ToString(json); NMLOG_INFO("%s : response=%s", __FUNCTION__, json.c_str() ); } namespace WPEFramework { @@ -120,7 +120,7 @@ namespace WPEFramework reinterpret_cast(payload.c_str()), token) == Core::ERROR_NONE) { - NMLOG_TRACE("WiFi manager plugin got security token"); + NMLOG_DEBUG("WiFi manager plugin got security token"); } else { NMLOG_WARNING("WiFi manager plugin failed to get security token"); } @@ -221,7 +221,7 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; - LOGINFOMETHOD(); + LOG_INPARAM(); if (m_networkmanager) rc = m_networkmanager->Invoke(5000, _T("StopWPS"), parameters, response); @@ -233,7 +233,7 @@ namespace WPEFramework response["result"] = string(); } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -243,7 +243,7 @@ namespace WPEFramework JsonObject tmpParameters; tmpParameters["ssid"] = "ssid"; // The input ssid name does not matter at this point in time as there is only one ssid persisted at any given point in time. - LOGINFOMETHOD(); + LOG_INPARAM(); if (m_networkmanager) rc = m_networkmanager->Invoke(5000, _T("RemoveKnownSSID"), tmpParameters, response); @@ -255,13 +255,13 @@ namespace WPEFramework response["result"] = 0; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t WiFiManager::connect(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; if (m_networkmanager) @@ -273,7 +273,7 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -282,7 +282,7 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpResponse; - LOGINFOMETHOD(); + LOG_INPARAM(); if (m_networkmanager) rc = m_networkmanager->Invoke(5000, _T("GetConnectedSSID"), parameters, tmpResponse); @@ -300,7 +300,7 @@ namespace WPEFramework response["frequency"] = tmpResponse["frequency"]; response["success"] = tmpResponse["success"]; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -313,13 +313,13 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t WiFiManager::getPairedSSID(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpResponse; @@ -339,13 +339,13 @@ namespace WPEFramework } response["success"] = tmpResponse["success"]; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t WiFiManager::getPairedSSIDInfo(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; if (m_networkmanager) @@ -353,13 +353,13 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t WiFiManager::getSupportedSecurityModes(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; if (m_networkmanager) @@ -367,14 +367,14 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t WiFiManager::isPaired (const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; - LOGINFOMETHOD(); + LOG_INPARAM(); JsonObject tmpResponse; rc = getPairedSSID(parameters, tmpResponse); @@ -392,7 +392,7 @@ namespace WPEFramework } response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -400,7 +400,7 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; - LOGINFOMETHOD(); + LOG_INPARAM(); if (m_networkmanager) rc = m_networkmanager->Invoke(5000, _T("AddToKnownSSIDs"), parameters, response); @@ -412,7 +412,7 @@ namespace WPEFramework response["result"] = 0; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -420,7 +420,7 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; - LOGINFOMETHOD(); + LOG_INPARAM(); if (m_networkmanager) rc = m_networkmanager->Invoke(5000, _T("WiFiDisconnect"), parameters, response); @@ -432,7 +432,7 @@ namespace WPEFramework response["result"] = 0; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -440,7 +440,7 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpParameters; - LOGINFOMETHOD(); + LOG_INPARAM(); if (parameters.HasLabel("method")) { string method = parameters["method"].String(); @@ -470,13 +470,13 @@ namespace WPEFramework { response["result"] = string(); } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t WiFiManager::startScan(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpParameters; @@ -485,13 +485,13 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t WiFiManager::stopScan(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; if (m_networkmanager) @@ -499,7 +499,7 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -591,7 +591,7 @@ namespace WPEFramework /** Event Handling and Publishing */ void WiFiManager::onWiFiStateChange(const JsonObject& parameters) { - LOGINFOMETHOD(); + LOG_INPARAM(); JsonObject legacyResult; JsonObject legacyErrorResult; uint32_t errorCode; @@ -621,7 +621,7 @@ namespace WPEFramework void WiFiManager::onAvailableSSIDs(const JsonObject& parameters) { - LOGINFOMETHOD(); + LOG_INPARAM(); NMLOG_INFO("Posting onAvailableSSIDs"); if(_gWiFiInstance) @@ -632,7 +632,7 @@ namespace WPEFramework void WiFiManager::onWiFiSignalStrengthChange(const JsonObject& parameters) { - LOGINFOMETHOD(); + LOG_INPARAM(); JsonObject legacyParams; legacyParams["signalStrength"] = parameters["signalQuality"]; legacyParams["strength"] = parameters["signalLevel"]; diff --git a/NetworkManagerConnectivity.cpp b/NetworkManagerConnectivity.cpp index e75334de3..e9cacd976 100644 --- a/NetworkManagerConnectivity.cpp +++ b/NetworkManagerConnectivity.cpp @@ -151,7 +151,6 @@ namespace WPEFramework curl_easy_setopt(curl_easy_handle, CURLOPT_USERAGENT, "RDKCaptiveCheck/1.0"); if(!headReq) { - // NMLOG_TRACE("curlopt get request"); /* HTTPGET request added insted of HTTPHEAD request fix for DELIA-61526 */ curl_easy_setopt(curl_easy_handle, CURLOPT_HTTPGET, 1L); } @@ -198,10 +197,9 @@ namespace WPEFramework if (CURLE_OK == msg->data.result) { if (curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &response_code) == CURLE_OK) { - //NMLOG_TRACE("endpoint = <%s> http response code <%d>", endpoint, static_cast(response_code)); if (HttpStatus_302_Found == response_code) { if ( (curl_easy_getinfo(msg->easy_handle, CURLINFO_REDIRECT_URL, &url) == CURLE_OK) && url != nullptr) { - NMLOG_TRACE("captive portal found !!!"); + NMLOG_INFO("captive portal found !!!"); captivePortalURI = url; } } @@ -239,7 +237,7 @@ namespace WPEFramework } if(curlVerboseEnabled()) { - NMLOG_TRACE("endpoints count = %d response count %d, handles = %d, deadline = %ld, time_now = %ld, time_earlier = %ld", + NMLOG_DEBUG("endpoints count = %d response count %d, handles = %d, deadline = %ld, time_now = %ld, time_earlier = %ld", static_cast(endpoints.size()), static_cast(http_responses.size()), handles, deadline, time_now, time_earlier); } @@ -481,7 +479,7 @@ namespace WPEFramework if (doConnectivityMonitor) { cvConnectivityMonitor.notify_one(); - NMLOG_TRACE("trigger connectivity monitor thread"); + NMLOG_DEBUG("trigger connectivity monitor thread"); return true; } @@ -526,7 +524,7 @@ namespace WPEFramework { if(doConnectivityMonitor) { - NMLOG_TRACE("connectivity monitor running so skiping ccm check"); + NMLOG_DEBUG("connectivity monitor running so skiping ccm check"); gIpv4InternetState = UNKNOWN; gIpv6InternetState = UNKNOWN; std::unique_lock lock(connMutex); @@ -621,7 +619,7 @@ namespace WPEFramework gIpv4InternetState = UNKNOWN; gIpv6InternetState = UNKNOWN; - NMLOG_TRACE("continous connectivity monitor exit"); + NMLOG_DEBUG("continous connectivity monitor exit"); } void ConnectivityMonitor::connectivityMonitorFunction() @@ -720,7 +718,7 @@ namespace WPEFramework if(!doContinuousMonitor) gInternetState = nsm_internetState::UNKNOWN; // no continous monitor running reset to unknow - NMLOG_TRACE("initial connectivity monitor exit"); + NMLOG_DEBUG("initial connectivity monitor exit"); } } // namespace Plugin diff --git a/NetworkManagerGnomeEvents.cpp b/NetworkManagerGnomeEvents.cpp index 6afd4f73e..b7f170627 100644 --- a/NetworkManagerGnomeEvents.cpp +++ b/NetworkManagerGnomeEvents.cpp @@ -80,7 +80,7 @@ namespace WPEFramework } NMDeviceStateReason reason = nm_device_get_state_reason(device); std::string wifiState; - // NMLOG_TRACE("\033[0;31m NMDeviceStateReason %d \033[0m",reason); + // NMLOG_DEBUG("\033[0;31m NMDeviceStateReason %d \033[0m",reason); switch (reason) { case NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE: @@ -157,7 +157,7 @@ namespace WPEFramework } } } - NMLOG_TRACE("wifi state: %s", wifiState.c_str()); + NMLOG_DEBUG("wifi state: %s", wifiState.c_str()); } else if(ifname == nmEvents->ifnameEth0) { @@ -185,7 +185,7 @@ namespace WPEFramework } } - NMLOG_TRACE("%s state: (%d)", ifname.c_str(), deviceState); + NMLOG_DEBUG("%s state: (%d)", ifname.c_str(), deviceState); } @@ -295,7 +295,7 @@ namespace WPEFramework } } else - NMLOG_TRACE("device error null"); + NMLOG_DEBUG("device error null"); } static void deviceRemovedCB(NMClient *client, NMDevice *device, NMEvents *nmEvents) @@ -330,7 +330,7 @@ namespace WPEFramework NMLOG_WARNING("internet connection down"); break; case NM_STATE_CONNECTED_GLOBAL: - NMLOG_TRACE("global internet connection success"); + NMLOG_DEBUG("global internet connection success"); break; default: break; @@ -393,7 +393,7 @@ namespace WPEFramework } } else - NMLOG_TRACE("device type not eth/wifi"); + NMLOG_DEBUG("device type not eth/wifi"); } } @@ -405,7 +405,7 @@ namespace WPEFramework bool GnomeNetworkManagerEvents::startNetworkMangerEventMonitor() { - NMLOG_TRACE("starting gnome event monitor"); + NMLOG_DEBUG("starting gnome event monitor"); if (NULL == nmEvents.client) { NMLOG_ERROR("Client Connection NULL DBUS event Failed!"); return false; @@ -452,7 +452,7 @@ namespace WPEFramework GnomeNetworkManagerEvents::GnomeNetworkManagerEvents() { - NMLOG_TRACE("GnomeNetworkManagerEvents"); + NMLOG_DEBUG("GnomeNetworkManagerEvents"); std::string wifiInterface = "wlan0", ethernetInterface = "eth0"; if(!nmUtils::GetInterfacesName(wifiInterface, ethernetInterface)) { @@ -523,7 +523,7 @@ namespace WPEFramework default: state = "Unknown"; } - NMLOG_TRACE("%s interface state changed - %s", iface.c_str(), state.c_str()); + NMLOG_DEBUG("%s interface state changed - %s", iface.c_str(), state.c_str()); if(_instance != nullptr && (iface == _nmEventInstance->nmEvents.ifnameWlan0 || iface == _nmEventInstance->nmEvents.ifnameEth0)) _instance->ReportInterfaceStateChangedEvent(static_cast(newState), iface); } @@ -570,7 +570,7 @@ namespace WPEFramework void GnomeNetworkManagerEvents::onAvailableSSIDsCb(NMDeviceWifi *wifiDevice, GParamSpec *pspec, gpointer userData) { - NMLOG_TRACE("wifi scanning completed ..."); + NMLOG_DEBUG("wifi scanning completed ..."); if(!NM_IS_DEVICE_WIFI(wifiDevice)) { NMLOG_ERROR("Not a wifi object "); @@ -592,7 +592,7 @@ namespace WPEFramework if(_nmEventInstance->debugLogs) { _nmEventInstance->debugLogs = false; NMLOG_INFO("Number of Access Points Available = %d", static_cast(accessPoints->len)); - NMLOG_TRACE("Scanned APIs are = %s",ssidListJson.c_str()); + NMLOG_DEBUG("Scanned APIs are = %s",ssidListJson.c_str()); } if(_nmEventInstance->doScanNotify) { @@ -606,7 +606,7 @@ namespace WPEFramework doScanNotify.store(doNotify); if(!doScanNotify) { - NMLOG_TRACE("stop periodic wifi scan result notify"); + NMLOG_DEBUG("stop periodic wifi scan result notify"); } debugLogs = enableLogs; } diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index 5104d2ee6..f069bc946 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -34,7 +34,7 @@ namespace WPEFramework // initialize the NMClient object client = nm_client_new(NULL, &error); if (client == NULL) { - NMLOG_TRACE("Error initializing NMClient: %s", error->message); + NMLOG_DEBUG("Error initializing NMClient: %s", error->message); g_error_free(error); return; } @@ -125,7 +125,7 @@ namespace WPEFramework interface = ifacePtr; if(interface != "eth0" && interface != "wlan0") { - NMLOG_TRACE("interface name is unknow"); + NMLOG_DEBUG("interface name is unknow"); interface.clear(); } else @@ -250,7 +250,7 @@ namespace WPEFramework if (g_strcmp0(name, interface.c_str()) == 0) { nm_device_set_managed(device, false); - NMLOG_TRACE("Interface %s status set to disabled", + NMLOG_DEBUG("Interface %s status set to disabled", interface.c_str()); } } @@ -388,7 +388,7 @@ namespace WPEFramework for (i = 0; i < p->len; i++) { a = static_cast(p->pdata[i]); result.m_ipAddress = nm_ip_address_get_address(a); - NMLOG_TRACE("\tinet6 %s/%d\n", nm_ip_address_get_address(a), nm_ip_address_get_prefix(a)); + NMLOG_DEBUG("\tinet6 %s/%d\n", nm_ip_address_get_address(a), nm_ip_address_get_prefix(a)); } gateway = nm_ip_config_get_gateway(ip6_config); @@ -421,10 +421,10 @@ namespace WPEFramework // Check if the operation was successful if (!nm_client_deactivate_connection_finish(NM_CLIENT(source_object), res, &error)) { - NMLOG_TRACE("Deactivating connection failed: %s", error->message); + NMLOG_DEBUG("Deactivating connection failed: %s", error->message); g_error_free(error); } else { - NMLOG_TRACE("Deactivating connection successful"); + NMLOG_DEBUG("Deactivating connection successful"); } } @@ -434,10 +434,10 @@ namespace WPEFramework // Check if the operation was successful if (!nm_client_activate_connection_finish(NM_CLIENT(source_object), res, &error)) { - NMLOG_TRACE("Activating connection failed: %s", error->message); + NMLOG_DEBUG("Activating connection failed: %s", error->message); g_error_free(error); } else { - NMLOG_TRACE("Activating connection successful"); + NMLOG_DEBUG("Activating connection successful"); } g_main_loop_quit((GMainLoop*)user_data); diff --git a/NetworkManagerGnomeUtils.cpp b/NetworkManagerGnomeUtils.cpp index 8e611b0da..e5368393b 100644 --- a/NetworkManagerGnomeUtils.cpp +++ b/NetworkManagerGnomeUtils.cpp @@ -73,19 +73,19 @@ namespace WPEFramework switch(flags) { case NM_802_11_AP_FLAGS_NONE: - NMLOG_TRACE("ap type : point has no special capabilities"); + NMLOG_DEBUG("ap type : point has no special capabilities"); break; case NM_802_11_AP_FLAGS_PRIVACY: - NMLOG_TRACE("ap type : access point requires authentication and encryption"); + NMLOG_DEBUG("ap type : access point requires authentication and encryption"); break; case NM_802_11_AP_FLAGS_WPS: - NMLOG_TRACE("ap type : access point supports some WPS method"); + NMLOG_DEBUG("ap type : access point supports some WPS method"); break; case NM_802_11_AP_FLAGS_WPS_PBC: - NMLOG_TRACE("ap type : access point supports push-button WPS"); + NMLOG_DEBUG("ap type : access point supports push-button WPS"); break; case NM_802_11_AP_FLAGS_WPS_PIN: - NMLOG_TRACE("ap type : access point supports PIN-based WPS"); + NMLOG_DEBUG("ap type : access point supports PIN-based WPS"); break; default: NMLOG_ERROR("ap type : 802.11 flags unknown!"); diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 4d45820d0..497f567cd 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -121,7 +121,7 @@ namespace WPEFramework if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_WIFI) { wifiDevice = device; - //NMLOG_TRACE("Wireless Device found ifce : %s !", nm_device_get_iface (wifiDevice)); + //NMLOG_DEBUG("Wireless Device found ifce : %s !", nm_device_get_iface (wifiDevice)); break; } } @@ -204,37 +204,37 @@ namespace WPEFramework else { wifiInfo.m_ssid = "-----"; - NMLOG_TRACE("ssid: %s", wifiInfo.m_ssid.c_str()); + NMLOG_DEBUG("ssid: %s", wifiInfo.m_ssid.c_str()); } wifiInfo.m_bssid = (hwaddr != nullptr) ? hwaddr : "-----"; - NMLOG_TRACE("bssid: %s", wifiInfo.m_bssid.c_str()); + NMLOG_DEBUG("bssid: %s", wifiInfo.m_bssid.c_str()); if (freq >= 2400 && freq < 5000) { wifiInfo.m_frequency = Exchange::INetworkManager::WiFiFrequency::WIFI_FREQUENCY_2_4_GHZ; - NMLOG_TRACE("freq: WIFI_FREQUENCY_2_4_GHZ"); + NMLOG_DEBUG("freq: WIFI_FREQUENCY_2_4_GHZ"); } else if (freq >= 5000 && freq < 6000) { wifiInfo.m_frequency = Exchange::INetworkManager::WiFiFrequency::WIFI_FREQUENCY_5_GHZ; - NMLOG_TRACE("freq: WIFI_FREQUENCY_5_GHZ"); + NMLOG_DEBUG("freq: WIFI_FREQUENCY_5_GHZ"); } else if (freq >= 6000) { wifiInfo.m_frequency = Exchange::INetworkManager::WiFiFrequency::WIFI_FREQUENCY_6_GHZ; - NMLOG_TRACE("freq: WIFI_FREQUENCY_6_GHZ"); + NMLOG_DEBUG("freq: WIFI_FREQUENCY_6_GHZ"); } else { wifiInfo.m_frequency = Exchange::INetworkManager::WiFiFrequency::WIFI_FREQUENCY_WHATEVER; - NMLOG_TRACE("freq: No available !"); + NMLOG_DEBUG("freq: No available !"); } wifiInfo.m_rate = std::to_string(bitrate); - NMLOG_TRACE("bitrate : %s kbit/s", wifiInfo.m_rate.c_str()); + NMLOG_DEBUG("bitrate : %s kbit/s", wifiInfo.m_rate.c_str()); //TODO signal strenght to dBm wifiInfo.m_signalStrength = std::to_string(static_cast(strength)); - NMLOG_TRACE("sterngth: %s %%", wifiInfo.m_signalStrength.c_str()); + NMLOG_DEBUG("sterngth: %s %%", wifiInfo.m_signalStrength.c_str()); wifiInfo.m_securityMode = static_cast(nmUtils::wifiSecurityModeFromAp(flags, wpaFlags, rsnFlags)); - NMLOG_TRACE("security %s", nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); - NMLOG_TRACE("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); + NMLOG_DEBUG("security %s", nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); + NMLOG_DEBUG("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); } bool wifiManager::isWifiConnected() @@ -244,7 +244,7 @@ namespace WPEFramework NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getNmDevice()); if(wifiDevice == NULL) { - NMLOG_TRACE("NMDeviceWifi * NULL !"); + NMLOG_DEBUG("NMDeviceWifi * NULL !"); return false; } @@ -254,7 +254,7 @@ namespace WPEFramework return false; } else - NMLOG_TRACE("active access point found !"); + NMLOG_DEBUG("active access point found !"); return true; } @@ -265,7 +265,7 @@ namespace WPEFramework NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getNmDevice()); if(wifiDevice == NULL) { - NMLOG_TRACE("NMDeviceWifi * NULL !"); + NMLOG_DEBUG("NMDeviceWifi * NULL !"); return false; } @@ -275,7 +275,7 @@ namespace WPEFramework return false; } else - NMLOG_TRACE("active access point found !"); + NMLOG_DEBUG("active access point found !"); getApInfo(activeAP, ssidinfo); return true; @@ -287,7 +287,7 @@ namespace WPEFramework GError *error = NULL; wifiManager *_wifiManager = (static_cast(user_data)); - NMLOG_TRACE("Disconnecting... "); + NMLOG_DEBUG("Disconnecting... "); _wifiManager->isSuccess = true; if (!nm_device_disconnect_finish(device, result, &error)) { if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -311,13 +311,13 @@ namespace WPEFramework NMDevice *wifiNMDevice = getNmDevice(); if(wifiNMDevice == NULL) { - NMLOG_TRACE("NMDeviceWifi NULL !"); + NMLOG_DEBUG("NMDeviceWifi NULL !"); return false; } nm_device_disconnect_async(wifiNMDevice, NULL, wifiDisconnectCb, this); wait(loop); - NMLOG_TRACE("Exit"); + NMLOG_DEBUG("Exit"); return isSuccess; } @@ -338,7 +338,7 @@ namespace WPEFramework const guint8 *ssidData = static_cast(g_bytes_get_data(ssidGBytes, &size)); std::string ssidstr(reinterpret_cast(ssidData), size); //g_bytes_unref(ssidGBytes); - // NMLOG_TRACE("ssid < %s >", ssidstr.c_str()); + // NMLOG_DEBUG("ssid < %s >", ssidstr.c_str()); if (strcmp(ssid, ssidstr.c_str()) == 0) { AccessPoint = candidate_ap; @@ -356,12 +356,12 @@ namespace WPEFramework wifiManager *_wifiManager = (static_cast(user_data)); if (_wifiManager->createNewConnection) { - NMLOG_TRACE("nm_client_add_and_activate_connection_finish"); + NMLOG_DEBUG("nm_client_add_and_activate_connection_finish"); nm_client_add_and_activate_connection_finish(NM_CLIENT(_wifiManager->client), result, &error); _wifiManager->isSuccess = true; } else { - NMLOG_TRACE("nm_client_activate_connection_finish "); + NMLOG_DEBUG("nm_client_activate_connection_finish "); nm_client_activate_connection_finish(NM_CLIENT(_wifiManager->client), result, &error); _wifiManager->isSuccess = true; } @@ -447,7 +447,7 @@ namespace WPEFramework NMLOG_WARNING("wifi already connected with %s AP", activeSSID.c_str()); } } - //NMLOG_TRACE("Wireless Device found ifce : %s !", ifname = nm_device_get_iface(device)); + //NMLOG_DEBUG("Wireless Device found ifce : %s !", ifname = nm_device_get_iface(device)); AccessPoint = checkSSIDAvailable(device, allaps, ssid_in); // TODO Scann hidden ssid also for lnf if(AccessPoint == NULL) { @@ -473,7 +473,7 @@ namespace WPEFramework if (nm_access_point_connection_valid(AccessPoint, NM_CONNECTION(currentConnection))) { connection = g_object_ref(currentConnection); - NMLOG_TRACE("Connection '%s' exists !", conName); + NMLOG_DEBUG("Connection '%s' exists !", conName); break; } } @@ -487,7 +487,7 @@ namespace WPEFramework if (!connection) { - NMLOG_TRACE("creating new connection '%s' ", conName); + NMLOG_DEBUG("creating new connection '%s' ", conName); connection = nm_simple_connection_new(); if (conName) { sConnection = (NMSettingConnection *) nm_setting_connection_new(); @@ -542,11 +542,11 @@ namespace WPEFramework GError *error = NULL; NMLOG_INFO("Ap securtity mode is 802.1X"); - NMLOG_TRACE("802.1x Identity : %s", wifiData.m_identity.c_str()); - NMLOG_TRACE("802.1x CA cert path : %s", wifiData.m_caCert.c_str()); - NMLOG_TRACE("802.1x Client cert path : %s", wifiData.m_clientCert.c_str()); - NMLOG_TRACE("802.1x Private key path : %s", wifiData.m_privateKey.c_str()); - NMLOG_TRACE("802.1x Private key psswd : %s", wifiData.m_privateKeyPasswd.c_str()); + NMLOG_DEBUG("802.1x Identity : %s", wifiData.m_identity.c_str()); + NMLOG_DEBUG("802.1x CA cert path : %s", wifiData.m_caCert.c_str()); + NMLOG_DEBUG("802.1x Client cert path : %s", wifiData.m_clientCert.c_str()); + NMLOG_DEBUG("802.1x Private key path : %s", wifiData.m_privateKey.c_str()); + NMLOG_DEBUG("802.1x Private key psswd : %s", wifiData.m_privateKeyPasswd.c_str()); s8021X = (NMSetting8021x *) nm_setting_802_1x_new(); nm_connection_add_setting(connection, NM_SETTING(s8021X)); @@ -665,7 +665,7 @@ namespace WPEFramework } else { - NMLOG_TRACE ("AddToKnownSSIDs is success"); + NMLOG_DEBUG ("AddToKnownSSIDs is success"); _wifiManager->isSuccess = true; } @@ -829,7 +829,7 @@ namespace WPEFramework } if (!ssids.empty()) { - NMLOG_TRACE("known wifi connections are %s", ssidPrint.c_str()); + NMLOG_DEBUG("known wifi connections are %s", ssidPrint.c_str()); return true; } @@ -841,7 +841,7 @@ namespace WPEFramework GError *error = NULL; wifiManager *_wifiManager = (static_cast(user_data)); if(nm_device_wifi_request_scan_finish(NM_DEVICE_WIFI(object), result, &error)) { - NMLOG_TRACE("Scanning success"); + NMLOG_DEBUG("Scanning success"); _wifiManager->isSuccess = true; } else @@ -864,7 +864,7 @@ namespace WPEFramework return false; NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getNmDevice()); if(wifiDevice == NULL) { - NMLOG_TRACE("NMDeviceWifi * NULL !"); + NMLOG_DEBUG("NMDeviceWifi * NULL !"); return false; } isSuccess = false; @@ -884,7 +884,7 @@ namespace WPEFramework nm_device_wifi_request_scan_options_async(wifiDevice, options, NULL, wifiScanCb, this); } else { - NMLOG_TRACE("staring normal wifi scanning"); + NMLOG_DEBUG("staring normal wifi scanning"); nm_device_wifi_request_scan_async(wifiDevice, NULL, wifiScanCb, this); } wait(loop); @@ -911,14 +911,14 @@ namespace WPEFramework gint64 current_time_in_msec = nm_utils_get_timestamp_msec(); gint64 time_difference_in_seconds = (current_time_in_msec - last_scan_time) / 1000; - NMLOG_TRACE("Current time in milliseconds: %" G_GINT64_FORMAT, current_time_in_msec); - NMLOG_TRACE("Last scan time in milliseconds: %" G_GINT64_FORMAT, last_scan_time); - NMLOG_TRACE("Time difference in seconds: %" G_GINT64_FORMAT, time_difference_in_seconds); + NMLOG_DEBUG("Current time in milliseconds: %" G_GINT64_FORMAT, current_time_in_msec); + NMLOG_DEBUG("Last scan time in milliseconds: %" G_GINT64_FORMAT, last_scan_time); + NMLOG_DEBUG("Time difference in seconds: %" G_GINT64_FORMAT, time_difference_in_seconds); if (time_difference_in_seconds <= timelimitInSec) { return true; } - NMLOG_TRACE("Last Wi-Fi scan exceeded time limit."); + NMLOG_DEBUG("Last Wi-Fi scan exceeded time limit."); return false; } diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 6c488573a..7315ca0f1 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -108,7 +108,7 @@ namespace WPEFramework return(Core::ERROR_GENERAL); } - NMLOG_TRACE("config line : %s", configLine.c_str()); + NMLOG_DEBUG("config line : %s", configLine.c_str()); Config config; if(config.FromString(configLine)) @@ -118,11 +118,11 @@ namespace WPEFramework m_stunPort = config.stun.port.Value(); m_stunBindTimeout = config.stun.interval.Value(); - NMLOG_TRACE("config : stun endpoint %s", m_stunEndPoint.c_str()); - NMLOG_TRACE("config : stun port %d", m_stunPort); - NMLOG_TRACE("config : stun interval %d", m_stunBindTimeout); + NMLOG_DEBUG("config : stun endpoint %s", m_stunEndPoint.c_str()); + NMLOG_DEBUG("config : stun port %d", m_stunPort); + NMLOG_DEBUG("config : stun interval %d", m_stunBindTimeout); - NMLOG_TRACE("config : loglevel %d", config.loglevel.Value()); + NMLOG_DEBUG("config : loglevel %d", config.loglevel.Value()); logLevel = static_cast (config.loglevel.Value()); // configure loglevel in libWPEFrameworkNetworkManagerImplementation.so NetworkManagerLogger::SetLevel(static_cast (logLevel)); @@ -130,23 +130,23 @@ namespace WPEFramework /* load connectivity monitor endpoints */ std::vector connectEndpts; if(!config.connectivityConf.endpoint_1.Value().empty()) { - NMLOG_TRACE("config : connectivity enpt 1 %s", config.connectivityConf.endpoint_1.Value().c_str()); + NMLOG_DEBUG("config : connectivity enpt 1 %s", config.connectivityConf.endpoint_1.Value().c_str()); connectEndpts.push_back(config.connectivityConf.endpoint_1.Value().c_str()); } if(!config.connectivityConf.endpoint_2.Value().empty()) { - NMLOG_TRACE("config : connectivity enpt 2 %s", config.connectivityConf.endpoint_2.Value().c_str()); + NMLOG_DEBUG("config : connectivity enpt 2 %s", config.connectivityConf.endpoint_2.Value().c_str()); connectEndpts.push_back(config.connectivityConf.endpoint_2.Value().c_str()); } if(!config.connectivityConf.endpoint_3.Value().empty()) { - NMLOG_TRACE("config : connectivity enpt 3 %s", config.connectivityConf.endpoint_3.Value().c_str()); + NMLOG_DEBUG("config : connectivity enpt 3 %s", config.connectivityConf.endpoint_3.Value().c_str()); connectEndpts.push_back(config.connectivityConf.endpoint_3.Value().c_str()); } if(!config.connectivityConf.endpoint_4.Value().empty()) { - NMLOG_TRACE("config : connectivity enpt 4 %s", config.connectivityConf.endpoint_4.Value().c_str()); + NMLOG_DEBUG("config : connectivity enpt 4 %s", config.connectivityConf.endpoint_4.Value().c_str()); connectEndpts.push_back(config.connectivityConf.endpoint_4.Value().c_str()); } if(!config.connectivityConf.endpoint_5.Value().empty()) { - NMLOG_TRACE("config : connectivity enpt 5 %s", config.connectivityConf.endpoint_5.Value().c_str()); + NMLOG_DEBUG("config : connectivity enpt 5 %s", config.connectivityConf.endpoint_5.Value().c_str()); connectEndpts.push_back(config.connectivityConf.endpoint_5.Value().c_str()); } @@ -300,7 +300,7 @@ namespace WPEFramework snprintf(cmd, sizeof(cmd), "ping -c %d -W %d '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); } - NMLOG_TRACE ("The Command is %s", cmd); + NMLOG_DEBUG ("The Command is %s", cmd); string commandToExecute(cmd); executeExternally(NETMGR_PING, commandToExecute, response); @@ -321,7 +321,7 @@ namespace WPEFramework snprintf(cmd, 256, "traceroute -w 3 -m 6 -q %d %s 52 2>&1", noOfRequest, endpoint.c_str()); } - NMLOG_TRACE ("The Command is %s", cmd); + NMLOG_DEBUG ("The Command is %s", cmd); string commandToExecute(cmd); executeExternally(NETMGR_TRACE, commandToExecute, tempResult); diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 9c86b6922..8c9839082 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -35,7 +35,7 @@ using namespace std; #include "NetworkManagerConnectivity.h" #include "NetworkManagerStunClient.h" -#define LOG_ENTRY_FUNCTION() { NMLOG_TRACE("Entering=%s", __FUNCTION__ ); } +#define LOG_ENTRY_FUNCTION() { NMLOG_DEBUG("Entering=%s", __FUNCTION__ ); } namespace WPEFramework { diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index c4ada38e7..a99978e66 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -19,8 +19,8 @@ #include "NetworkManager.h" -#define LOGINFOMETHOD() { std::string json; parameters.ToString(json); NMLOG_TRACE("params=%s", json.c_str() ); } -#define LOGTRACEMETHODFIN() { std::string json; response.ToString(json); NMLOG_TRACE("response=%s", json.c_str() ); } +#define LOG_INPARAM() { string json; parameters.ToString(json); NMLOG_DEBUG("%s : params=%s", __FUNCTION__, json.c_str() ); } +#define LOG_OUTPARAM() { string json; response.ToString(json); NMLOG_INFO("%s : response=%s", __FUNCTION__, json.c_str() ); } using namespace NetworkManagerLogger; @@ -114,7 +114,7 @@ namespace WPEFramework uint32_t NetworkManager::SetLogLevel (const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; LogLevel level = INFO_LEVEL; @@ -134,13 +134,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::GetAvailableInterfaces (const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::IInterfaceDetailsIterator* interfaces = NULL; @@ -151,7 +151,7 @@ namespace WPEFramework if (interfaces) { - NMLOG_TRACE("received response"); + NMLOG_DEBUG("received response"); JsonArray array; Exchange::INetworkManager::InterfaceDetails entry{}; while (interfaces->Next(entry) == true) { @@ -166,17 +166,17 @@ namespace WPEFramework } interfaces->Release(); - NMLOG_TRACE("Sending Success"); + NMLOG_DEBUG("Sending Success"); response["interfaces"] = array; response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::GetPrimaryInterface (const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string interface; if (_networkManager) @@ -190,13 +190,13 @@ namespace WPEFramework m_defaultInterface = interface; response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::SetPrimaryInterface (const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string interface = parameters["interface"].String(); @@ -215,13 +215,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::SetInterfaceState(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string interface = parameters["interface"].String(); bool enabled = parameters["enabled"].Boolean(); @@ -241,13 +241,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::GetInterfaceState(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; bool isEnabled = false; string interface = parameters["interface"].String(); @@ -268,13 +268,13 @@ namespace WPEFramework response["enabled"] = isEnabled; response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::GetIPSettings (const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string interface = ""; string ipversion = ""; @@ -316,13 +316,13 @@ namespace WPEFramework response["secondarydns"] = result.m_secondaryDns; response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::SetIPSettings(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::IPAddressInfo result{}; string interface = ""; @@ -358,13 +358,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::GetStunEndpoint(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string endPoint; uint32_t port; @@ -384,13 +384,13 @@ namespace WPEFramework response["cacheTimeout"] = cacheTimeout; response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::SetStunEndpoint(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string endPoint = parameters["endPoint"].String(); uint32_t port = parameters["port"].Number(); @@ -406,13 +406,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::GetConnectivityTestEndpoints(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::IStringIterator* endpoints = NULL; @@ -437,20 +437,20 @@ namespace WPEFramework response["success"] = true; } } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::SetConnectivityTestEndpoints(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; ::WPEFramework::RPC::IIteratorType* endpointsIter{}; JsonArray array = parameters["endpoints"].Array(); if (0 == array.Length() || 5 < array.Length()) { - NMLOG_TRACE("minimum of 1 to maximum of 5 Urls are allowed"); + NMLOG_DEBUG("minimum of 1 to maximum of 5 Urls are allowed"); return rc; } @@ -464,7 +464,7 @@ namespace WPEFramework } else { - NMLOG_TRACE("Unexpected variant type"); + NMLOG_DEBUG("Unexpected variant type"); return rc; } } @@ -483,13 +483,13 @@ namespace WPEFramework if (endpointsIter) endpointsIter->Release(); - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::IsConnectedToInternet(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string ipversion = parameters["ipversion"].String(); Exchange::INetworkManager::InternetStatus result; @@ -524,13 +524,13 @@ namespace WPEFramework response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::GetCaptivePortalURI(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string endPoint; if (_networkManager) @@ -543,17 +543,17 @@ namespace WPEFramework response["uri"] = endPoint; response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::StartConnectivityMonitoring(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; uint32_t interval = parameters["interval"].Number(); - NMLOG_TRACE("connectivity interval = %d", interval); + NMLOG_DEBUG("connectivity interval = %d", interval); if (_networkManager) rc = _networkManager->StartConnectivityMonitoring(interval); else @@ -563,13 +563,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::StopConnectivityMonitoring(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; if (_networkManager) @@ -581,13 +581,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::GetPublicIP(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string ipAddress{}; string ipversion = "IPv4"; @@ -617,13 +617,13 @@ namespace WPEFramework m_publicIPAddressType = ipversion; PublishToThunderAboutInternet(); } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } void NetworkManager::PublishToThunderAboutInternet() { - NMLOG_TRACE("No public IP persisted yet; Update the data"); + NMLOG_DEBUG("No public IP persisted yet; Update the data"); if (m_publicIPAddress.empty()) { JsonObject input, output; @@ -650,9 +650,10 @@ namespace WPEFramework uint32_t NetworkManager::Ping(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); string result{}; uint32_t rc = Core::ERROR_GENERAL; + LOG_INPARAM(); if (parameters.HasLabel("endpoint")) { string endpoint{}; @@ -687,13 +688,13 @@ namespace WPEFramework reply.FromString(result); response = reply; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::Trace(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string result{}; const string ipversion = parameters["ipversion"].String(); @@ -713,13 +714,13 @@ namespace WPEFramework reply["success"] = true; response = reply; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::StartWiFiScan(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; const Exchange::INetworkManager::WiFiFrequency frequency = static_cast (parameters["frequency"].Number()); @@ -732,13 +733,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::StopWiFiScan(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; if (_networkManager) @@ -750,13 +751,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::GetKnownSSIDs(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; JsonArray ssids; @@ -781,13 +782,13 @@ namespace WPEFramework response["ssids"] = ssids; response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::AddToKnownSSIDs(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::WiFiConnectTo ssid{}; @@ -807,13 +808,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::RemoveKnownSSID(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string ssid{}; @@ -830,13 +831,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::WiFiConnect(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::WiFiConnectTo ssid{}; @@ -870,13 +871,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::WiFiDisconnect(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; if (_networkManager) @@ -888,13 +889,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::GetConnectedSSID(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; @@ -914,13 +915,13 @@ namespace WPEFramework response["noise"] = ssidInfo.m_noise; response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::StartWPS(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string wps_pin{}; Exchange::INetworkManager::WiFiWPS method; @@ -946,13 +947,13 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::StopWPS(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; if (_networkManager) @@ -964,7 +965,7 @@ namespace WPEFramework { response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } @@ -973,7 +974,7 @@ namespace WPEFramework Exchange::INetworkManager::WiFiState state; uint32_t rc = Core::ERROR_GENERAL; - LOGINFOMETHOD(); + LOG_INPARAM(); if (_networkManager) rc = _networkManager->GetWifiState(state); else @@ -983,13 +984,13 @@ namespace WPEFramework response["state"] = static_cast (state); response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::GetWiFiSignalStrength(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string ssid{}; string signalStrength{}; @@ -1007,13 +1008,13 @@ namespace WPEFramework response["quality"] = static_cast (quality); response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } uint32_t NetworkManager::GetSupportedSecurityModes(const JsonObject& parameters, JsonObject& response) { - LOGINFOMETHOD(); + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::ISecurityModeIterator* securityModes{}; @@ -1036,7 +1037,7 @@ namespace WPEFramework } response["success"] = true; } - LOGTRACEMETHODFIN(); + LOG_OUTPARAM(); return rc; } } diff --git a/NetworkManagerLogger.cpp b/NetworkManagerLogger.cpp index 0b118314e..faeab4bf3 100644 --- a/NetworkManagerLogger.cpp +++ b/NetworkManagerLogger.cpp @@ -36,6 +36,33 @@ namespace NetworkManagerLogger { static LogLevel gDefaultLogLevel = INFO_LEVEL; + +#ifdef USE_RDK_LOGGER + rdk_LogLevel mapTordkLogLevel(LogLevel level) + { + rdk_LogLevel rdklevel = RDK_LOG_INFO; + switch (level) + { + case FATAL_LEVEL: + rdklevel = RDK_LOG_FATAL; + break; + case ERROR_LEVEL: + rdklevel = RDK_LOG_ERROR; + break; + case WARNING_LEVEL: + rdklevel = RDK_LOG_WARN; + break; + case INFO_LEVEL: + rdklevel = RDK_LOG_INFO; + break; + case DEBUG_LEVEL: + rdklevel = RDK_LOG_DEBUG; + break; + } + return rdklevel; + } +#endif + const char* methodName(const std::string& prettyFunction) { size_t colons = prettyFunction.find("::"); @@ -72,9 +99,9 @@ namespace NetworkManagerLogger { } formattedLog[kFormatMessageSize - 1] = '\0'; #ifdef USE_RDK_LOGGER - RDK_LOG(static_cast(level), "LOG.RDK.NETMGR", "%s\n", formattedLog); + RDK_LOG(mapTordkLogLevel(level), "LOG.RDK.NWMGR", "%s\n", formattedLog); #else - const char* levelMap[] = {"Fatal", "Error", "Warning", "Info", "Verbose", "Trace"}; + const char* levelMap[] = {"Fatal", "Error", "Warn", "Info", "Debug"}; struct timeval tv; struct tm* lt; @@ -84,7 +111,7 @@ namespace NetworkManagerLogger { gettimeofday(&tv, NULL); lt = localtime(&tv.tv_sec); - printf("%.2d:%.2d:%.2d.%.6lld %-10s %s:%d : %s\n", lt->tm_hour, lt->tm_min, lt->tm_sec, (long long int)tv.tv_usec, levelMap[level], basename(file), line, formattedLog); + printf("%.2d:%.2d:%.2d.%.6lld [%-5s] [PID=%d] [TID=%d] %s : %s\n", lt->tm_hour, lt->tm_min, lt->tm_sec, (long long int)tv.tv_usec, levelMap[level], getpid(), gettid(), func, formattedLog); fflush(stdout); #endif } diff --git a/NetworkManagerLogger.h b/NetworkManagerLogger.h index 2441c9920..65014d722 100644 --- a/NetworkManagerLogger.h +++ b/NetworkManagerLogger.h @@ -30,11 +30,11 @@ namespace NetworkManagerLogger { /** * Logging level with an increasing order of refinement - * (TRACE_LEVEL = Finest logging) + * (DEBUG_LEVEL = Finest logging) * It is essental to start with 0 and increase w/o gaps as the value * can be used for indexing in a mapping table. */ -enum LogLevel {FATAL_LEVEL = 0, ERROR_LEVEL, WARNING_LEVEL, INFO_LEVEL, VERBOSE_LEVEL, TRACE_LEVEL}; +enum LogLevel {FATAL_LEVEL = 0, ERROR_LEVEL, WARNING_LEVEL, INFO_LEVEL, DEBUG_LEVEL}; /** * @brief Init logging @@ -55,8 +55,7 @@ void SetLevel(LogLevel level); void logPrint(LogLevel level, const char* file, const char* func, int line, const char* format, ...) __attribute__ ((format (printf, 5, 6))); -#define NMLOG_TRACE(FMT, ...) logPrint(NetworkManagerLogger::TRACE_LEVEL, __FILE__, __func__, __LINE__, FMT, ##__VA_ARGS__) -#define NMLOG_VERBOSE(FMT, ...) logPrint(NetworkManagerLogger::VERBOSE_LEVEL, __FILE__, __func__, __LINE__, FMT, ##__VA_ARGS__) +#define NMLOG_DEBUG(FMT, ...) logPrint(NetworkManagerLogger::DEBUG_LEVEL, __FILE__, __func__, __LINE__, FMT, ##__VA_ARGS__) #define NMLOG_INFO(FMT, ...) logPrint(NetworkManagerLogger::INFO_LEVEL, __FILE__, __func__, __LINE__, FMT, ##__VA_ARGS__) #define NMLOG_WARNING(FMT, ...) logPrint(NetworkManagerLogger::WARNING_LEVEL, __FILE__, __func__, __LINE__, FMT, ##__VA_ARGS__) #define NMLOG_ERROR(FMT, ...) logPrint(NetworkManagerLogger::ERROR_LEVEL, __FILE__, __func__, __LINE__, FMT, ##__VA_ARGS__) diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 9fd5ffdc7..d82721326 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -763,7 +763,7 @@ namespace WPEFramework if (IARM_RESULT_SUCCESS == IARM_Bus_Call (IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_isInterfaceEnabled, (void *)&iarmData, sizeof(iarmData))) { - NMLOG_TRACE("Call to %s for %s success", IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_isInterfaceEnabled); + NMLOG_DEBUG("Call to %s for %s success", IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_isInterfaceEnabled); isEnabled = iarmData.isInterfaceEnabled; rc = Core::ERROR_NONE; } @@ -821,7 +821,6 @@ namespace WPEFramework if (IARM_RESULT_SUCCESS == IARM_Bus_Call (IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_getIPSettings, (void *)&iarmData, sizeof(iarmData))) { - NMLOG_TRACE("NetworkManagerImplementation::GetIPSettings - IARM Success.. Filling the data"); result.m_ipAddrType = string(iarmData.ipversion); result.m_autoConfig = iarmData.autoconfig; result.m_dhcpServer = string(iarmData.dhcpserver,MAX_IP_ADDRESS_LEN - 1); diff --git a/WiFiSignalStrengthMonitor.cpp b/WiFiSignalStrengthMonitor.cpp index 0230095b5..60165f93f 100644 --- a/WiFiSignalStrengthMonitor.cpp +++ b/WiFiSignalStrengthMonitor.cpp @@ -66,7 +66,7 @@ namespace WPEFramework else NMLOG_ERROR("signalStrength is empty"); - NMLOG_TRACE("SSID = %s Signal Strength %f db", ssid.c_str(), signalStrengthOut); + NMLOG_DEBUG("SSID = %s Signal Strength %f db", ssid.c_str(), signalStrengthOut); if (signalStrengthOut == 0.0f) { quality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; @@ -114,7 +114,7 @@ namespace WPEFramework Exchange::INetworkManager::WiFiSignalQuality newSignalQuality; if (_instance != nullptr) { - NMLOG_TRACE("checking WiFi signal strength"); + NMLOG_DEBUG("checking WiFi signal strength"); getSignalData(ssid, newSignalQuality, signalStrength); if(oldSignalQuality != newSignalQuality) { From e55d0f0cd51dfc40bcd49696e365b90bdc62820b Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 4 Oct 2024 18:55:48 -0400 Subject: [PATCH 025/271] Release of v0.4.0 Signed-off-by: Karunakaran A --- CHANGELOG.md | 7 +++++-- CMakeLists.txt | 2 +- NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 460e665b1..c7b39ff8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. -* For more details, refer to [versioning](https://github.com/rdkcentral/rdkservices#versioning) section under Main README. +## [0.4.0] - 2024-10-04 +### Added +- Added RDKLogger Integration +- Fixed Legacy Network API for getIPSetting2 +- Includes critical bug fixes ## [0.3.0] - 2024-09-16 ### Added @@ -23,7 +27,6 @@ All notable changes to this RDK Service will be documented in this file. - Fixed activation & subscription flow - Includes bug fixes - ## [0.2.0] - 2024-05-27 ### Added - Restructured the NetworkManager folder organization diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e55f9473..7c390399f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 3) +set(VERSION_MINOR 4) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/NetworkManager.json b/NetworkManager.json index 4fe9faf4a..0096bddaa 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -8,7 +8,7 @@ "locator": "libWPEFrameworkNetworkManager.so", "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", - "version": "0.3.0" + "version": "0.4.0" }, "common": { "$ref": "../../common/common.json" diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index ba8ef05a8..8a9b9de02 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: [0.3.0]()** +**Version: [0.4.0]()** A NetworkManager plugin for Thunder framework. From 73885d0ffa7dec34ed2368a489ce23ca378b0b9a Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Sun, 20 Oct 2024 08:34:52 -0400 Subject: [PATCH 026/271] Updated the documentation for external interfaces (#18) Signed-off-by: Karunakaran A --- docs/NetworkManagerPlugin.md | 206 ++++++++++++++++++++++------------- 1 file changed, 131 insertions(+), 75 deletions(-) diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 8a9b9de02..41f186668 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -86,6 +86,7 @@ NetworkManager interface methods: | [GetWiFiSignalStrength](#method.GetWiFiSignalStrength) | Get WiFiSignalStrength of connected SSID | | [GetSupportedSecurityModes](#method.GetSupportedSecurityModes) | Returns the Wifi security modes that the device supports | | [SetLogLevel](#method.SetLogLevel) | Set Log level for more information | +| [GetLogLevel](#method.GetLogLevel) | Gets the Log level thats used | | [GetWifiState](#method.GetWifiState) | Returns the current Wifi State | @@ -112,8 +113,8 @@ This method takes no parameters. | result?.Interfaces[#].type | string | Interface Type | | result?.Interfaces[#].name | string | Interface Name. ex: eth0 or wlan0 | | result?.Interfaces[#].mac | string | Interface MAC address | -| result?.Interfaces[#].isEnabled | boolean | Whether the interface is currently enabled | -| result?.Interfaces[#].isConnected | boolean | Whether the interface is currently connected | +| result?.Interfaces[#].enabled | boolean | Whether the interface is currently enabled | +| result?.Interfaces[#].connected | boolean | Whether the interface is currently connected | | result.success | boolean | Whether the request succeeded | ### Example @@ -135,13 +136,13 @@ This method takes no parameters. "jsonrpc": "2.0", "id": 42, "result": { - "Interfaces": [ + "interfaces": [ { "type": "ETHERNET", "name": "eth0", "mac": "AA:AA:AA:AA:AA:AA", - "isEnabled": true, - "isConnected": true + "enabled": true, + "connected": true } ], "success": true @@ -322,7 +323,7 @@ No Events | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.isEnabled | boolean | Whether the Interface is enabled or disabled | +| result.enabled | boolean | Whether the Interface is enabled or disabled | | result.success | boolean | Whether the request succeeded | ### Example @@ -347,7 +348,7 @@ No Events "jsonrpc": "2.0", "id": 42, "result": { - "isEnabled": true, + "enabled": true, "success": true } } @@ -382,7 +383,7 @@ No Events | result.ipaddress | string | The IP address | | result.prefix | integer | The prefix number | | result.gateway | string | The gateway address | -| result.v6LinkLocal | string | The v6LinkLocal | +| result.ula | string | The IPv6 Unified Local Address; Empty when IPv4 is requested | | result.primarydns | string | The primary DNS address | | result.secondarydns | string | The secondary DNS address | | result.success | boolean | Whether the request succeeded | @@ -417,7 +418,7 @@ No Events "ipaddress": "192.168.1.101", "prefix": 24, "gateway": "192.168.1.1", - "v6LinkLocal": "192.168.1.1", + "ula": "...", "primarydns": "192.168.1.1", "secondarydns": "192.168.1.2", "success": true @@ -509,10 +510,10 @@ This method takes no parameters. | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.endPoint | string | STUN server endPoint | +| result.endpoint | string | STUN server endpoint | | result.port | integer | STUN server port | -| result.bindTimeout | integer | STUN server bind timeout | -| result.cacheTimeout | integer | STUN server cache timeout | +| result.timeout | integer | STUN server bind timeout | +| result.cacheLifetime | integer | STUN server cache Lifetime | | result.success | boolean | Whether the request succeeded | ### Example @@ -534,10 +535,10 @@ This method takes no parameters. "jsonrpc": "2.0", "id": 42, "result": { - "endPoint": "stun.l.google.com", + "endpoint": "stun.l.google.com", "port": 3478, - "bindTimeout": 30, - "cacheTimeout": 0, + "timeout": 30, + "cacheLifetime": 0, "success": true } } @@ -557,10 +558,10 @@ No Events | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.endPoint | string | STUN server endPoint | +| params.endpoint | string | STUN server endpoint | | params.port | integer | STUN server port | -| params?.bindTimeout | integer | *(optional)* STUN server bind timeout | -| params?.cacheTimeout | integer | *(optional)* STUN server cache timeout | +| params?.timeout | integer | *(optional)* STUN server bind timeout | +| params?.cacheLifetime | integer | *(optional)* STUN server cache lifetime | ### Result @@ -579,10 +580,10 @@ No Events "id": 42, "method": "org.rdk.NetworkManager.SetStunEndpoint", "params": { - "endPoint": "stun.l.google.com", + "endpoint": "stun.l.google.com", "port": 3478, - "bindTimeout": 30, - "cacheTimeout": 0 + "timeout": 30, + "cacheLifetime": 0 } } ``` @@ -722,8 +723,10 @@ No Events | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.isConnectedToInternet | boolean | `true` if internet connectivity is detected, otherwise `false` | -| result.internetState | integer | The internet state | +| result.ipversion | string | either IPv4 or IPv6 | +| result.connected | boolean | `true` if internet connectivity is detected, otherwise `false` | +| result.state | integer | The internet state | +| result.status | integer | The internet status; could be `LIMITED_INTERNET`, `CAPTIVE_PORTAL`, `NO_INTERNET`, `FULLY_CONNECTED` | | result.success | boolean | Whether the request succeeded | ### Example @@ -748,8 +751,10 @@ No Events "jsonrpc": "2.0", "id": 42, "result": { - "isConnectedToInternet": true, - "internetState": 4, + "ipversion": "IPv4" + "connected": true, + "state": 3, + "status": "FULLY_CONNECTED", "success": true } } @@ -910,14 +915,15 @@ No Events | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | it allows empty parameter too | -| params.ipversion | string | either IPv4 or IPv6 | +| params.ipversion | string | *(optional)* Either IPv4 or IPv6 | ### Result | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.publicIP | string | Returns an public ip of the device | +| result.ipaddress | string | Returns an public ip of the device | +| result.ipversion | string | Returns an ip version of the public ip | | result.success | boolean | Whether the request succeeded | ### Example @@ -942,7 +948,8 @@ No Events "jsonrpc": "2.0", "id": 42, "result": { - "publicIP": "69.136.49.95", + "ipaddress": "69.136.49.95", + "ipversion": "IPv4" "success": true } } @@ -964,7 +971,7 @@ No Events | params | object | | | params.endpoint | string | The host name or IP address | | params.ipversion | string | either IPv4 or IPv6 | -| params.noOfRequest | integer | *(optional)* The number of packets to send. Default is 3 | +| params.count | integer | *(optional)* The number of packets to send. Default is 3 | | params.timeout | integer | Timeout | | params.guid | string | The globally unique identifier | @@ -997,7 +1004,7 @@ No Events "params": { "endpoint": "45.57.221.20", "ipversion": "IPv4", - "noOfRequest": 10, + "count": 5, "timeout": 30, "guid": "..." } @@ -1012,8 +1019,8 @@ No Events "id": 42, "result": { "target": "45.57.221.20", - "packetsTransmitted": 10, - "packetsReceived": 10, + "packetsTransmitted": 5, + "packetsReceived": 5, "packetLoss": "0.0", "tripMin": "61.264", "tripAvg": "130.397", @@ -1099,7 +1106,9 @@ Initiates WiFi scaning. This method supports scanning for specific range of freq | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.frequency | string | The frequency to scan. An empty or `null` value scans all frequencies. If a frequency is specified (2.4 or 5.0), then the results are only returned for matching frequencies | +| params.frequency | string | *(optional)* The frequency to scan. | +| params.ssids | array | *(optional)* The list of SSIDs to scan. | +| params.ssids[#] | string | | ### Result @@ -1116,10 +1125,7 @@ Initiates WiFi scaning. This method supports scanning for specific range of freq { "jsonrpc": "2.0", "id": 42, - "method": "org.rdk.NetworkManager.StartWiFiScan", - "params": { - "frequency": "..." - } + "method": "org.rdk.NetworkManager.StartWiFiScan" } ``` @@ -1244,7 +1250,7 @@ No Events | params | object | | | params.ssid | string | The paired SSID | | params.passphrase | string | The access point password | -| params.securityMode | integer | The security mode. See `getSupportedSecurityModes` | +| params.security | integer | The security mode. See `getSupportedSecurityModes` | ### Result @@ -1265,7 +1271,7 @@ No Events "params": { "ssid": "123412341234", "passphrase": "password", - "securityMode": 6 + "security": 6 } } ``` @@ -1352,8 +1358,8 @@ Initiates request to connect to the specified SSID with the given passphrase. Pa | params | object | | | params.ssid | string | The paired SSID | | params.passphrase | string | The access point password | -| params.securityMode | integer | The security mode. See `getSupportedSecurityModes` | -| params.persistSSIDInfo | boolean | *(optional)* Option to connect to SSID without persisting AccessPoint details (default: *true*; always persist) | +| params.security | integer | The security mode. See `getSupportedSecurityModes` | +| params?.persist | boolean | *(optional)* Option to connect to SSID without persisting AccessPoint details (default: *true*; always persist) | ### Result @@ -1374,8 +1380,8 @@ Initiates request to connect to the specified SSID with the given passphrase. Pa "params": { "ssid": "123412341234", "passphrase": "password", - "securityMode": 6, - "persistSSIDInfo": true + "security": 6, + "persist": true } } ``` @@ -1459,8 +1465,8 @@ This method takes no parameters. | result | object | | | result.ssid | string | The paired SSID | | result.bssid | string | The paired BSSID | -| result.securityMode | string | The security mode. See the `connect` method | -| result.signalStrength | string | The RSSI value in dBm | +| result.security | string | The security mode. See the `connect` method | +| result.strength | string | The RSSI value in dBm | | result.frequency | string | The supported frequency for this SSID in GHz | | result.rate | string | The physical data rate in Mbps | | result.noise | string | The average noise strength in dBm | @@ -1487,8 +1493,8 @@ This method takes no parameters. "result": { "ssid": "123412341234", "bssid": "ff:ff:ff:ff:ff:ff", - "securityMode": "5", - "signalStrength": "-27.000000", + "security": "5", + "strength": "-27.000000", "frequency": "2.442000", "rate": "144.000000", "noise": "-121.000000", @@ -1517,7 +1523,7 @@ If the `method` parameter is set to `SERIALIZED_PIN`, then RDK retrieves the ser | :-------- | :-------- | :-------- | | params | object | | | params.method | integer | The method used to obtain the pin (must be one of the following: PBC=0, PIN=1, SERIALIZED_PIN=2) | -| params.wps_pin | string | A valid 8 digit WPS pin number. Use this parameter when the `method` parameter is set to `PIN` | +| params.pin | string | A valid 8 digit WPS pin number. Use this parameter when the `method` parameter is set to `PIN` | ### Result @@ -1538,7 +1544,7 @@ If the `method` parameter is set to `SERIALIZED_PIN`, then RDK retrieves the ser "method": "org.rdk.NetworkManager.StartWPS", "params": { "method": 1, - "wps_pin": "88888888" + "pin": "88888888" } } ``` @@ -1621,8 +1627,8 @@ This method takes no parameters. | :-------- | :-------- | :-------- | | result | object | | | result.ssid | string | The paired SSID | -| result.signalStrength | string | The RSSI value in dBm | -| result.quality | integer | Signal strength Quality | +| result.strength | string | The RSSI value in dBm | +| result.quality | string | Signal strength Quality | | result.success | boolean | Whether the request succeeded | ### Example @@ -1645,8 +1651,8 @@ This method takes no parameters. "id": 42, "result": { "ssid": "123412341234", - "signalStrength": "-27.000000", - "quality": 123, + "strength": "-27.000000", + "quality": "Excellent", "success": true } } @@ -1735,10 +1741,9 @@ This method takes no parameters. Set Log level for more information. The possible set log level are as follows. * `0`: FATAL * `1`: ERROR -* `2`: WARNING +* `2`: WARN * `3`: INFO -* `4`: VERBOSE -* `5`: TRACE +* `4`: DEBUG . ### Events @@ -1750,7 +1755,7 @@ No Events | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.logLevel | integer | Set Log level to get more information | +| params.level | integer | Set Log level to get more information | ### Result @@ -1769,7 +1774,7 @@ No Events "id": 42, "method": "org.rdk.NetworkManager.SetLogLevel", "params": { - "logLevel": 1 + "level": 1 } } ``` @@ -1786,6 +1791,57 @@ No Events } ``` + +## *GetLogLevel [method](#head.Methods)* + +Gets the log level. It could be either of the below +* `0`: FATAL +* `1`: ERROR +* `2`: WARN +* `3`: INFO +* `4`: DEBUG + +### Events + +No Events + +### Parameters + +This method takes no parameters. + +### Result + +| Name | Type | Description | +| :-------- | :-------- | :-------- | +| result | object | | +| result.level | integer | The Log level | +| result.success | boolean | Whether the request succeeded | + +### Example + +#### Request + +```json +{ + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.GetLogLevel", +} +``` + +#### Response + +```json +{ + "jsonrpc": "2.0", + "id": 42, + "result": { + "level": 3 + "success": true + } +} +``` + ## *GetWifiState [method](#head.Methods)* @@ -1910,8 +1966,8 @@ Triggered when an IP Address is assigned or lost. | :-------- | :-------- | :-------- | | params | object | | | params.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | -| params.isIPv6 | boolean | It will be true if the IP address is IPv6 | -| params.ipAddress | string | The IPv6 or IPv4 address for the interface | +| params.ipversion | string | It will be IPv4 or IPv6 | +| params.ipaddress | string | The IPv6 or IPv4 address for the interface | | params.status | string | Whether IP address was acquired or lost (must be one of the following: 'ACQUIRED', 'LOST') (must be one of the following: *`ACQUIRED`*, *`LOST`*) | ### Example @@ -1922,8 +1978,8 @@ Triggered when an IP Address is assigned or lost. "method": "client.events.onAddressChange", "params": { "interface": "wlan0", - "isIPv6": false, - "ipAddress": "192.168.1.100", + "ipversion": "IPv4", + "ipaddress": "192.168.1.100", "status": "ACQUIRED" } } @@ -1939,8 +1995,8 @@ Triggered when the primary/active interface changes, regardless if it's from a s | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.oldInterfaceName | string | The previous interface that was changed | -| params.newInterfaceName | string | The current interface | +| params.prevActiveInterface | string | The previous interface that was changed | +| params.activeInterface | string | The current interface | ### Example @@ -1949,8 +2005,8 @@ Triggered when the primary/active interface changes, regardless if it's from a s "jsonrpc": "2.0", "method": "client.events.onActiveInterfaceChange", "params": { - "oldInterfaceName": "wlan0", - "newInterfaceName": "eth0" + "prevActiveInterface": "wlan0", + "activeInterface": "eth0" } } ``` @@ -1965,8 +2021,8 @@ Triggered when internet connection state changed.The possible internet connectio | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.PrevState | integer | The privious internet connection state | -| params.PrevStatus | string | The previous internet connection status | +| params.prevState | integer | The privious internet connection state | +| params.prevStatus | string | The previous internet connection status | | params.state | integer | The internet connection state | | params.status | string | The internet connection status | @@ -1977,9 +2033,9 @@ Triggered when internet connection state changed.The possible internet connectio "jsonrpc": "2.0", "method": "client.events.onInternetStatusChange", "params": { - "PrevState": 1, - "PrevStatus": "NO_INTERNET", - "state": 4, + "prevState": 0, + "prevStatus": "NO_INTERNET", + "state": 3, "status": "FULLY_CONNECTED" } } @@ -1999,7 +2055,7 @@ Triggered when scan completes or when scan cancelled. | params.ssids[#] | object | | | params.ssids[#].ssid | string | ssid | | params.ssids[#].security | integer | security | -| params.ssids[#].signalStrength | string | signalStrength | +| params.ssids[#].strength | string | signalStrength | | params.ssids[#].frequency | string | frequency | ### Example @@ -2013,7 +2069,7 @@ Triggered when scan completes or when scan cancelled. { "ssid": "myAP-2.4", "security": 6, - "signalStrength": "-27.000000", + "strength": "-27.000000", "frequency": "2.442000" } ] @@ -2082,8 +2138,8 @@ Triggered when WIFI connection Signal Strength get changed. "method": "client.events.onWiFiSignalStrengthChange", "params": { "ssid": "home-new_123", - "signalLevel": "-27.000000", - "signalQuality": "Excellent" + "strength": "-27.000000", + "quality": "Excellent" } } ``` From e1aa7f36aac07433f6e75d5f26940e0d994bd8d4 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Mon, 7 Oct 2024 06:05:31 +0530 Subject: [PATCH 027/271] DELIA-65737: Wi-Fi interface shows IP even after Wi-Fi is disconnected (#1) Implemented a cache logic to handle redundant calls * update the review comments --- NetworkManager.cpp | 2 +- NetworkManager.h | 62 +++++++++++++++++++++++++++++++++-- NetworkManagerJsonRpc.cpp | 66 ++++++++++++++++++++++++++++++++------ NetworkManagerRDKProxy.cpp | 2 +- 4 files changed, 119 insertions(+), 13 deletions(-) diff --git a/NetworkManager.cpp b/NetworkManager.cpp index c7d57b870..baa8d4826 100644 --- a/NetworkManager.cpp +++ b/NetworkManager.cpp @@ -44,7 +44,7 @@ namespace WPEFramework _notification(this) { // Don't do any work in the constructor - all set up should be done in Initialize - m_defaultInterface = "wlan0"; + m_primaryInterfaceCache = "wlan0"; } NetworkManager::~NetworkManager() diff --git a/NetworkManager.h b/NetworkManager.h index ce4771cf2..1838c545b 100644 --- a/NetworkManager.h +++ b/NetworkManager.h @@ -28,6 +28,7 @@ #include #include +#include namespace WPEFramework { @@ -123,7 +124,12 @@ namespace WPEFramework JsonObject params; params["interface"] = interface; params["state"] = InterfaceStateToString(event); + if(interface == "wlan0") + _parent.m_wifiStateCache.reset(); _parent.Notify("onInterfaceStateChange", params); + _parent.m_primaryInterfaceCache.reset(); + _parent.m_ipv6AddressCache.reset(); + _parent.m_ipv4AddressCache.reset(); } void onIPAddressChange(const string interface, const bool isAcquired, const bool isIPv6, const string ipAddress) override @@ -134,6 +140,10 @@ namespace WPEFramework params["interface"] = interface; params["ipAddress"] = ipAddress; params["isIPv6"] = isIPv6; + if(isIPv6) + _parent.m_ipv6AddressCache.reset(); + else + _parent.m_ipv4AddressCache.reset(); _parent.Notify("onIPAddressChange", params); } @@ -144,7 +154,7 @@ namespace WPEFramework params["oldInterfaceName"] = prevActiveInterface; params["newInterfaceName"] = currentActiveinterface; _parent.Notify("onActiveInterfaceChange", params); - + _parent.m_primaryInterfaceCache.reset(); } void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus oldState, const Exchange::INetworkManager::InternetStatus newstate) override @@ -184,6 +194,7 @@ namespace WPEFramework JsonObject result; result["state"] = static_cast (state); _parent.Notify("onWiFiStateChange", result); + _parent.m_wifiStateCache = state; } void onWiFiSignalStrengthChange(const string ssid, const string signalLevel, const Exchange::INetworkManager::WiFiSignalQuality signalQuality) override @@ -264,7 +275,55 @@ namespace WPEFramework return (m_publicIPAddress.empty() == true ? PluginHost::ISubSystem::IInternet::UNKNOWN : (m_publicIPAddressType == "IPV6" ? PluginHost::ISubSystem::IInternet::IPV6 : PluginHost::ISubSystem::IInternet::IPV4)); } void PublishToThunderAboutInternet(); + /* Class to store and manage cached data */ + template + class Cache { + public: + Cache() : is_set(false) {} + + Cache& operator=(const CacheValue& value) { + std::lock_guard lock(mutex); + this->value = value; + is_set.store(true); + return *this; + } + + Cache& operator=(CacheValue&& value) { + std::lock_guard lock(mutex); + this->value = std::move(value); + is_set.store(true); + return *this; + } + + bool isSet() const { + return is_set.load(); + } + + void reset() { + is_set.store(false); + } + + const CacheValue& getValue() const { + std::lock_guard lock(mutex); + return value; + } + + CacheValue& getValue() { + std::lock_guard lock(mutex); + return value; + } + + private: + CacheValue value; + std::atomic is_set; + mutable std::mutex mutex; + }; + // cached varibales + Cache m_wifiStateCache; + Cache m_ipv4AddressCache; + Cache m_ipv6AddressCache; + Cache m_primaryInterfaceCache; private: // Notification/event handlers // Clean up when we're told to deactivate @@ -315,7 +374,6 @@ namespace WPEFramework Exchange::INetworkManager *_networkManager; Core::Sink _notification; string m_publicIPAddress; - string m_defaultInterface; string m_publicIPAddressType; }; } diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index a99978e66..06da7b6fa 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -179,7 +179,13 @@ namespace WPEFramework LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string interface; - if (_networkManager) + if(m_primaryInterfaceCache.isSet()) + { + NMLOG_INFO("reading interface cached values"); + interface = m_primaryInterfaceCache.getValue(); + rc = Core::ERROR_NONE; + } + else if (_networkManager) rc = _networkManager->GetPrimaryInterface(interface); else rc = Core::ERROR_UNAVAILABLE; @@ -187,7 +193,7 @@ namespace WPEFramework if (Core::ERROR_NONE == rc) { response["interface"] = interface; - m_defaultInterface = interface; + m_primaryInterfaceCache = interface; response["success"] = true; } LOG_OUTPARAM(); @@ -278,6 +284,7 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; string interface = ""; string ipversion = ""; + bool isCacheLoaded = false; Exchange::INetworkManager::IPAddressInfo result{}; if (parameters.HasLabel("interface")) @@ -285,16 +292,56 @@ namespace WPEFramework if (parameters.HasLabel("ipversion")) ipversion = parameters["ipversion"].String(); - if (!interface.empty() && ("wlan0" != interface) && ("eth0" != interface)) + if (interface.empty() || ("wlan0" != interface && "eth0" != interface)) { - rc = Core::ERROR_BAD_REQUEST; - return rc; + if(!interface.empty()) { + NMLOG_WARNING("interface is neither wlan0 nor eth0: %s", interface.c_str()); + return Core::ERROR_BAD_REQUEST; + } + + interface = m_primaryInterfaceCache.getValue(); } - if (_networkManager) - rc = _networkManager->GetIPSettings(interface, ipversion, result); - else - rc = Core::ERROR_UNAVAILABLE; + if(m_primaryInterfaceCache.isSet() && (interface == m_primaryInterfaceCache.getValue())) + { + /* If ipversion is empty, IPv4 will be taken as the default version */ + if(m_ipv4AddressCache.isSet() && (ipversion.empty() || strcasecmp(ipversion.c_str(), "IPv4") == 0)) + { + NMLOG_INFO("reading ipv4 settings cached values"); + result = m_ipv4AddressCache.getValue(); + rc = Core::ERROR_NONE; + isCacheLoaded = true; + } + else if(m_ipv6AddressCache.isSet() && (ipversion.empty() || strcasecmp(ipversion.c_str(), "IPv6") == 0)) + { + NMLOG_INFO("reading ipv6 settings cached values"); + result = m_ipv6AddressCache.getValue(); + rc = Core::ERROR_NONE; + isCacheLoaded = true; + } + } + + if (!isCacheLoaded) + { + if (_networkManager) + { + rc = _networkManager->GetIPSettings(interface, ipversion, result); + /* The value will be cached only for the primary interface IP address. */ + if(Core::ERROR_NONE == rc && m_primaryInterfaceCache.isSet() && (interface == m_primaryInterfaceCache.getValue())) + { + NMLOG_DEBUG("caching the ip address values"); + if (strcasecmp(result.m_ipAddrType.c_str(), "IPv4") == 0) + m_ipv4AddressCache = result; + else if (strcasecmp(result.m_ipAddrType.c_str(), "IPv6") == 0) + m_ipv6AddressCache = result; + } + } + else + { + NMLOG_ERROR("_networkManager == null"); + rc = Core::ERROR_UNAVAILABLE; + } + } if (Core::ERROR_NONE == rc) { @@ -982,6 +1029,7 @@ namespace WPEFramework if (Core::ERROR_NONE == rc) { response["state"] = static_cast (state); + m_wifiStateCache = state; response["success"] = true; } LOG_OUTPARAM(); diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index d82721326..67052cdc9 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -629,7 +629,7 @@ namespace WPEFramework std::vector interfaceList; for (int i = 0; i < list.size; i++) { - NMLOG_INFO ("Interface Name = %s", list.interfaces[i].name); + NMLOG_DEBUG("Interface Name = %s", list.interfaces[i].name); string interfaceName(list.interfaces[i].name); if (("eth0" == interfaceName) || ("wlan0" == interfaceName)) { From 77a3469e88074159c64e73749229cdaa18ca4f4b Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Sun, 20 Oct 2024 08:34:52 -0400 Subject: [PATCH 028/271] Updated the documentation for external interfaces (#18) Signed-off-by: Karunakaran A From e34f87f1b2a8783d4c7b0b5a6e09935cb1bfb9c7 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:06:05 -0400 Subject: [PATCH 029/271] DELIA-66644 : Implement ComRPC in Network and WiFi Plugin to communicate with NetworkManager (#21) Reason for change: Use ComRPC in Network and WiFi Plugin to communicate with NetworkManager Test Procedure: Perform all the Network and Wifi JSONRPC requests n confirm Risks: High Signed-off-by: Karunakaran A --- CMakeLists.txt | 9 +- INetworkManager.h | 191 ++-- LegacyPlugin_NetworkAPIs.cpp | 815 +++++++++------- LegacyPlugin_NetworkAPIs.h | 6 +- LegacyPlugin_WiFiManagerAPIs.cpp | 437 +++++---- Module.cpp | 2 +- NetworkManager.cpp | 11 +- NetworkManager.h | 151 +-- NetworkManager.json | 720 ++++++++------ NetworkManagerConnectivity.cpp | 14 +- NetworkManagerConnectivity.h | 2 +- NetworkManagerGnomeEvents.cpp | 18 +- NetworkManagerGnomeEvents.h | 10 +- NetworkManagerGnomeProxy.cpp | 78 +- NetworkManagerGnomeWIFI.cpp | 85 +- NetworkManagerGnomeWIFI.h | 2 +- NetworkManagerImplementation.cpp | 104 +- NetworkManagerImplementation.h | 33 +- NetworkManagerJsonEnum.h | 99 ++ NetworkManagerJsonRpc.cpp | 737 +++++++------- NetworkManagerLogger.cpp | 25 +- NetworkManagerLogger.h | 7 + NetworkManagerPlugin.json | 15 - NetworkManagerRDKProxy.cpp | 170 ++-- WiFiSignalStrengthMonitor.cpp | 2 +- docs/NetworkManagerPlugin.md | 1558 ++++++++++++++---------------- 26 files changed, 2737 insertions(+), 2564 deletions(-) create mode 100644 NetworkManagerJsonEnum.h delete mode 100644 NetworkManagerPlugin.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c390399f..7bfac119d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 4) +set(VERSION_MINOR 5) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) @@ -34,6 +34,9 @@ set(PLUGIN_NETWORKMANAGER_STARTUPORDER "55" CACHE STRING "To configure startup o set(PLUGIN_LEGACY_NW_STARTUPORDER "56" CACHE STRING "To configure startup order of Legacy Network plugin") set(PLUGIN_LEGACY_WIFI_STARTUPORDER "56" CACHE STRING "To configure startup order of Legacy WiFi plugin") +set(PLUGIN_BUILD_REFERENCE ${PROJECT_VERSION} CACHE STRING "To Set the Hash for the plugin") +add_definitions(-DPLUGIN_BUILD_REFERENCE=${PLUGIN_BUILD_REFERENCE}) + if(ENABLE_GNOME_NETWORKMANAGER) pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(LIBNM REQUIRED libnm) @@ -45,6 +48,7 @@ endif () message("Setup ProxyStub for INetworkManager.h") find_package(CompileSettingsDebug CONFIG REQUIRED) find_package(ProxyStubGenerator REQUIRED) +find_package(JsonGenerator REQUIRED) set(ProxyStubGenerator_DIR ${CMAKE_SYSROOT}${CMAKE_INSTALL_PREFIX}/tools/cmake ${ProxyStubGenerator_DIR}) @@ -55,6 +59,9 @@ endif() message("The Search path is, ${GENERATOR_SEARCH_PATH}") ProxyStubGenerator(INPUT "${CMAKE_CURRENT_SOURCE_DIR}" OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/generated" INCLUDE_PATH ${GENERATOR_SEARCH_PATH}) +set(JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/NetworkManager.json") +JsonGenerator(CODE INPUT ${JSON_FILE} OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/generated" INCLUDE_PATH ${GENERATOR_SEARCH_PATH} CPPIFDIR "${CMAKE_CURRENT_SOURCE_DIR}" DOCS) + file(GLOB PROXY_STUB_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/generated/ProxyStubs*.cpp") message("Setup ${PROJECT_NAME} v${PROJECT_VERSION}") diff --git a/INetworkManager.h b/INetworkManager.h index f50c6296d..254eb0638 100644 --- a/INetworkManager.h +++ b/INetworkManager.h @@ -26,77 +26,73 @@ namespace WPEFramework { namespace Exchange { - enum myNetwork_ids { + enum myIDs { ID_NETWORKMANAGER = 0x800004E0, ID_NETWORKMANAGER_NOTIFICATION = ID_NETWORKMANAGER + 1, ID_NETWORKMANAGER_INTERFACE_DETAILS_ITERATOR = ID_NETWORKMANAGER + 2, ID_NETWORKMANAGER_WIFI_SECURITY_MODE_ITERATOR = ID_NETWORKMANAGER + 3 }; - /* @json */ + /* @json @text:keep */ struct EXTERNAL INetworkManager: virtual public Core::IUnknown { // All interfaces require a unique ID, defined in Ids.h enum { ID = ID_NETWORKMANAGER }; // Define the RPC methods - enum InterfaceType : uint8_t - { - INTERFACE_TYPE_ETHERNET, - INTERFACE_TYPE_WIFI, - INTERFACE_TYPE_P2P, + enum InterfaceType : uint8_t { + INTERFACE_TYPE_ETHERNET /* @text: ETHERNET */, + INTERFACE_TYPE_WIFI /* @text: WIFI */, + INTERFACE_TYPE_P2P /* @text: P2P */, }; struct EXTERNAL InterfaceDetails { - string m_type; - string m_name; - string m_mac; - bool m_isEnabled; - bool m_isConnected; + InterfaceType type; + string name; + string mac; + bool enabled; + bool connected; }; - enum IPAddressType : uint8_t + enum IPVersion : uint8_t { - IP_ADDRESS_V4, - IP_ADDRESS_V6, - IP_ADDRESS_BOTH + IP_ADDRESS_V4 /* @text: IPv4 */, + IP_ADDRESS_V6 /* @text: IPv6 */, }; - struct EXTERNAL IPAddressInfo { - string m_ipAddrType; - bool m_autoConfig; - string m_dhcpServer; - string m_v6LinkLocal; - string m_ipAddress; - uint32_t m_prefix; - string m_gateway; - string m_primaryDns; - string m_secondaryDns; + enum IPStatus : uint8_t + { + IP_LOST /* @text: LOST */, + IP_ACQUIRED /* @text: ACQUIRED */, }; - // Define the RPC methods - enum InternetStatus : uint8_t - { - INTERNET_NOT_AVAILABLE, - INTERNET_LIMITED, - INTERNET_CAPTIVE_PORTAL, - INTERNET_FULLY_CONNECTED, - INTERNET_UNKNOWN, + struct EXTERNAL IPAddress { + string ipversion /* @text: ipversion */; + bool autoconfig /* @text: autoconfig */; + string dhcpserver /* @text: dhcpserver */; + string ula /* @text: ula */; + string ipaddress /* @text: ipaddress */; + uint32_t prefix /* @text: prefix */; + string gateway /* @text: gateway */; + string primarydns /* @text: primarydns */; + string secondarydns /* @text: secondarydns */; }; - enum WiFiFrequency : uint8_t + // Define the RPC methods + enum InternetStatus : uint8_t { - WIFI_FREQUENCY_WHATEVER, - WIFI_FREQUENCY_2_4_GHZ, - WIFI_FREQUENCY_5_GHZ, - WIFI_FREQUENCY_6_GHZ + INTERNET_NOT_AVAILABLE /* @text: NO_INTERNET */, + INTERNET_LIMITED /* @text: LIMITED_INTERNET */, + INTERNET_CAPTIVE_PORTAL /* @text: CAPTIVE_PORTAL */, + INTERNET_FULLY_CONNECTED /* @text: FULLY_CONNECTED */, + INTERNET_UNKNOWN /* @text: NO_INTERNET */, }; enum WiFiWPS : uint8_t { - WIFI_WPS_PBC, - WIFI_WPS_PIN, - WIFI_WPS_SERIALIZED_PIN + WIFI_WPS_PBC /* @text: PBC */, + WIFI_WPS_PIN /* @text: PIN */, + WIFI_WPS_SERIALIZED_PIN /* @text: SERIALIZED_PIN */, }; enum WIFISecurityMode : uint8_t @@ -119,49 +115,53 @@ namespace WPEFramework }; struct EXTERNAL WiFiScanResults { - string m_ssid; - WIFISecurityMode m_securityMode; - string m_signalStrength; - double m_frequency; + string ssid; + WIFISecurityMode security; + string strength; + string frequency; }; struct EXTERNAL WiFiConnectTo { - string m_ssid; - string m_passphrase; - WIFISecurityMode m_securityMode; - string m_identity; - string m_caCert; - string m_clientCert; - string m_privateKey; - string m_privateKeyPasswd; - bool m_persistSSIDInfo; + string ssid; + string passphrase; + WIFISecurityMode security; + string ca_cert; + string client_cert; + string private_key; + string private_key_passwd; + string eap; + string eap_identity; + string eap_password; + string eap_phase1; + string eap_phase2; + bool persist; }; struct EXTERNAL WiFiSSIDInfo { - string m_ssid; - string m_bssid; - WIFISecurityMode m_securityMode; - string m_signalStrength; - double m_frequency; - string m_rate; - string m_noise; + string ssid; + string bssid; + WIFISecurityMode security; + string strength; + string frequency; + string rate; + string noise; }; struct EXTERNAL WIFISecurityModeInfo { - WIFISecurityMode m_securityMode; - string m_securityModeText; + WIFISecurityMode security; + string securityName; }; enum WiFiSignalQuality : uint8_t { - WIFI_SIGNAL_DISCONNECTED, - WIFI_SIGNAL_WEAK, - WIFI_SIGNAL_FAIR, - WIFI_SIGNAL_GOOD, - WIFI_SIGNAL_EXCELLENT + WIFI_SIGNAL_DISCONNECTED /* @text: Disconnected */, + WIFI_SIGNAL_WEAK /* @text: Weak */, + WIFI_SIGNAL_FAIR /* @text: Fair */, + WIFI_SIGNAL_GOOD /* @text: Good */, + WIFI_SIGNAL_EXCELLENT /* @text: Excellent */ }; - enum NMLogging : uint8_t + enum Logging : uint8_t { LOG_LEVEL_FATAL, LOG_LEVEL_ERROR, @@ -213,29 +213,29 @@ namespace WPEFramework virtual uint32_t SetPrimaryInterface (const string& interface/* @in */) = 0; /* @brief Enable/Disable the given interface */ - virtual uint32_t SetInterfaceState (const string& interface /* @in */, const bool& enabled /* @in */) = 0; + virtual uint32_t SetInterfaceState (const string& interface /* @in */, const bool enabled /* @in */) = 0; /* @brief Get the state of given interface */ - virtual uint32_t GetInterfaceState (const string& interface /* @in */, bool& isEnabled /* @out */) = 0; + virtual uint32_t GetInterfaceState (const string& interface /* @in */, bool& enabled /* @out */) = 0; /* @brief Get IP Address Of the Interface */ - virtual uint32_t GetIPSettings(const string& interface /* @in */, const string &ipversion /* @in */, IPAddressInfo& result /* @out */) = 0; + virtual uint32_t GetIPSettings(string& interface /* @inout */, const string& ipversion /* @in */, IPAddress& address /* @out */) = 0; /* @brief Set IP Address Of the Interface */ - virtual uint32_t SetIPSettings(const string& interface /* @in */, const string &ipversion /* @in */, const IPAddressInfo& address /* @in */) = 0; + virtual uint32_t SetIPSettings(const string& interface /* @in */, const IPAddress& address /* @in */) = 0; /* @brief Get STUN Endpoint to be used for identifying Public IP */ - virtual uint32_t GetStunEndpoint (string &endPoint /* @out */, uint32_t &port /* @out */, uint32_t &bindTimeout /* @out */, uint32_t &cacheTimeout /* @out */) const = 0; + virtual uint32_t GetStunEndpoint (string &endpoint /* @out */, uint32_t &port /* @out */, uint32_t &timeout /* @out */, uint32_t &cacheLifetime/* @out */) const = 0; /* @brief Set STUN Endpoint to be used to identify Public IP */ - virtual uint32_t SetStunEndpoint (string const endPoint /* @in */, const uint32_t port /* @in */, const uint32_t bindTimeout /* @in */, const uint32_t cacheTimeout /* @in */) = 0; + virtual uint32_t SetStunEndpoint (string const endpoint /* @in */, const uint32_t port /* @in */, const uint32_t timeout /* @in */, const uint32_t cacheLifetime /* @in */) = 0; /* @brief Get ConnectivityTest Endpoints */ - virtual uint32_t GetConnectivityTestEndpoints(IStringIterator*& endPoints/* @out */) const = 0; + virtual uint32_t GetConnectivityTestEndpoints(IStringIterator*& endpoints/* @out */) const = 0; /* @brief Set ConnectivityTest Endpoints */ - virtual uint32_t SetConnectivityTestEndpoints(IStringIterator* const endPoints /* @in */) = 0; + virtual uint32_t SetConnectivityTestEndpoints(IStringIterator* const endpoints /* @in */) = 0; /* @brief Get Internet Connectivty Status */ - virtual uint32_t IsConnectedToInternet(const string &ipversion /* @in */, InternetStatus &result /* @out */) = 0; + virtual uint32_t IsConnectedToInternet(string &ipversion /* @inout */, InternetStatus& status /* @out */) = 0; /* @brief Get Authentication URL if the device is behind Captive Portal */ - virtual uint32_t GetCaptivePortalURI(string &endPoints/* @out */) const = 0; + virtual uint32_t GetCaptivePortalURI(string &uri/* @out */) const = 0; /* @brief Start The Internet Connectivity Monitoring */ virtual uint32_t StartConnectivityMonitoring(const uint32_t interval /* @in */) = 0; @@ -243,18 +243,18 @@ namespace WPEFramework virtual uint32_t StopConnectivityMonitoring(void) const = 0; /* @brief Get the Public IP used for external world communication */ - virtual uint32_t GetPublicIP (const string &ipversion /* @in */, string& ipAddress /* @out */) = 0; + virtual uint32_t GetPublicIP (const string &ipversion /* @in */, string& ipaddress /* @out */) = 0; /* @brief Request for ping and get the response in as event. The GUID used in the request will be returned in the event. */ - virtual uint32_t Ping (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const uint16_t timeOutInSeconds /* @in */, const string guid /* @in */, string& response /* @out */) = 0; + virtual uint32_t Ping (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t count /* @in */, const uint16_t timeout /* @in */, const string guid /* @in */, string& response /* @out */) = 0; /* @brief Request for trace get the response in as event. The GUID used in the request will be returned in the event. */ - virtual uint32_t Trace (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const string guid /* @in */, string& response /* @out */) = 0; + virtual uint32_t Trace (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t nqueries /* @in */, const string guid /* @in */, string& response /* @out */) = 0; // WiFi Specific Methods /* @brief Initiate a WIFI Scan; This is Async method and returns the scan results as Event */ - virtual uint32_t StartWiFiScan(const WiFiFrequency frequency /* @in */) = 0; + virtual uint32_t StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) = 0; virtual uint32_t StopWiFiScan(void) = 0; virtual uint32_t GetKnownSSIDs(IStringIterator*& ssids /* @out */) = 0; @@ -265,17 +265,18 @@ namespace WPEFramework virtual uint32_t WiFiDisconnect(void) = 0; virtual uint32_t GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) = 0; - virtual uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) = 0; + virtual uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& pin /* @in */) = 0; virtual uint32_t StopWPS(void) = 0; virtual uint32_t GetWifiState(WiFiState &state /* @out */) = 0; - virtual uint32_t GetWiFiSignalStrength(string& ssid /* @out */, string& signalStrength /* @out */, WiFiSignalQuality& quality /* @out */) = 0; - virtual uint32_t GetSupportedSecurityModes(ISecurityModeIterator*& securityModes /* @out */) const = 0; + virtual uint32_t GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) = 0; + virtual uint32_t GetSupportedSecurityModes(ISecurityModeIterator*& modes/* @out */) const = 0; /* @brief Set the network manager plugin log level */ - virtual uint32_t SetLogLevel(const NMLogging& logLevel /* @in */) = 0; + virtual uint32_t SetLogLevel(const Logging& level /* @in */) = 0; + virtual uint32_t GetLogLevel(Logging& level /* @out */) = 0; /* @brief configure network manager plugin */ - virtual uint32_t Configure(const string& configLine /* @in */, NMLogging& logLevel /* @out */) = 0; + virtual uint32_t Configure(const string& configLine /* @in */) = 0; /* @event */ struct EXTERNAL INotification : virtual public Core::IUnknown @@ -283,15 +284,15 @@ namespace WPEFramework enum { ID = ID_NETWORKMANAGER_NOTIFICATION }; // Network Notifications that other processes can subscribe to - virtual void onInterfaceStateChange(const InterfaceState event /* @in */, const string interface /* @in */) = 0; - virtual void onActiveInterfaceChange(const string prevActiveInterface /* @in */, const string currentActiveinterface /* @in */) = 0; - virtual void onIPAddressChange(const string interface /* @in */, const bool isAcquired /* @in */, const bool isIPv6 /* @in */, const string ipAddress /* @in */) = 0; - virtual void onInternetStatusChange(const InternetStatus oldState /* @in */, const InternetStatus newstate /* @in */) = 0; + virtual void onInterfaceStateChange(const InterfaceState state /* @in */, const string interface /* @in */) = 0; + virtual void onActiveInterfaceChange(const string prevActiveInterface /* @in */, const string currentActiveInterface /* @in */) = 0; + virtual void onIPAddressChange(const string interface /* @in */, const string ipversion /* @in */, const string ipaddress /* @in */, const IPStatus status /* @in */) = 0; + virtual void onInternetStatusChange(const InternetStatus prevState /* @in */, const InternetStatus currState /* @in */) = 0; // WiFi Notifications that other processes can subscribe to - virtual void onAvailableSSIDs(const string jsonOfWiFiScanResults /* @in */) = 0; + virtual void onAvailableSSIDs(const string jsonOfScanResults /* @in */) = 0; virtual void onWiFiStateChange(const WiFiState state /* @in */) = 0; - virtual void onWiFiSignalStrengthChange(const string ssid /* @in */, const string signalLevel /* @in */, const WiFiSignalQuality signalQuality /* @in */) = 0; + virtual void onWiFiSignalStrengthChange(const string ssid /* @in */, const string strength /* @in */, const WiFiSignalQuality quality /* @in */) = 0; }; // Allow other processes to register/unregister from our notifications diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index d380f4e0f..6a86dc498 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -18,6 +18,7 @@ **/ #include "LegacyPlugin_NetworkAPIs.h" #include "NetworkManagerLogger.h" +#include "NetworkManagerJsonEnum.h" using namespace std; @@ -29,8 +30,18 @@ using namespace WPEFramework::Plugin; #define SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS 500 #define DEFAULT_PING_PACKETS 15 -#define LOG_INPARAM() { string json; parameters.ToString(json); NMLOG_INFO("%s : params=%s", __FUNCTION__, json.c_str() ); } -#define LOG_OUTPARAM() { string json; response.ToString(json); NMLOG_INFO("%s : response=%s", __FUNCTION__, json.c_str() ); } +#define LOG_INPARAM() { string json; parameters.ToString(json); NMLOG_INFO("params=%s", json.c_str() ); } +#define LOG_OUTPARAM() { string json; response.ToString(json); NMLOG_INFO("response=%s", json.c_str() ); } + +#define returnJson(rc) \ + { \ + if (Core::ERROR_NONE == rc) \ + response["success"] = true; \ + else \ + response["success"] = false; \ + LOG_OUTPARAM(); \ + return Core::ERROR_NONE; \ + } namespace WPEFramework { @@ -118,18 +129,14 @@ namespace WPEFramework auto security = m_service->QueryInterfaceByCallsign("SecurityAgent"); if (security != nullptr) { string payload = "http://localhost"; - if (security->CreateToken( - static_cast(payload.length()), - reinterpret_cast(payload.c_str()), - token) - == Core::ERROR_NONE) { + if (security->CreateToken(static_cast(payload.length()), reinterpret_cast(payload.c_str()), token) == Core::ERROR_NONE) { NMLOG_DEBUG("Network plugin got security token"); } else { NMLOG_WARNING("Network plugin failed to get security token"); } security->Release(); } else { - NMLOG_INFO("Network plugin: No security agent"); + NMLOG_DEBUG("Network plugin: No security agent"); } string query = "token=" + token; @@ -138,14 +145,13 @@ namespace WPEFramework if (interface != nullptr) { PluginHost::IShell::state state = interface->State(); - NMLOG_INFO("Current status of the %s plugin is %d", callsign.c_str(), state); - if((PluginHost::IShell::state::ACTIVATED == state) || (PluginHost::IShell::state::ACTIVATION == state)) { NMLOG_INFO("Dependency Plugin '%s' Ready", callsign.c_str()); } else { + NMLOG_INFO("Lets attempt to activate the Plugin '%s'", callsign.c_str()); activatePrimaryPlugin(); } interface->Release(); @@ -155,6 +161,7 @@ namespace WPEFramework m_networkmanager = make_shared >(_T(NETWORK_MANAGER_CALLSIGN), _T("org.rdk.Network"), query); subscribeToEvents(); + return string(); } @@ -230,7 +237,8 @@ namespace WPEFramework } #define CIDR_NETMASK_IP_LEN 32 -const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { +const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { + "0.0.0.0", "128.0.0.0", "192.0.0.0", "224.0.0.0", @@ -275,451 +283,520 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { uint32_t Network::getInterfaces (const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpResponse; - JsonArray array; - LOG_INPARAM(); - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetAvailableInterfaces"), parameters, tmpResponse); - else - rc = Core::ERROR_UNAVAILABLE; - - if ((rc == Core::ERROR_NONE) && (tmpResponse["success"].Boolean())) + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) { - const JsonArray& tmpArray = tmpResponse["interfaces"].Array(); - for (int i=0; iGetAvailableInterfaces(_interfaces); + if (Core::ERROR_NONE == rc) { - JsonObject each; - const JsonObject& arrayEntry = tmpArray[i].Object(); - each[_T("interface")] = arrayEntry["type"]; - each[_T("macAddress")] = arrayEntry["mac"]; - each[_T("enabled")] = arrayEntry["isEnabled"]; - each[_T("connected")] = arrayEntry["isConnected"]; - - array.Add(JsonValue(each)); + if (_interfaces != nullptr) + { + JsonArray array; + Exchange::INetworkManager::InterfaceDetails entry{}; + while (_interfaces->Next(entry) == true) + { + JsonObject each; + Core::JSON::EnumType type{entry.type}; + each["interface"] = type.Data(); + each["macAddress"] = entry.mac; + each["enabled"] = entry.enabled; + each["connected"] = entry.connected; + + array.Add(JsonValue(each)); + } + + _interfaces->Release(); + response["interfaces"] = array; + } } - - response["interfaces"] = array; - response["success"] = tmpResponse["success"]; + _nwmgr->Release(); } - LOG_OUTPARAM(); - return rc; + + returnJson(rc); } uint32_t Network::setStunEndPoint(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpParameters; - tmpParameters["endPoint"] = parameters["server"]; - tmpParameters["port"] = parameters["port"]; - tmpParameters["bindTimeout"] = parameters["timeout"]; - tmpParameters["cacheTimeout"] = parameters["cache_timeout"]; + string endPoint = parameters["server"].String(); + uint32_t port = parameters["port"].Number(); + uint32_t bindTimeout = parameters["timeout"].Number(); + uint32_t cacheTimeout = parameters["cache_timeout"].Number(); - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("SetStunEndpoint"), tmpParameters, response); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->SetStunEndpoint(endPoint, port, bindTimeout, cacheTimeout); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t Network::setInterfaceEnabled (const JsonObject& parameters, JsonObject& response) { - uint32_t rc = Core::ERROR_GENERAL; - string interface; - JsonObject tmpParameters; - LOG_INPARAM(); - if(caseInsensitiveCompare(parameters["interface"].String(),"WIFI")) - interface = "wlan0"; - else if(caseInsensitiveCompare(parameters["interface"].String(), "ETHERNET")) - interface = "eth0"; - - tmpParameters["interface"] = interface; - tmpParameters["enabled"] = parameters["enabled"]; - - if (m_networkmanager) + uint32_t rc = Core::ERROR_GENERAL; + if (parameters.HasLabel("interface") && parameters.HasLabel("enabled")) { - rc = m_networkmanager->Invoke(5000, _T("SetInterfaceState"), tmpParameters, response); + const string givenInterface = parameters["interface"].String(); + const bool enabled = parameters["enabled"].Boolean(); + const string interface = getInterfaceTypeToName(givenInterface); + + if ("wlan0" != interface && "eth0" != interface) + rc = Core::ERROR_BAD_REQUEST; + else + { + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->SetInterfaceState(interface, enabled); + _nwmgr->Release(); + } + else + rc = Core::ERROR_UNAVAILABLE; + } } else - rc = Core::ERROR_UNAVAILABLE; + rc = Core::ERROR_BAD_REQUEST; - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t Network::getDefaultInterface (const JsonObject& parameters, JsonObject& response) { - uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpResponse; - LOG_INPARAM(); + uint32_t rc = Core::ERROR_GENERAL; + string interface; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetPrimaryInterface"), parameters, tmpResponse); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->GetPrimaryInterface(interface); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) { - if ("wlan0" == tmpResponse["interface"].String()) - response["interface"] = "WIFI"; - else if("eth0" == tmpResponse["interface"].String()) - response["interface"] = "ETHERNET"; - response["success"] = tmpResponse["success"]; + string mappedInterface = getInterfaceNameToType(interface); + response["interface"] = mappedInterface; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t Network::setDefaultInterface(const JsonObject& parameters, JsonObject& response) { - uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpParameters; - string interface; LOG_INPARAM(); - if(caseInsensitiveCompare(parameters["interface"].String(), "WIFI")) - tmpParameters["interface"] = "wlan0"; - else if(caseInsensitiveCompare(parameters["interface"].String(), "ETHERNET")) - tmpParameters["interface"] = "eth0"; - - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("SetPrimaryInterface"), tmpParameters, response); + uint32_t rc = Core::ERROR_GENERAL; + string givenInterface = parameters["interface"].String(); + const string interface = getInterfaceTypeToName(givenInterface); + + if ("wlan0" != interface && "eth0" != interface) + { + rc = Core::ERROR_BAD_REQUEST; + return rc; + } + + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->SetPrimaryInterface(interface); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; - LOG_OUTPARAM(); - - return rc; + returnJson(rc); } uint32_t Network::setIPSettings(const JsonObject& parameters, JsonObject& response) { - uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpResponse; - JsonObject tmpParameters; LOG_INPARAM(); - - if(caseInsensitiveCompare(parameters["interface"].String(), "WIFI")) - tmpParameters["interface"] = "wlan0"; - else if(caseInsensitiveCompare(parameters["interface"].String(), "ETHERNET")) - tmpParameters["interface"] = "eth0"; - - tmpParameters["ipversion"] = parameters["ipversion"]; - tmpParameters["autoconfig"] = parameters["autoconfig"]; - tmpParameters["ipaddress"] = parameters["ipaddr"]; - auto it = find(begin(CIDR_PREFIXES), end(CIDR_PREFIXES), parameters["netmask"].String()); - if (it == end(CIDR_PREFIXES)) - return rc; - else - tmpParameters["prefix"] = distance(begin(CIDR_PREFIXES), it); - tmpParameters["gateway"] = parameters["gateway"]; - tmpParameters["primarydns"] = parameters["primarydns"]; - tmpParameters["secondarydns"] = parameters["secondarydns"]; + uint32_t rc = Core::ERROR_GENERAL; + Exchange::INetworkManager::IPAddress address{}; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("SetIPSettings"), tmpParameters, tmpResponse); - else - rc = Core::ERROR_UNAVAILABLE; + string givenInterface = ""; + string interface = ""; + string ipversion = ""; - if (Core::ERROR_NONE == rc) + if (parameters.HasLabel("interface")) { - response["supported"] = true; - response["success"] = tmpResponse["success"]; + givenInterface = parameters["interface"].String(); + interface = getInterfaceTypeToName(givenInterface); + + if ("wlan0" != interface && "eth0" != interface) + { + return Core::ERROR_BAD_REQUEST; + } + } + else + { + return Core::ERROR_BAD_REQUEST; } - LOG_OUTPARAM(); - return rc; - } - uint32_t Network::getIPSettings (const JsonObject& parameters, JsonObject& response) - { - uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpResponse; + address.autoconfig = parameters["autoconfig"].Boolean(); + if (!address.autoconfig) + { + address.ipaddress = parameters["ipaddr"].String(); + address.ipversion = parameters["ipversion"].String(); + address.gateway = parameters["gateway"].String(); + address.primarydns = parameters["primarydns"].String(); + address.secondarydns = parameters["secondarydns"].String(); + + auto it = find(begin(CIDR_PREFIXES), end(CIDR_PREFIXES), parameters["netmask"].String()); + if (it == end(CIDR_PREFIXES)) + return Core::ERROR_BAD_REQUEST; + else + address.prefix = distance(begin(CIDR_PREFIXES), it); - LOG_INPARAM(); - rc = getIPSettings2(parameters, tmpResponse); + } - if (tmpResponse.HasLabel("ipaddr")) - response = tmpResponse; - else + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) { - NMLOG_INFO("IP Address not assigned to the given interface yet"); - response["success"] = false; + rc = _nwmgr->SetIPSettings(interface, address); + _nwmgr->Release(); } + else + rc = Core::ERROR_UNAVAILABLE; - LOG_OUTPARAM(); - return rc; + returnJson(rc); } - uint32_t Network::getIPSettings2 (const JsonObject& parameters, JsonObject& response) + uint32_t Network::internalGetIPSettings(const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpResponse; - JsonObject tmpParameters; - size_t index; + string interface{}; + string givenInterface{}; + string ipversion{}; - LOG_INPARAM(); - - if (parameters.HasLabel("ipversion")) - tmpParameters["ipversion"] = parameters["ipversion"]; if (parameters.HasLabel("interface")) { - if (caseInsensitiveCompare(parameters["interface"].String(), "WIFI")) - tmpParameters["interface"] = "wlan0"; - else if(caseInsensitiveCompare(parameters["interface"].String(), "ETHERNET")) - tmpParameters["interface"] = "eth0"; + givenInterface = parameters["interface"].String(); + interface = getInterfaceTypeToName(givenInterface); + + if (!interface.empty() && "wlan0" != interface && "eth0" != interface) + { + return Core::ERROR_BAD_REQUEST; + } } - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetIPSettings"), tmpParameters, tmpResponse); - else - rc = Core::ERROR_UNAVAILABLE; + if (parameters.HasLabel("ipversion")) + ipversion = parameters["ipversion"].String(); - if (Core::ERROR_NONE == rc) + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) { - string ipversion = tmpResponse["ipversion"].String(); + Exchange::INetworkManager::IPAddress address{}; + rc = _nwmgr->GetIPSettings(interface, ipversion, address); + _nwmgr->Release(); - if (parameters.HasLabel("interface")) - { - response["interface"] = parameters["interface"]; - } - else + if (Core::ERROR_NONE == rc) { - if ("wlan0" == m_defaultInterface) - response["interface"] = "WIFI"; - else if("eth0" == m_defaultInterface) - response["interface"] = "ETHERNET"; - } + givenInterface = getInterfaceNameToType(interface); - response["autoconfig"] = tmpResponse["autoconfig"]; - if(!tmpResponse["ipaddress"].String().empty()) - { - response["ipversion"] = tmpResponse["ipversion"]; - response["ipaddr"] = tmpResponse["ipaddress"]; - if (caseInsensitiveCompare(ipversion, "IPV4")) - { - index = tmpResponse["prefix"].Number(); - if(CIDR_NETMASK_IP_LEN <= index) - return Core::ERROR_GENERAL; - response["netmask"] = CIDR_PREFIXES[index]; - } - else if (caseInsensitiveCompare(ipversion, "IPV6")) + response["interface"] = givenInterface; + response["ipversion"] = address.ipversion; + response["autoconfig"] = address.autoconfig; + if (!address.ipaddress.empty()) { - response["netmask"] = tmpResponse["prefix"]; + response["ipaddr"] = address.ipaddress; + if ("IPv4" == address.ipversion) + { + if(address.prefix > CIDR_NETMASK_IP_LEN) + { + rc = Core::ERROR_GENERAL; + return rc; + } + response["netmask"] = CIDR_PREFIXES[address.prefix]; + } + else + response["netmask"] = address.prefix; + + response["dhcpserver"] = address.dhcpserver; + response["gateway"] = address.gateway; + response["primarydns"] = address.primarydns; + response["secondarydns"] = address.secondarydns; } - response["gateway"] = tmpResponse["gateway"]; - response["dhcpserver"] = tmpResponse["dhcpserver"]; - response["primarydns"] = tmpResponse["primarydns"]; - response["secondarydns"] = tmpResponse["secondarydns"]; } - response["success"] = tmpResponse["success"]; } - LOG_OUTPARAM(); return rc; } - uint32_t Network::isConnectedToInternet(const JsonObject& parameters, JsonObject& response) + uint32_t Network::getIPSettings (const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpResponse; LOG_INPARAM(); - string ipversion = parameters["ipversion"].String(); + rc = internalGetIPSettings(parameters, tmpResponse); - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("IsConnectedToInternet"), parameters, tmpResponse); + if (tmpResponse.HasLabel("ipaddr") && (!tmpResponse["ipaddr"].String().empty())) + response = tmpResponse; else - rc = Core::ERROR_UNAVAILABLE; - - if (Core::ERROR_NONE == rc) { - response["connectedToInternet"] = tmpResponse["isConnectedToInternet"]; - if(caseInsensitiveCompare(ipversion, "IPV4") || caseInsensitiveCompare(ipversion, "IPV6")) - response["ipversion"] = ipversion.c_str(); - response["success"] = true; + NMLOG_INFO("IP Address not assigned to the given interface yet"); + rc = Core::ERROR_GENERAL; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } - uint32_t Network::getInternetConnectionState(const JsonObject& parameters, JsonObject& response) + + uint32_t Network::getIPSettings2 (const JsonObject& parameters, JsonObject& response) { + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - uint32_t rc1 = Core::ERROR_GENERAL; - string endPoint; - JsonObject tmpResponse; - JsonObject captivePortalResponse; - JsonObject tmpParameters; - string status; + rc = internalGetIPSettings(parameters, response); + + returnJson(rc); + } + + uint32_t Network::isConnectedToInternet(const JsonObject& parameters, JsonObject& response) + { + uint32_t rc = Core::ERROR_GENERAL; LOG_INPARAM(); - string ipversion = parameters["ipversion"].String(); + string ipversion{}; + Exchange::INetworkManager::InternetStatus status{}; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("IsConnectedToInternet"), parameters, tmpResponse); - else - rc = Core::ERROR_UNAVAILABLE; + if (parameters.HasLabel("ipversion")) + ipversion = parameters["ipversion"].String(); - if (Core::ERROR_NONE == rc) + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr != nullptr) { - status = tmpResponse["status"].String(); - NMLOG_DEBUG("status = %s", status.c_str() ); - NMLOG_DEBUG("tmpResponse[status].String() = %s", tmpResponse["status"].String().c_str() ); - if(status == "LIMITED_INTERNET") - response["state"] = static_cast(2); - else if(status == "CAPTIVE_PORTAL") + rc = _nwmgr->IsConnectedToInternet(ipversion, status); + _nwmgr->Release(); + + if (Core::ERROR_NONE == rc) { - response["state"] = static_cast(1); - rc1 = getCaptivePortalURI(tmpParameters, captivePortalResponse); - if (Core::ERROR_NONE == rc1) - response["uri"] = captivePortalResponse["uri"]; + response["ipversion"] = ipversion; + response["connectedToInternet"] = (Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED == status); } - else if(status == "FULLY_CONNECTED") - response["state"] = static_cast(3); - else - response["state"] = static_cast(0); + } + + returnJson(rc); + } + + uint32_t Network::getInternetConnectionState(const JsonObject& parameters, JsonObject& response) + { + uint32_t rc = Core::ERROR_GENERAL; + LOG_INPARAM(); + string ipversion{}; + Exchange::INetworkManager::InternetStatus status{}; - if(caseInsensitiveCompare(ipversion, "IPV4") || caseInsensitiveCompare(ipversion, "IPV6")) - response["ipversion"] = ipversion.c_str(); - response["success"] = true; + if (parameters.HasLabel("ipversion")) + ipversion = parameters["ipversion"].String(); + + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr != nullptr) + { + rc = _nwmgr->IsConnectedToInternet(ipversion, status); + + if (Core::ERROR_NONE == rc) + { + response["ipversion"] = ipversion; + response["state"] = JsonValue(status); + if (Exchange::INetworkManager::InternetStatus::INTERNET_CAPTIVE_PORTAL == status) + { + string uri{}; + _nwmgr->GetCaptivePortalURI(uri); + response["URI"] = uri; + } + } + _nwmgr->Release(); } - LOG_OUTPARAM(); - return rc; + + returnJson(rc); } + uint32_t Network::doPing(const JsonObject& parameters, JsonObject& response) { - uint32_t rc = Core::ERROR_GENERAL; - struct in_addr ipv4address; - struct in6_addr ipv6address; - JsonObject tmpParameters; - JsonObject tmpResponse; + LOG_INPARAM(); + string result{}; string endpoint{}; - + uint32_t rc = Core::ERROR_GENERAL; LOG_INPARAM(); + if (parameters.HasLabel("endpoint")) + { + string guid{}; + string ipversion{"IPv4"}; + uint32_t noOfRequest = 3; + uint16_t timeOutInSeconds = 5; - endpoint = parameters["endpoint"].String(); + endpoint = parameters["endpoint"].String(); - if (inet_pton(AF_INET, endpoint.c_str(), &ipv4address) > 0) - tmpParameters["ipversion"] = "IPv4"; - else if (inet_pton(AF_INET6, endpoint.c_str(), &ipv6address) > 0) - tmpParameters["ipversion"] = "IPv6"; + if (parameters.HasLabel("ipversion")) + ipversion = parameters["ipversion"].String(); - if (parameters.HasLabel("packets")) - tmpParameters["noOfRequest"] = parameters["packets"]; - else - tmpParameters["noOfRequest"] = DEFAULT_PING_PACKETS; - tmpParameters["endpoint"] = parameters["endpoint"]; - tmpParameters["timeout"] = 5; - tmpParameters["guid"] = parameters["guid"]; + if (parameters.HasLabel("packets")) + noOfRequest = parameters["packets"].Number(); - if (m_networkmanager) - rc = m_networkmanager->Invoke(15000, _T("Ping"), tmpParameters, response); - else - rc = Core::ERROR_UNAVAILABLE; + if (parameters.HasLabel("guid")) + guid = parameters["guid"].String(); + + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->Ping(ipversion, endpoint, noOfRequest, timeOutInSeconds, guid, result); + _nwmgr->Release(); + } + else + rc = Core::ERROR_UNAVAILABLE; + } if (Core::ERROR_NONE == rc) { - response["target"] = parameters["endpoint"]; - response["guid"] = parameters["guid"]; + JsonObject reply; + reply.FromString(result); + response = reply; + response["target"] = endpoint; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t Network::doTrace(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpParameters; - tmpParameters["endpoint"] = parameters["endpoint"].String(); - tmpParameters["packets"] = parameters["packets"].Number(); - tmpParameters["guid"] = ""; + if (parameters.HasLabel("endpoint")) + { + string result{}; + string ipversion{"IPv4"}; + const string endpoint = parameters["endpoint"].String(); + const uint32_t noOfRequest = parameters["packets"].Number(); + const string guid = parameters["guid"].String(); - if(m_networkmanager) - rc = m_networkmanager->Invoke(20000, _T("Trace"), tmpParameters, response); - else - rc = Core::ERROR_UNAVAILABLE; + if (parameters.HasLabel("ipversion")) + ipversion = parameters["ipversion"].String(); - LOG_OUTPARAM(); - return rc; + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->Trace(ipversion, endpoint, noOfRequest, guid, result); + _nwmgr->Release(); + } + else + rc = Core::ERROR_UNAVAILABLE; + + if (Core::ERROR_NONE == rc) + { + JsonObject reply; + reply.FromString(result); + response = reply; + response["target"] = endpoint; + } + } + returnJson(rc); } uint32_t Network::getPublicIP(const JsonObject& parameters, JsonObject& response) { - uint32_t rc = Core::ERROR_GENERAL; - string interface; - string ipversion{"IPv4"}; - JsonObject tmpParameters; - JsonObject tmpResponse; - LOG_INPARAM(); - if(caseInsensitiveCompare(parameters["iface"].String(), "WIFI")) - interface = "wlan0"; - else if(caseInsensitiveCompare(parameters["iface"].String(), "ETHERNET")) - interface = "eth0"; - - if(parameters["ipv6"].Boolean()) - ipversion = "IPv6"; - else - ipversion = "IPv4"; - - tmpParameters["interface"] = interface; - tmpParameters["ipversion"] = ipversion; + uint32_t rc = Core::ERROR_GENERAL; + string ipAddress{}; + string ipversion = "IPv4"; + if (parameters.HasLabel("ipversion")) + ipversion = parameters["ipversion"].String(); - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetPublicIP"), tmpParameters, tmpResponse); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->GetPublicIP(ipversion, ipAddress); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) { - response["public_ip"] = tmpResponse["publicIP"]; - response["success"] = tmpResponse["success"]; + response["public_ip"] = ipAddress; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t Network::isInterfaceEnabled (const JsonObject& parameters, JsonObject& response) { - uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpParameters; - LOG_INPARAM(); - string interface = parameters["interface"].String(); - string newInterface = ""; + uint32_t rc = Core::ERROR_GENERAL; - if(caseInsensitiveCompare(interface, "WIFI")) - newInterface = "wlan0"; - else if(caseInsensitiveCompare(interface, "ETHERNET")) - newInterface = "eth0"; + if (parameters.HasLabel("interface")) + { + bool enabled; + const string givenInterface = parameters["interface"].String(); + const string interface = getInterfaceTypeToName(givenInterface); - tmpParameters["interface"] = newInterface; + if ("wlan0" != interface && "eth0" != interface) + return Core::ERROR_BAD_REQUEST; + + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->GetInterfaceState(interface, enabled); + _nwmgr->Release(); + } + else + rc = Core::ERROR_UNAVAILABLE; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetInterfaceState"), tmpParameters, response); + if (Core::ERROR_NONE == rc) + response["enabled"] = enabled; + } else - rc = Core::ERROR_UNAVAILABLE; - - LOG_OUTPARAM(); + rc = Core::ERROR_BAD_REQUEST; - return rc; + returnJson(rc); } uint32_t Network::setConnectivityTestEndpoints(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("SetConnectivityTestEndpoints"), parameters, response); + ::WPEFramework::RPC::IIteratorType* endpointsIter{}; + JsonArray array = parameters["endpoints"].Array(); + + if (0 == array.Length() || 5 < array.Length()) + { + NMLOG_DEBUG("minimum of 1 to maximum of 5 Urls are allowed"); + returnJson(rc); + } + + std::vector endpoints; + JsonArray::Iterator index(array.Elements()); + while (index.Next() == true) + { + if (Core::JSON::Variant::type::STRING == index.Current().Content()) + { + endpoints.push_back(index.Current().String().c_str()); + } + else + { + NMLOG_DEBUG("Unexpected variant type"); + returnJson(rc); + } + } + endpointsIter = (Core::Service::Create(endpoints)); + + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + rc = _nwmgr->SetConnectivityTestEndpoints(endpointsIter); else rc = Core::ERROR_UNAVAILABLE; - LOG_OUTPARAM(); - return rc; + if(_nwmgr) + _nwmgr->Release(); + + if (endpointsIter) + endpointsIter->Release(); + + returnJson(rc); } uint32_t Network::startConnectivityMonitoring(const JsonObject& parameters, JsonObject& response) @@ -729,28 +806,37 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { uint32_t interval = parameters["interval"].Number(); NMLOG_DEBUG("connectivity interval = %d", interval); - - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("StartConnectivityMonitoring"), parameters, response); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + rc = _nwmgr->StartConnectivityMonitoring(interval); else rc = Core::ERROR_UNAVAILABLE; - LOG_OUTPARAM(); - return rc; + if(_nwmgr) + _nwmgr->Release(); + + returnJson(rc); } uint32_t Network::getCaptivePortalURI(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string endPoint; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetCaptivePortalURI"), parameters, response); + string uri; + + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->GetCaptivePortalURI(uri); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; - LOG_OUTPARAM(); - return rc; + if (Core::ERROR_NONE == rc) + response["uri"] = uri; + + returnJson(rc); } uint32_t Network::stopConnectivityMonitoring(const JsonObject& parameters, JsonObject& response) @@ -758,13 +844,16 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("StopConnectivityMonitoring"), parameters, response); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->StopConnectivityMonitoring(); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t Network::getStbIp(const JsonObject& parameters, JsonObject& response) @@ -773,18 +862,16 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { LOG_INPARAM(); JsonObject tmpResponse; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetIPSettings"), parameters, tmpResponse); - else - rc = Core::ERROR_UNAVAILABLE; + rc = internalGetIPSettings(parameters, tmpResponse); - if (Core::ERROR_NONE == rc) + if ((Core::ERROR_NONE == rc) && tmpResponse.HasLabel("ipaddr")) { - response["ip"] = tmpResponse["ipaddress"]; - response["success"] = true; + response["ip"] = tmpResponse["ipaddr"]; } - LOG_OUTPARAM(); - return rc; + else + rc = Core::ERROR_UNAVAILABLE; + + returnJson(rc); } uint32_t Network::getSTBIPFamily(const JsonObject& parameters, JsonObject& response) @@ -796,18 +883,16 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { tmpParameters["ipversion"] = parameters["family"]; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetIPSettings"), tmpParameters, tmpResponse); - else - rc = Core::ERROR_UNAVAILABLE; + rc = internalGetIPSettings(tmpParameters, tmpResponse); - if (Core::ERROR_NONE == rc) + if ((Core::ERROR_NONE == rc) && tmpResponse.HasLabel("ipaddr")) { - response["ip"] = tmpResponse["ipaddress"]; - response["success"] = true; + response["ip"] = tmpResponse["ipaddr"]; } - LOG_OUTPARAM(); - return rc; + else + rc = Core::ERROR_UNAVAILABLE; + + returnJson(rc); } /** Private */ @@ -864,33 +949,41 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { if (m_subsIfaceStateChange && m_subsActIfaceChange && m_subsIPAddrChange && m_subsInternetChange) { m_timer.stop(); - NMLOG_INFO("subscriber timer stoped"); + NMLOG_INFO("All the required events are subscribed; Retry timer stoped"); } else { m_timer.start(SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS); - NMLOG_INFO("subscriber timer started"); + NMLOG_INFO("Few required events are yet to be subscribed; Retry timer started"); } } - string Network::getInterfaceMapping(const string & interface) + string Network::getInterfaceNameToType(const string & interface) { if(interface == "wlan0") return string("WIFI"); else if(interface == "eth0") return string("ETHERNET"); - return string(" "); + return string(""); + } + + string Network::getInterfaceTypeToName(const string & interface) + { + if(interface == "WIFI") + return string("wlan0"); + else if(interface == "ETHERNET") + return string("eth0"); + return string(""); } /** Event Handling and Publishing */ void Network::ReportonInterfaceStateChange(const JsonObject& parameters) { - LOG_INPARAM(); JsonObject legacyParams; string json; - string state = parameters["state"].String(); + string state = parameters["status"].String(); - legacyParams["interface"] = getInterfaceMapping(parameters["interface"].String()); + legacyParams["interface"] = getInterfaceNameToType(parameters["interface"].String()); /* State check */ if(state == "INTERFACE_ADDED") @@ -902,14 +995,15 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { else if(state == "INTERFACE_LINK_DOWN") legacyParams["status"] = "DISCONNECTED"; + legacyParams.ToString(json); if((state == "INTERFACE_ADDED") || (state == "INTERFACE_REMOVED")) { - NMLOG_INFO("Posting onInterfaceStatusChanged"); + NMLOG_INFO("Posting onInterfaceStatusChanged as %s", json.c_str()); Notify("onInterfaceStatusChanged", legacyParams); } else if((state == "INTERFACE_LINK_UP") || (state == "INTERFACE_LINK_DOWN")) { - NMLOG_INFO("Posting onConnectionStatusChanged"); + NMLOG_INFO("Posting onConnectionStatusChanged as %s", json.c_str()); Notify("onConnectionStatusChanged", legacyParams); } @@ -918,23 +1012,25 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { void Network::ReportonActiveInterfaceChange(const JsonObject& parameters) { - LOG_INPARAM(); JsonObject legacyParams; - legacyParams["oldInterfaceName"] = getInterfaceMapping(parameters["oldInterfaceName"].String()); - legacyParams["newInterfaceName"] = getInterfaceMapping(parameters["newInterfaceName"].String()); + legacyParams["oldInterfaceName"] = getInterfaceNameToType(parameters["oldInterfaceName"].String()); + legacyParams["newInterfaceName"] = getInterfaceNameToType(parameters["newInterfaceName"].String()); m_defaultInterface = parameters["newInterfaceName"].String(); - NMLOG_INFO("Posting onDefaultInterfaceChanged"); + + string json; + legacyParams.ToString(json); + + NMLOG_INFO("Posting onDefaultInterfaceChanged as %s", json.c_str()); Notify("onDefaultInterfaceChanged", legacyParams); return; } void Network::ReportonIPAddressChange(const JsonObject& parameters) { - LOG_INPARAM(); JsonObject legacyParams; - legacyParams["interface"] = getInterfaceMapping(parameters["interface"].String()); + legacyParams["interface"] = getInterfaceNameToType(parameters["interface"].String()); if (parameters["isIPv6"].Boolean()) { @@ -946,7 +1042,11 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { } legacyParams["status"] = parameters["status"]; - NMLOG_INFO("Posting onIPAddressStatusChanged"); + + string json; + legacyParams.ToString(json); + NMLOG_INFO("Posting onIPAddressStatusChanged as %s", json.c_str()); + Notify("onIPAddressStatusChanged", legacyParams); if ("ACQUIRED" == parameters["status"].String()) @@ -957,14 +1057,20 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { void Network::ReportonInternetStatusChange(const JsonObject& parameters) { - NMLOG_INFO("Posting onInternetStatusChange"); - Notify("onInternetStatusChange", parameters); + JsonObject legacyParams; + string json; + + legacyParams["state"] = parameters["state"]; + legacyParams["status"] = parameters["status"]; + legacyParams.ToString(json); + + NMLOG_INFO("Posting onInternetStatusChanged as, %s", json.c_str()); + Notify("onInternetStatusChange", legacyParams); return; } void Network::onInterfaceStateChange(const JsonObject& parameters) { - LOG_INPARAM(); if(_gNWInstance) _gNWInstance->ReportonInterfaceStateChange(parameters); @@ -973,7 +1079,6 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { void Network::onActiveInterfaceChange(const JsonObject& parameters) { - LOG_INPARAM(); if(_gNWInstance) _gNWInstance->ReportonActiveInterfaceChange(parameters); return; @@ -981,7 +1086,6 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { void Network::onIPAddressChange(const JsonObject& parameters) { - LOG_INPARAM(); if(_gNWInstance) _gNWInstance->ReportonIPAddressChange(parameters); return; @@ -989,7 +1093,6 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { void Network::onInternetStatusChange(const JsonObject& parameters) { - LOG_INPARAM(); if(_gNWInstance) _gNWInstance->ReportonInternetStatusChange(parameters); } diff --git a/LegacyPlugin_NetworkAPIs.h b/LegacyPlugin_NetworkAPIs.h index 037b91b0d..df3019e1c 100644 --- a/LegacyPlugin_NetworkAPIs.h +++ b/LegacyPlugin_NetworkAPIs.h @@ -6,6 +6,7 @@ #include "Module.h" #include "core/Link.h" #include "NetworkManagerTimer.h" +#include "INetworkManager.h" namespace WPEFramework { namespace Plugin { @@ -31,8 +32,10 @@ namespace WPEFramework { void registerLegacyMethods(void); void unregisterLegacyMethods(void); void subscribeToEvents(void); - static std::string getInterfaceMapping(const std::string &interface); void activatePrimaryPlugin(); + uint32_t internalGetIPSettings(const JsonObject& parameters, JsonObject& response); + string getInterfaceNameToType(const string & interface); + string getInterfaceTypeToName(const string & interface); /* Methods */ uint32_t getInterfaces(const JsonObject& parameters, JsonObject& response); @@ -84,6 +87,7 @@ namespace WPEFramework { private: PluginHost::IShell* m_service; std::shared_ptr> m_networkmanager; + //WPEFramework::Exchange::INetworkManager* m_nwmgr; string m_defaultInterface; NetworkManagerTimer m_timer; diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index ac2872432..ba0c64278 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -18,7 +18,7 @@ **/ #include "LegacyPlugin_WiFiManagerAPIs.h" #include "NetworkManagerLogger.h" -#include "INetworkManager.h" +#include "NetworkManagerJsonEnum.h" using namespace std; using namespace WPEFramework::Plugin; @@ -28,8 +28,18 @@ using namespace WPEFramework::Plugin; #define NETWORK_MANAGER_CALLSIGN "org.rdk.NetworkManager.1" #define SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS 500 -#define LOG_INPARAM() { string json; parameters.ToString(json); NMLOG_INFO("%s : params=%s", __FUNCTION__, json.c_str() ); } -#define LOG_OUTPARAM() { string json; response.ToString(json); NMLOG_INFO("%s : response=%s", __FUNCTION__, json.c_str() ); } +#define LOG_INPARAM() { string json; parameters.ToString(json); NMLOG_INFO("params=%s", json.c_str() ); } +#define LOG_OUTPARAM() { string json; response.ToString(json); NMLOG_INFO("response=%s", json.c_str() ); } + +#define returnJson(rc) \ + { \ + if (Core::ERROR_NONE == rc) \ + response["success"] = true; \ + else \ + response["success"] = false; \ + LOG_OUTPARAM(); \ + return rc; \ + } namespace WPEFramework { @@ -134,14 +144,13 @@ namespace WPEFramework if (interface != nullptr) { PluginHost::IShell::state state = interface->State(); - NMLOG_INFO("Current status of the %s plugin is %d", callsign.c_str(), state); - if((PluginHost::IShell::state::ACTIVATED == state) || (PluginHost::IShell::state::ACTIVATION == state)) { NMLOG_INFO("Dependency Plugin '%s' Ready", callsign.c_str()); } else { + NMLOG_INFO("Lets attempt to activate the Plugin '%s'", callsign.c_str()); activatePrimaryPlugin(); } interface->Release(); @@ -219,156 +228,218 @@ namespace WPEFramework uint32_t WiFiManager::cancelWPSPairing (const JsonObject& parameters, JsonObject& response) { - uint32_t rc = Core::ERROR_GENERAL; - LOG_INPARAM(); + uint32_t rc = Core::ERROR_GENERAL; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("StopWPS"), parameters, response); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->StopWPS(); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) - { response["result"] = string(); - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t WiFiManager::clearSSID (const JsonObject& parameters, JsonObject& response) { - uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpParameters; - tmpParameters["ssid"] = "ssid"; // The input ssid name does not matter at this point in time as there is only one ssid persisted at any given point in time. - LOG_INPARAM(); + uint32_t rc = Core::ERROR_GENERAL; + string ssid{}; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("RemoveKnownSSID"), tmpParameters, response); + ssid = parameters["ssid"].String(); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->RemoveKnownSSID(ssid); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) - { response["result"] = 0; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t WiFiManager::connect(const JsonObject& parameters, JsonObject& response) { - LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; + Exchange::INetworkManager::WiFiConnectTo ssid{}; + NMLOG_INFO("Entry to %s\n", __FUNCTION__); - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("WiFiConnect"), parameters, response); + if (parameters.HasLabel("ssid")) + ssid.ssid = parameters["ssid"].String(); else - rc = Core::ERROR_UNAVAILABLE; + returnJson(rc); - if (Core::ERROR_NONE == rc) + if (parameters.HasLabel("passphrase")) + ssid.passphrase = parameters["passphrase"].String(); + + if (parameters.HasLabel("securityMode")) + ssid.security= static_cast (parameters["securityMode"].Number()); + + ssid.persist = true; + + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) { - response["success"] = true; + rc = _nwmgr->WiFiConnect(ssid); + _nwmgr->Release(); } - LOG_OUTPARAM(); - return rc; + else + rc = Core::ERROR_UNAVAILABLE; + + returnJson(rc); } uint32_t WiFiManager::getConnectedSSID (const JsonObject& parameters, JsonObject& response) { - uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpResponse; - LOG_INPARAM(); + uint32_t rc = Core::ERROR_GENERAL; + Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetConnectedSSID"), parameters, tmpResponse); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->GetConnectedSSID(ssidInfo); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) { - response["ssid"] = tmpResponse["ssid"]; - response["bssid"] = tmpResponse["bssid"]; - response["rate"] = tmpResponse["rate"]; - response["noise"] = tmpResponse["noise"]; - response["security"] = tmpResponse["securityMode"]; - response["signalStrength"] = tmpResponse["signalStrength"]; - response["frequency"] = tmpResponse["frequency"]; - response["success"] = tmpResponse["success"]; + response["ssid"] = ssidInfo.ssid; + response["bssid"] = ssidInfo.bssid; + response["rate"] = ssidInfo.rate; + response["noise"] = ssidInfo.noise; + response["security"] = JsonValue(ssidInfo.security); + response["signalStrength"] = ssidInfo.strength; + response["frequency"] = ssidInfo.frequency; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t WiFiManager::getCurrentState(const JsonObject& parameters, JsonObject& response) { + Exchange::INetworkManager::WiFiState state; uint32_t rc = Core::ERROR_GENERAL; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetWifiState"), parameters, response); + LOG_INPARAM(); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->GetWifiState(state); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; - LOG_OUTPARAM(); - return rc; + if (Core::ERROR_NONE == rc) + { + /* Legacy Enums Mapping */ + if (state >= Exchange::INetworkManager::WiFiState::WIFI_STATE_ERROR) + response["state"] = 6; // 6: FAILED - The device has encountered an unrecoverable error with the Wifi adapter. + else if (state > Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTED) + response["state"] = 2; // 2: DISCONNECTED - The device is installed and enabled, but not yet connected to a network + else + response["state"] = JsonValue(state); + } + + returnJson(rc); } uint32_t WiFiManager::getPairedSSID(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpResponse; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetKnownSSIDs"), parameters, tmpResponse); - else - rc = Core::ERROR_UNAVAILABLE; + ::WPEFramework::RPC::IIteratorType* _ssids{}; - JsonArray array = tmpResponse["ssids"].Array(); - if (0 == array.Length()) + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) { - response["ssid"] = ""; /* Assigning empty string when paired SSID is not available */ + rc = _nwmgr->GetKnownSSIDs(_ssids); + _nwmgr->Release(); } else + rc = Core::ERROR_UNAVAILABLE; + + if (Core::ERROR_NONE == rc) { - response["ssid"] = array[0]; + if (_ssids != nullptr) + { + string _resultItem_{}; + while (_ssids->Next(_resultItem_) == true) { + response["ssid"] = _resultItem_; + /* Just take one Entry : 1st Entry */ + break; + } + _ssids->Release(); + } } - response["success"] = tmpResponse["success"]; - - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t WiFiManager::getPairedSSIDInfo(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; + Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetConnectedSSID"), parameters, response); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->GetConnectedSSID(ssidInfo); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; - LOG_OUTPARAM(); - return rc; + if (Core::ERROR_NONE == rc) + { + response["ssid"] = ssidInfo.ssid; + response["bssid"] = ssidInfo.bssid; + } + returnJson(rc); } uint32_t WiFiManager::getSupportedSecurityModes(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; + Exchange::INetworkManager::ISecurityModeIterator* securityModes{}; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("GetSupportedSecurityModes"), parameters, response); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->GetSupportedSecurityModes(securityModes); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; - LOG_OUTPARAM(); - return rc; + if (Core::ERROR_NONE == rc) + { + if (securityModes != nullptr) + { + JsonObject modes{}; + Exchange::INetworkManager::WIFISecurityModeInfo _resultItem_{}; + while (securityModes->Next(_resultItem_) == true) + { + response.Set(_resultItem_.securityName.c_str(), JsonValue(_resultItem_.security)); + } + securityModes->Release(); + } + } + returnJson(rc); } uint32_t WiFiManager::isPaired (const JsonObject& parameters, JsonObject& response) @@ -381,112 +452,113 @@ namespace WPEFramework if (Core::ERROR_NONE == rc) { - JsonArray array = tmpResponse["ssids"].Array(); - if (0 == array.Length()) - { + if (tmpResponse.HasLabel("ssid")) response["result"] = 1; - } else - { response["result"] = 0; - } - response["success"] = true; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t WiFiManager::saveSSID (const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; + Exchange::INetworkManager::WiFiConnectTo ssid{}; + NMLOG_INFO("Entry to %s\n", __FUNCTION__); - LOG_INPARAM(); + if (parameters.HasLabel("ssid") && parameters.HasLabel("passphrase")) + { + ssid.ssid = parameters["ssid"].String(); + ssid.passphrase = parameters["passphrase"].String(); + ssid.security = static_cast (parameters["security"].Number()); - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("AddToKnownSSIDs"), parameters, response); - else - rc = Core::ERROR_UNAVAILABLE; + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->AddToKnownSSIDs(ssid); + _nwmgr->Release(); + } + else + rc = Core::ERROR_UNAVAILABLE; + } if (Core::ERROR_NONE == rc) - { response["result"] = 0; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t WiFiManager::disconnect (const JsonObject& parameters, JsonObject& response) { - uint32_t rc = Core::ERROR_GENERAL; - LOG_INPARAM(); + uint32_t rc = Core::ERROR_GENERAL; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("WiFiDisconnect"), parameters, response); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->WiFiDisconnect(); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) - { response["result"] = 0; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t WiFiManager::initiateWPSPairing (const JsonObject& parameters, JsonObject& response) { - uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpParameters; LOG_INPARAM(); + uint32_t rc = Core::ERROR_GENERAL; + string wps_pin{}; + Core::JSON::EnumType method; + if (parameters.HasLabel("method")) { - string method = parameters["method"].String(); - if (method == "PBC") - { - tmpParameters["method"] = 0; - } - else if (method == "PIN") - { - tmpParameters["method"] = 1; - tmpParameters["wps_pin"] = parameters.HasLabel("wps_pin"); - } - else if (method == "SERIALIZED_PIN") + if (parameters["method"].Content() == WPEFramework::Core::JSON::Variant::type::STRING) + method.FromString(parameters["method"].String()); + else if (parameters["method"].Content() == WPEFramework::Core::JSON::Variant::type::NUMBER) + method = static_cast (parameters["method"].Number()); + + if ((Exchange::INetworkManager::WIFI_WPS_PIN == method) && parameters.HasLabel("pin")) { - tmpParameters["method"] = 2; + wps_pin = parameters["pin"].String(); } } - else - tmpParameters["method"] = 0; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("StartWPS"), tmpParameters, response); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->StartWPS(method, wps_pin); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) - { - response["result"] = string(); - } - LOG_OUTPARAM(); - return rc; + response["result"] = 0; + returnJson(rc); } uint32_t WiFiManager::startScan(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - JsonObject tmpParameters; + string frequency = parameters["frequency"].String(); + Exchange::INetworkManager::IStringIterator* ssids = NULL; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("StartWiFiScan"), tmpParameters, response); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->StartWiFiScan(frequency, ssids); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t WiFiManager::stopScan(const JsonObject& parameters, JsonObject& response) @@ -494,13 +566,16 @@ namespace WPEFramework LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - if (m_networkmanager) - rc = m_networkmanager->Invoke(5000, _T("StopWiFiScan"), parameters, response); + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); + if (_nwmgr) + { + rc = _nwmgr->StopWiFiScan(); + _nwmgr->Release(); + } else rc = Core::ERROR_UNAVAILABLE; - LOG_OUTPARAM(); - return rc; + returnJson(rc); } /** Private */ @@ -542,58 +617,58 @@ namespace WPEFramework if (m_subsWiFiStateChange && m_subsAvailableSSIDs && m_subsWiFiStrengthChange) { m_timer.stop(); - NMLOG_INFO("subscriber timer stoped"); + NMLOG_INFO("All the required events are subscribed; Retry timer stoped"); } else { m_timer.start(SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS); - NMLOG_INFO("subscriber timer started"); + NMLOG_INFO("Few required events are yet to be subscribed; Retry timer started"); } } - bool WiFiManager::ErrorCodeMapping(const uint32_t ipvalue, uint32_t &opvalue) - { - bool ret = true; - - switch (ipvalue) - { - case Exchange::INetworkManager::WIFI_STATE_SSID_CHANGED: - opvalue = WIFI_SSID_CHANGED; - break; - case Exchange::INetworkManager::WIFI_STATE_CONNECTION_LOST: - opvalue = WIFI_CONNECTION_LOST; - break; - case Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED: - opvalue = WIFI_CONNECTION_FAILED; - break; - case Exchange::INetworkManager::WIFI_STATE_CONNECTION_INTERRUPTED: - opvalue = WIFI_CONNECTION_INTERRUPTED; - break; - case Exchange::INetworkManager::WIFI_STATE_INVALID_CREDENTIALS: - opvalue = WIFI_INVALID_CREDENTIALS; - break; - case Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND: - opvalue = WIFI_NO_SSID; - break; - case Exchange::INetworkManager::WIFI_STATE_ERROR: - opvalue = WIFI_UNKNOWN; - break; - case Exchange::INetworkManager::WIFI_STATE_AUTHENTICATION_FAILED: - opvalue = WIFI_AUTH_FAILED; - break; - default: - ret = false; - break; - } - return ret; + bool WiFiManager::ErrorCodeMapping(const uint32_t ipvalue, uint32_t &opvalue) + { + bool ret = true; + + switch (ipvalue) + { + case Exchange::INetworkManager::WIFI_STATE_SSID_CHANGED: + opvalue = WIFI_SSID_CHANGED; + break; + case Exchange::INetworkManager::WIFI_STATE_CONNECTION_LOST: + opvalue = WIFI_CONNECTION_LOST; + break; + case Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED: + opvalue = WIFI_CONNECTION_FAILED; + break; + case Exchange::INetworkManager::WIFI_STATE_CONNECTION_INTERRUPTED: + opvalue = WIFI_CONNECTION_INTERRUPTED; + break; + case Exchange::INetworkManager::WIFI_STATE_INVALID_CREDENTIALS: + opvalue = WIFI_INVALID_CREDENTIALS; + break; + case Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND: + opvalue = WIFI_NO_SSID; + break; + case Exchange::INetworkManager::WIFI_STATE_ERROR: + opvalue = WIFI_UNKNOWN; + break; + case Exchange::INetworkManager::WIFI_STATE_AUTHENTICATION_FAILED: + opvalue = WIFI_AUTH_FAILED; + break; + default: + ret = false; + break; + } + return ret; } /** Event Handling and Publishing */ void WiFiManager::onWiFiStateChange(const JsonObject& parameters) { - LOG_INPARAM(); JsonObject legacyResult; JsonObject legacyErrorResult; + string json; uint32_t errorCode; uint32_t state = parameters["state"].Number(); @@ -606,39 +681,53 @@ namespace WPEFramework { legacyErrorResult["code"] = errorCode; NMLOG_INFO("onError with errorcode as, %u", errorCode); - NMLOG_INFO("Posting onError"); + + legacyErrorResult.ToString(json); + NMLOG_INFO("Posting onError as %s", json.c_str()); + _gWiFiInstance->Notify("onError", legacyErrorResult); } else { NMLOG_INFO("onWiFiStateChange with state as: %u", state); - NMLOG_INFO("Posting onWIFIStateChanged"); + + legacyResult.ToString(json); + NMLOG_INFO("Posting onWIFIStateChanged as %s", json.c_str()); _gWiFiInstance->Notify("onWIFIStateChanged", legacyResult); } } + else + NMLOG_WARNING("Ignoring %s\n", __FUNCTION__); + return; } void WiFiManager::onAvailableSSIDs(const JsonObject& parameters) { - LOG_INPARAM(); - - NMLOG_INFO("Posting onAvailableSSIDs"); + string json; + parameters.ToString(json); + NMLOG_INFO("Posting onAvailableSSIDs Event as %s", json.c_str()); if(_gWiFiInstance) _gWiFiInstance->Notify("onAvailableSSIDs", parameters); + else + NMLOG_WARNING("Ignoring %s\n", __FUNCTION__); return; } void WiFiManager::onWiFiSignalStrengthChange(const JsonObject& parameters) { - LOG_INPARAM(); JsonObject legacyParams; legacyParams["signalStrength"] = parameters["signalQuality"]; legacyParams["strength"] = parameters["signalLevel"]; - NMLOG_INFO("Posting onWifiSignalThresholdChanged"); + + string json; + legacyParams.ToString(json); + NMLOG_INFO("Posting onWifiSignalThresholdChanged as %s", json.c_str()); if (_gWiFiInstance) _gWiFiInstance->Notify("onWifiSignalThresholdChanged", legacyParams); + else + NMLOG_WARNING("Ignoring %s\n", __FUNCTION__); return; } diff --git a/Module.cpp b/Module.cpp index a574f23db..d402f4409 100644 --- a/Module.cpp +++ b/Module.cpp @@ -18,4 +18,4 @@ **/ #include "Module.h" -MODULE_NAME_DECLARATION(BUILD_REFERENCE) +MODULE_NAME_DECLARATION(PLUGIN_BUILD_REFERENCE) diff --git a/NetworkManager.cpp b/NetworkManager.cpp index baa8d4826..c7f3be034 100644 --- a/NetworkManager.cpp +++ b/NetworkManager.cpp @@ -18,7 +18,6 @@ **/ #include "NetworkManager.h" - #include namespace WPEFramework @@ -43,8 +42,6 @@ namespace WPEFramework _networkManager(nullptr), _notification(this) { - // Don't do any work in the constructor - all set up should be done in Initialize - m_primaryInterfaceCache = "wlan0"; } NetworkManager::~NetworkManager() @@ -88,10 +85,14 @@ namespace WPEFramework if (_networkManager != nullptr) { // set the plugin configuration - Exchange::INetworkManager::NMLogging _loglevel; - _networkManager->Configure(_service->ConfigLine(), _loglevel); + Exchange::INetworkManager::Logging _loglevel; + _networkManager->Configure(_service->ConfigLine()); + // configure loglevel in libWPEFrameworkNetworkManager.so + _networkManager->GetLogLevel(_loglevel); NetworkManagerLogger::SetLevel(static_cast (_loglevel)); + + _networkManager->Register(&_notification); // Register all custom JSON-RPC methods diff --git a/NetworkManager.h b/NetworkManager.h index 1838c545b..a2543bed7 100644 --- a/NetworkManager.h +++ b/NetworkManager.h @@ -21,8 +21,6 @@ #include "Module.h" -// Include the interface we created -//#include #include "INetworkManager.h" #include "NetworkManagerLogger.h" @@ -53,59 +51,6 @@ namespace WPEFramework Notification() = delete; Notification(const Notification &) = delete; Notification &operator=(const Notification &) = delete; - string InterfaceStateToString(Exchange::INetworkManager::InterfaceState event) - { - switch (event) - { - case Exchange::INetworkManager::INTERFACE_ADDED: - return "INTERFACE_ADDED"; - case Exchange::INetworkManager::INTERFACE_LINK_UP: - return "INTERFACE_LINK_UP"; - case Exchange::INetworkManager::INTERFACE_LINK_DOWN: - return "INTERFACE_LINK_DOWN"; - case Exchange::INetworkManager::INTERFACE_ACQUIRING_IP: - return "INTERFACE_ACQUIRING_IP"; - case Exchange::INetworkManager::INTERFACE_REMOVED: - return "INTERFACE_REMOVED"; - case Exchange::INetworkManager::INTERFACE_DISABLED: - return "INTERFACE_DISABLED"; - } - return ""; - } - - string WiFiSignalQualityToString(Exchange::INetworkManager::WiFiSignalQuality quality) - { - switch (quality) - { - case Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED: - return "Disconnected"; - case Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_WEAK: - return "Weak"; - case Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_FAIR: - return "Fair"; - case Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_GOOD: - return "Good"; - case Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT: - return "Excellent"; - } - return ""; - } - - string InternetStatusToString(const Exchange::INetworkManager::InternetStatus internetStatus) - { - switch (internetStatus) - { - case Exchange::INetworkManager::InternetStatus::INTERNET_LIMITED: - return "LIMITED_INTERNET"; - case Exchange::INetworkManager::InternetStatus::INTERNET_CAPTIVE_PORTAL: - return "CAPTIVE_PORTAL"; - case Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED: - return "FULLY_CONNECTED"; - default: - return "NO_INTERNET"; - } - return ""; - } public: explicit Notification(NetworkManager *parent) @@ -118,93 +63,40 @@ namespace WPEFramework } public: - void onInterfaceStateChange(const Exchange::INetworkManager::InterfaceState event, const string interface) override - { - NMLOG_INFO("%s", __FUNCTION__); - JsonObject params; - params["interface"] = interface; - params["state"] = InterfaceStateToString(event); - if(interface == "wlan0") - _parent.m_wifiStateCache.reset(); - _parent.Notify("onInterfaceStateChange", params); - _parent.m_primaryInterfaceCache.reset(); - _parent.m_ipv6AddressCache.reset(); - _parent.m_ipv4AddressCache.reset(); - } - void onIPAddressChange(const string interface, const bool isAcquired, const bool isIPv6, const string ipAddress) override + void onInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface) override { - NMLOG_INFO("%s", __FUNCTION__); - JsonObject params; - params["status"] = string (isAcquired ? "ACQUIRED" : "LOST"); - params["interface"] = interface; - params["ipAddress"] = ipAddress; - params["isIPv6"] = isIPv6; - if(isIPv6) - _parent.m_ipv6AddressCache.reset(); - else - _parent.m_ipv4AddressCache.reset(); - _parent.Notify("onIPAddressChange", params); + _parent.onInterfaceStateChange(state, interface); } void onActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface) override { - NMLOG_INFO("%s", __FUNCTION__); - JsonObject params; - params["oldInterfaceName"] = prevActiveInterface; - params["newInterfaceName"] = currentActiveinterface; - _parent.Notify("onActiveInterfaceChange", params); - _parent.m_primaryInterfaceCache.reset(); + _parent.onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); } - void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus oldState, const Exchange::INetworkManager::InternetStatus newstate) override + void onIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status) override { - NMLOG_INFO("%s", __FUNCTION__); - JsonObject params; - - params["state"] = static_cast (newstate);; - params["status"] = InternetStatusToString(newstate); - params["prevState"] = static_cast (oldState); - params["prevStatus"] = InternetStatusToString(oldState); - - _parent.Notify("onInternetStatusChange", params); - - if (Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED == newstate) - { - NMLOG_INFO("Notify Thunder ISubsystem internet"); - _parent.PublishToThunderAboutInternet(); - } + _parent.onIPAddressChange(interface, ipversion, ipaddress, status); } - // WiFi Notifications that other processes can subscribe to - void onAvailableSSIDs(const string jsonOfWiFiScanResults) override + void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) override { - NMLOG_INFO("%s", __FUNCTION__); - JsonArray scanResults; - JsonObject result; - scanResults.FromString(jsonOfWiFiScanResults); - result["ssids"] = scanResults; - _parent.Notify("onAvailableSSIDs", result); + _parent.onInternetStatusChange(prevState, currState); + } + void onAvailableSSIDs(const string jsonOfScanResults) override + { + _parent.onAvailableSSIDs(jsonOfScanResults); } void onWiFiStateChange(const Exchange::INetworkManager::WiFiState state) override { - NMLOG_INFO("%s", __FUNCTION__); - JsonObject result; - result["state"] = static_cast (state); - _parent.Notify("onWiFiStateChange", result); - _parent.m_wifiStateCache = state; + _parent.onWiFiStateChange(state); } - void onWiFiSignalStrengthChange(const string ssid, const string signalLevel, const Exchange::INetworkManager::WiFiSignalQuality signalQuality) override + void onWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) override { - NMLOG_INFO("%s", __FUNCTION__); - JsonObject result; - result["ssid"] = ssid; - result["signalQuality"] = WiFiSignalQualityToString(signalQuality); - result["signalLevel"] = signalLevel; - _parent.Notify("onWiFiSignalStrengthChange", result); + _parent.onWiFiSignalStrengthChange(ssid, strength, quality); } // The activated/deactived methods are part of the RPC::IRemoteConnection::INotification @@ -320,10 +212,8 @@ namespace WPEFramework }; // cached varibales - Cache m_wifiStateCache; - Cache m_ipv4AddressCache; - Cache m_ipv6AddressCache; - Cache m_primaryInterfaceCache; + Cache m_ipv4AddressCache; + Cache m_ipv6AddressCache; private: // Notification/event handlers // Clean up when we're told to deactivate @@ -335,6 +225,7 @@ namespace WPEFramework // JSON-RPC methods (take JSON in, spit JSON back out) uint32_t SetLogLevel (const JsonObject& parameters, JsonObject& response); + uint32_t GetLogLevel (const JsonObject& parameters, JsonObject& response); uint32_t GetAvailableInterfaces (const JsonObject& parameters, JsonObject& response); uint32_t GetPrimaryInterface (const JsonObject& parameters, JsonObject& response); uint32_t SetPrimaryInterface (const JsonObject& parameters, JsonObject& response); @@ -367,6 +258,14 @@ namespace WPEFramework uint32_t GetWiFiSignalStrength(const JsonObject& parameters, JsonObject& response); uint32_t GetSupportedSecurityModes(const JsonObject& parameters, JsonObject& response); + void onInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface); + void onActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface); + void onIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status); + void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState); + void onAvailableSSIDs(const string jsonOfScanResults); + void onWiFiStateChange(const Exchange::INetworkManager::WiFiState state); + void onWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality); + private: uint32_t _connectionId; PluginHost::IShell *_service; diff --git a/NetworkManager.json b/NetworkManager.json index 0096bddaa..06842f8c0 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -1,19 +1,22 @@ { - "$schema": "https://raw.githubusercontent.com/rdkcentral/rdkservices/main/Tools/json_generator/schemas/interface.schema.json", + "$schema": "interface.schema.json", "jsonrpc": "2.0", "info": { "title": "NetworkManager Plugin", "class": "NetworkManager", "callsign": "org.rdk.NetworkManager", "locator": "libWPEFrameworkNetworkManager.so", - "status": "production", + "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", - "version": "0.4.0" - }, - "common": { - "$ref": "../../common/common.json" + "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json", + "version": "0.5.0" }, "definitions": { + "success": { + "summary": "Whether the request succeeded", + "type": "boolean", + "example": "true" + }, "interface": { "summary": "An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface", "type": "string", @@ -44,10 +47,10 @@ "type": "integer", "example": 24 }, - "v6LinkLocal": { - "summary": "The v6LinkLocal", + "ula": { + "summary": "The IPv6 Unified Local Address", "type": "string", - "example": "192.168.1.1" + "example": "d00:410:2016::" }, "gateway": { "summary": "The gateway address", @@ -69,28 +72,18 @@ "type": "integer", "example": "3478" }, - "endPoint":{ - "summary": "STUN server endPoint", - "type": "string", - "example": "stun.l.google.com" - }, "endpoint":{ "summary": "The host name or IP address", "type": "string", "example": "45.57.221.20" }, - "bindTimeout":{ - "summary": "STUN server bind timeout", - "type": "integer", - "example": "30" - }, - "cacheTimeout":{ + "cacheLifetime":{ "summary": "STUN server cache timeout", "type": "integer", "example": "0" }, "state": { - "summary": "The internet state", + "summary": "The given State", "type": "integer", "example": 4 }, @@ -99,8 +92,13 @@ "type": "string", "example": "" }, - "noOfRequest": { - "summary": "The number of packets to send. Default is 15.", + "count": { + "summary": "The number of requests to send. Default is 3.", + "type": "integer", + "example": 10 + }, + "packets": { + "summary": "The number of packets to send. Default is 5.", "type": "integer", "example": 10 }, @@ -124,12 +122,12 @@ "type": "string", "example": "password" }, - "securityMode": { - "summary": "The security mode. See `getSupportedSecurityModes`.", + "security": { + "summary": "The security mode. See `getSupportedsecurityModes`.", "type": "integer", "example": 6 }, - "signalStrength":{ + "strength":{ "summary": "The RSSI value in dBm", "type": "string", "example": "-27.000000" @@ -143,14 +141,56 @@ "summary": "Error string of scan failure", "type": "string", "example": "" - }, - "empty_string": { - "summary": "Not supported", - "type": "string", - "example": "" } }, "methods": { + "SetLogLevel":{ + "summary": "Set Log level for more information. The possible set log level are as follows. \n* `0`: FATAL \n* `1`: ERROR \n* `2`: WARNING \n* `3`: INFO \n* `4`: DEBUG \n", + "params": { + "type": "object", + "properties": { + "level": { + "summary": "Set Log level to get more information", + "type": "integer", + "example": 1 + } + }, + "required": [ + "level" + ] + }, + "result": { + "type": "object", + "properties": { + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] + } + }, + "GetLogLevel":{ + "summary": "Get Log level that is currently used.", + "result": { + "type": "object", + "properties": { + "level": { + "summary": "Get Log level to get more information", + "type": "integer", + "example": 1 + }, + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "level", + "success" + ] + } + }, "GetAvailableInterfaces":{ "summary": "Get device supported list of available interface including their state.", "result": { @@ -177,12 +217,12 @@ "type": "string", "example": "AA:AA:AA:AA:AA:AA" }, - "isEnabled":{ + "enabled":{ "summary": "Whether the interface is currently enabled", "type": "boolean", "example": true }, - "isConnected":{ + "connected":{ "summary": "Whether the interface is currently connected", "type": "boolean", "example": true @@ -192,13 +232,13 @@ "type", "name", "mac", - "isEnabled", - "isConnected" + "enabled", + "connected" ] } }, "success": { - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -208,7 +248,7 @@ } }, "GetPrimaryInterface": { - "summary": "Gets the primary/default network interface for the device. The active network interface is defined as the one that can make requests to the external network. Returns one of the supported interfaces as per `GetAvailableInterfaces`, or an empty value which indicates that there is no default network interface.", + "summary": "Gets the primary/default network interface for the device. The active network interface is defined as the one that can make requests to the external network. Returns one of the supported interfaces as per `GetAvailableInterfaces`.", "result": { "type": "object", "properties": { @@ -241,7 +281,84 @@ ] }, "result": { - "$ref": "#/common/result" + "type": "object", + "properties": { + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] + } + }, + "SetInterfaceState":{ + "summary": "Enable or disable the specified interface", + "events":{ + "onInterfaceStateChange" : "Triggered when interface’s status changes to enabled." + }, + "params": { + "type": "object", + "properties": { + "interface": { + "summary": "Enable the specified interface", + "type": "string", + "example": "wlan0" + }, + "enabled":{ + "summary": "Whether the interface must be enabled or disabled", + "type": "boolean", + "example": true + } + }, + "required": [ + "interface", + "enabled" + ] + }, + "result": { + "type": "object", + "properties": { + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] + } + }, + "GetInterfaceState":{ + "summary": "Gets the current Status of the specified interface", + "params": { + "type": "object", + "properties": { + "interface": { + "summary": "Disable the specified interface", + "type": "string", + "example": "wlan0" + } + }, + "required": [ + "interface" + ] + }, + "result": { + "type": "object", + "properties": { + "enabled":{ + "summary": "Whether the interface is enabled or disabled", + "type": "boolean", + "example": true + }, + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "enabled", + "success" + ] } }, "GetIPSettings":{ @@ -255,10 +372,7 @@ "ipversion": { "$ref": "#/definitions/ipversion" } - }, - "required": [ - "interface" - ] + } }, "result": { "type": "object", @@ -284,8 +398,8 @@ "gateway": { "$ref": "#/definitions/gateway" }, - "v6LinkLocal": { - "$ref": "#/definitions/v6LinkLocal" + "ula": { + "$ref": "#/definitions/ula" }, "primarydns": { "$ref": "#/definitions/primarydns" @@ -294,7 +408,7 @@ "$ref": "#/definitions/secondarydns" }, "success": { - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -303,7 +417,7 @@ "autoconfig", "ipaddress", "prefix", - "v6LinkLocal", + "ula", "gateway", "primarydns", "secondarydns", @@ -360,7 +474,7 @@ "type": "object", "properties": { "success": { - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -369,55 +483,55 @@ } }, "GetStunEndpoint": { - "summary": "Get the STUN Endpoint that is used to identify public IP of the device.", + "summary": "Get the STUN endpoint that is used to identify public IP of the device.", "result": { "type": "object", "properties": { - "endPoint": { - "$ref": "#/definitions/endPoint" + "endpoint": { + "$ref": "#/definitions/endpoint" }, "port": { "$ref": "#/definitions/port" }, - "bindTimeout": { - "$ref": "#/definitions/bindTimeout" + "timeout": { + "$ref": "#/definitions/timeout" }, - "cacheTimeout": { - "$ref": "#/definitions/cacheTimeout" + "cacheLifetime": { + "$ref": "#/definitions/cacheLifetime" }, "success": { - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ - "endPoint", + "endpoint", "port", - "bindTimeout", - "cacheTimeout", + "timeout", + "cacheLifetime", "success" ] } }, "SetStunEndpoint":{ - "summary": "Set the STUN Endpoint to be used to identify public IP of the device.", + "summary": "Set the STUN endpoint to be used to identify public IP of the device.", "params": { "type":"object", "properties": { - "endPoint": { - "$ref": "#/definitions/endPoint" + "endpoint": { + "$ref": "#/definitions/endpoint" }, "port": { "$ref": "#/definitions/port" }, - "bindTimeout": { - "$ref": "#/definitions/bindTimeout" + "timeout": { + "$ref": "#/definitions/timeout" }, - "cacheTimeout": { - "$ref": "#/definitions/cacheTimeout" + "cacheLifetime": { + "$ref": "#/definitions/cacheLifetime" } }, "required": [ - "endPoint", + "endpoint", "port" ] }, @@ -425,13 +539,9 @@ "type": "object", "properties": { "success": { - "$ref": "#/common/success" + "$ref": "#/definitions/success" } - }, - "required": [ - "public_ip", - "success" - ] + } } }, "GetConnectivityTestEndpoints":{ @@ -448,7 +558,7 @@ } }, "success": { - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -476,37 +586,59 @@ ] }, "result": { - "$ref": "#/common/result" + "type": "object", + "properties": { + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] } }, "IsConnectedToInternet":{ - "summary": "Seeks Whether the device has internet connectivity. This API might take up to 3s to validate internet connectivity.", + "summary": "Seeks whether the device has internet connectivity. This API might take up to 3s to validate internet connectivity.", "params": { "type":"object", "properties": { "ipversion": { "$ref": "#/definitions/ipversion" } - } + }, + "required": [ + ] }, "result": { "type": "object", "properties": { - "isConnectedToInternet": { + "ipversion": { + "$ref": "#/definitions/ipversion" + }, + "connected": { "summary": "`true` if internet connectivity is detected, otherwise `false`", "type": "boolean", "example": true }, - "internetState": { - "$ref": "#/definitions/state" + "state": { + "summary": "Internet state", + "type": "integer", + "example": 3 + }, + "status": { + "summary": "Internet status", + "type": "string", + "example": "FULLY_CONNECTED" }, "success": { - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ - "isConnectedToInternet", - "internetState", + "ipversion", + "connected", + "state", + "status", "success" ] } @@ -522,7 +654,7 @@ "example": "http://10.0.0.1/captiveportal.jst" }, "success":{ - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -532,7 +664,7 @@ } }, "StartConnectivityMonitoring":{ - "summary": "Enable a continuous monitoring of internet connectivity with heart beat interval thats given. If the monitoring is already happening, it will be restarted with new given interval.", + "summary": "Enable a continuous monitoring of internet connectivity with heart beat interval thats given. If the monitoring is already happening, it will be restarted with new given interval. When the interval is not passed, it will be 60s by default.", "events":{ "onInternetStatusChange" : "Triggered when internet connection state changed." }, @@ -546,14 +678,13 @@ } }, "required": [ - "interval" ] }, "result": { "type": "object", "properties": { "success":{ - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -567,7 +698,7 @@ "type": "object", "properties": { "success":{ - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -575,7 +706,7 @@ ] } }, - "GetPublicIP":{ + "GetPublicIP":{ "summary": "Gets the internet/public IP Address of the device.", "params": { "type":"object", @@ -586,23 +717,24 @@ } }, "required": [ - "ipversion" ] }, "result": { "type": "object", "properties": { - "publicIP":{ - "summary": "Returns an public ip of the device", - "type":"string", - "example": "69.136.49.95" + "ipaddress": { + "$ref": "#/definitions/ipaddress" + }, + "ipversion": { + "$ref": "#/definitions/ipversion" }, "success": { - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ - "publicIP", + "ipaddress", + "ipversion", "success" ] } @@ -618,8 +750,8 @@ "ipversion": { "$ref": "#/definitions/ipversion" }, - "noOfRequest": { - "$ref": "#/definitions/noOfRequest" + "count": { + "$ref": "#/definitions/count" }, "timeout": { "$ref": "#/definitions/timeout" @@ -630,19 +762,14 @@ }, "required": [ "endpoint", - "ipversion", - "noOfRequest", - "timeout", - "guid" + "ipversion" ] }, "result": { "type": "object", "properties": { - "target": { - "summary": "The target IP address", - "type": "string", - "example": "45.57.221.20" + "endpoint":{ + "$ref": "#/definitions/endpoint" }, "packetsTransmitted": { "summary": "The number of packets sent", @@ -690,11 +817,11 @@ "example": "..." }, "success": { - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ - "target", + "endpoint", "packetsTransmitted", "packetsReceived", "packetLoss", @@ -722,8 +849,8 @@ "ipversion": { "$ref": "#/definitions/ipversion" }, - "noOfRequest": { - "$ref": "#/definitions/noOfRequest" + "packets": { + "$ref": "#/definitions/packets" }, "guid": { "$ref": "#/definitions/guid" @@ -731,85 +858,39 @@ }, "required": [ "endpoint", - "ipversion", - "noOfRequest", - "guid" + "ipversion" ] }, "result": { "type": "object", "properties": { - "target": { - "summary": "The target IP address", - "type": "string", - "example": "45.57.221.20" - }, - "packetsTransmitted": { - "summary": "The number of packets sent", - "type": "integer", - "example": 10 - }, - "packetsReceived": { - "summary": "The number of packets received", - "type": "integer", - "example": 10 - }, - "packetLoss": { - "summary": "The number of packets lost", - "type": "string", - "example": "0.0" - }, - "tripMin": { - "summary": "The minimum amount of time to receive the packets", - "type": "string", - "example": "61.264" - }, - "tripAvg": { - "summary": "The average time to receive the packets", - "type": "string", - "example": "130.397" - }, - "tripMax": { - "summary": "The maximum amount of time to receive the packets", - "type": "string", - "example": "230.832" - }, - "tripStdDev": { - "summary": "The standard deviation for the trip", - "type": "string", - "example": "80.919" + "endpoint":{ + "$ref": "#/definitions/endpoint" }, - "error": { - "summary": "An error message", + "results": { + "summary": "The response of traceroute", "type": "string", "example": "..." - }, + }, "guid": { "summary": "The globally unique identifier", "type": "string", "example": "..." }, "success": { - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ - "target", - "packetsTransmitted", - "packetsReceived", - "packetLoss", - "tripMin", - "tripAvg", - "tripMax", - "tripStdDev", - "error", + "endpoint", + "results", "guid", "success" ] } }, "StartWiFiScan":{ - "summary": "Initiates WiFi scaning. This method supports scanning for specific range of frequency like 2.4GHz only or 5GHz only or 6GHz only or ALL. When no input passed about the frequency to be scanned, it scans for all. It publishes 'onAvailableSSIDs' event upon completion.", + "summary": "Initiates WiFi scaning. This method supports scanning for specific range of frequency like 2.4GHz only or 5GHz only or 6GHz only or ALL. When no input passed about the frequency to be scanned, it scans for all. When list of SSIDs to be scanned specifically, it can be passed as input. It publishes 'onAvailableSSIDs' event upon completion.", "events": { "onAvailableSSIDs" : "Triggered when list of SSIDs is available after the scan completes." }, @@ -817,20 +898,25 @@ "type": "object", "properties": { "frequency": { - "summary": "The frequency to scan. An empty or `null` value scans all frequencies. If a frequency is specified (2.4 or 5.0), then the results are only returned for matching frequencies.", + "summary": "The frequency to scan. An empty or `null` value scans all frequencies.", "type": "string", - "example": "" + "example": "5" + }, + "ssids": { + "summary": "The list of SSIDs to be scanned.", + "type": "array", + "items": { + "type": "string", + "example": "Xfinity Mobile" + } } - }, - "required": [ - "frequency" - ] + } }, "result": { "type": "object", "properties": { "success": { - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -841,7 +927,15 @@ "StopWiFiScan":{ "summary": "Stops WiFi scanning. Any discovered SSIDs from the call to the `StartWiFiScan` method up to the point where this method is called are still returned as event.", "result": { - "$ref": "#/common/result" + "type": "object", + "properties": { + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] } }, "GetKnownSSIDs":{ @@ -858,7 +952,7 @@ } }, "success": { - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -878,21 +972,21 @@ "passphrase": { "$ref": "#/definitions/passphrase" }, - "securityMode": { - "$ref": "#/definitions/securityMode" + "security": { + "$ref": "#/definitions/security" } }, "required": [ "ssid", "passphrase", - "securityMode" + "security" ] }, "result": { "type": "object", "properties": { "success":{ - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -901,7 +995,7 @@ } }, "RemoveKnownSSID":{ - "summary": "Remove given SSID from saved SSIDs. This method just removes from the list and of the list is having only one entry thats being removed, it will initiate a disconnect.", + "summary": "Remove given SSID from saved SSIDs. This method just removes an entry from the list and of the list is having only one entry thats being removed, it will initiate a disconnect.", "events":{ "onWiFiStateChange" : "Triggered when Wifi state changes to DISCONNECTED", "onAddressChange" : "Triggered when an IP Address is assigned or lost", @@ -922,7 +1016,7 @@ "type": "object", "properties": { "success":{ - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -944,18 +1038,76 @@ "passphrase": { "$ref": "#/definitions/passphrase" }, - "securityMode": { - "$ref": "#/definitions/securityMode" + "security": { + "$ref": "#/definitions/security" + }, + "ca_cert": { + "summary": "The ca_cert to be used for EAP", + "type": "string", + "example": "..." + }, + "client_cert": { + "summary": "The client_cert to be used for EAP", + "type": "string", + "example": "..." + }, + "private_key": { + "summary": "The private_key to be used for EAP", + "type": "string", + "example": "..." + }, + "private_key_passwd": { + "summary": "The private_key_passwd to be used for EAP", + "type": "string", + "example": "..." + }, + "eap": { + "summary": "The EAP type to be used", + "type": "string", + "example": "TLS" + }, + "eap_identity": { + "summary": "The identity to be used for EAP", + "type": "string", + "example": "..." + }, + "eap_password": { + "summary": "The eap_password to be used for EAP", + "type": "string", + "example": "..." + }, + "eap_phase1": { + "summary": "The eap_phase1 to be used for EAP", + "type": "string", + "example": "..." + }, + "eap_phase2": { + "summary": "The eap_phase2 to be used for EAP", + "type": "string", + "example": "..." + }, + "persist": { + "summary": " To persist the SSID across reboots; similar to auto connect", + "type": "boolean", + "example": true } }, "required": [ "ssid", "passphrase", - "securityMode" + "security" ] }, "result": { - "$ref": "#/common/result" + "type": "object", + "properties": { + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] } }, "WiFiDisconnect":{ @@ -969,7 +1121,7 @@ "type": "object", "properties": { "success":{ - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -988,13 +1140,13 @@ "bssid": { "$ref": "#/definitions/bssid" }, - "securityMode":{ + "security":{ "summary": "The security mode. See the `connect` method", "type": "string", "example": "5" }, - "signalStrength": { - "$ref": "#/definitions/signalStrength" + "strength": { + "$ref": "#/definitions/strength" }, "frequency": { "$ref": "#/definitions/frequency" @@ -1010,7 +1162,7 @@ "example": "-121.000000" }, "success":{ - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -1018,8 +1170,8 @@ "bssid", "rate", "noise", - "securityMode", - "signalStrength", + "security", + "strength", "frequency", "success" ] @@ -1037,18 +1189,17 @@ "properties": { "method": { "summary": "The method used to obtain the pin (must be one of the following: PBC=0, PIN=1, SERIALIZED_PIN=2)", - "type": "integer", - "example": 1 + "type": "string", + "example": "PIN" }, - "wps_pin": { + "pin": { "summary": "A valid 8 digit WPS pin number. Use this parameter when the `method` parameter is set to `PIN`.", "type": "string", "example": "88888888" } }, "required": [ - "method", - "wps_pin" + "method" ] }, "result": { @@ -1060,7 +1211,7 @@ "example": "88888888" }, "success":{ - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -1078,7 +1229,7 @@ "type": "object", "properties": { "success":{ - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -1097,8 +1248,8 @@ "ssid": { "$ref": "#/definitions/ssid" }, - "signalStrength": { - "$ref": "#/definitions/signalStrength" + "strength": { + "$ref": "#/definitions/strength" }, "quality":{ "summary": "Signal strength Quality", @@ -1106,18 +1257,18 @@ "example": 123 }, "success":{ - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ "ssid", - "signalStrength", + "strength", "quality", "success" ] } }, - "GetSupportedSecurityModes":{ + "GetSupportedsecurityModes":{ "summary": "Returns the Wifi security modes that the device supports.", "result": { "type": "object", @@ -1190,7 +1341,7 @@ "required": [] }, "success":{ - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ @@ -1199,107 +1350,26 @@ ] } }, - "SetLogLevel":{ - "summary": "Set Log level for more information. The possible set log level are as follows. \n* `0`: FATAL \n* `1`: ERROR \n* `2`: WARNING \n* `3`: INFO \n* `4`: VERBOSE \n* `5`: TRACE \n", - "params": { - "type": "object", - "properties": { - "loglevel": { - "summary": "Set Log level to get more information", - "type": "integer", - "example": 1 - } - }, - "required": [ - "loglevel" - ] - }, - "result": { - "type": "object", - "properties": { - "success": { - "$ref": "#/common/success" - } - }, - "required": [ - "success" - ] - } - }, - "EnableInterface":{ - "summary": "Enable the specified interface", - "events":{ - "onInterfaceStateChange" : "Triggered when interface’s status changes to enabled." - }, - "params": { - "type": "object", - "properties": { - "interface": { - "summary": "Enable the specified interface", - "type": "string", - "example": "wlan0" - } - }, - "required": [ - "interface" - ] - }, - "result": { - "type": "object", - "properties": { - "success": { - "$ref": "#/common/success" - } - }, - "required": [ - "success" - ] - } - }, - "DisableInterface":{ - "summary": "Disable the specified interface", - "events":{ - "onInterfaceStateChange" : "Triggered when interface’s status changes to disabled." - }, - "params": { - "type": "object", - "properties": { - "interface": { - "summary": "Disable the specified interface", - "type": "string", - "example": "wlan0" - } - }, - "required": [ - "interface" - ] - }, - "result": { - "type": "object", - "properties": { - "success": { - "$ref": "#/common/success" - } - }, - "required": [ - "success" - ] - } - }, "GetWifiState": { - "summary": "Returns the current Wifi State. The possible Wifi states are as follows. \n**Wifi States** \n* `0`: UNINSTALLED - The device was in an installed state and was uninstalled; or, the device does not have a Wifi radio installed \n* `1`: DISABLED - The device is installed but not yet enabled \n* `2`: DISCONNECTED - The device is installed and enabled, but not yet connected to a network \n* `3`: PAIRING - The device is in the process of pairing, but not yet connected to a network \n* `4`: CONNECTING - The device is attempting to connect to a network \n* `5`: CONNECTED - The device is successfully connected to a network \n* `6`: SSID_NOT_FOUND - The requested SSID to connect is not found \n* `7`: SSID_CHANGED - The device connected SSID is changed \n* `8`: CONNECTION_LOST - The device network connection is lost \n* `9`: CONNECTION_FAILED - The device connection got failed \n* `10`: CONNECTION_INTERRUPTED - The device connection is interrupted \n* `11`: INVALID_CREDENTIALS - The credentials provided to connect is not valid \n* `12`: AUTHENTICATION_FAILED - Authentication process as a whole could not be successfully completed \n* `13`: ERROR - The device has encountered an unrecoverable error with the Wifi adapter.", + "summary": "Returns the current Wifi State. The possible Wifi states are as follows. \n**Wifi States** \n* `0`: WIFI_STATE_UNINSTALLED - The device was in an installed state and was uninstalled; or, the device does not have a Wifi radio installed \n* `1`: WIFI_STATE_DISABLED - The device is installed but not yet enabled \n* `2`: WIFI_STATE_DISCONNECTED - The device is installed and enabled, but not yet connected to a network \n* `3`: WIFI_STATE_PAIRING - The device is in the process of pairing, but not yet connected to a network \n* `4`: WIFI_STATE_CONNECTING - The device is attempting to connect to a network \n* `5`: WIFI_STATE_CONNECTED - The device is successfully connected to a network \n* `6`: WIFI_STATE_SSID_NOT_FOUND - The requested SSID to connect is not found \n* `7`: WIFI_STATE_SSID_CHANGED - The device connected SSID is changed \n* `8`: WIFI_STATE_CONNECTION_LOST - The device network connection is lost \n* `9`: WIFI_STATE_CONNECTION_FAILED - The device connection got failed \n* `10`: WIFI_STATE_CONNECTION_INTERRUPTED - The device connection is interrupted \n* `11`: WIFI_STATE_INVALID_CREDENTIALS - The credentials provided to connect is not valid \n* `12`: WIFI_STATE_AUTHENTICATION_FAILED - Authentication process as a whole could not be successfully completed \n* `13`: WIFI_STATE_ERROR - The device has encountered an unrecoverable error with the Wifi adapter.", "result": { "type": "object", "properties": { "state": { "$ref": "#/definitions/state" }, + "status": { + "summary": "WiFi status", + "type": "string", + "example": "WIFI_STATE_CONNECTED" + }, "success":{ - "$ref": "#/common/success" + "$ref": "#/definitions/success" } }, "required": [ "state", + "status", "success" ] } @@ -1317,13 +1387,19 @@ }, "state":{ "summary": "Current state of the interface", + "type": "integer", + "example": 1 + }, + "status":{ + "summary": "Current status of the interface", "type": "string", - "example": "INTERFACE_ADDED" + "example": "INTERFACE_LINK_UP" } }, "required": [ "interface", - "state" + "state", + "status" ] } }, @@ -1335,15 +1411,11 @@ "interface":{ "$ref": "#/definitions/interface" }, - "isIPv6":{ - "summary": "It will be true if the IP address is IPv6", - "type": "boolean", - "example": false + "ipaddress": { + "$ref": "#/definitions/ipaddress" }, - "ipAddress":{ - "summary": "The IPv6 or IPv4 address for the interface", - "type": "string", - "example": "192.168.1.100" + "ipversion": { + "$ref": "#/definitions/ipversion" }, "status":{ "summary": "Whether IP address was acquired or lost (must be one of the following: 'ACQUIRED', 'LOST')", @@ -1357,8 +1429,8 @@ }, "required": [ "interface", - "isIPv6", - "ipAddress", + "ipaddress", + "ipversion", "status" ] } @@ -1368,20 +1440,20 @@ "params": { "type": "object", "properties": { - "oldInterfaceName":{ + "prevActiveInterface":{ "summary": "The previous interface that was changed", "type": "string", "example": "wlan0" }, - "newInterfaceName":{ + "activeInterface":{ "summary": "The current interface", "type": "string", "example": "eth0" } }, "required": [ - "oldInterfaceName", - "newInterfaceName" + "prevActiveInterface", + "activeInterface" ] } }, @@ -1390,12 +1462,12 @@ "params": { "type": "object", "properties": { - "PrevState":{ + "prevState":{ "summary": "The privious internet connection state", "type": "integer", "example": 1 }, - "PrevStatus":{ + "prevStatus":{ "summary": "The previous internet connection status", "type": "string", "example": "NO_INTERNET" @@ -1412,8 +1484,8 @@ } }, "required": [ - "PrevState", - "PrevStatus", + "prevState", + "prevStatus", "state", "status" ] @@ -1440,8 +1512,8 @@ "type": "integer", "example": 6 }, - "signalStrength":{ - "summary": "signalStrength", + "strength":{ + "summary": "strength", "type": "string", "example": "-27.000000" }, @@ -1454,7 +1526,7 @@ "required": [ "ssid", "security", - "signalStrength", + "strength", "frequency" ] } @@ -1463,18 +1535,24 @@ } }, "onWiFiStateChange":{ - "summary": "Triggered when WIFI connection state get changed. The possible states are, \n * '0' - 'WIFI_STATE_UNINSTALLED' \n * '1' - 'WIFI_STATE_DISABLED' \n * '2' - 'WIFI_STATE_DISCONNECTED' \n * '3' - 'WIFI_STATE_PAIRING' \n * '4' - 'WIFI_STATE_CONNECTING' \n * '5' - 'WIFI_STATE_CONNECTED' \n * '6' - 'WIFI_STATE_SSID_NOT_FOUND' \n * '7' - 'WIFI_STATE_SSID_CHANGED' \n * '8' - 'WIFI_STATE_CONNECTION_LOST' \n * '9' - 'WIFI_STATE_CONNECTION_FAILED' \n * '10'- 'WIFI_STATE_CONNECTION_INTERRUPTED' \n * '11' - 'WIFI_STATE_INVALID_CREDENTIALS' \n * '12' - 'WIFI_STATE_AUTHENTICATION_FAILED' \n * '13' - 'WIFI_STATE_ERROR' \n", + "summary": "Triggered when WIFI connection state get changed. The possible states are defined in `GetWifiState()`", "params": { "type": "object", "properties": { "state":{ - "summary": "onWiFiStateChange", + "summary": "WiFi State", "type": "integer", "example": "5" + }, + "status": { + "summary": "WiFi status", + "type": "string", + "example": "WIFI_STATE_CONNECTED" } }, "required": [ - "state" + "state", + "status" ] } }, @@ -1488,7 +1566,7 @@ "type": "string", "example": "home-new_123" }, - "signalStrength":{ + "strength":{ "summary": "Signal Strength", "type": "string", "example": "-27.000000" @@ -1501,7 +1579,7 @@ }, "required": [ "ssid", - "signalStrength", + "strength", "quality" ] } diff --git a/NetworkManagerConnectivity.cpp b/NetworkManagerConnectivity.cpp index e9cacd976..f76c8b4bc 100644 --- a/NetworkManagerConnectivity.cpp +++ b/NetworkManagerConnectivity.cpp @@ -158,12 +158,12 @@ namespace WPEFramework curl_easy_setopt(curl_easy_handle, CURLOPT_TIMEOUT_MS, deadline - current_time()); if ((ipversion == CURL_IPRESOLVE_V4) || (ipversion == CURL_IPRESOLVE_V6)) { - NMLOG_INFO("curlopt ipversion = %s reqtyp = %s", ipversion == CURL_IPRESOLVE_V4?"ipv4 only":"ipv6 only", headReq? "HEAD":"GET"); + NMLOG_DEBUG("curlopt ipversion = %s reqtyp = %s", ipversion == CURL_IPRESOLVE_V4?"ipv4 only":"ipv6 only", headReq? "HEAD":"GET"); curl_easy_setopt(curl_easy_handle, CURLOPT_IPRESOLVE, ipversion); } else { - NMLOG_INFO("curlopt ipversion = whatever reqtyp = %s", headReq? "HEAD":"GET"); + NMLOG_DEBUG("curlopt ipversion = whatever reqtyp = %s", headReq? "HEAD":"GET"); } if(curlVerboseEnabled()) curl_easy_setopt(curl_easy_handle, CURLOPT_VERBOSE, 1L); @@ -321,8 +321,6 @@ namespace WPEFramework setConnectivityMonitorEndpoints(cachedEndPnt); NMLOG_WARNING("cached connectivity endpoints loaded .."); } - else - connectivityMonitorEndpt.push_back("http://clients3.google.com/generate_204"); doContinuousMonitor = false; doConnectivityMonitor = false; @@ -386,7 +384,7 @@ namespace WPEFramework return false; } - nsm_internetState ConnectivityMonitor::getInternetState(nsm_ipversion ipversion) + nsm_internetState ConnectivityMonitor::getInternetState(nsm_ipversion& ipversion) { nsm_internetState internetState = nsm_internetState::UNKNOWN; // If monitor connectivity is running take the cache value @@ -395,16 +393,20 @@ namespace WPEFramework && gIpv4InternetState != nsm_internetState::UNKNOWN ) { NMLOG_WARNING("Reading Ipv4 internet state cached value %s", getInternetStateString(gIpv4InternetState)); internetState = gIpv4InternetState; + ipversion = NSM_IPRESOLVE_V4; } else if ( doContinuousMonitor && (nsm_ipversion::NSM_IPRESOLVE_V6 == ipversion || nsm_ipversion::NSM_IPRESOLVE_WHATEVER == ipversion) && gIpv6InternetState != nsm_internetState::UNKNOWN ) { NMLOG_WARNING("Reading Ipv6 internet state cached value %s", getInternetStateString(gIpv6InternetState)); internetState = gIpv6InternetState; + ipversion = NSM_IPRESOLVE_V6; } else { TestConnectivity testInternet(getConnectivityMonitorEndpoints(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, NMCONNECTIVITY_CURL_GET_REQUEST, ipversion); internetState = testInternet.getInternetState(); + // TODO : Lets not hard code here. + ipversion = NSM_IPRESOLVE_V4; } return internetState; } @@ -505,7 +507,7 @@ namespace WPEFramework { Exchange::INetworkManager::InternetStatus oldState = static_cast(gInternetState.load()); Exchange::INetworkManager::InternetStatus newState = static_cast(newInternetState); - _instance->ReportInternetStatusChangedEvent(oldState , newState); + _instance->ReportInternetStatusChange(oldState , newState); gInternetState = newInternetState; } else diff --git a/NetworkManagerConnectivity.h b/NetworkManagerConnectivity.h index 2a39ce234..26f256fa4 100644 --- a/NetworkManagerConnectivity.h +++ b/NetworkManagerConnectivity.h @@ -118,7 +118,7 @@ namespace WPEFramework void setConnectivityMonitorEndpoints(const std::vector &endpoints); std::vector getConnectivityMonitorEndpoints(); bool isConnectedToInternet(nsm_ipversion ipversion); - nsm_internetState getInternetState(nsm_ipversion ipversion); + nsm_internetState getInternetState(nsm_ipversion& ipversion); std::string getCaptivePortalURI(); private: diff --git a/NetworkManagerGnomeEvents.cpp b/NetworkManagerGnomeEvents.cpp index b7f170627..bd12c3419 100644 --- a/NetworkManagerGnomeEvents.cpp +++ b/NetworkManagerGnomeEvents.cpp @@ -491,7 +491,7 @@ namespace WPEFramework if(oldIface != newIface) { if(_instance != nullptr) - _instance->ReportActiveInterfaceChangedEvent(oldIface, newIface); + _instance->ReportActiveInterfaceChange(oldIface, newIface); NMLOG_INFO("old interface - %s new interface - %s", oldIface.c_str(), newIface.c_str()); oldIface = newIface; } @@ -525,16 +525,16 @@ namespace WPEFramework } NMLOG_DEBUG("%s interface state changed - %s", iface.c_str(), state.c_str()); if(_instance != nullptr && (iface == _nmEventInstance->nmEvents.ifnameWlan0 || iface == _nmEventInstance->nmEvents.ifnameEth0)) - _instance->ReportInterfaceStateChangedEvent(static_cast(newState), iface); + _instance->ReportInterfaceStateChange(static_cast(newState), iface); } void GnomeNetworkManagerEvents::onWIFIStateChanged(uint8_t state) { if(_instance != nullptr) - _instance->ReportWiFiStateChangedEvent(static_cast(state)); + _instance->ReportWiFiStateChange(static_cast(state)); } - void GnomeNetworkManagerEvents::onAddressChangeCb(std::string iface, std::string ipAddress, bool acqired, bool isIPv6) + void GnomeNetworkManagerEvents::onAddressChangeCb(std::string iface, std::string ipAddress, bool acquired, bool isIPv6) { static std::map ipv6Map; static std::map ipv4Map; @@ -563,9 +563,13 @@ namespace WPEFramework ipv4Map[iface] = ipAddress; } + Exchange::INetworkManager::IPStatus ipStatus{}; + if (acquired) + ipStatus = Exchange::INetworkManager::IP_ACQUIRED; + if(_instance != nullptr) - _instance->ReportIPAddressChangedEvent(iface, acqired, true, ipAddress); - NMLOG_INFO("iface:%s - ipaddress:%s - %s - isIPv6:%s", iface.c_str(), ipAddress.c_str(), acqired?"acquired":"lost", isIPv6?"true":"false"); + _instance->ReportIPAddressChange(iface, isIPv6?"IPv6":"IPv4", ipAddress, ipStatus); + NMLOG_INFO("iface:%s - ipaddress:%s - %s - isIPv6:%s", iface.c_str(), ipAddress.c_str(), acquired?"acquired":"lost", isIPv6?"true":"false"); } void GnomeNetworkManagerEvents::onAvailableSSIDsCb(NMDeviceWifi *wifiDevice, GParamSpec *pspec, gpointer userData) @@ -597,7 +601,7 @@ namespace WPEFramework if(_nmEventInstance->doScanNotify) { _nmEventInstance->doScanNotify = false; - _instance->ReportAvailableSSIDsEvent(ssidListJson); + _instance->ReportAvailableSSIDs(ssidListJson); } } diff --git a/NetworkManagerGnomeEvents.h b/NetworkManagerGnomeEvents.h index d65354d8d..d775aee91 100644 --- a/NetworkManagerGnomeEvents.h +++ b/NetworkManagerGnomeEvents.h @@ -43,11 +43,11 @@ namespace WPEFramework { public: - static void onInterfaceStateChangeCb(uint8_t newState, std::string iface); // ReportInterfaceStateChangedEvent - static void onAddressChangeCb(std::string iface, std::string ipAddress, bool acqired, bool isIPv6); // ReportIPAddressChangedEvent - static void onActiveInterfaceChangeCb(std::string newInterface); // ReportActiveInterfaceChangedEvent - static void onAvailableSSIDsCb(NMDeviceWifi *wifiDevice, GParamSpec *pspec, gpointer userData); // ReportAvailableSSIDsEvent - static void onWIFIStateChanged(uint8_t state); // ReportWiFiStateChangedEvent + static void onInterfaceStateChangeCb(uint8_t newState, std::string iface); // ReportInterfaceStateChange + static void onAddressChangeCb(std::string iface, std::string ipAddress, bool acqired, bool isIPv6); // ReportIPAddressChange + static void onActiveInterfaceChangeCb(std::string newInterface); // ReportActiveInterfaceChange + static void onAvailableSSIDsCb(NMDeviceWifi *wifiDevice, GParamSpec *pspec, gpointer userData); // ReportAvailableSSIDs + static void onWIFIStateChanged(uint8_t state); // ReportWiFiStateChange public: static GnomeNetworkManagerEvents* getInstance(); diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index f069bc946..6b1fbd314 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -70,14 +70,14 @@ namespace WPEFramework if (device) { if(i == 0) - tmp.m_type = string("WIFI"); + tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_WIFI; else - tmp.m_type = string("ETHERNET"); - tmp.m_name = interfaces[i].c_str(); - tmp.m_mac = nm_device_get_hw_address(device); + tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_ETHERNET; + tmp.name = interfaces[i].c_str(); + tmp.mac = nm_device_get_hw_address(device); state = nm_device_get_state(device); - tmp.m_isEnabled = (state > NM_DEVICE_STATE_UNAVAILABLE) ? true : false; - tmp.m_isConnected = (state > NM_DEVICE_STATE_DISCONNECTED) ? true : false; + tmp.enabled = (state > NM_DEVICE_STATE_UNAVAILABLE) ? true : false; + tmp.connected = (state > NM_DEVICE_STATE_DISCONNECTED) ? true : false; interfaceList.push_back(tmp); //g_clear_object(&device); } @@ -194,7 +194,7 @@ namespace WPEFramework return rc; } - uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool& enabled /* @in */) + uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) { uint32_t rc = Core::ERROR_NONE; if(client == nullptr) @@ -263,7 +263,7 @@ namespace WPEFramework } /* @brief Get IP Address Of the Interface */ - uint32_t NetworkManagerImplementation::GetIPSettings(const string& interface /* @in */, const string& ipversion /* @in */, IPAddressInfo& result /* @out */) + uint32_t NetworkManagerImplementation::GetIPSettings(string& interface /* @inout */, const string &ipversion /* @in */, IPAddress& result /* @out */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; NMActiveConnection *conn = NULL; @@ -361,19 +361,19 @@ namespace WPEFramework dhcpserver = nm_dhcp_config_get_one_option (dhcp4_config, "dhcp_server_identifier"); if(!ipversion.empty()) - result.m_ipAddrType = ipversion.c_str(); + result.ipversion = ipversion.c_str(); else - result.m_ipAddrType = "IPv4"; + result.ipversion = "IPv4"; if(dhcpserver) - result.m_dhcpServer = dhcpserver; - result.m_v6LinkLocal = ""; - result.m_ipAddress = nm_ip_address_get_address(address); - result.m_prefix = nm_ip_address_get_prefix(address); - result.m_gateway = gateway; + result.dhcpserver = dhcpserver; + result.ula = ""; + result.ipaddress = nm_ip_address_get_address(address); + result.prefix = nm_ip_address_get_prefix(address); + result.gateway = gateway; if((*(&dns_arr[0]))!=NULL) - result.m_primaryDns = *(&dns_arr[0]); + result.primarydns = *(&dns_arr[0]); if((*(&dns_arr[1]))!=NULL ) - result.m_secondaryDns = *(&dns_arr[1]); + result.secondarydns = *(&dns_arr[1]); rc = Core::ERROR_NONE; } @@ -387,7 +387,7 @@ namespace WPEFramework p = nm_ip_config_get_addresses(ip6_config); for (i = 0; i < p->len; i++) { a = static_cast(p->pdata[i]); - result.m_ipAddress = nm_ip_address_get_address(a); + result.ipaddress = nm_ip_address_get_address(a); NMLOG_DEBUG("\tinet6 %s/%d\n", nm_ip_address_get_address(a), nm_ip_address_get_prefix(a)); } gateway = nm_ip_config_get_gateway(ip6_config); @@ -397,16 +397,16 @@ namespace WPEFramework dhcp6_config = nm_active_connection_get_dhcp6_config(conn); dhcpserver = nm_dhcp_config_get_one_option (dhcp6_config, "dhcp_server_identifier"); - result.m_ipAddrType = ipversion.c_str(); + result.ipversion = ipversion.c_str(); if(dhcpserver) - result.m_dhcpServer = dhcpserver; - result.m_v6LinkLocal = ""; - result.m_prefix = 0; - result.m_gateway = gateway; + result.dhcpserver = dhcpserver; + result.ula = ""; + result.prefix = 0; + result.gateway = gateway; if((*(&dns_arr[0]))!=NULL) - result.m_primaryDns = *(&dns_arr[0]); + result.primarydns = *(&dns_arr[0]); if((*(&dns_arr[1]))!=NULL ) - result.m_secondaryDns = *(&dns_arr[1]); + result.secondarydns = *(&dns_arr[1]); } rc = Core::ERROR_NONE; } @@ -445,7 +445,7 @@ namespace WPEFramework /* @brief Set IP Address Of the Interface */ - uint32_t NetworkManagerImplementation::SetIPSettings(const string& interface /* @in */, const string &ipversion /* @in */, const IPAddressInfo& address /* @in */) + uint32_t NetworkManagerImplementation::SetIPSettings(const string& interface /* @in */, const IPAddress& address /* @in */) { GMainLoop *g_loop; g_loop = g_main_loop_new(NULL, FALSE); @@ -476,9 +476,9 @@ namespace WPEFramework break; } } - if (!address.m_autoConfig) + if (!address.autoconfig) { - if (nmUtils::caseInsensitiveCompare("IPv4", ipversion)) + if (nmUtils::caseInsensitiveCompare("IPv4", address.ipversion)) { NMSettingIPConfig *ip4_config = nm_connection_get_setting_ip4_config(conn); if (ip4_config == NULL) @@ -487,15 +487,15 @@ namespace WPEFramework } NMIPAddress *ipAddress; setting = nm_connection_get_setting_by_name(conn, "ipv4"); - ipAddress = nm_ip_address_new(AF_INET, address.m_ipAddress.c_str(), address.m_prefix, NULL); + ipAddress = nm_ip_address_new(AF_INET, address.ipaddress.c_str(), address.prefix, NULL); nm_setting_ip_config_clear_addresses(ip4_config); nm_setting_ip_config_add_address(NM_SETTING_IP_CONFIG(setting), ipAddress); nm_setting_ip_config_clear_dns(ip4_config); - nm_setting_ip_config_add_dns(ip4_config, address.m_primaryDns.c_str()); - nm_setting_ip_config_add_dns(ip4_config, address.m_secondaryDns.c_str()); + nm_setting_ip_config_add_dns(ip4_config, address.primarydns.c_str()); + nm_setting_ip_config_add_dns(ip4_config, address.secondarydns.c_str()); g_object_set(G_OBJECT(ip4_config), - NM_SETTING_IP_CONFIG_GATEWAY, address.m_gateway.c_str(), + NM_SETTING_IP_CONFIG_GATEWAY, address.gateway.c_str(), NM_SETTING_IP_CONFIG_NEVER_DEFAULT, FALSE, NULL); @@ -509,7 +509,7 @@ namespace WPEFramework } else { - if (nmUtils::caseInsensitiveCompare("IPv4", ipversion)) + if (nmUtils::caseInsensitiveCompare("IPv4", address.ipversion)) { s_ip4 = (NMSettingIP4Config *)nm_setting_ip4_config_new(); g_object_set(G_OBJECT(s_ip4), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); @@ -547,9 +547,11 @@ namespace WPEFramework return rc; } - uint32_t NetworkManagerImplementation::StartWiFiScan(const WiFiFrequency frequency /* @in */) + uint32_t NetworkManagerImplementation::StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; + (void) ssids; + nmEvent->setwifiScanOptions(true, true); if(wifi->wifiScanRequest(frequency)) rc = Core::ERROR_NONE; @@ -606,7 +608,7 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::WiFiConnect(const WiFiConnectTo& ssid /* @in */) { uint32_t rc = Core::ERROR_GENERAL; - if(ssid.m_ssid.empty() || ssid.m_ssid.size() > 32) + if(ssid.ssid.empty() || ssid.ssid.size() > 32) { NMLOG_WARNING("ssid is invalied"); return rc; @@ -615,7 +617,7 @@ namespace WPEFramework if(!wifi->isWifiScannedRecently()) { nmEvent->setwifiScanOptions(false, true); // not notify scan result but print logs - if(!wifi->wifiScanRequest(Exchange::INetworkManager::WiFiFrequency::WIFI_FREQUENCY_WHATEVER, ssid.m_ssid)) + if(!wifi->wifiScanRequest("", ssid.ssid)) { NMLOG_WARNING("scanning failed but try to connect"); } @@ -648,8 +650,8 @@ namespace WPEFramework WiFiSSIDInfo ssidInfo; if(wifi->wifiConnectedSSIDInfo(ssidInfo)) { - ssid = ssidInfo.m_ssid; - signalStrength = ssidInfo.m_signalStrength; + ssid = ssidInfo.ssid; + signalStrength = ssidInfo.strength; float signalStrengthFloat = 0.0f; if(!signalStrength.empty()) diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 497f567cd..12d8e49af 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -191,48 +191,31 @@ namespace WPEFramework if(size<=32) { std::string ssidTmp(reinterpret_cast(ssidData), size); - wifiInfo.m_ssid = ssidTmp; - NMLOG_INFO("ssid: %s", wifiInfo.m_ssid.c_str()); + wifiInfo.ssid = ssidTmp; + NMLOG_INFO("ssid: %s", wifiInfo.ssid.c_str()); } else { NMLOG_ERROR("Invallied ssid length Error"); - wifiInfo.m_ssid.clear(); + wifiInfo.ssid.clear(); return; } } else { - wifiInfo.m_ssid = "-----"; - NMLOG_DEBUG("ssid: %s", wifiInfo.m_ssid.c_str()); + wifiInfo.ssid = "-----"; + NMLOG_DEBUG("ssid: %s", wifiInfo.ssid.c_str()); } - wifiInfo.m_bssid = (hwaddr != nullptr) ? hwaddr : "-----"; - NMLOG_DEBUG("bssid: %s", wifiInfo.m_bssid.c_str()); - - if (freq >= 2400 && freq < 5000) { - wifiInfo.m_frequency = Exchange::INetworkManager::WiFiFrequency::WIFI_FREQUENCY_2_4_GHZ; - NMLOG_DEBUG("freq: WIFI_FREQUENCY_2_4_GHZ"); - } - else if (freq >= 5000 && freq < 6000) { - wifiInfo.m_frequency = Exchange::INetworkManager::WiFiFrequency::WIFI_FREQUENCY_5_GHZ; - NMLOG_DEBUG("freq: WIFI_FREQUENCY_5_GHZ"); - } - else if (freq >= 6000) { - wifiInfo.m_frequency = Exchange::INetworkManager::WiFiFrequency::WIFI_FREQUENCY_6_GHZ; - NMLOG_DEBUG("freq: WIFI_FREQUENCY_6_GHZ"); - } - else { - wifiInfo.m_frequency = Exchange::INetworkManager::WiFiFrequency::WIFI_FREQUENCY_WHATEVER; - NMLOG_DEBUG("freq: No available !"); - } - - wifiInfo.m_rate = std::to_string(bitrate); - NMLOG_DEBUG("bitrate : %s kbit/s", wifiInfo.m_rate.c_str()); + wifiInfo.bssid = (hwaddr != nullptr) ? hwaddr : "-----"; + NMLOG_DEBUG("bssid: %s", wifiInfo.bssid.c_str()); + wifiInfo.frequency = std::to_string((double)freq/1000); + wifiInfo.rate = std::to_string(bitrate); + NMLOG_DEBUG("bitrate : %s kbit/s", wifiInfo.rate.c_str()); //TODO signal strenght to dBm - wifiInfo.m_signalStrength = std::to_string(static_cast(strength)); - NMLOG_DEBUG("sterngth: %s %%", wifiInfo.m_signalStrength.c_str()); - wifiInfo.m_securityMode = static_cast(nmUtils::wifiSecurityModeFromAp(flags, wpaFlags, rsnFlags)); + wifiInfo.strength = std::to_string(static_cast(strength)); + NMLOG_DEBUG("sterngth: %s %%", wifiInfo.strength.c_str()); + wifiInfo.security = static_cast(nmUtils::wifiSecurityModeFromAp(flags, wpaFlags, rsnFlags)); NMLOG_DEBUG("security %s", nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); NMLOG_DEBUG("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); } @@ -401,8 +384,8 @@ namespace WPEFramework bool wifiManager::wifiConnect(Exchange::INetworkManager::WiFiConnectTo wifiData) { - const char *ssid_in = wifiData.m_ssid.c_str(); - const char* password_in = wifiData.m_passphrase.c_str(); + const char *ssid_in = wifiData.ssid.c_str(); + const char* password_in = wifiData.passphrase.c_str(); NMAccessPoint *AccessPoint = NULL; GPtrArray *allaps = NULL; const char *conName = ssid_in; @@ -542,19 +525,19 @@ namespace WPEFramework GError *error = NULL; NMLOG_INFO("Ap securtity mode is 802.1X"); - NMLOG_DEBUG("802.1x Identity : %s", wifiData.m_identity.c_str()); - NMLOG_DEBUG("802.1x CA cert path : %s", wifiData.m_caCert.c_str()); - NMLOG_DEBUG("802.1x Client cert path : %s", wifiData.m_clientCert.c_str()); - NMLOG_DEBUG("802.1x Private key path : %s", wifiData.m_privateKey.c_str()); - NMLOG_DEBUG("802.1x Private key psswd : %s", wifiData.m_privateKeyPasswd.c_str()); + NMLOG_DEBUG("802.1x Identity : %s", wifiData.eap_identity.c_str()); + NMLOG_DEBUG("802.1x CA cert path : %s", wifiData.ca_cert.c_str()); + NMLOG_DEBUG("802.1x Client cert path : %s", wifiData.client_cert.c_str()); + NMLOG_DEBUG("802.1x Private key path : %s", wifiData.private_key.c_str()); + NMLOG_DEBUG("802.1x Private key psswd : %s", wifiData.private_key_passwd.c_str()); s8021X = (NMSetting8021x *) nm_setting_802_1x_new(); nm_connection_add_setting(connection, NM_SETTING(s8021X)); - g_object_set(s8021X, NM_SETTING_802_1X_IDENTITY, wifiData.m_identity.c_str(), NULL); + g_object_set(s8021X, NM_SETTING_802_1X_IDENTITY, wifiData.eap_identity.c_str(), NULL); nm_setting_802_1x_add_eap_method(s8021X, "tls"); - if(!wifiData.m_caCert.empty() && !nm_setting_802_1x_set_ca_cert(s8021X, - wifiData.m_caCert.c_str(), + if(!wifiData.ca_cert.empty() && !nm_setting_802_1x_set_ca_cert(s8021X, + wifiData.ca_cert.c_str(), NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error)) @@ -564,8 +547,8 @@ namespace WPEFramework return false; } - if(!wifiData.m_clientCert.empty() && !nm_setting_802_1x_set_client_cert(s8021X, - wifiData.m_clientCert.c_str(), + if(!wifiData.client_cert.empty() && !nm_setting_802_1x_set_client_cert(s8021X, + wifiData.client_cert.c_str(), NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error)) @@ -575,9 +558,9 @@ namespace WPEFramework return false; } - if(!wifiData.m_privateKey.empty() && !nm_setting_802_1x_set_private_key(s8021X, - wifiData.m_privateKey.c_str(), - wifiData.m_privateKeyPasswd.c_str(), + if(!wifiData.private_key.empty() && !nm_setting_802_1x_set_private_key(s8021X, + wifiData.private_key.c_str(), + wifiData.private_key_passwd.c_str(), NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error)) @@ -687,20 +670,20 @@ namespace WPEFramework NM_SETTING_CONNECTION_UUID, uuid, NM_SETTING_CONNECTION_ID, - ssidinfo.m_ssid.c_str(), + ssidinfo.ssid.c_str(), NM_SETTING_CONNECTION_TYPE, "802-11-wireless", NULL); NMConnection *connection = nm_simple_connection_new(); nm_connection_add_setting(connection, NM_SETTING(nmConnSec)); nmSettingsWifi = (NMSettingWireless *)nm_setting_wireless_new(); - GString *ssidStr = g_string_new(ssidinfo.m_ssid.c_str()); + GString *ssidStr = g_string_new(ssidinfo.ssid.c_str()); g_object_set(G_OBJECT(nmSettingsWifi), NM_SETTING_WIRELESS_SSID, ssidStr, NULL); nm_connection_add_setting(connection, NM_SETTING(nmSettingsWifi)); nmSettingsWifiSec = (NMSettingWirelessSecurity *)nm_setting_wireless_security_new(); // TODO chek different securtity mode and portocol and add settings - switch(ssidinfo.m_securityMode) + switch(ssidinfo.security) { case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES: case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK: @@ -710,8 +693,8 @@ namespace WPEFramework case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE: { g_object_set(G_OBJECT(nmSettingsWifiSec), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,"wpa-psk", NULL); - if(!ssidinfo.m_passphrase.empty()) - g_object_set(G_OBJECT(nmSettingsWifiSec), NM_SETTING_WIRELESS_SECURITY_PSK, ssidinfo.m_passphrase.c_str(), NULL); + if(!ssidinfo.passphrase.empty()) + g_object_set(G_OBJECT(nmSettingsWifiSec), NM_SETTING_WIRELESS_SECURITY_PSK, ssidinfo.passphrase.c_str(), NULL); break; } case Exchange::INetworkManager::WIFI_SECURITY_NONE: @@ -858,7 +841,7 @@ namespace WPEFramework g_main_loop_quit(_wifiManager->loop); } - bool wifiManager::wifiScanRequest(const Exchange::INetworkManager::WiFiFrequency frequency, std::string ssidReq) + bool wifiManager::wifiScanRequest(std::string frequency, std::string ssidReq) { if(!createClientNewConnection()) return false; diff --git a/NetworkManagerGnomeWIFI.h b/NetworkManagerGnomeWIFI.h index ec17b4751..8762f409b 100644 --- a/NetworkManagerGnomeWIFI.h +++ b/NetworkManagerGnomeWIFI.h @@ -46,7 +46,7 @@ namespace WPEFramework bool wifiDisconnect(); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); bool wifiConnect(Exchange::INetworkManager::WiFiConnectTo wifiData); - bool wifiScanRequest(const Exchange::INetworkManager::WiFiFrequency frequency, std::string ssidReq = ""); + bool wifiScanRequest(std::string frequency, std::string ssidReq = ""); bool isWifiScannedRecently(int timelimitInSec = 10); // default 10 sec as shotest scanning interval bool getKnownSSIDs(std::list& ssids); bool addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo ssidinfo); diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 7315ca0f1..7da44a9eb 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -100,7 +100,7 @@ namespace WPEFramework return Core::ERROR_NONE; } - uint32_t NetworkManagerImplementation::Configure(const string& configLine /* @in */, NMLogging& logLevel /* @out */) + uint32_t NetworkManagerImplementation::Configure(const string& configLine /* @in */) { if(configLine.empty()) { @@ -123,9 +123,7 @@ namespace WPEFramework NMLOG_DEBUG("config : stun interval %d", m_stunBindTimeout); NMLOG_DEBUG("config : loglevel %d", config.loglevel.Value()); - logLevel = static_cast (config.loglevel.Value()); - // configure loglevel in libWPEFrameworkNetworkManagerImplementation.so - NetworkManagerLogger::SetLevel(static_cast (logLevel)); + NetworkManagerLogger::SetLevel(static_cast (config.loglevel.Value())); /* load connectivity monitor endpoints */ std::vector connectEndpts; @@ -150,7 +148,19 @@ namespace WPEFramework connectEndpts.push_back(config.connectivityConf.endpoint_5.Value().c_str()); } - connectivityMonitor.setConnectivityMonitorEndpoints(connectEndpts); + /* check whether the endpoint is already loaded from Cache; if Yes, do not use the one from configuration */ + if (connectivityMonitor.getConnectivityMonitorEndpoints().size() < 1) + { + NMLOG_INFO("config : Use the connectivity endpoint from config"); + connectivityMonitor.setConnectivityMonitorEndpoints(connectEndpts); + } + else if (connectEndpts.size() < 1) + { + std::vector backup; + NMLOG_INFO("config : Connectivity endpoints are empty in config; use the default"); + backup.push_back("http://clients3.google.com/generate_204"); + connectivityMonitor.setConnectivityMonitorEndpoints(backup); + } } else NMLOG_ERROR("Plugin configuration read error !"); @@ -211,7 +221,7 @@ namespace WPEFramework } /* @brief Get Internet Connectivty Status */ - uint32_t NetworkManagerImplementation::IsConnectedToInternet(const string &ipversion /* @in */, InternetStatus &result /* @out */) + uint32_t NetworkManagerImplementation::IsConnectedToInternet(string &ipversion /* @in */, InternetStatus &result /* @out */) { LOG_ENTRY_FUNCTION(); nsm_internetState isconnected; @@ -231,6 +241,11 @@ namespace WPEFramework else result = INTERNET_NOT_AVAILABLE; + if (NSM_IPRESOLVE_V6 == tmpVersion) + ipversion = "IPv6"; + else + ipversion = "IPv4"; + return Core::ERROR_NONE; } @@ -263,15 +278,16 @@ namespace WPEFramework } /* @brief Get the Public IP used for external world communication */ - uint32_t NetworkManagerImplementation::GetPublicIP (const string &ipversion /* @in */, string& ipAddress /* @out */) + uint32_t NetworkManagerImplementation::GetPublicIP (const string &ipversion /* @in */, string& ipaddress /* @out */) { LOG_ENTRY_FUNCTION(); stun::bind_result result; - bool isIPv6 = (0 == strcasecmp("IPv6", ipversion.c_str())); + bool isIPv6 = (ipversion == "IPv6"); + stun::protocol proto (isIPv6 ? stun::protocol::af_inet6 : stun::protocol::af_inet); if(stunClient.bind(m_stunEndPoint, m_stunPort, m_defaultInterface, proto, m_stunBindTimeout, m_stunCacheTimeout, result)) { - ipAddress = result.public_ip; + ipaddress = result.public_ip; return Core::ERROR_NONE; } else @@ -281,9 +297,19 @@ namespace WPEFramework } /* @brief Set the network manager plugin log level */ - uint32_t NetworkManagerImplementation::SetLogLevel(const NMLogging& logLevel /* @in */) + uint32_t NetworkManagerImplementation::SetLogLevel(const Logging& level /* @in */) + { + NetworkManagerLogger::SetLevel((LogLevel)level); + return Core::ERROR_NONE; + } + + /* @brief Get the network manager plugin log level */ + uint32_t NetworkManagerImplementation::GetLogLevel(Logging& level /* @out */) { - NetworkManagerLogger::SetLevel((LogLevel)logLevel); + LogLevel inLevel; + NetworkManagerLogger::GetLevel(inLevel); + + level = static_cast(inLevel); return Core::ERROR_NONE; } @@ -291,6 +317,7 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::Ping (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const uint16_t timeOutInSeconds /* @in */, const string guid /* @in */, string& response /* @out */) { char cmd[100] = ""; + string tempResult = ""; if(0 == strcasecmp("IPv6", ipversion.c_str())) { snprintf(cmd, sizeof(cmd), "ping6 -c %d -W %d '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); @@ -302,7 +329,12 @@ namespace WPEFramework NMLOG_DEBUG ("The Command is %s", cmd); string commandToExecute(cmd); - executeExternally(NETMGR_PING, commandToExecute, response); + executeExternally(NETMGR_PING, commandToExecute, tempResult); + + JsonObject temp; + temp.FromString(tempResult); + temp["endpoint"] = endpoint; + temp.ToString(response); return Core::ERROR_NONE; } @@ -326,7 +358,7 @@ namespace WPEFramework executeExternally(NETMGR_TRACE, commandToExecute, tempResult); JsonObject temp; - temp["target"] = endpoint; + temp["endpoint"] = endpoint; temp["results"] = tempResult; temp.ToString(response); @@ -485,7 +517,7 @@ namespace WPEFramework return Core::ERROR_NONE; } - void NetworkManagerImplementation::ReportInterfaceStateChangedEvent(INetworkManager::InterfaceState state, string interface) + void NetworkManagerImplementation::ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface) { LOG_ENTRY_FUNCTION(); if(Exchange::INetworkManager::INTERFACE_LINK_DOWN == state) { @@ -494,7 +526,6 @@ namespace WPEFramework connectivityMonitor.startConnectivityMonitor(false); } - NMLOG_INFO("Posting onInterfaceStateChange %s", interface.c_str()); _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onInterfaceStateChange(state, interface); @@ -502,48 +533,45 @@ namespace WPEFramework _notificationLock.Unlock(); } - void NetworkManagerImplementation::ReportIPAddressChangedEvent(const string& interface, bool isAcquired, bool isIPv6, const string& ipAddress) + void NetworkManagerImplementation::ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface) { - LOG_ENTRY_FUNCTION(); - if (isAcquired) { - // Start the connectivity monitor with 'true' to indicate the interface is up. - // The monitor will conntinoue even after no internet retry completed, Exit when fully connectd. - connectivityMonitor.startConnectivityMonitor(true); - } - - NMLOG_INFO("Posting onIPAddressChange %s", ipAddress.c_str()); + NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { - callback->onIPAddressChange(interface, isAcquired, isIPv6, ipAddress); + callback->onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); } _notificationLock.Unlock(); } - void NetworkManagerImplementation::ReportActiveInterfaceChangedEvent(const string prevActiveInterface, const string currentActiveinterface) + void NetworkManagerImplementation::ReportIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status) { LOG_ENTRY_FUNCTION(); - NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); + if (Exchange::INetworkManager::IP_ACQUIRED == status) { + // Start the connectivity monitor with 'true' to indicate the interface is up. + // The monitor will conntinoue even after no internet retry completed, Exit when fully connectd. + connectivityMonitor.startConnectivityMonitor(true); + } + + NMLOG_INFO("Posting onIPAddressChange %s", ipaddress.c_str()); _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { - callback->onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); + callback->onIPAddressChange(interface, ipversion, ipaddress, status); } _notificationLock.Unlock(); } - void NetworkManagerImplementation::ReportInternetStatusChangedEvent(const InternetStatus oldState, const InternetStatus newstate) + void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) { - LOG_ENTRY_FUNCTION(); - NMLOG_INFO("Posting onInternetStatusChange"); + NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { - callback->onInternetStatusChange(oldState, newstate); + callback->onInternetStatusChange(prevState, currState); } _notificationLock.Unlock(); } - void NetworkManagerImplementation::ReportAvailableSSIDsEvent(const string jsonOfWiFiScanResults) + void NetworkManagerImplementation::ReportAvailableSSIDs(const string jsonOfWiFiScanResults) { - LOG_ENTRY_FUNCTION(); _notificationLock.Lock(); NMLOG_INFO("Posting onAvailableSSIDs result is, %s", jsonOfWiFiScanResults.c_str()); for (const auto callback : _notificationCallbacks) { @@ -552,9 +580,8 @@ namespace WPEFramework _notificationLock.Unlock(); } - void NetworkManagerImplementation::ReportWiFiStateChangedEvent(const INetworkManager::WiFiState state) + void NetworkManagerImplementation::ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state) { - LOG_ENTRY_FUNCTION(); /* start signal strength monitor when wifi connected */ if(INetworkManager::WiFiState::WIFI_STATE_CONNECTED == state) m_wifiSignalMonitor.startWiFiSignalStrengthMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC); @@ -567,13 +594,12 @@ namespace WPEFramework _notificationLock.Unlock(); } - void NetworkManagerImplementation::ReportWiFiSignalStrengthChangedEvent(const string ssid, const string signalLevel, const WiFiSignalQuality signalQuality) + void NetworkManagerImplementation::ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) { - LOG_ENTRY_FUNCTION(); NMLOG_INFO("Posting onWiFiSignalStrengthChange"); _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { - callback->onWiFiSignalStrengthChange(ssid, signalLevel, signalQuality); + callback->onWiFiSignalStrengthChange(ssid, strength, quality); } _notificationLock.Unlock(); diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 8c9839082..d6ae934c2 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -35,8 +35,6 @@ using namespace std; #include "NetworkManagerConnectivity.h" #include "NetworkManagerStunClient.h" -#define LOG_ENTRY_FUNCTION() { NMLOG_DEBUG("Entering=%s", __FUNCTION__ ); } - namespace WPEFramework { namespace Plugin @@ -152,18 +150,18 @@ namespace WPEFramework uint32_t SetPrimaryInterface (const string& interface/* @in */) override; /* @brief Enable/Disable the given interface */ - uint32_t SetInterfaceState(const string& interface/* @in */, const bool& isEnabled/* @in */) override; + uint32_t SetInterfaceState(const string& interface/* @in */, const bool isEnabled/* @in */) override; /* @brief Get the state of given interface */ uint32_t GetInterfaceState(const string& interface/* @in */, bool& isEnabled/* @out */) override; /* @brief Get IP Address Of the Interface */ - uint32_t GetIPSettings(const string& interface /* @in */, const string &ipversion /* @in */, IPAddressInfo& result /* @out */) override; + uint32_t GetIPSettings(string& interface /* @inout */, const string& ipversion /* @in */, IPAddress& address /* @out */) override; /* @brief Set IP Address Of the Interface */ - uint32_t SetIPSettings(const string& interface /* @in */, const string &ipversion /* @in */, const IPAddressInfo& address /* @in */) override; + uint32_t SetIPSettings(const string& interface /* @in */, const IPAddress& address /* @in */) override; // WiFi Specific Methods /* @brief Initiate a WIFI Scan; This is Async method and returns the scan results as Event */ - uint32_t StartWiFiScan(const WiFiFrequency frequency /* @in */); + uint32_t StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) override; uint32_t StopWiFiScan(void) override; uint32_t GetKnownSSIDs(IStringIterator*& ssids /* @out */) override; @@ -188,7 +186,7 @@ namespace WPEFramework uint32_t SetConnectivityTestEndpoints(IStringIterator* const endPoints /* @in */) override; /* @brief Get Internet Connectivty Status */ - uint32_t IsConnectedToInternet(const string &ipversion /* @in */, InternetStatus &result /* @out */) override; + uint32_t IsConnectedToInternet(string &ipversion /* @inout */, InternetStatus &result /* @out */) override; /* @brief Get Authentication URL if the device is behind Captive Portal */ uint32_t GetCaptivePortalURI(string &endPoints/* @out */) const override; @@ -198,7 +196,7 @@ namespace WPEFramework uint32_t StopConnectivityMonitoring(void) const override; /* @brief Get the Public IP used for external world communication */ - uint32_t GetPublicIP (const string &ipversion /* @in */, string& ipAddress /* @out */) override; + uint32_t GetPublicIP (const string &ipversion /* @in */, string& ipaddress /* @out */) override; /* @brief Request for ping and get the response in as event. The GUID used in the request will be returned in the event. */ uint32_t Ping (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const uint16_t timeOutInSeconds /* @in */, const string guid /* @in */, string& response /* @out */) override; @@ -209,19 +207,20 @@ namespace WPEFramework uint32_t GetSupportedSecurityModes(ISecurityModeIterator*& securityModes /* @out */) const override; /* @brief Set the network manager plugin log level */ - uint32_t SetLogLevel(const NMLogging& logLevel /* @in */) override; + uint32_t SetLogLevel(const Logging& level /* @in */) override; + uint32_t GetLogLevel(Logging& level /* @out */) override; /* @brief configure network manager plugin */ - uint32_t Configure(const string& configLine /* @in */, NMLogging& logLevel /* @out */) override; + uint32_t Configure(const string& configLine /* @in */) override; /* Events */ - void ReportInterfaceStateChangedEvent(INetworkManager::InterfaceState state, string interface); - void ReportIPAddressChangedEvent(const string& interface, bool isAcquired, bool isIPv6, const string& ipAddress); - void ReportActiveInterfaceChangedEvent(const string prevActiveInterface, const string currentActiveinterface); - void ReportInternetStatusChangedEvent(const InternetStatus oldState, const InternetStatus newstate); - void ReportAvailableSSIDsEvent(const string jsonOfWiFiScanResults); - void ReportWiFiStateChangedEvent(const INetworkManager::WiFiState state); - void ReportWiFiSignalStrengthChangedEvent(const string ssid , const string signalLevel , const WiFiSignalQuality signalQuality); + void ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface); + void ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface); + void ReportIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status); + void ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState); + void ReportAvailableSSIDs(const string jsonOfScanResults); + void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); + void ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality); private: void platform_init(); diff --git a/NetworkManagerJsonEnum.h b/NetworkManagerJsonEnum.h new file mode 100644 index 000000000..54725b0b6 --- /dev/null +++ b/NetworkManagerJsonEnum.h @@ -0,0 +1,99 @@ +#pragma once + +#include +#include "INetworkManager.h" + +namespace WPEFramework { + +ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::InterfaceType) + { Exchange::INetworkManager::InterfaceType::INTERFACE_TYPE_ETHERNET, _TXT("ETHERNET") }, + { Exchange::INetworkManager::InterfaceType::INTERFACE_TYPE_WIFI, _TXT("WIFI") }, + { Exchange::INetworkManager::InterfaceType::INTERFACE_TYPE_P2P, _TXT("P2P") }, +ENUM_CONVERSION_END(Exchange::INetworkManager::InterfaceType) + +ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::IPVersion) + { Exchange::INetworkManager::IPVersion::IP_ADDRESS_V4, _TXT("IPv4") }, + { Exchange::INetworkManager::IPVersion::IP_ADDRESS_V6, _TXT("IPv6") }, +ENUM_CONVERSION_END(Exchange::INetworkManager::IPVersion) + +ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::InternetStatus) + { Exchange::INetworkManager::InternetStatus::INTERNET_NOT_AVAILABLE, _TXT("NO_INTERNET") }, + { Exchange::INetworkManager::InternetStatus::INTERNET_LIMITED, _TXT("LIMITED_INTERNET") }, + { Exchange::INetworkManager::InternetStatus::INTERNET_CAPTIVE_PORTAL, _TXT("CAPTIVE_PORTAL") }, + { Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED, _TXT("FULLY_CONNECTED") }, + { Exchange::INetworkManager::InternetStatus::INTERNET_UNKNOWN, _TXT("UNKNOWN") }, +ENUM_CONVERSION_END(Exchange::INetworkManager::InternetStatus) + +ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::WIFISecurityMode) + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE, _TXT("0") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_64, _TXT("1") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_128, _TXT("2") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_TKIP, _TXT("3") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES, _TXT("4") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_TKIP, _TXT("5") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES, _TXT("6") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_ENTERPRISE_TKIP, _TXT("7") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_ENTERPRISE_AES, _TXT("8") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_ENTERPRISE_TKIP, _TXT("9") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_ENTERPRISE_AES, _TXT("10") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK, _TXT("11") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_ENTERPRISE, _TXT("12") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_PSK_AES, _TXT("13") }, + { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE, _TXT("14") }, +ENUM_CONVERSION_END(Exchange::INetworkManager::WIFISecurityMode) + +ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::WiFiWPS) + { Exchange::INetworkManager::WiFiWPS::WIFI_WPS_PBC, _TXT("PBC") }, + { Exchange::INetworkManager::WiFiWPS::WIFI_WPS_PIN, _TXT("PIN") }, + { Exchange::INetworkManager::WiFiWPS::WIFI_WPS_SERIALIZED_PIN, _TXT("SERIALIZED_PIN") }, +ENUM_CONVERSION_END(Exchange::INetworkManager::WiFiWPS) + +ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::WiFiState) + { Exchange::INetworkManager::WiFiState::WIFI_STATE_UNINSTALLED, _TXT("WIFI_STATE_UNINSTALLED") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_DISABLED, _TXT("WIFI_STATE_DISABLED") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_DISCONNECTED, _TXT("WIFI_STATE_DISCONNECTED") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_PAIRING, _TXT("WIFI_STATE_PAIRING") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTING, _TXT("WIFI_STATE_CONNECTING") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTED, _TXT("WIFI_STATE_CONNECTED") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_SSID_NOT_FOUND, _TXT("WIFI_STATE_SSID_NOT_FOUND") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_SSID_CHANGED, _TXT("WIFI_STATE_SSID_CHANGED") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTION_LOST, _TXT("WIFI_STATE_CONNECTION_LOST") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTION_FAILED, _TXT("WIFI_STATE_CONNECTION_FAILED") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTION_INTERRUPTED, _TXT("WIFI_STATE_CONNECTION_INTERRUPTED") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_INVALID_CREDENTIALS, _TXT("WIFI_STATE_INVALID_CREDENTIALS") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_AUTHENTICATION_FAILED, _TXT("WIFI_STATE_AUTHENTICATION_FAILED") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_ERROR, _TXT("WIFI_STATE_ERROR") }, + { Exchange::INetworkManager::WiFiState::WIFI_STATE_INVALID, _TXT("WIFI_STATE_INVALID") }, +ENUM_CONVERSION_END(Exchange::INetworkManager::WiFiState) + +ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::WiFiSignalQuality) + { Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED, _TXT("Disconnected") }, + { Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_WEAK, _TXT("Weak") }, + { Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_FAIR, _TXT("Fair") }, + { Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_GOOD, _TXT("Good") }, + { Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT, _TXT("Excellent") }, +ENUM_CONVERSION_END(Exchange::INetworkManager::WiFiSignalQuality) + +ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::Logging) + { Exchange::INetworkManager::Logging::LOG_LEVEL_FATAL, _TXT("LOG_LEVEL_FATAL") }, + { Exchange::INetworkManager::Logging::LOG_LEVEL_ERROR, _TXT("LOG_LEVEL_ERROR") }, + { Exchange::INetworkManager::Logging::LOG_LEVEL_WARNING, _TXT("LOG_LEVEL_WARNING") }, + { Exchange::INetworkManager::Logging::LOG_LEVEL_INFO, _TXT("LOG_LEVEL_INFO") }, + { Exchange::INetworkManager::Logging::LOG_LEVEL_DEBUG, _TXT("LOG_LEVEL_DEBUG") }, +ENUM_CONVERSION_END(Exchange::INetworkManager::Logging) + +ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::InterfaceState) + { Exchange::INetworkManager::InterfaceState::INTERFACE_ADDED, _TXT("INTERFACE_ADDED") }, + { Exchange::INetworkManager::InterfaceState::INTERFACE_LINK_UP, _TXT("INTERFACE_LINK_UP") }, + { Exchange::INetworkManager::InterfaceState::INTERFACE_LINK_DOWN, _TXT("INTERFACE_LINK_DOWN") }, + { Exchange::INetworkManager::InterfaceState::INTERFACE_ACQUIRING_IP, _TXT("INTERFACE_ACQUIRING_IP") }, + { Exchange::INetworkManager::InterfaceState::INTERFACE_REMOVED, _TXT("INTERFACE_REMOVED") }, + { Exchange::INetworkManager::InterfaceState::INTERFACE_DISABLED, _TXT("INTERFACE_DISABLED") }, +ENUM_CONVERSION_END(Exchange::INetworkManager::InterfaceState) + +ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::IPStatus) + { Exchange::INetworkManager::IPStatus::IP_LOST, _TXT("LOST") }, + { Exchange::INetworkManager::IPStatus::IP_ACQUIRED, _TXT("ACQUIRED") }, +ENUM_CONVERSION_END(Exchange::INetworkManager::IPStatus) + +} diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 06da7b6fa..3c35db251 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -18,9 +18,22 @@ **/ #include "NetworkManager.h" +#include "INetworkManager.h" +#include "NetworkManagerJsonEnum.h" + +#define LOG_INPARAM() { string json; parameters.ToString(json); NMLOG_INFO("params=%s", json.c_str() ); } +#define LOG_OUTPARAM() { string json; response.ToString(json); NMLOG_INFO("response=%s", json.c_str() ); } + +#define returnJson(rc) \ + { \ + if (Core::ERROR_NONE == rc) \ + response["success"] = true; \ + else \ + response["success"] = false; \ + LOG_OUTPARAM(); \ + return Core::ERROR_NONE; \ + } -#define LOG_INPARAM() { string json; parameters.ToString(json); NMLOG_DEBUG("%s : params=%s", __FUNCTION__, json.c_str() ); } -#define LOG_OUTPARAM() { string json; response.ToString(json); NMLOG_INFO("%s : response=%s", __FUNCTION__, json.c_str() ); } using namespace NetworkManagerLogger; @@ -39,6 +52,7 @@ namespace WPEFramework */ void NetworkManager::RegisterAllMethods() { + Register("GetLogLevel", &NetworkManager::GetLogLevel, this); Register("SetLogLevel", &NetworkManager::SetLogLevel, this); Register("GetAvailableInterfaces", &NetworkManager::GetAvailableInterfaces, this); Register("GetPrimaryInterface", &NetworkManager::GetPrimaryInterface, this); @@ -118,60 +132,70 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; LogLevel level = INFO_LEVEL; - if (parameters.HasLabel("logLevel")) + if (parameters.HasLabel("level")) { - level = static_cast (parameters["logLevel"].Number()); + level = static_cast (parameters["level"].Number()); NetworkManagerLogger::SetLevel(level); - const Exchange::INetworkManager::NMLogging log = static_cast (level); + const Exchange::INetworkManager::Logging log = static_cast (level); if (_networkManager) rc = _networkManager->SetLogLevel(log); else rc = Core::ERROR_UNAVAILABLE; } - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } - uint32_t NetworkManager::GetAvailableInterfaces (const JsonObject& parameters, JsonObject& response) + uint32_t NetworkManager::GetLogLevel (const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); + uint32_t rc = Core::ERROR_NONE; + LogLevel level = INFO_LEVEL; + NetworkManagerLogger::GetLevel(level); + response["level"] = static_cast (level); + + returnJson(rc); + } + + uint32_t NetworkManager::GetAvailableInterfaces (const JsonObject& parameters, JsonObject& response) + { + LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - Exchange::INetworkManager::IInterfaceDetailsIterator* interfaces = NULL; + + Exchange::INetworkManager::IInterfaceDetailsIterator* _interfaces{}; + if (_networkManager) - rc = _networkManager->GetAvailableInterfaces(interfaces); + rc = _networkManager->GetAvailableInterfaces(_interfaces); else rc = Core::ERROR_UNAVAILABLE; - if (interfaces) + if (Core::ERROR_NONE == rc) { - NMLOG_DEBUG("received response"); - JsonArray array; - Exchange::INetworkManager::InterfaceDetails entry{}; - while (interfaces->Next(entry) == true) { - JsonObject each; - each[_T("type")] = entry.m_type; - each[_T("name")] = entry.m_name; - each[_T("mac")] = entry.m_mac; - each[_T("isEnabled")] = entry.m_isEnabled; - each[_T("isConnected")] = entry.m_isConnected; - - array.Add(JsonValue(each)); - } + if (_interfaces != nullptr) + { + JsonArray array; + Exchange::INetworkManager::InterfaceDetails entry{}; + while (_interfaces->Next(entry) == true) + { + JsonObject each; + Core::JSON::EnumType type{entry.type}; + each["type"] = type.Data(); + each["name"] = entry.name; + each["mac"] = entry.mac; + each["enabled"] = entry.enabled; + each["connected"] = entry.connected; + + array.Add(JsonValue(each)); + } - interfaces->Release(); - NMLOG_DEBUG("Sending Success"); - response["interfaces"] = array; - response["success"] = true; + _interfaces->Release(); + response["interfaces"] = array; + } } - LOG_OUTPARAM(); - return rc; + + returnJson(rc); } uint32_t NetworkManager::GetPrimaryInterface (const JsonObject& parameters, JsonObject& response) @@ -179,13 +203,8 @@ namespace WPEFramework LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string interface; - if(m_primaryInterfaceCache.isSet()) - { - NMLOG_INFO("reading interface cached values"); - interface = m_primaryInterfaceCache.getValue(); - rc = Core::ERROR_NONE; - } - else if (_networkManager) + + if (_networkManager) rc = _networkManager->GetPrimaryInterface(interface); else rc = Core::ERROR_UNAVAILABLE; @@ -193,11 +212,8 @@ namespace WPEFramework if (Core::ERROR_NONE == rc) { response["interface"] = interface; - m_primaryInterfaceCache = interface; - response["success"] = true; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::SetPrimaryInterface (const JsonObject& parameters, JsonObject& response) @@ -217,196 +233,121 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::SetInterfaceState(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string interface = parameters["interface"].String(); - bool enabled = parameters["enabled"].Boolean(); - - if ("wlan0" != interface && "eth0" != interface) + if (parameters.HasLabel("interface") && parameters.HasLabel("enabled")) { - rc = Core::ERROR_BAD_REQUEST; - return rc; - } + const string interface = parameters["interface"].String(); + const bool enabled = parameters["enabled"].Boolean(); - if (_networkManager) - rc = _networkManager->SetInterfaceState(interface, enabled); + if ("wlan0" != interface && "eth0" != interface) + rc = Core::ERROR_BAD_REQUEST; + else if (_networkManager) + rc = _networkManager->SetInterfaceState(interface, enabled); + else + rc = Core::ERROR_UNAVAILABLE; + } else - rc = Core::ERROR_UNAVAILABLE; + rc = Core::ERROR_BAD_REQUEST; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::GetInterfaceState(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - bool isEnabled = false; - string interface = parameters["interface"].String(); - if ("wlan0" != interface && "eth0" != interface) + if (parameters.HasLabel("interface")) { - rc = Core::ERROR_BAD_REQUEST; - return rc; - } + const string interface = parameters["interface"].String(); + bool enabled; - if (_networkManager) - rc = _networkManager->GetInterfaceState(interface, isEnabled); - else - rc = Core::ERROR_UNAVAILABLE; + if ("wlan0" != interface && "eth0" != interface) + rc = Core::ERROR_BAD_REQUEST; + else if (_networkManager) + rc = _networkManager->SetInterfaceState(interface, enabled); + else + rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["enabled"] = isEnabled; - response["success"] = true; + if (Core::ERROR_NONE == rc) + response["enabled"] = enabled; } - LOG_OUTPARAM(); - return rc; + else + rc = Core::ERROR_BAD_REQUEST; + + returnJson(rc); } uint32_t NetworkManager::GetIPSettings (const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string interface = ""; - string ipversion = ""; - bool isCacheLoaded = false; - Exchange::INetworkManager::IPAddressInfo result{}; - - if (parameters.HasLabel("interface")) - interface = parameters["interface"].String(); - if (parameters.HasLabel("ipversion")) - ipversion = parameters["ipversion"].String(); - - if (interface.empty() || ("wlan0" != interface && "eth0" != interface)) - { - if(!interface.empty()) { - NMLOG_WARNING("interface is neither wlan0 nor eth0: %s", interface.c_str()); - return Core::ERROR_BAD_REQUEST; - } + Exchange::INetworkManager::IPAddress address{}; - interface = m_primaryInterfaceCache.getValue(); - } - - if(m_primaryInterfaceCache.isSet() && (interface == m_primaryInterfaceCache.getValue())) - { - /* If ipversion is empty, IPv4 will be taken as the default version */ - if(m_ipv4AddressCache.isSet() && (ipversion.empty() || strcasecmp(ipversion.c_str(), "IPv4") == 0)) - { - NMLOG_INFO("reading ipv4 settings cached values"); - result = m_ipv4AddressCache.getValue(); - rc = Core::ERROR_NONE; - isCacheLoaded = true; - } - else if(m_ipv6AddressCache.isSet() && (ipversion.empty() || strcasecmp(ipversion.c_str(), "IPv6") == 0)) - { - NMLOG_INFO("reading ipv6 settings cached values"); - result = m_ipv6AddressCache.getValue(); - rc = Core::ERROR_NONE; - isCacheLoaded = true; - } - } + string interface = parameters["interface"].String(); + string ipversion = parameters["ipversion"].String(); - if (!isCacheLoaded) - { - if (_networkManager) - { - rc = _networkManager->GetIPSettings(interface, ipversion, result); - /* The value will be cached only for the primary interface IP address. */ - if(Core::ERROR_NONE == rc && m_primaryInterfaceCache.isSet() && (interface == m_primaryInterfaceCache.getValue())) - { - NMLOG_DEBUG("caching the ip address values"); - if (strcasecmp(result.m_ipAddrType.c_str(), "IPv4") == 0) - m_ipv4AddressCache = result; - else if (strcasecmp(result.m_ipAddrType.c_str(), "IPv6") == 0) - m_ipv6AddressCache = result; - } - } - else - { - NMLOG_ERROR("_networkManager == null"); - rc = Core::ERROR_UNAVAILABLE; - } - } + if (_networkManager) + rc = _networkManager->GetIPSettings(interface, ipversion, address); + else + rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) { - response["interface"] = interface; - - if (strcasecmp (result.m_ipAddrType.c_str(), "IPv4") == 0) - result.m_ipAddrType = "IPv4"; - else if (strcasecmp (result.m_ipAddrType.c_str(), "IPv6") == 0) - result.m_ipAddrType = "IPv6"; - response["ipversion"] = result.m_ipAddrType; - response["autoconfig"] = result.m_autoConfig; - response["ipaddress"] = result.m_ipAddress; - response["prefix"] = result.m_prefix; - response["gateway"] = result.m_gateway; - response["dhcpserver"] = result.m_dhcpServer; - if(!result.m_v6LinkLocal.empty()) - response["v6LinkLocal"] = result.m_v6LinkLocal; - response["primarydns"] = result.m_primaryDns; - response["secondarydns"] = result.m_secondaryDns; - response["success"] = true; + response["interface"] = interface; + response["ipversion"] = address.ipversion; + response["autoconfig"] = address.autoconfig; + response["ipaddress"] = address.ipaddress; + response["prefix"] = address.prefix; + response["ula"] = address.ula; + response["dhcpserver"] = address.dhcpserver; + response["gateway"] = address.gateway; + response["primarydns"] = address.primarydns; + response["secondarydns"] = address.secondarydns; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::SetIPSettings(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - Exchange::INetworkManager::IPAddressInfo result{}; + Exchange::INetworkManager::IPAddress address{}; + string interface = ""; string ipversion = ""; if (parameters.HasLabel("interface")) interface = parameters["interface"].String(); - if (parameters.HasLabel("ipversion")) - ipversion = parameters["ipversion"].String(); - - if ("wlan0" != interface && "eth0" != interface) + else { rc = Core::ERROR_BAD_REQUEST; return rc; } - result.m_autoConfig = parameters["autoconfig"].Boolean(); - if (!result.m_autoConfig) + address.autoconfig = parameters["autoconfig"].Boolean(); + if (!address.autoconfig) { - result.m_ipAddress = parameters["ipaddress"]; - result.m_prefix = parameters["prefix"].Number(); - result.m_gateway = parameters["gateway"]; - result.m_primaryDns = parameters["primarydns"]; - result.m_secondaryDns = parameters["secondarydns"]; + address.ipaddress = parameters["ipaddress"].String(); + address.ipversion = parameters["ipversion"].String(); + address.prefix = parameters["prefix"].Number(); + address.gateway = parameters["gateway"].String(); + address.primarydns = parameters["primarydns"].String(); + address.secondarydns = parameters["secondarydns"].String(); } if (_networkManager) - rc = _networkManager->SetIPSettings(interface, ipversion, result); + rc = _networkManager->SetIPSettings(interface, address); else rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::GetStunEndpoint(const JsonObject& parameters, JsonObject& response) @@ -415,46 +356,39 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; string endPoint; uint32_t port; - uint32_t bindTimeout; - uint32_t cacheTimeout; + uint32_t timeout; + uint32_t cacheLifetime; if (_networkManager) - rc = _networkManager->GetStunEndpoint(endPoint, port, bindTimeout, cacheTimeout); + rc = _networkManager->GetStunEndpoint(endPoint, port, timeout, cacheLifetime); else rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) { - response["endPoint"] = endPoint; + response["endpoint"] = endPoint; response["port"] = port; - response["bindTimeout"] = bindTimeout; - response["cacheTimeout"] = cacheTimeout; - response["success"] = true; + response["timeout"] = timeout; + response["cacheLifetime"] = cacheLifetime; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::SetStunEndpoint(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string endPoint = parameters["endPoint"].String(); + string endPoint = parameters["endpoint"].String(); uint32_t port = parameters["port"].Number(); - uint32_t bindTimeout = parameters["bindTimeout"].Number(); - uint32_t cacheTimeout = parameters["cacheTimeout"].Number(); + uint32_t bindTimeout = parameters["timeout"].Number(); + uint32_t cacheTimeout = parameters["cacheLifetime"].Number(); if (_networkManager) rc = _networkManager->SetStunEndpoint(endPoint, port, bindTimeout, cacheTimeout); else rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::GetConnectivityTestEndpoints(const JsonObject& parameters, JsonObject& response) @@ -462,7 +396,6 @@ namespace WPEFramework LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::IStringIterator* endpoints = NULL; - if (_networkManager) rc = _networkManager->GetConnectivityTestEndpoints(endpoints); @@ -474,18 +407,14 @@ namespace WPEFramework if (endpoints) { JsonArray array; - string endPoint{}; - while (endpoints->Next(endPoint) == true) - { - array.Add(endPoint); - } + string entry{}; + while (endpoints->Next(entry) == true) { array.Add(entry); } + endpoints->Release(); response["endpoints"] = array; - response["success"] = true; } } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::SetConnectivityTestEndpoints(const JsonObject& parameters, JsonObject& response) @@ -498,7 +427,7 @@ namespace WPEFramework if (0 == array.Length() || 5 < array.Length()) { NMLOG_DEBUG("minimum of 1 to maximum of 5 Urls are allowed"); - return rc; + returnJson(rc); } std::vector endpoints; @@ -512,7 +441,7 @@ namespace WPEFramework else { NMLOG_DEBUG("Unexpected variant type"); - return rc; + returnJson(rc); } } endpointsIter = (Core::Service::Create(endpoints)); @@ -522,16 +451,10 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - if (endpointsIter) endpointsIter->Release(); - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::IsConnectedToInternet(const JsonObject& parameters, JsonObject& response) @@ -549,49 +472,29 @@ namespace WPEFramework if (Core::ERROR_NONE == rc) { - response["isConnectedToInternet"] = (Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED == result); - response["internetState"] = static_cast (result); - switch (result) - { - case Exchange::INetworkManager::InternetStatus::INTERNET_LIMITED: - response["status"] = string("LIMITED_INTERNET"); - break; - case Exchange::INetworkManager::InternetStatus::INTERNET_CAPTIVE_PORTAL: - response["status"] = string("CAPTIVE_PORTAL"); - break; - case Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED: - response["status"] = string("FULLY_CONNECTED"); - // when fully connected to internet set Network subsystem - //setInternetSubsystem(); - break; - default: - response["status"] = string("NO_INTERNET"); - break; - } - - response["success"] = true; + Core::JSON::EnumType status(result); + response["ipversion"] = ipversion; + response["connected"] = (Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED == result); + response["state"] = JsonValue(status); + response["status"] = status.Data(); } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::GetCaptivePortalURI(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string endPoint; + string uri; if (_networkManager) - rc = _networkManager->GetCaptivePortalURI(endPoint); + rc = _networkManager->GetCaptivePortalURI(uri); else rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) - { - response["uri"] = endPoint; - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + response["uri"] = uri; + + returnJson(rc); } uint32_t NetworkManager::StartConnectivityMonitoring(const JsonObject& parameters, JsonObject& response) @@ -606,12 +509,7 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::StopConnectivityMonitoring(const JsonObject& parameters, JsonObject& response) @@ -624,12 +522,7 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::GetPublicIP(const JsonObject& parameters, JsonObject& response) @@ -656,16 +549,14 @@ namespace WPEFramework if (Core::ERROR_NONE == rc) { - response["publicIP"] = ipAddress; + response["ipaddress"] = ipAddress; response["ipversion"] = ipversion; - response["success"] = true; m_publicIPAddress = ipAddress; m_publicIPAddressType = ipversion; PublishToThunderAboutInternet(); } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } void NetworkManager::PublishToThunderAboutInternet() @@ -699,11 +590,11 @@ namespace WPEFramework { LOG_INPARAM(); string result{}; + string endpoint{}; uint32_t rc = Core::ERROR_GENERAL; LOG_INPARAM(); if (parameters.HasLabel("endpoint")) { - string endpoint{}; string guid{}; string ipversion{"IPv4"}; uint32_t noOfRequest = 3; @@ -714,8 +605,8 @@ namespace WPEFramework if (parameters.HasLabel("ipversion")) ipversion = parameters["ipversion"].String(); - if (parameters.HasLabel("noOfRequest")) - noOfRequest = parameters["noOfRequest"].Number(); + if (parameters.HasLabel("count")) + noOfRequest = parameters["count"].Number(); if (parameters.HasLabel("timeout")) timeOutInSeconds = parameters["timeout"].Number(); @@ -735,8 +626,7 @@ namespace WPEFramework reply.FromString(result); response = reply; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::Trace(const JsonObject& parameters, JsonObject& response) @@ -744,44 +634,42 @@ namespace WPEFramework LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string result{}; - const string ipversion = parameters["ipversion"].String(); - const string endpoint = parameters["endpoint"].String(); - const uint32_t noOfRequest = parameters["packets"].Number(); - const string guid = parameters["guid"].String(); + + if (parameters.HasLabel("endpoint")) + { + const string ipversion = parameters["ipversion"].String(); + const string endpoint = parameters["endpoint"].String(); + const uint32_t noOfRequest = parameters["packets"].Number(); + const string guid = parameters["guid"].String(); - if (_networkManager) - rc = _networkManager->Trace(ipversion, endpoint, noOfRequest, guid, result); - else - rc = Core::ERROR_UNAVAILABLE; + if (_networkManager) + rc = _networkManager->Trace(ipversion, endpoint, noOfRequest, guid, result); + else + rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - JsonObject reply; - reply.FromString(result); - reply["success"] = true; - response = reply; + if (Core::ERROR_NONE == rc) + { + JsonObject reply; + reply.FromString(result); + response = reply; + } } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::StartWiFiScan(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - const Exchange::INetworkManager::WiFiFrequency frequency = static_cast (parameters["frequency"].Number()); + string frequency = parameters["frequency"].String(); + Exchange::INetworkManager::IStringIterator* ssids = NULL; if (_networkManager) - rc = _networkManager->StartWiFiScan(frequency); + rc = _networkManager->StartWiFiScan(frequency, ssids); else rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::StopWiFiScan(const JsonObject& parameters, JsonObject& response) @@ -794,12 +682,7 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::GetKnownSSIDs(const JsonObject& parameters, JsonObject& response) @@ -807,7 +690,6 @@ namespace WPEFramework LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - JsonArray ssids; ::WPEFramework::RPC::IIteratorType* _ssids{}; if (_networkManager) @@ -815,35 +697,30 @@ namespace WPEFramework if (Core::ERROR_NONE == rc) { - ASSERT(_ssids != nullptr); - if (_ssids != nullptr) { + JsonArray ssids; string _resultItem_{}; - while (_ssids->Next(_resultItem_) == true) - { - ssids.Add() = _resultItem_; - } + while (_ssids->Next(_resultItem_) == true) { ssids.Add() = _resultItem_; } _ssids->Release(); + + response["ssids"] = ssids; } - response["ssids"] = ssids; - response["success"] = true; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::AddToKnownSSIDs(const JsonObject& parameters, JsonObject& response) { - LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::WiFiConnectTo ssid{}; + NMLOG_INFO("Entry to %s\n", __FUNCTION__); if (parameters.HasLabel("ssid") && parameters.HasLabel("passphrase")) { - ssid.m_ssid = parameters["ssid"].String(); - ssid.m_passphrase = parameters["passphrase"].String(); - ssid.m_securityMode = static_cast (parameters["securityMode"].Number()); + ssid.ssid = parameters["ssid"].String(); + ssid.passphrase = parameters["passphrase"].String(); + ssid.security = static_cast (parameters["security"].Number()); if (_networkManager) rc = _networkManager->AddToKnownSSIDs(ssid); @@ -851,12 +728,7 @@ namespace WPEFramework rc = Core::ERROR_UNAVAILABLE; } - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::RemoveKnownSSID(const JsonObject& parameters, JsonObject& response) @@ -873,53 +745,53 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; } + else + rc = Core::ERROR_BAD_REQUEST; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::WiFiConnect(const JsonObject& parameters, JsonObject& response) { - LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::WiFiConnectTo ssid{}; + NMLOG_INFO("Entry to %s\n", __FUNCTION__); if (parameters.HasLabel("ssid")) - ssid.m_ssid = parameters["ssid"].String(); + ssid.ssid = parameters["ssid"].String(); + else + returnJson(rc); + if (parameters.HasLabel("passphrase")) - ssid.m_passphrase = parameters["passphrase"].String(); - if (parameters.HasLabel("securityMode")) - ssid.m_securityMode = static_cast (parameters["securityMode"].Number()); - //TODO Check Security modes - if (parameters.HasLabel("identity")) - ssid.m_identity = parameters["identity"].String(); - if (parameters.HasLabel("caCert")) - ssid.m_caCert = parameters["caCert"].String(); - if (parameters.HasLabel("clientCert")) - ssid.m_clientCert = parameters["clientCert"].String(); - if (parameters.HasLabel("privateKey")) - ssid.m_privateKey = parameters["privateKey"].String(); - if (parameters.HasLabel("privateKeyPasswd")) - ssid.m_privateKeyPasswd = parameters["privateKeyPasswd"].String(); - if (parameters.HasLabel("persistSSIDInfo")) - ssid.m_persistSSIDInfo = parameters["persistSSIDInfo"].Boolean(); + ssid.passphrase = parameters["passphrase"].String(); + + if (parameters.HasLabel("security")) + ssid.security= static_cast (parameters["security"].Number()); + + // Check Security modes + if (parameters.HasLabel("eap")) + ssid.eap = parameters["eap"].String(); + if (parameters.HasLabel("eap_identity")) + ssid.eap_identity = parameters["eap_identity"].String(); + if (parameters.HasLabel("ca_cert")) + ssid.ca_cert = parameters["ca_cert"].String(); + if (parameters.HasLabel("client_cert")) + ssid.client_cert = parameters["client_cert"].String(); + if (parameters.HasLabel("private_key")) + ssid.private_key = parameters["private_key"].String(); + if (parameters.HasLabel("private_key_passwd")) + ssid.private_key_passwd = parameters["private_key_passwd"].String(); + if (parameters.HasLabel("persist")) + ssid.persist = parameters["persist"].Boolean(); else - ssid.m_persistSSIDInfo = true; + ssid.persist = true; + if (_networkManager) rc = _networkManager->WiFiConnect(ssid); else rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::WiFiDisconnect(const JsonObject& parameters, JsonObject& response) @@ -932,12 +804,7 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::GetConnectedSSID(const JsonObject& parameters, JsonObject& response) @@ -953,17 +820,15 @@ namespace WPEFramework if (Core::ERROR_NONE == rc) { - response["ssid"] = ssidInfo.m_ssid; - response["bssid"] = ssidInfo.m_bssid; - response["securityMode"] = static_cast (ssidInfo.m_securityMode); - response["signalStrength"] = ssidInfo.m_signalStrength; - response["frequency"] = ssidInfo.m_frequency; - response["rate"] = ssidInfo.m_rate; - response["noise"] = ssidInfo.m_noise; - response["success"] = true; + response["ssid"] = ssidInfo.ssid; + response["bssid"] = ssidInfo.bssid; + response["security"] = JsonValue(ssidInfo.security); + response["strength"] = ssidInfo.strength; + response["frequency"] = ssidInfo.frequency; + response["rate"] = ssidInfo.rate; + response["noise"] = ssidInfo.noise; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::StartWPS(const JsonObject& parameters, JsonObject& response) @@ -971,18 +836,19 @@ namespace WPEFramework LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string wps_pin{}; - Exchange::INetworkManager::WiFiWPS method; + Core::JSON::EnumType method; if (parameters.HasLabel("method")) { - method = static_cast (parameters["method"].Number()); - } - else - method = Exchange::INetworkManager::WIFI_WPS_PBC; + if (parameters["method"].Content() == WPEFramework::Core::JSON::Variant::type::STRING) + method.FromString(parameters["method"].String()); + else if (parameters["method"].Content() == WPEFramework::Core::JSON::Variant::type::NUMBER) + method = static_cast (parameters["method"].Number()); - if ((Exchange::INetworkManager::WIFI_WPS_PIN == method) && parameters.HasLabel("wps_pin")) - { - wps_pin = parameters["wps_pin"].String(); + if ((Exchange::INetworkManager::WIFI_WPS_PIN == method) && parameters.HasLabel("pin")) + { + wps_pin = parameters["pin"].String(); + } } if (_networkManager) @@ -990,12 +856,7 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::StopWPS(const JsonObject& parameters, JsonObject& response) @@ -1008,12 +869,7 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; - if (Core::ERROR_NONE == rc) - { - response["success"] = true; - } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::GetWifiState(const JsonObject& parameters, JsonObject& response) @@ -1026,14 +882,15 @@ namespace WPEFramework rc = _networkManager->GetWifiState(state); else rc = Core::ERROR_UNAVAILABLE; + if (Core::ERROR_NONE == rc) { - response["state"] = static_cast (state); - m_wifiStateCache = state; - response["success"] = true; + Core::JSON::EnumType iState{state}; + response["state"] = JsonValue(state); + response["status"] = iState.Data(); } - LOG_OUTPARAM(); - return rc; + + returnJson(rc); } uint32_t NetworkManager::GetWiFiSignalStrength(const JsonObject& parameters, JsonObject& response) @@ -1042,7 +899,7 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; string ssid{}; string signalStrength{}; - Exchange::INetworkManager::WiFiSignalQuality quality; + Exchange::INetworkManager::WiFiSignalQuality quality{}; if (_networkManager) rc = _networkManager->GetWiFiSignalStrength(ssid, signalStrength, quality); @@ -1051,13 +908,12 @@ namespace WPEFramework if (Core::ERROR_NONE == rc) { + Core::JSON::EnumType iquality(quality); response["ssid"] = ssid; - response["signalStrength"] = signalStrength; - response["quality"] = static_cast (quality); - response["success"] = true; + response["strength"] = signalStrength; + response["quality"] = iquality.Data(); } - LOG_OUTPARAM(); - return rc; + returnJson(rc); } uint32_t NetworkManager::GetSupportedSecurityModes(const JsonObject& parameters, JsonObject& response) @@ -1079,14 +935,95 @@ namespace WPEFramework Exchange::INetworkManager::WIFISecurityModeInfo _resultItem_{}; while (securityModes->Next(_resultItem_) == true) { - response.Set(_resultItem_.m_securityModeText.c_str(), JsonValue(_resultItem_.m_securityMode)); + response.Set(_resultItem_.securityName.c_str(), JsonValue(_resultItem_.security)); } securityModes->Release(); } - response["success"] = true; } - LOG_OUTPARAM(); - return rc; + returnJson(rc); + } + + void NetworkManager::onInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface) + { + Core::JSON::EnumType iState{state}; + JsonObject parameters; + parameters["state"] = JsonValue(state); + parameters["status"] = iState.Data(); + parameters["interface"] = interface; + + LOG_INPARAM(); + Notify(_T("onInterfaceStateChange"), parameters); + } + + void NetworkManager::onActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface) + { + JsonObject parameters; + parameters["prevActiveInterface"] = prevActiveInterface; + parameters["currentActiveInterface"] = currentActiveinterface; + + LOG_INPARAM(); + Notify(_T("onActiveInterfaceChange"), parameters); + } + + void NetworkManager::onIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status) + { + Core::JSON::EnumType iStatus{status}; + JsonObject parameters; + parameters["interface"] = interface; + parameters["ipversion"] = ipversion; + parameters["ipaddress"] = ipaddress; + parameters["status"] = iStatus.Data(); + + LOG_INPARAM(); + Notify(_T("onIPAddressChange"), parameters); + } + + void NetworkManager::onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) + { + JsonObject parameters; + Core::JSON::EnumType prevStatus(prevState); + Core::JSON::EnumType currStatus(currState); + parameters["prevState"] = JsonValue(prevState); + parameters["prevStatus"] = prevStatus.Data(); + parameters["state"] = JsonValue(currState); + parameters["status"] = currStatus.Data(); + + LOG_INPARAM(); + Notify(_T("onInternetStatusChange"), parameters); + } + + void NetworkManager::onAvailableSSIDs(const string jsonOfScanResults) + { + JsonObject parameters; + JsonArray scanResults; + scanResults.FromString(jsonOfScanResults); + parameters["ssids"] = scanResults; + + LOG_INPARAM(); + Notify(_T("onAvailableSSIDs"), parameters); + } + + void NetworkManager::onWiFiStateChange(const Exchange::INetworkManager::WiFiState state) + { + JsonObject parameters; + Core::JSON::EnumType iState{state}; + parameters["state"] = JsonValue(state); + parameters["status"] = iState.Data(); + + LOG_INPARAM(); + Notify(_T("onWiFiStateChange"), parameters); + } + + void NetworkManager::onWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) + { + Core::JSON::EnumType iquality(quality); + JsonObject parameters; + parameters["ssid"] = ssid; + parameters["strength"] = strength; + parameters["quality"] = iquality.Data(); + + LOG_INPARAM(); + Notify(_T("onWiFiSignalStrengthChange"), parameters); } } } diff --git a/NetworkManagerLogger.cpp b/NetworkManagerLogger.cpp index faeab4bf3..313fdcbcc 100644 --- a/NetworkManagerLogger.cpp +++ b/NetworkManagerLogger.cpp @@ -63,6 +63,18 @@ namespace NetworkManagerLogger { } #endif + const char* trimPath(const char* s) + { + if (!s) + return s; + + const char* t = strrchr(s, (int) '/'); + if (t) t++; + if (!t) t = s; + + return t; + } + const char* methodName(const std::string& prettyFunction) { size_t colons = prettyFunction.find("::"); @@ -104,6 +116,7 @@ namespace NetworkManagerLogger { const char* levelMap[] = {"Fatal", "Error", "Warn", "Info", "Debug"}; struct timeval tv; struct tm* lt; + const char* fileName = trimPath(file); if (gDefaultLogLevel < level) return; @@ -111,7 +124,7 @@ namespace NetworkManagerLogger { gettimeofday(&tv, NULL); lt = localtime(&tv.tv_sec); - printf("%.2d:%.2d:%.2d.%.6lld [%-5s] [PID=%d] [TID=%d] %s : %s\n", lt->tm_hour, lt->tm_min, lt->tm_sec, (long long int)tv.tv_usec, levelMap[level], getpid(), gettid(), func, formattedLog); + printf("%.2d:%.2d:%.2d.%.6lld [%-5s] [PID=%d] [TID=%d] [%s +%d] %s : %s\n", lt->tm_hour, lt->tm_min, lt->tm_sec, (long long int)tv.tv_usec, levelMap[level], getpid(), gettid(), fileName, line, func, formattedLog); fflush(stdout); #endif } @@ -124,4 +137,14 @@ namespace NetworkManagerLogger { // TODO : Inform RDKLogger to change the log level #endif } + + void GetLevel(LogLevel& level) + { + level = gDefaultLogLevel; + NMLOG_INFO("NetworkManager logLevel:%d", level); +#ifdef USE_RDK_LOGGER + // TODO : Inform RDKLogger to change the log level +#endif + } + } // namespace NetworkManagerLogger diff --git a/NetworkManagerLogger.h b/NetworkManagerLogger.h index 65014d722..e7bc5e0b0 100644 --- a/NetworkManagerLogger.h +++ b/NetworkManagerLogger.h @@ -47,6 +47,11 @@ void Init(); */ void SetLevel(LogLevel level); +/** + * @brief To set log level while runtime + */ +void GetLevel(LogLevel& level); + /** * @brief Log a message * The function is defined by logging backend. @@ -61,6 +66,8 @@ void logPrint(LogLevel level, const char* file, const char* func, int line, cons #define NMLOG_ERROR(FMT, ...) logPrint(NetworkManagerLogger::ERROR_LEVEL, __FILE__, __func__, __LINE__, FMT, ##__VA_ARGS__) #define NMLOG_FATAL(FMT, ...) logPrint(NetworkManagerLogger::FATAL_LEVEL, __FILE__,__func__, __LINE__, FMT, ##__VA_ARGS__) +#define LOG_ENTRY_FUNCTION() { NMLOG_DEBUG("Entering"); } + } // namespace NetworkManagerLogger #endif // NM_LOGGER_H diff --git a/NetworkManagerPlugin.json b/NetworkManagerPlugin.json deleted file mode 100644 index 388367f4b..000000000 --- a/NetworkManagerPlugin.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/rdkcentral/rdkservices/main/Tools/json_generator/schemas/plugin.schema.json", - "info": { - "title": "NetworkManager Plugin", - "class": "NetworkManager", - "callsign": "org.rdk.NetworkManager", - "locator": "libWPEFrameworkNetworkManager.so", - "status": "production", - "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", - "version": "0.1.0" - }, - "interface": { - "$ref": "NetworkManager.json#" - } -} diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 67052cdc9..77588a874 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -353,7 +353,6 @@ typedef struct _IARM_Bus_WiFiSrvMgr_SsidList_Param_t { #define IARM_BUS_WIFI_MGR_API_disconnectSSID "disconnectSSID" /**< Disconnect from current SSID */ #define IARM_BUS_WIFI_MGR_API_getCurrentState "getCurrentState" /**< Retrieve current state */ - namespace WPEFramework { namespace Plugin @@ -435,9 +434,9 @@ namespace WPEFramework if(interface == "eth0" || interface == "wlan0") { if (e->status) - ::_instance->ReportInterfaceStateChangedEvent(Exchange::INetworkManager::INTERFACE_ADDED, interface); + ::_instance->ReportInterfaceStateChange(Exchange::INetworkManager::INTERFACE_ADDED, interface); else - ::_instance->ReportInterfaceStateChangedEvent(Exchange::INetworkManager::INTERFACE_REMOVED, interface); + ::_instance->ReportInterfaceStateChange(Exchange::INetworkManager::INTERFACE_REMOVED, interface); } break; } @@ -448,9 +447,9 @@ namespace WPEFramework NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS :: %s", interface.c_str()); if(interface == "eth0" || interface == "wlan0") { if (e->status) - ::_instance->ReportInterfaceStateChangedEvent(Exchange::INetworkManager::INTERFACE_LINK_UP, interface); + ::_instance->ReportInterfaceStateChange(Exchange::INetworkManager::INTERFACE_LINK_UP, interface); else - ::_instance->ReportInterfaceStateChangedEvent(Exchange::INetworkManager::INTERFACE_LINK_DOWN, interface); + ::_instance->ReportInterfaceStateChange(Exchange::INetworkManager::INTERFACE_LINK_DOWN, interface); } break; } @@ -461,7 +460,15 @@ namespace WPEFramework NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS :: %s -- %s", interface.c_str(), e->ip_address); if(interface == "eth0" || interface == "wlan0") { - ::_instance->ReportIPAddressChangedEvent(interface, e->acquired, e->is_ipv6, string(e->ip_address)); + string ipversion("IPv4"); + Exchange::INetworkManager::IPStatus status; + + if (e->is_ipv6) + ipversion = "IPv6"; + if (e->acquired) + status = Exchange::INetworkManager::IP_ACQUIRED; + + ::_instance->ReportIPAddressChange(interface, ipversion, string(e->ip_address), status); } break; } @@ -478,7 +485,7 @@ namespace WPEFramework if(newInterface != "eth0" || newInterface != "wlan0") newInterface == ""; /* assigning "null" if the interface is not eth0 or wlan0 */ - ::_instance->ReportActiveInterfaceChangedEvent(oldInterface, newInterface); + ::_instance->ReportActiveInterfaceChange(oldInterface, newInterface); break; } case IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs: @@ -501,7 +508,8 @@ namespace WPEFramework string json; ssids.ToString(json); - ::_instance->ReportAvailableSSIDsEvent(json); + ::_instance->ReportAvailableSSIDs(json); + break; } case IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged: { @@ -509,7 +517,7 @@ namespace WPEFramework Exchange::INetworkManager::WiFiState state = Exchange::INetworkManager::WIFI_STATE_DISCONNECTED; NMLOG_INFO("Event IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged received; state=%d", e->data.wifiStateChange.state); state = to_wifi_state(e->data.wifiStateChange.state); - ::_instance->ReportWiFiStateChangedEvent(state); + ::_instance->ReportWiFiStateChange(state); break; } case IARM_BUS_WIFI_MGR_EVENT_onError: @@ -517,7 +525,7 @@ namespace WPEFramework IARM_BUS_WiFiSrvMgr_EventData_t* e = (IARM_BUS_WiFiSrvMgr_EventData_t *) data; Exchange::INetworkManager::WiFiState state = errorcode_to_wifi_state(e->data.wifiError.code); NMLOG_INFO("Event IARM_BUS_WIFI_MGR_EVENT_onError received; code=%d", e->data.wifiError.code); - ::_instance->ReportWiFiStateChangedEvent(state); + ::_instance->ReportWiFiStateChange(state); break; } default: @@ -636,14 +644,14 @@ namespace WPEFramework InterfaceDetails tmp; /* Update the interface as per RDK NetSrvMgr */ if ("eth0" == interfaceName) - tmp.m_type = string("ETHERNET"); + tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_ETHERNET; else if ("wlan0" == interfaceName) - tmp.m_type = string("WIFI"); + tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_WIFI; - tmp.m_name = interfaceName; - tmp.m_mac = string(list.interfaces[i].mac); - tmp.m_isEnabled = ((list.interfaces[i].flags & IFF_UP) != 0); - tmp.m_isConnected = ((list.interfaces[i].flags & IFF_RUNNING) != 0); + tmp.name = interfaceName; + tmp.mac = string(list.interfaces[i].mac); + tmp.enabled = ((list.interfaces[i].flags & IFF_UP) != 0); + tmp.connected = ((list.interfaces[i].flags & IFF_RUNNING) != 0); interfaceList.push_back(tmp); } } @@ -711,7 +719,7 @@ namespace WPEFramework return rc; } - uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool& enable /* @in */) + uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enable /* @in */) { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; @@ -804,7 +812,7 @@ namespace WPEFramework /* @brief Get IP Address Of the Interface */ - uint32_t NetworkManagerImplementation::GetIPSettings(const string& interface /* @in */, const string& ipversion /* @in */, IPAddressInfo& result /* @out */) + uint32_t NetworkManagerImplementation::GetIPSettings(string& interface /* @inout */, const string &ipversion /* @in */, IPAddress& address /* @out */) { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; @@ -815,24 +823,39 @@ namespace WPEFramework strncpy(iarmData.interface, "WIFI", INTERFACE_SIZE); else if ("eth0" == interface) strncpy(iarmData.interface, "ETHERNET", INTERFACE_SIZE); + else if (!interface.empty()) + { + NMLOG_ERROR("Given interface (%s) is NOT supported\n", interface.c_str()); + return Core::ERROR_NOT_SUPPORTED; + } + + if (("IPv4" == ipversion) || ("IPv6" == ipversion)) + sprintf(iarmData.ipversion,"%s", ipversion.c_str()); - strncpy(iarmData.ipversion, ipversion.c_str(), 16); iarmData.isSupported = true; if (IARM_RESULT_SUCCESS == IARM_Bus_Call (IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_getIPSettings, (void *)&iarmData, sizeof(iarmData))) { - result.m_ipAddrType = string(iarmData.ipversion); - result.m_autoConfig = iarmData.autoconfig; - result.m_dhcpServer = string(iarmData.dhcpserver,MAX_IP_ADDRESS_LEN - 1); - result.m_v6LinkLocal = ""; - result.m_ipAddress = string(iarmData.ipaddress,MAX_IP_ADDRESS_LEN - 1); + address.autoconfig = iarmData.autoconfig; + address.dhcpserver = string(iarmData.dhcpserver,MAX_IP_ADDRESS_LEN - 1); + address.ula = string(""); + address.ipaddress = string(iarmData.ipaddress,MAX_IP_ADDRESS_LEN - 1); + address.gateway = string(iarmData.gateway,MAX_IP_ADDRESS_LEN - 1); + address.primarydns = string(iarmData.primarydns,MAX_IP_ADDRESS_LEN - 1); + address.secondarydns = string(iarmData.secondarydns,MAX_IP_ADDRESS_LEN - 1); if (0 == strcasecmp("ipv4", iarmData.ipversion)) - result.m_prefix = NetmaskToPrefix(iarmData.netmask); + { + address.ipversion = string ("IPv4"); + address.prefix = NetmaskToPrefix(iarmData.netmask); + } else if (0 == strcasecmp("ipv6", iarmData.ipversion)) - result.m_prefix = std::atoi(iarmData.netmask); - result.m_gateway = string(iarmData.gateway,MAX_IP_ADDRESS_LEN - 1); - result.m_primaryDns = string(iarmData.primarydns,MAX_IP_ADDRESS_LEN - 1); - result.m_secondaryDns = string(iarmData.secondarydns,MAX_IP_ADDRESS_LEN - 1); + { + address.ipversion = string ("IPv6"); + address.prefix = std::atoi(iarmData.netmask); + } + + /* Return the default interface information */ + interface = string(interface); rc = Core::ERROR_NONE; } else @@ -843,8 +866,8 @@ namespace WPEFramework return rc; } -#define CIDR_NETMASK_IP_LEN 32 -const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { +const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { + "0.0.0.0", "128.0.0.0", "192.0.0.0", "224.0.0.0", @@ -880,10 +903,10 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { }; /* @brief Set IP Address Of the Interface */ - uint32_t NetworkManagerImplementation::SetIPSettings(const string& interface /* @in */, const string &ipversion /* @in */, const IPAddressInfo& address /* @in */) + uint32_t NetworkManagerImplementation::SetIPSettings(const string& interface /* @in */, const IPAddress& address /* @in */) { uint32_t rc = Core::ERROR_NONE; - if (0 == strcasecmp("ipv4", ipversion.c_str())) + if ("IPv4" == address.ipversion) { IARM_BUS_NetSrvMgr_Iface_Settings_t iarmData = {0}; /* Netsrvmgr returns eth0 & wlan0 as primary interface but when we want to set., we must set ETHERNET or WIFI*/ @@ -897,27 +920,28 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { rc = Core::ERROR_BAD_REQUEST; return rc; } + /* IP version */ - strncpy(iarmData.ipversion, ipversion.c_str(), 16); + sprintf(iarmData.ipversion, "IPv4"); - if (!address.m_autoConfig) + if (!address.autoconfig) { //Lets validate the prefix Address - if (address.m_prefix >= 32) + if (address.prefix > CIDR_NETMASK_IP_LEN) { rc = Core::ERROR_BAD_REQUEST; } else { - string netmask = CIDR_PREFIXES[address.m_prefix]; + string netmask = CIDR_PREFIXES[address.prefix]; //Lets validate the IP Address struct in_addr tmpIPAddress, tmpGWAddress, tmpNetmask; struct in_addr bcastAddr1, bcastAddr2; - if (inet_pton(AF_INET, address.m_ipAddress.c_str(), &tmpIPAddress) == 1 && + if (inet_pton(AF_INET, address.ipaddress.c_str(), &tmpIPAddress) == 1 && inet_pton(AF_INET, netmask.c_str(), &tmpNetmask) == 1 && - inet_pton(AF_INET, address.m_gateway.c_str(), &tmpGWAddress) == 1) + inet_pton(AF_INET, address.gateway.c_str(), &tmpGWAddress) == 1) { bcastAddr1.s_addr = tmpIPAddress.s_addr | ~tmpNetmask.s_addr; bcastAddr2.s_addr = tmpGWAddress.s_addr | ~tmpNetmask.s_addr; @@ -951,17 +975,17 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { if (Core::ERROR_NONE == rc) { - strncpy(iarmData.ipaddress, address.m_ipAddress.c_str(), 16); + strncpy(iarmData.ipaddress, address.ipaddress.c_str(), 16); strncpy(iarmData.netmask, netmask.c_str(), 16); - strncpy(iarmData.gateway, address.m_gateway.c_str(), 16); - strncpy(iarmData.primarydns, address.m_primaryDns.c_str(), 16); - strncpy(iarmData.secondarydns, address.m_secondaryDns.c_str(), 16); + strncpy(iarmData.gateway, address.gateway.c_str(), 16); + strncpy(iarmData.primarydns, address.primarydns.c_str(), 16); + strncpy(iarmData.secondarydns, address.secondarydns.c_str(), 16); } } } else { - iarmData.autoconfig = address.m_autoConfig; + iarmData.autoconfig = address.autoconfig; } if (Core::ERROR_NONE == rc) { @@ -986,16 +1010,18 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { return rc; } - uint32_t NetworkManagerImplementation::StartWiFiScan(const WiFiFrequency frequency /* @in */) + uint32_t NetworkManagerImplementation::StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; IARM_Bus_WiFiSrvMgr_SsidList_Param_t param; IARM_Result_t retVal = IARM_RESULT_SUCCESS; - memset(¶m, 0, sizeof(param)); + (void)ssids; (void) frequency; + memset(¶m, 0, sizeof(param)); + retVal = IARM_Bus_Call(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_API_getAvailableSSIDsAsync, (void *)¶m, sizeof(IARM_Bus_WiFiSrvMgr_SsidList_Param_t)); if(retVal == IARM_RESULT_SUCCESS) { @@ -1064,9 +1090,9 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { IARM_Bus_WiFiSrvMgr_Param_t param; memset(¶m, 0, sizeof(param)); - strncpy(param.data.connect.ssid, ssid.m_ssid.c_str(), SSID_SIZE - 1); - strncpy(param.data.connect.passphrase, ssid.m_passphrase.c_str(), PASSPHRASE_BUFF - 1); - param.data.connect.security_mode = (SsidSecurity) ssid.m_securityMode; + strncpy(param.data.connect.ssid, ssid.ssid.c_str(), SSID_SIZE - 1); + strncpy(param.data.connect.passphrase, ssid.passphrase.c_str(), PASSPHRASE_BUFF - 1); + param.data.connect.security_mode = (SsidSecurity) ssid.security; IARM_Result_t retVal = IARM_Bus_Call(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_API_saveSSID, (void *)¶m, sizeof(param)); if((retVal == IARM_RESULT_SUCCESS) && param.status) @@ -1114,20 +1140,20 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { IARM_Bus_WiFiSrvMgr_Param_t param; memset(¶m, 0, sizeof(param)); - if(ssid.m_ssid.length() || ssid.m_passphrase.length()) + if(ssid.ssid.length() || ssid.passphrase.length()) { - ssid.m_ssid.copy(param.data.connect.ssid, sizeof(param.data.connect.ssid) - 1); - ssid.m_passphrase.copy(param.data.connect.passphrase, sizeof(param.data.connect.passphrase) - 1); - param.data.connect.security_mode = (SsidSecurity)ssid.m_securityMode; - if(!ssid.m_identity.empty()) - ssid.m_identity.copy(param.data.connect.eapIdentity, sizeof(param.data.connect.eapIdentity) - 1); - if(!ssid.m_caCert.empty()) - ssid.m_caCert.copy(param.data.connect.carootcert, sizeof(param.data.connect.carootcert) - 1); - if(!ssid.m_clientCert.empty()) - ssid.m_clientCert.copy(param.data.connect.clientcert, sizeof(param.data.connect.clientcert) - 1); - if(!ssid.m_privateKey.empty()) - ssid.m_privateKey.copy(param.data.connect.privatekey, sizeof(param.data.connect.privatekey) - 1); - param.data.connect.persistSSIDInfo = ssid.m_persistSSIDInfo; + ssid.ssid.copy(param.data.connect.ssid, sizeof(param.data.connect.ssid) - 1); + ssid.passphrase.copy(param.data.connect.passphrase, sizeof(param.data.connect.passphrase) - 1); + param.data.connect.security_mode = (SsidSecurity)ssid.security; + if(!ssid.eap_identity.empty()) + ssid.eap_identity.copy(param.data.connect.eapIdentity, sizeof(param.data.connect.eapIdentity) - 1); + if(!ssid.ca_cert.empty()) + ssid.ca_cert.copy(param.data.connect.carootcert, sizeof(param.data.connect.carootcert) - 1); + if(!ssid.client_cert.empty()) + ssid.client_cert.copy(param.data.connect.clientcert, sizeof(param.data.connect.clientcert) - 1); + if(!ssid.private_key.empty()) + ssid.private_key.copy(param.data.connect.privatekey, sizeof(param.data.connect.privatekey) - 1); + param.data.connect.persistSSIDInfo = ssid.persist; } retVal = IARM_Bus_Call( IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_API_connect, (void *)¶m, sizeof(param)); @@ -1181,13 +1207,13 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { { auto &connectedSsid = param.data.getConnectedSSID; - ssidInfo.m_ssid = string(connectedSsid.ssid); - ssidInfo.m_bssid = string(connectedSsid.bssid); - ssidInfo.m_securityMode = (WIFISecurityMode) connectedSsid.securityMode; - ssidInfo.m_signalStrength = to_string(connectedSsid.signalStrength); - ssidInfo.m_frequency = static_cast(connectedSsid.frequency)/1000.0; - ssidInfo.m_rate = to_string(connectedSsid.rate); - ssidInfo.m_noise = to_string(connectedSsid.noise); + ssidInfo.ssid = string(connectedSsid.ssid); + ssidInfo.bssid = string(connectedSsid.bssid); + ssidInfo.security = (WIFISecurityMode) connectedSsid.securityMode; + ssidInfo.strength = to_string(connectedSsid.signalStrength); + ssidInfo.rate = to_string(connectedSsid.rate); + ssidInfo.noise = to_string(connectedSsid.noise); + ssidInfo.frequency = to_string((double)connectedSsid.frequency/1000); NMLOG_INFO ("GetConnectedSSID Success"); rc = Core::ERROR_NONE; @@ -1208,13 +1234,13 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN] = { if (Core::ERROR_NONE == GetConnectedSSID(ssidInfo)) { - ssid = ssidInfo.m_ssid; - signalStrength = ssidInfo.m_signalStrength; + ssid = ssidInfo.ssid; + signalStrength = ssidInfo.strength; if (!signalStrength.empty()) { signalStrengthOut = std::stof(signalStrength.c_str()); - NMLOG_INFO ("WiFiSignalStrength in dB = %s",signalStrengthOut); + NMLOG_INFO ("WiFiSignalStrength in dB = %f",signalStrengthOut); } if (signalStrengthOut == 0) diff --git a/WiFiSignalStrengthMonitor.cpp b/WiFiSignalStrengthMonitor.cpp index 60165f93f..839de661b 100644 --- a/WiFiSignalStrengthMonitor.cpp +++ b/WiFiSignalStrengthMonitor.cpp @@ -120,7 +120,7 @@ namespace WPEFramework { NMLOG_INFO("Notifying WiFiSignalStrengthChangedEvent %s", signalStrength.c_str()); oldSignalQuality = newSignalQuality; - _instance->ReportWiFiSignalStrengthChangedEvent(ssid, signalStrength, newSignalQuality); + _instance->ReportWiFiSignalStrengthChange(ssid, signalStrength, newSignalQuality); } if(newSignalQuality == Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED) diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 41f186668..53529aeb0 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,71 +2,90 @@ # NetworkManager Plugin -**Version: [0.4.0]()** +**Version: 0.5.0** -A NetworkManager plugin for Thunder framework. +**Status: :white_circle::white_circle::white_circle:** + +org.rdk.NetworkManager interface for Thunder framework. + +(Defined by [NetworkManager.json](https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json)) ### Table of Contents -- [Abbreviation, Acronyms and Terms](#head.Abbreviation,_Acronyms_and_Terms) +- [Introduction](#head.Introduction) - [Description](#head.Description) -- [Configuration](#head.Configuration) -- [Interfaces](#head.Interfaces) - [Methods](#head.Methods) - [Notifications](#head.Notifications) - -# Abbreviation, Acronyms and Terms + +# Introduction -[[Refer to this link](userguide/aat.md)] + +## Scope - -# Description +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.5.0). It includes detailed specification about its methods provided and notifications sent. -A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device. + +## Case Sensitivity - The plugin is designed to be an out-of-process service to be handled by Thunder framework. For more information about the framework refer to [[Thunder](#ref.Thunder)]. +All identifiers of the interfaces described in this document are case-sensitive. Thus, unless stated otherwise, all keywords, entities, properties, relations and actions should be treated as such. - -# Configuration + +## Acronyms, Abbreviations and Terms -The table below lists configuration options of the plugin. +The table below provides and overview of acronyms used in this document and their definitions. -| Name | Type | Description | -| :-------- | :-------- | :-------- | -| callsign | string | Plugin instance name (default: *org.rdk.NetworkManager*) | -| classname | string | Class name: *NetworkManager* | -| locator | string | Library name: *libWPEFrameworkNetworkManager.so* | -| autostart | boolean | Determines if the plugin shall be started automatically along with the framework | +| Acronym | Description | +| :-------- | :-------- | +| API | Application Programming Interface | +| HTTP | Hypertext Transfer Protocol | +| JSON | JavaScript Object Notation; a data interchange format | +| JSON-RPC | A remote procedure call protocol encoded in JSON | - -# Interfaces +The table below provides and overview of terms and abbreviations used in this document and their definitions. -This plugin implements the following interfaces: +| Term | Description | +| :-------- | :-------- | +| callsign | The name given to an instance of a plugin. One plugin can be instantiated multiple times, but each instance the instance name, callsign, must be unique. | + + +## References + +| Ref ID | Description | +| :-------- | :-------- | +| [HTTP](http://www.w3.org/Protocols) | HTTP specification | +| [JSON-RPC](https://www.jsonrpc.org/specification) | JSON-RPC 2.0 specification | +| [JSON](http://www.json.org/) | JSON specification | +| [Thunder](https://github.com/WebPlatformForEmbedded/Thunder/blob/master/doc/WPE%20-%20API%20-%20WPEFramework.docx) | Thunder API Reference | -- [NetworkManager.json](https://github.com/rdkcentral/ThunderInterfaces/blob/master/interfaces/NetworkManager.json) + +# Description + +A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device. # Methods -The following methods are provided by the org.rdk.NetworkManager plugin: +The following methods are provided by the org.rdk.NetworkManager interface: NetworkManager interface methods: | Method | Description | | :-------- | :-------- | +| [SetLogLevel](#method.SetLogLevel) | Set Log level for more information | +| [GetLogLevel](#method.GetLogLevel) | Get Log level that is currently used | | [GetAvailableInterfaces](#method.GetAvailableInterfaces) | Get device supported list of available interface including their state | | [GetPrimaryInterface](#method.GetPrimaryInterface) | Gets the primary/default network interface for the device | | [SetPrimaryInterface](#method.SetPrimaryInterface) | Sets the primary/default interface for the device | -| [SetInterfaceState](#method.SetInterfaceState) | Enable the interface | -| [GetInterfaceState](#method.GetInterfaceState) | Disable the interface | +| [SetInterfaceState](#method.SetInterfaceState) | Enable or disable the specified interface | +| [GetInterfaceState](#method.GetInterfaceState) | Gets the current Status of the specified interface | | [GetIPSettings](#method.GetIPSettings) | Gets the IP setting for the given interface | | [SetIPSettings](#method.SetIPSettings) | Sets the IP settings for the given interface | -| [GetStunEndpoint](#method.GetStunEndpoint) | Get the STUN Endpoint that is used to identify public IP of the device | -| [SetStunEndpoint](#method.SetStunEndpoint) | Set the STUN Endpoint to be used to identify public IP of the device | +| [GetStunEndpoint](#method.GetStunEndpoint) | Get the STUN endpoint that is used to identify public IP of the device | +| [SetStunEndpoint](#method.SetStunEndpoint) | Set the STUN endpoint to be used to identify public IP of the device | | [GetConnectivityTestEndpoints](#method.GetConnectivityTestEndpoints) | Gets currently used test endpoints | | [SetConnectivityTestEndpoints](#method.SetConnectivityTestEndpoints) | This method used to set up to 5 endpoints for a connectivity test | -| [IsConnectedToInternet](#method.IsConnectedToInternet) | Seeks Whether the device has internet connectivity | +| [IsConnectedToInternet](#method.IsConnectedToInternet) | Seeks whether the device has internet connectivity | | [GetCaptivePortalURI](#method.GetCaptivePortalURI) | Gets the captive portal URI if connected to any captive portal network | | [StartConnectivityMonitoring](#method.StartConnectivityMonitoring) | Enable a continuous monitoring of internet connectivity with heart beat interval thats given | | [StopConnectivityMonitoring](#method.StopConnectivityMonitoring) | Stops the connectivity monitoring | @@ -84,21 +103,108 @@ NetworkManager interface methods: | [StartWPS](#method.StartWPS) | Initiates a connection using Wifi Protected Setup (WPS) | | [StopWPS](#method.StopWPS) | Cancels the in-progress WPS pairing operation | | [GetWiFiSignalStrength](#method.GetWiFiSignalStrength) | Get WiFiSignalStrength of connected SSID | -| [GetSupportedSecurityModes](#method.GetSupportedSecurityModes) | Returns the Wifi security modes that the device supports | -| [SetLogLevel](#method.SetLogLevel) | Set Log level for more information | -| [GetLogLevel](#method.GetLogLevel) | Gets the Log level thats used | +| [GetSupportedsecurityModes](#method.GetSupportedsecurityModes) | Returns the Wifi security modes that the device supports | | [GetWifiState](#method.GetWifiState) | Returns the current Wifi State | + +## *SetLogLevel [method](#head.Methods)* + +Set Log level for more information. The possible set log level are as follows. +* `0`: FATAL +* `1`: ERROR +* `2`: WARNING +* `3`: INFO +* `4`: DEBUG +. + +### Parameters + +| Name | Type | Description | +| :-------- | :-------- | :-------- | +| params | object | | +| params.level | integer | Set Log level to get more information | + +### Result + +| Name | Type | Description | +| :-------- | :-------- | :-------- | +| result | object | | +| result.success | boolean | Whether the request succeeded | + +### Example + +#### Request + +```json +{ + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.SetLogLevel", + "params": { + "level": 1 + } +} +``` + +#### Response + +```json +{ + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } +} +``` + + +## *GetLogLevel [method](#head.Methods)* + +Get Log level that is currently used. + +### Parameters + +This method takes no parameters. + +### Result + +| Name | Type | Description | +| :-------- | :-------- | :-------- | +| result | object | | +| result.level | integer | Get Log level to get more information | +| result.success | boolean | Whether the request succeeded | + +### Example + +#### Request + +```json +{ + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetLogLevel" +} +``` + +#### Response + +```json +{ + "jsonrpc": "2.0", + "id": 42, + "result": { + "level": 1, + "success": true + } +} +``` ## *GetAvailableInterfaces [method](#head.Methods)* Get device supported list of available interface including their state. -### Events - -No Events - ### Parameters This method takes no parameters. @@ -123,9 +229,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetAvailableInterfaces" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetAvailableInterfaces" } ``` @@ -133,31 +239,27 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "interfaces": [ - { - "type": "ETHERNET", - "name": "eth0", - "mac": "AA:AA:AA:AA:AA:AA", - "enabled": true, - "connected": true - } - ], - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "Interfaces": [ + { + "type": "ETHERNET", + "name": "eth0", + "mac": "AA:AA:AA:AA:AA:AA", + "enabled": true, + "connected": true + } + ], + "success": true + } } ``` ## *GetPrimaryInterface [method](#head.Methods)* -Gets the primary/default network interface for the device. The active network interface is defined as the one that can make requests to the external network. Returns one of the supported interfaces as per `GetAvailableInterfaces`, or an empty value which indicates that there is no default network interface. - -### Events - -No Events +Gets the primary/default network interface for the device. The active network interface is defined as the one that can make requests to the external network. Returns one of the supported interfaces as per `GetAvailableInterfaces`. ### Parameters @@ -176,9 +278,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetPrimaryInterface" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetPrimaryInterface" } ``` @@ -186,11 +288,11 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "interface": "wlan0" - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "interface": "wlan0" + } } ``` @@ -199,14 +301,8 @@ This method takes no parameters. Sets the primary/default interface for the device. This call fails if the interface is not enabled. -### Events +Also see: [onActiveInterfaceChange](#event.onActiveInterfaceChange), [onInterfaceStateChange](#event.onInterfaceStateChange), [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) -| Event | Description | -| :-------- | :-------- | -| [onActiveInterfaceChange](#event.onActiveInterfaceChange) | Triggered when device’s default interface changed. | -| [onInterfaceStateChange](#event.onInterfaceStateChange) | Triggered when interface’s state changed | -| [onAddressChange](#event.onAddressChange) | Triggered when the device connects to router. | -| [onInternetStatusChange](#event.onInternetStatusChange) | Triggered when each IP address is lost or acquired. | ### Parameters | Name | Type | Description | @@ -227,12 +323,12 @@ Sets the primary/default interface for the device. This call fails if the interf ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.SetPrimaryInterface", - "params": { - "interface": "wlan0" - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.SetPrimaryInterface", + "params": { + "interface": "wlan0" + } } ``` @@ -240,32 +336,28 @@ Sets the primary/default interface for the device. This call fails if the interf ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` ## *SetInterfaceState [method](#head.Methods)* -Enable or Disable the specified interface. - -### Events +Enable or disable the specified interface. -| Event | Description | -| :-------- | :-------- | -| [onInterfaceStateChange](#event.onInterfaceStateChange) | Triggered when interface’s status changes to enabled or disabled. | +Also see: [onInterfaceStateChange](#event.onInterfaceStateChange) ### Parameters | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface in `GetAvailableInterfaces` | -| params.enabled | boolean | Set the state of the interface to be Enabled or Disabled | +| params.interface | string | Enable the specified interface | +| params.enabled | boolean | Whether the interface must be enabled or disabled | ### Result @@ -280,13 +372,13 @@ Enable or Disable the specified interface. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.SetInterfaceState", - "params": { - "interface": "wlan0", - "enabled": true - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.SetInterfaceState", + "params": { + "interface": "wlan0", + "enabled": true + } } ``` @@ -294,36 +386,32 @@ Enable or Disable the specified interface. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` ## *GetInterfaceState [method](#head.Methods)* -Disable the specified interface. - -### Events - -No Events +Gets the current Status of the specified interface. ### Parameters | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface in `GetAvailableInterfaces` | +| params.interface | string | Disable the specified interface | ### Result | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.enabled | boolean | Whether the Interface is enabled or disabled | +| result.enabled | boolean | Whether the interface is enabled or disabled | | result.success | boolean | Whether the request succeeded | ### Example @@ -332,12 +420,12 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetInterfaceState", - "params": { - "interface": "wlan0" - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetInterfaceState", + "params": { + "interface": "wlan0" + } } ``` @@ -345,12 +433,12 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "enabled": true, - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "enabled": true, + "success": true + } } ``` @@ -359,17 +447,13 @@ No Events Gets the IP setting for the given interface. -### Events - -No Events - ### Parameters | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.interface | string | *(optional)* An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface. If this is empty, default interface will be returned | -| params?.ipversion | string | *(optional)* either IPv4 or IPv6 | +| params?.interface | string | *(optional)* An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | +| params?.ipversion | string | *(optional)* Either IPv4 or IPv6 | ### Result @@ -377,13 +461,13 @@ No Events | :-------- | :-------- | :-------- | | result | object | | | result.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | -| result.ipversion | string | either IPv4 or IPv6 | +| result.ipversion | string | Either IPv4 or IPv6 | | result.autoconfig | boolean | `true` if DHCP is used, `false` if IP is configured manually | | result?.dhcpserver | string | *(optional)* The DHCP Server address | | result.ipaddress | string | The IP address | | result.prefix | integer | The prefix number | | result.gateway | string | The gateway address | -| result.ula | string | The IPv6 Unified Local Address; Empty when IPv4 is requested | +| result.ula | string | The IPv6 Unified Local Address | | result.primarydns | string | The primary DNS address | | result.secondarydns | string | The secondary DNS address | | result.success | boolean | Whether the request succeeded | @@ -394,13 +478,13 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetIPSettings", - "params": { - "interface": "wlan0", - "ipversion": "IPv4" - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetIPSettings", + "params": { + "interface": "wlan0", + "ipversion": "IPv4" + } } ``` @@ -408,21 +492,21 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "interface": "wlan0", - "ipversion": "IPv4", - "autoconfig": true, - "dhcpserver": "192.168.1.1", - "ipaddress": "192.168.1.101", - "prefix": 24, - "gateway": "192.168.1.1", - "ula": "...", - "primarydns": "192.168.1.1", - "secondarydns": "192.168.1.2", - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "interface": "wlan0", + "ipversion": "IPv4", + "autoconfig": true, + "dhcpserver": "192.168.1.1", + "ipaddress": "192.168.1.101", + "prefix": 24, + "gateway": "192.168.1.1", + "ula": "d00:410:2016::", + "primarydns": "192.168.1.1", + "secondarydns": "192.168.1.2", + "success": true + } } ``` @@ -431,19 +515,15 @@ No Events Sets the IP settings for the given interface. -### Events +Also see: [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) -| Event | Description | -| :-------- | :-------- | -| [onAddressChange](#event.onAddressChange) | Triggered when the device connects to router. | -| [onInternetStatusChange](#event.onInternetStatusChange) | Triggered when each IP address is lost or acquired. | ### Parameters | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | | params.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | -| params.ipversion | string | either IPv4 or IPv6 | +| params.ipversion | string | Either IPv4 or IPv6 | | params.autoconfig | boolean | `true` if DHCP is used, `false` if IP is configured manually | | params.ipaddress | string | The IP address | | params.prefix | integer | The prefix number | @@ -464,19 +544,19 @@ Sets the IP settings for the given interface. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.SetIPSettings", - "params": { - "interface": "wlan0", - "ipversion": "IPv4", - "autoconfig": true, - "ipaddress": "192.168.1.101", - "prefix": 24, - "gateway": "192.168.1.1", - "primarydns": "192.168.1.1", - "secondarydns": "192.168.1.2" - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.SetIPSettings", + "params": { + "interface": "wlan0", + "ipversion": "IPv4", + "autoconfig": true, + "ipaddress": "192.168.1.101", + "prefix": 24, + "gateway": "192.168.1.1", + "primarydns": "192.168.1.1", + "secondarydns": "192.168.1.2" + } } ``` @@ -484,22 +564,18 @@ Sets the IP settings for the given interface. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` ## *GetStunEndpoint [method](#head.Methods)* -Get the STUN Endpoint that is used to identify public IP of the device. - -### Events - -No Events +Get the STUN endpoint that is used to identify public IP of the device. ### Parameters @@ -510,10 +586,10 @@ This method takes no parameters. | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.endpoint | string | STUN server endpoint | +| result.endpoint | string | The host name or IP address | | result.port | integer | STUN server port | -| result.timeout | integer | STUN server bind timeout | -| result.cacheLifetime | integer | STUN server cache Lifetime | +| result.timeout | integer | Timeout | +| result.cacheLifetime | integer | STUN server cache timeout | | result.success | boolean | Whether the request succeeded | ### Example @@ -522,9 +598,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetStunEndpoint" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetStunEndpoint" } ``` @@ -532,36 +608,32 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "endpoint": "stun.l.google.com", - "port": 3478, - "timeout": 30, - "cacheLifetime": 0, - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "endpoint": "45.57.221.20", + "port": 3478, + "timeout": 30, + "cacheLifetime": 0, + "success": true + } } ``` ## *SetStunEndpoint [method](#head.Methods)* -Set the STUN Endpoint to be used to identify public IP of the device. - -### Events - -No Events +Set the STUN endpoint to be used to identify public IP of the device. ### Parameters | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.endpoint | string | STUN server endpoint | +| params.endpoint | string | The host name or IP address | | params.port | integer | STUN server port | -| params?.timeout | integer | *(optional)* STUN server bind timeout | -| params?.cacheLifetime | integer | *(optional)* STUN server cache lifetime | +| params?.timeout | integer | *(optional)* Timeout | +| params?.cacheLifetime | integer | *(optional)* STUN server cache timeout | ### Result @@ -576,15 +648,15 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.SetStunEndpoint", - "params": { - "endpoint": "stun.l.google.com", - "port": 3478, - "timeout": 30, - "cacheLifetime": 0 - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.SetStunEndpoint", + "params": { + "endpoint": "45.57.221.20", + "port": 3478, + "timeout": 30, + "cacheLifetime": 0 + } } ``` @@ -592,11 +664,11 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` @@ -605,10 +677,6 @@ No Events Gets currently used test endpoints. on success list out the connectivity test points connections. -### Events - -No Events - ### Parameters This method takes no parameters. @@ -628,9 +696,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetConnectivityTestEndpoints" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetConnectivityTestEndpoints" } ``` @@ -638,14 +706,14 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "endpoints": [ - "http://clients3.google.com/generate_204" - ], - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "endpoints": [ + "http://clients3.google.com/generate_204" + ], + "success": true + } } ``` @@ -654,10 +722,6 @@ This method takes no parameters. This method used to set up to 5 endpoints for a connectivity test. Successful connections are verified with HTTP Status code 204 (No Content). -### Events - -No Events - ### Parameters | Name | Type | Description | @@ -679,14 +743,14 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.SetConnectivityTestEndpoints", - "params": { - "endpoints": [ - "http://clients3.google.com/generate_204" - ] - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.SetConnectivityTestEndpoints", + "params": { + "endpoints": [ + "http://clients3.google.com/generate_204" + ] + } } ``` @@ -694,39 +758,35 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` ## *IsConnectedToInternet [method](#head.Methods)* -Seeks Whether the device has internet connectivity. This API might take up to 3s to validate internet connectivity. - -### Events - -No Events +Seeks whether the device has internet connectivity. This API might take up to 3s to validate internet connectivity. ### Parameters | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.ipversion | string | either IPv4 or IPv6 | +| params?.ipversion | string | *(optional)* Either IPv4 or IPv6 | ### Result | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.ipversion | string | either IPv4 or IPv6 | +| result.ipversion | string | Either IPv4 or IPv6 | | result.connected | boolean | `true` if internet connectivity is detected, otherwise `false` | -| result.state | integer | The internet state | -| result.status | integer | The internet status; could be `LIMITED_INTERNET`, `CAPTIVE_PORTAL`, `NO_INTERNET`, `FULLY_CONNECTED` | +| result.state | integer | Internet state | +| result.status | string | Internet status | | result.success | boolean | Whether the request succeeded | ### Example @@ -735,12 +795,12 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.IsConnectedToInternet", - "params": { - "ipversion": "IPv4" - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.IsConnectedToInternet", + "params": { + "ipversion": "IPv4" + } } ``` @@ -748,15 +808,15 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "ipversion": "IPv4" - "connected": true, - "state": 3, - "status": "FULLY_CONNECTED", - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "ipversion": "IPv4", + "connected": true, + "state": 3, + "status": "FULLY_CONNECTED", + "success": true + } } ``` @@ -765,10 +825,6 @@ No Events Gets the captive portal URI if connected to any captive portal network. -### Events - -No Events - ### Parameters This method takes no parameters. @@ -787,9 +843,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetCaptivePortalURI" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetCaptivePortalURI" } ``` @@ -797,31 +853,28 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "uri": "http://10.0.0.1/captiveportal.jst", - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "uri": "http://10.0.0.1/captiveportal.jst", + "success": true + } } ``` ## *StartConnectivityMonitoring [method](#head.Methods)* -Enable a continuous monitoring of internet connectivity with heart beat interval thats given. If the monitoring is already happening, it will be restarted with new given interval. +Enable a continuous monitoring of internet connectivity with heart beat interval thats given. If the monitoring is already happening, it will be restarted with new given interval. When the interval is not passed, it will be 60s by default. -### Events +Also see: [onInternetStatusChange](#event.onInternetStatusChange) -| Event | Description | -| :-------- | :-------- | -| [onInternetStatusChange](#event.onInternetStatusChange) | Triggered when internet connection state changed. | ### Parameters | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.interval | number | Interval in sec | +| params?.interval | integer | *(optional)* Interval in sec | ### Result @@ -836,12 +889,12 @@ Enable a continuous monitoring of internet connectivity with heart beat interval ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.StartConnectivityMonitoring", - "params": { - "interval": 30 - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.StartConnectivityMonitoring", + "params": { + "interval": 30 + } } ``` @@ -849,11 +902,11 @@ Enable a continuous monitoring of internet connectivity with heart beat interval ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` @@ -862,10 +915,6 @@ Enable a continuous monitoring of internet connectivity with heart beat interval Stops the connectivity monitoring. -### Events - -No Events - ### Parameters This method takes no parameters. @@ -883,9 +932,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.StopConnectivityMonitoring" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.StopConnectivityMonitoring" } ``` @@ -893,11 +942,11 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` @@ -906,24 +955,20 @@ This method takes no parameters. Gets the internet/public IP Address of the device. -### Events - -No Events - ### Parameters | Name | Type | Description | | :-------- | :-------- | :-------- | -| params | object | it allows empty parameter too | -| params.ipversion | string | *(optional)* Either IPv4 or IPv6 | +| params | object | It allows empty parameter too | +| params?.ipversion | string | *(optional)* Either IPv4 or IPv6 | ### Result | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.ipaddress | string | Returns an public ip of the device | -| result.ipversion | string | Returns an ip version of the public ip | +| result.ipaddress | string | The IP address | +| result.ipversion | string | Either IPv4 or IPv6 | | result.success | boolean | Whether the request succeeded | ### Example @@ -932,12 +977,12 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetPublicIP", - "params": { - "ipversion": "IPv4" - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetPublicIP", + "params": { + "ipversion": "IPv4" + } } ``` @@ -945,13 +990,13 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "ipaddress": "69.136.49.95", - "ipversion": "IPv4" - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "ipaddress": "192.168.1.101", + "ipversion": "IPv4", + "success": true + } } ``` @@ -960,27 +1005,23 @@ No Events Pings the specified endpoint with the specified number of packets. -### Events - -No Events - ### Parameters | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | | params.endpoint | string | The host name or IP address | -| params.ipversion | string | either IPv4 or IPv6 | -| params.count | integer | *(optional)* The number of packets to send. Default is 3 | -| params.timeout | integer | Timeout | -| params.guid | string | The globally unique identifier | +| params.ipversion | string | Either IPv4 or IPv6 | +| params?.count | integer | *(optional)* The number of requests to send. Default is 3 | +| params?.timeout | integer | *(optional)* Timeout | +| params?.guid | string | *(optional)* The globally unique identifier | ### Result | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.target | string | The target IP address | +| result.endpoint | string | The host name or IP address | | result.packetsTransmitted | integer | The number of packets sent | | result.packetsReceived | integer | The number of packets received | | result.packetLoss | string | The number of packets lost | @@ -998,16 +1039,16 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.Ping", - "params": { - "endpoint": "45.57.221.20", - "ipversion": "IPv4", - "count": 5, - "timeout": 30, - "guid": "..." - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.Ping", + "params": { + "endpoint": "45.57.221.20", + "ipversion": "IPv4", + "count": 10, + "timeout": 30, + "guid": "..." + } } ``` @@ -1015,21 +1056,21 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "target": "45.57.221.20", - "packetsTransmitted": 5, - "packetsReceived": 5, - "packetLoss": "0.0", - "tripMin": "61.264", - "tripAvg": "130.397", - "tripMax": "230.832", - "tripStdDev": "80.919", - "error": "...", - "guid": "...", - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "endpoint": "45.57.221.20", + "packetsTransmitted": 10, + "packetsReceived": 10, + "packetLoss": "0.0", + "tripMin": "61.264", + "tripAvg": "130.397", + "tripMax": "230.832", + "tripStdDev": "80.919", + "error": "...", + "guid": "...", + "success": true + } } ``` @@ -1038,27 +1079,24 @@ No Events Traces the specified endpoint with the specified number of packets using `traceroute`. -### Events - -No Events - ### Parameters -| Name | Type | Description | -| :-------- | :-------- | :-------- | +| Name | Type | Description | +| :-------- | :-------- | :-------- | | params | object | | -| params.ipversion| string | *(optional)* The host name or IP address | -| params.endpoint | string | The host name or IP address | -| params.packets | integer | *(optional)* The number of packets to send. Default is 5 | -| params.guid | string | *(optional)* The globally unique identifier | +| params.endpoint | string | The host name or IP address | +| params.ipversion | string | Either IPv4 or IPv6 | +| params?.packets | integer | *(optional)* The number of packets to send. Default is 5 | +| params?.guid | string | *(optional)* The globally unique identifier | ### Result | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.target | string | The target IP address | -| result.results | string | The results from `traceroute` | +| result.endpoint | string | The host name or IP address | +| result.results | string | The response of traceroute | +| result.guid | string | The globally unique identifier | | result.success | boolean | Whether the request succeeded | ### Example @@ -1067,13 +1105,15 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.Trace", - "params": { - "endpoint": "45.57.221.20", - "packets": 5 - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.Trace", + "params": { + "endpoint": "45.57.221.20", + "ipversion": "IPv4", + "packets": 10, + "guid": "..." + } } ``` @@ -1081,34 +1121,32 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "target": "45.57.221.20", - "success": true, - "results": "<<>>" - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "endpoint": "45.57.221.20", + "results": "...", + "guid": "...", + "success": true + } } ``` ## *StartWiFiScan [method](#head.Methods)* -Initiates WiFi scaning. This method supports scanning for specific range of frequency like 2.4GHz only or 5GHz only or 6GHz only or ALL. When no input passed about the frequency to be scanned, it scans for all. It publishes 'onAvailableSSIDs' event upon completion. +Initiates WiFi scaning. This method supports scanning for specific range of frequency like 2.4GHz only or 5GHz only or 6GHz only or ALL. When no input passed about the frequency to be scanned, it scans for all. When list of SSIDs to be scanned specifically, it can be passed as input. It publishes 'onAvailableSSIDs' event upon completion. -### Events +Also see: [onAvailableSSIDs](#event.onAvailableSSIDs) -| Event | Description | -| :-------- | :-------- | -| [onAvailableSSIDs](#event.onAvailableSSIDs) | Triggered when list of SSIDs is available after the scan completes. | ### Parameters | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.frequency | string | *(optional)* The frequency to scan. | -| params.ssids | array | *(optional)* The list of SSIDs to scan. | -| params.ssids[#] | string | | +| params?.frequency | string | *(optional)* The frequency to scan. An empty or `null` value scans all frequencies | +| params?.ssids | array | *(optional)* The list of SSIDs to be scanned | +| params?.ssids[#] | string | *(optional)* | ### Result @@ -1123,9 +1161,15 @@ Initiates WiFi scaning. This method supports scanning for specific range of freq ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.StartWiFiScan" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.StartWiFiScan", + "params": { + "frequency": "5", + "ssids": [ + "Xfinity Mobile" + ] + } } ``` @@ -1133,11 +1177,11 @@ Initiates WiFi scaning. This method supports scanning for specific range of freq ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` @@ -1146,10 +1190,6 @@ Initiates WiFi scaning. This method supports scanning for specific range of freq Stops WiFi scanning. Any discovered SSIDs from the call to the `StartWiFiScan` method up to the point where this method is called are still returned as event. -### Events - -No Events - ### Parameters This method takes no parameters. @@ -1167,9 +1207,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.StopWiFiScan" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.StopWiFiScan" } ``` @@ -1177,11 +1217,11 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` @@ -1190,10 +1230,6 @@ This method takes no parameters. Gets list of saved SSIDs. This method returns all the SSIDs that are saved as array. -### Events - -No Events - ### Parameters This method takes no parameters. @@ -1213,9 +1249,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetKnownSSIDs" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetKnownSSIDs" } ``` @@ -1223,14 +1259,14 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "ssids": [ - "Xfinity_Guest" - ], - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "ssids": [ + "Xfinity_Guest" + ], + "success": true + } } ``` @@ -1239,10 +1275,6 @@ This method takes no parameters. Saves the SSID, passphrase, and security mode for upcoming and future sessions. This method only adds to the persistent memory; does not disconnect from currently connected SSID. -### Events - -No Events - ### Parameters | Name | Type | Description | @@ -1250,7 +1282,7 @@ No Events | params | object | | | params.ssid | string | The paired SSID | | params.passphrase | string | The access point password | -| params.security | integer | The security mode. See `getSupportedSecurityModes` | +| params.security | integer | The security mode. See `getSupportedsecurityModes` | ### Result @@ -1265,14 +1297,14 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.AddToKnownSSIDs", - "params": { - "ssid": "123412341234", - "passphrase": "password", - "security": 6 - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.AddToKnownSSIDs", + "params": { + "ssid": "123412341234", + "passphrase": "password", + "security": 6 + } } ``` @@ -1280,26 +1312,21 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` ## *RemoveKnownSSID [method](#head.Methods)* -Remove given SSID from saved SSIDs. This method just removes from the list and of the list is having only one entry thats being removed, it will initiate a disconnect. +Remove given SSID from saved SSIDs. This method just removes an entry from the list and of the list is having only one entry thats being removed, it will initiate a disconnect. -### Events +Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) -| Event | Description | -| :-------- | :-------- | -| [onWiFiStateChange](#event.onWiFiStateChange) | Triggered when Wifi state changes to DISCONNECTED | -| [onAddressChange](#event.onAddressChange) | Triggered when an IP Address is assigned or lost | -| [onInternetStatusChange](#event.onInternetStatusChange) | Triggered when internet connection state changed | ### Parameters | Name | Type | Description | @@ -1320,12 +1347,12 @@ Remove given SSID from saved SSIDs. This method just removes from the list and o ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.RemoveKnownSSID", - "params": { - "ssid": "123412341234" - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.RemoveKnownSSID", + "params": { + "ssid": "123412341234" + } } ``` @@ -1333,11 +1360,11 @@ Remove given SSID from saved SSIDs. This method just removes from the list and o ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` @@ -1346,11 +1373,8 @@ Remove given SSID from saved SSIDs. This method just removes from the list and o Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. When called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`. -### Events +Also see: [onWiFiStateChange](#event.onWiFiStateChange) -| Event | Description | -| :-------- | :-------- | -| [onWiFiStateChange](#event.onWiFiStateChange) | Triggered when Wifi state changes to CONNECTING, CONNECTED . | ### Parameters | Name | Type | Description | @@ -1358,8 +1382,17 @@ Initiates request to connect to the specified SSID with the given passphrase. Pa | params | object | | | params.ssid | string | The paired SSID | | params.passphrase | string | The access point password | -| params.security | integer | The security mode. See `getSupportedSecurityModes` | -| params?.persist | boolean | *(optional)* Option to connect to SSID without persisting AccessPoint details (default: *true*; always persist) | +| params.security | integer | The security mode. See `getSupportedsecurityModes` | +| params?.ca_cert | string | *(optional)* The ca_cert to be used for EAP | +| params?.client_cert | string | *(optional)* The client_cert to be used for EAP | +| params?.private_key | string | *(optional)* The private_key to be used for EAP | +| params?.private_key_passwd | string | *(optional)* The private_key_passwd to be used for EAP | +| params?.eap | string | *(optional)* The EAP type to be used | +| params?.eap_identity | string | *(optional)* The identity to be used for EAP | +| params?.eap_password | string | *(optional)* The eap_password to be used for EAP | +| params?.eap_phase1 | string | *(optional)* The eap_phase1 to be used for EAP | +| params?.eap_phase2 | string | *(optional)* The eap_phase2 to be used for EAP | +| params?.persist | boolean | *(optional)* To persist the SSID across reboots; similar to auto connect | ### Result @@ -1374,15 +1407,24 @@ Initiates request to connect to the specified SSID with the given passphrase. Pa ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.WiFiConnect", - "params": { - "ssid": "123412341234", - "passphrase": "password", - "security": 6, - "persist": true - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.WiFiConnect", + "params": { + "ssid": "123412341234", + "passphrase": "password", + "security": 6, + "ca_cert": "...", + "client_cert": "...", + "private_key": "...", + "private_key_passwd": "...", + "eap": "TLS", + "eap_identity": "...", + "eap_password": "...", + "eap_phase1": "...", + "eap_phase2": "...", + "persist": true + } } ``` @@ -1390,11 +1432,11 @@ Initiates request to connect to the specified SSID with the given passphrase. Pa ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` @@ -1403,13 +1445,8 @@ Initiates request to connect to the specified SSID with the given passphrase. Pa Disconnects from the currently connected SSID. A event will be posted upon completion. -### Events +Also see: [onWIFIStateChange](#event.onWIFIStateChange), [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) -| Event | Description | -| :-------- | :-------- | -| [onWIFIStateChange](#event.onWIFIStateChange) | Triggered when Wifi state changes to DISCONNECTED (only if currently connected). | -| [onAddressChange](#event.onAddressChange) | Triggered when an IP Address is assigned or lost | -| [onInternetStatusChange](#event.onInternetStatusChange) | Triggered when internet connection state changed | ### Parameters This method takes no parameters. @@ -1427,9 +1464,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.WiFiDisconnect" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.WiFiDisconnect" } ``` @@ -1437,11 +1474,11 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` @@ -1450,10 +1487,6 @@ This method takes no parameters. Returns the connected SSID information. -### Events - -No Events - ### Parameters This method takes no parameters. @@ -1478,9 +1511,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetConnectedSSID" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetConnectedSSID" } ``` @@ -1488,18 +1521,18 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "ssid": "123412341234", - "bssid": "ff:ff:ff:ff:ff:ff", - "security": "5", - "strength": "-27.000000", - "frequency": "2.442000", - "rate": "144.000000", - "noise": "-121.000000", - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "ssid": "123412341234", + "bssid": "ff:ff:ff:ff:ff:ff", + "security": "5", + "strength": "-27.000000", + "frequency": "2.442000", + "rate": "144.000000", + "noise": "-121.000000", + "success": true + } } ``` @@ -1510,20 +1543,15 @@ Initiates a connection using Wifi Protected Setup (WPS). An existing connection If the `method` parameter is set to `SERIALIZED_PIN`, then RDK retrieves the serialized pin using the Manufacturer (MFR) API. If the `method` parameter is set to `PIN`, then RDK use the pin supplied as part of the request. If the `method` parameter is set to `PBC`, then RDK uses Push Button Configuration (PBC) to obtain the pin. -### Events +Also see: [onWIFIStateChange](#event.onWIFIStateChange), [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) -| Event | Description | -| :-------- | :-------- | -| [onWIFIStateChange](#event.onWIFIStateChange) | Triggered when Wifi state changes to DISCONNECTED (only if currently connected), CONNECTING, CONNECTED. | -| [onAddressChange](#event.onAddressChange) | Triggered when an IP Address is assigned or lost | -| [onInternetStatusChange](#event.onInternetStatusChange) | Triggered when internet connection state changed | ### Parameters | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.method | integer | The method used to obtain the pin (must be one of the following: PBC=0, PIN=1, SERIALIZED_PIN=2) | -| params.pin | string | A valid 8 digit WPS pin number. Use this parameter when the `method` parameter is set to `PIN` | +| params.method | string | The method used to obtain the pin (must be one of the following: PBC=0, PIN=1, SERIALIZED_PIN=2) | +| params?.pin | string | *(optional)* A valid 8 digit WPS pin number. Use this parameter when the `method` parameter is set to `PIN` | ### Result @@ -1539,13 +1567,13 @@ If the `method` parameter is set to `SERIALIZED_PIN`, then RDK retrieves the ser ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.StartWPS", - "params": { - "method": 1, - "pin": "88888888" - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.StartWPS", + "params": { + "method": "PIN", + "pin": "88888888" + } } ``` @@ -1553,12 +1581,12 @@ If the `method` parameter is set to `SERIALIZED_PIN`, then RDK retrieves the ser ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "pin": "88888888", - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "pin": "88888888", + "success": true + } } ``` @@ -1567,11 +1595,8 @@ If the `method` parameter is set to `SERIALIZED_PIN`, then RDK retrieves the ser Cancels the in-progress WPS pairing operation. The operation forcefully stops the in-progress pairing attempt and aborts the current scan. WPS pairing must be in-progress for the operation to succeed. -### Events +Also see: [onWIFIStateChange](#event.onWIFIStateChange) -| Event | Description | -| :-------- | :-------- | -| [onWIFIStateChange](#event.onWIFIStateChange) | Triggered when Wifi state changes to DISCONNECTED. | ### Parameters This method takes no parameters. @@ -1589,9 +1614,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.StopWPS" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.StopWPS" } ``` @@ -1599,11 +1624,11 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } } ``` @@ -1612,11 +1637,8 @@ This method takes no parameters. Get WiFiSignalStrength of connected SSID. -### Events +Also see: [onWiFiSignalStrengthChange](#event.onWiFiSignalStrengthChange) -| Event | Description | -| :-------- | :-------- | -| [onWiFiSignalStrengthChange](#event.onWiFiSignalStrengthChange) | Triggered when Wifi signal strength switches between Excellent, Good, Fair, Weak. | ### Parameters This method takes no parameters. @@ -1628,7 +1650,7 @@ This method takes no parameters. | result | object | | | result.ssid | string | The paired SSID | | result.strength | string | The RSSI value in dBm | -| result.quality | string | Signal strength Quality | +| result.quality | integer | Signal strength Quality | | result.success | boolean | Whether the request succeeded | ### Example @@ -1637,9 +1659,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetWiFiSignalStrength" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetWiFiSignalStrength" } ``` @@ -1647,26 +1669,22 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "ssid": "123412341234", - "strength": "-27.000000", - "quality": "Excellent", - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "ssid": "123412341234", + "strength": "-27.000000", + "quality": 123, + "success": true + } } ``` - -## *GetSupportedSecurityModes [method](#head.Methods)* + +## *GetSupportedsecurityModes [method](#head.Methods)* Returns the Wifi security modes that the device supports. -### Events - -No Events - ### Parameters This method takes no parameters. @@ -1700,82 +1718,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetSupportedSecurityModes" -} -``` - -#### Response - -```json -{ - "jsonrpc": "2.0", - "id": 42, - "result": { - "security_modes": { - "NET_WIFI_SECURITY_NONE": 0, - "NET_WIFI_SECURITY_WEP_64": 1, - "NET_WIFI_SECURITY_WEP_128": 2, - "NET_WIFI_SECURITY_WPA_PSK_TKIP": 3, - "NET_WIFI_SECURITY_WPA_PSK_AES": 4, - "NET_WIFI_SECURITY_WPA2_PSK_TKIP": 5, - "NET_WIFI_SECURITY_WPA2_PSK_AES": 6, - "NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP": 7, - "NET_WIFI_SECURITY_WPA_ENTERPRISE_AES": 8, - "NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP": 9, - "NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES": 10, - "NET_WIFI_SECURITY_WPA_WPA2_PSK": 11, - "NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE": 12, - "NET_WIFI_SECURITY_WPA3_PSK_AES": 13, - "NET_WIFI_SECURITY_WPA3_SAE": 14 - }, - "success": true - } -} -``` - - -## *SetLogLevel [method](#head.Methods)* - -Set Log level for more information. The possible set log level are as follows. -* `0`: FATAL -* `1`: ERROR -* `2`: WARN -* `3`: INFO -* `4`: DEBUG -. - -### Events - -No Events - -### Parameters - -| Name | Type | Description | -| :-------- | :-------- | :-------- | -| params | object | | -| params.level | integer | Set Log level to get more information | - -### Result - -| Name | Type | Description | -| :-------- | :-------- | :-------- | -| result | object | | -| result.success | boolean | Whether the request succeeded | - -### Example - -#### Request - -```json -{ - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.SetLogLevel", - "params": { - "level": 1 - } + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetSupportedsecurityModes" } ``` @@ -1783,87 +1728,50 @@ No Events ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } -} -``` - - -## *GetLogLevel [method](#head.Methods)* - -Gets the log level. It could be either of the below -* `0`: FATAL -* `1`: ERROR -* `2`: WARN -* `3`: INFO -* `4`: DEBUG - -### Events - -No Events - -### Parameters - -This method takes no parameters. - -### Result - -| Name | Type | Description | -| :-------- | :-------- | :-------- | -| result | object | | -| result.level | integer | The Log level | -| result.success | boolean | Whether the request succeeded | - -### Example - -#### Request - -```json -{ - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetLogLevel", -} -``` - -#### Response - -```json -{ - "jsonrpc": "2.0", - "id": 42, - "result": { - "level": 3 - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "security_modes": { + "NET_WIFI_SECURITY_NONE": 0, + "NET_WIFI_SECURITY_WEP_64": 1, + "NET_WIFI_SECURITY_WEP_128": 2, + "NET_WIFI_SECURITY_WPA_PSK_TKIP": 3, + "NET_WIFI_SECURITY_WPA_PSK_AES": 4, + "NET_WIFI_SECURITY_WPA2_PSK_TKIP": 5, + "NET_WIFI_SECURITY_WPA2_PSK_AES": 6, + "NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP": 7, + "NET_WIFI_SECURITY_WPA_ENTERPRISE_AES": 8, + "NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP": 9, + "NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES": 10, + "NET_WIFI_SECURITY_WPA_WPA2_PSK": 11, + "NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE": 12, + "NET_WIFI_SECURITY_WPA3_PSK_AES": 13, + "NET_WIFI_SECURITY_WPA3_SAE": 14 + }, + "success": true + } } ``` ## *GetWifiState [method](#head.Methods)* -Returns the current Wifi State. The possible Wifi states are as follows. -* `0`: UNINSTALLED - The device was in an installed state and was uninstalled; or, the device does not have a Wifi radio installed -* `1`: DISABLED - The device is installed but not yet enabled -* `2`: DISCONNECTED - The device is installed and enabled, but not yet connected to a network -* `3`: PAIRING - The device is in the process of pairing, but not yet connected to a network -* `4`: CONNECTING - The device is attempting to connect to a network -* `5`: CONNECTED - The device is successfully connected to a network -* `6`: SSID_NOT_FOUND - The requested SSID to connect is not found -* `7`: SSID_CHANGED - The device connected SSID is changed -* `8`: CONNECTION_LOST - The device network connection is lost -* `9`: CONNECTION_FAILED - The device network connection got failed -* `10`: CONNECTION_INTERRUPTED - The device connection is interrupted -* `11`: INVALID_CREDENTIALS - The credentials provided to connect is not valid -* `12`: AUTHENTICATION_FAILED - Authentication process as a whole could not be successfully completed -* `13`: ERROR - The device has encountered an unrecoverable error with the Wifi adapter - -### Events - -No Events +Returns the current Wifi State. The possible Wifi states are as follows. +**Wifi States** +* `0`: WIFI_STATE_UNINSTALLED - The device was in an installed state and was uninstalled; or, the device does not have a Wifi radio installed +* `1`: WIFI_STATE_DISABLED - The device is installed but not yet enabled +* `2`: WIFI_STATE_DISCONNECTED - The device is installed and enabled, but not yet connected to a network +* `3`: WIFI_STATE_PAIRING - The device is in the process of pairing, but not yet connected to a network +* `4`: WIFI_STATE_CONNECTING - The device is attempting to connect to a network +* `5`: WIFI_STATE_CONNECTED - The device is successfully connected to a network +* `6`: WIFI_STATE_SSID_NOT_FOUND - The requested SSID to connect is not found +* `7`: WIFI_STATE_SSID_CHANGED - The device connected SSID is changed +* `8`: WIFI_STATE_CONNECTION_LOST - The device network connection is lost +* `9`: WIFI_STATE_CONNECTION_FAILED - The device connection got failed +* `10`: WIFI_STATE_CONNECTION_INTERRUPTED - The device connection is interrupted +* `11`: WIFI_STATE_INVALID_CREDENTIALS - The credentials provided to connect is not valid +* `12`: WIFI_STATE_AUTHENTICATION_FAILED - Authentication process as a whole could not be successfully completed +* `13`: WIFI_STATE_ERROR - The device has encountered an unrecoverable error with the Wifi adapter. ### Parameters @@ -1874,7 +1782,8 @@ This method takes no parameters. | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.state | integer | The Wifi operational state | +| result.state | integer | The given State | +| result.status | string | WiFi status | | result.success | boolean | Whether the request succeeded | ### Example @@ -1883,9 +1792,9 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.GetWifiState" + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.GetWifiState" } ``` @@ -1893,21 +1802,22 @@ This method takes no parameters. ```json { - "jsonrpc": "2.0", - "id": 42, - "result": { - "state": 2, - "success": true - } + "jsonrpc": "2.0", + "id": 42, + "result": { + "state": 4, + "status": "WIFI_STATE_CONNECTED", + "success": true + } } ``` # Notifications -Notifications are autonomous events, triggered by the internals of the implementation, and broadcasted via JSON-RPC to all registered observers. Refer to [[Thunder](#ref.Thunder)] for information on how to register for a notification. +Notifications are autonomous events triggered by the internals of the implementation and broadcasted via JSON-RPC to all registered observers. Refer to [[Thunder](#ref.Thunder)] for information on how to register for a notification. -The following events are provided by the org.rdk.NetworkManager plugin: +The following events are provided by the org.rdk.NetworkManager interface: NetworkManager interface events: @@ -1921,7 +1831,6 @@ NetworkManager interface events: | [onWiFiStateChange](#event.onWiFiStateChange) | Triggered when WIFI connection state get changed | | [onWiFiSignalStrengthChange](#event.onWiFiSignalStrengthChange) | Triggered when WIFI connection Signal Strength get changed | - ## *onInterfaceStateChange [event](#head.Notifications)* @@ -1940,18 +1849,20 @@ Triggered when an interface state is changed. The possible states are | :-------- | :-------- | :-------- | | params | object | | | params.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | -| params.state | string | Current state of the interface | +| params.state | integer | Current state of the interface | +| params.status | string | Current status of the interface | ### Example ```json { - "jsonrpc": "2.0", - "method": "client.events.onInterfaceStateChange", - "params": { - "interface": "wlan0", - "state": "INTERFACE_ADDED" - } + "jsonrpc": "2.0", + "method": "client.events.1.onInterfaceStateChange", + "params": { + "interface": "wlan0", + "state": 1, + "status": "INTERFACE_LINK_UP" + } } ``` @@ -1966,22 +1877,22 @@ Triggered when an IP Address is assigned or lost. | :-------- | :-------- | :-------- | | params | object | | | params.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | -| params.ipversion | string | It will be IPv4 or IPv6 | -| params.ipaddress | string | The IPv6 or IPv4 address for the interface | -| params.status | string | Whether IP address was acquired or lost (must be one of the following: 'ACQUIRED', 'LOST') (must be one of the following: *`ACQUIRED`*, *`LOST`*) | +| params.ipaddress | string | The IP address | +| params.ipversion | string | Either IPv4 or IPv6 | +| params.status | string | Whether IP address was acquired or lost (must be one of the following: 'ACQUIRED', 'LOST') | ### Example ```json { - "jsonrpc": "2.0", - "method": "client.events.onAddressChange", - "params": { - "interface": "wlan0", - "ipversion": "IPv4", - "ipaddress": "192.168.1.100", - "status": "ACQUIRED" - } + "jsonrpc": "2.0", + "method": "client.events.1.onAddressChange", + "params": { + "interface": "wlan0", + "ipaddress": "192.168.1.101", + "ipversion": "IPv4", + "status": "ACQUIRED" + } } ``` @@ -2002,12 +1913,12 @@ Triggered when the primary/active interface changes, regardless if it's from a s ```json { - "jsonrpc": "2.0", - "method": "client.events.onActiveInterfaceChange", - "params": { - "prevActiveInterface": "wlan0", - "activeInterface": "eth0" - } + "jsonrpc": "2.0", + "method": "client.events.1.onActiveInterfaceChange", + "params": { + "prevActiveInterface": "wlan0", + "activeInterface": "eth0" + } } ``` @@ -2030,14 +1941,14 @@ Triggered when internet connection state changed.The possible internet connectio ```json { - "jsonrpc": "2.0", - "method": "client.events.onInternetStatusChange", - "params": { - "prevState": 0, - "prevStatus": "NO_INTERNET", - "state": 3, - "status": "FULLY_CONNECTED" - } + "jsonrpc": "2.0", + "method": "client.events.1.onInternetStatusChange", + "params": { + "prevState": 1, + "prevStatus": "NO_INTERNET", + "state": 4, + "status": "FULLY_CONNECTED" + } } ``` @@ -2053,66 +1964,53 @@ Triggered when scan completes or when scan cancelled. | params | object | | | params.ssids | array | On Available SSID's | | params.ssids[#] | object | | -| params.ssids[#].ssid | string | ssid | -| params.ssids[#].security | integer | security | -| params.ssids[#].strength | string | signalStrength | -| params.ssids[#].frequency | string | frequency | +| params.ssids[#].ssid | string | Ssid | +| params.ssids[#].security | integer | Security | +| params.ssids[#].strength | string | Strength | +| params.ssids[#].frequency | string | Frequency | ### Example ```json { - "jsonrpc": "2.0", - "method": "client.events.onAvailableSSIDs", - "params": { - "ssids": [ - { - "ssid": "myAP-2.4", - "security": 6, - "strength": "-27.000000", - "frequency": "2.442000" - } - ] - } + "jsonrpc": "2.0", + "method": "client.events.1.onAvailableSSIDs", + "params": { + "ssids": [ + { + "ssid": "myAP-2.4", + "security": 6, + "strength": "-27.000000", + "frequency": "2.442000" + } + ] + } } ``` ## *onWiFiStateChange [event](#head.Notifications)* -Triggered when WIFI connection state get changed. The possible states are, - * '0' - 'WIFI_STATE_UNINSTALLED' - * '1' - 'WIFI_STATE_DISABLED' - * '2' - 'WIFI_STATE_DISCONNECTED' - * '3' - 'WIFI_STATE_PAIRING' - * '4' - 'WIFI_STATE_CONNECTING' - * '5' - 'WIFI_STATE_CONNECTED' - * '6' - 'WIFI_STATE_SSID_NOT_FOUND' - * '7' - 'WIFI_STATE_SSID_CHANGED' - * '8' - 'WIFI_STATE_CONNECTION_LOST' - * '9' - 'WIFI_STATE_CONNECTION_FAILED' - * '10'- 'WIFI_STATE_CONNECTION_INTERRUPTED' - * '11' - 'WIFI_STATE_INVALID_CREDENTIALS' - * '12' - 'WIFI_STATE_AUTHENTICATION_FAILED' - * '13' - 'WIFI_STATE_ERROR' -. +Triggered when WIFI connection state get changed. The possible states are defined in `GetWifiState()`. ### Parameters | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.state | integer | onWiFiStateChange | +| params.state | integer | WiFi State | +| params.status | string | WiFi status | ### Example ```json { - "jsonrpc": "2.0", - "method": "client.events.onWiFiStateChange", - "params": { - "state": 5 - } + "jsonrpc": "2.0", + "method": "client.events.1.onWiFiStateChange", + "params": { + "state": 5, + "status": "WIFI_STATE_CONNECTED" + } } ``` @@ -2127,20 +2025,20 @@ Triggered when WIFI connection Signal Strength get changed. | :-------- | :-------- | :-------- | | params | object | | | params.ssid | string | Signal Strength changed SSID | -| params.signalLevel | string | Signal Strength | -| params.signalQuality | string | Signal quality | +| params.strength | string | Signal Strength | +| params.quality | string | Signal quality | ### Example ```json { - "jsonrpc": "2.0", - "method": "client.events.onWiFiSignalStrengthChange", - "params": { - "ssid": "home-new_123", - "strength": "-27.000000", - "quality": "Excellent" - } + "jsonrpc": "2.0", + "method": "client.events.1.onWiFiSignalStrengthChange", + "params": { + "ssid": "home-new_123", + "strength": "-27.000000", + "quality": "Excellent" + } } ``` From 7d453e561417e31e7cd7d11932a77100ca060acd Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Mon, 4 Nov 2024 23:26:17 -0500 Subject: [PATCH 030/271] DELIA-66644 : Updated documentation & GetIPSettings return value (#22) Signed-off-by: Karunakaran A --- NetworkManager.json | 12 ++++++++---- NetworkManagerJsonRpc.cpp | 17 ++++++++++------- NetworkManagerRDKProxy.cpp | 10 +++++----- docs/NetworkManagerPlugin.md | 16 ++++++++-------- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/NetworkManager.json b/NetworkManager.json index 06842f8c0..bbd67fb1b 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -196,8 +196,8 @@ "result": { "type": "object", "properties": { - "Interfaces": { - "summary": "An interface", + "interfaces": { + "summary": "An interface details", "type":"array", "items": { "type":"object", @@ -372,7 +372,9 @@ "ipversion": { "$ref": "#/definitions/ipversion" } - } + }, + "required": [ + ] }, "result": { "type": "object", @@ -910,7 +912,9 @@ "example": "Xfinity Mobile" } } - } + }, + "required": [ + ] }, "result": { "type": "object", diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 3c35db251..1963a70ad 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -303,13 +303,16 @@ namespace WPEFramework response["interface"] = interface; response["ipversion"] = address.ipversion; response["autoconfig"] = address.autoconfig; - response["ipaddress"] = address.ipaddress; - response["prefix"] = address.prefix; - response["ula"] = address.ula; - response["dhcpserver"] = address.dhcpserver; - response["gateway"] = address.gateway; - response["primarydns"] = address.primarydns; - response["secondarydns"] = address.secondarydns; + if (!address.ipaddress.empty()) + { + response["ipaddress"] = address.ipaddress; + response["prefix"] = address.prefix; + response["ula"] = address.ula; + response["dhcpserver"] = address.dhcpserver; + response["gateway"] = address.gateway; + response["primarydns"] = address.primarydns; + response["secondarydns"] = address.secondarydns; + } } returnJson(rc); } diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 77588a874..8f83df927 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -837,12 +837,12 @@ namespace WPEFramework if (IARM_RESULT_SUCCESS == IARM_Bus_Call (IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_getIPSettings, (void *)&iarmData, sizeof(iarmData))) { address.autoconfig = iarmData.autoconfig; - address.dhcpserver = string(iarmData.dhcpserver,MAX_IP_ADDRESS_LEN - 1); + address.dhcpserver = string(iarmData.dhcpserver); address.ula = string(""); - address.ipaddress = string(iarmData.ipaddress,MAX_IP_ADDRESS_LEN - 1); - address.gateway = string(iarmData.gateway,MAX_IP_ADDRESS_LEN - 1); - address.primarydns = string(iarmData.primarydns,MAX_IP_ADDRESS_LEN - 1); - address.secondarydns = string(iarmData.secondarydns,MAX_IP_ADDRESS_LEN - 1); + address.ipaddress = string(iarmData.ipaddress); + address.gateway = string(iarmData.gateway); + address.primarydns = string(iarmData.primarydns); + address.secondarydns = string(iarmData.secondarydns); if (0 == strcasecmp("ipv4", iarmData.ipversion)) { address.ipversion = string ("IPv4"); diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 53529aeb0..7dcb80564 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -214,13 +214,13 @@ This method takes no parameters. | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result?.Interfaces | array | *(optional)* An interface | -| result?.Interfaces[#] | object | *(optional)* | -| result?.Interfaces[#].type | string | Interface Type | -| result?.Interfaces[#].name | string | Interface Name. ex: eth0 or wlan0 | -| result?.Interfaces[#].mac | string | Interface MAC address | -| result?.Interfaces[#].enabled | boolean | Whether the interface is currently enabled | -| result?.Interfaces[#].connected | boolean | Whether the interface is currently connected | +| result.interfaces | array | An interface details | +| result.interfaces[#] | object | | +| result.interfaces[#].type | string | Interface Type | +| result.interfaces[#].name | string | Interface Name. ex: eth0 or wlan0 | +| result.interfaces[#].mac | string | Interface MAC address | +| result.interfaces[#].enabled | boolean | Whether the interface is currently enabled | +| result.interfaces[#].connected | boolean | Whether the interface is currently connected | | result.success | boolean | Whether the request succeeded | ### Example @@ -242,7 +242,7 @@ This method takes no parameters. "jsonrpc": "2.0", "id": 42, "result": { - "Interfaces": [ + "interfaces": [ { "type": "ETHERNET", "name": "eth0", From 3d3e3ac6e4bff9c62ea1a0fe6bd180e03facfdf2 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Tue, 5 Nov 2024 16:30:28 -0500 Subject: [PATCH 031/271] DELIA-66721 : Fixed the empty interface being returned in GetIPSettings (#23) Reason for change: Fixed the empty interface being returned in GetIPSettings Test Procedure: as per DELIA-66721 Risks: Low Signed-off-by: Karunakaran A --- LegacyPlugin_WiFiManagerAPIs.h | 2 -- NetworkManagerRDKProxy.cpp | 12 +++++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/LegacyPlugin_WiFiManagerAPIs.h b/LegacyPlugin_WiFiManagerAPIs.h index c4545d500..e596fd47f 100644 --- a/LegacyPlugin_WiFiManagerAPIs.h +++ b/LegacyPlugin_WiFiManagerAPIs.h @@ -72,8 +72,6 @@ namespace WPEFramework { uint32_t getPairedSSID(const JsonObject& parameters, JsonObject& response); uint32_t getPairedSSIDInfo(const JsonObject& parameters, JsonObject& response); uint32_t isPaired(const JsonObject& parameters, JsonObject& response); - uint32_t setSignalThresholdChangeEnabled(const JsonObject& parameters, JsonObject& response); - uint32_t isSignalThresholdChangeEnabled(const JsonObject& parameters, JsonObject& response); uint32_t getSupportedSecurityModes(const JsonObject& parameters, JsonObject& response); //End methods diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 8f83df927..517e135f0 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -855,7 +855,17 @@ namespace WPEFramework } /* Return the default interface information */ - interface = string(interface); + if (interface.empty()) + { + string tmpInterface = string(iarmData.interface); + if ("ETHERNET" == tmpInterface) + interface = "eth0"; + else if ("WIFI" == tmpInterface) + interface = "wlan0"; + else + rc = Core::ERROR_BAD_REQUEST; + } + rc = Core::ERROR_NONE; } else From 84b4ba6f5827dfbb0c9d8431b58c801403168bcf Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Fri, 8 Nov 2024 12:02:32 -0500 Subject: [PATCH 032/271] DELIA-66775 : Handle onIPAddressChange Event (#27) Reason for change: Fixed the empty IPAddress in onIPAddressChange Event Test Procedure: as per DELIA-66775 Risks: Medium Signed-off-by: Karunakaran A --- LegacyPlugin_NetworkAPIs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index 6a86dc498..64a6c04f4 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -1034,11 +1034,11 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { if (parameters["isIPv6"].Boolean()) { - legacyParams["ip6Address"] = parameters["ipAddress"]; + legacyParams["ip6Address"] = parameters["ipaddress"]; } else { - legacyParams["ip4Address"] = parameters["ipAddress"]; + legacyParams["ip4Address"] = parameters["ipaddress"]; } legacyParams["status"] = parameters["status"]; From 600bc9cab5c3582138159afd17c16f8dc15cd61d Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 11 Nov 2024 13:46:02 -0500 Subject: [PATCH 033/271] RDKE-352 - Add StartWPS in GNOME libnm (#28) * Added support for start WPS * Added support for start WPS --- NetworkManagerGnomeProxy.cpp | 12 +++++-- NetworkManagerGnomeWIFI.cpp | 69 ++++++++++++++++++++++++++++++++++-- NetworkManagerGnomeWIFI.h | 2 ++ 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index 6b1fbd314..bb32fc81a 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -687,13 +687,21 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) { - uint32_t rc = Core::ERROR_RPC_CALL_FAILED; + uint32_t rc = Core::ERROR_NONE; + if(wifi->initiateWPS()) + NMLOG_INFO ("startWPS success"); + else + rc = Core::ERROR_RPC_CALL_FAILED; return rc; } uint32_t NetworkManagerImplementation::StopWPS(void) { - uint32_t rc = Core::ERROR_RPC_CALL_FAILED; + uint32_t rc = Core::ERROR_NONE; + if(wifi->cancelWPS()) + NMLOG_INFO ("cancelWPS success"); + else + rc = Core::ERROR_RPC_CALL_FAILED; return rc; } diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 12d8e49af..b2ae798bc 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -29,8 +29,23 @@ #include "NetworkManagerGnomeWIFI.h" #include "NetworkManagerGnomeUtils.h" +using namespace std; namespace WPEFramework { + class Job : public Core::IDispatch { + public: + Job(function work) + : _work(work) + { + } + void Dispatch() override + { + _work(); + } + + private: + function _work; + }; namespace Plugin { @@ -508,7 +523,7 @@ namespace WPEFramework apRsnFlags = nm_access_point_get_rsn_flags(AccessPoint); // check ap flag ty securti we supporting - if(apFlags != NM_802_11_AP_FLAGS_NONE && strlen(password_in) < 1 ) + if(apFlags != NM_802_11_AP_FLAGS_NONE && strlen(password_in) < 1 && !(apFlags & NM_802_11_AP_FLAGS_WPS)) { NMLOG_ERROR("This ap(%s) security need password please add password!", ssid_in); return false; @@ -902,9 +917,57 @@ namespace WPEFramework return true; } NMLOG_DEBUG("Last Wi-Fi scan exceeded time limit."); - return false; - } + return false; + } + + bool wifiManager::initiateWPS() + { + Core::IWorkerPool::Instance().Submit(Core::ProxyType(Core::ProxyType::Create([&]() { + const GPtrArray *aps; + int count = 1, wpsConnected = 0; + if(!createClientNewConnection()) + return; + sleep(10); /* As we will get the ap info with NM_802_11_AP_FLAGS_WPS_PBC set after pressing the PBC button. + So we are waiting for 10 seconds here*/ + do{ + if(wifiScanRequest("")) + { + aps = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(getNmDevice())); + for (guint i = 0; i < aps->len; i++) { + NMAccessPoint *ap = static_cast(g_ptr_array_index(aps, i)); + + guint32 flags = nm_access_point_get_flags(ap); + + NMLOG_INFO("AP Flags: 0x%x\n", flags); + + if (flags & NM_802_11_AP_FLAGS_WPS_PBC) { + Exchange::INetworkManager::WiFiConnectTo wifiData; + GBytes *ssid; + ssid = nm_access_point_get_ssid(ap); + gsize size; + const guint8 *ssidData = static_cast(g_bytes_get_data(ssid, &size)); + std::string ssidTmp(reinterpret_cast(ssidData), size); + wifiData.ssid = ssidTmp.c_str(); + NMLOG_INFO("connected ssid: %s", ssidTmp.c_str()); + if(wifiConnect(wifiData)) + wpsConnected = 1; + break; + } + } + } + sleep(3); /* Waiting time between successive scan */ + count++; + }while(count <= 3 && !wpsConnected); + NMLOG_INFO("Completed scanning and wpsconnect status = %d", wpsConnected); + }))); + return true; + } + + bool wifiManager::cancelWPS() + { + return true; + } } // namespace Plugin } // namespace WPEFramework diff --git a/NetworkManagerGnomeWIFI.h b/NetworkManagerGnomeWIFI.h index 8762f409b..9ad556b8e 100644 --- a/NetworkManagerGnomeWIFI.h +++ b/NetworkManagerGnomeWIFI.h @@ -53,6 +53,8 @@ namespace WPEFramework bool removeKnownSSID(const string& ssid); bool quit(NMDevice *wifiNMDevice); bool wait(GMainLoop *loop, int timeOutMs = 10000); // default maximium set as 10 sec + bool initiateWPS(); + bool cancelWPS(); private: NMDevice *getNmDevice(); From 6622fd4d79c593a785048fea52d1667b974526f0 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:06:58 -0500 Subject: [PATCH 034/271] RDKEMW-229 : Check the empty interface & ipversion input (#30) Reason for change: Check the empty interface & ipversion input Test Procedure: Call org.rdk.NetworkManager.GetIPSettings with no input param Risks: Medium Signed-off-by: Karunakaran A --- NetworkManagerJsonRpc.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 1963a70ad..9b0a8ed38 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -290,8 +290,14 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::IPAddress address{}; - string interface = parameters["interface"].String(); - string ipversion = parameters["ipversion"].String(); + string interface{}; + string ipversion{}; + + if (parameters.HasLabel("interface")) + interface = parameters["interface"].String(); + + if (parameters.HasLabel("ipversion")) + ipversion = parameters["ipversion"].String(); if (_networkManager) rc = _networkManager->GetIPSettings(interface, ipversion, address); From 1b97caf45c161d5fdd216e109ff2792088302887 Mon Sep 17 00:00:00 2001 From: parvathika <131966254+parvathika@users.noreply.github.com> Date: Thu, 14 Nov 2024 00:35:59 +0530 Subject: [PATCH 035/271] RDK-54620 : Implement a UnitTest Framework and add L1/L2 workflow (#26) * Implemented Test Class for wifisiganlstrength monitor class * Update CMakeLists.txt to include the unittest folder * Update gnome_unit_test.yml to upload the code coverage report --------- Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- .github/workflows/gnome_unit_test.yml | 31 +++++++++- CMakeLists.txt | 6 ++ .../test_WiFiSignalStrengthMonitor.cpp | 58 +++++++++++++++++++ Tests/unit_test/tests.cmake | 43 ++++++++++++++ WiFiSignalStrengthMonitor.cpp | 1 + 5 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp create mode 100644 Tests/unit_test/tests.cmake diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index 6934e5528..107e6e455 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -13,7 +13,7 @@ jobs: unit-tests: name: Build and run unit tests runs-on: ubuntu-latest - + steps: - name: Configure cache if: ${{ !env.ACT }} @@ -32,7 +32,7 @@ jobs: - name: Install packages run: | sudo apt update - sudo apt-get install -y pkg-config libglib2.0-dev libnm-dev libcurl4-openssl-dev ninja-build + sudo apt-get install -y pkg-config libglib2.0-dev libnm-dev libcurl4-openssl-dev lcov ninja-build - name: Configure Python uses: actions/setup-python@v4 @@ -90,7 +90,7 @@ jobs: uses: actions/checkout@v3 with: path: networkmanager - + - name: Build networkmanager with Gnome Proxy run: > cmake @@ -99,7 +99,32 @@ jobs: -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DCMAKE_CXX_FLAGS=" -fprofile-arcs -ftest-coverage " -DENABLE_GNOME_NETWORKMANAGER=ON + -DENABLE_UNIT_TESTING=ON && cmake --build build/GnomeNetworkmanager --target install -j8 + + - name: Run unit tests without valgrind + run: > + PATH=${{github.workspace}}/install/usr/bin:${PATH} + LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} + tests + + - name: Generate coverage + run: | + lcov -c -o coverage.info -d build/GnomeNetworkmanager + lcov -r coverage.info '/usr/include/*' '*/build/GnomeNetworkmanager/*' \ + '*/install/usr/include/*' '*/Tests/*' 'googlemock/*' 'googletest/*' \ + -o filtered_coverage.info + - name: Generate the html report + run: | + genhtml filtered_coverage.info --output-directory /tmp/coverage_report + + - name: Upload the coverage report to Pull request using actions + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: /tmp/coverage_report + diff --git a/CMakeLists.txt b/CMakeLists.txt index 7bfac119d..48846adb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,8 @@ set(PROJECT_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) include(CmakeHelperFunctions) option(USE_RDK_LOGGER "Enable RDK Logger for logging" OFF ) +option(ENABLE_UNIT_TESTING "Enable unit tests" OFF) + string(TOLOWER ${NAMESPACE} STORAGE_DIRECTORY) get_directory_property(SEVICES_DEFINES COMPILE_DEFINITIONS) @@ -167,3 +169,7 @@ write_config() write_config(PLUGINS LegacyPlugin_NetworkAPIs CLASSNAME Network LOCATOR lib${PLUGIN_LEGACY_DEPRECATED_NETWORK}.so) write_config(PLUGINS LegacyPlugin_WiFiManagerAPIs CLASSNAME WiFiManager LOCATOR lib${PLUGIN_LEGACY_DEPRECATED_WIFI}.so) +if(ENABLE_UNIT_TESTING) + include(Tests/unit_test/tests.cmake) +endif(ENABLE_UNIT_TESTING) + diff --git a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp b/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp new file mode 100644 index 000000000..a2e1d3f94 --- /dev/null +++ b/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp @@ -0,0 +1,58 @@ +#include "WiFiSignalStrengthMonitor.h" +#include "NetworkManagerImplementation.h" +#include "NetworkManagerLogger.h" +#include "INetworkManager.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace WPEFramework; +using namespace WPEFramework::Plugin; +namespace WPEFramework +{ + namespace Plugin + { + NetworkManagerImplementation* _instance; + void NetworkManagerImplementation::ReportWiFiSignalStrengthChange(const string ssid, const string strength, const WiFiSignalQuality quality) + { + return; + } + void NetworkManagerImplementation::ReportInternetStatusChange(const InternetStatus prevState, const InternetStatus currState) + { + return; + } + } +} + +class WiFiSignalStrengthMonitorTest : public ::testing::Test { + protected: + WPEFramework::Plugin::WiFiSignalStrengthMonitor monitor; + void SetUp() override { + } + void TearDown() override { + } +}; +#define BUFFER_SIZE 1024 + +TEST_F(WiFiSignalStrengthMonitorTest, GetSignalData_Connected) { + std::string ssid = "TestSSID"; + Exchange::INetworkManager::WiFiSignalQuality quality; + std::string strengthOut= "-55"; + monitor.getSignalData(ssid, quality, strengthOut); +} + +TEST_F(WiFiSignalStrengthMonitorTest, StartWiFiSignalStrengthMonitor) { + monitor.startWiFiSignalStrengthMonitor(1); + +} + +int main(int argc, char **argv) { + ::testing::InitGoogleMock(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/Tests/unit_test/tests.cmake b/Tests/unit_test/tests.cmake new file mode 100644 index 000000000..177c02947 --- /dev/null +++ b/Tests/unit_test/tests.cmake @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 3.10) +set(UNIT_TEST "tests") + +find_package(PkgConfig REQUIRED) +pkg_check_modules(GLIB REQUIRED glib-2.0) +pkg_check_modules(GIO REQUIRED gio-2.0) +pkg_check_modules(LIBNM REQUIRED libnm) + +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip +) + +FetchContent_MakeAvailable(googletest) +add_executable(${UNIT_TEST} + Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp + WiFiSignalStrengthMonitor.cpp + NetworkManagerLogger.cpp + NetworkManagerConnectivity.cpp +) +set_target_properties(${UNIT_TEST} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) +target_compile_options(${UNIT_TEST} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") + +target_include_directories(${UNIT_TEST} PRIVATE + ${GLIB_INCLUDE_DIRS} + ${LIBNM_INCLUDE_DIRS} + ${GIO_INCLUDE_DIRS} + ${PROJECT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + Tests + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include +) + +target_link_libraries(${UNIT_TEST} PRIVATE gmock_main ${NAMESPACE}Core::${NAMESPACE}Core ${GLIB_LIBRARIES} ${GIO_LIBRARIES} ${LIBNM_LIBRARIES} ${CURL_LIBRARIES}) +target_include_directories(${UNIT_TEST} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +install(TARGETS ${UNIT_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) + diff --git a/WiFiSignalStrengthMonitor.cpp b/WiFiSignalStrengthMonitor.cpp index 839de661b..09b33cc22 100644 --- a/WiFiSignalStrengthMonitor.cpp +++ b/WiFiSignalStrengthMonitor.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "NetworkManagerLogger.h" #include "NetworkManagerImplementation.h" #include "WiFiSignalStrengthMonitor.h" From 6969691322cc57ca020be791d31bdbc1d30e38a4 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:09:58 -0500 Subject: [PATCH 036/271] Implement Fossid Scan to NetworkManager (#33) Signed-off-by: Karunakaran A --- ...id_integration_stateless_diffscan_target_repo.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/workflows/fossid_integration_stateless_diffscan_target_repo.yml diff --git a/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml b/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml new file mode 100644 index 000000000..da02b8b4f --- /dev/null +++ b/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml @@ -0,0 +1,12 @@ +name: Fossid Stateless Diff Scan + +on: pull_request + +jobs: + call-fossid-workflow: + uses: rdkcentral/build_tools_workflows/.github/workflows/fossid_integration_stateless_diffscan.yml@develop + secrets: + FOSSID_CONTAINER_USERNAME: ${{ secrets.FOSSID_CONTAINER_USERNAME }} + FOSSID_CONTAINER_PASSWORD: ${{ secrets.FOSSID_CONTAINER_PASSWORD }} + FOSSID_HOST_USERNAME: ${{ secrets.FOSSID_HOST_USERNAME }} + FOSSID_HOST_TOKEN: ${{ secrets.FOSSID_HOST_TOKEN }} From 3fda592d490e0989d95874fe1462229efbc3b829 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Fri, 15 Nov 2024 09:40:39 -0500 Subject: [PATCH 037/271] Release of v0.5.1 (#34) Signed-off-by: Karunakaran A --- CMakeLists.txt | 2 +- NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 48846adb1..eb91a4bd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) set(VERSION_MINOR 5) -set(VERSION_PATCH 0) +set(VERSION_PATCH 1) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) add_compile_definitions(NETWORKMANAGER_MINOR_VERSION=${VERSION_MINOR}) diff --git a/NetworkManager.json b/NetworkManager.json index bbd67fb1b..e7f5c534a 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json", - "version": "0.5.0" + "version": "0.5.1" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 7dcb80564..0a48ddfbc 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.5.0** +**Version: 0.5.1** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.5.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.5.1). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 8b1163348050e60b13bd07de4a9e8e3f8994a4e4 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Mon, 18 Nov 2024 07:24:26 +0530 Subject: [PATCH 038/271] RDKEMW-234: [RDKE][GNOME] Not getting values for WIFI interface on GetAvailableInterfaces method (#31) * Gnome issue fix for following api wifiConnect addtoknownssid removeknowssid getavilablessid getwifisiganlstrength GetAvailableInterfaces GetPrimaryInterface GetInterfaceState GetIPSettings * onAddressChange event modified * Posting event even if interface already connected before plugin start * Update NetworkManagerGnomeEvents.cpp Signed-off-by: cmuhammedrafi --- NetworkManagerGnomeEvents.cpp | 98 ++--- NetworkManagerGnomeProxy.cpp | 439 +++++++++++++--------- NetworkManagerGnomeUtils.cpp | 187 +++++----- NetworkManagerGnomeUtils.h | 6 +- NetworkManagerGnomeWIFI.cpp | 676 ++++++++++++++++++---------------- NetworkManagerGnomeWIFI.h | 4 +- NetworkManagerJsonRpc.cpp | 4 +- NetworkManagerRDKProxy.cpp | 2 +- WiFiSignalStrengthMonitor.cpp | 2 +- 9 files changed, 781 insertions(+), 637 deletions(-) diff --git a/NetworkManagerGnomeEvents.cpp b/NetworkManagerGnomeEvents.cpp index bd12c3419..0e0321fdf 100644 --- a/NetworkManagerGnomeEvents.cpp +++ b/NetworkManagerGnomeEvents.cpp @@ -47,24 +47,27 @@ namespace WPEFramework const char *connectionTyp = NULL; primaryConn = nm_client_get_primary_connection(client); nmEvents->activeConn = primaryConn; + std::string newIface ="unknown"; if (primaryConn) { activeConnId = nm_active_connection_get_id(primaryConn); connectionTyp = nm_active_connection_get_connection_type(primaryConn); NMLOG_INFO("active connection - %s (%s)", activeConnId, connectionTyp); - std::string newIface =""; if (0 == strncmp("802-3-ethernet", connectionTyp, sizeof("802-3-ethernet"))) - newIface = "eth0"; + newIface = nmUtils::ethIface(); else if(0 == strncmp("802-11-wireless", connectionTyp, sizeof("802-11-wireless"))) - newIface = "wlan0"; + newIface = nmUtils::wlanIface(); else NMLOG_WARNING("active connection not an ethernet/wifi %s", connectionTyp); GnomeNetworkManagerEvents::onActiveInterfaceChangeCb(newIface); } else - NMLOG_ERROR("now there's no active connection"); + { + GnomeNetworkManagerEvents::onActiveInterfaceChangeCb(newIface); + NMLOG_WARNING("now there's no active connection"); + } } static void deviceStateChangeCb(NMDevice *device, GParamSpec *pspec, NMEvents *nmEvents) @@ -134,7 +137,7 @@ namespace WPEFramework GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTING); break; case NM_DEVICE_STATE_IP_CHECK: - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP,"wlan0"); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP, nmUtils::wlanIface()); break; case NM_DEVICE_STATE_ACTIVATED: wifiState = "WIFI_STATE_CONNECTED"; @@ -150,10 +153,11 @@ namespace WPEFramework break; case NM_DEVICE_STATE_NEED_AUTH: //GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTION_INTERRUPTED); - //wifiState = "WIFI_STATE_CONNECTION_INTERRUPTED"; + wifiState = "WIFI_STATE_CONNECTION_INTERRUPTED"; break; default: - wifiState = "Un handiled"; + wifiState = "Un handiled: " ; + wifiState += std::to_string(deviceState); } } } @@ -165,23 +169,23 @@ namespace WPEFramework { case NM_DEVICE_STATE_UNKNOWN: case NM_DEVICE_STATE_UNMANAGED: - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_DISABLED, "eth0"); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_DISABLED, nmUtils::ethIface()); break; case NM_DEVICE_STATE_UNAVAILABLE: case NM_DEVICE_STATE_DISCONNECTED: - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_DOWN, "eth0"); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_DOWN, nmUtils::ethIface()); break; case NM_DEVICE_STATE_PREPARE: - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_UP, "eth0"); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_UP, nmUtils::ethIface()); break; case NM_DEVICE_STATE_IP_CONFIG: - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP,"eth0"); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP, nmUtils::ethIface()); case NM_DEVICE_STATE_NEED_AUTH: case NM_DEVICE_STATE_SECONDARIES: case NM_DEVICE_STATE_ACTIVATED: case NM_DEVICE_STATE_DEACTIVATING: default: - NMLOG_WARNING("Unhandiled state change"); + NMLOG_WARNING("Unhandiled state change %d", deviceState); } } @@ -256,10 +260,17 @@ namespace WPEFramework for (guint i = 0; i < addresses->len; ++i) { NMIPAddress *address = (NMIPAddress *)g_ptr_array_index(addresses, i); if (nm_ip_address_get_family(address) == AF_INET6) { - const char *ipAddress = nm_ip_address_get_address(address); + const char *ipaddr = nm_ip_address_get_address(address); //int prefix = nm_ip_address_get_prefix(address); - if(ipAddress != NULL) { + if(ipaddr != NULL) { + std::string ipAddress = ipaddr; + if (ipAddress.compare(0, 5, "fe80:") == 0 || + ipAddress.compare(0, 6, "fe80::") == 0) { + NMLOG_DEBUG("%s It's link-local ip", ipAddress.c_str()); + continue; // It's link-local so skiping + } GnomeNetworkManagerEvents::onAddressChangeCb(iface, ipAddress, true, true); + break; // SLAAC protocol may include multip ipv6 address posting only one Global address } } } @@ -272,10 +283,10 @@ namespace WPEFramework { std::string ifname = nm_device_get_iface(device); if(ifname == nmEvents->ifnameWlan0) { - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, "wlan0"); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, nmUtils::wlanIface()); } else if(ifname == nmEvents->ifnameEth0) { - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, "eth0"); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, nmUtils::ethIface()); } /* ip events added only for eth0 and wlan0 */ @@ -304,11 +315,11 @@ namespace WPEFramework { std::string ifname = nm_device_get_iface(device); if(ifname == nmEvents->ifnameWlan0) { - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED,"wlan0"); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::wlanIface()); g_signal_handlers_disconnect_by_func(device, (gpointer)deviceStateChangeCb, nmEvents); } else if(ifname == nmEvents->ifnameEth0) { - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, "eth0"); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::ethIface()); g_signal_handlers_disconnect_by_func(device, (gpointer)deviceStateChangeCb, nmEvents); } } @@ -380,10 +391,12 @@ namespace WPEFramework NMIPConfig *ipv4Config = nm_device_get_ip4_config(device); NMIPConfig *ipv6Config = nm_device_get_ip6_config(device); if (ipv4Config) { + ip4ChangedCb(ipv4Config, NULL, device); // posting event if interface already connected g_signal_connect(ipv4Config, "notify::addresses", G_CALLBACK(ip4ChangedCb), device); } if (ipv6Config) { + ip6ChangedCb(ipv6Config, NULL, device); g_signal_connect(ipv6Config, "notify::addresses", G_CALLBACK(ip6ChangedCb), device); } @@ -393,7 +406,7 @@ namespace WPEFramework } } else - NMLOG_DEBUG("device type not eth/wifi"); + NMLOG_DEBUG("device type not eth/wifi %s", ifname.c_str()); } } @@ -453,12 +466,6 @@ namespace WPEFramework GnomeNetworkManagerEvents::GnomeNetworkManagerEvents() { NMLOG_DEBUG("GnomeNetworkManagerEvents"); - std::string wifiInterface = "wlan0", ethernetInterface = "eth0"; - if(!nmUtils::GetInterfacesName(wifiInterface, ethernetInterface)) - { - NMLOG_FATAL("GetInterfacesName failed"); - return; - } GError *error = NULL; nmEvents.client = nm_client_new(NULL, &error); if(!nmEvents.client || error ) @@ -478,8 +485,8 @@ namespace WPEFramework return; } _nmEventInstance = this; - nmEvents.ifnameEth0 = ethernetInterface; - nmEvents.ifnameWlan0 = wifiInterface; + nmEvents.ifnameEth0 = nmUtils::ethIface(); + nmEvents.ifnameWlan0 = nmUtils::wlanIface(); } /* Gnome networkmanger new events */ @@ -539,28 +546,35 @@ namespace WPEFramework static std::map ipv6Map; static std::map ipv4Map; - if (isIPv6) + if(acquired) { - if (ipAddress.empty()) { - ipAddress = ipv6Map[iface]; - ipv6Map[iface].clear(); - } - else { + if (isIPv6) + { if (ipv6Map[iface].find(ipAddress) == std::string::npos) { // same ip comes multiple time so avoding that - if (!ipv6Map[iface].empty()) - ipv6Map[iface] += " "; - ipv6Map[iface] += ipAddress; // SLAAC protocol may include multip ipv6 address + ipv6Map[iface] = ipAddress; } - else - return; // skip same ip event posting + else // same ip not posting + return; + } + else + { + ipv4Map[iface] = ipAddress; } } else { - if (ipAddress.empty()) - ipAddress = ipv4Map[iface]; + if (isIPv6) + { + ipAddress = ipv6Map[iface]; + ipv6Map[iface].clear(); + } else - ipv4Map[iface] = ipAddress; + { + ipAddress = ipv4Map[iface]; + ipv4Map[iface].clear(); + } + if(ipAddress.empty()) + return; // empty ip address not posting event } Exchange::INetworkManager::IPStatus ipStatus{}; @@ -569,7 +583,7 @@ namespace WPEFramework if(_instance != nullptr) _instance->ReportIPAddressChange(iface, isIPv6?"IPv6":"IPv4", ipAddress, ipStatus); - NMLOG_INFO("iface:%s - ipaddress:%s - %s - isIPv6:%s", iface.c_str(), ipAddress.c_str(), acquired?"acquired":"lost", isIPv6?"true":"false"); + NMLOG_INFO("iface:%s - ipaddress:%s - %s - %s", iface.c_str(), ipAddress.c_str(), acquired?"acquired":"lost", isIPv6?"isIPv6":"isIPv4"); } void GnomeNetworkManagerEvents::onAvailableSSIDsCb(NMDeviceWifi *wifiDevice, GParamSpec *pspec, gpointer userData) diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index bb32fc81a..b8780aaa0 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -31,14 +31,23 @@ namespace WPEFramework { ::_instance = this; GError *error = NULL; + // initialize the NMClient object client = nm_client_new(NULL, &error); if (client == NULL) { - NMLOG_DEBUG("Error initializing NMClient: %s", error->message); + NMLOG_FATAL("Error initializing NMClient: %s", error->message); g_error_free(error); return; } + nmUtils::getInterfacesName(); // get interface name form '/etc/device.proprties' + NMDeviceState ethState = nmUtils::ifaceState(client, nmUtils::ethIface()); + if(ethState > NM_DEVICE_STATE_DISCONNECTED && ethState < NM_DEVICE_STATE_DEACTIVATING) + m_defaultInterface = nmUtils::ethIface(); + else + m_defaultInterface = nmUtils::wlanIface(); + + NMLOG_INFO("default interface is %s", m_defaultInterface.c_str()); nmEvent = GnomeNetworkManagerEvents::getInstance(); nmEvent->startNetworkMangerEventMonitor(); wifi = wifiManager::getInstance(); @@ -47,47 +56,59 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::GetAvailableInterfaces (Exchange::INetworkManager::IInterfaceDetailsIterator*& interfacesItr/* @out */) { - uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - NMDeviceType type; - NMDeviceState state; - NMDevice *device = NULL; - static std::vector interfaceList; + uint32_t rc = Core::ERROR_GENERAL; + std::vector interfaceList; + std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); - if(interfaceList.empty()) + if(client == nullptr) { + NMLOG_FATAL("client connection null:"); + return Core::ERROR_GENERAL; + } + + GPtrArray *devices = const_cast(nm_client_get_devices(client)); + if (devices == NULL) { + NMLOG_ERROR("Failed to get device list."); + return Core::ERROR_GENERAL; + } + + for (guint j = 0; j < devices->len; j++) { - std::string interfaces[2]; - if(!nmUtils::GetInterfacesName(interfaces[0], interfaces[1])) - { - NMLOG_WARNING("GetInterface Name Error !"); - return Core::ERROR_GENERAL; - } - for (size_t i = 0; i < 2; i++) + NMDevice *device = NM_DEVICE(devices->pdata[j]); + if(device != NULL) { - if(!interfaces[i].empty()) + const char* ifacePtr = nm_device_get_iface(device); + if(ifacePtr == nullptr) + continue; + std::string ifaceStr = ifacePtr; + if(ifaceStr == wifiname || ifaceStr == ethname) // only wifi and ethenet taking { - Exchange::INetworkManager::InterfaceDetails tmp; - device = nm_client_get_device_by_iface(client, interfaces[i].c_str()); - if (device) - { - if(i == 0) - tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_WIFI; - else - tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_ETHERNET; - tmp.name = interfaces[i].c_str(); - tmp.mac = nm_device_get_hw_address(device); - state = nm_device_get_state(device); - tmp.enabled = (state > NM_DEVICE_STATE_UNAVAILABLE) ? true : false; - tmp.connected = (state > NM_DEVICE_STATE_DISCONNECTED) ? true : false; - interfaceList.push_back(tmp); - //g_clear_object(&device); + NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; + Exchange::INetworkManager::InterfaceDetails interface; + if(ifaceStr == wifiname) { + interface.type = INTERFACE_TYPE_WIFI; + interface.name = wifiname; + } + if(ifaceStr == ethname) { + interface.type = INTERFACE_TYPE_ETHERNET; + interface.name = ethname; + } + interface.mac = nm_device_get_hw_address(device); + deviceState = nm_device_get_state(device); + interface.enabled = (deviceState >= NM_DEVICE_STATE_UNAVAILABLE) ? true : false; + if(deviceState > NM_DEVICE_STATE_DISCONNECTED && deviceState < NM_DEVICE_STATE_DEACTIVATING){ + interface.connected = true; + m_defaultInterface = interface.name; } + else + interface.connected = false; + interfaceList.push_back(interface); + rc = Core::ERROR_NONE; } } } using Implementation = RPC::IteratorType; interfacesItr = Core::Service::Create(interfaceList); - rc = Core::ERROR_NONE; return rc; } @@ -98,6 +119,8 @@ namespace WPEFramework GError *error = NULL; NMActiveConnection *activeConn = NULL; NMRemoteConnection *remoteConn = NULL; + std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); + if(client == nullptr) { NMLOG_WARNING("client connection null:"); @@ -106,26 +129,35 @@ namespace WPEFramework activeConn = nm_client_get_primary_connection(client); if (activeConn == NULL) { - NMLOG_ERROR("No active activeConn Interface found"); - return Core::ERROR_GENERAL; + NMLOG_WARNING("no active activeConn Interface found"); + NMDeviceState ethState = nmUtils::ifaceState(client, nmUtils::ethIface()); + /* if ethernet is connected but not completely activate then ethernet is taken as primary else wifi */ + if(ethState > NM_DEVICE_STATE_DISCONNECTED && ethState < NM_DEVICE_STATE_DEACTIVATING) + m_defaultInterface = interface = ethname; + else + m_defaultInterface = interface = wifiname; // default is wifi + return Core::ERROR_NONE; } + remoteConn = nm_active_connection_get_connection(activeConn); if(remoteConn == NULL) { - NMLOG_WARNING("remote connection error"); + NMLOG_ERROR("remote connection error"); return Core::ERROR_GENERAL; } - interface.clear(); + const char *ifacePtr = nm_connection_get_interface_name(NM_CONNECTION(remoteConn)); if(ifacePtr == NULL) { NMLOG_ERROR("nm_connection_get_interface_name is failed"); return Core::ERROR_GENERAL; } + interface = ifacePtr; - if(interface != "eth0" && interface != "wlan0") + m_defaultInterface = interface; + if(interface != wifiname && interface != ethname) { - NMLOG_DEBUG("interface name is unknow"); + NMLOG_ERROR("primary interface is not eth/wlan"); interface.clear(); } else @@ -138,30 +170,26 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::SetPrimaryInterface (const string& interface/* @in */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; + std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); + if(client == nullptr) { NMLOG_WARNING("client connection null:"); return Core::ERROR_RPC_CALL_FAILED; } - std::string iface = "eth0"; - std::string eth, wifi; - if(!nmUtils::GetInterfacesName(wifi, eth)) + if(interface.empty() || (wifiname != interface && ethname != interface)) { - NMLOG_WARNING("GetInterface Name Error !"); + NMLOG_FATAL("interface is not valied %s", interface.c_str()!=nullptr? interface.c_str():"empty"); return Core::ERROR_GENERAL; } - else if(interface == "wlan0" || nmUtils::caseInsensitiveCompare(interface,"WIFI")) - iface = wifi; - else if(interface == "eth0" || nmUtils::caseInsensitiveCompare(interface,"ETHERNET")) - iface = eth; - - NMDevice *device = nm_client_get_device_by_iface(client, iface.c_str()); + NMDevice *device = nm_client_get_device_by_iface(client, interface.c_str()); if (device == NULL) { - NMLOG_WARNING("no interface found "); + NMLOG_FATAL("libnm doesn't have device corresponding to %s", interface.c_str()); return Core::ERROR_GENERAL; } + const GPtrArray *connections = nm_client_get_connections(client); NMConnection *conn = NULL; NMSettingConnection *settings; @@ -171,7 +199,7 @@ namespace WPEFramework settings = nm_connection_get_setting_connection(connection); /* Check if the interface name matches */ - if (g_strcmp0(nm_setting_connection_get_interface_name(settings), iface.c_str()) == 0) { + if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) { conn = connection; break; } @@ -196,71 +224,103 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) { - uint32_t rc = Core::ERROR_NONE; + std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); + if(client == nullptr) { NMLOG_WARNING("client connection null:"); return Core::ERROR_RPC_CALL_FAILED; } - std::string iface = "eth0"; - std::string eth, wifi; - if(!nmUtils::GetInterfacesName(wifi, eth)) + if(interface.empty() || (wifiname != interface && ethname != interface)) { - NMLOG_WARNING("GetInterface Name Error !"); + NMLOG_ERROR("interface: %s; not valied", interface.c_str()!=nullptr? interface.c_str():"empty"); return Core::ERROR_GENERAL; } - else if(interface == "wlan0" || nmUtils::caseInsensitiveCompare(interface,"WIFI")) - iface = wifi; - else if(interface == "eth0" || nmUtils::caseInsensitiveCompare(interface,"ETHERNET")) - iface = eth; - - const GPtrArray *devices = nm_client_get_devices(client); - NMDevice *device = NULL; - - for (guint i = 0; i < devices->len; ++i) { - device = NM_DEVICE(g_ptr_array_index(devices, i)); - const char *name = nm_device_get_iface(device); - if (g_strcmp0(name, iface.c_str()) == 0) { - nm_device_set_managed(device, enabled); - NMLOG_INFO("Interface %s status set to %s", iface.c_str(), enabled ? "Enabled" : "Disabled"); - } + NMDevice *device = nm_client_get_device_by_iface(client, interface.c_str()); + if (device == NULL) { + NMLOG_FATAL("libnm doesn't have device corresponding to %s", interface.c_str()); + return Core::ERROR_GENERAL; } - // if(device) - // g_clear_object(&device); - return rc; + nm_device_set_managed(device, enabled); + NMLOG_INFO("interface %s state: %s", interface.c_str(), enabled ? "enabled" : "disabled"); + return Core::ERROR_NONE; } uint32_t NetworkManagerImplementation::GetInterfaceState(const string& interface/* @in */, bool& isEnabled /* @out */) { - uint32_t rc = Core::ERROR_NONE; -#if 0 //FIXME - const GPtrArray *devices = nm_client_get_devices(client); - NMDevice *device = NULL; + isEnabled = false; + bool isIfaceFound = false; + std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); - for (guint i = 0; i < devices->len; ++i) { - device = NM_DEVICE(g_ptr_array_index(devices, i)); + if(client == nullptr) + { + NMLOG_WARNING("client connection null:"); + return Core::ERROR_RPC_CALL_FAILED; + } - // Get the device details - const char *name = nm_device_get_iface(device); + if(interface.empty() || (wifiname != interface && ethname != interface)) + { + NMLOG_ERROR("interface: %s; not valied", interface.c_str()!=nullptr? interface.c_str():"empty"); + return Core::ERROR_GENERAL; + } - // Check if the device name matches - if (g_strcmp0(name, interface.c_str()) == 0) { - nm_device_set_managed(device, false); + GPtrArray *devices = const_cast(nm_client_get_devices(client)); + if (devices == NULL) { + NMLOG_ERROR("Failed to get device list."); + return Core::ERROR_GENERAL; + } - NMLOG_DEBUG("Interface %s status set to disabled", - interface.c_str()); + for (guint j = 0; j < devices->len; j++) + { + NMDevice *device = NM_DEVICE(devices->pdata[j]); + if(device != NULL) + { + const char* iface = nm_device_get_iface(device); + if(iface != NULL) + { + std::string ifaceStr; + ifaceStr.assign(iface); + NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; + if(ifaceStr == interface) + { + isIfaceFound = true; + deviceState = nm_device_get_state(device); + isEnabled = (deviceState > NM_DEVICE_STATE_UNAVAILABLE) ? true : false; + NMLOG_INFO("%s : %s", ifaceStr.c_str(), isEnabled?"enabled":"disabled"); + break; + } + } } } - - // Cleanup - if(device) - g_clear_object(&device); -#endif - return rc; - } + + if(isIfaceFound) + return Core::ERROR_NONE; + else + NMLOG_ERROR("%s : not found", interface.c_str()); + return Core::ERROR_GENERAL; + } + + bool static isAutoConnectEnabled(NMActiveConnection* activeConn) + { + NMConnection *connection = NM_CONNECTION(nm_active_connection_get_connection(activeConn)); + if(connection == NULL) + return false; + + NMSettingIPConfig *ipConfig = nm_connection_get_setting_ip4_config(connection); + if(ipConfig) + { + const char* ipConfMethod = nm_setting_ip_config_get_method (ipConfig); + if(ipConfMethod != NULL && g_strcmp0(ipConfMethod, "auto") == 0) + return true; + else + NMLOG_WARNING("ip configuration: %s", ipConfMethod != NULL? ipConfMethod: "null"); + } + + return false; + } /* @brief Get IP Address Of the Interface */ uint32_t NetworkManagerImplementation::GetIPSettings(string& interface /* @inout */, const string &ipversion /* @in */, IPAddress& result /* @out */) @@ -270,148 +330,180 @@ namespace WPEFramework NMIPConfig *ip4_config = NULL; NMIPConfig *ip6_config = NULL; const gchar *gateway = NULL; - char **dns_arr = NULL; + char **dnsArr = NULL; NMDhcpConfig *dhcp4_config = NULL; NMDhcpConfig *dhcp6_config = NULL; const char* dhcpserver; NMSettingConnection *settings; - NMIPAddress *address = NULL; NMDevice *device = NULL; + std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); + if(client == nullptr) { NMLOG_WARNING("client connection null:"); return Core::ERROR_RPC_CALL_FAILED; } - std::string iface = "eth0"; - std::string ethIface, wifiIface; - if(!nmUtils::GetInterfacesName(wifiIface, ethIface)) - { - NMLOG_WARNING("GetInterface Name Error !"); - return Core::ERROR_GENERAL; - } - - else if(interface == "wlan0" || nmUtils::caseInsensitiveCompare(interface,"WIFI")) - iface = wifiIface; - else if(interface == "eth0" || nmUtils::caseInsensitiveCompare(interface,"ETHERNET")) - iface = ethIface; - else + if(interface.empty() || interface == "null") { - if(Core::ERROR_NONE != GetPrimaryInterface(iface)) + if(Core::ERROR_NONE != GetPrimaryInterface(interface)) { - NMLOG_WARNING("interface is not specified and default interface get failed"); - return Core::ERROR_GENERAL; + NMLOG_WARNING("default interface get failed"); + return Core::ERROR_NONE; } + if(interface.empty()) + { + NMLOG_DEBUG("default interface return empty default is wlan0"); + interface = wifiname; + } + } + else if(wifiname != interface && ethname != interface) + { + NMLOG_ERROR("interface: %s; not valied", interface.c_str()); + return Core::ERROR_GENERAL; } - device = nm_client_get_device_by_iface(client, iface.c_str()); + device = nm_client_get_device_by_iface(client, interface.c_str()); if (device == NULL) { - NMLOG_WARNING("no interface found / wifi not connected no ip found"); + NMLOG_FATAL("libnm doesn't have device corresponding to %s", interface.c_str()); return Core::ERROR_GENERAL; } NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; deviceState = nm_device_get_state(device); - if(deviceState != NM_DEVICE_STATE_ACTIVATED) + if(deviceState < NM_DEVICE_STATE_DISCONNECTED) { - NMLOG_WARNING("device state is not activated state: (%d)", deviceState); + NMLOG_WARNING("Device state is not a valid state: (%d)", deviceState); return Core::ERROR_GENERAL; } if(ipversion.empty()) - NMLOG_WARNING("ipversion is empty default value IPV4"); + NMLOG_WARNING("ipversion is empty default value IPv4"); const GPtrArray *connections = nm_client_get_active_connections(client); if(connections == NULL) { - NMLOG_WARNING("nm_client_get_active_connections error"); + NMLOG_WARNING("no active connection; ip is not assigned to interface"); return Core::ERROR_GENERAL; } - for (guint i = 0; i < connections->len; i++){ + + for (guint i = 0; i < connections->len; i++) + { NMActiveConnection *connection = NM_ACTIVE_CONNECTION(connections->pdata[i]); + if (connection == nullptr) + continue; settings = nm_connection_get_setting_connection(NM_CONNECTION(nm_active_connection_get_connection(connection))); - /* Check if the interface name matches */ - if (g_strcmp0(nm_setting_connection_get_interface_name(settings), iface.c_str()) == 0) { + if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) { conn = connection; break; } } + if (conn == NULL) { - NMLOG_ERROR("no active connection found"); + NMLOG_WARNING("no active connection on %s interface", interface.c_str()); return Core::ERROR_GENERAL; } - if(ipversion.empty()||nmUtils::caseInsensitiveCompare(ipversion,"IPV4")) + result.autoconfig = isAutoConnectEnabled(conn); + if(ipversion.empty() || ipversion == "null" || nmUtils::caseInsensitiveCompare(ipversion, "IPV4")) // default ipversion ipv4 { ip4_config = nm_active_connection_get_ip4_config(conn); + NMIPAddress *ipAddr = NULL; + std::string ipStr; if (ip4_config != NULL) { - const GPtrArray *p; - int i; - p = nm_ip_config_get_addresses(ip4_config); - for (i = 0; i < p->len; i++) { - address = static_cast(p->pdata[i]); + const GPtrArray *ipByte; + ipByte = nm_ip_config_get_addresses(ip4_config); + for (int i = 0; i < ipByte->len; i++) { + ipAddr = static_cast(ipByte->pdata[i]); + if(ipAddr) + ipStr = nm_ip_address_get_address(ipAddr); + if(!ipStr.empty()) + { + result.ipaddress = nm_ip_address_get_address(ipAddr); + result.prefix = nm_ip_address_get_prefix(ipAddr); + NMLOG_INFO("IPv4 addr: %s/%d", result.ipaddress.c_str(), result.prefix); + result.ipversion = "IPv4"; // if null add as default + } } gateway = nm_ip_config_get_gateway(ip4_config); - } - dns_arr = (char **)nm_ip_config_get_nameservers(ip4_config); + } + dnsArr = (char **)nm_ip_config_get_nameservers(ip4_config); dhcp4_config = nm_active_connection_get_dhcp4_config(conn); - dhcpserver = nm_dhcp_config_get_one_option (dhcp4_config, - "dhcp_server_identifier"); - if(!ipversion.empty()) - result.ipversion = ipversion.c_str(); - else - result.ipversion = "IPv4"; + if(dhcp4_config) + dhcpserver = nm_dhcp_config_get_one_option (dhcp4_config, "dhcp_server_identifier"); if(dhcpserver) result.dhcpserver = dhcpserver; - result.ula = ""; - result.ipaddress = nm_ip_address_get_address(address); - result.prefix = nm_ip_address_get_prefix(address); - result.gateway = gateway; - if((*(&dns_arr[0]))!=NULL) - result.primarydns = *(&dns_arr[0]); - if((*(&dns_arr[1]))!=NULL ) - result.secondarydns = *(&dns_arr[1]); + result.ula = ""; + if(gateway) + result.gateway = gateway; + if((*(&dnsArr[0]))!=NULL) + result.primarydns = *(&dnsArr[0]); + if((*(&dnsArr[1]))!=NULL ) + result.secondarydns = *(&dnsArr[1]); rc = Core::ERROR_NONE; } - else if(nmUtils::caseInsensitiveCompare(ipversion,"IPV6")) + else if(nmUtils::caseInsensitiveCompare(ipversion, "IPV6")) { - NMIPAddress *a; + result.ipversion = ipversion.c_str(); + NMIPAddress *ipAddr = nullptr; ip6_config = nm_active_connection_get_ip6_config(conn); - if (ip6_config != NULL) { - const GPtrArray *p; - int i; - p = nm_ip_config_get_addresses(ip6_config); - for (i = 0; i < p->len; i++) { - a = static_cast(p->pdata[i]); - result.ipaddress = nm_ip_address_get_address(a); - NMLOG_DEBUG("\tinet6 %s/%d\n", nm_ip_address_get_address(a), nm_ip_address_get_prefix(a)); + if(ip6_config == nullptr) + { + NMLOG_WARNING("no ipv6 config found"); + rc = Core::ERROR_GENERAL; + } + else + { + std::string ipStr; + const GPtrArray *ipArray = nullptr; + ipArray = nm_ip_config_get_addresses(ip6_config); + for (int i = 0; i < ipArray->len; i++) + { + ipAddr = static_cast(ipArray->pdata[i]); + if(ipAddr) + ipStr = nm_ip_address_get_address(ipAddr); + if(!ipStr.empty()) + { + if (ipStr.compare(0, 5, "fe80:") == 0 || ipStr.compare(0, 6, "fe80::") == 0) { + result.ula = ipStr; + NMLOG_INFO("link-local ip: %s", result.ula.c_str()); + } + else { + result.prefix = nm_ip_address_get_prefix(ipAddr); + if(result.ipaddress.empty()) // SLAAC mutiple ip not added + result.ipaddress = ipStr; + NMLOG_INFO("global ip %s/%d", ipStr.c_str(), result.prefix); + } + } } - gateway = nm_ip_config_get_gateway(ip6_config); - dns_arr = (char **)nm_ip_config_get_nameservers(ip6_config); + gateway = nm_ip_config_get_gateway(ip6_config); + if(gateway) + result.gateway= gateway; + dnsArr = (char **)nm_ip_config_get_nameservers(ip6_config); + if((*(&dnsArr[0]))!= NULL) + result.primarydns = *(&dnsArr[0]); + if((*(&dnsArr[1]))!=NULL ) + result.secondarydns = *(&dnsArr[1]); dhcp6_config = nm_active_connection_get_dhcp6_config(conn); - dhcpserver = nm_dhcp_config_get_one_option (dhcp6_config, - "dhcp_server_identifier"); - result.ipversion = ipversion.c_str(); - if(dhcpserver) - result.dhcpserver = dhcpserver; - result.ula = ""; - result.prefix = 0; - result.gateway = gateway; - if((*(&dns_arr[0]))!=NULL) - result.primarydns = *(&dns_arr[0]); - if((*(&dns_arr[1]))!=NULL ) - result.secondarydns = *(&dns_arr[1]); + if(dhcp6_config) + { + dhcpserver = nm_dhcp_config_get_one_option (dhcp6_config, "dhcp_server_identifier"); + if(dhcpserver) { + result.dhcpserver = dhcpserver; + } + } + result.ipversion = "IPv6"; + rc = Core::ERROR_NONE; } - rc = Core::ERROR_NONE; } else - NMLOG_WARNING("ipversion is not IPV4 orIPV6"); + NMLOG_WARNING("ipversion error IPv4/IPv6"); return rc; } @@ -503,7 +595,7 @@ namespace WPEFramework else { //FIXME : Add IPv6 support here - printf("Setting IPv6 is not supported at this point in time. This is just a place holder\n"); + NMLOG_WARNING("Setting IPv6 is not supported at this point in time. This is just a place holder"); rc = Core::ERROR_NOT_SUPPORTED; } } @@ -592,6 +684,7 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::AddToKnownSSIDs(const WiFiConnectTo& ssid /* @in */) { uint32_t rc = Core::ERROR_GENERAL; + NMLOG_WARNING("ssid security %d", ssid.security); if(wifi->addToKnownSSIDs(ssid)) rc = Core::ERROR_NONE; return rc; @@ -613,15 +706,17 @@ namespace WPEFramework NMLOG_WARNING("ssid is invalied"); return rc; } - // Check the last scanning time and if it exceeds 10 sec do a rescanning + + // Check the last scanning time and if it exceeds 5 sec do a rescanning if(!wifi->isWifiScannedRecently()) { - nmEvent->setwifiScanOptions(false, true); // not notify scan result but print logs - if(!wifi->wifiScanRequest("", ssid.ssid)) + nmEvent->setwifiScanOptions(false, false); + if(!wifi->wifiScanRequest()) { NMLOG_WARNING("scanning failed but try to connect"); } } + if(wifi->wifiConnect(ssid)) rc = Core::ERROR_NONE; return rc; diff --git a/NetworkManagerGnomeUtils.cpp b/NetworkManagerGnomeUtils.cpp index e5368393b..d6099c6d0 100644 --- a/NetworkManagerGnomeUtils.cpp +++ b/NetworkManagerGnomeUtils.cpp @@ -17,86 +17,104 @@ namespace WPEFramework { namespace Plugin { - static const char* ifnameEth = "eth0"; - static const char* ifnameWlan = "wlan0"; + static std::string m_ethifname = "eth0"; + static std::string m_wlanifname = "wlan0"; - uint8_t nmUtils::wifiSecurityModeFromAp(guint32 flags, guint32 wpaFlags, guint32 rsnFlags) - { - uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; - if ((flags == NM_802_11_AP_FLAGS_NONE) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE; - } - else if( (flags & NM_802_11_AP_FLAGS_PRIVACY) && ((wpaFlags & NM_802_11_AP_SEC_PAIR_WEP40) || (rsnFlags & NM_802_11_AP_SEC_PAIR_WEP40)) ) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_64; - } - else if( (flags & NM_802_11_AP_FLAGS_PRIVACY) && ((wpaFlags & NM_802_11_AP_SEC_PAIR_WEP104) || (rsnFlags & NM_802_11_AP_SEC_PAIR_WEP104)) ) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_128; - } - else if((wpaFlags & NM_802_11_AP_SEC_PAIR_TKIP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_TKIP)) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_TKIP; - } - else if((wpaFlags & NM_802_11_AP_SEC_PAIR_CCMP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_CCMP)) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES; - } - else if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) && (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_ENTERPRISE; - } - else if(rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK; - } - else if((wpaFlags & NM_802_11_AP_SEC_GROUP_CCMP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_CCMP)) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES; - } - else if((wpaFlags & NM_802_11_AP_SEC_GROUP_TKIP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_TKIP)) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_TKIP; + const char* nmUtils::wlanIface() {return m_wlanifname.c_str();} + const char* nmUtils::ethIface() {return m_ethifname.c_str();} + + NMDeviceState nmUtils::ifaceState(NMClient *client, const char* interface) + { + NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; + NMDevice *device = NULL; + if(client == NULL) + return deviceState; + + device = nm_client_get_device_by_iface(client, interface); + if (device == NULL) { + NMLOG_FATAL("libnm doesn't have device corresponding to %s", interface); + return deviceState; } - else if((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE) || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE; + + deviceState = nm_device_get_state(device); + return deviceState; + } + + uint8_t nmUtils::wifiSecurityModeFromAp(guint32 flags, guint32 wpaFlags, guint32 rsnFlags) + { + uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; + if ((flags == NM_802_11_AP_FLAGS_NONE) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE; + else if( (flags & NM_802_11_AP_FLAGS_PRIVACY) && ((wpaFlags & NM_802_11_AP_SEC_PAIR_WEP40) || (rsnFlags & NM_802_11_AP_SEC_PAIR_WEP40)) ) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_64; + else if( (flags & NM_802_11_AP_FLAGS_PRIVACY) && ((wpaFlags & NM_802_11_AP_SEC_PAIR_WEP104) || (rsnFlags & NM_802_11_AP_SEC_PAIR_WEP104)) ) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_128; + else if((wpaFlags & NM_802_11_AP_SEC_PAIR_TKIP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_TKIP)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_TKIP; + else if((wpaFlags & NM_802_11_AP_SEC_PAIR_CCMP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_CCMP)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES; + else if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) && (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_ENTERPRISE; + else if(rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK; + else if((wpaFlags & NM_802_11_AP_SEC_GROUP_CCMP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_CCMP)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES; + else if((wpaFlags & NM_802_11_AP_SEC_GROUP_TKIP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_TKIP)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_TKIP; + else if((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE) || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE; + else + NMLOG_WARNING("security mode not defined (flag: %d, wpaFlags: %d, rsnFlags: %d)", flags, wpaFlags, rsnFlags); + return security; + } + + // Function to convert percentage (0-100) to dBm string + const char* nmUtils::convertPercentageToSignalStrengtStr(int percentage) { + + if (percentage <= 0 || percentage > 100) { + return ""; } - else - NMLOG_WARNING("security mode not defined (flag: %d, wpaFlags: %d, rsnFlags: %d)", flags, wpaFlags, rsnFlags); - return security; - } - std::string nmUtils::getSecurityModeString(guint32 flags, guint32 wpaFlags, guint32 rsnFlags) + /* + * -30 dBm to -50 dBm: Excellent signal strength. + * -50 dBm to -60 dBm: Very good signal strength. + * -60 dBm to -70 dBm: Good signal strength; acceptable for basic internet browsing. + * -70 dBm to -80 dBm: Weak signal; performance may degrade, slower speeds, and possible dropouts. + * -80 dBm to -90 dBm: Very poor signal; likely unusable or highly unreliable. + * Below -90 dBm: Disconnected or too weak to establish a stable connection. + */ + + // dBm range: -30 dBm (strong) to -90 dBm (weak) + const int max_dBm = -30; + const int min_dBm = -90; + int dBm_value = max_dBm + ((min_dBm - max_dBm) * (100 - percentage)) / 100; + static char result[8]={0}; + snprintf(result, sizeof(result), "%d", dBm_value); + return result; + } + + std::string nmUtils::getSecurityModeString(guint32 flag, guint32 wpaFlags, guint32 rsnFlags) { - switch(flags) + std::string securityStr = "[AP type: "; + if (flag == NM_802_11_AP_FLAGS_NONE) + securityStr += "NONE "; + else { - case NM_802_11_AP_FLAGS_NONE: - NMLOG_DEBUG("ap type : point has no special capabilities"); - break; - case NM_802_11_AP_FLAGS_PRIVACY: - NMLOG_DEBUG("ap type : access point requires authentication and encryption"); - break; - case NM_802_11_AP_FLAGS_WPS: - NMLOG_DEBUG("ap type : access point supports some WPS method"); - break; - case NM_802_11_AP_FLAGS_WPS_PBC: - NMLOG_DEBUG("ap type : access point supports push-button WPS"); - break; - case NM_802_11_AP_FLAGS_WPS_PIN: - NMLOG_DEBUG("ap type : access point supports PIN-based WPS"); - break; - default: - NMLOG_ERROR("ap type : 802.11 flags unknown!"); + if ((flag & NM_802_11_AP_FLAGS_PRIVACY) != 0) + securityStr += "PRIVACY "; + if ((flag & NM_802_11_AP_FLAGS_WPS) != 0) + securityStr += "WPS "; + if ((flag & NM_802_11_AP_FLAGS_WPS_PBC) != 0) + securityStr += "WPS_PBC "; + if ((flag & NM_802_11_AP_FLAGS_WPS_PIN) != 0) + securityStr += "WPS_PIN "; } + securityStr += "] "; - std::string securityStr; - - if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags != NM_802_11_AP_SEC_NONE) && (rsnFlags != NM_802_11_AP_SEC_NONE)) + if (!(flag & NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags != NM_802_11_AP_SEC_NONE) && (rsnFlags != NM_802_11_AP_SEC_NONE)) securityStr += ("Encrypted: "); - if ((flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE) + if ((flag & NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) securityStr += ("WEP "); if (wpaFlags != NM_802_11_AP_SEC_NONE) @@ -124,7 +142,7 @@ namespace WPEFramework } uint32_t flags[2] = { wpaFlags, rsnFlags }; - securityStr += "[ WPA Flags: "; + securityStr += "[WPA: "; for (int i = 0; i < 2; ++i) { @@ -158,10 +176,10 @@ namespace WPEFramework securityStr += "wpa-eap-suite-b-192 "; if (i == 0) { - securityStr += "] [ RSN Flags: "; + securityStr += "] [RSN: "; } } - securityStr +="]"; + securityStr +="] "; return securityStr; } @@ -263,22 +281,11 @@ namespace WPEFramework return upperStr1 == upperStr2; } - bool nmUtils::GetInterfacesName(std::string &wifiIfname ,std::string ðIfname) + bool nmUtils::getInterfacesName() { std::string line; - static bool fileParsingCompleted = false; - static std::string m_wifiIfname; - static std::string m_ethIfname; // cached interface name - wifiIfname.clear(); - ethIfname.clear(); - if(fileParsingCompleted) - { - if(!m_wifiIfname.empty()) - wifiIfname = m_wifiIfname; - if(!m_ethIfname.empty()) - ethIfname = m_ethIfname; - return true; - } + std::string wifiIfname; + std::string ethIfname; // cached interface name std::ifstream file("/etc/device.properties"); if (!file.is_open()) { @@ -308,9 +315,9 @@ namespace WPEFramework NMLOG_FATAL("Could not find any interface name in /etc/device.properties"); return false; } - m_wifiIfname = wifiIfname; - m_ethIfname = ethIfname; - fileParsingCompleted = true; + m_wlanifname = wifiIfname; + m_ethifname = ethIfname; + NMLOG_INFO("/etc/device.properties eth: %s, wlan: %s", m_ethifname.c_str(), m_wlanifname.c_str()); return true; } } // Plugin diff --git a/NetworkManagerGnomeUtils.h b/NetworkManagerGnomeUtils.h index c52a5a733..f55e808f4 100644 --- a/NetworkManagerGnomeUtils.h +++ b/NetworkManagerGnomeUtils.h @@ -33,13 +33,17 @@ namespace WPEFramework { public: - static bool GetInterfacesName(std::string &wifiIfname ,std::string ðIfname); + static bool getInterfacesName(); + static const char* wlanIface(); + static const char* ethIface(); + static const char* convertPercentageToSignalStrengtStr(int percentage); static bool caseInsensitiveCompare(const std::string& str1, const std::string& str2); static uint8_t wifiSecurityModeFromAp(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); static std::string wifiFrequencyFromAp(guint32 apFreq); static std::string getSecurityModeString(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); static JsonObject apToJsonObject(NMAccessPoint *ap); static void printActiveSSIDsOnly(NMDeviceWifi *wifiDevice); + static NMDeviceState ifaceState(NMClient *client, const char* interface); }; } diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index b2ae798bc..a16b44566 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -28,6 +28,7 @@ #include "INetworkManager.h" #include "NetworkManagerGnomeWIFI.h" #include "NetworkManagerGnomeUtils.h" +#include "NetworkManagerImplementation.h" using namespace std; namespace WPEFramework @@ -48,6 +49,7 @@ namespace WPEFramework }; namespace Plugin { + extern NetworkManagerImplementation* _instance; wifiManager::wifiManager() : client(nullptr), loop(nullptr), createNewConnection(false) { NMLOG_INFO("wifiManager"); @@ -131,9 +133,14 @@ namespace WPEFramework return wifiDevice; } - for (guint j = 0; j < devices->len; j++) { + for (guint j = 0; j < devices->len; j++) + { NMDevice *device = NM_DEVICE(devices->pdata[j]); - if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_WIFI) + const char* interface = nm_device_get_iface(device); + if(interface == nullptr) + continue; + std::string iface = interface; + if (iface == nmUtils::wlanIface()) { wifiDevice = device; //NMLOG_DEBUG("Wireless Device found ifce : %s !", nm_device_get_iface (wifiDevice)); @@ -228,7 +235,7 @@ namespace WPEFramework wifiInfo.rate = std::to_string(bitrate); NMLOG_DEBUG("bitrate : %s kbit/s", wifiInfo.rate.c_str()); //TODO signal strenght to dBm - wifiInfo.strength = std::to_string(static_cast(strength)); + wifiInfo.strength = std::string(nmUtils::convertPercentageToSignalStrengtStr(strength)); NMLOG_DEBUG("sterngth: %s %%", wifiInfo.strength.c_str()); wifiInfo.security = static_cast(nmUtils::wifiSecurityModeFromAp(flags, wpaFlags, rsnFlags)); NMLOG_DEBUG("security %s", nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); @@ -248,7 +255,7 @@ namespace WPEFramework NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(wifiDevice); if(activeAP == NULL) { - NMLOG_ERROR("No active access point found !"); + NMLOG_DEBUG("No active access point found !"); return false; } else @@ -269,7 +276,7 @@ namespace WPEFramework NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(wifiDevice); if(activeAP == NULL) { - NMLOG_ERROR("No active access point found !"); + NMLOG_DEBUG("No active access point found !"); return false; } else @@ -309,39 +316,39 @@ namespace WPEFramework NMDevice *wifiNMDevice = getNmDevice(); if(wifiNMDevice == NULL) { - NMLOG_DEBUG("NMDeviceWifi NULL !"); + NMLOG_ERROR("NMDeviceWifi NULL !"); return false; } nm_device_disconnect_async(wifiNMDevice, NULL, wifiDisconnectCb, this); wait(loop); - NMLOG_DEBUG("Exit"); return isSuccess; } - static NMAccessPoint *checkSSIDAvailable(NMDevice *device, const GPtrArray *aps, const char *ssid) + static NMAccessPoint *checkSSIDAvailable(NMDevice *device, const char *ssid) { - NMAccessPoint *AccessPoint = NULL; + NMAccessPoint *AccessPoint = NULL; + const GPtrArray *aps = NULL; + if(ssid == NULL) + return NULL; + aps = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(device)); for (guint i = 0; i < aps->len; i++) { - NMAccessPoint *candidate_ap = static_cast(g_ptr_array_index(aps, i)); - if (ssid) + NMAccessPoint *ap = static_cast(g_ptr_array_index(aps, i)); + GBytes *ssidGBytes; + ssidGBytes = nm_access_point_get_ssid(ap); + if (!ssidGBytes) + continue; + gsize size; + const guint8 *ssidData = static_cast(g_bytes_get_data(ssidGBytes, &size)); + std::string ssidstr(reinterpret_cast(ssidData), size); + //g_bytes_unref(ssidGBytes); + // NMLOG_DEBUG("ssid < %s >", ssidstr.c_str()); + if (strcmp(ssid, ssidstr.c_str()) == 0) { - GBytes *ssidGBytes; - ssidGBytes = nm_access_point_get_ssid(candidate_ap); - if (!ssidGBytes) - continue; - gsize size; - const guint8 *ssidData = static_cast(g_bytes_get_data(ssidGBytes, &size)); - std::string ssidstr(reinterpret_cast(ssidData), size); - //g_bytes_unref(ssidGBytes); - // NMLOG_DEBUG("ssid < %s >", ssidstr.c_str()); - if (strcmp(ssid, ssidstr.c_str()) == 0) - { - AccessPoint = candidate_ap; - break; - } + AccessPoint = ap; + break; } } @@ -376,6 +383,24 @@ namespace WPEFramework g_main_loop_quit(_wifiManager->loop); } + static void removeKnownSSIDCb(GObject *client, GAsyncResult *result, gpointer user_data) + { + GError *error = NULL; + wifiManager *_wifiManager = (static_cast(user_data)); + NMRemoteConnection *connection = NM_REMOTE_CONNECTION(client); + if (!nm_remote_connection_delete_finish(connection, result, &error)) { + NMLOG_ERROR("RemoveKnownSSID failed %s", error->message); + _wifiManager->isSuccess = false; + } + else + { + NMLOG_INFO ("RemoveKnownSSID is success"); + _wifiManager->isSuccess = true; + } + + _wifiManager->quit(NULL); + } + static void wifiConnectionUpdate(GObject *rmObject, GAsyncResult *res, gpointer user_data) { NMRemoteConnection *remote_con = NM_REMOTE_CONNECTION(rmObject); @@ -397,245 +422,236 @@ namespace WPEFramework _wifiManager->client, NM_CONNECTION(remote_con), _wifiManager->wifidevice, _wifiManager->objectPath, NULL, wifiConnectCb, _wifiManager); } - bool wifiManager::wifiConnect(Exchange::INetworkManager::WiFiConnectTo wifiData) + static bool connectionBuilder(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo, NMConnection *m_connection) { - const char *ssid_in = wifiData.ssid.c_str(); - const char* password_in = wifiData.passphrase.c_str(); - NMAccessPoint *AccessPoint = NULL; - GPtrArray *allaps = NULL; - const char *conName = ssid_in; - NMConnection *connection = NULL; - NMSettingConnection *sConnection = NULL; - NMSetting8021x *s8021X = NULL; - NMSettingWireless *sWireless = NULL; - NMSettingWirelessSecurity *sSecurity = NULL; - NM80211ApFlags apFlags; - NM80211ApSecurityFlags apWpaFlags; - NM80211ApSecurityFlags apRsnFlags; - const char *ifname = NULL; - const GPtrArray *availableConnections; - bool SSIDmatch = false; - Exchange::INetworkManager::WiFiSSIDInfo apinfo; - - if(!createClientNewConnection()) - return false; - - if (strlen(ssid_in) > 32) + if(ssidinfo.ssid.empty() || ssidinfo.ssid.length() > 32) { - NMLOG_WARNING("ssid length grater than 32"); + NMLOG_WARNING("ssid name is missing or invalied"); return false; } + /* Build up the 'connection' Setting */ + NMSettingConnection *sConnection = (NMSettingConnection *) nm_setting_connection_new(); + const char *uuid = nm_utils_uuid_generate(); + g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_UUID, uuid, NULL); // uuid + g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_ID, ssidinfo.ssid.c_str(), NULL); // connection id = ssid + g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_INTERFACE_NAME, "wlan0", NULL); // interface name + g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_TYPE, "802-11-wireless", NULL); // type 802.11wireless + nm_connection_add_setting(m_connection, NM_SETTING(sConnection)); - NMDevice *device = NULL; - device = getNmDevice(); - if(device == NULL) - return false; - wifidevice = device; + /* Build up the '802-11-wireless-security' settings */ + NMSettingWireless *sWireless = NULL; + sWireless = (NMSettingWireless *)nm_setting_wireless_new(); + nm_connection_add_setting(m_connection, NM_SETTING(sWireless)); + GBytes *ssid = g_bytes_new(ssidinfo.ssid.c_str(), strlen(ssidinfo.ssid.c_str())); + g_object_set(G_OBJECT(sWireless), NM_SETTING_WIRELESS_SSID, ssid, NULL); // ssid in Gbyte + g_object_set(G_OBJECT(sWireless), NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA, NULL); // infra mode + g_object_set(G_OBJECT(sWireless), NM_SETTING_WIRELESS_HIDDEN, true, NULL); // hidden = true + // 'bssid' parameter is used to restrict the connection only to the BSSID + // g_object_set(s_wifi, NM_SETTING_WIRELESS_BSSID, bssid, NULL); - std::string activeSSID; - if(getConnectedSSID(NM_DEVICE_WIFI(wifidevice), activeSSID)) + NMSettingWirelessSecurity *sSecurity = NULL; + switch(ssidinfo.security) { - if(strcmp(ssid_in, activeSSID.c_str()) == 0) + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_TKIP: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_TKIP: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE: { - NMLOG_WARNING("ssid already connected !"); - return true; + if(ssidinfo.passphrase.empty() || ssidinfo.passphrase.length() < 8) + { + NMLOG_WARNING("password legth should be > 8"); + return false; + } + + sSecurity = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); + nm_connection_add_setting(m_connection, NM_SETTING(sSecurity)); + if(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE == ssidinfo.security) + { + NMLOG_INFO("key-mgmt: %s", "sae"); + g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,"sae", NULL); + } + else + { + NMLOG_INFO("key-mgmt: %s", "wpa-psk"); + g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,"wpa-psk", NULL); + } + g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", NULL); + g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_PSK, ssidinfo.passphrase.c_str(), NULL); + break; } - else + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_ENTERPRISE_TKIP: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_ENTERPRISE_AES: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_ENTERPRISE_TKIP: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_ENTERPRISE_AES: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_ENTERPRISE: { - NMLOG_WARNING("wifi already connected with %s AP", activeSSID.c_str()); - } - } - //NMLOG_DEBUG("Wireless Device found ifce : %s !", ifname = nm_device_get_iface(device)); - AccessPoint = checkSSIDAvailable(device, allaps, ssid_in); - // TODO Scann hidden ssid also for lnf - if(AccessPoint == NULL) { - NMLOG_WARNING("No network with SSID '%s' found !", ssid_in); - // TODO send SSID NO AVAILABLE event - return false; - } - - getApInfo(AccessPoint, apinfo); + NMSetting8021x *s8021X = NULL; + GError *error = NULL; + + NMLOG_INFO("key-mgmt: %s", "802.1X"); + NMLOG_DEBUG("802.1x Identity : %s", ssidinfo.eap_identity.c_str()); + NMLOG_DEBUG("802.1x CA cert path : %s", ssidinfo.ca_cert.c_str()); + NMLOG_DEBUG("802.1x Client cert path : %s", ssidinfo.client_cert.c_str()); + NMLOG_DEBUG("802.1x Private key path : %s", ssidinfo.private_key.c_str()); + NMLOG_DEBUG("802.1x Private key psswd : %s", ssidinfo.private_key_passwd.c_str()); + + s8021X = (NMSetting8021x *) nm_setting_802_1x_new(); + nm_connection_add_setting(m_connection, NM_SETTING(s8021X)); + g_object_set(s8021X, NM_SETTING_802_1X_IDENTITY, ssidinfo.eap_identity.c_str(), NULL); + nm_setting_802_1x_add_eap_method(s8021X, "tls"); + if(!ssidinfo.ca_cert.empty() && !nm_setting_802_1x_set_ca_cert(s8021X, + ssidinfo.ca_cert.c_str(), + NM_SETTING_802_1X_CK_SCHEME_PATH, + NULL, + &error)) + { + NMLOG_ERROR("ca certificate add failed: %s", error->message); + g_error_free(error); + return false; + } - availableConnections = nm_device_get_available_connections(device); - for (guint i = 0; i < availableConnections->len; i++) - { - NMConnection *currentConnection = static_cast(g_ptr_array_index(availableConnections, i)); - const char *id = nm_connection_get_id(NM_CONNECTION(currentConnection)); + if(!ssidinfo.client_cert.empty() && !nm_setting_802_1x_set_client_cert(s8021X, + ssidinfo.client_cert.c_str(), + NM_SETTING_802_1X_CK_SCHEME_PATH, + NULL, + &error)) + { + NMLOG_ERROR("client certificate add failed: %s", error->message); + g_error_free(error); + return false; + } - if (conName) { - if (!id || strcmp(id, conName)) - continue; + if(!ssidinfo.private_key.empty() && !nm_setting_802_1x_set_private_key(s8021X, + ssidinfo.private_key.c_str(), + ssidinfo.private_key_passwd.c_str(), + NM_SETTING_802_1X_CK_SCHEME_PATH, + NULL, + &error)) + { + NMLOG_ERROR("client private key add failed: %s", error->message); + g_error_free(error); + return false; + } - SSIDmatch = TRUE; + sSecurity = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); + nm_connection_add_setting(m_connection, NM_SETTING(sSecurity)); + g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,"wpa-eap", NULL); + break; } - - if (nm_access_point_connection_valid(AccessPoint, NM_CONNECTION(currentConnection))) { - connection = g_object_ref(currentConnection); - NMLOG_DEBUG("Connection '%s' exists !", conName); + case Exchange::INetworkManager::WIFI_SECURITY_NONE: + { + NMLOG_INFO("key-mgmt: %s", "none"); + sSecurity = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); + nm_connection_add_setting(m_connection, NM_SETTING(sSecurity)); + g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,"none", NULL); + NMLOG_WARNING("open wifi network configuration"); break; } + default: + { + NMLOG_ERROR("wifi securtity type not supported %d", ssidinfo.security); + return false; + } } - if (SSIDmatch && !connection) - { - NMLOG_ERROR("Connection '%s' exists but properties don't match", conName); - //TODO Remove Connection - return false; - } + /* Build up the 'ipv4' Setting */ + NMSettingIP4Config *sIpv4Conf = (NMSettingIP4Config *) nm_setting_ip4_config_new(); + g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); // autoconf = true + nm_connection_add_setting(m_connection, NM_SETTING(sIpv4Conf)); - if (!connection) - { - NMLOG_DEBUG("creating new connection '%s' ", conName); - connection = nm_simple_connection_new(); - if (conName) { - sConnection = (NMSettingConnection *) nm_setting_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(sConnection)); - const char *uuid = nm_utils_uuid_generate();; - - g_object_set(G_OBJECT(sConnection), - NM_SETTING_CONNECTION_UUID, - uuid, - NM_SETTING_CONNECTION_ID, - conName, - NM_SETTING_CONNECTION_TYPE, - "802-11-wireless", - NULL); - } + /* Build up the 'ipv6' Setting */ + NMSettingIP6Config *sIpv6Conf = (NMSettingIP6Config *) nm_setting_ip6_config_new(); + g_object_set(G_OBJECT(sIpv6Conf), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); // autoconf = true + nm_connection_add_setting(m_connection, NM_SETTING(sIpv6Conf)); + return true; + } - sWireless = (NMSettingWireless *)nm_setting_wireless_new(); - GBytes *ssid = g_bytes_new(ssid_in, strlen(ssid_in)); - g_object_set(G_OBJECT(sWireless), - NM_SETTING_WIRELESS_SSID, - ssid, - NULL); - //g_bytes_unref(ssid); - /* For lnf network need to include - * - * 'bssid' parameter is used to restrict the connection only to the BSSID - * g_object_set(s_wifi, NM_SETTING_WIRELESS_BSSID, bssid, NULL); - * g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NM_SETTING_WIRELESS_HIDDEN, hidden, NULL); - */ - nm_connection_add_setting(connection, NM_SETTING(sWireless)); - } - - apFlags = nm_access_point_get_flags(AccessPoint); - apWpaFlags = nm_access_point_get_wpa_flags(AccessPoint); - apRsnFlags = nm_access_point_get_rsn_flags(AccessPoint); - - // check ap flag ty securti we supporting - if(apFlags != NM_802_11_AP_FLAGS_NONE && strlen(password_in) < 1 && !(apFlags & NM_802_11_AP_FLAGS_WPS)) - { - NMLOG_ERROR("This ap(%s) security need password please add password!", ssid_in); - return false; - } + bool wifiManager::wifiConnect(Exchange::INetworkManager::WiFiConnectTo ssidInfo) + { + NMAccessPoint *AccessPoint = NULL; + NMConnection *m_connection = NULL; + const GPtrArray *availableConnections; + bool SSIDmatch = false; + isSuccess = false; - if ( (apRsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE) || (apRsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) { + if(!createClientNewConnection()) + return false; - NMLOG_ERROR("Ap wifi security OWE"); + NMDevice *device = getNmDevice(); + if(device == NULL) return false; - } - if( (apWpaFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) || (apRsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) ) + std::string activeSSID; + if(getConnectedSSID(NM_DEVICE_WIFI(device), activeSSID)) { - GError *error = NULL; - NMLOG_INFO("Ap securtity mode is 802.1X"); - - NMLOG_DEBUG("802.1x Identity : %s", wifiData.eap_identity.c_str()); - NMLOG_DEBUG("802.1x CA cert path : %s", wifiData.ca_cert.c_str()); - NMLOG_DEBUG("802.1x Client cert path : %s", wifiData.client_cert.c_str()); - NMLOG_DEBUG("802.1x Private key path : %s", wifiData.private_key.c_str()); - NMLOG_DEBUG("802.1x Private key psswd : %s", wifiData.private_key_passwd.c_str()); - - s8021X = (NMSetting8021x *) nm_setting_802_1x_new(); - nm_connection_add_setting(connection, NM_SETTING(s8021X)); - - g_object_set(s8021X, NM_SETTING_802_1X_IDENTITY, wifiData.eap_identity.c_str(), NULL); - nm_setting_802_1x_add_eap_method(s8021X, "tls"); - if(!wifiData.ca_cert.empty() && !nm_setting_802_1x_set_ca_cert(s8021X, - wifiData.ca_cert.c_str(), - NM_SETTING_802_1X_CK_SCHEME_PATH, - NULL, - &error)) + if(ssidInfo.ssid == activeSSID) { - NMLOG_ERROR("ca certificate add failed: %s", error->message); - g_error_free(error); - return false; + NMLOG_INFO("ssid already connected !"); + return true; } + else + NMLOG_DEBUG("wifi already connected with %s AP", activeSSID.c_str()); + } - if(!wifiData.client_cert.empty() && !nm_setting_802_1x_set_client_cert(s8021X, - wifiData.client_cert.c_str(), - NM_SETTING_802_1X_CK_SCHEME_PATH, - NULL, - &error)) - { - NMLOG_ERROR("client certificate add failed: %s", error->message); - g_error_free(error); - return false; - } + AccessPoint = checkSSIDAvailable(device, ssidInfo.ssid.c_str()); + if(AccessPoint == NULL) { + NMLOG_WARNING("SSID '%s' not found !", ssidInfo.ssid.c_str()); + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + return false; + } - if(!wifiData.private_key.empty() && !nm_setting_802_1x_set_private_key(s8021X, - wifiData.private_key.c_str(), - wifiData.private_key_passwd.c_str(), - NM_SETTING_802_1X_CK_SCHEME_PATH, - NULL, - &error)) - { - NMLOG_ERROR("client private key add failed: %s", error->message); - g_error_free(error); - return false; - } + Exchange::INetworkManager::WiFiSSIDInfo apinfo; + getApInfo(AccessPoint, apinfo); - sSecurity = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(sSecurity)); - g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,"wpa-eap", NULL); - } - else if ((apFlags & NM_802_11_AP_FLAGS_PRIVACY) || (apWpaFlags != NM_802_11_AP_SEC_NONE )|| (apRsnFlags != NM_802_11_AP_SEC_NONE )) + availableConnections = nm_device_get_available_connections(device); + for (guint i = 0; i < availableConnections->len; i++) { - NMLOG_INFO("%s ap securtity mode (%s) supported !", ssid_in, nmUtils::getSecurityModeString(apFlags,apWpaFlags,apRsnFlags).c_str()); - - if (password_in) + NMConnection *connection = static_cast(g_ptr_array_index(availableConnections, i)); + const char *connId = nm_connection_get_id(NM_CONNECTION(connection)); + if (connId != NULL && strcmp(connId, ssidInfo.ssid.c_str()) == 0) { - sSecurity = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(connection, NM_SETTING(sSecurity)); - - if (apWpaFlags == NM_802_11_AP_SEC_NONE && apRsnFlags == NM_802_11_AP_SEC_NONE) - { - nm_setting_wireless_security_set_wep_key(sSecurity, 0, password_in); - NMLOG_ERROR("wifi security WEP mode not supported ! need to add wep-key-type"); - return false; + if (nm_access_point_connection_valid(AccessPoint, NM_CONNECTION(connection))) { + m_connection = g_object_ref(connection); + NMLOG_DEBUG("connection '%s' exists !", ssidInfo.ssid.c_str()); + if (m_connection == NULL) + { + NMLOG_ERROR("m_connection == NULL smothing went worng"); + return false; + } + break; } - else if ((apWpaFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) - || (apRsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) || (apRsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE)) { - - g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,"wpa-psk", NULL); - g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_PSK, password_in, NULL); + else + { + if (NM_IS_REMOTE_CONNECTION(connection)) + { + /* + * libnm reuses the existing connection if new settings match the AP properties; + * remove the old one because now only one connection per SSID is supported. + */ + NMLOG_WARNING(" '%s' connection exist but properties miss match; deleting...", ssidInfo.ssid.c_str()); + nm_remote_connection_delete_async(NM_REMOTE_CONNECTION(connection), + NULL, + removeKnownSSIDCb, + this); + } } } - else - { - NMLOG_ERROR("This AccessPoint(%s) need password please add password!", ssid_in); - return false; - } } - else + + if (NM_IS_REMOTE_CONNECTION(m_connection)) { - /* for open network every flag value will be zero */ - if (apFlags == NM_802_11_AP_FLAGS_NONE && apWpaFlags == NM_802_11_AP_SEC_NONE && apRsnFlags == NM_802_11_AP_SEC_NONE) { - NMLOG_INFO("open network no password requied"); - } - else { - NMLOG_ERROR("wifi security mode not supported !"); + if(!connectionBuilder(ssidInfo, m_connection)) + { + NMLOG_ERROR("connection builder failed"); return false; } - } - - objectPath = nm_object_get_path(NM_OBJECT(AccessPoint)); - GVariant *nmDbusConnection = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL); - if (NM_IS_REMOTE_CONNECTION(connection)) - { - nm_remote_connection_update2(NM_REMOTE_CONNECTION(connection), - nmDbusConnection, - NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT, // autoconnect right away + GVariant *connSettings = nm_connection_to_dbus(m_connection, NM_CONNECTION_SERIALIZE_ALL); + nm_remote_connection_update2(NM_REMOTE_CONNECTION(m_connection), + connSettings, + NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT, // block auto connect becuse manualy activate NULL, NULL, wifiConnectionUpdate, @@ -643,27 +659,57 @@ namespace WPEFramework } else { + NMLOG_DEBUG("creating new connection '%s' ", ssidInfo.ssid.c_str()); + m_connection = nm_simple_connection_new(); + objectPath = nm_object_get_path(NM_OBJECT(AccessPoint)); + if(!connectionBuilder(ssidInfo, m_connection)) + { + NMLOG_ERROR("connection builder failed"); + return false; + } createNewConnection = true; - nm_client_add_and_activate_connection_async(client, connection, device, objectPath, NULL, wifiConnectCb, this); + nm_client_add_and_activate_connection_async(client, m_connection, device, objectPath, NULL, wifiConnectCb, this); } wait(loop); return isSuccess; } - static void addToKnownSSIDsCb(GObject *client, GAsyncResult *result, gpointer user_data) + static void addToKnownSSIDsUpdateCb(GObject *rmObject, GAsyncResult *res, gpointer user_data) { + NMRemoteConnection *remote_con = NM_REMOTE_CONNECTION(rmObject); + wifiManager *_wifiManager = (static_cast(user_data)); + GVariant *ret = NULL; + GError *error = NULL; + ret = nm_remote_connection_update2_finish(remote_con, res, &error); + + if (!ret) { + NMLOG_ERROR("Error: %s.", error->message); + g_error_free(error); + _wifiManager->isSuccess = false; + NMLOG_ERROR("AddToKnownSSIDs failed"); + } + else + { + _wifiManager->isSuccess = true; + NMLOG_INFO("AddToKnownSSIDs success"); + } + _wifiManager->quit(NULL); + } + + static void addToKnownSSIDsCb(GObject *client, GAsyncResult *result, gpointer user_data) + { GError *error = NULL; wifiManager *_wifiManager = (static_cast(user_data)); - //NMRemoteConnection *connection = NM_REMOTE_CONNECTION(s); - if (!nm_client_add_connection_finish(NM_CLIENT(client), result, &error)) { - NMLOG_ERROR ("AddToKnownSSIDs Failed"); + GVariant **outResult = NULL; + if (!nm_client_add_connection2_finish(NM_CLIENT(client), result, outResult, &error)) { + NMLOG_ERROR("AddToKnownSSIDs Failed"); _wifiManager->isSuccess = false; } else { - NMLOG_DEBUG ("AddToKnownSSIDs is success"); + NMLOG_INFO("AddToKnownSSIDs success"); _wifiManager->isSuccess = true; } @@ -672,129 +718,108 @@ namespace WPEFramework bool wifiManager::addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo ssidinfo) { + isSuccess = false; + NMConnection *m_connection = NULL; + if(!createClientNewConnection()) return false; - NMSettingWirelessSecurity *nmSettingsWifiSec; - NMSettingWireless *nmSettingsWifi; - const char *uuid = nm_utils_uuid_generate(); + NMDevice *device = getNmDevice(); + if(device == NULL) + return false; - nmSettingsWifiSec = (NMSettingWirelessSecurity *)nm_setting_wireless_security_new(); - NMSettingConnection *nmConnSec = (NMSettingConnection *)nm_setting_connection_new(); - g_object_set(G_OBJECT(nmConnSec), - NM_SETTING_CONNECTION_UUID, - uuid, - NM_SETTING_CONNECTION_ID, - ssidinfo.ssid.c_str(), - NM_SETTING_CONNECTION_TYPE, - "802-11-wireless", - NULL); - NMConnection *connection = nm_simple_connection_new(); - nm_connection_add_setting(connection, NM_SETTING(nmConnSec)); - nmSettingsWifi = (NMSettingWireless *)nm_setting_wireless_new(); - GString *ssidStr = g_string_new(ssidinfo.ssid.c_str()); - g_object_set(G_OBJECT(nmSettingsWifi), NM_SETTING_WIRELESS_SSID, ssidStr, NULL); - - nm_connection_add_setting(connection, NM_SETTING(nmSettingsWifi)); - nmSettingsWifiSec = (NMSettingWirelessSecurity *)nm_setting_wireless_security_new(); - // TODO chek different securtity mode and portocol and add settings - switch(ssidinfo.security) + const GPtrArray *availableConnections = nm_device_get_available_connections(device); + for (guint i = 0; i < availableConnections->len; i++) { - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_TKIP: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_TKIP: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE: + NMConnection *connection = static_cast(g_ptr_array_index(availableConnections, i)); + const char *connId = nm_connection_get_id(NM_CONNECTION(connection)); + if (connId != NULL && strcmp(connId, ssidinfo.ssid.c_str()) == 0) { - g_object_set(G_OBJECT(nmSettingsWifiSec), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,"wpa-psk", NULL); - if(!ssidinfo.passphrase.empty()) - g_object_set(G_OBJECT(nmSettingsWifiSec), NM_SETTING_WIRELESS_SECURITY_PSK, ssidinfo.passphrase.c_str(), NULL); - break; + m_connection = g_object_ref(connection); } - case Exchange::INetworkManager::WIFI_SECURITY_NONE: - NMLOG_INFO("open wifi network configuration"); - break; - default: + } + + if (NM_IS_REMOTE_CONNECTION(m_connection)) + { + if(!connectionBuilder(ssidinfo, m_connection)) { - NMLOG_WARNING("connection wifi securtity type not supported"); + NMLOG_ERROR("connection builder failed"); return false; } - } - - nm_connection_add_setting(connection, NM_SETTING(nmSettingsWifiSec)); - nm_client_add_connection_async(client, connection, true, NULL, addToKnownSSIDsCb, this); - //wait(loop); - // TODO change to GmainLoooprun - g_main_loop_unref(loop); - return isSuccess; - } - - static void removeKnownSSIDCb(GObject *client, GAsyncResult *result, gpointer user_data) - { - GError *error = NULL; - wifiManager *_wifiManager = (static_cast(user_data)); - NMRemoteConnection *connection = NM_REMOTE_CONNECTION(client); - if (!nm_remote_connection_delete_finish(connection, result, &error)) { - NMLOG_ERROR("RemoveKnownSSID failed %s", error->message); - _wifiManager->isSuccess = false; + NMLOG_DEBUG("update exsisting connection '%s' ", ssidinfo.ssid.c_str()); + GVariant *connSettings = nm_connection_to_dbus(m_connection, NM_CONNECTION_SERIALIZE_ALL); + nm_remote_connection_update2(NM_REMOTE_CONNECTION(m_connection), + connSettings, + NM_SETTINGS_UPDATE2_FLAG_TO_DISK, + NULL, + NULL, + addToKnownSSIDsUpdateCb, + this); } else { - NMLOG_INFO ("RemoveKnownSSID is success"); - _wifiManager->isSuccess = true; + NMLOG_DEBUG("creating new connection '%s' ", ssidinfo.ssid.c_str()); + m_connection = nm_simple_connection_new(); + if(!connectionBuilder(ssidinfo, m_connection)) + { + NMLOG_ERROR("connection builder failed"); + return false; + } + createNewConnection = true; + GVariant *connSettings = nm_connection_to_dbus(m_connection, NM_CONNECTION_SERIALIZE_ALL); + nm_client_add_connection2(client, + connSettings, + NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK, + NULL, TRUE, NULL, + addToKnownSSIDsCb, this); } - - g_main_loop_quit(_wifiManager->loop); + wait(loop); + return isSuccess; } bool wifiManager::removeKnownSSID(const string& ssid) { + NMConnection *m_connection = NULL; + isSuccess = false; if(!createClientNewConnection()) return false; if(ssid.empty()) + { + NMLOG_ERROR("ssid is empty"); return false; - isSuccess = false; - - NMRemoteConnection* remoteConnection; - const GPtrArray* connections = nm_client_get_connections(client); + } - for (guint i = 0; i < connections->len; i++) + const GPtrArray *allconnections = nm_client_get_connections(client); + for (guint i = 0; i < allconnections->len; i++) { - remoteConnection = NM_REMOTE_CONNECTION(connections->pdata[i]); - NMConnection *connection = NM_CONNECTION(connections->pdata[i]); - if (NM_IS_SETTING_WIRELESS(nm_connection_get_setting_wireless(connection))) + NMConnection *connection = static_cast(g_ptr_array_index(allconnections, i)); + if (!NM_IS_SETTING_WIRELESS(nm_connection_get_setting_wireless(connection))) + continue; // if not wireless connection skipt + const char *connId = nm_connection_get_id(NM_CONNECTION(connection)); + if(connId == NULL) + continue; + NMLOG_DEBUG("wireless connection '%s'", connId); + if (strcmp(connId, ssid.c_str()) == 0) { - GBytes *ssidBytes = nm_setting_wireless_get_ssid(nm_connection_get_setting_wireless(connection)); - if (ssidBytes) + m_connection = g_object_ref(connection); + if (NM_IS_REMOTE_CONNECTION(m_connection)) { - gsize ssidSize; - const guint8 *ssidData = static_cast(g_bytes_get_data(ssidBytes, &ssidSize)); - std::string ssidstr(reinterpret_cast(ssidData), ssidSize); - if (ssid == ssidstr) - { - //nm_remote_connection_delete_async(remoteConnection, NULL, removeKnownSSIDCb, this); - // TODO add async - GError *error = NULL; - nm_remote_connection_delete(remoteConnection, NULL, &error); - if (error) - { - NMLOG_ERROR("RemoveKnownSSID failed %s", error->message); - g_error_free(error); - } - else - { - NMLOG_INFO("RemoveKnownSSID is success %s", ssid.c_str()); - isSuccess = true; - } - break; // if remove all connection with same ssid not to break - } + NMLOG_INFO("deleting '%s' connection...", ssid.c_str()); + nm_remote_connection_delete_async(NM_REMOTE_CONNECTION(m_connection), + NULL, + removeKnownSSIDCb, + this); } + wait(loop); + break; // multiple connection with same name not handiled } } - + + if(!m_connection) + NMLOG_INFO("'%s' no such connection profile", ssid.c_str()); + return isSuccess; } @@ -856,7 +881,7 @@ namespace WPEFramework g_main_loop_quit(_wifiManager->loop); } - bool wifiManager::wifiScanRequest(std::string frequency, std::string ssidReq) + bool wifiManager::wifiScanRequest(std::string ssidReq) { if(!createClientNewConnection()) return false; @@ -866,7 +891,7 @@ namespace WPEFramework return false; } isSuccess = false; - if(!ssidReq.empty()) + if(!ssidReq.empty() && ssidReq != "null") { NMLOG_INFO("staring wifi scanning .. %s", ssidReq.c_str()); GVariantBuilder builder, array_builder; @@ -877,7 +902,6 @@ namespace WPEFramework g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (const guint8 *) ssidReq.c_str(), ssidReq.length(), 1) ); g_variant_builder_add(&builder, "{sv}", "ssids", g_variant_builder_end(&array_builder)); - g_variant_builder_add(&builder, "{sv}", "hidden", g_variant_new_boolean(TRUE)); options = g_variant_builder_end(&builder); nm_device_wifi_request_scan_options_async(wifiDevice, options, NULL, wifiScanCb, this); } diff --git a/NetworkManagerGnomeWIFI.h b/NetworkManagerGnomeWIFI.h index 9ad556b8e..4a6462256 100644 --- a/NetworkManagerGnomeWIFI.h +++ b/NetworkManagerGnomeWIFI.h @@ -46,8 +46,8 @@ namespace WPEFramework bool wifiDisconnect(); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); bool wifiConnect(Exchange::INetworkManager::WiFiConnectTo wifiData); - bool wifiScanRequest(std::string frequency, std::string ssidReq = ""); - bool isWifiScannedRecently(int timelimitInSec = 10); // default 10 sec as shotest scanning interval + bool wifiScanRequest(std::string ssidReq = ""); + bool isWifiScannedRecently(int timelimitInSec = 5); // default 10 sec as shotest scanning interval bool getKnownSSIDs(std::list& ssids); bool addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo ssidinfo); bool removeKnownSSID(const string& ssid); diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 9b0a8ed38..8feedf50b 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -723,7 +723,7 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::WiFiConnectTo ssid{}; - NMLOG_INFO("Entry to %s\n", __FUNCTION__); + NMLOG_INFO("Entry to %s", __FUNCTION__); if (parameters.HasLabel("ssid") && parameters.HasLabel("passphrase")) { @@ -764,7 +764,7 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::WiFiConnectTo ssid{}; - NMLOG_INFO("Entry to %s\n", __FUNCTION__); + NMLOG_INFO("Entry to %s", __FUNCTION__); if (parameters.HasLabel("ssid")) ssid.ssid = parameters["ssid"].String(); diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 517e135f0..8099a3cc3 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -825,7 +825,7 @@ namespace WPEFramework strncpy(iarmData.interface, "ETHERNET", INTERFACE_SIZE); else if (!interface.empty()) { - NMLOG_ERROR("Given interface (%s) is NOT supported\n", interface.c_str()); + NMLOG_ERROR("Given interface (%s) is NOT supported", interface.c_str()); return Core::ERROR_NOT_SUPPORTED; } diff --git a/WiFiSignalStrengthMonitor.cpp b/WiFiSignalStrengthMonitor.cpp index 09b33cc22..27243b3b3 100644 --- a/WiFiSignalStrengthMonitor.cpp +++ b/WiFiSignalStrengthMonitor.cpp @@ -28,7 +28,7 @@ namespace WPEFramework FILE *fp = popen(command, "r"); if (!fp) { - NMLOG_ERROR("Failed in getting output from command %s \n",command); + NMLOG_ERROR("Failed in getting output from command %s",command); return keystr; } From 3d54c2780d6f2582fde62cad51b2be5cdccd32c1 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Sun, 17 Nov 2024 20:56:00 -0500 Subject: [PATCH 039/271] Revert "Implement Fossid Scan to NetworkManager (#33)" (#35) This reverts commit 04bce90e2197a1bcc12ab5054ffc6d1dbf1fc144. --- ...id_integration_stateless_diffscan_target_repo.yml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 .github/workflows/fossid_integration_stateless_diffscan_target_repo.yml diff --git a/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml b/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml deleted file mode 100644 index da02b8b4f..000000000 --- a/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: Fossid Stateless Diff Scan - -on: pull_request - -jobs: - call-fossid-workflow: - uses: rdkcentral/build_tools_workflows/.github/workflows/fossid_integration_stateless_diffscan.yml@develop - secrets: - FOSSID_CONTAINER_USERNAME: ${{ secrets.FOSSID_CONTAINER_USERNAME }} - FOSSID_CONTAINER_PASSWORD: ${{ secrets.FOSSID_CONTAINER_PASSWORD }} - FOSSID_HOST_USERNAME: ${{ secrets.FOSSID_HOST_USERNAME }} - FOSSID_HOST_TOKEN: ${{ secrets.FOSSID_HOST_TOKEN }} From 41834e2e85089d9ffa9c739c9b31de373284c461 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Tue, 19 Nov 2024 22:13:49 +0530 Subject: [PATCH 040/271] DELIA-66876 : Fxing onWifiSignalThresholdChanged and onDefaultInterfaceChanged EventData (#36) * The onWifiSignalThresholdChanged and onDefaultInterfaceChanged events are posted with empty/null event data. Fixing it * Updated the release version --- CMakeLists.txt | 2 +- LegacyPlugin_NetworkAPIs.cpp | 12 ++++++------ LegacyPlugin_WiFiManagerAPIs.cpp | 10 +++++----- NetworkManager.json | 2 +- WiFiSignalStrengthMonitor.cpp | 7 +++---- docs/NetworkManagerPlugin.md | 4 ++-- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eb91a4bd9..e2c1dacb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) set(VERSION_MINOR 5) -set(VERSION_PATCH 1) +set(VERSION_PATCH 2) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) add_compile_definitions(NETWORKMANAGER_MINOR_VERSION=${VERSION_MINOR}) diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index 64a6c04f4..1919c3b14 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -1014,10 +1014,10 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { { JsonObject legacyParams; - legacyParams["oldInterfaceName"] = getInterfaceNameToType(parameters["oldInterfaceName"].String()); - legacyParams["newInterfaceName"] = getInterfaceNameToType(parameters["newInterfaceName"].String()); + legacyParams["oldInterfaceName"] = getInterfaceNameToType(parameters["prevActiveInterface"].String()); + legacyParams["newInterfaceName"] = getInterfaceNameToType(parameters["currentActiveInterface"].String()); - m_defaultInterface = parameters["newInterfaceName"].String(); + m_defaultInterface = parameters["currentActiveInterface"].String(); string json; legacyParams.ToString(json); @@ -1032,7 +1032,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { JsonObject legacyParams; legacyParams["interface"] = getInterfaceNameToType(parameters["interface"].String()); - if (parameters["isIPv6"].Boolean()) + if (parameters["ipversion"].String() == "IPv6") { legacyParams["ip6Address"] = parameters["ipaddress"]; } @@ -1049,8 +1049,8 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { Notify("onIPAddressStatusChanged", legacyParams); - if ("ACQUIRED" == parameters["status"].String()) - m_defaultInterface = parameters["interface"].String(); + // if ("ACQUIRED" == parameters["status"].String()) + // m_defaultInterface = parameters["interface"].String(); return; } diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index ba0c64278..5dada6b22 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -697,7 +697,7 @@ namespace WPEFramework } } else - NMLOG_WARNING("Ignoring %s\n", __FUNCTION__); + NMLOG_WARNING("Ignoring %s", __FUNCTION__); return; } @@ -710,7 +710,7 @@ namespace WPEFramework if(_gWiFiInstance) _gWiFiInstance->Notify("onAvailableSSIDs", parameters); else - NMLOG_WARNING("Ignoring %s\n", __FUNCTION__); + NMLOG_WARNING("Ignoring %s", __FUNCTION__); return; } @@ -718,8 +718,8 @@ namespace WPEFramework void WiFiManager::onWiFiSignalStrengthChange(const JsonObject& parameters) { JsonObject legacyParams; - legacyParams["signalStrength"] = parameters["signalQuality"]; - legacyParams["strength"] = parameters["signalLevel"]; + legacyParams["signalStrength"] = parameters["strength"]; + legacyParams["strength"] = parameters["quality"]; string json; legacyParams.ToString(json); @@ -727,7 +727,7 @@ namespace WPEFramework if (_gWiFiInstance) _gWiFiInstance->Notify("onWifiSignalThresholdChanged", legacyParams); else - NMLOG_WARNING("Ignoring %s\n", __FUNCTION__); + NMLOG_WARNING("Ignoring %s", __FUNCTION__); return; } diff --git a/NetworkManager.json b/NetworkManager.json index e7f5c534a..fc96137ed 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json", - "version": "0.5.1" + "version": "0.5.2" }, "definitions": { "success": { diff --git a/WiFiSignalStrengthMonitor.cpp b/WiFiSignalStrengthMonitor.cpp index 27243b3b3..32aaa4c95 100644 --- a/WiFiSignalStrengthMonitor.cpp +++ b/WiFiSignalStrengthMonitor.cpp @@ -54,8 +54,8 @@ namespace WPEFramework ssid = retrieveValues(ssid_command, "ssid", buff, sizeof (buff)); if (ssid.empty()) { - NMLOG_ERROR("ssid is empty"); quality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; + strengthOut = "0.00"; return; } @@ -71,6 +71,7 @@ namespace WPEFramework if (signalStrengthOut == 0.0f) { quality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; + strengthOut = "0.00"; } else if (signalStrengthOut >= signalStrengthThresholdExcellent && signalStrengthOut < 0) { @@ -100,14 +101,12 @@ namespace WPEFramework isRunning = true; monitorThread = std::thread(&WiFiSignalStrengthMonitor::monitorThreadFunction, this, interval); monitorThread.detach(); - std::thread::id threadId = monitorThread.get_id(); - NMLOG_INFO("Thread started with interval: %d seconds", interval); } void WiFiSignalStrengthMonitor::monitorThreadFunction(int interval) { static Exchange::INetworkManager::WiFiSignalQuality oldSignalQuality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; - NMLOG_INFO("WiFiSignalStrengthMonitor thread started !"); + NMLOG_INFO("WiFiSignalStrengthMonitor thread started ! (%d)", interval); while (!stopThread) { string ssid = ""; diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 0a48ddfbc..f8a41b66a 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.5.1** +**Version: 0.5.2** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.5.1). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.5.2). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From ab7ae16280fb1ca08adcd71701c8f851ef3ffa12 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 20 Nov 2024 10:23:43 -0500 Subject: [PATCH 041/271] DELIA-66893 - GetInterfaceState is not working (#37) Reason for change: GetInterfaceState is using the SetInterfaceState networkmanager implementation call instead of GetInterfaceState call. Modified the same. Test Procedure: Check with curl commands Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR --- NetworkManagerJsonRpc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 8feedf50b..5557e498f 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -271,7 +271,7 @@ namespace WPEFramework if ("wlan0" != interface && "eth0" != interface) rc = Core::ERROR_BAD_REQUEST; else if (_networkManager) - rc = _networkManager->SetInterfaceState(interface, enabled); + rc = _networkManager->GetInterfaceState(interface, enabled); else rc = Core::ERROR_UNAVAILABLE; From 516986b1019127c3561ca2a96f058c2a75263061 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 21 Nov 2024 20:11:26 +0530 Subject: [PATCH 042/271] RDKERDKE-353 WiFi is connected on bootup even if WiFi option was disabled before reboot (#38) -) set interface api updated -) onavailable ssid sterngth renamed -) removed unused variable --- NetworkManagerGnomeEvents.cpp | 66 +++++++++++------ NetworkManagerGnomeEvents.h | 3 +- NetworkManagerGnomeProxy.cpp | 136 ++++++++++++++++++---------------- NetworkManagerGnomeUtils.cpp | 24 +++--- NetworkManagerGnomeWIFI.cpp | 96 +++++++++++++++++++++--- NetworkManagerGnomeWIFI.h | 1 + 6 files changed, 215 insertions(+), 111 deletions(-) diff --git a/NetworkManagerGnomeEvents.cpp b/NetworkManagerGnomeEvents.cpp index 0e0321fdf..56e94be41 100644 --- a/NetworkManagerGnomeEvents.cpp +++ b/NetworkManagerGnomeEvents.cpp @@ -72,10 +72,14 @@ namespace WPEFramework static void deviceStateChangeCb(NMDevice *device, GParamSpec *pspec, NMEvents *nmEvents) { + static bool isEthDisabled = false; + static bool isWlanDisabled = false; + if(device == nullptr) + return; NMDeviceState deviceState; deviceState = nm_device_get_state(device); std::string ifname = nm_device_get_iface(device); - if(ifname == nmEvents->ifnameWlan0) + if(ifname == nmUtils::wlanIface()) { if(!NM_IS_DEVICE_WIFI(device)) { NMLOG_FATAL("not a wifi device !"); @@ -118,19 +122,24 @@ namespace WPEFramework case NM_DEVICE_STATE_UNKNOWN: wifiState = "WIFI_STATE_UNINSTALLED"; GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_UNINSTALLED); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::wlanIface()); break; case NM_DEVICE_STATE_UNMANAGED: wifiState = "WIFI_STATE_DISABLED"; GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_DISABLED); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::wlanIface()); + isWlanDisabled = true; break; case NM_DEVICE_STATE_UNAVAILABLE: case NM_DEVICE_STATE_DISCONNECTED: wifiState = "WIFI_STATE_DISCONNECTED"; GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_DISCONNECTED); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_DOWN, nmUtils::wlanIface()); break; case NM_DEVICE_STATE_PREPARE: wifiState = "WIFI_STATE_PAIRING"; GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_PAIRING); + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_UP, nmUtils::wlanIface()); break; case NM_DEVICE_STATE_CONFIG: wifiState = "WIFI_STATE_CONNECTING"; @@ -159,18 +168,27 @@ namespace WPEFramework wifiState = "Un handiled: " ; wifiState += std::to_string(deviceState); } + + if(isWlanDisabled & deviceState > NM_DEVICE_STATE_UNMANAGED) + { + isWlanDisabled = false; + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, nmUtils::wlanIface()); + } + + break; } } NMLOG_DEBUG("wifi state: %s", wifiState.c_str()); } - else if(ifname == nmEvents->ifnameEth0) + else if(ifname == nmUtils::ethIface()) { switch (deviceState) { case NM_DEVICE_STATE_UNKNOWN: case NM_DEVICE_STATE_UNMANAGED: - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_DISABLED, nmUtils::ethIface()); - break; + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::ethIface()); + isEthDisabled = true; + break; case NM_DEVICE_STATE_UNAVAILABLE: case NM_DEVICE_STATE_DISCONNECTED: GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_DOWN, nmUtils::ethIface()); @@ -187,10 +205,15 @@ namespace WPEFramework default: NMLOG_WARNING("Unhandiled state change %d", deviceState); } + + if(isEthDisabled & deviceState > NM_DEVICE_STATE_UNMANAGED) + { + isEthDisabled = false; + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, nmUtils::ethIface()); + } } NMLOG_DEBUG("%s state: (%d)", ifname.c_str(), deviceState); - } static void ip4ChangedCb(NMIPConfig *ipConfig, GParamSpec *pspec, gpointer userData) @@ -282,15 +305,15 @@ namespace WPEFramework if( ((device != NULL) && NM_IS_DEVICE(device)) ) { std::string ifname = nm_device_get_iface(device); - if(ifname == nmEvents->ifnameWlan0) { + if(ifname == nmUtils::wlanIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, nmUtils::wlanIface()); } - else if(ifname == nmEvents->ifnameEth0) { + else if(ifname == nmUtils::ethIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, nmUtils::ethIface()); } /* ip events added only for eth0 and wlan0 */ - if((ifname == nmEvents->ifnameEth0) || (ifname == nmEvents->ifnameWlan0)) + if(ifname == nmUtils::ethIface() || ifname == nmUtils::wlanIface()) { g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(deviceStateChangeCb), nmEvents); // TODO call notify::" NM_DEVICE_ACTIVE_CONNECTION if needed @@ -314,11 +337,11 @@ namespace WPEFramework if( ((device != NULL) && NM_IS_DEVICE(device)) ) { std::string ifname = nm_device_get_iface(device); - if(ifname == nmEvents->ifnameWlan0) { + if(ifname == nmUtils::wlanIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::wlanIface()); g_signal_handlers_disconnect_by_func(device, (gpointer)deviceStateChangeCb, nmEvents); } - else if(ifname == nmEvents->ifnameEth0) { + else if(ifname == nmUtils::ethIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::ethIface()); g_signal_handlers_disconnect_by_func(device, (gpointer)deviceStateChangeCb, nmEvents); } @@ -383,11 +406,11 @@ namespace WPEFramework NMDevice *device = NM_DEVICE(g_ptr_array_index(devices, count)); if( ((device != NULL) && NM_IS_DEVICE(device)) ) { - g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(deviceStateChangeCb), nmEvents); - //g_signal_connect(device, "notify::" NM_DEVICE_ACTIVE_CONNECTION, G_CALLBACK(deviceActiveConnChangeCb), NULL); std::string ifname = nm_device_get_iface(device); - if((ifname == nmEvents->ifnameEth0) || (ifname == nmEvents->ifnameWlan0)) /* ip events added only for eth0 and wlan0 */ + if((ifname == nmUtils::ethIface()) || (ifname == nmUtils::wlanIface())) { + deviceStateChangeCb(device, nullptr, nullptr); //posting event if interface already connected + g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(deviceStateChangeCb), nmEvents); NMIPConfig *ipv4Config = nm_device_get_ip4_config(device); NMIPConfig *ipv6Config = nm_device_get_ip6_config(device); if (ipv4Config) { @@ -485,8 +508,6 @@ namespace WPEFramework return; } _nmEventInstance = this; - nmEvents.ifnameEth0 = nmUtils::ethIface(); - nmEvents.ifnameWlan0 = nmUtils::wlanIface(); } /* Gnome networkmanger new events */ @@ -506,7 +527,7 @@ namespace WPEFramework void GnomeNetworkManagerEvents::onInterfaceStateChangeCb(uint8_t newState, std::string iface) { - std::string state = ""; + std::string state {}; switch (newState) { case Exchange::INetworkManager::INTERFACE_ADDED: @@ -530,8 +551,9 @@ namespace WPEFramework default: state = "Unknown"; } + NMLOG_DEBUG("%s interface state changed - %s", iface.c_str(), state.c_str()); - if(_instance != nullptr && (iface == _nmEventInstance->nmEvents.ifnameWlan0 || iface == _nmEventInstance->nmEvents.ifnameEth0)) + if(_instance != nullptr && (iface == nmUtils::wlanIface() || iface == nmUtils::ethIface())) _instance->ReportInterfaceStateChange(static_cast(newState), iface); } @@ -607,11 +629,8 @@ namespace WPEFramework } ssidList.ToString(ssidListJson); - if(_nmEventInstance->debugLogs) { - _nmEventInstance->debugLogs = false; - NMLOG_INFO("Number of Access Points Available = %d", static_cast(accessPoints->len)); - NMLOG_DEBUG("Scanned APIs are = %s",ssidListJson.c_str()); - } + NMLOG_INFO("No of AP Available = %d", static_cast(accessPoints->len)); + //NMLOG_DEBUG("Scanned APIs are = %s",ssidListJson.c_str()); if(_nmEventInstance->doScanNotify) { _nmEventInstance->doScanNotify = false; @@ -619,14 +638,13 @@ namespace WPEFramework } } - void GnomeNetworkManagerEvents::setwifiScanOptions(bool doNotify, bool enableLogs) + void GnomeNetworkManagerEvents::setwifiScanOptions(bool doNotify) { doScanNotify.store(doNotify); if(!doScanNotify) { NMLOG_DEBUG("stop periodic wifi scan result notify"); } - debugLogs = enableLogs; } } // Plugin diff --git a/NetworkManagerGnomeEvents.h b/NetworkManagerGnomeEvents.h index d775aee91..69f08bdd4 100644 --- a/NetworkManagerGnomeEvents.h +++ b/NetworkManagerGnomeEvents.h @@ -53,7 +53,7 @@ namespace WPEFramework static GnomeNetworkManagerEvents* getInstance(); bool startNetworkMangerEventMonitor(); void stopNetworkMangerEventMonitor(); - void setwifiScanOptions(bool doNotify, bool enableLogs = false); + void setwifiScanOptions(bool doNotify); private: static void* networkMangerEventMonitor(void *arg); @@ -61,7 +61,6 @@ namespace WPEFramework ~GnomeNetworkManagerEvents(); std::atomicisEventThrdActive = {false}; std::atomicdoScanNotify = {false}; - std::atomicdebugLogs = {false}; NMEvents nmEvents; GThread *eventThrdID; }; diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index b8780aaa0..bf8b66bde 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -224,7 +224,6 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) { - std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); if(client == nullptr) { @@ -232,19 +231,18 @@ namespace WPEFramework return Core::ERROR_RPC_CALL_FAILED; } - if(interface.empty() || (wifiname != interface && ethname != interface)) + if(interface.empty() || (interface != nmUtils::wlanIface() && interface != nmUtils::ethIface())) { NMLOG_ERROR("interface: %s; not valied", interface.c_str()!=nullptr? interface.c_str():"empty"); return Core::ERROR_GENERAL; } - NMDevice *device = nm_client_get_device_by_iface(client, interface.c_str()); - if (device == NULL) { - NMLOG_FATAL("libnm doesn't have device corresponding to %s", interface.c_str()); + if(!wifi->setInterfaceState(interface, enabled)) + { + NMLOG_ERROR("interface state change failed"); return Core::ERROR_GENERAL; } - nm_device_set_managed(device, enabled); NMLOG_INFO("interface %s state: %s", interface.c_str(), enabled ? "enabled" : "disabled"); return Core::ERROR_NONE; } @@ -407,29 +405,40 @@ namespace WPEFramework } result.autoconfig = isAutoConnectEnabled(conn); - if(ipversion.empty() || ipversion == "null" || nmUtils::caseInsensitiveCompare(ipversion, "IPV4")) // default ipversion ipv4 + + if(ipversion.empty() || nmUtils::caseInsensitiveCompare(ipversion, "IPV4")) // default ipversion ipv4 { ip4_config = nm_active_connection_get_ip4_config(conn); NMIPAddress *ipAddr = NULL; std::string ipStr; - if (ip4_config != NULL) { - const GPtrArray *ipByte; - ipByte = nm_ip_config_get_addresses(ip4_config); - for (int i = 0; i < ipByte->len; i++) { - ipAddr = static_cast(ipByte->pdata[i]); - if(ipAddr) - ipStr = nm_ip_address_get_address(ipAddr); - if(!ipStr.empty()) - { - result.ipaddress = nm_ip_address_get_address(ipAddr); - result.prefix = nm_ip_address_get_prefix(ipAddr); - NMLOG_INFO("IPv4 addr: %s/%d", result.ipaddress.c_str(), result.prefix); - result.ipversion = "IPv4"; // if null add as default - } + if (ip4_config == nullptr) { + NMLOG_WARNING("no IPv4 configurtion on %s", interface.c_str()); + return Core::ERROR_GENERAL; + } + + const GPtrArray *ipByte = nullptr; + ipByte = nm_ip_config_get_addresses(ip4_config); + if (ipByte == nullptr) { + NMLOG_WARNING("No IPv4 data found on %s", interface.c_str()); + return Core::ERROR_GENERAL; + } + + for (int i = 0; i < ipByte->len; i++) + { + ipAddr = static_cast(ipByte->pdata[i]); + if(ipAddr) + ipStr = nm_ip_address_get_address(ipAddr); + if(!ipStr.empty()) + { + result.ipaddress = nm_ip_address_get_address(ipAddr); + result.prefix = nm_ip_address_get_prefix(ipAddr); + NMLOG_INFO("IPv4 addr: %s/%d", result.ipaddress.c_str(), result.prefix); + result.ipversion = "IPv4"; // if null add as default } - gateway = nm_ip_config_get_gateway(ip4_config); } + gateway = nm_ip_config_get_gateway(ip4_config); + dnsArr = (char **)nm_ip_config_get_nameservers(ip4_config); dhcp4_config = nm_active_connection_get_dhcp4_config(conn); if(dhcp4_config) @@ -453,54 +462,52 @@ namespace WPEFramework ip6_config = nm_active_connection_get_ip6_config(conn); if(ip6_config == nullptr) { - NMLOG_WARNING("no ipv6 config found"); - rc = Core::ERROR_GENERAL; + NMLOG_WARNING("no IPv6 configurtion on %s", interface.c_str()); + return Core::ERROR_GENERAL; } - else + + std::string ipStr; + const GPtrArray *ipArray = nullptr; + ipArray = nm_ip_config_get_addresses(ip6_config); + for (int i = 0; i < ipArray->len; i++) { - std::string ipStr; - const GPtrArray *ipArray = nullptr; - ipArray = nm_ip_config_get_addresses(ip6_config); - for (int i = 0; i < ipArray->len; i++) + ipAddr = static_cast(ipArray->pdata[i]); + if(ipAddr) + ipStr = nm_ip_address_get_address(ipAddr); + if(!ipStr.empty()) { - ipAddr = static_cast(ipArray->pdata[i]); - if(ipAddr) - ipStr = nm_ip_address_get_address(ipAddr); - if(!ipStr.empty()) - { - if (ipStr.compare(0, 5, "fe80:") == 0 || ipStr.compare(0, 6, "fe80::") == 0) { - result.ula = ipStr; - NMLOG_INFO("link-local ip: %s", result.ula.c_str()); - } - else { - result.prefix = nm_ip_address_get_prefix(ipAddr); - if(result.ipaddress.empty()) // SLAAC mutiple ip not added - result.ipaddress = ipStr; - NMLOG_INFO("global ip %s/%d", ipStr.c_str(), result.prefix); - } + if (ipStr.compare(0, 5, "fe80:") == 0 || ipStr.compare(0, 6, "fe80::") == 0) { + result.ula = ipStr; + NMLOG_INFO("link-local ip: %s", result.ula.c_str()); + } + else { + result.prefix = nm_ip_address_get_prefix(ipAddr); + if(result.ipaddress.empty()) // SLAAC mutiple ip not added + result.ipaddress = ipStr; + NMLOG_INFO("global ip %s/%d", ipStr.c_str(), result.prefix); } } + } - gateway = nm_ip_config_get_gateway(ip6_config); - if(gateway) - result.gateway= gateway; - dnsArr = (char **)nm_ip_config_get_nameservers(ip6_config); - if((*(&dnsArr[0]))!= NULL) - result.primarydns = *(&dnsArr[0]); - if((*(&dnsArr[1]))!=NULL ) - result.secondarydns = *(&dnsArr[1]); - - dhcp6_config = nm_active_connection_get_dhcp6_config(conn); - if(dhcp6_config) - { - dhcpserver = nm_dhcp_config_get_one_option (dhcp6_config, "dhcp_server_identifier"); - if(dhcpserver) { - result.dhcpserver = dhcpserver; - } + gateway = nm_ip_config_get_gateway(ip6_config); + if(gateway) + result.gateway= gateway; + dnsArr = (char **)nm_ip_config_get_nameservers(ip6_config); + if((*(&dnsArr[0]))!= NULL) + result.primarydns = *(&dnsArr[0]); + if((*(&dnsArr[1]))!=NULL ) + result.secondarydns = *(&dnsArr[1]); + + dhcp6_config = nm_active_connection_get_dhcp6_config(conn); + if(dhcp6_config) + { + dhcpserver = nm_dhcp_config_get_one_option (dhcp6_config, "dhcp_server_identifier"); + if(dhcpserver) { + result.dhcpserver = dhcpserver; } - result.ipversion = "IPv6"; - rc = Core::ERROR_NONE; } + result.ipversion = "IPv6"; + rc = Core::ERROR_NONE; } else NMLOG_WARNING("ipversion error IPv4/IPv6"); @@ -518,6 +525,7 @@ namespace WPEFramework } else { NMLOG_DEBUG("Deactivating connection successful"); } + g_main_loop_quit((GMainLoop*)user_data); } // Callback for nm_client_activate_connection_async @@ -644,7 +652,7 @@ namespace WPEFramework uint32_t rc = Core::ERROR_RPC_CALL_FAILED; (void) ssids; - nmEvent->setwifiScanOptions(true, true); + nmEvent->setwifiScanOptions(true); if(wifi->wifiScanRequest(frequency)) rc = Core::ERROR_NONE; return rc; @@ -710,7 +718,7 @@ namespace WPEFramework // Check the last scanning time and if it exceeds 5 sec do a rescanning if(!wifi->isWifiScannedRecently()) { - nmEvent->setwifiScanOptions(false, false); + nmEvent->setwifiScanOptions(false); if(!wifi->wifiScanRequest()) { NMLOG_WARNING("scanning failed but try to connect"); diff --git a/NetworkManagerGnomeUtils.cpp b/NetworkManagerGnomeUtils.cpp index d6099c6d0..63a4a3b0a 100644 --- a/NetworkManagerGnomeUtils.cpp +++ b/NetworkManagerGnomeUtils.cpp @@ -216,20 +216,20 @@ namespace WPEFramework ssidStr = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid)); string ssidString(ssidStr); ssidObj["ssid"] = ssidString; + strength = nm_access_point_get_strength(ap); + apFreq = nm_access_point_get_frequency(ap); + flags = nm_access_point_get_flags(ap); + wpaFlags = nm_access_point_get_wpa_flags(ap); + rsnFlags = nm_access_point_get_rsn_flags(ap); + freq = nmUtils::wifiFrequencyFromAp(apFreq); + security = nmUtils::wifiSecurityModeFromAp(flags, wpaFlags, rsnFlags); + + ssidObj["security"] = security; + ssidObj["strength"] = nmUtils::convertPercentageToSignalStrengtStr(strength); + ssidObj["frequency"] = freq; } else - ssidObj["ssid"] = "---"; // hidden ssid TODO modify - strength = nm_access_point_get_strength(ap); - apFreq = nm_access_point_get_frequency(ap); - flags = nm_access_point_get_flags(ap); - wpaFlags = nm_access_point_get_wpa_flags(ap); - rsnFlags = nm_access_point_get_rsn_flags(ap); - freq = nmUtils::wifiFrequencyFromAp(apFreq); - security = nmUtils::wifiSecurityModeFromAp(flags, wpaFlags, rsnFlags); - - ssidObj["security"] = security; - ssidObj["signalStrength"] = strength; - ssidObj["frequency"] = freq; + NMLOG_DEBUG("hidden ssid found, bssid: %s", nm_access_point_get_bssid(ap)); return ssidObj; } diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index a16b44566..4d665b918 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -236,7 +236,7 @@ namespace WPEFramework NMLOG_DEBUG("bitrate : %s kbit/s", wifiInfo.rate.c_str()); //TODO signal strenght to dBm wifiInfo.strength = std::string(nmUtils::convertPercentageToSignalStrengtStr(strength)); - NMLOG_DEBUG("sterngth: %s %%", wifiInfo.strength.c_str()); + NMLOG_DEBUG("sterngth: %s dbm", wifiInfo.strength.c_str()); wifiInfo.security = static_cast(nmUtils::wifiSecurityModeFromAp(flags, wpaFlags, rsnFlags)); NMLOG_DEBUG("security %s", nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); NMLOG_DEBUG("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); @@ -249,13 +249,13 @@ namespace WPEFramework NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getNmDevice()); if(wifiDevice == NULL) { - NMLOG_DEBUG("NMDeviceWifi * NULL !"); + NMLOG_FATAL("NMDeviceWifi * NULL !"); return false; } NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(wifiDevice); if(activeAP == NULL) { - NMLOG_DEBUG("No active access point found !"); + NMLOG_INFO("No active access point found !"); return false; } else @@ -270,7 +270,7 @@ namespace WPEFramework NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getNmDevice()); if(wifiDevice == NULL) { - NMLOG_DEBUG("NMDeviceWifi * NULL !"); + NMLOG_FATAL("NMDeviceWifi * NULL !"); return false; } @@ -286,7 +286,7 @@ namespace WPEFramework return true; } - static void wifiDisconnectCb(GObject *object, GAsyncResult *result, gpointer user_data) + static void disconnectCb(GObject *object, GAsyncResult *result, gpointer user_data) { NMDevice *device = NM_DEVICE(object); GError *error = NULL; @@ -316,11 +316,11 @@ namespace WPEFramework NMDevice *wifiNMDevice = getNmDevice(); if(wifiNMDevice == NULL) { - NMLOG_ERROR("NMDeviceWifi NULL !"); - return false; + NMLOG_WARNING("wifi state is unmanaged !"); + return true; } - nm_device_disconnect_async(wifiNMDevice, NULL, wifiDisconnectCb, this); + nm_device_disconnect_async(wifiNMDevice, NULL, disconnectCb, this); wait(loop); return isSuccess; } @@ -887,7 +887,7 @@ namespace WPEFramework return false; NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getNmDevice()); if(wifiDevice == NULL) { - NMLOG_DEBUG("NMDeviceWifi * NULL !"); + NMLOG_FATAL("NMDeviceWifi * NULL !"); return false; } isSuccess = false; @@ -993,5 +993,83 @@ namespace WPEFramework return true; } + static void deviceManagedCb(GObject *object, GAsyncResult *result, gpointer user_data) + { + wifiManager *_wifiManager = static_cast(user_data); + GError *error = nullptr; + + if (!nm_client_dbus_set_property_finish(NM_CLIENT(object), result, &error)) { + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free(error); + return; + } + + NMLOG_ERROR("Failed to set Managed property: %s", error->message); + g_error_free(error); + _wifiManager->isSuccess = false; + } else { + NMLOG_DEBUG("Successfully set Managed property."); + _wifiManager->isSuccess = true; + } + + _wifiManager->quit(nullptr); + } + + bool wifiManager::setInterfaceState(std::string interface, bool enabled) + { + isSuccess = false; + NMDevice *device = nullptr; + + if (!createClientNewConnection()) + return false; + + GPtrArray *devices = const_cast(nm_client_get_devices(client)); + if (devices == nullptr) { + NMLOG_ERROR("Failed to get device list."); + return isSuccess; + } + + for (guint j = 0; j < devices->len; j++) { + device = NM_DEVICE(devices->pdata[j]); + const char *ifaceStr = nm_device_get_iface(device); + if (ifaceStr == nullptr) + continue; + if (interface == ifaceStr) { + // NMLOG_DEBUG("Device found: %s", interface.c_str()); + break; + } else { + device = nullptr; + } + } + + if (device == nullptr) + return false; + + NMDeviceState deviceState = nm_device_get_state(device); + + if (enabled) { + NMLOG_DEBUG("Enabling interface..."); + if (deviceState >= NM_DEVICE_STATE_DISCONNECTED) // already enabled + return true; + } else { + NMLOG_DEBUG("Disabling interface..."); + if (deviceState <= NM_DEVICE_STATE_UNMANAGED) // already disabled + return true; + else if (deviceState > NM_DEVICE_STATE_DISCONNECTED) { + nm_device_disconnect_async(device, nullptr, disconnectCb, this); + wait(loop); + sleep(1); // to remove the connection + } + } + + const char *objectPath = nm_object_get_path(NM_OBJECT(device)); + GVariant *value = g_variant_new_boolean(enabled); + + nm_client_dbus_set_property( client, objectPath, NM_DBUS_INTERFACE_DEVICE,"Managed", + value, -1, nullptr, deviceManagedCb, this); + wait(loop); + return isSuccess; + } + } // namespace Plugin } // namespace WPEFramework diff --git a/NetworkManagerGnomeWIFI.h b/NetworkManagerGnomeWIFI.h index 4a6462256..747040156 100644 --- a/NetworkManagerGnomeWIFI.h +++ b/NetworkManagerGnomeWIFI.h @@ -55,6 +55,7 @@ namespace WPEFramework bool wait(GMainLoop *loop, int timeOutMs = 10000); // default maximium set as 10 sec bool initiateWPS(); bool cancelWPS(); + bool setInterfaceState(std::string interface, bool enabled); private: NMDevice *getNmDevice(); From 9a456e3d4dafb5b49f0b232ff074f26c726f6d6c Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:34:50 +0530 Subject: [PATCH 043/271] Release of v0.5.3 (#39) Signed-off-by: cmuhammedrafi --- CMakeLists.txt | 2 +- NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2c1dacb4..0d66c3ec9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) set(VERSION_MINOR 5) -set(VERSION_PATCH 2) +set(VERSION_PATCH 3) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) add_compile_definitions(NETWORKMANAGER_MINOR_VERSION=${VERSION_MINOR}) diff --git a/NetworkManager.json b/NetworkManager.json index fc96137ed..dec2b65e7 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json", - "version": "0.5.2" + "version": "0.5.3" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index f8a41b66a..9713c84d9 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.5.2** +**Version: 0.5.3** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.5.2). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.5.3). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From eb41001ba29e445b377ae8125bd6a8b61ff6868d Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 25 Nov 2024 22:47:41 -0500 Subject: [PATCH 044/271] DELIA-66920 - GetWiFiSignalStrength is not return actual strength (#41) * DELIA-66920 - GetWiFiSignalStrength is not return actual strength Reason for change: Removed the internal mapping and returning the actual strength value Test Procedure: Check with curl command Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR --- NetworkManagerRDKProxy.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 8099a3cc3..c6541f364 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -1261,22 +1261,18 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { else if (signalStrengthOut >= signalStrengthThresholdExcellent && signalStrengthOut < 0) { quality = WIFI_SIGNAL_EXCELLENT; - signalStrength = "100"; } else if (signalStrengthOut >= signalStrengthThresholdGood && signalStrengthOut < signalStrengthThresholdExcellent) { quality = WIFI_SIGNAL_GOOD; - signalStrength = "75"; } else if (signalStrengthOut >= signalStrengthThresholdFair && signalStrengthOut < signalStrengthThresholdGood) { quality = WIFI_SIGNAL_FAIR; - signalStrength = "50"; } else { quality = WIFI_SIGNAL_WEAK; - signalStrength = "25"; } NMLOG_INFO ("GetWiFiSignalStrength success"); From 4888cf4b402e0f319f2f5f4be76204c8584a2bf3 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 26 Nov 2024 15:45:44 -0500 Subject: [PATCH 045/271] RDKE-352 - Modified the WPS API (#40) * RDKE-352 - Modified the WPS API Reason for change: Modified StartWPS API to use wpa_cli and wifiConnect API call to connect with wifi using WPS Test Procedure: Check with StartWPS curl command Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR --- NetworkManagerGnomeWIFI.cpp | 222 ++++++++++++++++++++++++++++-------- NetworkManagerGnomeWIFI.h | 8 ++ 2 files changed, 183 insertions(+), 47 deletions(-) diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 4d665b918..8fb62a70c 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -171,21 +171,22 @@ namespace WPEFramework return wifiDevice; } - bool static getConnectedSSID(NMDeviceWifi *wifiDevice, std::string& ssidin) + bool static getConnectedSSID(NMDevice *device, std::string& ssidin) { GBytes *ssid; - NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(wifiDevice); - if(activeAP == NULL) { - return false; + NMDeviceState device_state = nm_device_get_state(device); + if (device_state == NM_DEVICE_STATE_ACTIVATED) + { + NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(NM_DEVICE_WIFI(device)); + ssid = nm_access_point_get_ssid(activeAP); + gsize size; + const guint8 *ssidData = static_cast(g_bytes_get_data(ssid, &size)); + std::string ssidTmp(reinterpret_cast(ssidData), size); + ssidin = ssidTmp; + NMLOG_INFO("connected ssid: %s", ssidin.c_str()); + return true; } - - ssid = nm_access_point_get_ssid(activeAP); - gsize size; - const guint8 *ssidData = static_cast(g_bytes_get_data(ssid, &size)); - std::string ssidTmp(reinterpret_cast(ssidData), size); - ssidin = ssidTmp; - NMLOG_INFO("connected ssid: %s", ssidin.c_str()); - return true; + return false; } static void getApInfo(NMAccessPoint *AccessPoint, Exchange::INetworkManager::WiFiSSIDInfo &wifiInfo) @@ -584,7 +585,7 @@ namespace WPEFramework return false; std::string activeSSID; - if(getConnectedSSID(NM_DEVICE_WIFI(device), activeSSID)) + if(getConnectedSSID(device, activeSSID)) { if(ssidInfo.ssid == activeSSID) { @@ -944,52 +945,179 @@ namespace WPEFramework return false; } - bool wifiManager::initiateWPS() + void wifiManager::wpsAction() { - Core::IWorkerPool::Instance().Submit(Core::ProxyType(Core::ProxyType::Create([&]() { - const GPtrArray *aps; - int count = 1, wpsConnected = 0; - if(!createClientNewConnection()) + FILE *fp = nullptr; + std::ifstream configFile(WPA_SUPPLICANT_CONF); + std::string line = ""; + std::string securityPattern = "key_mgmt="; + std::string ssidPattern = "ssid="; + std::string passphrasePattern = "psk="; + std::string security = "", ssid = "", passphrase = ""; + Exchange::INetworkManager::WiFiConnectTo wifiData = {}; + std::array buffer = {}; + std::string wpaCliResult = ""; + gboolean wpsConnect = false; + struct timespec startTime = {}, endTime = {}; + long timeDiff = 0; + + if (!g_main_context_acquire(wpsContext)) + { + NMLOG_ERROR("Failed to acquire wpsContext"); return; + } + + g_main_context_push_thread_default(wpsContext); + + std::string wpaCliCommand = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_pbc"; + fp = popen(wpaCliCommand.c_str(), "r"); + if (fp == nullptr) + { + NMLOG_ERROR("WPS failed to connect with the SSID"); + g_main_context_pop_thread_default(wpsContext); + g_main_context_release(wpsContext); + return ; + } + pclose(fp); + std::string wpaCliStatus = WPA_CLI_STATUS; + clock_gettime(CLOCK_MONOTONIC, &startTime); + while(!wpsStop.load()) + { + fp = popen(wpaCliStatus.c_str(), "r"); + if (fp == nullptr) + { + NMLOG_ERROR("WPS not able to fetch the connection status"); + continue; + } + while (fgets(buffer.data(), buffer.size(), fp) != nullptr) + { + wpaCliResult += buffer.data(); + } + wpsConnect = (wpaCliResult.find("wpa_state=COMPLETED") != std::string::npos); + clock_gettime(CLOCK_MONOTONIC, &endTime); + timeDiff = (endTime.tv_sec - startTime.tv_sec); + NMLOG_DEBUG("Time elapsed before getting wifi connected = %ld", timeDiff); + if(wpsConnect || timeDiff > 120) + break; + pclose(fp); + sleep(5); + } + + if(!wpsConnect) + { + g_main_context_pop_thread_default(wpsContext); + g_main_context_release(wpsContext);/* TODO: Need to disconnect the wpa_cli connection, as the libnm is not aware of the connection created by wpa_cli */ + return; + } + + { + if (!configFile.is_open()) + { + NMLOG_ERROR("WPS connected with an SSID but not able to fetch IP address"); + g_main_context_pop_thread_default(wpsContext); + g_main_context_release(wpsContext); + return; + } - sleep(10); /* As we will get the ap info with NM_802_11_AP_FLAGS_WPS_PBC set after pressing the PBC button. - So we are waiting for 10 seconds here*/ - do{ - if(wifiScanRequest("")) + while (std::getline(configFile, line)) { - aps = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(getNmDevice())); - for (guint i = 0; i < aps->len; i++) { - NMAccessPoint *ap = static_cast(g_ptr_array_index(aps, i)); - - guint32 flags = nm_access_point_get_flags(ap); - - NMLOG_INFO("AP Flags: 0x%x\n", flags); - - if (flags & NM_802_11_AP_FLAGS_WPS_PBC) { - Exchange::INetworkManager::WiFiConnectTo wifiData; - GBytes *ssid; - ssid = nm_access_point_get_ssid(ap); - gsize size; - const guint8 *ssidData = static_cast(g_bytes_get_data(ssid, &size)); - std::string ssidTmp(reinterpret_cast(ssidData), size); - wifiData.ssid = ssidTmp.c_str(); - NMLOG_INFO("connected ssid: %s", ssidTmp.c_str()); - if(wifiConnect(wifiData)) - wpsConnected = 1; - break; + size_t pos; + + // Fetch security value + pos = line.find(securityPattern); + if (pos != std::string::npos) + { + pos += securityPattern.length(); + size_t end = line.find(' ', pos); + if (end == std::string::npos) + { + end = line.length(); } + security = line.substr(pos, end - pos); + continue; + } + + // Fetch ssid value + pos = line.find(ssidPattern); + if (pos != std::string::npos) + { + pos += ssidPattern.length(); + size_t end = line.find('"', pos + 1); + if (end == std::string::npos) + { + end = line.length(); + } + ssid = line.substr(pos + 1, end - pos - 1); + continue; + } + + // Fetch passphare value + pos = line.find(passphrasePattern); + if (pos != std::string::npos) + { + pos += passphrasePattern.length(); + size_t end = line.find('"', pos + 1); + if (end == std::string::npos) + { + end = line.length(); + } + passphrase = line.substr(pos + 1, end - pos - 1); + continue; } } - sleep(3); /* Waiting time between successive scan */ - count++; - }while(count <= 3 && !wpsConnected); - NMLOG_INFO("Completed scanning and wpsconnect status = %d", wpsConnected); - }))); + + configFile.close(); + wifiData.ssid = ssid; + wifiData.passphrase = passphrase; + if(security == "WPA-PSK") + wifiData.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES; + else if(security == "WPA2-PSK") + wifiData.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES; + } + if(this->wifiConnect(wifiData)) + NMLOG_INFO("WPS connected successfully"); + else + NMLOG_ERROR("WPS connect failed");/* TODO: Need to disconnect the wpa_cli connection, as the libnm is not aware of the connection created by wpa_cli */ + + g_main_context_pop_thread_default(wpsContext); + g_main_context_release(wpsContext); + if (wpsContext) { + g_main_context_unref(wpsContext); + wpsContext = nullptr; + } + return; + } + + bool wifiManager::initiateWPS() + { + if (!createClientNewConnection()) + return false; + + if(!wpsContext){ + if (wpsThread.joinable()) { + wpsThread.join(); + } + wpsContext = g_main_context_new(); + wpsThread = std::thread(&wifiManager::wpsAction, this); + } + else + NMLOG_INFO("Start WPS is already in progress"); + return true; } bool wifiManager::cancelWPS() { + NMLOG_INFO ("Stop WPS %s", __FUNCTION__); + wpsStop.store(true); + if (wpsThread.joinable()) { + wpsThread.join(); + } + if (wpsContext) { + g_main_context_unref(wpsContext); + wpsContext = nullptr; + } + wpsStop.store(false); return true; } diff --git a/NetworkManagerGnomeWIFI.h b/NetworkManagerGnomeWIFI.h index 747040156..eada5a8a9 100644 --- a/NetworkManagerGnomeWIFI.h +++ b/NetworkManagerGnomeWIFI.h @@ -28,6 +28,10 @@ #include #include #include +#include + +#define WPA_SUPPLICANT_CONF "/opt/secure/wifi/wpa_supplicant.conf" +#define WPA_CLI_STATUS "wpa_cli status" namespace WPEFramework { @@ -55,6 +59,7 @@ namespace WPEFramework bool wait(GMainLoop *loop, int timeOutMs = 10000); // default maximium set as 10 sec bool initiateWPS(); bool cancelWPS(); + void wpsAction(); bool setInterfaceState(std::string interface, bool enabled); private: NMDevice *getNmDevice(); @@ -78,12 +83,15 @@ namespace WPEFramework void operator=(wifiManager const&) = delete; bool createClientNewConnection(); + std::atomic wpsStop = {false}; + std::thread wpsThread; public: NMClient *client; GMainLoop *loop; gboolean createNewConnection; GMainContext *nmContext = nullptr; + GMainContext *wpsContext = nullptr; const char* objectPath; NMDevice *wifidevice; GSource *source; From 9e0e9156e82b3098e39104469c0b24d68c19b880 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 26 Nov 2024 16:11:16 -0500 Subject: [PATCH 046/271] Initialized IPstatus to lost in NetworkManagerInternalEventHandler for IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS (#42) --- NetworkManagerRDKProxy.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index c6541f364..3ad434b0c 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -457,11 +457,12 @@ namespace WPEFramework { IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t *e = (IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t*) data; interface = e->interface; - NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS :: %s -- %s", interface.c_str(), e->ip_address); + NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS: %s - %s - %s", interface.c_str(), e->ip_address, e->acquired?"Acquired":"Lost" +); if(interface == "eth0" || interface == "wlan0") { string ipversion("IPv4"); - Exchange::INetworkManager::IPStatus status; + Exchange::INetworkManager::IPStatus status = Exchange::INetworkManager::IP_LOST; if (e->is_ipv6) ipversion = "IPv6"; From cefc90fc37a794b04556576b87f2745700702310 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 26 Nov 2024 16:12:05 -0500 Subject: [PATCH 047/271] Updated the json and documentation for signal strength as string instead of integer (#43) Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- NetworkManager.json | 4 ++-- docs/NetworkManagerPlugin.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NetworkManager.json b/NetworkManager.json index dec2b65e7..d0cbde9ed 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -1257,8 +1257,8 @@ }, "quality":{ "summary": "Signal strength Quality", - "type": "integer", - "example": 123 + "type": "string", + "example": "Excellent" }, "success":{ "$ref": "#/definitions/success" diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 9713c84d9..44c375b01 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -1650,7 +1650,7 @@ This method takes no parameters. | result | object | | | result.ssid | string | The paired SSID | | result.strength | string | The RSSI value in dBm | -| result.quality | integer | Signal strength Quality | +| result.quality | string | Signal strength Quality | | result.success | boolean | Whether the request succeeded | ### Example @@ -1674,7 +1674,7 @@ This method takes no parameters. "result": { "ssid": "123412341234", "strength": "-27.000000", - "quality": 123, + "quality": "Excellent", "success": true } } From 647c853da6dd29524a0ad032e526c54293932743 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 29 Nov 2024 16:33:15 -0500 Subject: [PATCH 048/271] Release of v0.5.4 Release of v0.5.4 --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ CMakeLists.txt | 2 +- NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 11 ++++++++--- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7b39ff8c..56932775a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,37 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.5.4] - 2024-11-29 +### Fixed +- Fixed documentation of NetworkManager +- Handled IPAddressChange event + +## [0.5.3] - 2024-11-21 +### Fixed +- Fixed GetInterfaceState method +- Fixed bootup events on Gnome backend + +## [0.5.2] - 2024-11-19 +### Fixed +- Fixed Event data for DefaultInterfacechanged & WiFiThresholdChanged +- Fixed GetAvailableInterfaces on Gnome backend + +## [0.5.1] - 2024-11-15 +### Added +- Implemented WPS support on Gnome Backend +- Implemented L1/L2 unit test support +### Fixed +- Fixed GetIPSettings error +- Fixed IPAddressChange event + +## [0.5.0] - 2024-11-05 +### Added +- Enhanced WiFi Connection Structure to support EAP +- Defined JsonEnum to publish the Events +- Refactored Legacy Plugins to use ComRPC to communicate with NetworkManager +- Documentation Update +- Minor bug fixes + ## [0.4.0] - 2024-10-04 ### Added - Added RDKLogger Integration diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d66c3ec9..8b5ba9d93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) set(VERSION_MINOR 5) -set(VERSION_PATCH 3) +set(VERSION_PATCH 4) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) add_compile_definitions(NETWORKMANAGER_MINOR_VERSION=${VERSION_MINOR}) diff --git a/NetworkManager.json b/NetworkManager.json index d0cbde9ed..79d08ef44 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -1242,7 +1242,7 @@ } }, "GetWiFiSignalStrength":{ - "summary": "Get WiFiSignalStrength of connected SSID.", + "summary": "Get WiFiSignalStrength of connected SSID. The signal quality is identifed based on the signal strength. The possible states are \n* 'Excellent' \n* 'Good' \n* 'Fair' \n* 'Weak' \n", "events":{ "onWiFiSignalStrengthChange" : "Triggered when Wifi signal strength switches between Excellent, Good, Fair, Weak." }, diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 44c375b01..f6914578a 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.5.3** +**Version: 0.5.4** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.5.3). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.5.4). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity @@ -1635,7 +1635,12 @@ This method takes no parameters. ## *GetWiFiSignalStrength [method](#head.Methods)* -Get WiFiSignalStrength of connected SSID. +Get WiFiSignalStrength of connected SSID. The signal quality is identifed based on the signal strength. The possible states are +* 'Excellent' +* 'Good' +* 'Fair' +* 'Weak' +. Also see: [onWiFiSignalStrengthChange](#event.onWiFiSignalStrengthChange) From 3c2a1406b22d7cfc8be5397652117c3ba28b120c Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 29 Nov 2024 16:54:20 -0500 Subject: [PATCH 049/271] Updated Wifi State Updated Wifi State --- NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NetworkManager.json b/NetworkManager.json index 79d08ef44..d18ca0075 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -1242,7 +1242,7 @@ } }, "GetWiFiSignalStrength":{ - "summary": "Get WiFiSignalStrength of connected SSID. The signal quality is identifed based on the signal strength. The possible states are \n* 'Excellent' \n* 'Good' \n* 'Fair' \n* 'Weak' \n", + "summary": "Get WiFiSignalStrength of connected SSID. The signal quality is identifed based on the signal strength. The possible states are \n* 'Excellent' \n* 'Good' \n* 'Fair' \n* 'Weak' \n* 'Disconnected' \n", "events":{ "onWiFiSignalStrengthChange" : "Triggered when Wifi signal strength switches between Excellent, Good, Fair, Weak." }, diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index f6914578a..757fb68f2 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -1640,6 +1640,7 @@ Get WiFiSignalStrength of connected SSID. The signal quality is identifed based * 'Good' * 'Fair' * 'Weak' +* 'Disconnected' . Also see: [onWiFiSignalStrengthChange](#event.onWiFiSignalStrengthChange) From ca90b6ce9430779fc6de3a96edae10877ee16b07 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Tue, 3 Dec 2024 02:29:17 +0530 Subject: [PATCH 050/271] SetIPsettings stuck in Gmailoop (#49) --- NetworkManagerGnomeEvents.cpp | 4 +- NetworkManagerGnomeProxy.cpp | 130 +--------------------- NetworkManagerGnomeUtils.cpp | 14 +-- NetworkManagerGnomeUtils.h | 2 +- NetworkManagerGnomeWIFI.cpp | 204 ++++++++++++++++++++++++++++++++-- NetworkManagerGnomeWIFI.h | 3 +- NetworkManagerJsonRpc.cpp | 41 ++++--- 7 files changed, 229 insertions(+), 169 deletions(-) diff --git a/NetworkManagerGnomeEvents.cpp b/NetworkManagerGnomeEvents.cpp index 56e94be41..c5c5c7233 100644 --- a/NetworkManagerGnomeEvents.cpp +++ b/NetworkManagerGnomeEvents.cpp @@ -624,8 +624,8 @@ namespace WPEFramework { JsonObject ssidObj; ap = static_cast(accessPoints->pdata[i]); - ssidObj = nmUtils::apToJsonObject(ap); - ssidList.Add(ssidObj); + if(nmUtils::apToJsonObject(ap, ssidObj)) + ssidList.Add(ssidObj); } ssidList.ToString(ssidListJson); diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index bf8b66bde..b6145ee47 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -514,136 +514,12 @@ namespace WPEFramework return rc; } - // Callback for nm_client_deactivate_connection_async - static void on_deactivate_complete(GObject *source_object, GAsyncResult *res, gpointer user_data) { - GError *error = NULL; - - // Check if the operation was successful - if (!nm_client_deactivate_connection_finish(NM_CLIENT(source_object), res, &error)) { - NMLOG_DEBUG("Deactivating connection failed: %s", error->message); - g_error_free(error); - } else { - NMLOG_DEBUG("Deactivating connection successful"); - } - g_main_loop_quit((GMainLoop*)user_data); - } - - // Callback for nm_client_activate_connection_async - static void on_activate_complete(GObject *source_object, GAsyncResult *res, gpointer user_data) { - GError *error = NULL; - - // Check if the operation was successful - if (!nm_client_activate_connection_finish(NM_CLIENT(source_object), res, &error)) { - NMLOG_DEBUG("Activating connection failed: %s", error->message); - g_error_free(error); - } else { - NMLOG_DEBUG("Activating connection successful"); - } - - g_main_loop_quit((GMainLoop*)user_data); - } - - /* @brief Set IP Address Of the Interface */ uint32_t NetworkManagerImplementation::SetIPSettings(const string& interface /* @in */, const IPAddress& address /* @in */) { - GMainLoop *g_loop; - g_loop = g_main_loop_new(NULL, FALSE); - uint32_t rc = Core::ERROR_NONE; - if(client == nullptr) - { - NMLOG_WARNING("client connection null"); - return Core::ERROR_GENERAL; - } - const GPtrArray *connections = nm_client_get_connections(client); - NMSettingIP4Config *s_ip4; - NMSettingIP6Config *s_ip6; - NMConnection *conn = NULL; - NMSettingConnection *settings; - NMRemoteConnection *remote_connection; - NMSetting *setting; - const char *uuid; - NMDevice *device = NULL; - const char *spec_object; - - for (guint i = 0; i < connections->len; i++) { - NMConnection *connection = NM_CONNECTION(connections->pdata[i]); - settings = nm_connection_get_setting_connection(connection); - - /* Check if the interface name matches */ - if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) { - conn = connection; - break; - } - } - if (!address.autoconfig) - { - if (nmUtils::caseInsensitiveCompare("IPv4", address.ipversion)) - { - NMSettingIPConfig *ip4_config = nm_connection_get_setting_ip4_config(conn); - if (ip4_config == NULL) - { - ip4_config = (NMSettingIPConfig *)nm_setting_ip4_config_new(); - } - NMIPAddress *ipAddress; - setting = nm_connection_get_setting_by_name(conn, "ipv4"); - ipAddress = nm_ip_address_new(AF_INET, address.ipaddress.c_str(), address.prefix, NULL); - nm_setting_ip_config_clear_addresses(ip4_config); - nm_setting_ip_config_add_address(NM_SETTING_IP_CONFIG(setting), ipAddress); - nm_setting_ip_config_clear_dns(ip4_config); - nm_setting_ip_config_add_dns(ip4_config, address.primarydns.c_str()); - nm_setting_ip_config_add_dns(ip4_config, address.secondarydns.c_str()); - - g_object_set(G_OBJECT(ip4_config), - NM_SETTING_IP_CONFIG_GATEWAY, address.gateway.c_str(), - NM_SETTING_IP_CONFIG_NEVER_DEFAULT, - FALSE, - NULL); - } - else - { - //FIXME : Add IPv6 support here - NMLOG_WARNING("Setting IPv6 is not supported at this point in time. This is just a place holder"); - rc = Core::ERROR_NOT_SUPPORTED; - } - } - else - { - if (nmUtils::caseInsensitiveCompare("IPv4", address.ipversion)) - { - s_ip4 = (NMSettingIP4Config *)nm_setting_ip4_config_new(); - g_object_set(G_OBJECT(s_ip4), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - nm_connection_add_setting(conn, NM_SETTING(s_ip4)); - } - else - { - s_ip6 = (NMSettingIP6Config *)nm_setting_ip6_config_new(); - g_object_set(G_OBJECT(s_ip6), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); - nm_connection_add_setting(conn, NM_SETTING(s_ip6)); - } - } - device = nm_client_get_device_by_iface(client, interface.c_str()); - uuid = nm_connection_get_uuid(conn); - remote_connection = nm_client_get_connection_by_uuid(client, uuid); - NMActiveConnection *active_connection = NULL; - - const GPtrArray *acv_connections = nm_client_get_active_connections(client); - for (guint i = 0; i < acv_connections->len; i++) { - NMActiveConnection *connection1 = NM_ACTIVE_CONNECTION(acv_connections->pdata[i]); - settings = nm_connection_get_setting_connection(NM_CONNECTION(nm_active_connection_get_connection(connection1))); - - /* Check if the interface name matches */ - if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) { - active_connection = connection1; - break; - } - } - - spec_object = nm_object_get_path(NM_OBJECT(active_connection)); - nm_remote_connection_commit_changes(remote_connection, false, NULL, NULL); - nm_client_deactivate_connection_async(client, active_connection, NULL, on_deactivate_complete, NULL); - nm_client_activate_connection_async(client, conn, device, spec_object, NULL, on_activate_complete, g_loop); - g_main_loop_run(g_loop); + uint32_t rc = Core::ERROR_GENERAL; + if(wifi->setIpSettings(interface, address)) + rc = Core::ERROR_NONE; return rc; } diff --git a/NetworkManagerGnomeUtils.cpp b/NetworkManagerGnomeUtils.cpp index 63a4a3b0a..6b10ec2a1 100644 --- a/NetworkManagerGnomeUtils.cpp +++ b/NetworkManagerGnomeUtils.cpp @@ -198,17 +198,15 @@ namespace WPEFramework return freq; } - JsonObject nmUtils::apToJsonObject(NMAccessPoint *ap) + bool nmUtils::apToJsonObject(NMAccessPoint *ap, JsonObject& ssidObj) { - GError *error = NULL; GBytes *ssid = NULL; int strength = 0; std::string freq; int security; guint32 flags, wpaFlags, rsnFlags, apFreq; - JsonObject ssidObj; if(ap == nullptr) - return ssidObj; + return false; ssid = nm_access_point_get_ssid(ap); if (ssid) { @@ -227,11 +225,11 @@ namespace WPEFramework ssidObj["security"] = security; ssidObj["strength"] = nmUtils::convertPercentageToSignalStrengtStr(strength); ssidObj["frequency"] = freq; + return true; } - else - NMLOG_DEBUG("hidden ssid found, bssid: %s", nm_access_point_get_bssid(ap)); - - return ssidObj; + // else + // NMLOG_DEBUG("hidden ssid found, bssid: %s", nm_access_point_get_bssid(ap)); + return false; } void nmUtils::printActiveSSIDsOnly(NMDeviceWifi *wifiDevice) diff --git a/NetworkManagerGnomeUtils.h b/NetworkManagerGnomeUtils.h index f55e808f4..d305fc7fd 100644 --- a/NetworkManagerGnomeUtils.h +++ b/NetworkManagerGnomeUtils.h @@ -41,7 +41,7 @@ namespace WPEFramework static uint8_t wifiSecurityModeFromAp(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); static std::string wifiFrequencyFromAp(guint32 apFreq); static std::string getSecurityModeString(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); - static JsonObject apToJsonObject(NMAccessPoint *ap); + static bool apToJsonObject(NMAccessPoint *ap, JsonObject& ssidObj); static void printActiveSSIDsOnly(NMDeviceWifi *wifiDevice); static NMDeviceState ifaceState(NMClient *client, const char* interface); }; diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 8fb62a70c..22d8a1fc6 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -123,7 +123,7 @@ namespace WPEFramework return true; } - NMDevice* wifiManager::getNmDevice() + NMDevice* wifiManager::getWifiDevice() { NMDevice *wifiDevice = NULL; @@ -248,7 +248,7 @@ namespace WPEFramework if(!createClientNewConnection()) return false; - NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getNmDevice()); + NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getWifiDevice()); if(wifiDevice == NULL) { NMLOG_FATAL("NMDeviceWifi * NULL !"); return false; @@ -269,7 +269,7 @@ namespace WPEFramework if(!createClientNewConnection()) return false; - NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getNmDevice()); + NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getWifiDevice()); if(wifiDevice == NULL) { NMLOG_FATAL("NMDeviceWifi * NULL !"); return false; @@ -315,7 +315,7 @@ namespace WPEFramework if(!createClientNewConnection()) return false; - NMDevice *wifiNMDevice = getNmDevice(); + NMDevice *wifiNMDevice = getWifiDevice(); if(wifiNMDevice == NULL) { NMLOG_WARNING("wifi state is unmanaged !"); return true; @@ -580,7 +580,7 @@ namespace WPEFramework if(!createClientNewConnection()) return false; - NMDevice *device = getNmDevice(); + NMDevice *device = getWifiDevice(); if(device == NULL) return false; @@ -725,7 +725,7 @@ namespace WPEFramework if(!createClientNewConnection()) return false; - NMDevice *device = getNmDevice(); + NMDevice *device = getWifiDevice(); if(device == NULL) return false; @@ -886,7 +886,7 @@ namespace WPEFramework { if(!createClientNewConnection()) return false; - NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getNmDevice()); + NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getWifiDevice()); if(wifiDevice == NULL) { NMLOG_FATAL("NMDeviceWifi * NULL !"); return false; @@ -919,7 +919,7 @@ namespace WPEFramework if (!createClientNewConnection()) return false; - NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getNmDevice()); + NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getWifiDevice()); if (wifiDevice == NULL) { NMLOG_ERROR("Invalid Wi-Fi device."); return false; @@ -1183,6 +1183,7 @@ namespace WPEFramework NMLOG_DEBUG("Disabling interface..."); if (deviceState <= NM_DEVICE_STATE_UNMANAGED) // already disabled return true; + else if (deviceState > NM_DEVICE_STATE_DISCONNECTED) { nm_device_disconnect_async(device, nullptr, disconnectCb, this); wait(loop); @@ -1199,5 +1200,192 @@ namespace WPEFramework return isSuccess; } + static void onActivateComplete(GObject *source_object, GAsyncResult *res, gpointer user_data) + { + GError *error = NULL; + wifiManager *_wifiManager = static_cast(user_data); + NMLOG_DEBUG("activate connection completeing..."); + // Check if the operation was successful + if (!nm_client_activate_connection_finish(NM_CLIENT(source_object), res, &error)) { + NMLOG_DEBUG("Activating connection failed: %s", error->message); + g_error_free(error); + _wifiManager->isSuccess = false; + } else { + NMLOG_DEBUG("Activating connection successful"); + _wifiManager->isSuccess = true; + } + _wifiManager->quit(nullptr); + } + + bool static checkAutoConnectEnabledInIPv4Conn(NMConnection *connection) + { + if(connection == NULL) + return false; + NMSettingIPConfig *ipConfig = nm_connection_get_setting_ip4_config(connection); + if(ipConfig) + { + const char* ipConfMethod = nm_setting_ip_config_get_method (ipConfig); + if(ipConfMethod != NULL && g_strcmp0(ipConfMethod, "auto") == 0) + return true; + else + NMLOG_WARNING("ip configuration: %s", ipConfMethod != NULL? ipConfMethod: "null"); + } + + return false; + } + + bool wifiManager::setIpSettings(const string interface, const Exchange::INetworkManager::IPAddress address) + { + isSuccess = false; + NMConnection *connection = NULL; + NMRemoteConnection *remoteConn = NULL; + NMActiveConnection* activeConnection = NULL; + NMSetting *setting = NULL; + NMDevice *device = NULL; + const char *specObject = NULL; + + if (!createClientNewConnection()) + return false; + + device = nm_client_get_device_by_iface(client, interface.c_str()); + if(device == NULL) + return false; + + if(interface == nmUtils::ethIface()) + { + NMSettingConnection *settings = NULL; + if(device == NULL) + return false; + + const GPtrArray *connections = nm_device_get_available_connections(device); + if (connections == NULL || connections->len == 0) + { + NMLOG_WARNING("no connections availble to edit "); + return false; + } + + for (guint i = 0; i < connections->len; i++) + { + NMConnection *tmpConn = NM_CONNECTION(connections->pdata[i]); + if(tmpConn == nullptr) + continue; + settings = nm_connection_get_setting_connection(connection); + if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) { + connection = tmpConn; + + if (NM_IS_REMOTE_CONNECTION(connection)) { + remoteConn = NM_REMOTE_CONNECTION(connection); + } else { + NMLOG_ERROR("The connection is not a remote connection."); + return false; /* connection and remoteconnection should match */ + } + + NMLOG_DEBUG("ethernet connection found "); + break; + } + } + } + else if(interface == nmUtils::wlanIface()) + { + /* for wifi we need active connection to modify becuse of multiple wifi connection */ + activeConnection = nm_device_get_active_connection(device); + if(activeConnection == NULL) + { + NMLOG_ERROR("no active connection for wifi"); + return false; + } + remoteConn = nm_active_connection_get_connection(activeConnection); + connection = NM_CONNECTION(remoteConn); + } + else + return false; // interface is not eth0 or wlan0 + + if(connection == nullptr) + { + NMLOG_WARNING("not a single connection availble for %s", interface.c_str()); + return false; + } + + if(address.autoconfig) + { + NMSettingIP4Config *sIp4 = nullptr; + NMSettingIP6Config *sIp6 = nullptr; + if (nmUtils::caseInsensitiveCompare("IPv4", address.ipversion)) + { + if(checkAutoConnectEnabledInIPv4Conn(connection)) // already auto connect true connection + { + NMLOG_INFO("Setting IPv4 auto connect enabled"); + return true; // no need to modify + } + sIp4 = (NMSettingIP4Config *)nm_setting_ip4_config_new(); + g_object_set(G_OBJECT(sIp4), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + nm_connection_add_setting(connection, NM_SETTING(sIp4)); + } + else + { + sIp6 = (NMSettingIP6Config *)nm_setting_ip6_config_new(); + g_object_set(G_OBJECT(sIp6), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); + nm_connection_add_setting(connection, NM_SETTING(sIp6)); + } + } + else + { + if (nmUtils::caseInsensitiveCompare("IPv4", address.ipversion)) + { + NMSettingIPConfig *ip4Config = nm_connection_get_setting_ip4_config(connection); + if (ip4Config == nullptr) + { + ip4Config = (NMSettingIPConfig *)nm_setting_ip4_config_new(); + } + NMIPAddress *ipAddress; + setting = nm_connection_get_setting_by_name(connection, "ipv4"); + ipAddress = nm_ip_address_new(AF_INET, address.ipaddress.c_str(), address.prefix, NULL); + nm_setting_ip_config_clear_addresses(ip4Config); + nm_setting_ip_config_add_address(NM_SETTING_IP_CONFIG(setting), ipAddress); + nm_setting_ip_config_clear_dns(ip4Config); + if(!address.primarydns.empty()) + nm_setting_ip_config_add_dns(ip4Config, address.primarydns.c_str()); + if(!address.secondarydns.empty()) + nm_setting_ip_config_add_dns(ip4Config, address.secondarydns.c_str()); + + g_object_set(G_OBJECT(ip4Config),NM_SETTING_IP_CONFIG_GATEWAY, address.gateway.c_str(), NULL); + g_object_set(G_OBJECT(ip4Config),NM_SETTING_IP_CONFIG_NEVER_DEFAULT, FALSE, NULL); + g_object_set(G_OBJECT(ip4Config), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL); + } + else + { + //FIXME : Add IPv6 support here + NMLOG_WARNING("Setting IPv6 is not supported at this point in time. This is just a place holder"); + } + } + + // TODO fix depricated api + GError *error = NULL; + + if (!nm_remote_connection_commit_changes(remoteConn, FALSE, NULL, &error)) { + if (error) { + NMLOG_ERROR("Failed to commit changes to the remote connection: %s", error->message); + g_error_free(error); // Free the GError object after handling it + } else { + NMLOG_ERROR("Failed to commit changes to the remote connection (unknown error)."); + } + return false; + } + + if (activeConnection != NULL) { + specObject = nm_object_get_path(NM_OBJECT(activeConnection)); + GError *deactivate_error = NULL; + // TODO fix depricated api + if (!nm_client_deactivate_connection(client, activeConnection, NULL, &deactivate_error)) { + NMLOG_ERROR("Failed to deactivate connection: %s", deactivate_error->message); + g_clear_error(&deactivate_error); + return false; + } + } + + nm_client_activate_connection_async(client, connection, device, specObject, NULL, onActivateComplete, this); + wait(loop); + return isSuccess; + } } // namespace Plugin } // namespace WPEFramework diff --git a/NetworkManagerGnomeWIFI.h b/NetworkManagerGnomeWIFI.h index eada5a8a9..dcce93ca8 100644 --- a/NetworkManagerGnomeWIFI.h +++ b/NetworkManagerGnomeWIFI.h @@ -61,8 +61,9 @@ namespace WPEFramework bool cancelWPS(); void wpsAction(); bool setInterfaceState(std::string interface, bool enabled); + bool setIpSettings(const string interface, const Exchange::INetworkManager::IPAddress address); private: - NMDevice *getNmDevice(); + NMDevice *getWifiDevice(); private: wifiManager(); diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 5557e498f..bb143f0d1 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -329,33 +329,30 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::IPAddress address{}; - string interface = ""; - string ipversion = ""; + string interface = {}; - if (parameters.HasLabel("interface")) - interface = parameters["interface"].String(); - else - { + if (!parameters.HasLabel("interface") || !parameters.HasLabel("ipversion") || !parameters.HasLabel("autoconfig")) rc = Core::ERROR_BAD_REQUEST; - return rc; - } - - address.autoconfig = parameters["autoconfig"].Boolean(); - if (!address.autoconfig) + else { - address.ipaddress = parameters["ipaddress"].String(); - address.ipversion = parameters["ipversion"].String(); - address.prefix = parameters["prefix"].Number(); - address.gateway = parameters["gateway"].String(); - address.primarydns = parameters["primarydns"].String(); - address.secondarydns = parameters["secondarydns"].String(); - } + interface = parameters["interface"].String(); + address.ipversion = parameters["ipversion"].String(); + address.autoconfig = parameters["autoconfig"].Boolean(); - if (_networkManager) - rc = _networkManager->SetIPSettings(interface, address); - else - rc = Core::ERROR_UNAVAILABLE; + if (!address.autoconfig) + { + address.ipaddress = parameters["ipaddress"].String(); + address.prefix = parameters["prefix"].Number(); + address.gateway = parameters["gateway"].String(); + address.primarydns = parameters["primarydns"].String(); + address.secondarydns = parameters["secondarydns"].String(); + } + if (_networkManager) + rc = _networkManager->SetIPSettings(interface, address); + else + rc = Core::ERROR_UNAVAILABLE; + } returnJson(rc); } From 37195eb065e9b481ea24b3f2cec33642f3fabbf9 Mon Sep 17 00:00:00 2001 From: parvathika <131966254+parvathika@users.noreply.github.com> Date: Tue, 3 Dec 2024 20:14:16 +0530 Subject: [PATCH 051/271] Implement unit test file for connectivity and stun (#45) --- .../test_NetworkManagerConnectivity.cpp | 132 ++++++++++++++++++ .../test_NetworkManagerStunClient.cpp | 69 +++++++++ Tests/unit_test/tests.cmake | 3 + 3 files changed, 204 insertions(+) create mode 100644 Tests/unit_test/test_NetworkManagerConnectivity.cpp create mode 100644 Tests/unit_test/test_NetworkManagerStunClient.cpp diff --git a/Tests/unit_test/test_NetworkManagerConnectivity.cpp b/Tests/unit_test/test_NetworkManagerConnectivity.cpp new file mode 100644 index 000000000..f175a929b --- /dev/null +++ b/Tests/unit_test/test_NetworkManagerConnectivity.cpp @@ -0,0 +1,132 @@ +#include "NetworkManagerImplementation.h" +#include "NetworkManagerConnectivity.h" +#include "WiFiSignalStrengthMonitor.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace WPEFramework; + +class ConnectivityMonitorTest : public ::testing::Test { +protected: + + WPEFramework::Plugin::ConnectivityMonitor cm; + + void SetUp() override { + + } + + void TearDown() override { + + } +}; + + TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_Success) { + int timeout = 30; + bool result = cm.startContinuousConnectivityMonitor(timeout); + EXPECT_TRUE(result); +} +TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_FailureNegativeTimeout) { + int timeout = -1; + bool result = cm.startContinuousConnectivityMonitor(timeout); + EXPECT_TRUE(result); +} +TEST_F(ConnectivityMonitorTest, StartMonitorWithTimeoutLessThanMinimum) { + int timeout = 3; + bool result = cm.startContinuousConnectivityMonitor(timeout); + EXPECT_TRUE(result); +} +TEST_F(ConnectivityMonitorTest, MonitorFailsToStart) { + int timeout = 0; + bool result = cm.startContinuousConnectivityMonitor(timeout); + EXPECT_TRUE(result); +} + +TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_WhenStarted) { + int timeout = 30; + cm.startContinuousConnectivityMonitor(timeout); + bool result = cm.stopContinuousConnectivityMonitor(); + EXPECT_TRUE(result); +} +TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_WhenNotStarted) { + bool result = cm.stopContinuousConnectivityMonitor(); + EXPECT_TRUE(result); +} +TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_AfterMultipleStartsAndStops) { + int timeout = 30; + cm.startContinuousConnectivityMonitor(timeout); + bool result = cm.stopContinuousConnectivityMonitor(); + EXPECT_TRUE(result); + + cm.startContinuousConnectivityMonitor(timeout); + result = cm.stopContinuousConnectivityMonitor(); + EXPECT_TRUE(result); + + cm.startContinuousConnectivityMonitor(timeout); + result = cm.stopContinuousConnectivityMonitor(); + EXPECT_TRUE(result); +} +TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_LongRunningMonitor) { + int timeout = 1000; + cm.startContinuousConnectivityMonitor(timeout); + std::this_thread::sleep_for(std::chrono::seconds(2)); + + bool result = cm.stopContinuousConnectivityMonitor(); + EXPECT_TRUE(result); +} + + TEST_F(ConnectivityMonitorTest, StartMonitor_WithInterfaceStatusTrue) { + bool interfaceStatus = true; + bool result = cm.startConnectivityMonitor(interfaceStatus); + EXPECT_TRUE(result); +} +TEST_F(ConnectivityMonitorTest, StartMonitor_WithInterfaceStatusFalse) { + bool interfaceStatus = false; + bool result = cm.startConnectivityMonitor(interfaceStatus); + EXPECT_TRUE(result); +} +TEST_F(ConnectivityMonitorTest, StartMonitor_NotifyIfAlreadyMonitoring) { + bool interfaceStatus = true; + cm.startConnectivityMonitor(interfaceStatus); + bool result = cm.startConnectivityMonitor(interfaceStatus); + EXPECT_TRUE(result); +} + +TEST_F(ConnectivityMonitorTest, SetEndpoints_Valid) { + std::vector endpoints = {"https://github.com/rdkcentral", "https://github.com/rdkcentral/rdkservices"}; + cm.setConnectivityMonitorEndpoints(endpoints); + EXPECT_EQ(cm.getConnectivityMonitorEndpoints(), endpoints); +} +TEST_F(ConnectivityMonitorTest, SetEndpoints_EmptyList) { + std::vector endpoints; + cm.setConnectivityMonitorEndpoints(endpoints); + EXPECT_TRUE(cm.getConnectivityMonitorEndpoints().empty()); +} +TEST_F(ConnectivityMonitorTest, SetEndpoints_InvalidShortEndpoints) { + std::vector endpoints = {"ab", "htt", "xyz"}; + cm.setConnectivityMonitorEndpoints(endpoints); + EXPECT_TRUE(cm.getConnectivityMonitorEndpoints().empty()); +} +TEST_F(ConnectivityMonitorTest, SetEndpoints_DuplicateEndpoints) { + std::vector endpoints = {"https://github.com", "https://github.com"}; + cm.setConnectivityMonitorEndpoints(endpoints); + EXPECT_EQ(cm.getConnectivityMonitorEndpoints().size(), 2); +} + + + + diff --git a/Tests/unit_test/test_NetworkManagerStunClient.cpp b/Tests/unit_test/test_NetworkManagerStunClient.cpp new file mode 100644 index 000000000..b235eb2da --- /dev/null +++ b/Tests/unit_test/test_NetworkManagerStunClient.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "NetworkManagerStunClient.h" + +using namespace std; +using namespace stun; + +class AddressTest : public ::testing::Test { +protected: + stun::attributes::address ad; + void SetUp() override { + + } + void TearDown() override { + + } +}; + +class ClientTest : public ::testing::Test { +protected: + stun::client cl; + void SetUp() override { + + } + void TearDown() override { + + } +}; + +TEST_F(ClientTest, BindSuccess) { + stun::bind_result result; + bool success = cl.bind("https://github.com/", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); + EXPECT_FALSE(success); + EXPECT_FALSE(result.is_valid()); +} + +TEST_F(ClientTest, BindFailure) { + stun::bind_result result; + bool success = cl.bind("http//tata.com", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); + EXPECT_FALSE(success); + EXPECT_FALSE(result.is_valid()); +} +TEST_F(ClientTest, BindWithInvalidInterface) { + stun::bind_result result; + bool success = cl.bind("https://github.com/", 3478, "invalid_interface", stun::protocol::af_inet, 5000, 10000, result); + EXPECT_FALSE(success); + EXPECT_FALSE(result.is_valid()); +} + diff --git a/Tests/unit_test/tests.cmake b/Tests/unit_test/tests.cmake index 177c02947..82d2cd928 100644 --- a/Tests/unit_test/tests.cmake +++ b/Tests/unit_test/tests.cmake @@ -15,9 +15,12 @@ FetchContent_Declare( FetchContent_MakeAvailable(googletest) add_executable(${UNIT_TEST} Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp + Tests/unit_test/test_NetworkManagerConnectivity.cpp + Tests/unit_test/test_NetworkManagerStunClient.cpp WiFiSignalStrengthMonitor.cpp NetworkManagerLogger.cpp NetworkManagerConnectivity.cpp + NetworkManagerStunClient.cpp ) set_target_properties(${UNIT_TEST} PROPERTIES CXX_STANDARD 11 From da274ffa9dfcd445c23ebf855a27189b20745f52 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Wed, 4 Dec 2024 19:58:41 +0530 Subject: [PATCH 052/271] DELIA-66968 Disable continuous connectivity monitor when Interface is disconnected (#51) * DELIA-66968 Disable continuous connectivity monitor when Interface is disconnected * unit test modified --------- Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- .github/workflows/gnome_unit_test.yml | 2 +- CMakeLists.txt | 2 +- NetworkManagerConnectivity.cpp | 93 +++++++++++-------- NetworkManagerConnectivity.h | 9 +- NetworkManagerGnomeProxy.cpp | 20 ++-- NetworkManagerImplementation.cpp | 33 +++++-- NetworkManagerImplementation.h | 6 ++ NetworkManagerRDKProxy.cpp | 71 ++++++++++++-- .../test_NetworkManagerConnectivity.cpp | 78 +++++++--------- .../test_NetworkManagerStunClient.cpp | 42 +-------- .../test_WiFiSignalStrengthMonitor.cpp | 14 +-- .../{tests.cmake => unit_tests.cmake} | 6 +- 12 files changed, 212 insertions(+), 164 deletions(-) rename Tests/unit_test/{tests.cmake => unit_tests.cmake} (96%) diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index 107e6e455..4dcb52e8b 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -110,7 +110,7 @@ jobs: run: > PATH=${{github.workspace}}/install/usr/bin:${PATH} LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} - tests + unit_tests - name: Generate coverage run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b5ba9d93..592e9915b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,6 +170,6 @@ write_config(PLUGINS LegacyPlugin_NetworkAPIs CLASSNAME Network LOCATOR lib${PLU write_config(PLUGINS LegacyPlugin_WiFiManagerAPIs CLASSNAME WiFiManager LOCATOR lib${PLUGIN_LEGACY_DEPRECATED_WIFI}.so) if(ENABLE_UNIT_TESTING) - include(Tests/unit_test/tests.cmake) + include(Tests/unit_test/unit_tests.cmake) endif(ENABLE_UNIT_TESTING) diff --git a/NetworkManagerConnectivity.cpp b/NetworkManagerConnectivity.cpp index f76c8b4bc..1a4667e1d 100644 --- a/NetworkManagerConnectivity.cpp +++ b/NetworkManagerConnectivity.cpp @@ -158,7 +158,7 @@ namespace WPEFramework curl_easy_setopt(curl_easy_handle, CURLOPT_TIMEOUT_MS, deadline - current_time()); if ((ipversion == CURL_IPRESOLVE_V4) || (ipversion == CURL_IPRESOLVE_V6)) { - NMLOG_DEBUG("curlopt ipversion = %s reqtyp = %s", ipversion == CURL_IPRESOLVE_V4?"ipv4 only":"ipv6 only", headReq? "HEAD":"GET"); + NMLOG_DEBUG("curlopt ipversion = %s reqtyp = %s", ipversion == CURL_IPRESOLVE_V4?"IPv4":"IPv6", headReq? "HEAD":"GET"); curl_easy_setopt(curl_easy_handle, CURLOPT_IPRESOLVE, ipversion); } else @@ -324,10 +324,9 @@ namespace WPEFramework doContinuousMonitor = false; doConnectivityMonitor = false; - gInternetState = nsm_internetState::UNKNOWN; - gIpv4InternetState = nsm_internetState::UNKNOWN; - gIpv6InternetState = nsm_internetState::UNKNOWN; - ginterfaceStatus = false; + m_InternetState = nsm_internetState::UNKNOWN; + m_Ipv4InternetState = nsm_internetState::UNKNOWN; + m_Ipv6InternetState = nsm_internetState::UNKNOWN; } ConnectivityMonitor::~ConnectivityMonitor() @@ -390,15 +389,15 @@ namespace WPEFramework // If monitor connectivity is running take the cache value if ( doContinuousMonitor && (nsm_ipversion::NSM_IPRESOLVE_V4 == ipversion || nsm_ipversion::NSM_IPRESOLVE_WHATEVER == ipversion) - && gIpv4InternetState != nsm_internetState::UNKNOWN ) { - NMLOG_WARNING("Reading Ipv4 internet state cached value %s", getInternetStateString(gIpv4InternetState)); - internetState = gIpv4InternetState; + && m_Ipv4InternetState != nsm_internetState::UNKNOWN ) { + NMLOG_WARNING("Reading Ipv4 internet state cached value %s", getInternetStateString(m_Ipv4InternetState)); + internetState = m_Ipv4InternetState; ipversion = NSM_IPRESOLVE_V4; } else if ( doContinuousMonitor && (nsm_ipversion::NSM_IPRESOLVE_V6 == ipversion || nsm_ipversion::NSM_IPRESOLVE_WHATEVER == ipversion) - && gIpv6InternetState != nsm_internetState::UNKNOWN ) { - NMLOG_WARNING("Reading Ipv6 internet state cached value %s", getInternetStateString(gIpv6InternetState)); - internetState = gIpv6InternetState; + && m_Ipv6InternetState != nsm_internetState::UNKNOWN ) { + NMLOG_WARNING("Reading Ipv6 internet state cached value %s", getInternetStateString(m_Ipv6InternetState)); + internetState = m_Ipv6InternetState; ipversion = NSM_IPRESOLVE_V6; } else @@ -425,6 +424,8 @@ namespace WPEFramework bool ConnectivityMonitor::startContinuousConnectivityMonitor(int timeoutInSeconds) { + if(_instance != nullptr ) + NMLOG_INFO("interface status eth - %s wlan - %s ", _instance->m_ethConnected? "up":"down", _instance->m_wlanConnected? "up":"down"); continuousMonitorTimeout.store(timeoutInSeconds >= NMCONNECTIVITY_MONITOR_MIN_INTERVAL ? timeoutInSeconds : NMCONNECTIVITY_MONITOR_DEFAULT_INTERVAL); if (doContinuousMonitor) { @@ -472,12 +473,11 @@ namespace WPEFramework * --> when IP address accuired * --> when etherenet/wifi disconnected */ - bool ConnectivityMonitor::startConnectivityMonitor(bool interfaceStatus) + bool ConnectivityMonitor::startConnectivityMonitor() { - ginterfaceStatus = interfaceStatus; /* this will give interface status connected/ disconnected */ - gInternetState = UNKNOWN; - gIpv4InternetState = UNKNOWN; - gIpv6InternetState = UNKNOWN; + m_InternetState = nsm_internetState::UNKNOWN; + m_Ipv4InternetState = nsm_internetState::UNKNOWN; + m_Ipv6InternetState = nsm_internetState::UNKNOWN; if (doConnectivityMonitor) { cvConnectivityMonitor.notify_one(); @@ -497,21 +497,26 @@ namespace WPEFramework return false; } - NMLOG_ERROR("connectivity monitor started %d", NMCONNECTIVITY_MONITOR_MIN_INTERVAL); + if(_instance != nullptr) { + NMLOG_INFO("connectivity monitor started %d sec - eth %s - wlan %s", NMCONNECTIVITY_MONITOR_MIN_INTERVAL, + _instance->m_ethConnected? "up":"down", _instance->m_wlanConnected? "up":"down"); + } return true; } void ConnectivityMonitor::notifyInternetStatusChangedEvent(nsm_internetState newInternetState) { + static Exchange::INetworkManager::InternetStatus oldState = Exchange::INetworkManager::InternetStatus::INTERNET_UNKNOWN; if(_instance != nullptr) { - Exchange::INetworkManager::InternetStatus oldState = static_cast(gInternetState.load()); + NMLOG_INFO("notify internet state %s", getInternetStateString(newInternetState)); Exchange::INetworkManager::InternetStatus newState = static_cast(newInternetState); _instance->ReportInternetStatusChange(oldState , newState); - gInternetState = newInternetState; + m_InternetState = newInternetState; + oldState = newState; // 'm_InternetState' not exactly previous state, it may change to unknow when interface changed } else - NMLOG_WARNING("NetworkManagerImplementation Instance NULL notifyInternetStatusChange failed."); + NMLOG_FATAL("NetworkManagerImplementation Instance NULL notifyInternetStatusChange failed."); } void ConnectivityMonitor::continuousMonitorFunction() @@ -524,20 +529,31 @@ namespace WPEFramework do { + if(_instance != nullptr && (!_instance->m_ethConnected && !_instance->m_wlanConnected)) // no wifi no ethernet connected + { + NMLOG_DEBUG("no interface connected; no ccm check"); + m_Ipv4InternetState = NO_INTERNET; + m_Ipv6InternetState = NO_INTERNET; + std::unique_lock lock(connMutex); + cvContinuousMonitor.wait_for(lock, std::chrono::seconds(continuousMonitorTimeout.load())); + ipResolveTyp = NSM_IPRESOLVE_WHATEVER; + continue; + } + if(doConnectivityMonitor) { NMLOG_DEBUG("connectivity monitor running so skiping ccm check"); - gIpv4InternetState = UNKNOWN; - gIpv6InternetState = UNKNOWN; + m_Ipv4InternetState = nsm_internetState::UNKNOWN; + m_Ipv6InternetState = nsm_internetState::UNKNOWN; std::unique_lock lock(connMutex); cvContinuousMonitor.wait_for(lock, std::chrono::seconds(continuousMonitorTimeout.load())); - ipResolveTyp = NSM_IPRESOLVE_WHATEVER; /* some interface change happense*/ + ipResolveTyp = NSM_IPRESOLVE_WHATEVER; /* some interface change happense */ continue; } else if (ipResolveTyp == NSM_IPRESOLVE_WHATEVER) { - nsm_internetState ipV4InternetState = UNKNOWN; - nsm_internetState ipV6InternetState = UNKNOWN; + nsm_internetState ipV4InternetState = nsm_internetState::UNKNOWN; + nsm_internetState ipV6InternetState = nsm_internetState::UNKNOWN; auto curlCheckThrdIpv4 = [&]() { TestConnectivity testInternet(getConnectivityMonitorEndpoints(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, NMCONNECTIVITY_CURL_GET_REQUEST, NSM_IPRESOLVE_V4); @@ -573,17 +589,17 @@ namespace WPEFramework NMCONNECTIVITY_CURL_HEAD_REQUEST, ipResolveTyp); currentInternetState = testInternet.getInternetState(); if(ipResolveTyp == NSM_IPRESOLVE_V4) - gIpv4InternetState = currentInternetState; + m_Ipv4InternetState = currentInternetState; else if(ipResolveTyp == NSM_IPRESOLVE_V6) - gIpv6InternetState = currentInternetState; + m_Ipv6InternetState = currentInternetState; } if (currentInternetState == NO_INTERNET) { - if(gInternetState == FULLY_CONNECTED && notifyPreRetry < NMCONNECTIVITY_NO_INTERNET_RETRY_COUNT) + if(m_InternetState == FULLY_CONNECTED && notifyPreRetry < NMCONNECTIVITY_NO_INTERNET_RETRY_COUNT) { /* it will prevent posting notification */ - currentInternetState = gInternetState; + currentInternetState = m_InternetState; TempInterval = 5; NMLOG_INFO("No internet retrying connection check %d ...", notifyPreRetry); notifyPreRetry++; @@ -601,9 +617,8 @@ namespace WPEFramework TempInterval = continuousMonitorTimeout.load(); } - if(gInternetState != currentInternetState) + if(m_InternetState != currentInternetState) { - NMLOG_INFO("Internet state changed to %s", getInternetStateString(currentInternetState)); /* Notify Internet state change */ notifyInternetStatusChangedEvent(currentInternetState); } @@ -619,8 +634,8 @@ namespace WPEFramework } while(doContinuousMonitor); - gIpv4InternetState = UNKNOWN; - gIpv6InternetState = UNKNOWN; + m_Ipv4InternetState = nsm_internetState::UNKNOWN; + m_Ipv6InternetState = nsm_internetState::UNKNOWN; NMLOG_DEBUG("continous connectivity monitor exit"); } @@ -663,8 +678,8 @@ namespace WPEFramework NMLOG_INFO("Connectivity check retrying %d ...", notifyPreRetry); } - if(gInternetState != UNKNOWN) - currentInternetState = gInternetState; + if(m_InternetState != nsm_internetState::UNKNOWN) + currentInternetState = m_InternetState; TempInterval = 5; } else if(tempInternetState != currentInternetState) // last state have change @@ -681,8 +696,9 @@ namespace WPEFramework doConnectivityMonitor = false; // self exit notifyNow = true; // post current state when retry complete } - else if(ginterfaceStatus) // interface is active and still no internet, continue check every 30 sec + else if(_instance != nullptr && (_instance->m_ethConnected | _instance->m_wlanConnected)) { + /* interface is connected and still no internet, continue check every 30 sec */ TempInterval = NMCONNECTIVITY_CONN_MONITOR_RETRY_INTERVAL; /* notify if retry completed and state stil no internet state */ if(notifyPreRetry == NMCONNECTIVITY_CONN_MONITOR_RETRY_COUNT) @@ -699,10 +715,9 @@ namespace WPEFramework } } - if(gInternetState != currentInternetState || notifyNow) + if(m_InternetState != currentInternetState || notifyNow) { notifyNow = false; - NMLOG_INFO("notify internet state %s", getInternetStateString(currentInternetState)); notifyInternetStatusChangedEvent(currentInternetState); } @@ -719,7 +734,7 @@ namespace WPEFramework } while(doConnectivityMonitor); if(!doContinuousMonitor) - gInternetState = nsm_internetState::UNKNOWN; // no continous monitor running reset to unknow + m_InternetState = nsm_internetState::UNKNOWN; // no continous monitor running reset to unknow NMLOG_DEBUG("initial connectivity monitor exit"); } diff --git a/NetworkManagerConnectivity.h b/NetworkManagerConnectivity.h index 26f256fa4..3a5b215a3 100644 --- a/NetworkManagerConnectivity.h +++ b/NetworkManagerConnectivity.h @@ -114,7 +114,7 @@ namespace WPEFramework ~ConnectivityMonitor(); bool startContinuousConnectivityMonitor(int timeoutInSeconds); bool stopContinuousConnectivityMonitor(); - bool startConnectivityMonitor(bool interfaceStatus); + bool startConnectivityMonitor(); void setConnectivityMonitorEndpoints(const std::vector &endpoints); std::vector getConnectivityMonitorEndpoints(); bool isConnectedToInternet(nsm_ipversion ipversion); @@ -140,10 +140,9 @@ namespace WPEFramework EndpointCache endpointCache; std::mutex endpointMutex; - std::atomic ginterfaceStatus; - std::atomic gInternetState; - std::atomic gIpv4InternetState; - std::atomic gIpv6InternetState; + std::atomic m_InternetState; + std::atomic m_Ipv4InternetState; + std::atomic m_Ipv6InternetState; }; } // namespace Plugin } // namespace WPEFramework diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index b6145ee47..9a00cc82e 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -84,23 +84,25 @@ namespace WPEFramework { NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; Exchange::INetworkManager::InterfaceDetails interface; + interface.mac = nm_device_get_hw_address(device); + deviceState = nm_device_get_state(device); + interface.enabled = (deviceState >= NM_DEVICE_STATE_UNAVAILABLE)? true : false; + if(deviceState > NM_DEVICE_STATE_DISCONNECTED && deviceState < NM_DEVICE_STATE_DEACTIVATING) + interface.connected = true; + else + interface.connected = false; + if(ifaceStr == wifiname) { interface.type = INTERFACE_TYPE_WIFI; interface.name = wifiname; + m_wlanConnected = interface.connected; } if(ifaceStr == ethname) { interface.type = INTERFACE_TYPE_ETHERNET; interface.name = ethname; + m_ethConnected = interface.connected; } - interface.mac = nm_device_get_hw_address(device); - deviceState = nm_device_get_state(device); - interface.enabled = (deviceState >= NM_DEVICE_STATE_UNAVAILABLE) ? true : false; - if(deviceState > NM_DEVICE_STATE_DISCONNECTED && deviceState < NM_DEVICE_STATE_DEACTIVATING){ - interface.connected = true; - m_defaultInterface = interface.name; - } - else - interface.connected = false; + interfaceList.push_back(interface); rc = Core::ERROR_NONE; } diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 7da44a9eb..66b0d0fa2 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -50,6 +50,8 @@ namespace WPEFramework m_stunCacheTimeout = 0; m_defaultInterface = ""; m_publicIP = ""; + m_ethConnected = false; + m_wlanConnected = false; } NetworkManagerImplementation::~NetworkManagerImplementation() @@ -520,13 +522,22 @@ namespace WPEFramework void NetworkManagerImplementation::ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface) { LOG_ENTRY_FUNCTION(); - if(Exchange::INetworkManager::INTERFACE_LINK_DOWN == state) { + if(Exchange::INetworkManager::INTERFACE_LINK_DOWN == state || Exchange::INetworkManager::INTERFACE_REMOVED == state) { // Start the connectivity monitor with 'false' to indicate the interface is down. // The monitor will automatically exit after the retry attempts are completed, posting a 'noInternet' event. - connectivityMonitor.startConnectivityMonitor(false); + if(interface == "eth0") + m_ethConnected = false; + else + m_wlanConnected = false; + connectivityMonitor.startConnectivityMonitor(); } + /* Only the Ethernet connection status is changing here. The WiFi status is updated in the WiFi state callback. */ + if(Exchange::INetworkManager::INTERFACE_LINK_UP == state && interface == "eth0") + m_ethConnected = true; + _notificationLock.Lock(); + NMLOG_INFO("Posting onInterfaceChange %s - %u", interface.c_str(), (unsigned)state); for (const auto callback : _notificationCallbacks) { callback->onInterfaceStateChange(state, interface); } @@ -535,8 +546,8 @@ namespace WPEFramework void NetworkManagerImplementation::ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface) { - NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); _notificationLock.Lock(); + NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); for (const auto callback : _notificationCallbacks) { callback->onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); } @@ -549,11 +560,11 @@ namespace WPEFramework if (Exchange::INetworkManager::IP_ACQUIRED == status) { // Start the connectivity monitor with 'true' to indicate the interface is up. // The monitor will conntinoue even after no internet retry completed, Exit when fully connectd. - connectivityMonitor.startConnectivityMonitor(true); + connectivityMonitor.startConnectivityMonitor(); } - NMLOG_INFO("Posting onIPAddressChange %s", ipaddress.c_str()); _notificationLock.Lock(); + NMLOG_INFO("Posting onIPAddressChange %s - %s", ipaddress.c_str(), interface.c_str()); for (const auto callback : _notificationCallbacks) { callback->onIPAddressChange(interface, ipversion, ipaddress, status); } @@ -562,8 +573,8 @@ namespace WPEFramework void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) { - NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); _notificationLock.Lock(); + NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); for (const auto callback : _notificationCallbacks) { callback->onInternetStatusChange(prevState, currState); } @@ -584,10 +595,15 @@ namespace WPEFramework { /* start signal strength monitor when wifi connected */ if(INetworkManager::WiFiState::WIFI_STATE_CONNECTED == state) + { + m_wlanConnected = true; m_wifiSignalMonitor.startWiFiSignalStrengthMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC); + } + else + m_wlanConnected = false; /* Any other state is considered as WiFi not connected. */ - NMLOG_INFO("Posting onWiFiStateChange"); _notificationLock.Lock(); + NMLOG_INFO("Posting onWiFiStateChange (%d)", state); for (const auto callback : _notificationCallbacks) { callback->onWiFiStateChange(state); } @@ -596,11 +612,10 @@ namespace WPEFramework void NetworkManagerImplementation::ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) { - NMLOG_INFO("Posting onWiFiSignalStrengthChange"); _notificationLock.Lock(); + NMLOG_INFO("Posting onWiFiSignalStrengthChange %s", strength.c_str()); for (const auto callback : _notificationCallbacks) { callback->onWiFiSignalStrengthChange(ssid, strength, quality); - } _notificationLock.Unlock(); } diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index d6ae934c2..a9cdcaf58 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -25,6 +25,7 @@ #include #include #include +#include using namespace std; @@ -222,9 +223,14 @@ namespace WPEFramework void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); void ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality); + public: + std::atomic m_ethConnected; + std::atomic m_wlanConnected; + private: void platform_init(); void retryIarmEventRegistration(); + void getInitialConnectionState(); void threadEventRegistration(); void executeExternally(NetworkEvents event, const string commandToExecute, string& response); diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 3ad434b0c..dfdea98ab 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -457,8 +457,7 @@ namespace WPEFramework { IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t *e = (IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t*) data; interface = e->interface; - NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS: %s - %s - %s", interface.c_str(), e->ip_address, e->acquired?"Acquired":"Lost" -); + NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS: %s - %s - %s", interface.c_str(), e->ip_address, e->acquired?"Acquired":"Lost"); if(interface == "eth0" || interface == "wlan0") { string ipversion("IPv4"); @@ -577,10 +576,57 @@ namespace WPEFramework IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, NetworkManagerInternalEventHandler); NMLOG_INFO("threadEventRegistration successfully subscribed to IARM event for NetworkManager Plugin"); + /* + * Read current network state and post the event. + * Useful if NetworkManager plugin or WPEFramework is restarted + * or netsrvmgr misses to post iarm events during bootup. + */ + getInitialConnectionState(); } } + void NetworkManagerImplementation::getInitialConnectionState() + { + // check the connection state and post event + Exchange::INetworkManager::IInterfaceDetailsIterator* _interfaces{}; + uint32_t rc = GetAvailableInterfaces(_interfaces); + + if (Core::ERROR_NONE == rc) + { + if (_interfaces != nullptr) + { + Exchange::INetworkManager::InterfaceDetails iface{}; + while (_interfaces->Next(iface) == true) + { + Core::JSON::EnumType type{iface.type}; + if(iface.enabled) + { + NMLOG_INFO("'%s' interface is enabled", iface.name.c_str()); + // ReportInterfaceStateChange(Exchange::INetworkManager::INTERFACE_ADDED, iface.name); + if(iface.connected) + { + NMLOG_INFO("'%s' interface is connected", iface.name.c_str()); + ReportActiveInterfaceChange(iface.name, iface.name); + std::string ipversion = {}; + Exchange::INetworkManager::IPAddress addr; + rc = GetIPSettings(iface.name, ipversion, addr); + if (Core::ERROR_NONE == rc) + { + if(!addr.ipaddress.empty()) { + NMLOG_INFO("'%s' interface have ip '%s'", iface.name.c_str(), addr.ipaddress.c_str()); + ReportIPAddressChange(iface.name, addr.ipversion, addr.ipaddress, Exchange::INetworkManager::IP_ACQUIRED); + } + } + } + } + } + + _interfaces->Release(); + } + } + } + void NetworkManagerImplementation::platform_init() { LOG_ENTRY_FUNCTION(); @@ -625,7 +671,14 @@ namespace WPEFramework IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged, NetworkManagerInternalEventHandler); IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onError, NetworkManagerInternalEventHandler); IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, NetworkManagerInternalEventHandler); + /* + * Read current network state and post the event. + * Useful if NetworkManager plugin or WPEFramework is restarted + * or netsrvmgr misses to post iarm events during bootup. + */ + getInitialConnectionState(); } + } uint32_t NetworkManagerImplementation::GetAvailableInterfaces (Exchange::INetworkManager::IInterfaceDetailsIterator*& interfacesItr/* @out */) @@ -644,15 +697,19 @@ namespace WPEFramework { InterfaceDetails tmp; /* Update the interface as per RDK NetSrvMgr */ - if ("eth0" == interfaceName) - tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_ETHERNET; - else if ("wlan0" == interfaceName) - tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_WIFI; - tmp.name = interfaceName; tmp.mac = string(list.interfaces[i].mac); tmp.enabled = ((list.interfaces[i].flags & IFF_UP) != 0); tmp.connected = ((list.interfaces[i].flags & IFF_RUNNING) != 0); + if ("eth0" == interfaceName) { + tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_ETHERNET; + m_ethConnected = tmp.connected; + } + else if ("wlan0" == interfaceName) { + tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_WIFI; + m_wlanConnected = tmp.connected; + } + interfaceList.push_back(tmp); } } diff --git a/Tests/unit_test/test_NetworkManagerConnectivity.cpp b/Tests/unit_test/test_NetworkManagerConnectivity.cpp index f175a929b..74f4309f9 100644 --- a/Tests/unit_test/test_NetworkManagerConnectivity.cpp +++ b/Tests/unit_test/test_NetworkManagerConnectivity.cpp @@ -1,6 +1,6 @@ #include "NetworkManagerImplementation.h" #include "NetworkManagerConnectivity.h" -#include "WiFiSignalStrengthMonitor.h" + #include #include #include @@ -20,36 +20,30 @@ using namespace std; using namespace WPEFramework; - + class ConnectivityMonitorTest : public ::testing::Test { protected: - - WPEFramework::Plugin::ConnectivityMonitor cm; - - void SetUp() override { - - } - - void TearDown() override { - - } + WPEFramework::Plugin::ConnectivityMonitor cm; }; - - TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_Success) { - int timeout = 30; + +TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_Success) { + int timeout = 30; bool result = cm.startContinuousConnectivityMonitor(timeout); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } + TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_FailureNegativeTimeout) { - int timeout = -1; + int timeout = -1; bool result = cm.startContinuousConnectivityMonitor(timeout); - EXPECT_TRUE(result); -} + EXPECT_TRUE(result); +} + TEST_F(ConnectivityMonitorTest, StartMonitorWithTimeoutLessThanMinimum) { - int timeout = 3; + int timeout = 3; bool result = cm.startContinuousConnectivityMonitor(timeout); EXPECT_TRUE(result); } + TEST_F(ConnectivityMonitorTest, MonitorFailsToStart) { int timeout = 0; bool result = cm.startContinuousConnectivityMonitor(timeout); @@ -60,17 +54,19 @@ TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_WhenStarted) { int timeout = 30; cm.startContinuousConnectivityMonitor(timeout); bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } + TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_WhenNotStarted) { bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } + TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_AfterMultipleStartsAndStops) { int timeout = 30; cm.startContinuousConnectivityMonitor(timeout); bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); cm.startContinuousConnectivityMonitor(timeout); result = cm.stopContinuousConnectivityMonitor(); @@ -78,55 +74,51 @@ TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_AfterMultipleStartsAndStop cm.startContinuousConnectivityMonitor(timeout); result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } + TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_LongRunningMonitor) { int timeout = 1000; cm.startContinuousConnectivityMonitor(timeout); std::this_thread::sleep_for(std::chrono::seconds(2)); bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } - TEST_F(ConnectivityMonitorTest, StartMonitor_WithInterfaceStatusTrue) { - bool interfaceStatus = true; - bool result = cm.startConnectivityMonitor(interfaceStatus); - EXPECT_TRUE(result); -} -TEST_F(ConnectivityMonitorTest, StartMonitor_WithInterfaceStatusFalse) { - bool interfaceStatus = false; - bool result = cm.startConnectivityMonitor(interfaceStatus); - EXPECT_TRUE(result); +TEST_F(ConnectivityMonitorTest, StartMonitor_WithInterfaceStatus) { + bool result = cm.startConnectivityMonitor(); + EXPECT_TRUE(result); } + TEST_F(ConnectivityMonitorTest, StartMonitor_NotifyIfAlreadyMonitoring) { - bool interfaceStatus = true; - cm.startConnectivityMonitor(interfaceStatus); - bool result = cm.startConnectivityMonitor(interfaceStatus); - EXPECT_TRUE(result); + bool result = false; + result = cm.startConnectivityMonitor(); + EXPECT_TRUE(result); + result = cm.startConnectivityMonitor(); + EXPECT_TRUE(result); } TEST_F(ConnectivityMonitorTest, SetEndpoints_Valid) { std::vector endpoints = {"https://github.com/rdkcentral", "https://github.com/rdkcentral/rdkservices"}; cm.setConnectivityMonitorEndpoints(endpoints); EXPECT_EQ(cm.getConnectivityMonitorEndpoints(), endpoints); -} +} + TEST_F(ConnectivityMonitorTest, SetEndpoints_EmptyList) { std::vector endpoints; cm.setConnectivityMonitorEndpoints(endpoints); EXPECT_TRUE(cm.getConnectivityMonitorEndpoints().empty()); } + TEST_F(ConnectivityMonitorTest, SetEndpoints_InvalidShortEndpoints) { std::vector endpoints = {"ab", "htt", "xyz"}; cm.setConnectivityMonitorEndpoints(endpoints); EXPECT_TRUE(cm.getConnectivityMonitorEndpoints().empty()); } + TEST_F(ConnectivityMonitorTest, SetEndpoints_DuplicateEndpoints) { std::vector endpoints = {"https://github.com", "https://github.com"}; cm.setConnectivityMonitorEndpoints(endpoints); EXPECT_EQ(cm.getConnectivityMonitorEndpoints().size(), 2); } - - - - diff --git a/Tests/unit_test/test_NetworkManagerStunClient.cpp b/Tests/unit_test/test_NetworkManagerStunClient.cpp index b235eb2da..5276344a1 100644 --- a/Tests/unit_test/test_NetworkManagerStunClient.cpp +++ b/Tests/unit_test/test_NetworkManagerStunClient.cpp @@ -1,23 +1,3 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include "NetworkManagerStunClient.h" @@ -28,42 +8,30 @@ using namespace stun; class AddressTest : public ::testing::Test { protected: stun::attributes::address ad; - void SetUp() override { - - } - void TearDown() override { - - } }; class ClientTest : public ::testing::Test { protected: - stun::client cl; - void SetUp() override { - - } - void TearDown() override { - - } + stun::client _client; }; TEST_F(ClientTest, BindSuccess) { stun::bind_result result; - bool success = cl.bind("https://github.com/", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); + bool success = _client.bind("https://github.com/", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); EXPECT_FALSE(success); EXPECT_FALSE(result.is_valid()); } TEST_F(ClientTest, BindFailure) { stun::bind_result result; - bool success = cl.bind("http//tata.com", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); + bool success = _client.bind("http//tata.com", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); EXPECT_FALSE(success); EXPECT_FALSE(result.is_valid()); } + TEST_F(ClientTest, BindWithInvalidInterface) { stun::bind_result result; - bool success = cl.bind("https://github.com/", 3478, "invalid_interface", stun::protocol::af_inet, 5000, 10000, result); + bool success = _client.bind("https://github.com/", 3478, "invalid_interface", stun::protocol::af_inet, 5000, 10000, result); EXPECT_FALSE(success); EXPECT_FALSE(result.is_valid()); } - diff --git a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp b/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp index a2e1d3f94..5618a6cb0 100644 --- a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp +++ b/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp @@ -17,11 +17,12 @@ namespace WPEFramework { namespace Plugin { - NetworkManagerImplementation* _instance; + NetworkManagerImplementation* _instance = nullptr; void NetworkManagerImplementation::ReportWiFiSignalStrengthChange(const string ssid, const string strength, const WiFiSignalQuality quality) - { + { return; } + void NetworkManagerImplementation::ReportInternetStatusChange(const InternetStatus prevState, const InternetStatus currState) { return; @@ -32,12 +33,7 @@ namespace WPEFramework class WiFiSignalStrengthMonitorTest : public ::testing::Test { protected: WPEFramework::Plugin::WiFiSignalStrengthMonitor monitor; - void SetUp() override { - } - void TearDown() override { - } }; -#define BUFFER_SIZE 1024 TEST_F(WiFiSignalStrengthMonitorTest, GetSignalData_Connected) { std::string ssid = "TestSSID"; @@ -47,12 +43,10 @@ TEST_F(WiFiSignalStrengthMonitorTest, GetSignalData_Connected) { } TEST_F(WiFiSignalStrengthMonitorTest, StartWiFiSignalStrengthMonitor) { - monitor.startWiFiSignalStrengthMonitor(1); - + monitor.startWiFiSignalStrengthMonitor(1); } int main(int argc, char **argv) { ::testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); } - diff --git a/Tests/unit_test/tests.cmake b/Tests/unit_test/unit_tests.cmake similarity index 96% rename from Tests/unit_test/tests.cmake rename to Tests/unit_test/unit_tests.cmake index 82d2cd928..9c56c2428 100644 --- a/Tests/unit_test/tests.cmake +++ b/Tests/unit_test/unit_tests.cmake @@ -1,5 +1,4 @@ -cmake_minimum_required(VERSION 3.10) -set(UNIT_TEST "tests") +set(UNIT_TEST "unit_tests") find_package(PkgConfig REQUIRED) pkg_check_modules(GLIB REQUIRED glib-2.0) @@ -22,10 +21,12 @@ add_executable(${UNIT_TEST} NetworkManagerConnectivity.cpp NetworkManagerStunClient.cpp ) + set_target_properties(${UNIT_TEST} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES ) + target_compile_options(${UNIT_TEST} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") @@ -43,4 +44,3 @@ target_include_directories(${UNIT_TEST} PRIVATE target_link_libraries(${UNIT_TEST} PRIVATE gmock_main ${NAMESPACE}Core::${NAMESPACE}Core ${GLIB_LIBRARIES} ${GIO_LIBRARIES} ${LIBNM_LIBRARIES} ${CURL_LIBRARIES}) target_include_directories(${UNIT_TEST} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) install(TARGETS ${UNIT_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) - From d98437cd7becc8f96c63f0ad892b86e92d0f86be Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:13:51 -0500 Subject: [PATCH 053/271] CELLO-352 : Handle the WPS return code for RDKProxy & Legacy Plugin (#53) Reason for change: Below are the changes, (1) The legacy plugin must return `"result":1` when failed as per the existing documentation. So added this change. (2) When WPS is initiated and wps failed at the RDKProxy, its returning RPC success but with the return param.status as failure. This has to be handled. Test Procedure: As per CELLO-352 Risks: Low Signed-off-by: Karunakaran A --- LegacyPlugin_WiFiManagerAPIs.cpp | 2 ++ NetworkManagerRDKProxy.cpp | 47 ++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index 5dada6b22..a86631c72 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -539,6 +539,8 @@ namespace WPEFramework if (Core::ERROR_NONE == rc) response["result"] = 0; + else + response["result"] = 1; returnJson(rc); } diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index dfdea98ab..a6b7d1555 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -576,9 +576,9 @@ namespace WPEFramework IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, NetworkManagerInternalEventHandler); NMLOG_INFO("threadEventRegistration successfully subscribed to IARM event for NetworkManager Plugin"); - /* + /* * Read current network state and post the event. - * Useful if NetworkManager plugin or WPEFramework is restarted + * Useful if NetworkManager plugin or WPEFramework is restarted * or netsrvmgr misses to post iarm events during bootup. */ getInitialConnectionState(); @@ -671,9 +671,9 @@ namespace WPEFramework IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged, NetworkManagerInternalEventHandler); IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onError, NetworkManagerInternalEventHandler); IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, NetworkManagerInternalEventHandler); - /* + /* * Read current network state and post the event. - * Useful if NetworkManager plugin or WPEFramework is restarted + * Useful if NetworkManager plugin or WPEFramework is restarted * or netsrvmgr misses to post iarm events during bootup. */ getInitialConnectionState(); @@ -685,7 +685,7 @@ namespace WPEFramework { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - IARM_BUS_NetSrvMgr_InterfaceList_t list; + IARM_BUS_NetSrvMgr_InterfaceList_t list{}; if (IARM_RESULT_SUCCESS == IARM_Bus_Call(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_getInterfaceList, (void*)&list, sizeof(list))) { std::vector interfaceList; @@ -870,7 +870,7 @@ namespace WPEFramework /* @brief Get IP Address Of the Interface */ - uint32_t NetworkManagerImplementation::GetIPSettings(string& interface /* @inout */, const string &ipversion /* @in */, IPAddress& address /* @out */) + uint32_t NetworkManagerImplementation::GetIPSettings(string& interface /* @inout */, const string &ipversion /* @in */, IPAddress& address /* @out */) { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; @@ -1082,7 +1082,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - IARM_Bus_WiFiSrvMgr_SsidList_Param_t param; + IARM_Bus_WiFiSrvMgr_SsidList_Param_t param{}; IARM_Result_t retVal = IARM_RESULT_SUCCESS; (void)ssids; @@ -1107,7 +1107,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - IARM_Bus_WiFiSrvMgr_Param_t param; + IARM_Bus_WiFiSrvMgr_Param_t param{}; memset(¶m, 0, sizeof(param)); if (IARM_RESULT_SUCCESS == IARM_Bus_Call(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_API_stopProgressiveWifiScanning, (void*) ¶m, sizeof(IARM_Bus_WiFiSrvMgr_Param_t))) @@ -1127,7 +1127,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; IARM_Result_t retVal = IARM_RESULT_SUCCESS; - IARM_Bus_WiFiSrvMgr_Param_t param; + IARM_Bus_WiFiSrvMgr_Param_t param{}; memset(¶m, 0, sizeof(param)); @@ -1155,7 +1155,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - IARM_Bus_WiFiSrvMgr_Param_t param; + IARM_Bus_WiFiSrvMgr_Param_t param{}; memset(¶m, 0, sizeof(param)); strncpy(param.data.connect.ssid, ssid.ssid.c_str(), SSID_SIZE - 1); @@ -1179,7 +1179,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - IARM_Bus_WiFiSrvMgr_Param_t param; + IARM_Bus_WiFiSrvMgr_Param_t param{}; memset(¶m, 0, sizeof(param)); /* Currently RDK-NM supports only one saved SSID. So when you say clear, it jsut clears it. No need to pass input at this point in time. @@ -1205,7 +1205,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; IARM_Result_t retVal = IARM_RESULT_SUCCESS; - IARM_Bus_WiFiSrvMgr_Param_t param; + IARM_Bus_WiFiSrvMgr_Param_t param{}; memset(¶m, 0, sizeof(param)); if(ssid.ssid.length() || ssid.passphrase.length()) @@ -1243,7 +1243,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { LOG_ENTRY_FUNCTION(); IARM_Result_t retVal = IARM_RESULT_SUCCESS; uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - IARM_Bus_WiFiSrvMgr_Param_t param; + IARM_Bus_WiFiSrvMgr_Param_t param{}; memset(¶m, 0, sizeof(param)); retVal = IARM_Bus_Call(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_API_disconnectSSID, (void *)¶m, sizeof(param)); @@ -1264,7 +1264,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; IARM_Result_t retVal = IARM_RESULT_SUCCESS; - IARM_Bus_WiFiSrvMgr_Param_t param; + IARM_Bus_WiFiSrvMgr_Param_t param{}; memset(¶m, 0, sizeof(param)); @@ -1347,7 +1347,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - IARM_Bus_WiFiSrvMgr_WPS_Parameters_t wps_parameters; + IARM_Bus_WiFiSrvMgr_WPS_Parameters_t wps_parameters{}; if (method == WIFI_WPS_PBC) { wps_parameters.pbc = true; @@ -1362,15 +1362,22 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { snprintf(wps_parameters.pin, sizeof(wps_parameters.pin), "xxxxxxxx"); wps_parameters.pbc = false; } + wps_parameters.status = false; if (IARM_RESULT_SUCCESS == IARM_Bus_Call(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_API_initiateWPSPairing2, (void *)&wps_parameters, sizeof(wps_parameters))) { - NMLOG_INFO ("StartWPS is success"); - rc = Core::ERROR_NONE; + if (wps_parameters.status) + { + NMLOG_INFO ("StartWPS is success"); + rc = Core::ERROR_NONE; + } + else + NMLOG_ERROR ("StartWPS: Failed"); } - else + + if (Core::ERROR_NONE != rc) { - NMLOG_ERROR ("StartWPS: Failed"); + NMLOG_ERROR ("StartWPS: Failed"); } return rc; @@ -1389,7 +1396,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { } else { - NMLOG_ERROR ("StopWPS: Failed"); + NMLOG_ERROR ("StopWPS: Failed"); } return rc; From 1185adff1ff0d0a068a27ac59b8d4a1910525a59 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 5 Dec 2024 12:01:21 -0500 Subject: [PATCH 054/271] RDKE-352 - Fixed WPS issue with EPG on factory reset (#54) * RDKE-352 - Fixed WPS issue with EPG on factory reset Reason for change: Fixed WPS issue with EPG on factory reset Test Procedure: Verify the WPS functionality with EPG on factory reset Risks: Medium Priority: P0 Signed-off-by: Gururaaja ESR --- NetworkManagerGnomeProxy.cpp | 5 ++ NetworkManagerGnomeWIFI.cpp | 147 ++++++++++++++++++++++++----------- 2 files changed, 107 insertions(+), 45 deletions(-) diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index 9a00cc82e..94b678408 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -669,6 +669,11 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) { uint32_t rc = Core::ERROR_NONE; + if(method == WIFI_WPS_SERIALIZED_PIN || method == WIFI_WPS_PIN) + { + NMLOG_ERROR("WPS PIN method is not supported as of now"); + return Core::ERROR_RPC_CALL_FAILED; + } if(wifi->initiateWPS()) NMLOG_INFO ("startWPS success"); else diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 22d8a1fc6..64be90163 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -948,7 +948,6 @@ namespace WPEFramework void wifiManager::wpsAction() { FILE *fp = nullptr; - std::ifstream configFile(WPA_SUPPLICANT_CONF); std::string line = ""; std::string securityPattern = "key_mgmt="; std::string ssidPattern = "ssid="; @@ -960,8 +959,15 @@ namespace WPEFramework gboolean wpsConnect = false; struct timespec startTime = {}, endTime = {}; long timeDiff = 0; + int count = 0; + bool scanResult = false; + bool ssidFound = false; + const char* bssid = nullptr; + gboolean pbcFound = false; + const GPtrArray *aps; - if (!g_main_context_acquire(wpsContext)) + + if (!wpsContext || !g_main_context_acquire(wpsContext)) { NMLOG_ERROR("Failed to acquire wpsContext"); return; @@ -969,7 +975,37 @@ namespace WPEFramework g_main_context_push_thread_default(wpsContext); - std::string wpaCliCommand = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_pbc"; + do{ + sleep(10); + loop = g_main_loop_new(wpsContext, FALSE); + scanResult = wifiScanRequest(""); + loop = g_main_loop_new(nmContext, FALSE); + if(scanResult) + { + aps = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(getWifiDevice())); + for (guint i = 0; i < aps->len; i++) { + NMAccessPoint *ap = static_cast(g_ptr_array_index(aps, i)); + guint32 flags = nm_access_point_get_flags(ap); + + if (flags & NM_802_11_AP_FLAGS_WPS_PBC) + { + bssid = nm_access_point_get_bssid(ap); + pbcFound = true; + break; + } + } + } + count++; + }while(count < 10 && !pbcFound && !wpsStop.load()); + + if(!pbcFound || wpsStop.load()) + { + g_main_context_pop_thread_default(wpsContext); + g_main_context_release(wpsContext); + return; + } + + std::string wpaCliCommand = "wpa_cli disconnect && wpa_cli -i " + std::string(nmUtils::wlanIface()) + " abort_scan && wpa_cli -i " + std::string(nmUtils::wlanIface()) + " bss_flush 0 && wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_pbc " + std::string(bssid); fp = popen(wpaCliCommand.c_str(), "r"); if (fp == nullptr) { @@ -993,13 +1029,16 @@ namespace WPEFramework { wpaCliResult += buffer.data(); } + pclose(fp); wpsConnect = (wpaCliResult.find("wpa_state=COMPLETED") != std::string::npos); clock_gettime(CLOCK_MONOTONIC, &endTime); timeDiff = (endTime.tv_sec - startTime.tv_sec); NMLOG_DEBUG("Time elapsed before getting wifi connected = %ld", timeDiff); - if(wpsConnect || timeDiff > 120) + if(wpsConnect || timeDiff > 20) + { + NMLOG_WARNING("WPS Connect status = %d; took %ld seconds", wpsConnect, (100 + timeDiff)); break; - pclose(fp); + } sleep(5); } @@ -1010,7 +1049,10 @@ namespace WPEFramework return; } + count = 0; + while(count < 2 && !ssidFound) { + std::ifstream configFile(WPA_SUPPLICANT_CONF); if (!configFile.is_open()) { NMLOG_ERROR("WPS connected with an SSID but not able to fetch IP address"); @@ -1021,22 +1063,9 @@ namespace WPEFramework while (std::getline(configFile, line)) { + NMLOG_DEBUG("Attempting to read the configuration to populate SSID specific information"); size_t pos; - // Fetch security value - pos = line.find(securityPattern); - if (pos != std::string::npos) - { - pos += securityPattern.length(); - size_t end = line.find(' ', pos); - if (end == std::string::npos) - { - end = line.length(); - } - security = line.substr(pos, end - pos); - continue; - } - // Fetch ssid value pos = line.find(ssidPattern); if (pos != std::string::npos) @@ -1048,37 +1077,64 @@ namespace WPEFramework end = line.length(); } ssid = line.substr(pos + 1, end - pos - 1); + ssidFound = true; + NMLOG_DEBUG("SSID found"); continue; } - // Fetch passphare value - pos = line.find(passphrasePattern); - if (pos != std::string::npos) - { - pos += passphrasePattern.length(); - size_t end = line.find('"', pos + 1); - if (end == std::string::npos) + if (ssidFound) { + // Fetch security value + pos = line.find(securityPattern); + if (pos != std::string::npos) { - end = line.length(); + pos += securityPattern.length(); + size_t end = line.find(' ', pos); + if (end == std::string::npos) + { + end = line.length(); + } + security = line.substr(pos, end - pos); + continue; } - passphrase = line.substr(pos + 1, end - pos - 1); - continue; + + // Fetch passphare value + pos = line.find(passphrasePattern); + if (pos != std::string::npos) + { + pos += passphrasePattern.length(); + size_t end = line.find('"', pos + 1); + if (end == std::string::npos) + { + end = line.length(); + } + passphrase = line.substr(pos + 1, end - pos - 1); + } + NMLOG_DEBUG("Fetched SSID = %s, security = %s", ssid.c_str(), security.c_str()); } } - configFile.close(); - wifiData.ssid = ssid; - wifiData.passphrase = passphrase; - if(security == "WPA-PSK") - wifiData.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES; - else if(security == "WPA2-PSK") - wifiData.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES; - } - if(this->wifiConnect(wifiData)) - NMLOG_INFO("WPS connected successfully"); - else - NMLOG_ERROR("WPS connect failed");/* TODO: Need to disconnect the wpa_cli connection, as the libnm is not aware of the connection created by wpa_cli */ - + if(ssid.empty()) + { + count++; + NMLOG_INFO("connected successfully; attempting to retrive SSID info to persist"); + sleep(5); + } + else + { + wifiData.ssid = ssid; + wifiData.passphrase = passphrase; + if(security == "WPA-PSK") + wifiData.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES; + else if(security == "WPA2-PSK") + wifiData.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES; + loop = g_main_loop_new(wpsContext, FALSE); + if(this->wifiConnect(wifiData)) + NMLOG_INFO("NetworkManager updated with WPS status - connected successfully"); + else + NMLOG_ERROR("NetworkManager is not able to sync up with underneath wpa_supplicant/hal regarding the WPS connect"); /* TODO: Need to disconnect the wpa_cli connection, as the libnm is not aware of the connection created by wpa_cli */ + loop = g_main_loop_new(nmContext, FALSE); + } + } g_main_context_pop_thread_default(wpsContext); g_main_context_release(wpsContext); if (wpsContext) { @@ -1090,14 +1146,15 @@ namespace WPEFramework bool wifiManager::initiateWPS() { - if (!createClientNewConnection()) - return false; - if(!wpsContext){ if (wpsThread.joinable()) { wpsThread.join(); } wpsContext = g_main_context_new(); + if (!wpsContext) { + NMLOG_ERROR("Failed to create new main context for WPS"); + return false; + } wpsThread = std::thread(&wifiManager::wpsAction, this); } else From 72a61bb253126b5e5d7b9fbc6dc298bb5eec3ffb Mon Sep 17 00:00:00 2001 From: tabbas651 <74683978+tabbas651@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:33:08 -0500 Subject: [PATCH 055/271] DELIA-66222,DELIA-66509: onAvailableSSIDs event not functioning correctly in the WiFi plugin (#44) * DELIA-66222,DELIA-66509: onAvailableSSIDs event not functioning correctly in the WiFi plugin Reason for change: Added the SsidList & frequency filter logic during WifiStartScan Test Procedure: Verify in custom build Risks: None Signed-off-by: Thamim Razith tabbas651@cable.comcast.com Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- LegacyPlugin_WiFiManagerAPIs.cpp | 25 +++++++++++- NetworkManagerGnomeEvents.cpp | 5 +-- NetworkManagerGnomeProxy.cpp | 23 ++++++++++- NetworkManagerImplementation.cpp | 66 ++++++++++++++++++++++++++++++-- NetworkManagerImplementation.h | 8 +++- NetworkManagerJsonRpc.cpp | 32 +++++++++++++++- NetworkManagerRDKProxy.cpp | 25 +++++++++--- 7 files changed, 164 insertions(+), 20 deletions(-) diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index a86631c72..336913223 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -544,13 +544,31 @@ namespace WPEFramework returnJson(rc); } - uint32_t WiFiManager::startScan(const JsonObject& parameters, JsonObject& response) + uint32_t WiFiManager::startScan(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string frequency = parameters["frequency"].String(); + string frequency{}; Exchange::INetworkManager::IStringIterator* ssids = NULL; + + if (parameters.HasLabel("frequency")) + frequency = parameters["frequency"].String(); + + if (parameters.HasLabel("ssid")) + { + string inputSSID = parameters["ssid"].String(); + string ssid{}; + vector inputSSIDlist; + stringstream ssidStream(inputSSID); + while (getline(ssidStream, ssid, '|')) + { + inputSSIDlist.push_back(ssid); + } + + ssids = (Core::Service::Create(inputSSIDlist)); + } + auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); if (_nwmgr) { @@ -560,6 +578,9 @@ namespace WPEFramework else rc = Core::ERROR_UNAVAILABLE; + if (ssids) + ssids->Release(); + returnJson(rc); } diff --git a/NetworkManagerGnomeEvents.cpp b/NetworkManagerGnomeEvents.cpp index c5c5c7233..3b745b7e3 100644 --- a/NetworkManagerGnomeEvents.cpp +++ b/NetworkManagerGnomeEvents.cpp @@ -617,7 +617,6 @@ namespace WPEFramework return; } JsonArray ssidList = JsonArray(); - string ssidListJson; NMAccessPoint *ap = nullptr; const GPtrArray *accessPoints = nm_device_wifi_get_access_points(wifiDevice); for (guint i = 0; i < accessPoints->len; i++) @@ -628,13 +627,11 @@ namespace WPEFramework ssidList.Add(ssidObj); } - ssidList.ToString(ssidListJson); NMLOG_INFO("No of AP Available = %d", static_cast(accessPoints->len)); - //NMLOG_DEBUG("Scanned APIs are = %s",ssidListJson.c_str()); if(_nmEventInstance->doScanNotify) { _nmEventInstance->doScanNotify = false; - _instance->ReportAvailableSSIDs(ssidListJson); + _instance->ReportAvailableSSIDs(ssidList); } } diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index 94b678408..fe1faddd4 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -528,10 +528,29 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - (void) ssids; + + //Cleared the Existing Store filterred SSID list + m_filterSsidslist.clear(); + m_filterfrequency.clear(); + + if(ssids) + { + string tmpssidlist{}; + while (ssids->Next(tmpssidlist) == true) + { + m_filterSsidslist.push_back(tmpssidlist.c_str()); + NMLOG_DEBUG("%s added to SSID filtering", tmpssidlist.c_str()); + } + } + + if (!frequency.empty()) + { + m_filterfrequency = frequency; + NMLOG_DEBUG("Scan SSIDs of frequency %s", m_filterfrequency.c_str()); + } nmEvent->setwifiScanOptions(true); - if(wifi->wifiScanRequest(frequency)) + if(wifi->wifiScanRequest(m_filterfrequency)) rc = Core::ERROR_NONE; return rc; } diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 66b0d0fa2..f08fe09cb 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -490,6 +490,56 @@ namespace WPEFramework return; } + + void NetworkManagerImplementation::filterScanResults(JsonArray &ssids) + { + JsonArray result; + double filterFreq = 0.0; + std::unordered_set scanForSsidsSet(m_filterSsidslist.begin(), m_filterSsidslist.end()); + + // If neither SSID list nor frequency is provided, exit + if (m_filterSsidslist.empty() && m_filterfrequency.empty()) + { + NMLOG_DEBUG("Neither SSID nor Frequency is provided. Exiting function."); + return; + } + + if (!m_filterfrequency.empty()) + { + filterFreq = std::stod(m_filterfrequency); + NMLOG_DEBUG("Frequency provided: %lf\n", filterFreq); + } + + for (int i = 0; i < ssids.Length(); i++) + { + JsonObject object = ssids[i].Object(); + string ssid = object["ssid"].String(); + string frequency = object["frequency"].String(); + + NMLOG_DEBUG("Processing SSID: %s, Frequency: %s\n", ssid.c_str(), frequency.c_str()); + + double frequencyValue = std::stod(frequency); + + //Debug to print log + NMLOG_DEBUG("Processing Frequency after double conversion: %lf\n", frequencyValue); + + bool ssidMatches = scanForSsidsSet.empty() || scanForSsidsSet.find(ssid) != scanForSsidsSet.end(); + bool freqMatches = m_filterfrequency.empty() || (filterFreq == frequencyValue); + + if (ssidMatches && freqMatches) + { + result.Add(object); + NMLOG_DEBUG("Match found: SSID = %s, Frequency = %lf\n", ssid.c_str(), frequencyValue); + } + else + { + NMLOG_DEBUG("No match: SSID = %s, Frequency = %lf\n", ssid.c_str(), frequencyValue); + } + } + ssids = result; + NMLOG_DEBUG("After filtering, found %d SSIDs.", ssids.Length()); + } + // WiFi Specific Methods /* @brief Initiate a WIFI Scan; This is Async method and returns the scan results as Event */ uint32_t NetworkManagerImplementation::GetSupportedSecurityModes(ISecurityModeIterator*& securityModes /* @out */) const @@ -581,12 +631,22 @@ namespace WPEFramework _notificationLock.Unlock(); } - void NetworkManagerImplementation::ReportAvailableSSIDs(const string jsonOfWiFiScanResults) + void NetworkManagerImplementation::ReportAvailableSSIDs(JsonArray &arrayofWiFiScanResults) { _notificationLock.Lock(); - NMLOG_INFO("Posting onAvailableSSIDs result is, %s", jsonOfWiFiScanResults.c_str()); + string jsonOfWiFiScanResults; + string jsonOfFilterScanResults; + + arrayofWiFiScanResults.ToString(jsonOfWiFiScanResults); + NMLOG_DEBUG("Posting onAvailableSSIDs result before Filtering is, %s", jsonOfWiFiScanResults.c_str()); + + filterScanResults(arrayofWiFiScanResults); + + arrayofWiFiScanResults.ToString(jsonOfFilterScanResults); + + NMLOG_INFO("Posting onAvailableSSIDs result is, %s", jsonOfFilterScanResults.c_str()); for (const auto callback : _notificationCallbacks) { - callback->onAvailableSSIDs(jsonOfWiFiScanResults); + callback->onAvailableSSIDs(jsonOfFilterScanResults); } _notificationLock.Unlock(); } diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index a9cdcaf58..64767f98b 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -219,7 +219,7 @@ namespace WPEFramework void ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface); void ReportIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status); void ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState); - void ReportAvailableSSIDs(const string jsonOfScanResults); + void ReportAvailableSSIDs(JsonArray &arrayofWiFiScanResults); void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); void ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality); @@ -233,6 +233,7 @@ namespace WPEFramework void getInitialConnectionState(); void threadEventRegistration(); void executeExternally(NetworkEvents event, const string commandToExecute, string& response); + void filterScanResults(JsonArray &ssids); private: std::list _notificationCallbacks; @@ -245,7 +246,10 @@ namespace WPEFramework uint16_t m_stunBindTimeout; uint16_t m_stunCacheTimeout; std::thread m_registrationThread; - public: + string m_filterfrequency; + std::vector m_filterSsidslist; + + public: WiFiSignalStrengthMonitor m_wifiSignalMonitor; mutable ConnectivityMonitor connectivityMonitor; }; diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index bb143f0d1..1079443bf 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -667,14 +667,42 @@ namespace WPEFramework { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string frequency = parameters["frequency"].String(); - Exchange::INetworkManager::IStringIterator* ssids = NULL; + string frequency{}; + Exchange::INetworkManager::IStringIterator* ssids = NULL; + + if (parameters.HasLabel("frequency")) + frequency = parameters["frequency"].String(); + + if (parameters.HasLabel("ssids")) + { + JsonArray array = parameters["ssids"].Array(); + std::vector ssidslist; + JsonArray::Iterator index(array.Elements()); + + while (index.Next() == true) + { + if (Core::JSON::Variant::type::STRING == index.Current().Content()) + { + ssidslist.push_back(index.Current().String().c_str()); + } + else + { + NMLOG_ERROR("Unexpected variant type in SSID array."); + returnJson(rc); + } + } + ssids = (Core::Service::Create(ssidslist)); + } if (_networkManager) rc = _networkManager->StartWiFiScan(frequency, ssids); else rc = Core::ERROR_UNAVAILABLE; + if (ssids) + ssids->Release(); + + returnJson(rc); } diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index a6b7d1555..45785711c 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -505,10 +505,8 @@ namespace WPEFramework } JsonArray ssids = eventDocument["getAvailableSSIDs"].Array(); - string json; - ssids.ToString(json); - ::_instance->ReportAvailableSSIDs(json); + ::_instance->ReportAvailableSSIDs(ssids); break; } case IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged: @@ -1085,8 +1083,25 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { IARM_Bus_WiFiSrvMgr_SsidList_Param_t param{}; IARM_Result_t retVal = IARM_RESULT_SUCCESS; - (void)ssids; - (void) frequency; + //Cleared the Existing Store filterred SSID list + m_filterSsidslist.clear(); + m_filterfrequency.clear(); + + if(ssids) + { + string ssidlist{}; + while (ssids->Next(ssidlist) == true) + { + m_filterSsidslist.push_back(ssidlist.c_str()); + NMLOG_DEBUG("%s added to SSID filtering", ssidlist.c_str()); + } + } + + if (!frequency.empty()) + { + m_filterfrequency = frequency; + NMLOG_DEBUG("Scan SSIDs of frequency %s", m_filterfrequency.c_str()); + } memset(¶m, 0, sizeof(param)); From 457977eb6ce946c36a82aa277917d136a24067b2 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Wed, 11 Dec 2024 11:09:07 -0500 Subject: [PATCH 056/271] Release of v0.6.0 Signed-off-by: Karunakaran A --- CHANGELOG.md | 8 ++++++++ CMakeLists.txt | 4 ++-- NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56932775a..6ffd188ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,14 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.6.0] - 2024-12-10 +### Added +- Added specific SSID/frequency scanning +- Added retry logic in WPS Connect +- Added Unittest for Connectivity Class +- Fixed Continuous Connectivity Monitoring when no interface connected +- Fixed SetIPSettings on GNome backed + ## [0.5.4] - 2024-11-29 ### Fixed - Fixed documentation of NetworkManager diff --git a/CMakeLists.txt b/CMakeLists.txt index 592e9915b..3670fe97f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 5) -set(VERSION_PATCH 4) +set(VERSION_MINOR 6) +set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) add_compile_definitions(NETWORKMANAGER_MINOR_VERSION=${VERSION_MINOR}) diff --git a/NetworkManager.json b/NetworkManager.json index d18ca0075..7636a5524 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json", - "version": "0.5.3" + "version": "0.6.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 757fb68f2..8c6b3f3ea 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.5.4** +**Version: 0.6.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.5.4). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.6.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 69c02f38893f795b5bdfc56cc234c8d594663c9c Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Wed, 18 Dec 2024 16:06:00 -0500 Subject: [PATCH 057/271] Revert "DELIA-66968 Disable continuous connectivity monitor when Interface is disconnected (#51)" This reverts commit da274ffa9dfcd445c23ebf855a27189b20745f52. --- .github/workflows/gnome_unit_test.yml | 2 +- CMakeLists.txt | 2 +- NetworkManagerConnectivity.cpp | 93 ++++++++----------- NetworkManagerConnectivity.h | 9 +- NetworkManagerGnomeProxy.cpp | 20 ++-- NetworkManagerImplementation.cpp | 33 ++----- NetworkManagerImplementation.h | 6 -- NetworkManagerRDKProxy.cpp | 71 ++------------ .../test_NetworkManagerConnectivity.cpp | 78 +++++++++------- .../test_NetworkManagerStunClient.cpp | 42 ++++++++- .../test_WiFiSignalStrengthMonitor.cpp | 14 ++- .../{unit_tests.cmake => tests.cmake} | 6 +- 12 files changed, 164 insertions(+), 212 deletions(-) rename Tests/unit_test/{unit_tests.cmake => tests.cmake} (96%) diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index 4dcb52e8b..107e6e455 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -110,7 +110,7 @@ jobs: run: > PATH=${{github.workspace}}/install/usr/bin:${PATH} LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} - unit_tests + tests - name: Generate coverage run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 3670fe97f..6937da5ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,6 +170,6 @@ write_config(PLUGINS LegacyPlugin_NetworkAPIs CLASSNAME Network LOCATOR lib${PLU write_config(PLUGINS LegacyPlugin_WiFiManagerAPIs CLASSNAME WiFiManager LOCATOR lib${PLUGIN_LEGACY_DEPRECATED_WIFI}.so) if(ENABLE_UNIT_TESTING) - include(Tests/unit_test/unit_tests.cmake) + include(Tests/unit_test/tests.cmake) endif(ENABLE_UNIT_TESTING) diff --git a/NetworkManagerConnectivity.cpp b/NetworkManagerConnectivity.cpp index 1a4667e1d..f76c8b4bc 100644 --- a/NetworkManagerConnectivity.cpp +++ b/NetworkManagerConnectivity.cpp @@ -158,7 +158,7 @@ namespace WPEFramework curl_easy_setopt(curl_easy_handle, CURLOPT_TIMEOUT_MS, deadline - current_time()); if ((ipversion == CURL_IPRESOLVE_V4) || (ipversion == CURL_IPRESOLVE_V6)) { - NMLOG_DEBUG("curlopt ipversion = %s reqtyp = %s", ipversion == CURL_IPRESOLVE_V4?"IPv4":"IPv6", headReq? "HEAD":"GET"); + NMLOG_DEBUG("curlopt ipversion = %s reqtyp = %s", ipversion == CURL_IPRESOLVE_V4?"ipv4 only":"ipv6 only", headReq? "HEAD":"GET"); curl_easy_setopt(curl_easy_handle, CURLOPT_IPRESOLVE, ipversion); } else @@ -324,9 +324,10 @@ namespace WPEFramework doContinuousMonitor = false; doConnectivityMonitor = false; - m_InternetState = nsm_internetState::UNKNOWN; - m_Ipv4InternetState = nsm_internetState::UNKNOWN; - m_Ipv6InternetState = nsm_internetState::UNKNOWN; + gInternetState = nsm_internetState::UNKNOWN; + gIpv4InternetState = nsm_internetState::UNKNOWN; + gIpv6InternetState = nsm_internetState::UNKNOWN; + ginterfaceStatus = false; } ConnectivityMonitor::~ConnectivityMonitor() @@ -389,15 +390,15 @@ namespace WPEFramework // If monitor connectivity is running take the cache value if ( doContinuousMonitor && (nsm_ipversion::NSM_IPRESOLVE_V4 == ipversion || nsm_ipversion::NSM_IPRESOLVE_WHATEVER == ipversion) - && m_Ipv4InternetState != nsm_internetState::UNKNOWN ) { - NMLOG_WARNING("Reading Ipv4 internet state cached value %s", getInternetStateString(m_Ipv4InternetState)); - internetState = m_Ipv4InternetState; + && gIpv4InternetState != nsm_internetState::UNKNOWN ) { + NMLOG_WARNING("Reading Ipv4 internet state cached value %s", getInternetStateString(gIpv4InternetState)); + internetState = gIpv4InternetState; ipversion = NSM_IPRESOLVE_V4; } else if ( doContinuousMonitor && (nsm_ipversion::NSM_IPRESOLVE_V6 == ipversion || nsm_ipversion::NSM_IPRESOLVE_WHATEVER == ipversion) - && m_Ipv6InternetState != nsm_internetState::UNKNOWN ) { - NMLOG_WARNING("Reading Ipv6 internet state cached value %s", getInternetStateString(m_Ipv6InternetState)); - internetState = m_Ipv6InternetState; + && gIpv6InternetState != nsm_internetState::UNKNOWN ) { + NMLOG_WARNING("Reading Ipv6 internet state cached value %s", getInternetStateString(gIpv6InternetState)); + internetState = gIpv6InternetState; ipversion = NSM_IPRESOLVE_V6; } else @@ -424,8 +425,6 @@ namespace WPEFramework bool ConnectivityMonitor::startContinuousConnectivityMonitor(int timeoutInSeconds) { - if(_instance != nullptr ) - NMLOG_INFO("interface status eth - %s wlan - %s ", _instance->m_ethConnected? "up":"down", _instance->m_wlanConnected? "up":"down"); continuousMonitorTimeout.store(timeoutInSeconds >= NMCONNECTIVITY_MONITOR_MIN_INTERVAL ? timeoutInSeconds : NMCONNECTIVITY_MONITOR_DEFAULT_INTERVAL); if (doContinuousMonitor) { @@ -473,11 +472,12 @@ namespace WPEFramework * --> when IP address accuired * --> when etherenet/wifi disconnected */ - bool ConnectivityMonitor::startConnectivityMonitor() + bool ConnectivityMonitor::startConnectivityMonitor(bool interfaceStatus) { - m_InternetState = nsm_internetState::UNKNOWN; - m_Ipv4InternetState = nsm_internetState::UNKNOWN; - m_Ipv6InternetState = nsm_internetState::UNKNOWN; + ginterfaceStatus = interfaceStatus; /* this will give interface status connected/ disconnected */ + gInternetState = UNKNOWN; + gIpv4InternetState = UNKNOWN; + gIpv6InternetState = UNKNOWN; if (doConnectivityMonitor) { cvConnectivityMonitor.notify_one(); @@ -497,26 +497,21 @@ namespace WPEFramework return false; } - if(_instance != nullptr) { - NMLOG_INFO("connectivity monitor started %d sec - eth %s - wlan %s", NMCONNECTIVITY_MONITOR_MIN_INTERVAL, - _instance->m_ethConnected? "up":"down", _instance->m_wlanConnected? "up":"down"); - } + NMLOG_ERROR("connectivity monitor started %d", NMCONNECTIVITY_MONITOR_MIN_INTERVAL); return true; } void ConnectivityMonitor::notifyInternetStatusChangedEvent(nsm_internetState newInternetState) { - static Exchange::INetworkManager::InternetStatus oldState = Exchange::INetworkManager::InternetStatus::INTERNET_UNKNOWN; if(_instance != nullptr) { - NMLOG_INFO("notify internet state %s", getInternetStateString(newInternetState)); + Exchange::INetworkManager::InternetStatus oldState = static_cast(gInternetState.load()); Exchange::INetworkManager::InternetStatus newState = static_cast(newInternetState); _instance->ReportInternetStatusChange(oldState , newState); - m_InternetState = newInternetState; - oldState = newState; // 'm_InternetState' not exactly previous state, it may change to unknow when interface changed + gInternetState = newInternetState; } else - NMLOG_FATAL("NetworkManagerImplementation Instance NULL notifyInternetStatusChange failed."); + NMLOG_WARNING("NetworkManagerImplementation Instance NULL notifyInternetStatusChange failed."); } void ConnectivityMonitor::continuousMonitorFunction() @@ -529,31 +524,20 @@ namespace WPEFramework do { - if(_instance != nullptr && (!_instance->m_ethConnected && !_instance->m_wlanConnected)) // no wifi no ethernet connected - { - NMLOG_DEBUG("no interface connected; no ccm check"); - m_Ipv4InternetState = NO_INTERNET; - m_Ipv6InternetState = NO_INTERNET; - std::unique_lock lock(connMutex); - cvContinuousMonitor.wait_for(lock, std::chrono::seconds(continuousMonitorTimeout.load())); - ipResolveTyp = NSM_IPRESOLVE_WHATEVER; - continue; - } - if(doConnectivityMonitor) { NMLOG_DEBUG("connectivity monitor running so skiping ccm check"); - m_Ipv4InternetState = nsm_internetState::UNKNOWN; - m_Ipv6InternetState = nsm_internetState::UNKNOWN; + gIpv4InternetState = UNKNOWN; + gIpv6InternetState = UNKNOWN; std::unique_lock lock(connMutex); cvContinuousMonitor.wait_for(lock, std::chrono::seconds(continuousMonitorTimeout.load())); - ipResolveTyp = NSM_IPRESOLVE_WHATEVER; /* some interface change happense */ + ipResolveTyp = NSM_IPRESOLVE_WHATEVER; /* some interface change happense*/ continue; } else if (ipResolveTyp == NSM_IPRESOLVE_WHATEVER) { - nsm_internetState ipV4InternetState = nsm_internetState::UNKNOWN; - nsm_internetState ipV6InternetState = nsm_internetState::UNKNOWN; + nsm_internetState ipV4InternetState = UNKNOWN; + nsm_internetState ipV6InternetState = UNKNOWN; auto curlCheckThrdIpv4 = [&]() { TestConnectivity testInternet(getConnectivityMonitorEndpoints(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, NMCONNECTIVITY_CURL_GET_REQUEST, NSM_IPRESOLVE_V4); @@ -589,17 +573,17 @@ namespace WPEFramework NMCONNECTIVITY_CURL_HEAD_REQUEST, ipResolveTyp); currentInternetState = testInternet.getInternetState(); if(ipResolveTyp == NSM_IPRESOLVE_V4) - m_Ipv4InternetState = currentInternetState; + gIpv4InternetState = currentInternetState; else if(ipResolveTyp == NSM_IPRESOLVE_V6) - m_Ipv6InternetState = currentInternetState; + gIpv6InternetState = currentInternetState; } if (currentInternetState == NO_INTERNET) { - if(m_InternetState == FULLY_CONNECTED && notifyPreRetry < NMCONNECTIVITY_NO_INTERNET_RETRY_COUNT) + if(gInternetState == FULLY_CONNECTED && notifyPreRetry < NMCONNECTIVITY_NO_INTERNET_RETRY_COUNT) { /* it will prevent posting notification */ - currentInternetState = m_InternetState; + currentInternetState = gInternetState; TempInterval = 5; NMLOG_INFO("No internet retrying connection check %d ...", notifyPreRetry); notifyPreRetry++; @@ -617,8 +601,9 @@ namespace WPEFramework TempInterval = continuousMonitorTimeout.load(); } - if(m_InternetState != currentInternetState) + if(gInternetState != currentInternetState) { + NMLOG_INFO("Internet state changed to %s", getInternetStateString(currentInternetState)); /* Notify Internet state change */ notifyInternetStatusChangedEvent(currentInternetState); } @@ -634,8 +619,8 @@ namespace WPEFramework } while(doContinuousMonitor); - m_Ipv4InternetState = nsm_internetState::UNKNOWN; - m_Ipv6InternetState = nsm_internetState::UNKNOWN; + gIpv4InternetState = UNKNOWN; + gIpv6InternetState = UNKNOWN; NMLOG_DEBUG("continous connectivity monitor exit"); } @@ -678,8 +663,8 @@ namespace WPEFramework NMLOG_INFO("Connectivity check retrying %d ...", notifyPreRetry); } - if(m_InternetState != nsm_internetState::UNKNOWN) - currentInternetState = m_InternetState; + if(gInternetState != UNKNOWN) + currentInternetState = gInternetState; TempInterval = 5; } else if(tempInternetState != currentInternetState) // last state have change @@ -696,9 +681,8 @@ namespace WPEFramework doConnectivityMonitor = false; // self exit notifyNow = true; // post current state when retry complete } - else if(_instance != nullptr && (_instance->m_ethConnected | _instance->m_wlanConnected)) + else if(ginterfaceStatus) // interface is active and still no internet, continue check every 30 sec { - /* interface is connected and still no internet, continue check every 30 sec */ TempInterval = NMCONNECTIVITY_CONN_MONITOR_RETRY_INTERVAL; /* notify if retry completed and state stil no internet state */ if(notifyPreRetry == NMCONNECTIVITY_CONN_MONITOR_RETRY_COUNT) @@ -715,9 +699,10 @@ namespace WPEFramework } } - if(m_InternetState != currentInternetState || notifyNow) + if(gInternetState != currentInternetState || notifyNow) { notifyNow = false; + NMLOG_INFO("notify internet state %s", getInternetStateString(currentInternetState)); notifyInternetStatusChangedEvent(currentInternetState); } @@ -734,7 +719,7 @@ namespace WPEFramework } while(doConnectivityMonitor); if(!doContinuousMonitor) - m_InternetState = nsm_internetState::UNKNOWN; // no continous monitor running reset to unknow + gInternetState = nsm_internetState::UNKNOWN; // no continous monitor running reset to unknow NMLOG_DEBUG("initial connectivity monitor exit"); } diff --git a/NetworkManagerConnectivity.h b/NetworkManagerConnectivity.h index 3a5b215a3..26f256fa4 100644 --- a/NetworkManagerConnectivity.h +++ b/NetworkManagerConnectivity.h @@ -114,7 +114,7 @@ namespace WPEFramework ~ConnectivityMonitor(); bool startContinuousConnectivityMonitor(int timeoutInSeconds); bool stopContinuousConnectivityMonitor(); - bool startConnectivityMonitor(); + bool startConnectivityMonitor(bool interfaceStatus); void setConnectivityMonitorEndpoints(const std::vector &endpoints); std::vector getConnectivityMonitorEndpoints(); bool isConnectedToInternet(nsm_ipversion ipversion); @@ -140,9 +140,10 @@ namespace WPEFramework EndpointCache endpointCache; std::mutex endpointMutex; - std::atomic m_InternetState; - std::atomic m_Ipv4InternetState; - std::atomic m_Ipv6InternetState; + std::atomic ginterfaceStatus; + std::atomic gInternetState; + std::atomic gIpv4InternetState; + std::atomic gIpv6InternetState; }; } // namespace Plugin } // namespace WPEFramework diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index fe1faddd4..eb84bef6c 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -84,25 +84,23 @@ namespace WPEFramework { NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; Exchange::INetworkManager::InterfaceDetails interface; - interface.mac = nm_device_get_hw_address(device); - deviceState = nm_device_get_state(device); - interface.enabled = (deviceState >= NM_DEVICE_STATE_UNAVAILABLE)? true : false; - if(deviceState > NM_DEVICE_STATE_DISCONNECTED && deviceState < NM_DEVICE_STATE_DEACTIVATING) - interface.connected = true; - else - interface.connected = false; - if(ifaceStr == wifiname) { interface.type = INTERFACE_TYPE_WIFI; interface.name = wifiname; - m_wlanConnected = interface.connected; } if(ifaceStr == ethname) { interface.type = INTERFACE_TYPE_ETHERNET; interface.name = ethname; - m_ethConnected = interface.connected; } - + interface.mac = nm_device_get_hw_address(device); + deviceState = nm_device_get_state(device); + interface.enabled = (deviceState >= NM_DEVICE_STATE_UNAVAILABLE) ? true : false; + if(deviceState > NM_DEVICE_STATE_DISCONNECTED && deviceState < NM_DEVICE_STATE_DEACTIVATING){ + interface.connected = true; + m_defaultInterface = interface.name; + } + else + interface.connected = false; interfaceList.push_back(interface); rc = Core::ERROR_NONE; } diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index f08fe09cb..6ca6bd9b2 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -50,8 +50,6 @@ namespace WPEFramework m_stunCacheTimeout = 0; m_defaultInterface = ""; m_publicIP = ""; - m_ethConnected = false; - m_wlanConnected = false; } NetworkManagerImplementation::~NetworkManagerImplementation() @@ -572,22 +570,13 @@ namespace WPEFramework void NetworkManagerImplementation::ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface) { LOG_ENTRY_FUNCTION(); - if(Exchange::INetworkManager::INTERFACE_LINK_DOWN == state || Exchange::INetworkManager::INTERFACE_REMOVED == state) { + if(Exchange::INetworkManager::INTERFACE_LINK_DOWN == state) { // Start the connectivity monitor with 'false' to indicate the interface is down. // The monitor will automatically exit after the retry attempts are completed, posting a 'noInternet' event. - if(interface == "eth0") - m_ethConnected = false; - else - m_wlanConnected = false; - connectivityMonitor.startConnectivityMonitor(); + connectivityMonitor.startConnectivityMonitor(false); } - /* Only the Ethernet connection status is changing here. The WiFi status is updated in the WiFi state callback. */ - if(Exchange::INetworkManager::INTERFACE_LINK_UP == state && interface == "eth0") - m_ethConnected = true; - _notificationLock.Lock(); - NMLOG_INFO("Posting onInterfaceChange %s - %u", interface.c_str(), (unsigned)state); for (const auto callback : _notificationCallbacks) { callback->onInterfaceStateChange(state, interface); } @@ -596,8 +585,8 @@ namespace WPEFramework void NetworkManagerImplementation::ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface) { - _notificationLock.Lock(); NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); + _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); } @@ -610,11 +599,11 @@ namespace WPEFramework if (Exchange::INetworkManager::IP_ACQUIRED == status) { // Start the connectivity monitor with 'true' to indicate the interface is up. // The monitor will conntinoue even after no internet retry completed, Exit when fully connectd. - connectivityMonitor.startConnectivityMonitor(); + connectivityMonitor.startConnectivityMonitor(true); } + NMLOG_INFO("Posting onIPAddressChange %s", ipaddress.c_str()); _notificationLock.Lock(); - NMLOG_INFO("Posting onIPAddressChange %s - %s", ipaddress.c_str(), interface.c_str()); for (const auto callback : _notificationCallbacks) { callback->onIPAddressChange(interface, ipversion, ipaddress, status); } @@ -623,8 +612,8 @@ namespace WPEFramework void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) { - _notificationLock.Lock(); NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); + _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onInternetStatusChange(prevState, currState); } @@ -655,15 +644,10 @@ namespace WPEFramework { /* start signal strength monitor when wifi connected */ if(INetworkManager::WiFiState::WIFI_STATE_CONNECTED == state) - { - m_wlanConnected = true; m_wifiSignalMonitor.startWiFiSignalStrengthMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC); - } - else - m_wlanConnected = false; /* Any other state is considered as WiFi not connected. */ + NMLOG_INFO("Posting onWiFiStateChange"); _notificationLock.Lock(); - NMLOG_INFO("Posting onWiFiStateChange (%d)", state); for (const auto callback : _notificationCallbacks) { callback->onWiFiStateChange(state); } @@ -672,10 +656,11 @@ namespace WPEFramework void NetworkManagerImplementation::ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) { + NMLOG_INFO("Posting onWiFiSignalStrengthChange"); _notificationLock.Lock(); - NMLOG_INFO("Posting onWiFiSignalStrengthChange %s", strength.c_str()); for (const auto callback : _notificationCallbacks) { callback->onWiFiSignalStrengthChange(ssid, strength, quality); + } _notificationLock.Unlock(); } diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 64767f98b..e8cbd532f 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -25,7 +25,6 @@ #include #include #include -#include using namespace std; @@ -223,14 +222,9 @@ namespace WPEFramework void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); void ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality); - public: - std::atomic m_ethConnected; - std::atomic m_wlanConnected; - private: void platform_init(); void retryIarmEventRegistration(); - void getInitialConnectionState(); void threadEventRegistration(); void executeExternally(NetworkEvents event, const string commandToExecute, string& response); void filterScanResults(JsonArray &ssids); diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 45785711c..891818722 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -457,7 +457,8 @@ namespace WPEFramework { IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t *e = (IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t*) data; interface = e->interface; - NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS: %s - %s - %s", interface.c_str(), e->ip_address, e->acquired?"Acquired":"Lost"); + NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS: %s - %s - %s", interface.c_str(), e->ip_address, e->acquired?"Acquired":"Lost" +); if(interface == "eth0" || interface == "wlan0") { string ipversion("IPv4"); @@ -574,57 +575,10 @@ namespace WPEFramework IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, NetworkManagerInternalEventHandler); NMLOG_INFO("threadEventRegistration successfully subscribed to IARM event for NetworkManager Plugin"); - /* - * Read current network state and post the event. - * Useful if NetworkManager plugin or WPEFramework is restarted - * or netsrvmgr misses to post iarm events during bootup. - */ - getInitialConnectionState(); } } - void NetworkManagerImplementation::getInitialConnectionState() - { - // check the connection state and post event - Exchange::INetworkManager::IInterfaceDetailsIterator* _interfaces{}; - uint32_t rc = GetAvailableInterfaces(_interfaces); - - if (Core::ERROR_NONE == rc) - { - if (_interfaces != nullptr) - { - Exchange::INetworkManager::InterfaceDetails iface{}; - while (_interfaces->Next(iface) == true) - { - Core::JSON::EnumType type{iface.type}; - if(iface.enabled) - { - NMLOG_INFO("'%s' interface is enabled", iface.name.c_str()); - // ReportInterfaceStateChange(Exchange::INetworkManager::INTERFACE_ADDED, iface.name); - if(iface.connected) - { - NMLOG_INFO("'%s' interface is connected", iface.name.c_str()); - ReportActiveInterfaceChange(iface.name, iface.name); - std::string ipversion = {}; - Exchange::INetworkManager::IPAddress addr; - rc = GetIPSettings(iface.name, ipversion, addr); - if (Core::ERROR_NONE == rc) - { - if(!addr.ipaddress.empty()) { - NMLOG_INFO("'%s' interface have ip '%s'", iface.name.c_str(), addr.ipaddress.c_str()); - ReportIPAddressChange(iface.name, addr.ipversion, addr.ipaddress, Exchange::INetworkManager::IP_ACQUIRED); - } - } - } - } - } - - _interfaces->Release(); - } - } - } - void NetworkManagerImplementation::platform_init() { LOG_ENTRY_FUNCTION(); @@ -669,14 +623,7 @@ namespace WPEFramework IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged, NetworkManagerInternalEventHandler); IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onError, NetworkManagerInternalEventHandler); IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, NetworkManagerInternalEventHandler); - /* - * Read current network state and post the event. - * Useful if NetworkManager plugin or WPEFramework is restarted - * or netsrvmgr misses to post iarm events during bootup. - */ - getInitialConnectionState(); } - } uint32_t NetworkManagerImplementation::GetAvailableInterfaces (Exchange::INetworkManager::IInterfaceDetailsIterator*& interfacesItr/* @out */) @@ -695,19 +642,15 @@ namespace WPEFramework { InterfaceDetails tmp; /* Update the interface as per RDK NetSrvMgr */ + if ("eth0" == interfaceName) + tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_ETHERNET; + else if ("wlan0" == interfaceName) + tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_WIFI; + tmp.name = interfaceName; tmp.mac = string(list.interfaces[i].mac); tmp.enabled = ((list.interfaces[i].flags & IFF_UP) != 0); tmp.connected = ((list.interfaces[i].flags & IFF_RUNNING) != 0); - if ("eth0" == interfaceName) { - tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_ETHERNET; - m_ethConnected = tmp.connected; - } - else if ("wlan0" == interfaceName) { - tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_WIFI; - m_wlanConnected = tmp.connected; - } - interfaceList.push_back(tmp); } } diff --git a/Tests/unit_test/test_NetworkManagerConnectivity.cpp b/Tests/unit_test/test_NetworkManagerConnectivity.cpp index 74f4309f9..f175a929b 100644 --- a/Tests/unit_test/test_NetworkManagerConnectivity.cpp +++ b/Tests/unit_test/test_NetworkManagerConnectivity.cpp @@ -1,6 +1,6 @@ #include "NetworkManagerImplementation.h" #include "NetworkManagerConnectivity.h" - +#include "WiFiSignalStrengthMonitor.h" #include #include #include @@ -20,30 +20,36 @@ using namespace std; using namespace WPEFramework; - + class ConnectivityMonitorTest : public ::testing::Test { protected: - WPEFramework::Plugin::ConnectivityMonitor cm; -}; + + WPEFramework::Plugin::ConnectivityMonitor cm; -TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_Success) { - int timeout = 30; + void SetUp() override { + + } + + void TearDown() override { + + } +}; + + TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_Success) { + int timeout = 30; bool result = cm.startContinuousConnectivityMonitor(timeout); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } - TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_FailureNegativeTimeout) { - int timeout = -1; + int timeout = -1; bool result = cm.startContinuousConnectivityMonitor(timeout); - EXPECT_TRUE(result); -} - + EXPECT_TRUE(result); +} TEST_F(ConnectivityMonitorTest, StartMonitorWithTimeoutLessThanMinimum) { - int timeout = 3; + int timeout = 3; bool result = cm.startContinuousConnectivityMonitor(timeout); EXPECT_TRUE(result); } - TEST_F(ConnectivityMonitorTest, MonitorFailsToStart) { int timeout = 0; bool result = cm.startContinuousConnectivityMonitor(timeout); @@ -54,19 +60,17 @@ TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_WhenStarted) { int timeout = 30; cm.startContinuousConnectivityMonitor(timeout); bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } - TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_WhenNotStarted) { bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } - TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_AfterMultipleStartsAndStops) { int timeout = 30; cm.startContinuousConnectivityMonitor(timeout); bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); cm.startContinuousConnectivityMonitor(timeout); result = cm.stopContinuousConnectivityMonitor(); @@ -74,51 +78,55 @@ TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_AfterMultipleStartsAndStop cm.startContinuousConnectivityMonitor(timeout); result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } - TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_LongRunningMonitor) { int timeout = 1000; cm.startContinuousConnectivityMonitor(timeout); std::this_thread::sleep_for(std::chrono::seconds(2)); bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } -TEST_F(ConnectivityMonitorTest, StartMonitor_WithInterfaceStatus) { - bool result = cm.startConnectivityMonitor(); - EXPECT_TRUE(result); + TEST_F(ConnectivityMonitorTest, StartMonitor_WithInterfaceStatusTrue) { + bool interfaceStatus = true; + bool result = cm.startConnectivityMonitor(interfaceStatus); + EXPECT_TRUE(result); +} +TEST_F(ConnectivityMonitorTest, StartMonitor_WithInterfaceStatusFalse) { + bool interfaceStatus = false; + bool result = cm.startConnectivityMonitor(interfaceStatus); + EXPECT_TRUE(result); } - TEST_F(ConnectivityMonitorTest, StartMonitor_NotifyIfAlreadyMonitoring) { - bool result = false; - result = cm.startConnectivityMonitor(); - EXPECT_TRUE(result); - result = cm.startConnectivityMonitor(); - EXPECT_TRUE(result); + bool interfaceStatus = true; + cm.startConnectivityMonitor(interfaceStatus); + bool result = cm.startConnectivityMonitor(interfaceStatus); + EXPECT_TRUE(result); } TEST_F(ConnectivityMonitorTest, SetEndpoints_Valid) { std::vector endpoints = {"https://github.com/rdkcentral", "https://github.com/rdkcentral/rdkservices"}; cm.setConnectivityMonitorEndpoints(endpoints); EXPECT_EQ(cm.getConnectivityMonitorEndpoints(), endpoints); -} - +} TEST_F(ConnectivityMonitorTest, SetEndpoints_EmptyList) { std::vector endpoints; cm.setConnectivityMonitorEndpoints(endpoints); EXPECT_TRUE(cm.getConnectivityMonitorEndpoints().empty()); } - TEST_F(ConnectivityMonitorTest, SetEndpoints_InvalidShortEndpoints) { std::vector endpoints = {"ab", "htt", "xyz"}; cm.setConnectivityMonitorEndpoints(endpoints); EXPECT_TRUE(cm.getConnectivityMonitorEndpoints().empty()); } - TEST_F(ConnectivityMonitorTest, SetEndpoints_DuplicateEndpoints) { std::vector endpoints = {"https://github.com", "https://github.com"}; cm.setConnectivityMonitorEndpoints(endpoints); EXPECT_EQ(cm.getConnectivityMonitorEndpoints().size(), 2); } + + + + diff --git a/Tests/unit_test/test_NetworkManagerStunClient.cpp b/Tests/unit_test/test_NetworkManagerStunClient.cpp index 5276344a1..b235eb2da 100644 --- a/Tests/unit_test/test_NetworkManagerStunClient.cpp +++ b/Tests/unit_test/test_NetworkManagerStunClient.cpp @@ -1,3 +1,23 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include "NetworkManagerStunClient.h" @@ -8,30 +28,42 @@ using namespace stun; class AddressTest : public ::testing::Test { protected: stun::attributes::address ad; + void SetUp() override { + + } + void TearDown() override { + + } }; class ClientTest : public ::testing::Test { protected: - stun::client _client; + stun::client cl; + void SetUp() override { + + } + void TearDown() override { + + } }; TEST_F(ClientTest, BindSuccess) { stun::bind_result result; - bool success = _client.bind("https://github.com/", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); + bool success = cl.bind("https://github.com/", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); EXPECT_FALSE(success); EXPECT_FALSE(result.is_valid()); } TEST_F(ClientTest, BindFailure) { stun::bind_result result; - bool success = _client.bind("http//tata.com", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); + bool success = cl.bind("http//tata.com", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); EXPECT_FALSE(success); EXPECT_FALSE(result.is_valid()); } - TEST_F(ClientTest, BindWithInvalidInterface) { stun::bind_result result; - bool success = _client.bind("https://github.com/", 3478, "invalid_interface", stun::protocol::af_inet, 5000, 10000, result); + bool success = cl.bind("https://github.com/", 3478, "invalid_interface", stun::protocol::af_inet, 5000, 10000, result); EXPECT_FALSE(success); EXPECT_FALSE(result.is_valid()); } + diff --git a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp b/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp index 5618a6cb0..a2e1d3f94 100644 --- a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp +++ b/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp @@ -17,12 +17,11 @@ namespace WPEFramework { namespace Plugin { - NetworkManagerImplementation* _instance = nullptr; + NetworkManagerImplementation* _instance; void NetworkManagerImplementation::ReportWiFiSignalStrengthChange(const string ssid, const string strength, const WiFiSignalQuality quality) - { + { return; } - void NetworkManagerImplementation::ReportInternetStatusChange(const InternetStatus prevState, const InternetStatus currState) { return; @@ -33,7 +32,12 @@ namespace WPEFramework class WiFiSignalStrengthMonitorTest : public ::testing::Test { protected: WPEFramework::Plugin::WiFiSignalStrengthMonitor monitor; + void SetUp() override { + } + void TearDown() override { + } }; +#define BUFFER_SIZE 1024 TEST_F(WiFiSignalStrengthMonitorTest, GetSignalData_Connected) { std::string ssid = "TestSSID"; @@ -43,10 +47,12 @@ TEST_F(WiFiSignalStrengthMonitorTest, GetSignalData_Connected) { } TEST_F(WiFiSignalStrengthMonitorTest, StartWiFiSignalStrengthMonitor) { - monitor.startWiFiSignalStrengthMonitor(1); + monitor.startWiFiSignalStrengthMonitor(1); + } int main(int argc, char **argv) { ::testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); } + diff --git a/Tests/unit_test/unit_tests.cmake b/Tests/unit_test/tests.cmake similarity index 96% rename from Tests/unit_test/unit_tests.cmake rename to Tests/unit_test/tests.cmake index 9c56c2428..82d2cd928 100644 --- a/Tests/unit_test/unit_tests.cmake +++ b/Tests/unit_test/tests.cmake @@ -1,4 +1,5 @@ -set(UNIT_TEST "unit_tests") +cmake_minimum_required(VERSION 3.10) +set(UNIT_TEST "tests") find_package(PkgConfig REQUIRED) pkg_check_modules(GLIB REQUIRED glib-2.0) @@ -21,12 +22,10 @@ add_executable(${UNIT_TEST} NetworkManagerConnectivity.cpp NetworkManagerStunClient.cpp ) - set_target_properties(${UNIT_TEST} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES ) - target_compile_options(${UNIT_TEST} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") @@ -44,3 +43,4 @@ target_include_directories(${UNIT_TEST} PRIVATE target_link_libraries(${UNIT_TEST} PRIVATE gmock_main ${NAMESPACE}Core::${NAMESPACE}Core ${GLIB_LIBRARIES} ${GIO_LIBRARIES} ${LIBNM_LIBRARIES} ${CURL_LIBRARIES}) target_include_directories(${UNIT_TEST} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) install(TARGETS ${UNIT_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) + From 330ed6c6091c10ea53471593a71d3d0dd1e043f2 Mon Sep 17 00:00:00 2001 From: parvathika <131966254+parvathika@users.noreply.github.com> Date: Fri, 13 Dec 2024 19:27:44 +0530 Subject: [PATCH 058/271] To fix the workflow issue (#58) * fix the workflow issue * Update gnome_unit_test.yml --- .github/workflows/gnome_unit_test.yml | 2 +- .../unit_test/test_NetworkManagerConnectivity.cpp | 15 --------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index 107e6e455..c186b0629 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -12,7 +12,7 @@ env: jobs: unit-tests: name: Build and run unit tests - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Configure cache diff --git a/Tests/unit_test/test_NetworkManagerConnectivity.cpp b/Tests/unit_test/test_NetworkManagerConnectivity.cpp index f175a929b..1d04623ea 100644 --- a/Tests/unit_test/test_NetworkManagerConnectivity.cpp +++ b/Tests/unit_test/test_NetworkManagerConnectivity.cpp @@ -1,20 +1,5 @@ #include "NetworkManagerImplementation.h" #include "NetworkManagerConnectivity.h" -#include "WiFiSignalStrengthMonitor.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include From 5d9c79e6449cc437b4425c1699091883f2952e38 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 13 Dec 2024 16:08:24 -0500 Subject: [PATCH 059/271] RDKEMW-540 : Update the WPS Approach (#56) - Updated the WPS Approach - Renamed the member variables of the class - Updated the logging --- NetworkManagerGnomeWIFI.cpp | 382 ++++++++++++++++++++++-------------- NetworkManagerGnomeWIFI.h | 40 ++-- 2 files changed, 262 insertions(+), 160 deletions(-) diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 64be90163..4bb0f3871 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -51,24 +51,24 @@ namespace WPEFramework { extern NetworkManagerImplementation* _instance; - wifiManager::wifiManager() : client(nullptr), loop(nullptr), createNewConnection(false) { + wifiManager::wifiManager() : m_client(nullptr), m_loop(nullptr), m_createNewConnection(false) { NMLOG_INFO("wifiManager"); - nmContext = g_main_context_new(); - g_main_context_push_thread_default(nmContext); - loop = g_main_loop_new(nmContext, FALSE); + m_nmContext = g_main_context_new(); + g_main_context_push_thread_default(m_nmContext); + m_loop = g_main_loop_new(m_nmContext, FALSE); } bool wifiManager::createClientNewConnection() { GError *error = NULL; - if(client != nullptr) + if(m_client != nullptr) { - g_object_unref(client); - client = nullptr; + g_object_unref(m_client); + m_client = nullptr; } - client = nm_client_new(NULL, &error); - if (!client || !loop) { + m_client = nm_client_new(NULL, &error); + if (!m_client || !m_loop) { NMLOG_ERROR("Could not connect to NetworkManager: %s.", error->message); g_error_free(error); return false; @@ -78,17 +78,12 @@ namespace WPEFramework bool wifiManager::quit(NMDevice *wifiNMDevice) { - if (wifiNMDevice && wifiDeviceStateGsignal > 0) { - g_signal_handler_disconnect(wifiNMDevice, wifiDeviceStateGsignal); - wifiDeviceStateGsignal = 0; - } - - if(!g_main_loop_is_running(loop)) { + if(!g_main_loop_is_running(m_loop)) { NMLOG_ERROR("g_main_loop_is not running"); return false; } - g_main_loop_quit(loop); + g_main_loop_quit(m_loop); return false; } @@ -96,8 +91,8 @@ namespace WPEFramework { wifiManager *_wifiManager = (static_cast(user_data)); NMLOG_WARNING("GmainLoop ERROR_TIMEDOUT"); - _wifiManager->isSuccess = false; - g_main_loop_quit(_wifiManager->loop); + _wifiManager->m_isSuccess = false; + g_main_loop_quit(_wifiManager->m_loop); return true; } @@ -107,18 +102,18 @@ namespace WPEFramework NMLOG_WARNING("g_main_loop_is running"); return false; } - source = g_timeout_source_new(timeOutMs); // 10000ms interval - g_source_set_callback(source, (GSourceFunc)gmainLoopTimoutCB, this, NULL); - g_source_attach(source, NULL); + m_source = g_timeout_source_new(timeOutMs); // 10000ms interval + g_source_set_callback(m_source, (GSourceFunc)gmainLoopTimoutCB, this, NULL); + g_source_attach(m_source, NULL); g_main_loop_run(loop); - if(source != nullptr) { - if(g_source_is_destroyed(source)) { + if(m_source != nullptr) { + if(g_source_is_destroyed(m_source)) { NMLOG_WARNING("Source has been destroyed"); } else { - g_source_destroy(source); + g_source_destroy(m_source); } - g_source_unref(source); + g_source_unref(m_source); } return true; } @@ -127,7 +122,7 @@ namespace WPEFramework { NMDevice *wifiDevice = NULL; - GPtrArray *devices = const_cast(nm_client_get_devices(client)); + GPtrArray *devices = const_cast(nm_client_get_devices(m_client)); if (devices == NULL) { NMLOG_ERROR("Failed to get device list."); return wifiDevice; @@ -294,7 +289,7 @@ namespace WPEFramework wifiManager *_wifiManager = (static_cast(user_data)); NMLOG_DEBUG("Disconnecting... "); - _wifiManager->isSuccess = true; + _wifiManager->m_isSuccess = true; if (!nm_device_disconnect_finish(device, result, &error)) { if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; @@ -305,7 +300,7 @@ namespace WPEFramework error->message); g_error_free(error); _wifiManager->quit(device); - _wifiManager->isSuccess = false; + _wifiManager->m_isSuccess = false; } _wifiManager->quit(device); } @@ -322,8 +317,8 @@ namespace WPEFramework } nm_device_disconnect_async(wifiNMDevice, NULL, disconnectCb, this); - wait(loop); - return isSuccess; + wait(m_loop); + return m_isSuccess; } static NMAccessPoint *checkSSIDAvailable(NMDevice *device, const char *ssid) @@ -361,27 +356,27 @@ namespace WPEFramework GError *error = NULL; wifiManager *_wifiManager = (static_cast(user_data)); - if (_wifiManager->createNewConnection) { + if (_wifiManager->m_createNewConnection) { NMLOG_DEBUG("nm_client_add_and_activate_connection_finish"); - nm_client_add_and_activate_connection_finish(NM_CLIENT(_wifiManager->client), result, &error); - _wifiManager->isSuccess = true; + nm_client_add_and_activate_connection_finish(NM_CLIENT(_wifiManager->m_client), result, &error); + _wifiManager->m_isSuccess = true; } else { NMLOG_DEBUG("nm_client_activate_connection_finish "); - nm_client_activate_connection_finish(NM_CLIENT(_wifiManager->client), result, &error); - _wifiManager->isSuccess = true; + nm_client_activate_connection_finish(NM_CLIENT(_wifiManager->m_client), result, &error); + _wifiManager->m_isSuccess = true; } if (error) { - _wifiManager->isSuccess = false; - if (_wifiManager->createNewConnection) { + _wifiManager->m_isSuccess = false; + if (_wifiManager->m_createNewConnection) { NMLOG_ERROR("Failed to add/activate new connection: %s", error->message); } else { NMLOG_ERROR("Failed to activate connection: %s", error->message); } } - g_main_loop_quit(_wifiManager->loop); + g_main_loop_quit(_wifiManager->m_loop); } static void removeKnownSSIDCb(GObject *client, GAsyncResult *result, gpointer user_data) @@ -391,12 +386,12 @@ namespace WPEFramework NMRemoteConnection *connection = NM_REMOTE_CONNECTION(client); if (!nm_remote_connection_delete_finish(connection, result, &error)) { NMLOG_ERROR("RemoveKnownSSID failed %s", error->message); - _wifiManager->isSuccess = false; + _wifiManager->m_isSuccess = false; } else { NMLOG_INFO ("RemoveKnownSSID is success"); - _wifiManager->isSuccess = true; + _wifiManager->m_isSuccess = true; } _wifiManager->quit(NULL); @@ -414,13 +409,13 @@ namespace WPEFramework if (!ret) { NMLOG_ERROR("Error: %s.", error->message); g_error_free(error); - _wifiManager->isSuccess = false; + _wifiManager->m_isSuccess = false; _wifiManager->quit(NULL); return; } - _wifiManager->createNewConnection = false; // no need to create new connection + _wifiManager->m_createNewConnection = false; // no need to create new connection nm_client_activate_connection_async( - _wifiManager->client, NM_CONNECTION(remote_con), _wifiManager->wifidevice, _wifiManager->objectPath, NULL, wifiConnectCb, _wifiManager); + _wifiManager->m_client, NM_CONNECTION(remote_con), _wifiManager->m_wifidevice, _wifiManager->m_objectPath, NULL, wifiConnectCb, _wifiManager); } static bool connectionBuilder(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo, NMConnection *m_connection) @@ -575,7 +570,7 @@ namespace WPEFramework NMConnection *m_connection = NULL; const GPtrArray *availableConnections; bool SSIDmatch = false; - isSuccess = false; + m_isSuccess = false; if(!createClientNewConnection()) return false; @@ -662,18 +657,18 @@ namespace WPEFramework { NMLOG_DEBUG("creating new connection '%s' ", ssidInfo.ssid.c_str()); m_connection = nm_simple_connection_new(); - objectPath = nm_object_get_path(NM_OBJECT(AccessPoint)); + m_objectPath = nm_object_get_path(NM_OBJECT(AccessPoint)); if(!connectionBuilder(ssidInfo, m_connection)) { NMLOG_ERROR("connection builder failed"); return false; } - createNewConnection = true; - nm_client_add_and_activate_connection_async(client, m_connection, device, objectPath, NULL, wifiConnectCb, this); + m_createNewConnection = true; + nm_client_add_and_activate_connection_async(m_client, m_connection, device, m_objectPath, NULL, wifiConnectCb, this); } - wait(loop); - return isSuccess; + wait(m_loop); + return m_isSuccess; } static void addToKnownSSIDsUpdateCb(GObject *rmObject, GAsyncResult *res, gpointer user_data) @@ -688,12 +683,12 @@ namespace WPEFramework if (!ret) { NMLOG_ERROR("Error: %s.", error->message); g_error_free(error); - _wifiManager->isSuccess = false; + _wifiManager->m_isSuccess = false; NMLOG_ERROR("AddToKnownSSIDs failed"); } else { - _wifiManager->isSuccess = true; + _wifiManager->m_isSuccess = true; NMLOG_INFO("AddToKnownSSIDs success"); } _wifiManager->quit(NULL); @@ -706,20 +701,20 @@ namespace WPEFramework GVariant **outResult = NULL; if (!nm_client_add_connection2_finish(NM_CLIENT(client), result, outResult, &error)) { NMLOG_ERROR("AddToKnownSSIDs Failed"); - _wifiManager->isSuccess = false; + _wifiManager->m_isSuccess = false; } else { NMLOG_INFO("AddToKnownSSIDs success"); - _wifiManager->isSuccess = true; + _wifiManager->m_isSuccess = true; } - g_main_loop_quit(_wifiManager->loop); + g_main_loop_quit(_wifiManager->m_loop); } bool wifiManager::addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo ssidinfo) { - isSuccess = false; + m_isSuccess = false; NMConnection *m_connection = NULL; if(!createClientNewConnection()) @@ -766,22 +761,22 @@ namespace WPEFramework NMLOG_ERROR("connection builder failed"); return false; } - createNewConnection = true; + m_createNewConnection = true; GVariant *connSettings = nm_connection_to_dbus(m_connection, NM_CONNECTION_SERIALIZE_ALL); - nm_client_add_connection2(client, + nm_client_add_connection2(m_client, connSettings, NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK, NULL, TRUE, NULL, addToKnownSSIDsCb, this); } - wait(loop); - return isSuccess; + wait(m_loop); + return m_isSuccess; } bool wifiManager::removeKnownSSID(const string& ssid) { NMConnection *m_connection = NULL; - isSuccess = false; + m_isSuccess = false; if(!createClientNewConnection()) return false; @@ -792,7 +787,7 @@ namespace WPEFramework return false; } - const GPtrArray *allconnections = nm_client_get_connections(client); + const GPtrArray *allconnections = nm_client_get_connections(m_client); for (guint i = 0; i < allconnections->len; i++) { NMConnection *connection = static_cast(g_ptr_array_index(allconnections, i)); @@ -813,7 +808,7 @@ namespace WPEFramework removeKnownSSIDCb, this); } - wait(loop); + wait(m_loop); break; // multiple connection with same name not handiled } } @@ -821,14 +816,14 @@ namespace WPEFramework if(!m_connection) NMLOG_INFO("'%s' no such connection profile", ssid.c_str()); - return isSuccess; + return m_isSuccess; } bool wifiManager::getKnownSSIDs(std::list& ssids) { if(!createClientNewConnection()) return false; - const GPtrArray *connections = nm_client_get_connections(client); + const GPtrArray *connections = nm_client_get_connections(m_client); std::string ssidPrint; for (guint i = 0; i < connections->len; i++) { @@ -866,20 +861,20 @@ namespace WPEFramework wifiManager *_wifiManager = (static_cast(user_data)); if(nm_device_wifi_request_scan_finish(NM_DEVICE_WIFI(object), result, &error)) { NMLOG_DEBUG("Scanning success"); - _wifiManager->isSuccess = true; + _wifiManager->m_isSuccess = true; } else { NMLOG_ERROR("Scanning Failed"); - _wifiManager->isSuccess = false; + _wifiManager->m_isSuccess = false; } if (error) { NMLOG_ERROR("Scanning Failed Error: %s.", error->message); - _wifiManager->isSuccess = false; + _wifiManager->m_isSuccess = false; g_error_free(error); } - g_main_loop_quit(_wifiManager->loop); + g_main_loop_quit(_wifiManager->m_loop); } bool wifiManager::wifiScanRequest(std::string ssidReq) @@ -891,7 +886,7 @@ namespace WPEFramework NMLOG_FATAL("NMDeviceWifi * NULL !"); return false; } - isSuccess = false; + m_isSuccess = false; if(!ssidReq.empty() && ssidReq != "null") { NMLOG_INFO("staring wifi scanning .. %s", ssidReq.c_str()); @@ -910,8 +905,8 @@ namespace WPEFramework NMLOG_DEBUG("staring normal wifi scanning"); nm_device_wifi_request_scan_async(wifiDevice, NULL, wifiScanCb, this); } - wait(loop); - return isSuccess; + wait(m_loop); + return m_isSuccess; } bool wifiManager::isWifiScannedRecently(int timelimitInSec) @@ -945,6 +940,23 @@ namespace WPEFramework return false; } + std::string wifiManager::executeWpaCliCommand(const std::string& wpaCliCommand) { + std::array buffer; + std::string wpaCliResult; + FILE* fp = popen(wpaCliCommand.c_str(), "r"); + if (fp == nullptr) { + NMLOG_ERROR("Failed to run command: %s", wpaCliCommand.c_str()); + return "ERROR"; + } + + while (fgets(buffer.data(), buffer.size(), fp) != nullptr) { + wpaCliResult += buffer.data(); + } + pclose(fp); + NMLOG_DEBUG("Command output: %s", wpaCliResult.c_str()); + return wpaCliResult; + } + void wifiManager::wpsAction() { FILE *fp = nullptr; @@ -954,98 +966,168 @@ namespace WPEFramework std::string passphrasePattern = "psk="; std::string security = "", ssid = "", passphrase = ""; Exchange::INetworkManager::WiFiConnectTo wifiData = {}; - std::array buffer = {}; std::string wpaCliResult = ""; gboolean wpsConnect = false; struct timespec startTime = {}, endTime = {}; long timeDiff = 0; + long wpsPBCDuration = 0; int count = 0; bool scanResult = false; bool ssidFound = false; const char* bssid = nullptr; gboolean pbcFound = false; const GPtrArray *aps; + wifi_wps_pbc_ap_t apList[MAX_WPS_AP_COUNT]; + int wpsApCount = 0; - - if (!wpsContext || !g_main_context_acquire(wpsContext)) + if (!m_wpsContext || !g_main_context_acquire(m_wpsContext)) { NMLOG_ERROR("Failed to acquire wpsContext"); + if (m_wpsContext) { + g_main_context_unref(m_wpsContext); + m_wpsContext = nullptr; + } return; } - g_main_context_push_thread_default(wpsContext); + g_main_context_push_thread_default(m_wpsContext); + clock_gettime(CLOCK_MONOTONIC, &startTime); do{ sleep(10); - loop = g_main_loop_new(wpsContext, FALSE); + m_loop = g_main_loop_new(m_wpsContext, FALSE); scanResult = wifiScanRequest(""); - loop = g_main_loop_new(nmContext, FALSE); + m_loop = g_main_loop_new(m_nmContext, FALSE); + NMLOG_DEBUG("Wifi scan result = %d", scanResult); if(scanResult) { aps = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(getWifiDevice())); - for (guint i = 0; i < aps->len; i++) { - NMAccessPoint *ap = static_cast(g_ptr_array_index(aps, i)); + for (guint apCount = 0; apCount < aps->len; apCount++) { + NMAccessPoint *ap = static_cast(g_ptr_array_index(aps, apCount)); guint32 flags = nm_access_point_get_flags(ap); + GBytes *ssid; + gsize size; + std::string ssidStr; - if (flags & NM_802_11_AP_FLAGS_WPS_PBC) + NMLOG_DEBUG("Access point flag value : %u", flags); + if ((flags & NM_802_11_AP_FLAGS_WPS_PBC) && (wpsApCount < MAX_WPS_AP_COUNT)) { + clock_gettime(CLOCK_MONOTONIC, &endTime); + NMLOG_DEBUG("WPS Push button event is received"); bssid = nm_access_point_get_bssid(ap); + if (bssid != NULL) { + strncpy(apList[wpsApCount].bssid, bssid, sizeof(apList[wpsApCount].bssid) - 1); + apList[wpsApCount].bssid[sizeof(apList[wpsApCount].bssid) - 1] = '\0'; + } + NMLOG_DEBUG("PBC enabled access point bssid = %s", bssid); + ssid = nm_access_point_get_ssid(ap); + const guint8 *ssidData = static_cast(g_bytes_get_data(ssid, &size)); + std::string ssidTmp(reinterpret_cast(ssidData), size); + strncpy(apList[wpsApCount].ssid, ssidTmp.c_str(), sizeof(apList[wpsApCount].ssid) - 1); + apList[wpsApCount].ssid[sizeof(apList[wpsApCount].ssid) - 1] = '\0'; + NMLOG_INFO("PBC enabled access point ssid: %s", apList[wpsApCount].ssid); pbcFound = true; - break; + wpsApCount++; } } + if(pbcFound) + break; } count++; + clock_gettime(CLOCK_MONOTONIC, &endTime); }while(count < 10 && !pbcFound && !wpsStop.load()); + wpsPBCDuration = (endTime.tv_sec - startTime.tv_sec); if(!pbcFound || wpsStop.load()) { - g_main_context_pop_thread_default(wpsContext); - g_main_context_release(wpsContext); + g_main_context_pop_thread_default(m_wpsContext); + g_main_context_release(m_wpsContext); + if (m_wpsContext) { + g_main_context_unref(m_wpsContext); + m_wpsContext = nullptr; + } return; } - std::string wpaCliCommand = "wpa_cli disconnect && wpa_cli -i " + std::string(nmUtils::wlanIface()) + " abort_scan && wpa_cli -i " + std::string(nmUtils::wlanIface()) + " bss_flush 0 && wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_pbc " + std::string(bssid); - fp = popen(wpaCliCommand.c_str(), "r"); - if (fp == nullptr) + std::string command1 = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " disconnect && "; + std::string command2 = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " remove_network 0 && "; + std::string command3 = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " save_config && "; + std::string command4 = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " abort_scan && "; + std::string command5 = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " bss_flush 0"; + std::string wpaCliCommand = command1 + command2 + command3 + command4 + command5; + NMLOG_DEBUG("Initial wps command = %s", wpaCliCommand.c_str()); + wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliCommand); + if (wpaCliResult == "ERROR") { NMLOG_ERROR("WPS failed to connect with the SSID"); - g_main_context_pop_thread_default(wpsContext); - g_main_context_release(wpsContext); + g_main_context_pop_thread_default(m_wpsContext); + g_main_context_release(m_wpsContext); + if (m_wpsContext) { + g_main_context_unref(m_wpsContext); + m_wpsContext = nullptr; + } return ; } - pclose(fp); - std::string wpaCliStatus = WPA_CLI_STATUS; - clock_gettime(CLOCK_MONOTONIC, &startTime); - while(!wpsStop.load()) + NMLOG_DEBUG("Initial wps command output = %s", wpaCliResult.c_str()); + wpaCliCommand.clear(); + for(guint wpsPbcAp=0; wpsPbcAp < wpsApCount && !wpsConnect && !wpsStop.load(); wpsPbcAp++) { - fp = popen(wpaCliStatus.c_str(), "r"); - if (fp == nullptr) + wpaCliCommand = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_pbc " + std::string(apList[wpsPbcAp].bssid); + NMLOG_DEBUG("wpacli pbc command with bssid = %s", wpaCliCommand.c_str()); + NMLOG_INFO("Connecting with the SSID = %s", apList[wpsPbcAp].ssid); + wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliCommand); + if (wpaCliResult == "ERROR") { - NMLOG_ERROR("WPS not able to fetch the connection status"); - continue; - } - while (fgets(buffer.data(), buffer.size(), fp) != nullptr) - { - wpaCliResult += buffer.data(); + NMLOG_ERROR("WPS failed to connect with the SSID"); + g_main_context_pop_thread_default(m_wpsContext); + g_main_context_release(m_wpsContext); + if (m_wpsContext) { + g_main_context_unref(m_wpsContext); + m_wpsContext = nullptr; + } + return ; } - pclose(fp); - wpsConnect = (wpaCliResult.find("wpa_state=COMPLETED") != std::string::npos); - clock_gettime(CLOCK_MONOTONIC, &endTime); - timeDiff = (endTime.tv_sec - startTime.tv_sec); - NMLOG_DEBUG("Time elapsed before getting wifi connected = %ld", timeDiff); - if(wpsConnect || timeDiff > 20) + NMLOG_DEBUG("wps pbc connect output = %s", wpaCliResult.c_str()); + std::string wpaCliStatus = WPA_CLI_STATUS; + startTime = {}, endTime = {}; + wpaCliResult.clear(); + clock_gettime(CLOCK_MONOTONIC, &startTime); + while(!wpsStop.load()) { - NMLOG_WARNING("WPS Connect status = %d; took %ld seconds", wpsConnect, (100 + timeDiff)); - break; + wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliStatus); + if (wpaCliResult == "ERROR") + { + NMLOG_ERROR("WPS not able to fetch the connection status"); + continue; + } + NMLOG_DEBUG("wpacli status = %s", wpaCliResult.c_str()); + wpsConnect = (wpaCliResult.find("wpa_state=COMPLETED") != std::string::npos); + clock_gettime(CLOCK_MONOTONIC, &endTime); + timeDiff = (endTime.tv_sec - startTime.tv_sec); + NMLOG_DEBUG("Time elapsed in getting state completed = %ld", timeDiff); + if(wpsConnect || timeDiff > 20) + { + NMLOG_WARNING("WPS Connect status = %d; took %ld seconds", wpsConnect, (wpsPBCDuration + timeDiff)); + break; + } + sleep(3); } - sleep(5); } if(!wpsConnect) { - g_main_context_pop_thread_default(wpsContext); - g_main_context_release(wpsContext);/* TODO: Need to disconnect the wpa_cli connection, as the libnm is not aware of the connection created by wpa_cli */ + g_main_context_pop_thread_default(m_wpsContext); + g_main_context_release(m_wpsContext);/* TODO: Need to disconnect the wpa_cli connection, as the libnm is not aware of the connection created by wpa_cli */ + wpaCliCommand.clear(); + wpaCliResult.clear(); + wpaCliCommand = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_cancel"; + wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliCommand); + if (wpaCliResult == "ERROR") + NMLOG_ERROR("WPS cancel failed"); + if (m_wpsContext) { + g_main_context_unref(m_wpsContext); + m_wpsContext = nullptr; + } return; } @@ -1056,8 +1138,12 @@ namespace WPEFramework if (!configFile.is_open()) { NMLOG_ERROR("WPS connected with an SSID but not able to fetch IP address"); - g_main_context_pop_thread_default(wpsContext); - g_main_context_release(wpsContext); + g_main_context_pop_thread_default(m_wpsContext); + g_main_context_release(m_wpsContext); + if (m_wpsContext) { + g_main_context_unref(m_wpsContext); + m_wpsContext = nullptr; + } return; } @@ -1127,31 +1213,41 @@ namespace WPEFramework wifiData.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES; else if(security == "WPA2-PSK") wifiData.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES; - loop = g_main_loop_new(wpsContext, FALSE); + m_loop = g_main_loop_new(m_wpsContext, FALSE); if(this->wifiConnect(wifiData)) NMLOG_INFO("NetworkManager updated with WPS status - connected successfully"); else + { NMLOG_ERROR("NetworkManager is not able to sync up with underneath wpa_supplicant/hal regarding the WPS connect"); /* TODO: Need to disconnect the wpa_cli connection, as the libnm is not aware of the connection created by wpa_cli */ - loop = g_main_loop_new(nmContext, FALSE); + wpaCliCommand.clear(); + wpaCliResult.clear(); + wpaCliCommand = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_cancel"; + wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliCommand); + if (wpaCliResult == "ERROR") + { + NMLOG_ERROR("WPS cancel failed"); + } + } + m_loop = g_main_loop_new(m_nmContext, FALSE); } } - g_main_context_pop_thread_default(wpsContext); - g_main_context_release(wpsContext); - if (wpsContext) { - g_main_context_unref(wpsContext); - wpsContext = nullptr; + g_main_context_pop_thread_default(m_wpsContext); + g_main_context_release(m_wpsContext); + if (m_wpsContext) { + g_main_context_unref(m_wpsContext); + m_wpsContext = nullptr; } return; } bool wifiManager::initiateWPS() { - if(!wpsContext){ + if(!m_wpsContext){ if (wpsThread.joinable()) { wpsThread.join(); } - wpsContext = g_main_context_new(); - if (!wpsContext) { + m_wpsContext = g_main_context_new(); + if (!m_wpsContext) { NMLOG_ERROR("Failed to create new main context for WPS"); return false; } @@ -1170,9 +1266,9 @@ namespace WPEFramework if (wpsThread.joinable()) { wpsThread.join(); } - if (wpsContext) { - g_main_context_unref(wpsContext); - wpsContext = nullptr; + if (m_wpsContext) { + g_main_context_unref(m_wpsContext); + m_wpsContext = nullptr; } wpsStop.store(false); return true; @@ -1191,10 +1287,10 @@ namespace WPEFramework NMLOG_ERROR("Failed to set Managed property: %s", error->message); g_error_free(error); - _wifiManager->isSuccess = false; + _wifiManager->m_isSuccess = false; } else { NMLOG_DEBUG("Successfully set Managed property."); - _wifiManager->isSuccess = true; + _wifiManager->m_isSuccess = true; } _wifiManager->quit(nullptr); @@ -1202,16 +1298,16 @@ namespace WPEFramework bool wifiManager::setInterfaceState(std::string interface, bool enabled) { - isSuccess = false; + m_isSuccess = false; NMDevice *device = nullptr; if (!createClientNewConnection()) return false; - GPtrArray *devices = const_cast(nm_client_get_devices(client)); + GPtrArray *devices = const_cast(nm_client_get_devices(m_client)); if (devices == nullptr) { NMLOG_ERROR("Failed to get device list."); - return isSuccess; + return m_isSuccess; } for (guint j = 0; j < devices->len; j++) { @@ -1243,7 +1339,7 @@ namespace WPEFramework else if (deviceState > NM_DEVICE_STATE_DISCONNECTED) { nm_device_disconnect_async(device, nullptr, disconnectCb, this); - wait(loop); + wait(m_loop); sleep(1); // to remove the connection } } @@ -1251,10 +1347,10 @@ namespace WPEFramework const char *objectPath = nm_object_get_path(NM_OBJECT(device)); GVariant *value = g_variant_new_boolean(enabled); - nm_client_dbus_set_property( client, objectPath, NM_DBUS_INTERFACE_DEVICE,"Managed", + nm_client_dbus_set_property( m_client, objectPath, NM_DBUS_INTERFACE_DEVICE,"Managed", value, -1, nullptr, deviceManagedCb, this); - wait(loop); - return isSuccess; + wait(m_loop); + return m_isSuccess; } static void onActivateComplete(GObject *source_object, GAsyncResult *res, gpointer user_data) @@ -1266,10 +1362,10 @@ namespace WPEFramework if (!nm_client_activate_connection_finish(NM_CLIENT(source_object), res, &error)) { NMLOG_DEBUG("Activating connection failed: %s", error->message); g_error_free(error); - _wifiManager->isSuccess = false; + _wifiManager->m_isSuccess = false; } else { NMLOG_DEBUG("Activating connection successful"); - _wifiManager->isSuccess = true; + _wifiManager->m_isSuccess = true; } _wifiManager->quit(nullptr); } @@ -1293,7 +1389,7 @@ namespace WPEFramework bool wifiManager::setIpSettings(const string interface, const Exchange::INetworkManager::IPAddress address) { - isSuccess = false; + m_isSuccess = false; NMConnection *connection = NULL; NMRemoteConnection *remoteConn = NULL; NMActiveConnection* activeConnection = NULL; @@ -1304,7 +1400,7 @@ namespace WPEFramework if (!createClientNewConnection()) return false; - device = nm_client_get_device_by_iface(client, interface.c_str()); + device = nm_client_get_device_by_iface(m_client, interface.c_str()); if(device == NULL) return false; @@ -1433,16 +1529,16 @@ namespace WPEFramework specObject = nm_object_get_path(NM_OBJECT(activeConnection)); GError *deactivate_error = NULL; // TODO fix depricated api - if (!nm_client_deactivate_connection(client, activeConnection, NULL, &deactivate_error)) { + if (!nm_client_deactivate_connection(m_client, activeConnection, NULL, &deactivate_error)) { NMLOG_ERROR("Failed to deactivate connection: %s", deactivate_error->message); g_clear_error(&deactivate_error); return false; } } - nm_client_activate_connection_async(client, connection, device, specObject, NULL, onActivateComplete, this); - wait(loop); - return isSuccess; + nm_client_activate_connection_async(m_client, connection, device, specObject, NULL, onActivateComplete, this); + wait(m_loop); + return m_isSuccess; } } // namespace Plugin } // namespace WPEFramework diff --git a/NetworkManagerGnomeWIFI.h b/NetworkManagerGnomeWIFI.h index dcce93ca8..6b7dfe17d 100644 --- a/NetworkManagerGnomeWIFI.h +++ b/NetworkManagerGnomeWIFI.h @@ -32,6 +32,12 @@ #define WPA_SUPPLICANT_CONF "/opt/secure/wifi/wpa_supplicant.conf" #define WPA_CLI_STATUS "wpa_cli status" +#define MAX_WPS_AP_COUNT 3 +typedef struct _wifi_wps_pbc_ap +{ + char bssid[32]; + char ssid[32]; +} wifi_wps_pbc_ap_t; namespace WPEFramework { @@ -60,6 +66,7 @@ namespace WPEFramework bool initiateWPS(); bool cancelWPS(); void wpsAction(); + std::string executeWpaCliCommand(const std::string& wpaCliCommand); bool setInterfaceState(std::string interface, bool enabled); bool setIpSettings(const string interface, const Exchange::INetworkManager::IPAddress address); private: @@ -69,14 +76,14 @@ namespace WPEFramework wifiManager(); ~wifiManager() { NMLOG_INFO("~wifiManager"); - g_main_context_pop_thread_default(nmContext); - if(client != NULL) { - g_object_unref(client); - client = NULL; + g_main_context_pop_thread_default(m_nmContext); + if(m_client != NULL) { + g_object_unref(m_client); + m_client = NULL; } - if(loop != NULL) { - g_main_loop_unref(loop); - loop = NULL; + if(m_loop != NULL) { + g_main_loop_unref(m_loop); + m_loop = NULL; } } @@ -88,16 +95,15 @@ namespace WPEFramework std::thread wpsThread; public: - NMClient *client; - GMainLoop *loop; - gboolean createNewConnection; - GMainContext *nmContext = nullptr; - GMainContext *wpsContext = nullptr; - const char* objectPath; - NMDevice *wifidevice; - GSource *source; - guint wifiDeviceStateGsignal = 0; - bool isSuccess = false; + NMClient *m_client; + GMainLoop *m_loop; + gboolean m_createNewConnection; + GMainContext *m_nmContext = nullptr; + GMainContext *m_wpsContext = nullptr; + const char* m_objectPath; + NMDevice *m_wifidevice; + GSource *m_source; + bool m_isSuccess = false; }; } // Plugin } // WPEFramework From e35f170308fed45937bd8a6d51197f0e679a2aff Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 17 Dec 2024 10:47:23 -0500 Subject: [PATCH 060/271] RDKEMW-540 - Changed the wpa_cli completed logic and wifi connect (#59) * Changed the wpa_cli verification completion logic * Changed the wpa_cli verification completion logic --- NetworkManagerGnomeWIFI.cpp | 202 +++++++++++++++--------------------- NetworkManagerGnomeWIFI.h | 2 + 2 files changed, 83 insertions(+), 121 deletions(-) diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 4bb0f3871..adcb4349f 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -965,7 +965,6 @@ namespace WPEFramework std::string ssidPattern = "ssid="; std::string passphrasePattern = "psk="; std::string security = "", ssid = "", passphrase = ""; - Exchange::INetworkManager::WiFiConnectTo wifiData = {}; std::string wpaCliResult = ""; gboolean wpsConnect = false; struct timespec startTime = {}, endTime = {}; @@ -973,7 +972,6 @@ namespace WPEFramework long wpsPBCDuration = 0; int count = 0; bool scanResult = false; - bool ssidFound = false; const char* bssid = nullptr; gboolean pbcFound = false; const GPtrArray *aps; @@ -1009,7 +1007,6 @@ namespace WPEFramework gsize size; std::string ssidStr; - NMLOG_DEBUG("Access point flag value : %u", flags); if ((flags & NM_802_11_AP_FLAGS_WPS_PBC) && (wpsApCount < MAX_WPS_AP_COUNT)) { clock_gettime(CLOCK_MONOTONIC, &endTime); @@ -1040,6 +1037,7 @@ namespace WPEFramework if(!pbcFound || wpsStop.load()) { + NMLOG_ERROR("PBC enabled SSID not found in the scan results"); g_main_context_pop_thread_default(m_wpsContext); g_main_context_release(m_wpsContext); if (m_wpsContext) { @@ -1075,6 +1073,7 @@ namespace WPEFramework wpaCliCommand = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_pbc " + std::string(apList[wpsPbcAp].bssid); NMLOG_DEBUG("wpacli pbc command with bssid = %s", wpaCliCommand.c_str()); NMLOG_INFO("Connecting with the SSID = %s", apList[wpsPbcAp].ssid); + wpaCliResult.clear(); wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliCommand); if (wpaCliResult == "ERROR") { @@ -1087,155 +1086,116 @@ namespace WPEFramework } return ; } - NMLOG_DEBUG("wps pbc connect output = %s", wpaCliResult.c_str()); - std::string wpaCliStatus = WPA_CLI_STATUS; + startTime = {}, endTime = {}; - wpaCliResult.clear(); + int waitTime = (MAX_WPS_WAIT_DURATION - wpsPBCDuration)/wpsApCount; clock_gettime(CLOCK_MONOTONIC, &startTime); - while(!wpsStop.load()) + while(!wpsConnect && !wpsStop.load()) { - wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliStatus); - if (wpaCliResult == "ERROR") - { - NMLOG_ERROR("WPS not able to fetch the connection status"); - continue; - } - NMLOG_DEBUG("wpacli status = %s", wpaCliResult.c_str()); - wpsConnect = (wpaCliResult.find("wpa_state=COMPLETED") != std::string::npos); - clock_gettime(CLOCK_MONOTONIC, &endTime); - timeDiff = (endTime.tv_sec - startTime.tv_sec); - NMLOG_DEBUG("Time elapsed in getting state completed = %ld", timeDiff); - if(wpsConnect || timeDiff > 20) + std::ifstream configFile(WPA_SUPPLICANT_CONF); + if (!configFile.is_open()) { - NMLOG_WARNING("WPS Connect status = %d; took %ld seconds", wpsConnect, (wpsPBCDuration + timeDiff)); - break; + NMLOG_ERROR("WPS connected with an SSID but not able to fetch IP address"); + g_main_context_pop_thread_default(m_wpsContext); + g_main_context_release(m_wpsContext); + if (m_wpsContext) { + g_main_context_unref(m_wpsContext); + m_wpsContext = nullptr; + } + return; } - sleep(3); - } - } - if(!wpsConnect) - { - g_main_context_pop_thread_default(m_wpsContext); - g_main_context_release(m_wpsContext);/* TODO: Need to disconnect the wpa_cli connection, as the libnm is not aware of the connection created by wpa_cli */ - wpaCliCommand.clear(); - wpaCliResult.clear(); - wpaCliCommand = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_cancel"; - wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliCommand); - if (wpaCliResult == "ERROR") - NMLOG_ERROR("WPS cancel failed"); - if (m_wpsContext) { - g_main_context_unref(m_wpsContext); - m_wpsContext = nullptr; - } - return; - } - - count = 0; - while(count < 2 && !ssidFound) - { - std::ifstream configFile(WPA_SUPPLICANT_CONF); - if (!configFile.is_open()) - { - NMLOG_ERROR("WPS connected with an SSID but not able to fetch IP address"); - g_main_context_pop_thread_default(m_wpsContext); - g_main_context_release(m_wpsContext); - if (m_wpsContext) { - g_main_context_unref(m_wpsContext); - m_wpsContext = nullptr; - } - return; - } - - while (std::getline(configFile, line)) - { - NMLOG_DEBUG("Attempting to read the configuration to populate SSID specific information"); - size_t pos; - - // Fetch ssid value - pos = line.find(ssidPattern); - if (pos != std::string::npos) + while (std::getline(configFile, line)) { - pos += ssidPattern.length(); - size_t end = line.find('"', pos + 1); - if (end == std::string::npos) - { - end = line.length(); - } - ssid = line.substr(pos + 1, end - pos - 1); - ssidFound = true; - NMLOG_DEBUG("SSID found"); - continue; - } + NMLOG_DEBUG("Attempting to read the configuration to populate SSID specific information"); + size_t pos; - if (ssidFound) { - // Fetch security value - pos = line.find(securityPattern); + // Fetch ssid value + pos = line.find(ssidPattern); if (pos != std::string::npos) { - pos += securityPattern.length(); - size_t end = line.find(' ', pos); + pos += ssidPattern.length(); + size_t end = line.find('"', pos + 1); if (end == std::string::npos) { end = line.length(); } - security = line.substr(pos, end - pos); + ssid = line.substr(pos + 1, end - pos - 1); + wpsConnect = true; + NMLOG_DEBUG("SSID found"); continue; } - // Fetch passphare value - pos = line.find(passphrasePattern); - if (pos != std::string::npos) - { - pos += passphrasePattern.length(); - size_t end = line.find('"', pos + 1); - if (end == std::string::npos) + if (wpsConnect) { + // Fetch security value + pos = line.find(securityPattern); + if (pos != std::string::npos) { - end = line.length(); + pos += securityPattern.length(); + size_t end = line.find(' ', pos); + if (end == std::string::npos) + { + end = line.length(); + } + security = line.substr(pos, end - pos); + continue; } - passphrase = line.substr(pos + 1, end - pos - 1); + + // Fetch passphare value + pos = line.find(passphrasePattern); + if (pos != std::string::npos) + { + pos += passphrasePattern.length(); + size_t end = line.find('"', pos + 1); + if (end == std::string::npos) + { + end = line.length(); + } + passphrase = line.substr(pos + 1, end - pos - 1); + } + NMLOG_DEBUG("Fetched SSID = %s, security = %s", ssid.c_str(), security.c_str()); } - NMLOG_DEBUG("Fetched SSID = %s, security = %s", ssid.c_str(), security.c_str()); } + configFile.close(); + clock_gettime(CLOCK_MONOTONIC, &endTime); + timeDiff = (endTime.tv_sec - startTime.tv_sec); + NMLOG_DEBUG("Time elapsed in getting SSID = %ld", timeDiff); + if(ssid.empty() && timeDiff < waitTime) + { + NMLOG_INFO("connected successfully; attempting to retrive SSID info to persist"); + sleep(5); + } + else + break; } - configFile.close(); - if(ssid.empty()) - { - count++; - NMLOG_INFO("connected successfully; attempting to retrive SSID info to persist"); - sleep(5); - } + } + if(wpsConnect) + { + std::string nmCliCommand1 = "nmcli connection add type wifi ifname " + std::string(nmUtils::wlanIface()) + " con-name " + ssid + " ssid " + ssid + " wifi-sec.psk " + passphrase + " wifi-sec.key-mgmt wpa-psk && "; + std::string nmCliCommand2 = "nmcli connection up " + ssid; + std::string nmCliCommand = nmCliCommand1 + nmCliCommand2; + std::string nmCliResult = ""; + nmCliResult = wifiManager::executeWpaCliCommand(nmCliCommand); + if (nmCliResult != "ERROR") + NMLOG_INFO("NetworkManager updated with WPS status - connected successfully"); else { - wifiData.ssid = ssid; - wifiData.passphrase = passphrase; - if(security == "WPA-PSK") - wifiData.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES; - else if(security == "WPA2-PSK") - wifiData.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES; - m_loop = g_main_loop_new(m_wpsContext, FALSE); - if(this->wifiConnect(wifiData)) - NMLOG_INFO("NetworkManager updated with WPS status - connected successfully"); - else + NMLOG_ERROR("NetworkManager is not able to sync up with underneath wpa_supplicant/hal regarding the WPS connect"); /* TODO: Need to disconnect the wpa_cli connection, as the libnm is not aware of the connection created by wpa_cli */ + wpaCliCommand.clear(); + wpaCliResult.clear(); + wpaCliCommand = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_cancel"; + wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliCommand); + if (wpaCliResult == "ERROR") { - NMLOG_ERROR("NetworkManager is not able to sync up with underneath wpa_supplicant/hal regarding the WPS connect"); /* TODO: Need to disconnect the wpa_cli connection, as the libnm is not aware of the connection created by wpa_cli */ - wpaCliCommand.clear(); - wpaCliResult.clear(); - wpaCliCommand = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_cancel"; - wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliCommand); - if (wpaCliResult == "ERROR") - { - NMLOG_ERROR("WPS cancel failed"); - } + NMLOG_ERROR("WPS cancel failed"); } - m_loop = g_main_loop_new(m_nmContext, FALSE); } } g_main_context_pop_thread_default(m_wpsContext); g_main_context_release(m_wpsContext); if (m_wpsContext) { - g_main_context_unref(m_wpsContext); - m_wpsContext = nullptr; + g_main_context_unref(m_wpsContext); + m_wpsContext = nullptr; } return; } diff --git a/NetworkManagerGnomeWIFI.h b/NetworkManagerGnomeWIFI.h index 6b7dfe17d..4a5bf2a72 100644 --- a/NetworkManagerGnomeWIFI.h +++ b/NetworkManagerGnomeWIFI.h @@ -33,6 +33,8 @@ #define WPA_SUPPLICANT_CONF "/opt/secure/wifi/wpa_supplicant.conf" #define WPA_CLI_STATUS "wpa_cli status" #define MAX_WPS_AP_COUNT 3 +#define MAX_WPS_WAIT_DURATION 120 + typedef struct _wifi_wps_pbc_ap { char bssid[32]; From 35d9bb584cc1a5bfe100f844460c0e89f85b8b9e Mon Sep 17 00:00:00 2001 From: Simon Chung Date: Thu, 19 Dec 2024 11:41:34 +0000 Subject: [PATCH 061/271] RDKECMF-223 Add CODEOWNERS file --- .github/CODEOWNERS | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..42b93c904 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# @global-owner1 and @global-owner2 will be requested for +# review when someone opens a pull request. +* @rdkcentral/networkmanager-maintainers From a3089a5d3a2b9370a98200e4044d1eaba19abdc4 Mon Sep 17 00:00:00 2001 From: Stephen Barrett Date: Thu, 19 Dec 2024 11:53:06 +0000 Subject: [PATCH 062/271] Merge pull request #61 from rdkcentral/feature/test-workflows RDKECMF-223 Add CODEOWNERS file From 9e3aef1df3d8ff2fc6741205b02fceb26e2faac7 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Wed, 4 Dec 2024 19:58:41 +0530 Subject: [PATCH 063/271] DELIA-66968 Disable continuous connectivity monitor when Interface is disconnected (#51) * DELIA-66968 Disable continuous connectivity monitor when Interface is disconnected * unit test modified --------- Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- .github/workflows/gnome_unit_test.yml | 2 +- CMakeLists.txt | 2 +- NetworkManagerConnectivity.cpp | 93 +++++++++++-------- NetworkManagerConnectivity.h | 9 +- NetworkManagerGnomeProxy.cpp | 20 ++-- NetworkManagerImplementation.cpp | 33 +++++-- NetworkManagerImplementation.h | 6 ++ NetworkManagerRDKProxy.cpp | 71 ++++++++++++-- .../test_NetworkManagerConnectivity.cpp | 76 +++++++-------- .../test_NetworkManagerStunClient.cpp | 42 +-------- .../test_WiFiSignalStrengthMonitor.cpp | 14 +-- .../{tests.cmake => unit_tests.cmake} | 6 +- 12 files changed, 211 insertions(+), 163 deletions(-) rename Tests/unit_test/{tests.cmake => unit_tests.cmake} (96%) diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index c186b0629..3d8fd2782 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -110,7 +110,7 @@ jobs: run: > PATH=${{github.workspace}}/install/usr/bin:${PATH} LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} - tests + unit_tests - name: Generate coverage run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 6937da5ed..3670fe97f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,6 +170,6 @@ write_config(PLUGINS LegacyPlugin_NetworkAPIs CLASSNAME Network LOCATOR lib${PLU write_config(PLUGINS LegacyPlugin_WiFiManagerAPIs CLASSNAME WiFiManager LOCATOR lib${PLUGIN_LEGACY_DEPRECATED_WIFI}.so) if(ENABLE_UNIT_TESTING) - include(Tests/unit_test/tests.cmake) + include(Tests/unit_test/unit_tests.cmake) endif(ENABLE_UNIT_TESTING) diff --git a/NetworkManagerConnectivity.cpp b/NetworkManagerConnectivity.cpp index f76c8b4bc..1a4667e1d 100644 --- a/NetworkManagerConnectivity.cpp +++ b/NetworkManagerConnectivity.cpp @@ -158,7 +158,7 @@ namespace WPEFramework curl_easy_setopt(curl_easy_handle, CURLOPT_TIMEOUT_MS, deadline - current_time()); if ((ipversion == CURL_IPRESOLVE_V4) || (ipversion == CURL_IPRESOLVE_V6)) { - NMLOG_DEBUG("curlopt ipversion = %s reqtyp = %s", ipversion == CURL_IPRESOLVE_V4?"ipv4 only":"ipv6 only", headReq? "HEAD":"GET"); + NMLOG_DEBUG("curlopt ipversion = %s reqtyp = %s", ipversion == CURL_IPRESOLVE_V4?"IPv4":"IPv6", headReq? "HEAD":"GET"); curl_easy_setopt(curl_easy_handle, CURLOPT_IPRESOLVE, ipversion); } else @@ -324,10 +324,9 @@ namespace WPEFramework doContinuousMonitor = false; doConnectivityMonitor = false; - gInternetState = nsm_internetState::UNKNOWN; - gIpv4InternetState = nsm_internetState::UNKNOWN; - gIpv6InternetState = nsm_internetState::UNKNOWN; - ginterfaceStatus = false; + m_InternetState = nsm_internetState::UNKNOWN; + m_Ipv4InternetState = nsm_internetState::UNKNOWN; + m_Ipv6InternetState = nsm_internetState::UNKNOWN; } ConnectivityMonitor::~ConnectivityMonitor() @@ -390,15 +389,15 @@ namespace WPEFramework // If monitor connectivity is running take the cache value if ( doContinuousMonitor && (nsm_ipversion::NSM_IPRESOLVE_V4 == ipversion || nsm_ipversion::NSM_IPRESOLVE_WHATEVER == ipversion) - && gIpv4InternetState != nsm_internetState::UNKNOWN ) { - NMLOG_WARNING("Reading Ipv4 internet state cached value %s", getInternetStateString(gIpv4InternetState)); - internetState = gIpv4InternetState; + && m_Ipv4InternetState != nsm_internetState::UNKNOWN ) { + NMLOG_WARNING("Reading Ipv4 internet state cached value %s", getInternetStateString(m_Ipv4InternetState)); + internetState = m_Ipv4InternetState; ipversion = NSM_IPRESOLVE_V4; } else if ( doContinuousMonitor && (nsm_ipversion::NSM_IPRESOLVE_V6 == ipversion || nsm_ipversion::NSM_IPRESOLVE_WHATEVER == ipversion) - && gIpv6InternetState != nsm_internetState::UNKNOWN ) { - NMLOG_WARNING("Reading Ipv6 internet state cached value %s", getInternetStateString(gIpv6InternetState)); - internetState = gIpv6InternetState; + && m_Ipv6InternetState != nsm_internetState::UNKNOWN ) { + NMLOG_WARNING("Reading Ipv6 internet state cached value %s", getInternetStateString(m_Ipv6InternetState)); + internetState = m_Ipv6InternetState; ipversion = NSM_IPRESOLVE_V6; } else @@ -425,6 +424,8 @@ namespace WPEFramework bool ConnectivityMonitor::startContinuousConnectivityMonitor(int timeoutInSeconds) { + if(_instance != nullptr ) + NMLOG_INFO("interface status eth - %s wlan - %s ", _instance->m_ethConnected? "up":"down", _instance->m_wlanConnected? "up":"down"); continuousMonitorTimeout.store(timeoutInSeconds >= NMCONNECTIVITY_MONITOR_MIN_INTERVAL ? timeoutInSeconds : NMCONNECTIVITY_MONITOR_DEFAULT_INTERVAL); if (doContinuousMonitor) { @@ -472,12 +473,11 @@ namespace WPEFramework * --> when IP address accuired * --> when etherenet/wifi disconnected */ - bool ConnectivityMonitor::startConnectivityMonitor(bool interfaceStatus) + bool ConnectivityMonitor::startConnectivityMonitor() { - ginterfaceStatus = interfaceStatus; /* this will give interface status connected/ disconnected */ - gInternetState = UNKNOWN; - gIpv4InternetState = UNKNOWN; - gIpv6InternetState = UNKNOWN; + m_InternetState = nsm_internetState::UNKNOWN; + m_Ipv4InternetState = nsm_internetState::UNKNOWN; + m_Ipv6InternetState = nsm_internetState::UNKNOWN; if (doConnectivityMonitor) { cvConnectivityMonitor.notify_one(); @@ -497,21 +497,26 @@ namespace WPEFramework return false; } - NMLOG_ERROR("connectivity monitor started %d", NMCONNECTIVITY_MONITOR_MIN_INTERVAL); + if(_instance != nullptr) { + NMLOG_INFO("connectivity monitor started %d sec - eth %s - wlan %s", NMCONNECTIVITY_MONITOR_MIN_INTERVAL, + _instance->m_ethConnected? "up":"down", _instance->m_wlanConnected? "up":"down"); + } return true; } void ConnectivityMonitor::notifyInternetStatusChangedEvent(nsm_internetState newInternetState) { + static Exchange::INetworkManager::InternetStatus oldState = Exchange::INetworkManager::InternetStatus::INTERNET_UNKNOWN; if(_instance != nullptr) { - Exchange::INetworkManager::InternetStatus oldState = static_cast(gInternetState.load()); + NMLOG_INFO("notify internet state %s", getInternetStateString(newInternetState)); Exchange::INetworkManager::InternetStatus newState = static_cast(newInternetState); _instance->ReportInternetStatusChange(oldState , newState); - gInternetState = newInternetState; + m_InternetState = newInternetState; + oldState = newState; // 'm_InternetState' not exactly previous state, it may change to unknow when interface changed } else - NMLOG_WARNING("NetworkManagerImplementation Instance NULL notifyInternetStatusChange failed."); + NMLOG_FATAL("NetworkManagerImplementation Instance NULL notifyInternetStatusChange failed."); } void ConnectivityMonitor::continuousMonitorFunction() @@ -524,20 +529,31 @@ namespace WPEFramework do { + if(_instance != nullptr && (!_instance->m_ethConnected && !_instance->m_wlanConnected)) // no wifi no ethernet connected + { + NMLOG_DEBUG("no interface connected; no ccm check"); + m_Ipv4InternetState = NO_INTERNET; + m_Ipv6InternetState = NO_INTERNET; + std::unique_lock lock(connMutex); + cvContinuousMonitor.wait_for(lock, std::chrono::seconds(continuousMonitorTimeout.load())); + ipResolveTyp = NSM_IPRESOLVE_WHATEVER; + continue; + } + if(doConnectivityMonitor) { NMLOG_DEBUG("connectivity monitor running so skiping ccm check"); - gIpv4InternetState = UNKNOWN; - gIpv6InternetState = UNKNOWN; + m_Ipv4InternetState = nsm_internetState::UNKNOWN; + m_Ipv6InternetState = nsm_internetState::UNKNOWN; std::unique_lock lock(connMutex); cvContinuousMonitor.wait_for(lock, std::chrono::seconds(continuousMonitorTimeout.load())); - ipResolveTyp = NSM_IPRESOLVE_WHATEVER; /* some interface change happense*/ + ipResolveTyp = NSM_IPRESOLVE_WHATEVER; /* some interface change happense */ continue; } else if (ipResolveTyp == NSM_IPRESOLVE_WHATEVER) { - nsm_internetState ipV4InternetState = UNKNOWN; - nsm_internetState ipV6InternetState = UNKNOWN; + nsm_internetState ipV4InternetState = nsm_internetState::UNKNOWN; + nsm_internetState ipV6InternetState = nsm_internetState::UNKNOWN; auto curlCheckThrdIpv4 = [&]() { TestConnectivity testInternet(getConnectivityMonitorEndpoints(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, NMCONNECTIVITY_CURL_GET_REQUEST, NSM_IPRESOLVE_V4); @@ -573,17 +589,17 @@ namespace WPEFramework NMCONNECTIVITY_CURL_HEAD_REQUEST, ipResolveTyp); currentInternetState = testInternet.getInternetState(); if(ipResolveTyp == NSM_IPRESOLVE_V4) - gIpv4InternetState = currentInternetState; + m_Ipv4InternetState = currentInternetState; else if(ipResolveTyp == NSM_IPRESOLVE_V6) - gIpv6InternetState = currentInternetState; + m_Ipv6InternetState = currentInternetState; } if (currentInternetState == NO_INTERNET) { - if(gInternetState == FULLY_CONNECTED && notifyPreRetry < NMCONNECTIVITY_NO_INTERNET_RETRY_COUNT) + if(m_InternetState == FULLY_CONNECTED && notifyPreRetry < NMCONNECTIVITY_NO_INTERNET_RETRY_COUNT) { /* it will prevent posting notification */ - currentInternetState = gInternetState; + currentInternetState = m_InternetState; TempInterval = 5; NMLOG_INFO("No internet retrying connection check %d ...", notifyPreRetry); notifyPreRetry++; @@ -601,9 +617,8 @@ namespace WPEFramework TempInterval = continuousMonitorTimeout.load(); } - if(gInternetState != currentInternetState) + if(m_InternetState != currentInternetState) { - NMLOG_INFO("Internet state changed to %s", getInternetStateString(currentInternetState)); /* Notify Internet state change */ notifyInternetStatusChangedEvent(currentInternetState); } @@ -619,8 +634,8 @@ namespace WPEFramework } while(doContinuousMonitor); - gIpv4InternetState = UNKNOWN; - gIpv6InternetState = UNKNOWN; + m_Ipv4InternetState = nsm_internetState::UNKNOWN; + m_Ipv6InternetState = nsm_internetState::UNKNOWN; NMLOG_DEBUG("continous connectivity monitor exit"); } @@ -663,8 +678,8 @@ namespace WPEFramework NMLOG_INFO("Connectivity check retrying %d ...", notifyPreRetry); } - if(gInternetState != UNKNOWN) - currentInternetState = gInternetState; + if(m_InternetState != nsm_internetState::UNKNOWN) + currentInternetState = m_InternetState; TempInterval = 5; } else if(tempInternetState != currentInternetState) // last state have change @@ -681,8 +696,9 @@ namespace WPEFramework doConnectivityMonitor = false; // self exit notifyNow = true; // post current state when retry complete } - else if(ginterfaceStatus) // interface is active and still no internet, continue check every 30 sec + else if(_instance != nullptr && (_instance->m_ethConnected | _instance->m_wlanConnected)) { + /* interface is connected and still no internet, continue check every 30 sec */ TempInterval = NMCONNECTIVITY_CONN_MONITOR_RETRY_INTERVAL; /* notify if retry completed and state stil no internet state */ if(notifyPreRetry == NMCONNECTIVITY_CONN_MONITOR_RETRY_COUNT) @@ -699,10 +715,9 @@ namespace WPEFramework } } - if(gInternetState != currentInternetState || notifyNow) + if(m_InternetState != currentInternetState || notifyNow) { notifyNow = false; - NMLOG_INFO("notify internet state %s", getInternetStateString(currentInternetState)); notifyInternetStatusChangedEvent(currentInternetState); } @@ -719,7 +734,7 @@ namespace WPEFramework } while(doConnectivityMonitor); if(!doContinuousMonitor) - gInternetState = nsm_internetState::UNKNOWN; // no continous monitor running reset to unknow + m_InternetState = nsm_internetState::UNKNOWN; // no continous monitor running reset to unknow NMLOG_DEBUG("initial connectivity monitor exit"); } diff --git a/NetworkManagerConnectivity.h b/NetworkManagerConnectivity.h index 26f256fa4..3a5b215a3 100644 --- a/NetworkManagerConnectivity.h +++ b/NetworkManagerConnectivity.h @@ -114,7 +114,7 @@ namespace WPEFramework ~ConnectivityMonitor(); bool startContinuousConnectivityMonitor(int timeoutInSeconds); bool stopContinuousConnectivityMonitor(); - bool startConnectivityMonitor(bool interfaceStatus); + bool startConnectivityMonitor(); void setConnectivityMonitorEndpoints(const std::vector &endpoints); std::vector getConnectivityMonitorEndpoints(); bool isConnectedToInternet(nsm_ipversion ipversion); @@ -140,10 +140,9 @@ namespace WPEFramework EndpointCache endpointCache; std::mutex endpointMutex; - std::atomic ginterfaceStatus; - std::atomic gInternetState; - std::atomic gIpv4InternetState; - std::atomic gIpv6InternetState; + std::atomic m_InternetState; + std::atomic m_Ipv4InternetState; + std::atomic m_Ipv6InternetState; }; } // namespace Plugin } // namespace WPEFramework diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index eb84bef6c..fe1faddd4 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -84,23 +84,25 @@ namespace WPEFramework { NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; Exchange::INetworkManager::InterfaceDetails interface; + interface.mac = nm_device_get_hw_address(device); + deviceState = nm_device_get_state(device); + interface.enabled = (deviceState >= NM_DEVICE_STATE_UNAVAILABLE)? true : false; + if(deviceState > NM_DEVICE_STATE_DISCONNECTED && deviceState < NM_DEVICE_STATE_DEACTIVATING) + interface.connected = true; + else + interface.connected = false; + if(ifaceStr == wifiname) { interface.type = INTERFACE_TYPE_WIFI; interface.name = wifiname; + m_wlanConnected = interface.connected; } if(ifaceStr == ethname) { interface.type = INTERFACE_TYPE_ETHERNET; interface.name = ethname; + m_ethConnected = interface.connected; } - interface.mac = nm_device_get_hw_address(device); - deviceState = nm_device_get_state(device); - interface.enabled = (deviceState >= NM_DEVICE_STATE_UNAVAILABLE) ? true : false; - if(deviceState > NM_DEVICE_STATE_DISCONNECTED && deviceState < NM_DEVICE_STATE_DEACTIVATING){ - interface.connected = true; - m_defaultInterface = interface.name; - } - else - interface.connected = false; + interfaceList.push_back(interface); rc = Core::ERROR_NONE; } diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 6ca6bd9b2..f08fe09cb 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -50,6 +50,8 @@ namespace WPEFramework m_stunCacheTimeout = 0; m_defaultInterface = ""; m_publicIP = ""; + m_ethConnected = false; + m_wlanConnected = false; } NetworkManagerImplementation::~NetworkManagerImplementation() @@ -570,13 +572,22 @@ namespace WPEFramework void NetworkManagerImplementation::ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface) { LOG_ENTRY_FUNCTION(); - if(Exchange::INetworkManager::INTERFACE_LINK_DOWN == state) { + if(Exchange::INetworkManager::INTERFACE_LINK_DOWN == state || Exchange::INetworkManager::INTERFACE_REMOVED == state) { // Start the connectivity monitor with 'false' to indicate the interface is down. // The monitor will automatically exit after the retry attempts are completed, posting a 'noInternet' event. - connectivityMonitor.startConnectivityMonitor(false); + if(interface == "eth0") + m_ethConnected = false; + else + m_wlanConnected = false; + connectivityMonitor.startConnectivityMonitor(); } + /* Only the Ethernet connection status is changing here. The WiFi status is updated in the WiFi state callback. */ + if(Exchange::INetworkManager::INTERFACE_LINK_UP == state && interface == "eth0") + m_ethConnected = true; + _notificationLock.Lock(); + NMLOG_INFO("Posting onInterfaceChange %s - %u", interface.c_str(), (unsigned)state); for (const auto callback : _notificationCallbacks) { callback->onInterfaceStateChange(state, interface); } @@ -585,8 +596,8 @@ namespace WPEFramework void NetworkManagerImplementation::ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface) { - NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); _notificationLock.Lock(); + NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); for (const auto callback : _notificationCallbacks) { callback->onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); } @@ -599,11 +610,11 @@ namespace WPEFramework if (Exchange::INetworkManager::IP_ACQUIRED == status) { // Start the connectivity monitor with 'true' to indicate the interface is up. // The monitor will conntinoue even after no internet retry completed, Exit when fully connectd. - connectivityMonitor.startConnectivityMonitor(true); + connectivityMonitor.startConnectivityMonitor(); } - NMLOG_INFO("Posting onIPAddressChange %s", ipaddress.c_str()); _notificationLock.Lock(); + NMLOG_INFO("Posting onIPAddressChange %s - %s", ipaddress.c_str(), interface.c_str()); for (const auto callback : _notificationCallbacks) { callback->onIPAddressChange(interface, ipversion, ipaddress, status); } @@ -612,8 +623,8 @@ namespace WPEFramework void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) { - NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); _notificationLock.Lock(); + NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); for (const auto callback : _notificationCallbacks) { callback->onInternetStatusChange(prevState, currState); } @@ -644,10 +655,15 @@ namespace WPEFramework { /* start signal strength monitor when wifi connected */ if(INetworkManager::WiFiState::WIFI_STATE_CONNECTED == state) + { + m_wlanConnected = true; m_wifiSignalMonitor.startWiFiSignalStrengthMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC); + } + else + m_wlanConnected = false; /* Any other state is considered as WiFi not connected. */ - NMLOG_INFO("Posting onWiFiStateChange"); _notificationLock.Lock(); + NMLOG_INFO("Posting onWiFiStateChange (%d)", state); for (const auto callback : _notificationCallbacks) { callback->onWiFiStateChange(state); } @@ -656,11 +672,10 @@ namespace WPEFramework void NetworkManagerImplementation::ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) { - NMLOG_INFO("Posting onWiFiSignalStrengthChange"); _notificationLock.Lock(); + NMLOG_INFO("Posting onWiFiSignalStrengthChange %s", strength.c_str()); for (const auto callback : _notificationCallbacks) { callback->onWiFiSignalStrengthChange(ssid, strength, quality); - } _notificationLock.Unlock(); } diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index e8cbd532f..64767f98b 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -25,6 +25,7 @@ #include #include #include +#include using namespace std; @@ -222,9 +223,14 @@ namespace WPEFramework void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); void ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality); + public: + std::atomic m_ethConnected; + std::atomic m_wlanConnected; + private: void platform_init(); void retryIarmEventRegistration(); + void getInitialConnectionState(); void threadEventRegistration(); void executeExternally(NetworkEvents event, const string commandToExecute, string& response); void filterScanResults(JsonArray &ssids); diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 891818722..cbe5c4307 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -457,8 +457,7 @@ namespace WPEFramework { IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t *e = (IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t*) data; interface = e->interface; - NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS: %s - %s - %s", interface.c_str(), e->ip_address, e->acquired?"Acquired":"Lost" -); + NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS: %s - %s - %s", interface.c_str(), e->ip_address, e->acquired?"Acquired":"Lost"); if(interface == "eth0" || interface == "wlan0") { string ipversion("IPv4"); @@ -575,10 +574,57 @@ namespace WPEFramework IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, NetworkManagerInternalEventHandler); NMLOG_INFO("threadEventRegistration successfully subscribed to IARM event for NetworkManager Plugin"); + /* + * Read current network state and post the event. + * Useful if NetworkManager plugin or WPEFramework is restarted + * or netsrvmgr misses to post iarm events during bootup. + */ + getInitialConnectionState(); } } + void NetworkManagerImplementation::getInitialConnectionState() + { + // check the connection state and post event + Exchange::INetworkManager::IInterfaceDetailsIterator* _interfaces{}; + uint32_t rc = GetAvailableInterfaces(_interfaces); + + if (Core::ERROR_NONE == rc) + { + if (_interfaces != nullptr) + { + Exchange::INetworkManager::InterfaceDetails iface{}; + while (_interfaces->Next(iface) == true) + { + Core::JSON::EnumType type{iface.type}; + if(iface.enabled) + { + NMLOG_INFO("'%s' interface is enabled", iface.name.c_str()); + // ReportInterfaceStateChange(Exchange::INetworkManager::INTERFACE_ADDED, iface.name); + if(iface.connected) + { + NMLOG_INFO("'%s' interface is connected", iface.name.c_str()); + ReportActiveInterfaceChange(iface.name, iface.name); + std::string ipversion = {}; + Exchange::INetworkManager::IPAddress addr; + rc = GetIPSettings(iface.name, ipversion, addr); + if (Core::ERROR_NONE == rc) + { + if(!addr.ipaddress.empty()) { + NMLOG_INFO("'%s' interface have ip '%s'", iface.name.c_str(), addr.ipaddress.c_str()); + ReportIPAddressChange(iface.name, addr.ipversion, addr.ipaddress, Exchange::INetworkManager::IP_ACQUIRED); + } + } + } + } + } + + _interfaces->Release(); + } + } + } + void NetworkManagerImplementation::platform_init() { LOG_ENTRY_FUNCTION(); @@ -623,7 +669,14 @@ namespace WPEFramework IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged, NetworkManagerInternalEventHandler); IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onError, NetworkManagerInternalEventHandler); IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, NetworkManagerInternalEventHandler); + /* + * Read current network state and post the event. + * Useful if NetworkManager plugin or WPEFramework is restarted + * or netsrvmgr misses to post iarm events during bootup. + */ + getInitialConnectionState(); } + } uint32_t NetworkManagerImplementation::GetAvailableInterfaces (Exchange::INetworkManager::IInterfaceDetailsIterator*& interfacesItr/* @out */) @@ -642,15 +695,19 @@ namespace WPEFramework { InterfaceDetails tmp; /* Update the interface as per RDK NetSrvMgr */ - if ("eth0" == interfaceName) - tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_ETHERNET; - else if ("wlan0" == interfaceName) - tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_WIFI; - tmp.name = interfaceName; tmp.mac = string(list.interfaces[i].mac); tmp.enabled = ((list.interfaces[i].flags & IFF_UP) != 0); tmp.connected = ((list.interfaces[i].flags & IFF_RUNNING) != 0); + if ("eth0" == interfaceName) { + tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_ETHERNET; + m_ethConnected = tmp.connected; + } + else if ("wlan0" == interfaceName) { + tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_WIFI; + m_wlanConnected = tmp.connected; + } + interfaceList.push_back(tmp); } } diff --git a/Tests/unit_test/test_NetworkManagerConnectivity.cpp b/Tests/unit_test/test_NetworkManagerConnectivity.cpp index 1d04623ea..a04520291 100644 --- a/Tests/unit_test/test_NetworkManagerConnectivity.cpp +++ b/Tests/unit_test/test_NetworkManagerConnectivity.cpp @@ -5,36 +5,30 @@ using namespace std; using namespace WPEFramework; - + class ConnectivityMonitorTest : public ::testing::Test { protected: - - WPEFramework::Plugin::ConnectivityMonitor cm; - - void SetUp() override { - - } - - void TearDown() override { - - } + WPEFramework::Plugin::ConnectivityMonitor cm; }; - - TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_Success) { - int timeout = 30; + +TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_Success) { + int timeout = 30; bool result = cm.startContinuousConnectivityMonitor(timeout); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } + TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_FailureNegativeTimeout) { - int timeout = -1; + int timeout = -1; bool result = cm.startContinuousConnectivityMonitor(timeout); - EXPECT_TRUE(result); -} + EXPECT_TRUE(result); +} + TEST_F(ConnectivityMonitorTest, StartMonitorWithTimeoutLessThanMinimum) { - int timeout = 3; + int timeout = 3; bool result = cm.startContinuousConnectivityMonitor(timeout); EXPECT_TRUE(result); } + TEST_F(ConnectivityMonitorTest, MonitorFailsToStart) { int timeout = 0; bool result = cm.startContinuousConnectivityMonitor(timeout); @@ -45,17 +39,19 @@ TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_WhenStarted) { int timeout = 30; cm.startContinuousConnectivityMonitor(timeout); bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } + TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_WhenNotStarted) { bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } + TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_AfterMultipleStartsAndStops) { int timeout = 30; cm.startContinuousConnectivityMonitor(timeout); bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); cm.startContinuousConnectivityMonitor(timeout); result = cm.stopContinuousConnectivityMonitor(); @@ -63,55 +59,51 @@ TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_AfterMultipleStartsAndStop cm.startContinuousConnectivityMonitor(timeout); result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } + TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_LongRunningMonitor) { int timeout = 1000; cm.startContinuousConnectivityMonitor(timeout); std::this_thread::sleep_for(std::chrono::seconds(2)); bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); + EXPECT_TRUE(result); } - TEST_F(ConnectivityMonitorTest, StartMonitor_WithInterfaceStatusTrue) { - bool interfaceStatus = true; - bool result = cm.startConnectivityMonitor(interfaceStatus); - EXPECT_TRUE(result); -} -TEST_F(ConnectivityMonitorTest, StartMonitor_WithInterfaceStatusFalse) { - bool interfaceStatus = false; - bool result = cm.startConnectivityMonitor(interfaceStatus); - EXPECT_TRUE(result); +TEST_F(ConnectivityMonitorTest, StartMonitor_WithInterfaceStatus) { + bool result = cm.startConnectivityMonitor(); + EXPECT_TRUE(result); } + TEST_F(ConnectivityMonitorTest, StartMonitor_NotifyIfAlreadyMonitoring) { - bool interfaceStatus = true; - cm.startConnectivityMonitor(interfaceStatus); - bool result = cm.startConnectivityMonitor(interfaceStatus); - EXPECT_TRUE(result); + bool result = false; + result = cm.startConnectivityMonitor(); + EXPECT_TRUE(result); + result = cm.startConnectivityMonitor(); + EXPECT_TRUE(result); } TEST_F(ConnectivityMonitorTest, SetEndpoints_Valid) { std::vector endpoints = {"https://github.com/rdkcentral", "https://github.com/rdkcentral/rdkservices"}; cm.setConnectivityMonitorEndpoints(endpoints); EXPECT_EQ(cm.getConnectivityMonitorEndpoints(), endpoints); -} +} + TEST_F(ConnectivityMonitorTest, SetEndpoints_EmptyList) { std::vector endpoints; cm.setConnectivityMonitorEndpoints(endpoints); EXPECT_TRUE(cm.getConnectivityMonitorEndpoints().empty()); } + TEST_F(ConnectivityMonitorTest, SetEndpoints_InvalidShortEndpoints) { std::vector endpoints = {"ab", "htt", "xyz"}; cm.setConnectivityMonitorEndpoints(endpoints); EXPECT_TRUE(cm.getConnectivityMonitorEndpoints().empty()); } + TEST_F(ConnectivityMonitorTest, SetEndpoints_DuplicateEndpoints) { std::vector endpoints = {"https://github.com", "https://github.com"}; cm.setConnectivityMonitorEndpoints(endpoints); EXPECT_EQ(cm.getConnectivityMonitorEndpoints().size(), 2); } - - - - diff --git a/Tests/unit_test/test_NetworkManagerStunClient.cpp b/Tests/unit_test/test_NetworkManagerStunClient.cpp index b235eb2da..5276344a1 100644 --- a/Tests/unit_test/test_NetworkManagerStunClient.cpp +++ b/Tests/unit_test/test_NetworkManagerStunClient.cpp @@ -1,23 +1,3 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include "NetworkManagerStunClient.h" @@ -28,42 +8,30 @@ using namespace stun; class AddressTest : public ::testing::Test { protected: stun::attributes::address ad; - void SetUp() override { - - } - void TearDown() override { - - } }; class ClientTest : public ::testing::Test { protected: - stun::client cl; - void SetUp() override { - - } - void TearDown() override { - - } + stun::client _client; }; TEST_F(ClientTest, BindSuccess) { stun::bind_result result; - bool success = cl.bind("https://github.com/", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); + bool success = _client.bind("https://github.com/", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); EXPECT_FALSE(success); EXPECT_FALSE(result.is_valid()); } TEST_F(ClientTest, BindFailure) { stun::bind_result result; - bool success = cl.bind("http//tata.com", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); + bool success = _client.bind("http//tata.com", 3478, "eth0", stun::protocol::af_inet, 5000, 10000, result); EXPECT_FALSE(success); EXPECT_FALSE(result.is_valid()); } + TEST_F(ClientTest, BindWithInvalidInterface) { stun::bind_result result; - bool success = cl.bind("https://github.com/", 3478, "invalid_interface", stun::protocol::af_inet, 5000, 10000, result); + bool success = _client.bind("https://github.com/", 3478, "invalid_interface", stun::protocol::af_inet, 5000, 10000, result); EXPECT_FALSE(success); EXPECT_FALSE(result.is_valid()); } - diff --git a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp b/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp index a2e1d3f94..5618a6cb0 100644 --- a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp +++ b/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp @@ -17,11 +17,12 @@ namespace WPEFramework { namespace Plugin { - NetworkManagerImplementation* _instance; + NetworkManagerImplementation* _instance = nullptr; void NetworkManagerImplementation::ReportWiFiSignalStrengthChange(const string ssid, const string strength, const WiFiSignalQuality quality) - { + { return; } + void NetworkManagerImplementation::ReportInternetStatusChange(const InternetStatus prevState, const InternetStatus currState) { return; @@ -32,12 +33,7 @@ namespace WPEFramework class WiFiSignalStrengthMonitorTest : public ::testing::Test { protected: WPEFramework::Plugin::WiFiSignalStrengthMonitor monitor; - void SetUp() override { - } - void TearDown() override { - } }; -#define BUFFER_SIZE 1024 TEST_F(WiFiSignalStrengthMonitorTest, GetSignalData_Connected) { std::string ssid = "TestSSID"; @@ -47,12 +43,10 @@ TEST_F(WiFiSignalStrengthMonitorTest, GetSignalData_Connected) { } TEST_F(WiFiSignalStrengthMonitorTest, StartWiFiSignalStrengthMonitor) { - monitor.startWiFiSignalStrengthMonitor(1); - + monitor.startWiFiSignalStrengthMonitor(1); } int main(int argc, char **argv) { ::testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); } - diff --git a/Tests/unit_test/tests.cmake b/Tests/unit_test/unit_tests.cmake similarity index 96% rename from Tests/unit_test/tests.cmake rename to Tests/unit_test/unit_tests.cmake index 82d2cd928..9c56c2428 100644 --- a/Tests/unit_test/tests.cmake +++ b/Tests/unit_test/unit_tests.cmake @@ -1,5 +1,4 @@ -cmake_minimum_required(VERSION 3.10) -set(UNIT_TEST "tests") +set(UNIT_TEST "unit_tests") find_package(PkgConfig REQUIRED) pkg_check_modules(GLIB REQUIRED glib-2.0) @@ -22,10 +21,12 @@ add_executable(${UNIT_TEST} NetworkManagerConnectivity.cpp NetworkManagerStunClient.cpp ) + set_target_properties(${UNIT_TEST} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES ) + target_compile_options(${UNIT_TEST} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") @@ -43,4 +44,3 @@ target_include_directories(${UNIT_TEST} PRIVATE target_link_libraries(${UNIT_TEST} PRIVATE gmock_main ${NAMESPACE}Core::${NAMESPACE}Core ${GLIB_LIBRARIES} ${GIO_LIBRARIES} ${LIBNM_LIBRARIES} ${CURL_LIBRARIES}) target_include_directories(${UNIT_TEST} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) install(TARGETS ${UNIT_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) - From 2894fc5d80befe6b94c93849a6338703117b91a1 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 19 Dec 2024 20:50:05 +0530 Subject: [PATCH 064/271] SERXIONE-6805 Box reboots with reboot reason MAINTENANCE_REBOOT, when the box is in Active Standby (#62) * SERXIONE-6805 Box reboots with reboot reason MAINTENANCE_REBOOT, when the box is in Active Standby * set the connection flag in ipaddress event also --- NetworkManagerImplementation.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index f08fe09cb..997eaf24d 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -598,6 +598,12 @@ namespace WPEFramework { _notificationLock.Lock(); NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); + + if(currentActiveinterface == "eth0") + m_ethConnected = true; + else if (currentActiveinterface == "wlan0") + m_wlanConnected = true; + for (const auto callback : _notificationCallbacks) { callback->onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); } @@ -611,6 +617,11 @@ namespace WPEFramework // Start the connectivity monitor with 'true' to indicate the interface is up. // The monitor will conntinoue even after no internet retry completed, Exit when fully connectd. connectivityMonitor.startConnectivityMonitor(); + // if ipaddress is aquired means there should be interface connected + if(interface == "eth0") + m_ethConnected = true; + else if (interface == "wlan0") + m_wlanConnected = true; } _notificationLock.Lock(); From df11a08262662da6b33f753dceb905b58b9bd846 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Fri, 20 Dec 2024 14:53:12 -0500 Subject: [PATCH 065/271] DELIA-67124 : Handle the JSON Subscribe Event (#65) DELIA-67124 : Handle the JSON Subscribe Event Reason for change: The subscription request reached the NetworkManager and responded but due to the boot-up time no-cpu scenario, the success is NOT sent to consumer. So the consumer subscribes for the 2nd time, it returns already_exist error. It should be handled cleanly. Test Procedure: As per DELIA-67124 Risks: Low Signed-off-by: Karunakaran A --- NetworkManager.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/NetworkManager.h b/NetworkManager.h index a2543bed7..353c34f78 100644 --- a/NetworkManager.h +++ b/NetworkManager.h @@ -132,6 +132,14 @@ namespace WPEFramework void Deinitialize(PluginHost::IShell *service) override; string Information() const override; + //override Subscribe from IDispatcher + uint32_t Subscribe(const uint32_t channel, const string& event, const string& designator) override + { + NMLOG_DEBUG("Subscription received for %s event from channelID (%u) with designator as %s", event.c_str(), channel, designator.c_str()); + JSONRPC::Subscribe(channel, event, designator); + return Core::ERROR_NONE; + } + // Do not allow copy/move constructors NetworkManager(const NetworkManager &) = delete; NetworkManager &operator=(const NetworkManager &) = delete; From 95fe8d6f7f6ac72d0c30fc5064924dbcc2c2ed0f Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Sun, 22 Dec 2024 00:22:16 -0500 Subject: [PATCH 066/271] RDKEMW-892 : Replace Printf with NMLOG (#66) Reason for change: Replace Printf with NMLOG Test Procedure: Test `"org.rdk.NetworkManager.GetPublicIP"` Risks: Low Signed-off-by: kamirt573_comcast --- INetworkManager.h | 2 +- NetworkManagerImplementation.cpp | 7 +++- NetworkManagerImplementation.h | 2 +- NetworkManagerJsonRpc.cpp | 2 +- NetworkManagerStunClient.cpp | 66 +++++++++++--------------------- NetworkManagerStunClient.h | 6 +-- 6 files changed, 32 insertions(+), 53 deletions(-) diff --git a/INetworkManager.h b/INetworkManager.h index 254eb0638..c1920bbef 100644 --- a/INetworkManager.h +++ b/INetworkManager.h @@ -243,7 +243,7 @@ namespace WPEFramework virtual uint32_t StopConnectivityMonitoring(void) const = 0; /* @brief Get the Public IP used for external world communication */ - virtual uint32_t GetPublicIP (const string &ipversion /* @in */, string& ipaddress /* @out */) = 0; + virtual uint32_t GetPublicIP (string &ipversion /* @inout */, string& ipaddress /* @out */) = 0; /* @brief Request for ping and get the response in as event. The GUID used in the request will be returned in the event. */ virtual uint32_t Ping (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t count /* @in */, const uint16_t timeout /* @in */, const string guid /* @in */, string& response /* @out */) = 0; diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 997eaf24d..311967f62 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -280,7 +280,7 @@ namespace WPEFramework } /* @brief Get the Public IP used for external world communication */ - uint32_t NetworkManagerImplementation::GetPublicIP (const string &ipversion /* @in */, string& ipaddress /* @out */) + uint32_t NetworkManagerImplementation::GetPublicIP (string &ipversion /* @inout */, string& ipaddress /* @out */) { LOG_ENTRY_FUNCTION(); stun::bind_result result; @@ -289,6 +289,11 @@ namespace WPEFramework stun::protocol proto (isIPv6 ? stun::protocol::af_inet6 : stun::protocol::af_inet); if(stunClient.bind(m_stunEndPoint, m_stunPort, m_defaultInterface, proto, m_stunBindTimeout, m_stunCacheTimeout, result)) { + if (isIPv6) + ipversion = "IPv6"; + else + ipversion = "IPv4"; + ipaddress = result.public_ip; return Core::ERROR_NONE; } diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 64767f98b..8897b7dfd 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -197,7 +197,7 @@ namespace WPEFramework uint32_t StopConnectivityMonitoring(void) const override; /* @brief Get the Public IP used for external world communication */ - uint32_t GetPublicIP (const string &ipversion /* @in */, string& ipaddress /* @out */) override; + uint32_t GetPublicIP (string &ipversion /* @inout */, string& ipaddress /* @out */) override; /* @brief Request for ping and get the response in as event. The GUID used in the request will be returned in the event. */ uint32_t Ping (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const uint16_t timeOutInSeconds /* @in */, const string guid /* @in */, string& response /* @out */) override; diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 1079443bf..662862826 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -567,7 +567,6 @@ namespace WPEFramework void NetworkManager::PublishToThunderAboutInternet() { - NMLOG_DEBUG("No public IP persisted yet; Update the data"); if (m_publicIPAddress.empty()) { JsonObject input, output; @@ -576,6 +575,7 @@ namespace WPEFramework if (!m_publicIPAddress.empty()) { + NMLOG_DEBUG("No public IP persisted yet; Update the data"); PluginHost::ISubSystem* subSystem = _service->SubSystems(); if (subSystem != nullptr) diff --git a/NetworkManagerStunClient.cpp b/NetworkManagerStunClient.cpp index 999f14e88..1960f0f91 100644 --- a/NetworkManagerStunClient.cpp +++ b/NetworkManagerStunClient.cpp @@ -51,7 +51,7 @@ namespace details { int m_fd; }; - #ifdef _STUN_DEBUG +#ifdef _STUN_DEBUG void dump_buffer(char const * prefix, buffer const & buff) { if (prefix) @@ -61,14 +61,7 @@ namespace details { printf("\n"); return; } - #endif - - #ifdef _STUN_DEBUG - #define STUN_TRACE(format, ...) printf("STUN:" format __VA_OPT__(,) __VA_ARGS__) - #else - #define STUN_TRACE(format, ...) - #endif - +#endif void throw_error(char const * format, ...) { @@ -126,7 +119,7 @@ namespace details { details::throw_error("failed to find ip for interface:%s", iface.c_str()); return iface_info; } - STUN_TRACE("local_addr:%s\n", sockaddr_to_string(iface_info).c_str()); + NMLOG_DEBUG("local_addr:%s", sockaddr_to_string(iface_info).c_str()); return iface_info; } @@ -290,7 +283,6 @@ client::client() , m_cache_timeout(30) , m_last_cache_time() , m_last_result() - , m_verbose(true) , m_fd(-1) { } @@ -350,7 +342,7 @@ bool client::bind( dirty = true; } - verbose("client::bind enter: server=%s port=%u iface=%s ipv6=%u timeout=%u cache_timeout=%u dirty=%u\n", + NMLOG_DEBUG("client::bind enter: server=%s port=%u iface=%s ipv6=%u timeout=%u cache_timeout=%u dirty=%u", hostname.c_str(), port, interface.c_str(), proto == stun::protocol::af_inet6, bind_timeout, cache_timeout, dirty); if(m_cache_timeout > 0 /*asking if caching is enabled*/ @@ -360,18 +352,18 @@ bool client::bind( auto time_in_cache = std::chrono::duration_cast( std::chrono::steady_clock::now() - m_last_cache_time); - verbose("client::bind cache time=%lld\n", time_in_cache.count()); + NMLOG_DEBUG("client::bind cache time=%ld", time_in_cache.count()); if(time_in_cache.count() < m_cache_timeout) { result = m_last_result; - verbose("client::bind returning cached result: %s\n", result.public_ip.c_str()); + NMLOG_DEBUG("client::bind returning cached result: %s", result.public_ip.c_str()); return true; } else { - verbose("client::client::bind cached result expired\n"); + NMLOG_DEBUG("client::client::bind cached result expired"); } } @@ -387,7 +379,7 @@ bool client::bind( std::chrono::milliseconds wait_time(interval_wait_time); for (int i = 0; i < num_attempts && total_time < m_bind_timeout; ++i) { - verbose("client::bind sending bind request\n"); + NMLOG_DEBUG("client::bind sending bind request"); std::unique_ptr binding_response = send_binding_request(wait_time); @@ -415,25 +407,25 @@ bool client::bind( m_last_cache_time = std::chrono::steady_clock::now(); - verbose("client::bind success: public_ip=%s\n", result.public_ip.c_str()); + NMLOG_DEBUG("client::bind success: public_ip=%s", result.public_ip.c_str()); ret_ok = true; } else { - verbose("client::bind failed: ip missing from binding response\n"); + NMLOG_DEBUG("client::bind failed: ip missing from binding response"); } } else { - verbose("client::bind failed: no response received from server\n"); + NMLOG_INFO("client::bind failed: no response received from server"); } } } #ifdef __cpp_exceptions catch (std::exception const & err) { - verbose("client::bind failed: %s\n", err.what()); + NMLOG_WARNING("client::bind failed: %s", err.what()); } #endif @@ -454,13 +446,13 @@ void client::create_udp_socket(int inet_family) if (inet_family != AF_INET && inet_family != AF_INET6) details::throw_error("invalid inet family:%d", inet_family); - verbose("creating udp/%s socket\n", details::family_to_string(inet_family)); + NMLOG_DEBUG("creating udp/%s socket", details::family_to_string(inet_family)); int soc = socket(inet_family, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (soc < 0) details::throw_error("error creating socket. %s", strerror(errno)); - #ifdef _SUN_USE_MSGHDR + #ifdef _STUN_USE_MSGHDR int optval = 1; setsockopt(soc, IPPROTO_IP, IP_PKTINFO, &optval, sizeof(int)); #endif @@ -468,7 +460,7 @@ void client::create_udp_socket(int inet_family) if (!m_interface.empty()) { sockaddr_storage local_addr = details::get_interface_address(m_interface, inet_family); - verbose("binding to local interface %s/%s\n", m_interface.c_str(), + NMLOG_DEBUG("binding to local interface %s/%s", m_interface.c_str(), sockaddr_to_string(local_addr).c_str()); int ret = ::bind(soc, reinterpret_cast(&local_addr), details::socket_length(local_addr)); @@ -479,18 +471,16 @@ void client::create_udp_socket(int inet_family) sockaddr_to_string(local_addr).c_str(), strerror(err)); } else { - if (m_verbose) { sockaddr_storage local_endpoint; socklen_t socklen = sizeof(sockaddr_storage); int ret = getsockname(soc, reinterpret_cast(&local_endpoint), &socklen); if (ret == 0) - verbose("local endpoint %s/%d\n", sockaddr_to_string(local_endpoint).c_str(), + NMLOG_DEBUG("local endpoint %s/%d", sockaddr_to_string(local_endpoint).c_str(), details::sockaddr_get_port(local_endpoint)); - } } } else - verbose("no local interface supplied to bind to\n"); + NMLOG_DEBUG("no local interface supplied to bind to"); if (m_fd != -1) close(m_fd); @@ -506,13 +496,13 @@ message * client::send_message(sockaddr_storage const & remote_addr, message con buffer bytes = req.encode(); - STUN_TRACE("remote_addr:%s\n", sockaddr_to_string(remote_addr).c_str()); + NMLOG_DEBUG("remote_addr:%s", sockaddr_to_string(remote_addr).c_str()); #ifdef _STUN_DEBUG details::dump_buffer("STUN >>> ", bytes); #endif - verbose("sending messsage\n"); + NMLOG_DEBUG("sending messsage"); ssize_t n = sendto(m_fd, &bytes[0], bytes.size(), 0, (sockaddr *) &remote_addr, details::socket_length(remote_addr)); if (n < 0) @@ -537,10 +527,10 @@ message * client::send_message(sockaddr_storage const & remote_addr, message con timeout.tv_sec = (timeout.tv_usec / kMicrosecondsPerSecond); timeout.tv_usec -= (timeout.tv_sec * kMicrosecondsPerSecond); } - verbose("waiting for response, timeout set to %lus - %luus\n", timeout.tv_sec, timeout.tv_usec); + NMLOG_DEBUG("waiting for response, timeout set to %lus - %luus", timeout.tv_sec, timeout.tv_usec); int ret = select(m_fd + 1, &rfds, nullptr, nullptr, &timeout); if (ret == 0) { - STUN_TRACE("select timeout out\n"); + NMLOG_DEBUG("select timeout out"); return nullptr; } @@ -608,18 +598,6 @@ message * client::send_message(sockaddr_storage const & remote_addr, message con return decoder::decode_message(bytes, nullptr); } -void client::verbose(char const * format, ...) -{ - if (!m_verbose) - return; - va_list ap; - va_start(ap, format); - printf("STUN:"); - vprintf(format, ap); - va_end(ap); - return; -} - network_access_type client::discover_network_access_type(server const & srv) { std::chrono::milliseconds wait_time(250); @@ -672,7 +650,7 @@ std::unique_ptr client::send_binding_request(std::chrono::milliseconds std::unique_ptr client::send_binding_request(sockaddr_storage const & addr, std::chrono::milliseconds wait_time) { - this->verbose("sending binding request with wait time:%lld ms\n", wait_time.count()); + NMLOG_DEBUG("sending binding request with wait time:%ld ms", wait_time.count()); this->create_udp_socket(addr.ss_family); std::unique_ptr binding_request(message_factory::create_binding_request()); std::unique_ptr binding_response(this->send_message(addr, *binding_request, wait_time)); diff --git a/NetworkManagerStunClient.h b/NetworkManagerStunClient.h index c2f69297a..09f093a56 100644 --- a/NetworkManagerStunClient.h +++ b/NetworkManagerStunClient.h @@ -8,6 +8,7 @@ #include #include #include +#include "NetworkManagerLogger.h" namespace stun { @@ -157,11 +158,7 @@ class client { network_access_type discover_network_access_type(server const & srv); - inline void set_verbose(bool b) { - m_verbose = b; - } private: - void verbose(char const * format, ...) __attribute__((format(printf, 2, 3))); void create_udp_socket(int inet_family); std::unique_ptr send_binding_request(std::chrono::milliseconds wait_time); @@ -180,7 +177,6 @@ class client { uint16_t m_cache_timeout; std::chrono::time_point m_last_cache_time; bind_result m_last_result; - bool m_verbose; int m_fd; }; From 293031c8d8037c447e387e28746080558a262162 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Mon, 30 Dec 2024 21:25:17 -0500 Subject: [PATCH 067/271] Code Enhancements to the NetworkManager Plugin (#68) Reason for change: Code Enhancements to the NetworkManager Plugin Test Procedure: Sanity Testing Risks: Medium Signed-off-by: Karunakaran A --- CMakeLists.txt | 6 +- INetworkManager.h | 10 +- LegacyPlugin_NetworkAPIs.cpp | 25 +- LegacyPlugin_NetworkAPIs.h | 3 +- LegacyPlugin_WiFiManagerAPIs.cpp | 6 + NetworkManager.cpp | 19 +- NetworkManager.json | 2 +- NetworkManagerImplementation.cpp | 223 +++++++++-------- NetworkManagerImplementation.h | 410 +++++++++++++++++-------------- NetworkManagerJsonRpc.cpp | 14 +- NetworkManagerRDKProxy.cpp | 7 +- 11 files changed, 393 insertions(+), 332 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3670fe97f..82961a4b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,9 +32,9 @@ find_package(${NAMESPACE}Core REQUIRED) find_package(${NAMESPACE}Plugins REQUIRED) find_package(CURL) -set(PLUGIN_NETWORKMANAGER_STARTUPORDER "55" CACHE STRING "To configure startup order of Unified NetworkManager plugin") -set(PLUGIN_LEGACY_NW_STARTUPORDER "56" CACHE STRING "To configure startup order of Legacy Network plugin") -set(PLUGIN_LEGACY_WIFI_STARTUPORDER "56" CACHE STRING "To configure startup order of Legacy WiFi plugin") +set(PLUGIN_NETWORKMANAGER_STARTUPORDER "25" CACHE STRING "To configure startup order of Unified NetworkManager plugin") +set(PLUGIN_LEGACY_NW_STARTUPORDER "35" CACHE STRING "To configure startup order of Legacy Network plugin") +set(PLUGIN_LEGACY_WIFI_STARTUPORDER "35" CACHE STRING "To configure startup order of Legacy WiFi plugin") set(PLUGIN_BUILD_REFERENCE ${PROJECT_VERSION} CACHE STRING "To Set the Hash for the plugin") add_definitions(-DPLUGIN_BUILD_REFERENCE=${PLUGIN_BUILD_REFERENCE}) diff --git a/INetworkManager.h b/INetworkManager.h index c1920bbef..90c10760b 100644 --- a/INetworkManager.h +++ b/INetworkManager.h @@ -85,7 +85,7 @@ namespace WPEFramework INTERNET_LIMITED /* @text: LIMITED_INTERNET */, INTERNET_CAPTIVE_PORTAL /* @text: CAPTIVE_PORTAL */, INTERNET_FULLY_CONNECTED /* @text: FULLY_CONNECTED */, - INTERNET_UNKNOWN /* @text: NO_INTERNET */, + INTERNET_UNKNOWN /* @text: UNKNOWN */, }; enum WiFiWPS : uint8_t @@ -237,9 +237,9 @@ namespace WPEFramework /* @brief Get Authentication URL if the device is behind Captive Portal */ virtual uint32_t GetCaptivePortalURI(string &uri/* @out */) const = 0; - /* @brief Start The Internet Connectivity Monitoring */ + /* @brief Start The Internet Connectivity Monitoring */ virtual uint32_t StartConnectivityMonitoring(const uint32_t interval /* @in */) = 0; - /* @brief Stop The Internet Connectivity Monitoring */ + /* @brief Stop The Internet Connectivity Monitoring */ virtual uint32_t StopConnectivityMonitoring(void) const = 0; /* @brief Get the Public IP used for external world communication */ @@ -275,8 +275,8 @@ namespace WPEFramework virtual uint32_t SetLogLevel(const Logging& level /* @in */) = 0; virtual uint32_t GetLogLevel(Logging& level /* @out */) = 0; - /* @brief configure network manager plugin */ - virtual uint32_t Configure(const string& configLine /* @in */) = 0; + /* @brief Configure the Network Manager plugin */ + virtual uint32_t Configure(PluginHost::IShell* service /* @in */) = 0; /* @event */ struct EXTERNAL INotification : virtual public Core::IUnknown diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index 1919c3b14..9f0068acc 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -20,7 +20,6 @@ #include "NetworkManagerLogger.h" #include "NetworkManagerJsonEnum.h" - using namespace std; using namespace WPEFramework::Plugin; #define API_VERSION_NUMBER_MAJOR 2 @@ -84,7 +83,6 @@ namespace WPEFramework , m_subsInternetChange(false) { _gNWInstance = this; - m_defaultInterface = "wlan0"; m_timer.connect(std::bind(&Network::subscribeToEvents, this)); registerLegacyMethods(); } @@ -167,7 +165,13 @@ namespace WPEFramework void Network::Deinitialize(PluginHost::IShell* /* service */) { + m_timer.stop(); unregisterLegacyMethods(); + + if (m_networkmanager) + m_networkmanager.reset(); + + m_networkmanager = NULL; m_service->Release(); m_service = nullptr; _gNWInstance = nullptr; @@ -204,7 +208,7 @@ namespace WPEFramework Register("getInternetConnectionState", &Network::getInternetConnectionState, this); Register("ping", &Network::doPing, this); Register("isConnectedToInternet", &Network::isConnectedToInternet, this); - Register("setStunEndPoint", &Network::setStunEndPoint, this); + Register("setStunEndPoint", &Network::setStunEndpoint, this); Register("trace", &Network::doTrace, this); Register("setConnectivityTestEndpoints", &Network::setConnectivityTestEndpoints, this); Register("startConnectivityMonitoring", &Network::startConnectivityMonitoring, this); @@ -219,6 +223,8 @@ namespace WPEFramework */ void Network::unregisterLegacyMethods(void) { + Unregister("getStbIp"); + Unregister("getSTBIPFamily"); Unregister("getInterfaces"); Unregister("isInterfaceEnabled"); Unregister("getPublicIP"); @@ -230,6 +236,8 @@ namespace WPEFramework Unregister("getInternetConnectionState"); Unregister("ping"); Unregister("isConnectedToInternet"); + Unregister("setStunEndPoint"); + Unregister("trace"); Unregister("setConnectivityTestEndpoints"); Unregister("startConnectivityMonitoring"); Unregister("getCaptivePortalURI"); @@ -319,11 +327,11 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { returnJson(rc); } - uint32_t Network::setStunEndPoint(const JsonObject& parameters, JsonObject& response) + uint32_t Network::setStunEndpoint(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string endPoint = parameters["server"].String(); + string endpoint = parameters["server"].String(); uint32_t port = parameters["port"].Number(); uint32_t bindTimeout = parameters["timeout"].Number(); uint32_t cacheTimeout = parameters["cache_timeout"].Number(); @@ -331,7 +339,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); if (_nwmgr) { - rc = _nwmgr->SetStunEndpoint(endPoint, port, bindTimeout, cacheTimeout); + rc = _nwmgr->SetStunEndpoint(endpoint, port, bindTimeout, cacheTimeout); _nwmgr->Release(); } else @@ -1017,8 +1025,6 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { legacyParams["oldInterfaceName"] = getInterfaceNameToType(parameters["prevActiveInterface"].String()); legacyParams["newInterfaceName"] = getInterfaceNameToType(parameters["currentActiveInterface"].String()); - m_defaultInterface = parameters["currentActiveInterface"].String(); - string json; legacyParams.ToString(json); @@ -1049,9 +1055,6 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { Notify("onIPAddressStatusChanged", legacyParams); - // if ("ACQUIRED" == parameters["status"].String()) - // m_defaultInterface = parameters["interface"].String(); - return; } diff --git a/LegacyPlugin_NetworkAPIs.h b/LegacyPlugin_NetworkAPIs.h index df3019e1c..d61c045a6 100644 --- a/LegacyPlugin_NetworkAPIs.h +++ b/LegacyPlugin_NetworkAPIs.h @@ -55,7 +55,7 @@ namespace WPEFramework { uint32_t getCaptivePortalURI(const JsonObject& parameters, JsonObject& response); uint32_t stopConnectivityMonitoring(const JsonObject& parameters, JsonObject& response); uint32_t getPublicIP(const JsonObject& parameters, JsonObject& response); - uint32_t setStunEndPoint(const JsonObject& parameters, JsonObject& response); + uint32_t setStunEndpoint(const JsonObject& parameters, JsonObject& response); uint32_t getStbIp(const JsonObject& parameters, JsonObject& response); uint32_t getSTBIPFamily(const JsonObject& parameters, JsonObject& response); @@ -88,7 +88,6 @@ namespace WPEFramework { PluginHost::IShell* m_service; std::shared_ptr> m_networkmanager; //WPEFramework::Exchange::INetworkManager* m_nwmgr; - string m_defaultInterface; NetworkManagerTimer m_timer; bool m_subsIfaceStateChange; diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index 336913223..0cf50ca4d 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -165,7 +165,13 @@ namespace WPEFramework void WiFiManager::Deinitialize(PluginHost::IShell* /* service */) { + m_timer.stop(); unregisterLegacyMethods(); + + if (m_networkmanager) + m_networkmanager.reset(); + + m_networkmanager = NULL; m_service->Release(); m_service = nullptr; _gWiFiInstance = nullptr; diff --git a/NetworkManager.cpp b/NetworkManager.cpp index c7f3be034..f068565d4 100644 --- a/NetworkManager.cpp +++ b/NetworkManager.cpp @@ -59,6 +59,7 @@ namespace WPEFramework */ const string NetworkManager::Initialize(PluginHost::IShell *service) { + string message{}; // Make sure everything is null as we expect ASSERT(_service == nullptr); ASSERT(_networkManager == nullptr); @@ -84,20 +85,24 @@ namespace WPEFramework // Still running inside the main WPEFramework process - the child process will have now been spawned and registered if necessary if (_networkManager != nullptr) { - // set the plugin configuration - Exchange::INetworkManager::Logging _loglevel; - _networkManager->Configure(_service->ConfigLine()); + if (_networkManager->Configure(service) != Core::ERROR_NONE) + { + SYSLOG(Logging::Startup, (_T("Configuring NetworkManager"))); + message = _T("NetworkManager failed to configure"); + } - // configure loglevel in libWPEFrameworkNetworkManager.so + // Set the plugin log level + Exchange::INetworkManager::Logging _loglevel; _networkManager->GetLogLevel(_loglevel); NetworkManagerLogger::SetLevel(static_cast (_loglevel)); - + // Register Notifications _networkManager->Register(&_notification); // Register all custom JSON-RPC methods RegisterAllMethods(); + // Get IPlugin interface for this plugin _networkManagerImpl = _networkManager->QueryInterface(); } @@ -109,11 +114,11 @@ namespace WPEFramework _service = nullptr; // Returning a string signals that we failed to initialize - WPEFramework will print this as an error message - return "Failed to initialize NetworkManager"; + message = _T("Failed to initialize NetworkManager"); } // Success - return ""; + return message; } /** diff --git a/NetworkManager.json b/NetworkManager.json index 7636a5524..fb9f5c33e 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -1242,7 +1242,7 @@ } }, "GetWiFiSignalStrength":{ - "summary": "Get WiFiSignalStrength of connected SSID. The signal quality is identifed based on the signal strength. The possible states are \n* 'Excellent' \n* 'Good' \n* 'Fair' \n* 'Weak' \n* 'Disconnected' \n", + "summary": "Get WiFiSignalStrength of connected SSID. The signal quality is identifed based on the signal strength. The possible states are\n* 'Excellent'\n* 'Good'\n* 'Fair'\n* 'Weak'\n* 'Disconnected'\n", "events":{ "onWiFiSignalStrengthChange" : "Triggered when Wifi signal strength switches between Excellent, Good, Fair, Weak." }, diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 311967f62..81c17497a 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -18,7 +18,6 @@ **/ #include "NetworkManagerImplementation.h" -#include "NetworkManagerConnectivity.h" #include "WiFiSignalStrengthMonitor.h" using namespace WPEFramework; @@ -36,15 +35,8 @@ namespace WPEFramework NetworkManagerImplementation::NetworkManagerImplementation() : _notificationCallbacks({}) { - /* Initialize Network Manager */ - NetworkManagerLogger::Init(); - - LOG_ENTRY_FUNCTION(); - /* Name says it all */ - platform_init(); - /* Initialize STUN Endpoints */ - m_stunEndPoint = "stun.l.google.com"; + m_stunEndpoint = "stun.l.google.com"; m_stunPort = 19302; m_stunBindTimeout = 30; m_stunCacheTimeout = 0; @@ -52,6 +44,10 @@ namespace WPEFramework m_publicIP = ""; m_ethConnected = false; m_wlanConnected = false; + + /* Initialize Network Manager */ + NetworkManagerLogger::Init(); + LOG_ENTRY_FUNCTION(); } NetworkManagerImplementation::~NetworkManagerImplementation() @@ -61,6 +57,7 @@ namespace WPEFramework { m_registrationThread.join(); } + connectivityMonitor.stopContinuousConnectivityMonitor(); } /** @@ -102,79 +99,93 @@ namespace WPEFramework return Core::ERROR_NONE; } - uint32_t NetworkManagerImplementation::Configure(const string& configLine /* @in */) + uint32_t NetworkManagerImplementation::Configure(PluginHost::IShell* service) { - if(configLine.empty()) - { - NMLOG_FATAL("config line : is empty !"); - return(Core::ERROR_GENERAL); - } - - NMLOG_DEBUG("config line : %s", configLine.c_str()); + LOG_ENTRY_FUNCTION(); + Configuration config; - Config config; - if(config.FromString(configLine)) + if (service) { - /* stun configuration copy */ - m_stunEndPoint = config.stun.stunEndpoint.Value(); - m_stunPort = config.stun.port.Value(); - m_stunBindTimeout = config.stun.interval.Value(); - - NMLOG_DEBUG("config : stun endpoint %s", m_stunEndPoint.c_str()); - NMLOG_DEBUG("config : stun port %d", m_stunPort); - NMLOG_DEBUG("config : stun interval %d", m_stunBindTimeout); - - NMLOG_DEBUG("config : loglevel %d", config.loglevel.Value()); - NetworkManagerLogger::SetLevel(static_cast (config.loglevel.Value())); - - /* load connectivity monitor endpoints */ - std::vector connectEndpts; - if(!config.connectivityConf.endpoint_1.Value().empty()) { - NMLOG_DEBUG("config : connectivity enpt 1 %s", config.connectivityConf.endpoint_1.Value().c_str()); - connectEndpts.push_back(config.connectivityConf.endpoint_1.Value().c_str()); - } - if(!config.connectivityConf.endpoint_2.Value().empty()) { - NMLOG_DEBUG("config : connectivity enpt 2 %s", config.connectivityConf.endpoint_2.Value().c_str()); - connectEndpts.push_back(config.connectivityConf.endpoint_2.Value().c_str()); - } - if(!config.connectivityConf.endpoint_3.Value().empty()) { - NMLOG_DEBUG("config : connectivity enpt 3 %s", config.connectivityConf.endpoint_3.Value().c_str()); - connectEndpts.push_back(config.connectivityConf.endpoint_3.Value().c_str()); - } - if(!config.connectivityConf.endpoint_4.Value().empty()) { - NMLOG_DEBUG("config : connectivity enpt 4 %s", config.connectivityConf.endpoint_4.Value().c_str()); - connectEndpts.push_back(config.connectivityConf.endpoint_4.Value().c_str()); - } - if(!config.connectivityConf.endpoint_5.Value().empty()) { - NMLOG_DEBUG("config : connectivity enpt 5 %s", config.connectivityConf.endpoint_5.Value().c_str()); - connectEndpts.push_back(config.connectivityConf.endpoint_5.Value().c_str()); - } - - /* check whether the endpoint is already loaded from Cache; if Yes, do not use the one from configuration */ - if (connectivityMonitor.getConnectivityMonitorEndpoints().size() < 1) + string configLine = service->ConfigLine(); + if(configLine.empty()) { - NMLOG_INFO("config : Use the connectivity endpoint from config"); - connectivityMonitor.setConnectivityMonitorEndpoints(connectEndpts); + NMLOG_FATAL("config line : is empty !"); + return Core::ERROR_GENERAL; } - else if (connectEndpts.size() < 1) + else { - std::vector backup; - NMLOG_INFO("config : Connectivity endpoints are empty in config; use the default"); - backup.push_back("http://clients3.google.com/generate_204"); - connectivityMonitor.setConnectivityMonitorEndpoints(backup); + NMLOG_INFO("Loading the incoming configuration : %s", configLine.c_str()); + config.FromString(configLine); } } else - NMLOG_ERROR("Plugin configuration read error !"); + { + NMLOG_FATAL("Service is NULL!"); + return Core::ERROR_GENERAL; + + } + + NetworkManagerLogger::SetLevel(static_cast (config.loglevel.Value())); + NMLOG_DEBUG("loglevel %d", config.loglevel.Value()); + + /* STUN configuration copy */ + m_stunEndpoint = config.stun.stunEndpoint.Value(); + m_stunPort = config.stun.port.Value(); + m_stunBindTimeout = config.stun.interval.Value(); + + NMLOG_INFO("stun endpoint %s", m_stunEndpoint.c_str()); + NMLOG_DEBUG("stun port %d", m_stunPort); + NMLOG_DEBUG("stun interval %d", m_stunBindTimeout); + + /* Connectivity monitor endpoints configuration */ + std::vector connectEndpts; + if(!config.connectivityConf.endpoint_1.Value().empty()) { + NMLOG_INFO("connectivity endpoint 1 %s", config.connectivityConf.endpoint_1.Value().c_str()); + connectEndpts.push_back(config.connectivityConf.endpoint_1.Value().c_str()); + } + if(!config.connectivityConf.endpoint_2.Value().empty()) { + NMLOG_DEBUG("connectivity endpoint 2 %s", config.connectivityConf.endpoint_2.Value().c_str()); + connectEndpts.push_back(config.connectivityConf.endpoint_2.Value().c_str()); + } + if(!config.connectivityConf.endpoint_3.Value().empty()) { + NMLOG_DEBUG("connectivity endpoint 3 %s", config.connectivityConf.endpoint_3.Value().c_str()); + connectEndpts.push_back(config.connectivityConf.endpoint_3.Value().c_str()); + } + if(!config.connectivityConf.endpoint_4.Value().empty()) { + NMLOG_DEBUG("connectivity endpoint 4 %s", config.connectivityConf.endpoint_4.Value().c_str()); + connectEndpts.push_back(config.connectivityConf.endpoint_4.Value().c_str()); + } + if(!config.connectivityConf.endpoint_5.Value().empty()) { + NMLOG_DEBUG("connectivity endpoint 5 %s", config.connectivityConf.endpoint_5.Value().c_str()); + connectEndpts.push_back(config.connectivityConf.endpoint_5.Value().c_str()); + } + + /* check whether the endpoint is already loaded from Cache; if Yes, do not use the one from configuration */ + if (connectivityMonitor.getConnectivityMonitorEndpoints().size() < 1) + { + NMLOG_INFO("Use the connectivity endpoint from config"); + connectivityMonitor.setConnectivityMonitorEndpoints(connectEndpts); + } + else if (connectEndpts.size() < 1) + { + std::vector backup; + NMLOG_INFO("Connectivity endpoints are empty in config; use the default"); + backup.push_back("http://clients3.google.com/generate_204"); + connectivityMonitor.setConnectivityMonitorEndpoints(backup); + } + + /* As all the configuration is set, lets instantiate platform */ + std::thread platformThread = std::thread(&NetworkManagerImplementation::platform_init, this); + platformThread.join(); return(Core::ERROR_NONE); } /* @brief Get STUN Endpoint to be used for identifying Public IP */ - uint32_t NetworkManagerImplementation::GetStunEndpoint (string &endPoint /* @out */, uint32_t& port /* @out */, uint32_t& bindTimeout /* @out */, uint32_t& cacheTimeout /* @out */) const + uint32_t NetworkManagerImplementation::GetStunEndpoint (string &endpoint /* @out */, uint32_t& port /* @out */, uint32_t& bindTimeout /* @out */, uint32_t& cacheTimeout /* @out */) const { LOG_ENTRY_FUNCTION(); - endPoint = m_stunEndPoint; + endpoint = m_stunEndpoint; port = m_stunPort; bindTimeout = m_stunBindTimeout; cacheTimeout = m_stunCacheTimeout; @@ -182,42 +193,52 @@ namespace WPEFramework } /* @brief Set STUN Endpoint to be used to identify Public IP */ - uint32_t NetworkManagerImplementation::SetStunEndpoint (string const endPoint /* @in */, const uint32_t port /* @in */, const uint32_t bindTimeout /* @in */, const uint32_t cacheTimeout /* @in */) + uint32_t NetworkManagerImplementation::SetStunEndpoint (string const endpoint /* @in */, const uint32_t port /* @in */, const uint32_t bindTimeout /* @in */, const uint32_t cacheTimeout /* @in */) { LOG_ENTRY_FUNCTION(); - if (!endPoint.empty()) - m_stunEndPoint = endPoint; - if (port != 0) + if (!endpoint.empty()) + m_stunEndpoint = endpoint; + + if (0 != port) m_stunPort = port; - m_stunBindTimeout = bindTimeout; - m_stunCacheTimeout = cacheTimeout; + if (0 != bindTimeout) + m_stunBindTimeout = bindTimeout; + + if (0 != cacheTimeout) + m_stunCacheTimeout = cacheTimeout; + return Core::ERROR_NONE; } /* @brief Get ConnectivityTest Endpoints */ - uint32_t NetworkManagerImplementation::GetConnectivityTestEndpoints(IStringIterator*& endPoints/* @out */) const + uint32_t NetworkManagerImplementation::GetConnectivityTestEndpoints(IStringIterator*& endpoints/* @out */) const { LOG_ENTRY_FUNCTION(); - std::vector tmpEndPoints = connectivityMonitor.getConnectivityMonitorEndpoints(); - endPoints = (Core::Service::Create(tmpEndPoints)); + std::vector tmpEndpoints = connectivityMonitor.getConnectivityMonitorEndpoints(); + endpoints = (Core::Service::Create(tmpEndpoints)); return Core::ERROR_NONE; } /* @brief Set ConnectivityTest Endpoints */ - uint32_t NetworkManagerImplementation::SetConnectivityTestEndpoints(IStringIterator* const endPoints /* @in */) + uint32_t NetworkManagerImplementation::SetConnectivityTestEndpoints(IStringIterator* const endpoints /* @in */) { LOG_ENTRY_FUNCTION(); - std::vector tmpEndPoints; - if(endPoints) + std::vector tmpEndpoints; + + if(endpoints && (endpoints->Count() >= 1)) { - string endPoint{}; - while (endPoints->Next(endPoint) == true) + string endpoint{}; + while(endpoints->Next(endpoint)) { - tmpEndPoints.push_back(endPoint); + /* The url must be atleast 7 letters to be a valid `http://` url */ + if(!endpoint.empty() && endpoint.size() > 7) + { + tmpEndpoints.push_back(endpoint); + } } - connectivityMonitor.setConnectivityMonitorEndpoints(tmpEndPoints); + connectivityMonitor.setConnectivityMonitorEndpoints(tmpEndpoints); } return Core::ERROR_NONE; } @@ -252,14 +273,14 @@ namespace WPEFramework } /* @brief Get Authentication URL if the device is behind Captive Portal */ - uint32_t NetworkManagerImplementation::GetCaptivePortalURI(string &endPoints/* @out */) const + uint32_t NetworkManagerImplementation::GetCaptivePortalURI(string &uri /* @out */) const { LOG_ENTRY_FUNCTION(); - endPoints = connectivityMonitor.getCaptivePortalURI(); + uri = connectivityMonitor.getCaptivePortalURI(); return Core::ERROR_NONE; } - /* @brief Start The Internet Connectivity Monitoring */ + /* @brief Start The Internet Connectivity Monitoring */ uint32_t NetworkManagerImplementation::StartConnectivityMonitoring(const uint32_t interval/* @in */) { LOG_ENTRY_FUNCTION(); @@ -269,7 +290,7 @@ namespace WPEFramework return Core::ERROR_GENERAL; } - /* @brief Stop The Internet Connectivity Monitoring */ + /* @brief Stop The Internet Connectivity Monitoring */ uint32_t NetworkManagerImplementation::StopConnectivityMonitoring(void) const { LOG_ENTRY_FUNCTION(); @@ -287,7 +308,7 @@ namespace WPEFramework bool isIPv6 = (ipversion == "IPv6"); stun::protocol proto (isIPv6 ? stun::protocol::af_inet6 : stun::protocol::af_inet); - if(stunClient.bind(m_stunEndPoint, m_stunPort, m_defaultInterface, proto, m_stunBindTimeout, m_stunCacheTimeout, result)) + if(stunClient.bind(m_stunEndpoint, m_stunPort, m_defaultInterface, proto, m_stunBindTimeout, m_stunCacheTimeout, result)) { if (isIPv6) ipversion = "IPv6"; @@ -577,13 +598,13 @@ namespace WPEFramework void NetworkManagerImplementation::ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface) { LOG_ENTRY_FUNCTION(); - if(Exchange::INetworkManager::INTERFACE_LINK_DOWN == state || Exchange::INetworkManager::INTERFACE_REMOVED == state) { - // Start the connectivity monitor with 'false' to indicate the interface is down. - // The monitor will automatically exit after the retry attempts are completed, posting a 'noInternet' event. + if(Exchange::INetworkManager::INTERFACE_LINK_DOWN == state || Exchange::INetworkManager::INTERFACE_REMOVED == state) + { if(interface == "eth0") m_ethConnected = false; - else + else if(interface == "wlan0") m_wlanConnected = false; + connectivityMonitor.startConnectivityMonitor(); } @@ -619,14 +640,15 @@ namespace WPEFramework { LOG_ENTRY_FUNCTION(); if (Exchange::INetworkManager::IP_ACQUIRED == status) { - // Start the connectivity monitor with 'true' to indicate the interface is up. - // The monitor will conntinoue even after no internet retry completed, Exit when fully connectd. - connectivityMonitor.startConnectivityMonitor(); // if ipaddress is aquired means there should be interface connected if(interface == "eth0") m_ethConnected = true; - else if (interface == "wlan0") + else if(interface == "wlan0") m_wlanConnected = true; + + // Start the connectivity monitor with 'true' to indicate the interface is up. + // The monitor will conntinoue even after no internet retry completed, Exit when fully connectd. + connectivityMonitor.startConnectivityMonitor(); } _notificationLock.Lock(); @@ -647,20 +669,21 @@ namespace WPEFramework _notificationLock.Unlock(); } - void NetworkManagerImplementation::ReportAvailableSSIDs(JsonArray &arrayofWiFiScanResults) + void NetworkManagerImplementation::ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults) { _notificationLock.Lock(); string jsonOfWiFiScanResults; string jsonOfFilterScanResults; + JsonArray filterResult = arrayofWiFiScanResults; arrayofWiFiScanResults.ToString(jsonOfWiFiScanResults); - NMLOG_DEBUG("Posting onAvailableSSIDs result before Filtering is, %s", jsonOfWiFiScanResults.c_str()); + NMLOG_DEBUG("onAvailableSSIDs Filtering is, %s", jsonOfWiFiScanResults.c_str()); - filterScanResults(arrayofWiFiScanResults); + filterScanResults(filterResult); - arrayofWiFiScanResults.ToString(jsonOfFilterScanResults); + filterResult.ToString(jsonOfFilterScanResults); - NMLOG_INFO("Posting onAvailableSSIDs result is, %s", jsonOfFilterScanResults.c_str()); + NMLOG_INFO("Posting onAvailableSSIDs event as, %s", jsonOfFilterScanResults.c_str()); for (const auto callback : _notificationCallbacks) { callback->onAvailableSSIDs(jsonOfFilterScanResults); } diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 8897b7dfd..5c9c74eed 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -29,7 +29,6 @@ using namespace std; -//#include #include "INetworkManager.h" #include "NetworkManagerLogger.h" #include "WiFiSignalStrengthMonitor.h" @@ -42,216 +41,247 @@ namespace WPEFramework { class NetworkManagerImplementation : public Exchange::INetworkManager { - enum NetworkEvents { + enum NetworkEvents + { NETMGR_PING, NETMGR_TRACE, }; - class Config : public Core::JSON::Container { - private: - Config(const Config&); - Config& operator=(const Config&); - - public: class ConnectivityConf : public Core::JSON::Container { - public: - ConnectivityConf& operator=(const ConnectivityConf&) = delete; + public: + ConnectivityConf& operator=(const ConnectivityConf&) = delete; - ConnectivityConf() - : Core::JSON::Container() - , endpoint_1(_T("http://clients3.google.com/generate_204")) - , endpoint_2(_T("")) - , endpoint_3(_T("")) - , endpoint_4(_T("")) - , endpoint_5(_T("")) - , ConnectivityCheckInterval(6) - { - Add(_T("endpoint_1"), &endpoint_1); - Add(_T("endpoint_2"), &endpoint_2); - Add(_T("endpoint_3"), &endpoint_3); - Add(_T("endpoint_4"), &endpoint_4); - Add(_T("endpoint_5"), &endpoint_5); - Add(_T("interval"), &ConnectivityCheckInterval); - } - ~ConnectivityConf() override = default; + ConnectivityConf() + : Core::JSON::Container() + , endpoint_1(_T("http://clients3.google.com/generate_204")) + , endpoint_2(_T("")) + , endpoint_3(_T("")) + , endpoint_4(_T("")) + , endpoint_5(_T("")) + , ConnectivityCheckInterval(6) + { + Add(_T("endpoint_1"), &endpoint_1); + Add(_T("endpoint_2"), &endpoint_2); + Add(_T("endpoint_3"), &endpoint_3); + Add(_T("endpoint_4"), &endpoint_4); + Add(_T("endpoint_5"), &endpoint_5); + Add(_T("interval"), &ConnectivityCheckInterval); + } + ~ConnectivityConf() override = default; - public: - /* connectivity configuration */ - Core::JSON::String endpoint_1; - Core::JSON::String endpoint_2; - Core::JSON::String endpoint_3; - Core::JSON::String endpoint_4; - Core::JSON::String endpoint_5; - Core::JSON::DecUInt32 ConnectivityCheckInterval; + public: + /* connectivity configuration */ + Core::JSON::String endpoint_1; + Core::JSON::String endpoint_2; + Core::JSON::String endpoint_3; + Core::JSON::String endpoint_4; + Core::JSON::String endpoint_5; + Core::JSON::DecUInt32 ConnectivityCheckInterval; }; class Stun : public Core::JSON::Container { + public: + Stun& operator=(const Stun&) = delete; + + Stun() + : Core::JSON::Container() + , stunEndpoint(_T("stun.l.google.com")) + , port(19302) + , interval(30) + { + Add(_T("endpoint"), &stunEndpoint); + Add(_T("port"), &port); + Add(_T("interval"), &interval); + } + ~Stun() override = default; + + public: + /* stun configuration */ + Core::JSON::String stunEndpoint; + Core::JSON::DecUInt32 port; + Core::JSON::DecUInt32 interval; + }; + + class WiFiConfig : public Core::JSON::Container + { public: - Stun& operator=(const Stun&) = delete; + Core::JSON::String ssid; + Core::JSON::String password; + Core::JSON::DecUInt8 security; - Stun() - : Core::JSON::Container() - , stunEndpoint(_T("stun.l.google.com")) - , port(19302) - , interval(30) + WiFiConfig() : Core::JSON::Container() { - Add(_T("endpoint"), &stunEndpoint); - Add(_T("port"), &port); - Add(_T("interval"), &interval); + Add(_T("ssid"), &ssid); + Add(_T("password"), &password); + Add(_T("security"), &security); } - ~Stun() override = default; - public: - /* stun configuration */ - Core::JSON::String stunEndpoint; - Core::JSON::DecUInt32 port; - Core::JSON::DecUInt32 interval; + ~WiFiConfig() override = default; + WiFiConfig& operator=(const WiFiConfig&) = delete; + }; + + class Configuration : public Core::JSON::Container { + private: + Configuration(const Configuration&); + Configuration& operator=(const Configuration&); + + public: + Configuration() + : Core::JSON::Container() + { + Add(_T("connectivity"), &connectivityConf); + Add(_T("stun"), &stun); + Add(_T("loglevel"), &loglevel); + } + ~Configuration() override = default; + + public: + ConnectivityConf connectivityConf; + Stun stun; + Core::JSON::DecUInt32 loglevel; }; - public: - Config() - : Core::JSON::Container() + + class Job : public Core::IDispatch { + public: + Job(function work) + : _work(work) { - Add(_T("connectivity"), &connectivityConf); - Add(_T("stun"), &stun); - Add(_T("loglevel"), &loglevel); } - ~Config() override = default; + void Dispatch() override + { + _work(); + } - public: - ConnectivityConf connectivityConf; - Stun stun; - Core::JSON::DecUInt32 loglevel; - }; + private: + function _work; + }; + + public: + NetworkManagerImplementation(); + ~NetworkManagerImplementation() override; + + // Do not allow copy/move constructors + NetworkManagerImplementation(const NetworkManagerImplementation &) = delete; + NetworkManagerImplementation &operator=(const NetworkManagerImplementation &) = delete; + + BEGIN_INTERFACE_MAP(NetworkManagerImplementation) + INTERFACE_ENTRY(Exchange::INetworkManager) + END_INTERFACE_MAP - public: - NetworkManagerImplementation(); - ~NetworkManagerImplementation() override; - - // Do not allow copy/move constructors - NetworkManagerImplementation(const NetworkManagerImplementation &) = delete; - NetworkManagerImplementation &operator=(const NetworkManagerImplementation &) = delete; - - BEGIN_INTERFACE_MAP(NetworkManagerImplementation) - INTERFACE_ENTRY(Exchange::INetworkManager) - END_INTERFACE_MAP - - // Handle Notification registration/removal - uint32_t Register(INetworkManager::INotification *notification) override; - uint32_t Unregister(INetworkManager::INotification *notification) override; - - public: - // Below Control APIs will work with RDK or GNome NW. - /* @brief Get all the Available Interfaces */ - uint32_t GetAvailableInterfaces (IInterfaceDetailsIterator*& interfaces/* @out */) override; - - /* @brief Get the active Interface used for external world communication */ - uint32_t GetPrimaryInterface (string& interface /* @out */) override; - /* @brief Set the active Interface used for external world communication */ - uint32_t SetPrimaryInterface (const string& interface/* @in */) override; - - /* @brief Enable/Disable the given interface */ - uint32_t SetInterfaceState(const string& interface/* @in */, const bool isEnabled/* @in */) override; - /* @brief Get the state of given interface */ - uint32_t GetInterfaceState(const string& interface/* @in */, bool& isEnabled/* @out */) override; - - /* @brief Get IP Address Of the Interface */ - uint32_t GetIPSettings(string& interface /* @inout */, const string& ipversion /* @in */, IPAddress& address /* @out */) override; - /* @brief Set IP Address Of the Interface */ - uint32_t SetIPSettings(const string& interface /* @in */, const IPAddress& address /* @in */) override; - - // WiFi Specific Methods - /* @brief Initiate a WIFI Scan; This is Async method and returns the scan results as Event */ - uint32_t StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) override; - uint32_t StopWiFiScan(void) override; - - uint32_t GetKnownSSIDs(IStringIterator*& ssids /* @out */) override; - uint32_t AddToKnownSSIDs(const WiFiConnectTo& ssid /* @in */) override; - uint32_t RemoveKnownSSID(const string& ssid /* @in */) override; - - uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) override; - uint32_t WiFiDisconnect(void) override; - uint32_t GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) override; - - uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) override; - uint32_t StopWPS(void) override; - uint32_t GetWifiState(WiFiState &state) override; - uint32_t GetWiFiSignalStrength(string& ssid /* @out */, string& signalStrength /* @out */, WiFiSignalQuality& quality /* @out */) override; - - uint32_t SetStunEndpoint (string const endPoint /* @in */, const uint32_t port /* @in */, const uint32_t bindTimeout /* @in */, const uint32_t cacheTimeout /* @in */) override; - uint32_t GetStunEndpoint (string &endPoint /* @out */, uint32_t& port /* @out */, uint32_t& bindTimeout /* @out */, uint32_t& cacheTimeout /* @out */) const override; - - /* @brief Get ConnectivityTest Endpoints */ - uint32_t GetConnectivityTestEndpoints(IStringIterator*& endPoints/* @out */) const override; - /* @brief Set ConnectivityTest Endpoints */ - uint32_t SetConnectivityTestEndpoints(IStringIterator* const endPoints /* @in */) override; - - /* @brief Get Internet Connectivty Status */ - uint32_t IsConnectedToInternet(string &ipversion /* @inout */, InternetStatus &result /* @out */) override; - /* @brief Get Authentication URL if the device is behind Captive Portal */ - uint32_t GetCaptivePortalURI(string &endPoints/* @out */) const override; - - /* @brief Start The Internet Connectivity Monitoring */ - uint32_t StartConnectivityMonitoring(const uint32_t interval/* @in */) override; - /* @brief Stop The Internet Connectivity Monitoring */ - uint32_t StopConnectivityMonitoring(void) const override; - - /* @brief Get the Public IP used for external world communication */ - uint32_t GetPublicIP (string &ipversion /* @inout */, string& ipaddress /* @out */) override; - - /* @brief Request for ping and get the response in as event. The GUID used in the request will be returned in the event. */ - uint32_t Ping (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const uint16_t timeOutInSeconds /* @in */, const string guid /* @in */, string& response /* @out */) override; - - /* @brief Request for trace get the response in as event. The GUID used in the request will be returned in the event. */ - uint32_t Trace (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const string guid /* @in */, string& response /* @out */) override; - - uint32_t GetSupportedSecurityModes(ISecurityModeIterator*& securityModes /* @out */) const override; - - /* @brief Set the network manager plugin log level */ - uint32_t SetLogLevel(const Logging& level /* @in */) override; - uint32_t GetLogLevel(Logging& level /* @out */) override; - - /* @brief configure network manager plugin */ - uint32_t Configure(const string& configLine /* @in */) override; - - /* Events */ - void ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface); - void ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface); - void ReportIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status); - void ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState); - void ReportAvailableSSIDs(JsonArray &arrayofWiFiScanResults); - void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); - void ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality); - - public: - std::atomic m_ethConnected; - std::atomic m_wlanConnected; - - private: - void platform_init(); - void retryIarmEventRegistration(); - void getInitialConnectionState(); - void threadEventRegistration(); - void executeExternally(NetworkEvents event, const string commandToExecute, string& response); - void filterScanResults(JsonArray &ssids); - - private: - std::list _notificationCallbacks; - Core::CriticalSection _notificationLock; - string m_defaultInterface; - string m_publicIP; - stun::client stunClient; - string m_stunEndPoint; - uint16_t m_stunPort; - uint16_t m_stunBindTimeout; - uint16_t m_stunCacheTimeout; - std::thread m_registrationThread; - string m_filterfrequency; - std::vector m_filterSsidslist; - - public: - WiFiSignalStrengthMonitor m_wifiSignalMonitor; - mutable ConnectivityMonitor connectivityMonitor; + // Handle Notification registration/removal + uint32_t Register(INetworkManager::INotification *notification) override; + uint32_t Unregister(INetworkManager::INotification *notification) override; + + public: + // Below Control APIs will work with RDK or GNome NW. + /* @brief Get all the Available Interfaces */ + uint32_t GetAvailableInterfaces (IInterfaceDetailsIterator*& interfaces/* @out */) override; + + /* @brief Get the active Interface used for external world communication */ + uint32_t GetPrimaryInterface (string& interface /* @out */) override; + /* @brief Set the active Interface used for external world communication */ + uint32_t SetPrimaryInterface (const string& interface/* @in */) override; + + /* @brief Enable/Disable the given interface */ + uint32_t SetInterfaceState(const string& interface/* @in */, const bool isEnabled/* @in */) override; + /* @brief Get the state of given interface */ + uint32_t GetInterfaceState(const string& interface/* @in */, bool& isEnabled/* @out */) override; + + /* @brief Get IP Address Of the Interface */ + uint32_t GetIPSettings(string& interface /* @inout */, const string& ipversion /* @in */, IPAddress& address /* @out */) override; + /* @brief Set IP Address Of the Interface */ + uint32_t SetIPSettings(const string& interface /* @in */, const IPAddress& address /* @in */) override; + + // WiFi Specific Methods + /* @brief Initiate a WIFI Scan; This is Async method and returns the scan results as Event */ + uint32_t StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) override; + uint32_t StopWiFiScan(void) override; + + uint32_t GetKnownSSIDs(IStringIterator*& ssids /* @out */) override; + uint32_t AddToKnownSSIDs(const WiFiConnectTo& ssid /* @in */) override; + uint32_t RemoveKnownSSID(const string& ssid /* @in */) override; + + uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) override; + uint32_t WiFiDisconnect(void) override; + uint32_t GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) override; + + uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) override; + uint32_t StopWPS(void) override; + uint32_t GetWifiState(WiFiState &state) override; + uint32_t GetWiFiSignalStrength(string& ssid /* @out */, string& signalStrength /* @out */, WiFiSignalQuality& quality /* @out */) override; + + uint32_t SetStunEndpoint (string const endpoint /* @in */, const uint32_t port /* @in */, const uint32_t bindTimeout /* @in */, const uint32_t cacheTimeout /* @in */) override; + uint32_t GetStunEndpoint (string &endpoint /* @out */, uint32_t& port /* @out */, uint32_t& bindTimeout /* @out */, uint32_t& cacheTimeout /* @out */) const override; + + /* @brief Get ConnectivityTest Endpoints */ + uint32_t GetConnectivityTestEndpoints(IStringIterator*& endpoints/* @out */) const override; + /* @brief Set ConnectivityTest Endpoints */ + uint32_t SetConnectivityTestEndpoints(IStringIterator* const endpoints /* @in */) override; + + /* @brief Get Internet Connectivty Status */ + uint32_t IsConnectedToInternet(string &ipversion /* @inout */, InternetStatus &result /* @out */) override; + /* @brief Get Authentication URL if the device is behind Captive Portal */ + uint32_t GetCaptivePortalURI(string &endpoints/* @out */) const override; + + /* @brief Start The Internet Connectivity Monitoring */ + uint32_t StartConnectivityMonitoring(const uint32_t interval/* @in */) override; + /* @brief Stop The Internet Connectivity Monitoring */ + uint32_t StopConnectivityMonitoring(void) const override; + + /* @brief Get the Public IP used for external world communication */ + uint32_t GetPublicIP (string &ipversion /* @inout */, string& ipaddress /* @out */) override; + + /* @brief Request for ping and get the response in as event. The GUID used in the request will be returned in the event. */ + uint32_t Ping (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const uint16_t timeOutInSeconds /* @in */, const string guid /* @in */, string& response /* @out */) override; + + /* @brief Request for trace get the response in as event. The GUID used in the request will be returned in the event. */ + uint32_t Trace (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const string guid /* @in */, string& response /* @out */) override; + + uint32_t GetSupportedSecurityModes(ISecurityModeIterator*& securityModes /* @out */) const override; + + /* @brief Set the network manager plugin log level */ + uint32_t SetLogLevel(const Logging& level /* @in */) override; + uint32_t GetLogLevel(Logging& level /* @out */) override; + + /* @brief configure network manager plugin */ + uint32_t Configure(PluginHost::IShell* service) override; + + /* Events */ + void ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface); + void ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface); + void ReportIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status); + void ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState); + void ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults); + void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); + void ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality); + + private: + void platform_init(void); + void getInitialConnectionState(void); + void executeExternally(NetworkEvents event, const string commandToExecute, string& response); + void threadEventRegistration(void); + void filterScanResults(JsonArray &ssids); + + private: + std::list _notificationCallbacks; + Core::CriticalSection _notificationLock; + string m_defaultInterface; + string m_publicIP; + stun::client stunClient; + string m_stunEndpoint; + uint16_t m_stunPort; + uint16_t m_stunBindTimeout; + uint16_t m_stunCacheTimeout; + std::thread m_registrationThread; + string m_filterfrequency; + std::vector m_filterSsidslist; + + public: + std::atomic m_ethConnected; + std::atomic m_wlanConnected; + WiFiSignalStrengthMonitor m_wifiSignalMonitor; + mutable ConnectivityMonitor connectivityMonitor; }; } } diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 662862826..694230280 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -360,19 +360,19 @@ namespace WPEFramework { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string endPoint; + string endpoint; uint32_t port; uint32_t timeout; uint32_t cacheLifetime; if (_networkManager) - rc = _networkManager->GetStunEndpoint(endPoint, port, timeout, cacheLifetime); + rc = _networkManager->GetStunEndpoint(endpoint, port, timeout, cacheLifetime); else rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) { - response["endpoint"] = endPoint; + response["endpoint"] = endpoint; response["port"] = port; response["timeout"] = timeout; response["cacheLifetime"] = cacheLifetime; @@ -384,13 +384,13 @@ namespace WPEFramework { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string endPoint = parameters["endpoint"].String(); + string endpoint = parameters["endpoint"].String(); uint32_t port = parameters["port"].Number(); uint32_t bindTimeout = parameters["timeout"].Number(); uint32_t cacheTimeout = parameters["cacheLifetime"].Number(); if (_networkManager) - rc = _networkManager->SetStunEndpoint(endPoint, port, bindTimeout, cacheTimeout); + rc = _networkManager->SetStunEndpoint(endpoint, port, bindTimeout, cacheTimeout); else rc = Core::ERROR_UNAVAILABLE; @@ -583,8 +583,8 @@ namespace WPEFramework const PluginHost::ISubSystem::IInternet* internet(subSystem->Get()); if (nullptr == internet) { + NMLOG_INFO("Setting INTERNET ISubSystem"); subSystem->Set(PluginHost::ISubSystem::INTERNET, this); - NMLOG_INFO("Set INTERNET ISubSystem"); } subSystem->Release(); @@ -632,7 +632,7 @@ namespace WPEFramework reply.FromString(result); response = reply; } - returnJson(rc); + return rc; } uint32_t NetworkManager::Trace(const JsonObject& parameters, JsonObject& response) diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index cbe5c4307..e6fe30c43 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -537,11 +537,6 @@ namespace WPEFramework NMLOG_WARNING("WARNING - cannot handle IARM events without a Network plugin instance!"); } - void NetworkManagerImplementation::retryIarmEventRegistration() - { - m_registrationThread = thread(&NetworkManagerImplementation::threadEventRegistration, this); - - } void NetworkManagerImplementation::threadEventRegistration() { IARM_Result_t res = IARM_RESULT_SUCCESS; @@ -658,7 +653,7 @@ namespace WPEFramework { string msg = "NetSrvMgr is not available"; NMLOG_INFO("NETWORK_NOT_READY: The NetSrvMgr Component is not available.Retrying in separate thread ::%s::", msg.c_str()); - retryIarmEventRegistration(); + m_registrationThread = thread(&NetworkManagerImplementation::threadEventRegistration, this); } else { IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS, NetworkManagerInternalEventHandler); From be1a12e4f698afd5b46228ebfb490468ebaad393 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Mon, 30 Dec 2024 21:35:47 -0500 Subject: [PATCH 068/271] Release of v0.7.0 Signed-off-by: Karunakaran A --- CHANGELOG.md | 10 ++++++++++ CMakeLists.txt | 2 +- NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ffd188ee..018968fca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,16 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.7.0] - 2024-12-30 +### Added +- Gnome WPS custom design implemented +- Handle interface status based on IPAddress change event +- Cleanup STUN client codebase +- Handle JSON Event Subscription +- Handle Platform Init and Configure functions of out-of-process +- Handle the startup order +- Added L1 test cases for the plugins + ## [0.6.0] - 2024-12-10 ### Added - Added specific SSID/frequency scanning diff --git a/CMakeLists.txt b/CMakeLists.txt index 82961a4b0..363463c2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 6) +set(VERSION_MINOR 7) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/NetworkManager.json b/NetworkManager.json index fb9f5c33e..028586d78 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json", - "version": "0.6.0" + "version": "0.7.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 8c6b3f3ea..61b3ea518 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.6.0** +**Version: 0.7.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.6.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.7.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 0604fa5a1a687298d3c88795813500cb523cfb12 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Fri, 3 Jan 2025 12:12:42 -0500 Subject: [PATCH 069/271] RDKEMW-516 : GetPublicIP Method is not taking ipversion & interface correctly (#69) Reason for change: GetPublicIP Method is not taking ipversion & interface correctly Test Procedure: As per RDKEMW-516 Risks: Low Signed-off-by: kamirt573_comcast --- CHANGELOG.md | 5 +++++ CMakeLists.txt | 2 +- INetworkManager.h | 2 +- LegacyPlugin_NetworkAPIs.cpp | 13 ++++++++++--- NetworkManager.json | 33 +++++++++++++++++++------------- NetworkManagerImplementation.cpp | 23 ++++++++++++++++++++-- NetworkManagerImplementation.h | 2 +- NetworkManagerJsonRpc.cpp | 32 +++++++++++-------------------- docs/NetworkManagerPlugin.md | 12 ++++++++---- 9 files changed, 78 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 018968fca..553e999ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.8.0] - 2025-01-03 +### Changed +- Updated the definition of GetPublicIP method to take interface as additional input +- Updated the Legacy Plugin to use newly defined API + ## [0.7.0] - 2024-12-30 ### Added - Gnome WPS custom design implemented diff --git a/CMakeLists.txt b/CMakeLists.txt index 363463c2f..589df8816 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 7) +set(VERSION_MINOR 8) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/INetworkManager.h b/INetworkManager.h index 90c10760b..6b67729f5 100644 --- a/INetworkManager.h +++ b/INetworkManager.h @@ -243,7 +243,7 @@ namespace WPEFramework virtual uint32_t StopConnectivityMonitoring(void) const = 0; /* @brief Get the Public IP used for external world communication */ - virtual uint32_t GetPublicIP (string &ipversion /* @inout */, string& ipaddress /* @out */) = 0; + virtual uint32_t GetPublicIP (string& interface /* @inout */, string &ipversion /* @inout */, string& ipaddress /* @out */) = 0; /* @brief Request for ping and get the response in as event. The GUID used in the request will be returned in the event. */ virtual uint32_t Ping (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t count /* @in */, const uint16_t timeout /* @in */, const string guid /* @in */, string& response /* @out */) = 0; diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index 9f0068acc..d65c3ecc0 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -712,13 +712,20 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { uint32_t rc = Core::ERROR_GENERAL; string ipAddress{}; string ipversion = "IPv4"; - if (parameters.HasLabel("ipversion")) - ipversion = parameters["ipversion"].String(); + if (parameters.HasLabel("ipv6") && parameters["ipv6"].Boolean()) + ipversion = "IPv6"; + + string interface = ""; + if (parameters.HasLabel("iface")) + { + string givenInterface = parameters["iface"].String(); + interface = getInterfaceTypeToName(givenInterface); + } auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); if (_nwmgr) { - rc = _nwmgr->GetPublicIP(ipversion, ipAddress); + rc = _nwmgr->GetPublicIP(interface, ipversion, ipAddress); _nwmgr->Release(); } else diff --git a/NetworkManager.json b/NetworkManager.json index 028586d78..649a044b0 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json", - "version": "0.7.0" + "version": "0.8.0" }, "definitions": { "success": { @@ -423,7 +423,7 @@ "gateway", "primarydns", "secondarydns", - "success" + "success" ] } }, @@ -714,6 +714,9 @@ "type":"object", "summary":"it allows empty parameter too", "properties": { + "interface":{ + "$ref": "#/definitions/interface" + }, "ipversion": { "$ref": "#/definitions/ipversion" } @@ -724,19 +727,23 @@ "result": { "type": "object", "properties": { - "ipaddress": { - "$ref": "#/definitions/ipaddress" + "interface":{ + "$ref": "#/definitions/interface" }, "ipversion": { "$ref": "#/definitions/ipversion" }, + "ipaddress": { + "$ref": "#/definitions/ipaddress" + }, "success": { "$ref": "#/definitions/success" } }, "required": [ - "ipaddress", + "interface", "ipversion", + "ipaddress", "success" ] } @@ -846,7 +853,7 @@ "type":"object", "properties": { "endpoint":{ - "$ref": "#/definitions/endpoint" + "$ref": "#/definitions/endpoint" }, "ipversion": { "$ref": "#/definitions/ipversion" @@ -867,7 +874,7 @@ "type": "object", "properties": { "endpoint":{ - "$ref": "#/definitions/endpoint" + "$ref": "#/definitions/endpoint" }, "results": { "summary": "The response of traceroute", @@ -1333,7 +1340,7 @@ "type": "integer", "example": 12 }, - "NET_WIFI_SECURITY_WPA3_PSK_AES": { + "NET_WIFI_SECURITY_WPA3_PSK_AES": { "type": "integer", "example": 13 }, @@ -1387,7 +1394,7 @@ "type": "object", "properties": { "interface":{ - "$ref": "#/definitions/interface" + "$ref": "#/definitions/interface" }, "state":{ "summary": "Current state of the interface", @@ -1546,7 +1553,7 @@ "state":{ "summary": "WiFi State", "type": "integer", - "example": "5" + "example": "5" }, "status": { "summary": "WiFi status", @@ -1568,17 +1575,17 @@ "ssid":{ "summary": "Signal Strength changed SSID", "type": "string", - "example": "home-new_123" + "example": "home-new_123" }, "strength":{ "summary": "Signal Strength", "type": "string", - "example": "-27.000000" + "example": "-27.000000" }, "quality":{ "summary": "Signal quality", "type": "string", - "example": "Excellent" + "example": "Excellent" } }, "required": [ diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 81c17497a..6dad3144c 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -301,20 +301,30 @@ namespace WPEFramework } /* @brief Get the Public IP used for external world communication */ - uint32_t NetworkManagerImplementation::GetPublicIP (string &ipversion /* @inout */, string& ipaddress /* @out */) + uint32_t NetworkManagerImplementation::GetPublicIP (string& interface /* @inout */, string &ipversion /* @inout */, string& ipaddress /* @out */) { LOG_ENTRY_FUNCTION(); stun::bind_result result; bool isIPv6 = (ipversion == "IPv6"); + // Either Interface must be connected to get the public IP + if (!(m_ethConnected | m_wlanConnected)) + { + NMLOG_WARNING("No interface Connected"); + return Core::ERROR_GENERAL; + } + stun::protocol proto (isIPv6 ? stun::protocol::af_inet6 : stun::protocol::af_inet); - if(stunClient.bind(m_stunEndpoint, m_stunPort, m_defaultInterface, proto, m_stunBindTimeout, m_stunCacheTimeout, result)) + if(stunClient.bind(m_stunEndpoint, m_stunPort, interface, proto, m_stunBindTimeout, m_stunCacheTimeout, result)) { if (isIPv6) ipversion = "IPv6"; else ipversion = "IPv4"; + if (interface.empty()) + interface = m_defaultInterface; + ipaddress = result.public_ip; return Core::ERROR_NONE; } @@ -630,6 +640,9 @@ namespace WPEFramework else if (currentActiveinterface == "wlan0") m_wlanConnected = true; + // FIXME : This could be the place to define `m_defaultInterface` to incoming `currentActiveinterface`. + // m_defaultInterface = currentActiveinterface; + for (const auto callback : _notificationCallbacks) { callback->onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); } @@ -646,6 +659,12 @@ namespace WPEFramework else if(interface == "wlan0") m_wlanConnected = true; + // FIXME : Availability of ip address for a given interface does not mean that its the default interface. This hardcoding will work for RDKProxy but not for Gnome. + if (m_ethConnected && m_wlanConnected) + m_defaultInterface = "eth0"; + else + m_defaultInterface = interface; + // Start the connectivity monitor with 'true' to indicate the interface is up. // The monitor will conntinoue even after no internet retry completed, Exit when fully connectd. connectivityMonitor.startConnectivityMonitor(); diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 5c9c74eed..83fcc03d6 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -230,7 +230,7 @@ namespace WPEFramework uint32_t StopConnectivityMonitoring(void) const override; /* @brief Get the Public IP used for external world communication */ - uint32_t GetPublicIP (string &ipversion /* @inout */, string& ipaddress /* @out */) override; + uint32_t GetPublicIP (string& interface /* @inout */, string &ipversion /* @inout */, string& ipaddress /* @out */) override; /* @brief Request for ping and get the response in as event. The GUID used in the request will be returned in the event. */ uint32_t Ping (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const uint16_t timeOutInSeconds /* @in */, const string guid /* @in */, string& response /* @out */) override; diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 694230280..f1b8d76e8 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -535,30 +535,27 @@ namespace WPEFramework { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string ipAddress{}; + string interface{}; + string ipaddress{}; string ipversion = "IPv4"; if (parameters.HasLabel("ipversion")) ipversion = parameters["ipversion"].String(); - if ((!m_publicIPAddress.empty()) && (m_publicIPAddressType == ipversion)) - { - rc = Core::ERROR_NONE; - ipAddress = m_publicIPAddress; - } + if (parameters.HasLabel("interface")) + interface = parameters["interface"].String(); + + if (_networkManager) + rc = _networkManager->GetPublicIP(interface, ipversion, ipaddress); else - { - if (_networkManager) - rc = _networkManager->GetPublicIP(ipversion, ipAddress); - else - rc = Core::ERROR_UNAVAILABLE; - } + rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) { - response["ipaddress"] = ipAddress; + response["interface"] = interface; + response["ipaddress"] = ipaddress; response["ipversion"] = ipversion; - m_publicIPAddress = ipAddress; + m_publicIPAddress = ipaddress; m_publicIPAddressType = ipversion; PublishToThunderAboutInternet(); } @@ -567,15 +564,8 @@ namespace WPEFramework void NetworkManager::PublishToThunderAboutInternet() { - if (m_publicIPAddress.empty()) - { - JsonObject input, output; - GetPublicIP(input, output); - } - if (!m_publicIPAddress.empty()) { - NMLOG_DEBUG("No public IP persisted yet; Update the data"); PluginHost::ISubSystem* subSystem = _service->SubSystems(); if (subSystem != nullptr) diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 61b3ea518..66203f5f8 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.7.0** +**Version: 0.8.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.7.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.8.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity @@ -960,6 +960,7 @@ Gets the internet/public IP Address of the device. | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | It allows empty parameter too | +| params?.interface | string | *(optional)* An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | | params?.ipversion | string | *(optional)* Either IPv4 or IPv6 | ### Result @@ -967,8 +968,9 @@ Gets the internet/public IP Address of the device. | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.ipaddress | string | The IP address | +| result.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | | result.ipversion | string | Either IPv4 or IPv6 | +| result.ipaddress | string | The IP address | | result.success | boolean | Whether the request succeeded | ### Example @@ -981,6 +983,7 @@ Gets the internet/public IP Address of the device. "id": 42, "method": "org.rdk.NetworkManager.1.GetPublicIP", "params": { + "interface": "wlan0", "ipversion": "IPv4" } } @@ -993,8 +996,9 @@ Gets the internet/public IP Address of the device. "jsonrpc": "2.0", "id": 42, "result": { - "ipaddress": "192.168.1.101", + "interface": "wlan0", "ipversion": "IPv4", + "ipaddress": "192.168.1.101", "success": true } } From 92a7a5d40e56dc857ecad599d249aaecfc6a398e Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Sat, 4 Jan 2025 01:15:57 +0530 Subject: [PATCH 070/271] DELIA-66597, DELIA-66657 [RDE] - Implement GNOME support via direct G-DBus call for WiFi API and Events (#55) * DELIA-66597, DELIA-66657 [RDE] - Implement GNOME support via direct G-DBus call for WiFi API and Events * gdbus event implimetation memory leak fixed --- .../raspberrypi/NetworkManagerGdbusTest.cmake | 39 + Tests/raspberrypi/NetworkManagerGdbusTest.cpp | 274 ++++++ gdbus/NetworkManagerGdbusClient.cpp | 904 ++++++++++++++++++ gdbus/NetworkManagerGdbusClient.h | 67 ++ gdbus/NetworkManagerGdbusEvent.cpp | 789 +++++++++++++++ gdbus/NetworkManagerGdbusEvent.h | 84 ++ gdbus/NetworkManagerGdbusMgr.cpp | 262 +++++ gdbus/NetworkManagerGdbusMgr.h | 56 ++ gdbus/NetworkManagerGdbusProxy.cpp | 197 ++++ gdbus/NetworkManagerGdbusUtils.cpp | 551 +++++++++++ gdbus/NetworkManagerGdbusUtils.h | 87 ++ 11 files changed, 3310 insertions(+) create mode 100644 Tests/raspberrypi/NetworkManagerGdbusTest.cmake create mode 100644 Tests/raspberrypi/NetworkManagerGdbusTest.cpp create mode 100644 gdbus/NetworkManagerGdbusClient.cpp create mode 100644 gdbus/NetworkManagerGdbusClient.h create mode 100644 gdbus/NetworkManagerGdbusEvent.cpp create mode 100644 gdbus/NetworkManagerGdbusEvent.h create mode 100644 gdbus/NetworkManagerGdbusMgr.cpp create mode 100644 gdbus/NetworkManagerGdbusMgr.h create mode 100644 gdbus/NetworkManagerGdbusProxy.cpp create mode 100644 gdbus/NetworkManagerGdbusUtils.cpp create mode 100644 gdbus/NetworkManagerGdbusUtils.h diff --git a/Tests/raspberrypi/NetworkManagerGdbusTest.cmake b/Tests/raspberrypi/NetworkManagerGdbusTest.cmake new file mode 100644 index 000000000..bceae28dd --- /dev/null +++ b/Tests/raspberrypi/NetworkManagerGdbusTest.cmake @@ -0,0 +1,39 @@ +message("building rpi test build") +# Define the project +set(RPI_TEST "NetworkManagerGdbusTest") + +# Required packages +find_package(PkgConfig REQUIRED) +pkg_check_modules(GLIB REQUIRED glib-2.0) +pkg_check_modules(GIO REQUIRED gio-2.0) +pkg_check_modules(LIBNM REQUIRED libnm) + +# Create the executable target +add_executable(${RPI_TEST} + NetworkManagerLogger.cpp + gdbus/NetworkManagerGdbusClient.cpp + gdbus/NetworkManagerGdbusUtils.cpp + gdbus/NetworkManagerGdbusMgr.cpp + gdbus/NetworkManagerGdbusEvent.cpp + Tests/raspberrypi/NetworkManagerGdbusTest.cpp +) + +# Set target properties for C++ standard +set_target_properties(${RPI_TEST} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) + +# Add compiler options, such as forced include of a specific header +target_compile_options(${RPI_TEST} PRIVATE -g -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) + +target_include_directories(${RPI_TEST} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}) +target_include_directories(${RPI_TEST} PRIVATE gdbus) +# Link libraries to the target +target_link_libraries(${RPI_TEST} ${NAMESPACE}Core::${NAMESPACE}Core ${GLIB_LIBRARIES} ${GIO_LIBRARIES} uuid) + +# Include directories +target_include_directories(${RPI_TEST} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + +# Install the executable to the appropriate location +install(TARGETS ${RPI_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/Tests/raspberrypi/NetworkManagerGdbusTest.cpp b/Tests/raspberrypi/NetworkManagerGdbusTest.cpp new file mode 100644 index 000000000..01d9a60e1 --- /dev/null +++ b/Tests/raspberrypi/NetworkManagerGdbusTest.cpp @@ -0,0 +1,274 @@ +#include "NetworkManagerGdbusClient.h" +#include "NetworkManagerGdbusMgr.h" +#include "NetworkManagerLogger.h" +#include "NetworkManagerGdbusEvent.h" +#include "INetworkManager.h" +#include "NetworkManagerGdbusUtils.h" +#include "NetworkManagerImplementation.h" +#include +#include +#include +#include +#include + +using namespace WPEFramework; +using namespace WPEFramework::Plugin; +using namespace WPEFramework::Exchange; +using namespace std; + +namespace WPEFramework +{ + namespace Plugin + { + + void NetworkManagerImplementation::ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface) + { + NMLOG_INFO("calling 'ReportInterfaceStateChange' cb"); + } + void NetworkManagerImplementation::ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface) + { + NMLOG_INFO("calling 'ReportActiveInterfaceChange' cb"); + } + void NetworkManagerImplementation::ReportIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status) + { + NMLOG_INFO("calling 'ReportIPAddressChange' cb"); + } + void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) + { + NMLOG_INFO("calling 'ReportInternetStatusChange' cb"); + } + void NetworkManagerImplementation::ReportAvailableSSIDs(JsonArray &arrayofWiFiScanResults) + { + NMLOG_INFO("calling 'ReportAvailableSSIDs' cb"); + } + void NetworkManagerImplementation::ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state) + { + NMLOG_INFO("calling 'ReportWiFiStateChange' cb"); + } + void NetworkManagerImplementation::ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) + { + NMLOG_INFO("calling 'ReportWiFiSignalStrengthChange' cb"); + } + + NetworkManagerImplementation* _instance = nullptr; + } +} + +void displayMenu() +{ + std::cout << "\n--- Network Manager API Test Menu ---" << std::endl; + std::cout << "1. Get Known SSIDs" << std::endl; + std::cout << "2. Get Available SSIDs" << std::endl; + std::cout << "3. Get Connected SSID" << std::endl; + std::cout << "4. Add to Known SSIDs" << std::endl; + std::cout << "5. Remove Known SSIDs" << std::endl; + std::cout << "6. Start WiFi Scan" << std::endl; + std::cout << "7. WiFi Connect" << std::endl; + std::cout << "8. WiFi Disconnect" << std::endl; + std::cout << "9. Get WiFi State" << std::endl; + std::cout << "10. Get WiFi Signal Strength" << std::endl; + std::cout << "0. Exit" << std::endl; + std::cout << "-------------------------------------" << std::endl; +} + +WPEFramework::Exchange::INetworkManager::WIFISecurityMode getSecurityType() +{ + int securityChoice; + std::cout << "Select Security Type:" << std::endl; + std::cout << "1. WPA/WPA2 PSK AES" << std::endl; + std::cout << "2. WPA/WPA2 PSK TKIP" << std::endl; + std::cout << "3. Open (No Security)" << std::endl; + std::cin >> securityChoice; + + switch (securityChoice) { + case 1: + return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_WPA_PSK_AES; + case 2: + return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_WPA_PSK_TKIP; + case 3: + return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_NONE; + default: + std::cout << "Invalid choice. Defaulting to open." << std::endl; + return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_NONE; + } +} + +void printSSIDs(const std::list& ssids) +{ + if (ssids.empty()) { + std::cout << "No SSIDs found" << std::endl; + } else { + std::cout << "SSIDs:" << std::endl; + for (const auto& ssid : ssids) { + std::cout << "- " << ssid << std::endl; + } + } +} + + +int main() +{ + + NetworkManagerClient* nmClient = NetworkManagerClient::getInstance(); + NetworkManagerEvents* nmEvents = NetworkManagerEvents::getInstance(); + int choice = -1; + + while (choice != 0) { + displayMenu(); + std::cout << "Enter your choice: \n"; + std::cin >> choice; + + switch (choice) { + case 1: { + std::list ssids; + if (nmClient->getKnownSSIDs(ssids)) { + printSSIDs(ssids); + } else { + NMLOG_ERROR("Failed to get known SSIDs"); + } + break; + } + + case 2: { + std::list ssids; + if (nmClient->getAvailableSSIDs(ssids)) { + printSSIDs(ssids); + } else { + NMLOG_ERROR("Failed to get available SSIDs"); + } + break; + } + + case 3: { + Exchange::INetworkManager::WiFiSSIDInfo ssidinfo; + if (nmClient->getConnectedSSID(ssidinfo)) { + NMLOG_INFO("Connected SSID: %s", ssidinfo.ssid.c_str()); + } else { + NMLOG_ERROR("Failed to get connected SSID"); + } + break; + } + + case 4: { + std::string ssid, passphrase; + std::cout << "Enter SSID to add : "; + std::cin.ignore(); + std::getline(std::cin, ssid); + std::cout << "Enter passphrase: "; + std::getline(std::cin, passphrase); + WPEFramework::Exchange::INetworkManager::WIFISecurityMode securityType = getSecurityType(); + Exchange::INetworkManager::WiFiConnectTo ssidinfo = { + .ssid = ssid, + .passphrase = passphrase, + .security = securityType, + .persist = true, + }; + if (nmClient->addToKnownSSIDs(ssidinfo)) { + NMLOG_INFO("SSID added to known list successfully"); + } else { + NMLOG_ERROR("Failed to add SSID to known list"); + } + break; + } + + case 5: { + std::string ssid; + std::cout << "Enter SSID to remove: "; + std::cin >> ssid; + if (nmClient->removeKnownSSIDs(ssid)) { + NMLOG_INFO("SSID removed successfully"); + } else { + NMLOG_ERROR("Failed to remove SSID"); + } + break; + } + + case 6: { + std::string ssid; + std::cout << "Enter SSID to scan (leave blank for all): "; + std::cin.ignore(); + std::getline(std::cin, ssid); + nmEvents->setwifiScanOptions(true); + if (nmClient->startWifiScan(ssid)) { + NMLOG_INFO("WiFi scan started successfully"); + } else { + NMLOG_ERROR("Failed to start WiFi scan"); + } + break; + } + + case 7: { + std::string ssid, passphrase; + bool persist; + + std::cout << "Enter SSID to connect: "; + std::cin.ignore(); + std::getline(std::cin, ssid); + + std::cout << "Enter passphrase: "; + std::getline(std::cin, passphrase); + + WPEFramework::Exchange::INetworkManager::WIFISecurityMode securityType = getSecurityType(); + + std::cout << "Persist SSID info? (1 for yes, 0 for no): "; + std::cin >> persist; + + Exchange::INetworkManager::WiFiConnectTo ssidinfo = { + .ssid = ssid, + .passphrase = passphrase, + .security = securityType, + .persist = persist + }; + + if (nmClient->wifiConnect(ssidinfo)) { + NMLOG_INFO("Connected to WiFi successfully"); + } else { + NMLOG_ERROR("Failed to connect to WiFi"); + } + break; + } + + case 8: { + if (nmClient->wifiDisconnect()) { + NMLOG_INFO("Disconnected from WiFi successfully"); + } else { + NMLOG_ERROR("Failed to disconnect from WiFi"); + } + break; + } + + case 9: { + Exchange::INetworkManager::WiFiState state; + if (nmClient->getWifiState(state)) { + NMLOG_INFO("WiFi State: %d", state); // Assuming state is an enum or int + } else { + NMLOG_ERROR("Failed to get WiFi state"); + } + break; + } + + case 10: { + std::string ssid, signalStrength; + Exchange::INetworkManager::WiFiSignalQuality quality; + if (nmClient->getWiFiSignalStrength(ssid, signalStrength, quality)) { + NMLOG_INFO("SSID: %s, Signal Strength: %s, Quality: %d", ssid.c_str(), signalStrength.c_str(), quality); + } else { + NMLOG_ERROR("Failed to get WiFi signal strength"); + } + break; + } + + case 0: + std::cout << "Exiting program." << std::endl; + break; + + default: + std::cout << "Invalid choice, please try again." << std::endl; + break; + } + } + + NMLOG_INFO("Program completed successfully"); + nmEvents->stopNetworkMangerEventMonitor(); + return 0; +} diff --git a/gdbus/NetworkManagerGdbusClient.cpp b/gdbus/NetworkManagerGdbusClient.cpp new file mode 100644 index 000000000..59e4f678e --- /dev/null +++ b/gdbus/NetworkManagerGdbusClient.cpp @@ -0,0 +1,904 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2022 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include "NetworkManagerLogger.h" +#include "NetworkManagerGdbusClient.h" +#include "NetworkManagerGdbusUtils.h" + +namespace WPEFramework +{ + namespace Plugin + { + + NetworkManagerClient::NetworkManagerClient() { + NMLOG_INFO("NetworkManagerClient"); + } + + NetworkManagerClient::~NetworkManagerClient() { + NMLOG_INFO("~NetworkManagerClient"); + } + + static bool getSSIDFromConnection(DbusMgr &m_dbus, const std::string connPath, std::string& ssid) + { + GError *error = NULL; + GDBusProxy *ConnProxy = NULL; + GVariant *settingsProxy= NULL, *connection= NULL, *gVarConn= NULL; + bool ret = false; + + ConnProxy = m_dbus.getNetworkManagerSettingsConnectionProxy(connPath.c_str()); + if(ConnProxy == NULL) + return false; + + settingsProxy = g_dbus_proxy_call_sync(ConnProxy, "GetSettings", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (!settingsProxy) { + g_dbus_error_strip_remote_error(error); + NMLOG_ERROR("Failed to get connection settings: %s", error->message); + g_error_free(error); + g_object_unref(ConnProxy); + return false; + } + + g_variant_get(settingsProxy, "(@a{sa{sv}})", &connection); + gVarConn = g_variant_lookup_value(connection, "connection", NULL); + + if(gVarConn == NULL) { + NMLOG_ERROR("connection Gvarient Error"); + g_variant_unref(settingsProxy); + g_object_unref(ConnProxy); + return false; + } + + if(gVarConn) + { + const char *connTyp = NULL; + const char *interfaceName = NULL; + G_VARIANT_LOOKUP(gVarConn, "type", "&s", &connTyp); + G_VARIANT_LOOKUP(gVarConn, "interface-name", "&s", &interfaceName); + if((strcmp(connTyp, "802-11-wireless") == 0) && strcmp(interfaceName, GnomeUtils::getWifiIfname()) == 0 ) + { + // 802-11-wireless.ssid: + GVariant *setting = NULL; + setting = g_variant_lookup_value(connection, "802-11-wireless", NULL); + if(setting) + { + GVariantIter iter; + GVariant *value = NULL; + const char *propertyName; + g_variant_iter_init(&iter, setting); + while (g_variant_iter_next(&iter, "{&sv}", &propertyName, &value)) { + if (strcmp(propertyName, "ssid") == 0) { + // Decode SSID from GVariant of type "ay" + gsize ssid_length = 0; + const guchar *ssid_data = static_cast(g_variant_get_fixed_array(value, &ssid_length, sizeof(guchar))); + if (ssid_data && ssid_length > 0 && ssid_length <= 32) { + ssid.assign(reinterpret_cast(ssid_data), ssid_length); + NMLOG_DEBUG("SSID: %s", ssid.c_str()); + } else { + NMLOG_ERROR("Invalid SSID length: %zu (maximum is 32)", ssid_length); + ssid.empty(); + } + } + if(value) { + g_variant_unref(value); + value = NULL; + } + } + g_variant_unref(setting); + setting = NULL; + } + + if(!ssid.empty()) + { + // 802-11-wireless-security.key-mgmt: wpa-psk + const char* keyMgmt = NULL; + setting = g_variant_lookup_value(connection, "802-11-wireless-security", NULL); + if(setting != NULL) + { + G_VARIANT_LOOKUP(setting, "key-mgmt", "&s", &keyMgmt); + if(keyMgmt != NULL) + NMLOG_DEBUG("802-11-wireless-security.key-mgmt: %s", keyMgmt); + g_variant_unref(setting); + setting = NULL; + } + ret = true; + } + } + else + ret = false; + g_variant_unref(gVarConn); + } + + if (connection) + g_variant_unref(connection); + if (settingsProxy) + g_variant_unref(settingsProxy); + g_object_unref(ConnProxy); + + return ret; + } + + static bool deleteConnection(DbusMgr m_dbus, const std::string& path, std::string& ssid) + { + GError *error = NULL; + GDBusProxy *ConnProxy = NULL; + GVariant *deleteVar= NULL; + + ConnProxy = m_dbus.getNetworkManagerSettingsConnectionProxy(path.c_str()); + if(ConnProxy == NULL) + return false; + + deleteVar = g_dbus_proxy_call_sync(ConnProxy, "Delete", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (!deleteVar) { + g_dbus_error_strip_remote_error(error); + NMLOG_ERROR("Failed to get connection settings: %s", error->message); + g_error_free(error); + g_object_unref(ConnProxy); + return false; + } + else + NMLOG_INFO("connection '%s' Removed path: %s", ssid.c_str(), path.c_str()); + + if (deleteVar) + g_variant_unref(deleteVar); + g_object_unref(ConnProxy); + + return true; + } + + bool NetworkManagerClient::getKnownSSIDs(std::list& ssids) + { + std::list paths; + if(!GnomeUtils::getConnectionPaths(m_dbus, paths)) + { + NMLOG_ERROR("Connection path fetch failed"); + return false; + } + + for (const std::string& path : paths) { + // NMLOG_DEBUG("connection path %s", path.c_str()); + std::string ssid; + if(getSSIDFromConnection(m_dbus, path, ssid) && !ssid.empty()) + ssids.push_back(ssid); + } + + if(ssids.empty()) + { + NMLOG_WARNING("no Known SSID list empty"); + return false; + } + return true; + } + + bool NetworkManagerClient::getConnectedSSID(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo) + { + GDBusProxy* wProxy = NULL; + GVariant* result = NULL; + gchar *activeApPath = NULL; + bool ret = false; + deviceInfo devInfo{}; + + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), devInfo)) + return false; + + if(devInfo.path.empty() || devInfo.state < NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_ERROR("access point state not valid %d", devInfo.state); + return false; + } + + wProxy = m_dbus.getNetworkManagerWirelessProxy(devInfo.path.c_str()); + if(wProxy == NULL) + return false; + + result = g_dbus_proxy_get_cached_property(wProxy, "ActiveAccessPoint"); + if (!result) { + NMLOG_ERROR("Failed to get ActiveAccessPoint property."); + g_object_unref(wProxy); + return false; + } + + g_variant_get(result, "o", &activeApPath); + + if(activeApPath != NULL && g_strcmp0(activeApPath, "/") != 0) + { + //NMLOG_DEBUG("ActiveAccessPoint property path %s", activeApPath); + if(GnomeUtils::getApDetails(m_dbus, activeApPath, ssidinfo)) + { + ret = true; + } + } + else + NMLOG_WARNING("active access point not found"); + + if(activeApPath != NULL) + g_free(activeApPath); + g_variant_unref(result); + g_object_unref(wProxy); + return ret; + } + + bool NetworkManagerClient::getAvailableSSIDs(std::list& ssids) + { + GError* error = nullptr; + GDBusProxy* wProxy = nullptr; + deviceInfo devProperty{}; + + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), devProperty)) + return false; + + if(devProperty.path.empty() || devProperty.state < NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_ERROR("no wifi device found"); + return false; + } + + wProxy = m_dbus.getNetworkManagerWirelessProxy(devProperty.path.c_str()); + if (wProxy == NULL) + return false; + + GVariant* result = g_dbus_proxy_call_sync(wProxy, "GetAllAccessPoints", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + NMLOG_ERROR("Error creating proxy: %s", error->message); + g_error_free(error); + g_object_unref(wProxy); + return false; + } + + GVariantIter* iter = NULL; + const gchar* apPath = NULL; + g_variant_get(result, "(ao)", &iter); + + while (g_variant_iter_loop(iter, "o", &apPath)) { + Exchange::INetworkManager::WiFiSSIDInfo wifiInfo{}; + NMLOG_DEBUG("Access Point Path: %s", apPath); + if(GnomeUtils::getApDetails(m_dbus, apPath, wifiInfo)) + ssids.push_back(wifiInfo.ssid); + } + + g_variant_iter_free(iter); + g_variant_unref(result); + g_object_unref(wProxy); + + return true; + } + + bool NetworkManagerClient::startWifiScan(const std::string ssid) + { + GError* error = NULL; + GDBusProxy* wProxy = NULL; + deviceInfo devInfo; + + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), devInfo)) + return false; + + if(devInfo.path.empty() || devInfo.state < NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_WARNING("access point not active"); + return false; + } + + wProxy = m_dbus.getNetworkManagerWirelessProxy(devInfo.path.c_str()); + if(wProxy == NULL) + return false; + + GVariant* timeVariant = NULL; + timeVariant = g_dbus_proxy_get_cached_property(wProxy, "LastScan"); + if (!timeVariant) { + NMLOG_ERROR("Failed to get LastScan properties"); + g_object_unref(wProxy); + return false; + } + + if (g_variant_is_of_type (timeVariant, G_VARIANT_TYPE_INT64)) { + gint64 timestamp; + timestamp = g_variant_get_int64 (timeVariant); + NMLOG_DEBUG("Last scan timestamp: %lld", static_cast(timestamp)); + } else { + g_warning("Unexpected variant type: %s", g_variant_get_type_string (timeVariant)); + } + + if (!ssid.empty()) + { + GVariantBuilder builder; + NMLOG_INFO("Starting WiFi scanning with SSID: %s", ssid.c_str()); + GVariantBuilder ssidArray; + g_variant_builder_init(&ssidArray, G_VARIANT_TYPE("aay")); + g_variant_builder_add_value( + &ssidArray, g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (const guint8 *)ssid.c_str(), ssid.length(),1) + ); + /* ssid GVariant = [['S', 'S', 'I', 'D']] */ + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&builder, "{sv}", "ssids", g_variant_builder_end(&ssidArray)); + g_dbus_proxy_call_sync(wProxy, "RequestScan", g_variant_new("(a{sv})", builder), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + } + + else { + g_dbus_proxy_call_sync(wProxy, "RequestScan", g_variant_new("(a{sv})", NULL), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + } + + if (error) + { + NMLOG_ERROR("Error RequestScan: %s", error->message); + g_error_free(error); + g_object_unref(wProxy); + return false; + } + + g_object_unref(wProxy); + return true; + } + + bool updateConnctionAndactivate(DbusMgr& m_dbus, GVariantBuilder& connBuilder, const char* devicePath, const char* connPath) + { + GDBusProxy* proxy = nullptr; + GError* error = nullptr; + GVariant* result = nullptr; + + proxy = m_dbus.getNetworkManagerSettingsConnectionProxy(connPath); + if(proxy == NULL) + return false; + + result = g_dbus_proxy_call_sync (proxy, "Update", + g_variant_new("(a{sa{sv}})", connBuilder), + G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); + + if (error) { + NMLOG_ERROR("Failed to call Update : %s", error->message); + g_clear_error(&error); + g_object_unref(proxy); + return false; + } + + if(result) + g_variant_unref(result); + g_object_unref(proxy); + + proxy = m_dbus.getNetworkManagerProxy(); + if(proxy == NULL) + return false; + + if (error) { + NMLOG_ERROR( "Failed to create proxy: %s", error->message); + g_clear_error(&error); + return false; + } + const char* specificObject = "/"; + + result = g_dbus_proxy_call_sync (proxy, "ActivateConnection", + g_variant_new("(ooo)", connPath, devicePath, specificObject), + G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); + + if (error) { + NMLOG_ERROR("Failed to call ActivateConnection: %s", error->message); + g_clear_error(&error); + g_object_unref(proxy); + return false; + } + + if(result) { + GVariant* activeConnVariant; + g_variant_get(result, "(@o)", &activeConnVariant); + const char* activeConnPath = g_variant_get_string(activeConnVariant, nullptr); + NMLOG_DEBUG("connPath %s; activeconn %s", connPath, activeConnPath); + g_variant_unref(activeConnVariant); + } + + if(result) + g_variant_unref(result); + if(proxy) + g_object_unref(proxy); + + return true; + } + + bool addNewConnctionAndactivate(DbusMgr& m_dbus, GVariantBuilder connBuilder, const char* devicePath, bool persist) + { + GDBusProxy* proxy = nullptr; + GError* error = nullptr; + GVariant* result = nullptr; + + proxy = m_dbus.getNetworkManagerProxy(); + if(proxy == NULL) + return false; + + const char* specific_object = "/"; + + GVariantBuilder optionsBuilder; + g_variant_builder_init (&optionsBuilder, G_VARIANT_TYPE ("a{sv}")); + if(!persist) // by default it will be in disk mode + { + NMLOG_WARNING("wifi connection will not persist to the disk"); + g_variant_builder_add(&optionsBuilder, "{sv}", "persist", g_variant_new_string("volatile")); + } + //else + //g_variant_builder_add(&optionsBuilder, "{sv}", "persist", g_variant_new_string("disk")); + + result = g_dbus_proxy_call_sync (proxy, "AddAndActivateConnection2", + g_variant_new("(a{sa{sv}}ooa{sv})", connBuilder, devicePath, specific_object, optionsBuilder), + G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); + + if (result == NULL) { + if(error != NULL) + { + NMLOG_ERROR("Failed to call AddAndActivateConnection2: %s", error->message); + g_clear_error(&error); + } + g_object_unref(proxy); + return false; + } + + GVariant* pathVariant = NULL; + GVariant* activeConnVariant = NULL; + GVariant* resultDict = NULL; + + g_variant_get(result, "(@o@o@a{sv})", &pathVariant, &activeConnVariant, &resultDict); + + // Extract connection and active connection paths + const char* newConnPath = g_variant_get_string(pathVariant, nullptr); + const char* activeConnPath = g_variant_get_string(activeConnVariant, nullptr); + + NMLOG_INFO("newconn %s; activeconn %s",newConnPath, activeConnPath); + if(pathVariant) + g_variant_unref(pathVariant); + if(activeConnVariant) + g_variant_unref(activeConnVariant); + if(resultDict) + g_variant_unref(resultDict); + if(result) + g_variant_unref(result); + if(proxy) + g_object_unref(proxy); + return true; + } + + static inline std::string generateUUID() + { + uuid_t uuid{}; + char buffer[37] = {0}; // 36 + NULL + uuid_generate_random(uuid); + uuid_unparse_lower(uuid, buffer); + if(buffer[0] != '\0') + return std::string(buffer); + return std::string(""); + } + + static bool connectionBuilder(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo, GVariantBuilder& connBuilder) + { + GVariantBuilder settingsBuilder; + + g_variant_builder_init (&connBuilder, G_VARIANT_TYPE ("a{sa{sv}}")); + if(ssidinfo.ssid.empty() || ssidinfo.ssid.length() > 32) + { + NMLOG_WARNING("ssid name is missing or invalied"); + return false; + } + + NMLOG_INFO("ssid %s, security %d, persist %d", ssidinfo.ssid.c_str(), (int)ssidinfo.security, (int)ssidinfo.persist); + + /* Adding 'connection' settings */ + g_variant_builder_init (&settingsBuilder, G_VARIANT_TYPE ("a{sv}")); + std::string uuid = generateUUID(); + if(uuid.empty() || uuid.length() < 32) + { + NMLOG_ERROR("uuid generate failed"); + return false; + } + g_variant_builder_add (&settingsBuilder, "{sv}", "uuid", g_variant_new_string (uuid.c_str())); + g_variant_builder_add (&settingsBuilder, "{sv}", "id", g_variant_new_string (ssidinfo.ssid.c_str())); // connection id = ssid name + g_variant_builder_add (&settingsBuilder, "{sv}", "interface-name", g_variant_new_string (GnomeUtils::getWifiIfname())); + g_variant_builder_add (&settingsBuilder, "{sv}", "type", g_variant_new_string ("802-11-wireless")); + g_variant_builder_add (&connBuilder, "{sa{sv}}", "connection", &settingsBuilder); + /* Adding '802-11-wireless 'settings */ + g_variant_builder_init (&settingsBuilder, G_VARIANT_TYPE ("a{sv}")); + GVariant *ssidArray = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (const guint8 *)ssidinfo.ssid.c_str(), ssidinfo.ssid.length(), 1); + g_variant_builder_add (&settingsBuilder, "{sv}", "ssid", ssidArray); + g_variant_builder_add (&settingsBuilder, "{sv}", "mode", g_variant_new_string("infrastructure")); + g_variant_builder_add (&settingsBuilder, "{sv}", "hidden", g_variant_new_boolean(true)); // set hidden: yes + g_variant_builder_add (&connBuilder, "{sa{sv}}", "802-11-wireless", &settingsBuilder); + + /* Adding '802-11-wireless-security' settings */ + g_variant_builder_init (&settingsBuilder, G_VARIANT_TYPE ("a{sv}")); + + switch(ssidinfo.security) + { + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_TKIP: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_TKIP: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_PSK_AES: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE: + { + if(ssidinfo.passphrase.empty() || ssidinfo.passphrase.length() < 8) + { + NMLOG_WARNING("wifi securtity type password erro length > 8"); + GVariant *sVariant = g_variant_builder_end(&settingsBuilder); + if(sVariant) + g_variant_unref(sVariant); + return false; + } + + if(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE == ssidinfo.security) + { + NMLOG_DEBUG("802-11-wireless-security key-mgmt: 'sae'"); + g_variant_builder_add (&settingsBuilder, "{sv}", "key-mgmt", g_variant_new_string("sae")); + } + else + { + NMLOG_DEBUG("802-11-wireless-security key-mgmt: 'wpa-psk'"); + g_variant_builder_add (&settingsBuilder, "{sv}", "key-mgmt", g_variant_new_string("wpa-psk")); // WPA + WPA2 + WPA3 personal + } + g_variant_builder_add (&settingsBuilder, "{sv}", "psk", g_variant_new_string(ssidinfo.passphrase.c_str())); // password + break; + } + + case Exchange::INetworkManager::WIFI_SECURITY_NONE: + { + NMLOG_DEBUG("802-11-wireless-security key-mgmt: 'none'"); + g_variant_builder_add (&settingsBuilder, "{sv}", "key-mgmt", g_variant_new_string("none")); // no password protection + break; + } + default: + { + NMLOG_WARNING("connection wifi securtity type not supported %d", ssidinfo.security); + GVariant *sVariant = g_variant_builder_end(&settingsBuilder); + if(sVariant) + g_variant_unref(sVariant); + return false; + } + } + + g_variant_builder_add (&connBuilder, "{sa{sv}}", "802-11-wireless-security", &settingsBuilder); + /* Adding the 'ipv4' Setting */ + g_variant_builder_init (&settingsBuilder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (&settingsBuilder, "{sv}", "method", g_variant_new_string ("auto")); + g_variant_builder_add (&connBuilder, "{sa{sv}}", "ipv4", &settingsBuilder); + + /* Adding the 'ipv6' Setting */ + g_variant_builder_init (&settingsBuilder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (&settingsBuilder, "{sv}", "method", g_variant_new_string ("auto")); + g_variant_builder_add (&connBuilder, "{sa{sv}}", "ipv6", &settingsBuilder); + NMLOG_DEBUG("connection builder success..."); + return true; + } + + bool NetworkManagerClient::addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo) + { + GVariantBuilder connBuilder; + bool ret = false, reuseConnection = false; + GVariant *result = NULL; + GError* error = NULL; + const char *newConPath = NULL; + std::string exsistingConn; + deviceInfo deviceProp; + + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), deviceProp)) + return false; + + if(deviceProp.path.empty() || deviceProp.state == NM_DEVICE_STATE_UNKNOWN) + { + NMLOG_WARNING("wlan0 interface not active"); + return false; + } + + std::list paths{}; + if(GnomeUtils::getWifiConnectionPaths(m_dbus, deviceProp.path.c_str(), paths)) + { + for (const std::string& path : paths) + { + std::string ssid{}; + if(getSSIDFromConnection(m_dbus, path, ssid) && ssid == ssidinfo.ssid) + { + exsistingConn = path; + NMLOG_DEBUG("same connection exsist (%s) updating ...", exsistingConn.c_str()); + reuseConnection = true; + break; // only one connection will be activate (same property only) + } + } + } + + if(!connectionBuilder(ssidinfo, connBuilder)) + { + NMLOG_WARNING("connection builder failed"); + GVariant *variant = g_variant_builder_end(&connBuilder); + if(variant) + g_variant_unref(variant); + return false; + } + + if(reuseConnection) + { + GDBusProxy* proxy = m_dbus.getNetworkManagerSettingsConnectionProxy(exsistingConn.c_str()); + + if(proxy != nullptr) + { + result = g_dbus_proxy_call_sync (proxy, "Update", + g_variant_new("(a{sa{sv}})", connBuilder), + G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); + + if (error == nullptr) { + NMLOG_DEBUG("same connection updated success : %s", exsistingConn.c_str()); + ret = true; + } + else { + NMLOG_ERROR("Failed to call Update : %s", error->message); + g_clear_error(&error); + } + if(result) + g_variant_unref (result); + g_object_unref(proxy); + } + } + else + { + GDBusProxy *proxy = NULL; + proxy = m_dbus.getNetworkManagerSettingsProxy(); + if (proxy != nullptr) + { + result = g_dbus_proxy_call_sync (proxy, "AddConnection", + g_variant_new ("(a{sa{sv}})", &connBuilder), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + + if (error != nullptr) { + g_dbus_error_strip_remote_error (error); + NMLOG_ERROR ("Could not create NetworkManager/Settings proxy: %s", error->message); + g_error_free (error); + g_object_unref(proxy); + return false; + } + + if (result) { + g_variant_get (result, "(&o)", &newConPath); + NMLOG_INFO("Added a new connection: %s", newConPath); + ret = true; + g_variant_unref (result); + } else { + g_dbus_error_strip_remote_error (error); + NMLOG_ERROR("Error adding connection: %s", error->message); + g_clear_error (&error); + } + g_object_unref(proxy); + } + } + + return ret; + } + + bool NetworkManagerClient::removeKnownSSIDs(const std::string& ssid) + { + bool ret = false; + if(ssid.empty()) + { + NMLOG_ERROR("ssid name is empty"); + return false; + } + + std::list paths; + if(!GnomeUtils::getConnectionPaths(m_dbus, paths)) + { + NMLOG_ERROR("remove connection path fetch failed"); + return false; + } + + for (const std::string& path : paths) { + // NMLOG_DEBUG("remove connection path %s", path.c_str()); + std::string connSsid; + if(getSSIDFromConnection(m_dbus, path, connSsid) && connSsid == ssid) { + ret = deleteConnection(m_dbus, path, connSsid); + } + } + + if(!ret) + NMLOG_ERROR("ssid '%s' Connection remove failed", ssid.c_str()); + + return ret; + } + + bool NetworkManagerClient::getWiFiSignalStrength(string& ssid, string& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality) + { + Exchange::INetworkManager::WiFiSSIDInfo ssidInfo; + const float signalStrengthThresholdExcellent = -50.0f; + const float signalStrengthThresholdGood = -60.0f; + const float signalStrengthThresholdFair = -67.0f; + + if(!getConnectedSSID(ssidInfo)) + { + NMLOG_ERROR("no wifi connected"); + return false; + } + else + { + ssid = ssidInfo.ssid; + signalStrength = ssidInfo.strength; + + float signalStrengthFloat = 0.0f; + if(!signalStrength.empty()) + signalStrengthFloat = std::stof(signalStrength.c_str()); + + if (signalStrengthFloat == 0) + quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; + else if (signalStrengthFloat >= signalStrengthThresholdExcellent && signalStrengthFloat < 0) + quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT; + else if (signalStrengthFloat >= signalStrengthThresholdGood && signalStrengthFloat < signalStrengthThresholdExcellent) + quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_GOOD; + else if (signalStrengthFloat >= signalStrengthThresholdFair && signalStrengthFloat < signalStrengthThresholdGood) + quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_FAIR; + else + quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_WEAK; + NMLOG_INFO("strength success %s dBm", signalStrength.c_str()); + } + + return true; + } + + bool NetworkManagerClient::getWifiState(Exchange::INetworkManager::WiFiState &state) + { + deviceInfo deviceProp; + state = Exchange::INetworkManager::WiFiState::WIFI_STATE_UNINSTALLED; + + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), deviceProp)) + return false; + + // Todo check NMDeviceStateReason for more information + switch(deviceProp.state) + { + case NM_DEVICE_STATE_ACTIVATED: + state = Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTED; + break; + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + state = Exchange::INetworkManager::WiFiState::WIFI_STATE_PAIRING; + break; + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_IP_CHECK: + case NM_DEVICE_STATE_SECONDARIES: + state = Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTING; + break; + case NM_DEVICE_STATE_DEACTIVATING: + case NM_DEVICE_STATE_FAILED: + case NM_DEVICE_STATE_DISCONNECTED: + state = Exchange::INetworkManager::WiFiState::WIFI_STATE_DISCONNECTED; + break; + default: + state = Exchange::INetworkManager::WiFiState::WIFI_STATE_DISABLED; + } + NMLOG_DEBUG("networkmanager wifi state (%d) mapped state (%d) ", (int)deviceProp.state, (int)state); + return true; + } + + bool NetworkManagerClient::wifiConnect(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo) + { + // TODO check sudo nmcli device wifi connect HomeNet password rafi@123 + // Error: Connection activation failed: Device disconnected by user or client error ? + GVariantBuilder connBuilder; + bool reuseConnection = false; + deviceInfo deviceProp; + std::string exsistingConn; + + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), deviceProp)) + return false; + + if(deviceProp.path.empty() || deviceProp.state < NM_DEVICE_STATE_UNAVAILABLE) + { + NMLOG_ERROR("wlan0 interface not active"); + return false; + } + + std::list paths; + if(GnomeUtils::getWifiConnectionPaths(m_dbus, deviceProp.path.c_str(), paths)) + { + for (const std::string& path : paths) { + std::string ssid; + if(getSSIDFromConnection(m_dbus, path, ssid) && ssid == ssidinfo.ssid) + { + exsistingConn = path; + NMLOG_WARNING("same connection exsist (%s)", exsistingConn.c_str()); + reuseConnection = true; + break; // only one connection will be activate (same property only) + } + } + } + + if(reuseConnection) + { + NMLOG_INFO("activating connection..."); + if(!connectionBuilder(ssidinfo, connBuilder)) { + NMLOG_WARNING("connection builder failed"); + return false; + } + + if(updateConnctionAndactivate(m_dbus, connBuilder, deviceProp.path.c_str(), exsistingConn.c_str())) + NMLOG_INFO("updated connection request success"); + else { + NMLOG_ERROR("wifi connect request failed"); + return false; + } + } + else + { + if(!connectionBuilder(ssidinfo, connBuilder)) { + NMLOG_WARNING("connection builder failed"); + return false; + } + if(addNewConnctionAndactivate(m_dbus, connBuilder, deviceProp.path.c_str(), ssidinfo.persist)) + NMLOG_INFO("wifi connect request success"); + else { + NMLOG_ERROR("wifi connect request failed"); + return false; + } + } + + return true; + } + + bool NetworkManagerClient::wifiDisconnect() + { + GError* error = NULL; + GDBusProxy* wProxy = NULL; + deviceInfo devInfo; + + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), devInfo) || devInfo.path.empty()) + return false; + + if(devInfo.state <= NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_WARNING("wifi in disconnected state"); + return true; + } + + wProxy = m_dbus.getNetworkManagerDeviceProxy(devInfo.path.c_str()); + if(wProxy == NULL) + return false; + else + g_dbus_proxy_call_sync(wProxy, "Disconnect", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + return true; + if (error) { + NMLOG_ERROR("Error calling Disconnect method: %s", error->message); + g_error_free(error); + g_object_unref(wProxy); + return false; + } + else + NMLOG_INFO("wifi disconnected success"); + + g_object_unref(wProxy); + return true; + } + + bool NetworkManagerClient::startWPS() + { + return false; + } + + bool NetworkManagerClient::stopWPS() + { + return false; + } + + } // WPEFramework +} // Plugin diff --git a/gdbus/NetworkManagerGdbusClient.h b/gdbus/NetworkManagerGdbusClient.h new file mode 100644 index 000000000..15b8eb11b --- /dev/null +++ b/gdbus/NetworkManagerGdbusClient.h @@ -0,0 +1,67 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include +#include +#include +#include + +#include "NetworkManagerLogger.h" +#include "NetworkManagerGdbusMgr.h" +#include "INetworkManager.h" + +namespace WPEFramework +{ + namespace Plugin + { + + class NetworkManagerClient + { + public: + static NetworkManagerClient* getInstance() + { + static NetworkManagerClient instance; + return &instance; + } + + NetworkManagerClient(const NetworkManagerClient&) = delete; + NetworkManagerClient& operator=(const NetworkManagerClient&) = delete; + + bool getKnownSSIDs(std::list& ssids); + bool getAvailableSSIDs(std::list& ssids); + bool getConnectedSSID(Exchange::INetworkManager::WiFiSSIDInfo& ssidinfo); + bool addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo); + bool removeKnownSSIDs(const std::string& ssid); + bool startWifiScan(const std::string ssid = ""); + bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo); + bool wifiDisconnect(); + bool getWifiState(Exchange::INetworkManager::WiFiState &state); + bool getWiFiSignalStrength(std::string& ssid, std::string& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality); + bool startWPS(); + bool stopWPS(); + + private: + NetworkManagerClient(); + ~NetworkManagerClient(); + + DbusMgr m_dbus; + }; + } // Plugin +} // WPEFramework \ No newline at end of file diff --git a/gdbus/NetworkManagerGdbusEvent.cpp b/gdbus/NetworkManagerGdbusEvent.cpp new file mode 100644 index 000000000..21c035802 --- /dev/null +++ b/gdbus/NetworkManagerGdbusEvent.cpp @@ -0,0 +1,789 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include + +#include "NetworkManagerGdbusEvent.h" +#include "NetworkManagerGdbusUtils.h" +#include "NetworkManagerImplementation.h" +#include "NetworkManagerLogger.h" +#include "INetworkManager.h" + +namespace WPEFramework +{ + namespace Plugin + { + + static NetworkManagerEvents *_NetworkManagerEvents = nullptr; + extern NetworkManagerImplementation* _instance; + + static std::string getInterafaceNameFormDevicePath(const char* DevicePath) + { + GDBusProxy *deviceProxy = NULL; + std::string ifname; + deviceProxy =_NetworkManagerEvents->eventDbus.getNetworkManagerDeviceProxy(DevicePath); + if (deviceProxy == NULL) + return ifname; + GVariant *ifaceVariant = g_dbus_proxy_get_cached_property(deviceProxy, "Interface"); + if (ifaceVariant == NULL) { + NMLOG_WARNING("Interface property get error"); + return ifname; + } + + const gchar *ifaceName = g_variant_get_string(ifaceVariant, NULL); + if(ifaceName != nullptr) + ifname = ifaceName; + + g_variant_unref(ifaceVariant); + g_object_unref(deviceProxy); + return ifname; + } + + static void lastScanPropertiesChangedCB(GDBusProxy *proxy, GVariant *changedProps, + const gchar *invalidProps[], gpointer userData) { + + if (proxy == NULL) { + NMLOG_FATAL("cb doesn't have proxy "); + return; + } + + GVariant *lastScanVariant = g_variant_lookup_value(changedProps, "LastScan", NULL); + if (lastScanVariant == NULL) + return; + + gint64 lastScanTime = g_variant_get_int64(lastScanVariant); + NMLOG_DEBUG("LastScan value changed: %" G_GINT64_FORMAT, lastScanTime); + g_variant_unref(lastScanVariant); + + const gchar *objectPath = g_dbus_proxy_get_object_path(proxy); + if (objectPath == NULL) { + NMLOG_WARNING("Failed to get the proxy object path"); + return; + } + + NetworkManagerEvents::onAvailableSSIDsCb(objectPath); + } + + static bool subscribeForlastScanPropertyEvent(const gchar *wirelessPath) + { + // Todo clean the proxy first + NMLOG_DEBUG("Monitoring lastScan time property: %s", wirelessPath); + _NetworkManagerEvents->nmEvents.wirelessProxy = _NetworkManagerEvents->eventDbus.getNetworkManagerWirelessProxy(wirelessPath); + if (_NetworkManagerEvents->nmEvents.wirelessProxy == nullptr) { + return false; + } + g_signal_connect(_NetworkManagerEvents->nmEvents.wirelessProxy, "g-properties-changed", G_CALLBACK(lastScanPropertiesChangedCB), NULL); + return true; + } + + static void primaryConnectionChangedCB(GDBusProxy *proxy, GVariant *changedPropes, GStrv invalidatPropes, gpointer userData) + { + if (changedPropes == NULL) { + NMLOG_FATAL("cb doesn't have changed_properties "); + return; + } + + GVariant *primaryConnPathVariant = g_variant_lookup_value(changedPropes, "PrimaryConnection", NULL); + if (primaryConnPathVariant != NULL) + { + const gchar *primaryConnPath = NULL; + std::string newIface = ""; + primaryConnPath = g_variant_get_string(primaryConnPathVariant, NULL); + if(primaryConnPath && g_strcmp0(primaryConnPath, "/") == 0) + { + NMLOG_DEBUG("no active primary connection"); + // sending empty string if no active interface + NetworkManagerEvents::onActiveInterfaceChangeCb(std::string("Unknown")); + g_variant_unref(primaryConnPathVariant); + return; + } + else if(primaryConnPath) + { + GDBusProxy *activeProxy = NULL; + NMLOG_DEBUG("PrimaryConnection changed: %s", primaryConnPath); + activeProxy =_NetworkManagerEvents->eventDbus.getNetworkManagerActiveConnProxy(primaryConnPath); + if(activeProxy != NULL) + { + GVariant *typeVariant = g_dbus_proxy_get_cached_property(activeProxy, "Type"); + if (typeVariant != NULL) + { + const gchar *connectionType = g_variant_get_string(typeVariant, NULL); + if(connectionType != NULL) { + if (0 == strncmp("802-3-ethernet", connectionType, sizeof("802-3-ethernet"))) + NetworkManagerEvents::onActiveInterfaceChangeCb(std::string(GnomeUtils::getEthIfname())); + else if(0 == strncmp("802-11-wireless", connectionType, sizeof("802-11-wireless"))) + NetworkManagerEvents::onActiveInterfaceChangeCb(std::string(GnomeUtils::getWifiIfname())); + else + NMLOG_WARNING("active connection not an ethernet/wifi %s", connectionType); + } + else + NMLOG_WARNING("connection type NULL"); + g_variant_unref(typeVariant); + } + else + NMLOG_ERROR("PrimaryConnection Type property missing"); + g_object_unref(activeProxy); + } + } + else + NMLOG_WARNING("PrimaryConnection object missing"); + g_variant_unref(primaryConnPathVariant); + } + } + + static void deviceAddRemoveCb(GDBusProxy *proxy, gchar *senderName, gchar *signalName, + GVariant *parameters, gpointer userData) { + + if (signalName == NULL) { + NMLOG_FATAL("cb doesn't have signalName "); + return; + } + + const gchar *devicePath = NULL; + std::string ifname; + if (g_strcmp0(signalName, "DeviceAdded") == 0 || g_strcmp0(signalName, "DeviceRemoved") == 0) + { + if (g_variant_is_of_type(parameters, G_VARIANT_TYPE_TUPLE)) { + GVariant *first_element = g_variant_get_child_value(parameters, 0); + + if (g_variant_is_of_type(first_element, G_VARIANT_TYPE_OBJECT_PATH)) { + devicePath = g_variant_get_string(first_element, NULL); + ifname = getInterafaceNameFormDevicePath(devicePath); + } else { + NMLOG_ERROR("varient type not object path %s", g_variant_get_type_string(first_element)); + } + g_variant_unref(first_element); + } + if (g_strcmp0(signalName, "DeviceAdded") == 0) { + NMLOG_INFO("Device Added: %s", ifname.c_str()); + if(ifname == GnomeUtils::getWifiIfname() || ifname == GnomeUtils::getEthIfname() ) + { + NMLOG_INFO("monitoring device: %s", ifname.c_str()); + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, ifname.c_str()); + // TODO monitor device + // monitorDevice() + } + } + else if(g_strcmp0(signalName, "DeviceRemoved")) { + NMLOG_INFO("Device Removed: %s", ifname.c_str()); + if(ifname == GnomeUtils::getWifiIfname() || ifname == GnomeUtils::getEthIfname() ) + { + NMLOG_INFO("monitoring device: %s", ifname.c_str()); + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, ifname.c_str()); + } + } + } + } + + static void deviceStateChangedCB(GDBusProxy *proxy, gchar *senderName, gchar *signalName, + GVariant *parameters, gpointer userData) { + + if (signalName == NULL || g_strcmp0(signalName, "StateChanged") != 0) { + return; + } + + static bool doPostEthUpEvent= false; + static bool doPostWlanUpEvent= false; + + const gchar *devicePath = g_dbus_proxy_get_object_path(proxy); + std::string ifname = getInterafaceNameFormDevicePath(devicePath); + if(ifname.empty()) + { + NMLOG_WARNING("interface name null"); + return; + } + guint32 oldState, newState, stateReason; + g_variant_get(parameters, "(uuu)", &newState, &oldState, &stateReason); + NMDeviceState deviceState = static_cast(newState); + NMDeviceStateReason deviceStateReason = static_cast(stateReason); + + NMLOG_DEBUG("%s: Old State: %u, New State: %u, Reason: %u", ifname.c_str(), oldState, newState, stateReason); + if(ifname == GnomeUtils::getWifiIfname()) + { + std::string wifiState; + switch (deviceStateReason) + { + case NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE: + wifiState = "WIFI_STATE_UNINSTALLED"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_UNINSTALLED, wifiState); + break; + case NM_DEVICE_STATE_REASON_SSID_NOT_FOUND: + wifiState = "WIFI_STATE_SSID_NOT_FOUND"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND, wifiState); + break; + case NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT: // supplicant took too long to authenticate + case NM_DEVICE_STATE_REASON_NO_SECRETS: + wifiState = "WIFI_STATE_AUTHENTICATION_FAILED"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_AUTHENTICATION_FAILED, wifiState); + break; + case NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED: // 802.1x supplicant failed + wifiState = "WIFI_STATE_ERROR"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_ERROR, wifiState); + break; + case NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED: // 802.1x supplicant configuration failed + wifiState = "WIFI_STATE_CONNECTION_INTERRUPTED"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTION_INTERRUPTED, wifiState); + break; + case NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT: // 802.1x supplicant disconnected + wifiState = "WIFI_STATE_INVALID_CREDENTIALS"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_INVALID_CREDENTIALS, wifiState); + break; + default: + { + switch (deviceState) + { + case NM_DEVICE_STATE_UNKNOWN: + wifiState = "WIFI_STATE_UNINSTALLED"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_UNINSTALLED, wifiState); + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, GnomeUtils::getWifiIfname()); + doPostWlanUpEvent= true; + break; + case NM_DEVICE_STATE_UNMANAGED: + wifiState = "WIFI_STATE_DISABLED"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_DISABLED, wifiState); + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, GnomeUtils::getWifiIfname()); + doPostWlanUpEvent= true; + break; + case NM_DEVICE_STATE_UNAVAILABLE: + case NM_DEVICE_STATE_DISCONNECTED: + wifiState = "WIFI_STATE_DISCONNECTED"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_DISCONNECTED, wifiState); + NetworkManagerEvents::onAddressChangeCb(GnomeUtils::getWifiIfname(), false, false); + NetworkManagerEvents::onAddressChangeCb(GnomeUtils::getWifiIfname(), false, true); + break; + case NM_DEVICE_STATE_PREPARE: + wifiState = "WIFI_STATE_PAIRING"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_PAIRING, wifiState); + break; + case NM_DEVICE_STATE_CONFIG: + wifiState = "WIFI_STATE_CONNECTING"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTING, wifiState); + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_UP, GnomeUtils::getWifiIfname()); + break; + case NM_DEVICE_STATE_IP_CHECK: + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP, GnomeUtils::getWifiIfname()); + break; + case NM_DEVICE_STATE_ACTIVATED: + wifiState = "WIFI_STATE_CONNECTED"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTED, wifiState); + break; + case NM_DEVICE_STATE_DEACTIVATING: + wifiState = "WIFI_STATE_CONNECTION_LOST"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTION_LOST, wifiState); + break; + case NM_DEVICE_STATE_FAILED: + wifiState = "WIFI_STATE_CONNECTION_FAILED"; + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED, wifiState); + break; + case NM_DEVICE_STATE_NEED_AUTH: + //NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTION_INTERRUPTED); + wifiState = "WIFI_STATE_CONNECTION_INTERRUPTED"; + break; + default: + wifiState = "Un handiled"; + } + + if(doPostWlanUpEvent && deviceState > NM_DEVICE_STATE_UNMANAGED) + { + doPostWlanUpEvent = false; + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, GnomeUtils::getWifiIfname()); + } + } + } + } + else if(ifname == GnomeUtils::getEthIfname()) + { + switch (deviceState) + { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_DISABLED, GnomeUtils::getEthIfname()); + doPostEthUpEvent= true; + break; + case NM_DEVICE_STATE_UNAVAILABLE: + case NM_DEVICE_STATE_DISCONNECTED: + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_DOWN, GnomeUtils::getEthIfname()); + NetworkManagerEvents::onAddressChangeCb(GnomeUtils::getEthIfname(), false, false); + NetworkManagerEvents::onAddressChangeCb(GnomeUtils::getEthIfname(), false, true); + break; + case NM_DEVICE_STATE_PREPARE: + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_UP, GnomeUtils::getEthIfname()); + break; + case NM_DEVICE_STATE_IP_CONFIG: + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP, GnomeUtils::getEthIfname()); + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_SECONDARIES: + case NM_DEVICE_STATE_ACTIVATED: + case NM_DEVICE_STATE_DEACTIVATING: + default: + NMLOG_WARNING("Unhandiled state change eth0"); + + if(doPostEthUpEvent && deviceState > NM_DEVICE_STATE_UNMANAGED) + { + doPostEthUpEvent = false; + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, GnomeUtils::getEthIfname()); + } + } + } + + } + + static void onConnectionSignalReceivedCB (GDBusProxy *proxy, gchar *senderName, gchar *signalName, + GVariant *parameters, gpointer userData) { + if (g_strcmp0(senderName, "NewConnection") == 0) { + NMLOG_INFO("new connection added success"); + NMLOG_DEBUG("Parameters: %s", g_variant_print(parameters, TRUE)); + } else if (g_strcmp0(signalName, "ConnectionRemoved") == 0) { + NMLOG_INFO("connection remove success"); + NMLOG_DEBUG("Parameters: %s", g_variant_print(parameters, TRUE)); + } + } + + static void ipV4addressChangeCb(GDBusProxy *proxy, GVariant *changedProps, GStrv invalidProps, gpointer userData) + { + if (changedProps == NULL || proxy == NULL) { + NMLOG_FATAL("cb doesn't have changed properties "); + return; + } + + GVariant *addressVariant = g_variant_lookup_value(changedProps, "Addresses", NULL); + if (addressVariant != NULL) + { + const char* iface = static_cast(userData); + if(iface != NULL ) + { + std::string ipAddr; uint32_t prifix; + if(GnomeUtils::getIPv4AddrFromIPv4ConfigProxy(proxy, ipAddr, prifix)) + NetworkManagerEvents::onAddressChangeCb(std::string(iface), true, false, ipAddr); + } + g_variant_unref(addressVariant); + } + } + + static void ipV6addressChangeCb(GDBusProxy *proxy, GVariant *changedProps, GStrv invalidProps, gpointer userData) + { + if (changedProps == NULL || proxy == NULL) { + NMLOG_FATAL("cb doesn't have changed properties "); + return; + } + + GVariant *addressVariant = g_variant_lookup_value(changedProps, "Addresses", NULL); + if (addressVariant != NULL) + { + const char* iface = static_cast(userData); + if(iface != NULL) + { + std::string ipAddr; uint32_t prifix; + if(GnomeUtils::getIPv6AddrFromIPv6ConfigProxy(proxy, ipAddr, prifix)) + NetworkManagerEvents::onAddressChangeCb(std::string(iface), true, true, ipAddr); + } + + g_variant_unref(addressVariant); + } + else + { + GVariantIter *propsIter= NULL; + const gchar *propertyName= NULL; + GVariant *propertyValue= NULL; + + // Iterate over all changed properties + g_variant_get(changedProps, "a{sv}", &propsIter); + while (g_variant_iter_loop(propsIter, "{&sv}", &propertyName, &propertyValue)) { + NMLOG_DEBUG("Other Property: %s", propertyName); + // if(propertyValue) + // g_variant_unref(changedProps); + } + g_variant_iter_free(propsIter); + } + } + + static void monitorDevice(const gchar *devicePath) + { + std::string ifname = getInterafaceNameFormDevicePath(devicePath); + gpointer userdata = NULL; + if(ifname.empty()) + { + NMLOG_WARNING("interface is missing for the device(%s)", devicePath); + return; + } + + if(ifname != GnomeUtils::getEthIfname() && ifname != GnomeUtils::getWifiIfname()) + { + NMLOG_DEBUG("interface is not eth0/wlan0: %s", ifname.c_str()); + return; + } + + GDBusProxy *deviceProxy =_NetworkManagerEvents->eventDbus.getNetworkManagerDeviceProxy(devicePath); + if(deviceProxy == nullptr) + return; + + g_signal_connect(deviceProxy, "g-signal", G_CALLBACK(deviceStateChangedCB), NULL); + NMLOG_DEBUG("Monitoring device: %s", devicePath); + if(ifname == GnomeUtils::getWifiIfname()) + { + _NetworkManagerEvents->nmEvents.wirelessDeviceProxy = deviceProxy; + _NetworkManagerEvents->nmEvents.wifiDevicePath = devicePath; + userdata = _NetworkManagerEvents->wlanIfname; // TODO change to GnomeUtils::getWifiIfname() + subscribeForlastScanPropertyEvent(devicePath); + } + else if(ifname == GnomeUtils::getEthIfname()) + { + _NetworkManagerEvents->nmEvents.wiredDeviceProxy = deviceProxy; + _NetworkManagerEvents->nmEvents.ethDevicePath = devicePath; + userdata = _NetworkManagerEvents->ethIfname; + } + + const gchar *ipv4ConfigPath = NULL; + const gchar *ipv6ConfigPath = NULL; + GVariant *ip4Config = g_dbus_proxy_get_cached_property(deviceProxy, "Ip4Config"); + if (ip4Config) + { + ipv4ConfigPath = g_variant_get_string(ip4Config, NULL); + NMLOG_DEBUG("Monitoring ip4_config_path: %s", ipv4ConfigPath); + } + + GVariant *ip6Config = g_dbus_proxy_get_cached_property(deviceProxy, "Ip6Config"); + if(ip6Config) + { + ipv6ConfigPath = g_variant_get_string(ip6Config, NULL); + NMLOG_DEBUG("Monitoring ip6_config_path: %s", ipv6ConfigPath); + } + + if(ipv4ConfigPath) + { + GDBusProxy *ipV4Proxy = _NetworkManagerEvents->eventDbus.getNetworkManagerIpv4Proxy(ipv4ConfigPath); + g_signal_connect(ipV4Proxy, "g-properties-changed", G_CALLBACK(ipV4addressChangeCb), userdata); + if(ifname == GnomeUtils::getEthIfname()) + _NetworkManagerEvents->nmEvents.ethIPv4Proxy = ipV4Proxy; + else if(ifname == GnomeUtils::getWifiIfname()) + _NetworkManagerEvents->nmEvents.wlanIPv4Proxy = ipV4Proxy; + } + + if(ipv6ConfigPath) + { + GDBusProxy *ipV6Proxy = _NetworkManagerEvents->eventDbus.getNetworkManagerIpv6Proxy(ipv6ConfigPath); + g_signal_connect(ipV6Proxy, "g-properties-changed", G_CALLBACK(ipV6addressChangeCb), userdata); + if(ifname == GnomeUtils::getEthIfname()) + _NetworkManagerEvents->nmEvents.ethIPv6Proxy = ipV6Proxy; + else if(ifname == GnomeUtils::getWifiIfname()) + _NetworkManagerEvents->nmEvents.wlanIPv6Proxy = ipV6Proxy; + } + + if(ip4Config) + g_variant_unref(ip4Config); + if(ip6Config) + g_variant_unref(ip6Config); + } + + void* NetworkManagerEvents::networkMangerEventMonitor(void *arg) + { + if(arg == NULL) + { + NMLOG_FATAL("function argument error: nm event monitor failed"); + return nullptr; + } + + NMEvents *nmEvents = static_cast(arg); + nmEvents->networkManagerProxy = _NetworkManagerEvents->eventDbus.getNetworkManagerProxy(); + if (nmEvents->networkManagerProxy == NULL) { + return nullptr; + } + + g_signal_connect(nmEvents->networkManagerProxy, "g-signal", G_CALLBACK(deviceAddRemoveCb), NULL); + g_signal_connect(nmEvents->networkManagerProxy, "g-properties-changed", G_CALLBACK(primaryConnectionChangedCB), NULL); + + GVariant *devices = g_dbus_proxy_get_cached_property(nmEvents->networkManagerProxy, "Devices"); + if (devices != NULL) { + GVariantIter iter; + gchar *devicePath = NULL; + + g_variant_iter_init(&iter, devices); + while (g_variant_iter_loop(&iter, "&o", &devicePath)) { + monitorDevice(devicePath); + } + + g_variant_unref(devices); + } + + nmEvents->settingsProxy = _NetworkManagerEvents->eventDbus.getNetworkManagerSettingsProxy(); + if (nmEvents->settingsProxy == NULL) + NMLOG_WARNING("Settings proxy failed no connection event registerd"); + else + g_signal_connect(nmEvents->settingsProxy, "g-signal", G_CALLBACK(onConnectionSignalReceivedCB), NULL); + + NMLOG_INFO("registered all networkmnager dbus events"); + g_main_loop_run(nmEvents->loop); + + if(nmEvents->wirelessDeviceProxy) + g_object_unref(nmEvents->wirelessDeviceProxy); + if(nmEvents->wirelessProxy) + g_object_unref(nmEvents->wirelessProxy); + if(nmEvents->wiredDeviceProxy) + g_object_unref(nmEvents->wiredDeviceProxy); + if(nmEvents->networkManagerProxy) + g_object_unref(nmEvents->networkManagerProxy); + if(nmEvents->settingsProxy) + g_object_unref(nmEvents->settingsProxy); + if(nmEvents->ethIPv4Proxy) + g_object_unref(nmEvents->ethIPv4Proxy); + if(nmEvents->ethIPv6Proxy) + g_object_unref(nmEvents->ethIPv6Proxy); + if(nmEvents->wlanIPv4Proxy) + g_object_unref(nmEvents->wlanIPv4Proxy); + if(nmEvents->wlanIPv6Proxy) + g_object_unref(nmEvents->wlanIPv6Proxy); + + NMLOG_WARNING("unregistered all event monitor"); + return nullptr; + } + + bool NetworkManagerEvents::startNetworkMangerEventMonitor() + { + NMLOG_DEBUG("starting gnome event monitor..."); + + if(!isEventThrdActive) { + isEventThrdActive = true; + eventThrdID = g_thread_new("nm_event_thrd", NetworkManagerEvents::networkMangerEventMonitor, &nmEvents); + } + return true; + } + + void NetworkManagerEvents::stopNetworkMangerEventMonitor() + { + + if (nmEvents.loop != NULL) { + g_main_loop_quit(nmEvents.loop); + } + if (eventThrdID) { + g_thread_join(eventThrdID); + eventThrdID = NULL; + NMLOG_WARNING("gnome event monitor stoped"); + } + isEventThrdActive = false; + } + + NetworkManagerEvents::~NetworkManagerEvents() + { + NMLOG_INFO("~NetworkManagerEvents"); + stopNetworkMangerEventMonitor(); + } + + NetworkManagerEvents* NetworkManagerEvents::getInstance() + { + static NetworkManagerEvents instance; + return &instance; + } + + NetworkManagerEvents::NetworkManagerEvents() + { + NMLOG_DEBUG("NetworkManagerEvents"); + nmEvents.loop = g_main_loop_new(NULL, FALSE); + if(nmEvents.loop == NULL) { + NMLOG_FATAL("GMain loop failed Fatal Error: Event will not work"); + return; + } + strncpy(wlanIfname, GnomeUtils::getWifiIfname(), sizeof(wlanIfname)); + strncpy(ethIfname, GnomeUtils::getEthIfname(), sizeof(ethIfname)); + _NetworkManagerEvents = this; + startNetworkMangerEventMonitor(); + } + + /* Gnome networkmanger events call backs */ + void NetworkManagerEvents::onActiveInterfaceChangeCb(std::string newIface) + { + static std::string oldIface = "Unknown"; + if(oldIface != newIface) + { + NMLOG_INFO("old interface - %s new interface - %s", oldIface.c_str(), newIface.c_str()); + oldIface = newIface; + if(_instance != nullptr) + _instance->ReportActiveInterfaceChange(oldIface, newIface); + } + } + + void NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::InterfaceState newState, std::string iface) + { + std::string state; + switch (newState) + { + case Exchange::INetworkManager::INTERFACE_ADDED: + state = "INTERFACE_ADDED"; + break; + case Exchange::INetworkManager::INTERFACE_LINK_UP: + state = "INTERFACE_LINK_UP"; + break; + case Exchange::INetworkManager::INTERFACE_LINK_DOWN: + state = "INTERFACE_LINK_DOWN"; + break; + case Exchange::INetworkManager::INTERFACE_ACQUIRING_IP: + state = "INTERFACE_ACQUIRING_IP"; + break; + case Exchange::INetworkManager::INTERFACE_REMOVED: + state = "INTERFACE_REMOVED"; + break; + case Exchange::INetworkManager::INTERFACE_DISABLED: + state = "INTERFACE_DISABLED"; + break; + default: + state = "Unknown"; + } + + NMLOG_DEBUG("%s interface state changed - %s", iface.c_str(), state.c_str()); + if(_instance != nullptr && (iface == GnomeUtils::getWifiIfname() || iface == GnomeUtils::getEthIfname())) + _instance->ReportInterfaceStateChange(static_cast(newState), iface); + } + + void NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WiFiState state, std::string& wifiStateStr) + { + NMLOG_DEBUG("wifi state changed: %d ; NM wifi: %s", state, wifiStateStr.c_str()); + if(_instance != nullptr) + _instance->ReportWiFiStateChange(static_cast(state)); + } + + void NetworkManagerEvents::onAddressChangeCb(std::string iface, bool acquired, bool isIPv6, std::string ipAddress) + { + static std::map ipv6Map; + static std::map ipv4Map; + + if (isIPv6) + { + if (acquired == false) { // ip lost event + if(ipv6Map.size() < 1) + { + return; // no ipv6 added yet no event posting + } + ipAddress = ipv6Map[iface]; + ipv6Map[iface].clear(); + } + else // acquired + { + if (ipAddress.compare(0, 5, "fe80:") == 0 || + ipAddress.compare(0, 6, "fe80::") == 0) { + NMLOG_DEBUG("It's link-local ip"); + return; // It's link-local + } + /* same ip comes multiple time so avoding that */ + if (ipv6Map[iface].find(ipAddress) == std::string::npos && !ipAddress.empty()) { + ipv6Map[iface] = ipAddress; // SLAAC protocol may include multip ipv6 address last one will save + } + else + return; // skip same ip event posting if empty request + } + } + else + { + if (acquired == false) { // ip lost event + if(ipv4Map.size() < 1) + { + return; // no ipv4 added yet no event posting + } + ipAddress = ipv4Map[iface]; + ipv4Map[iface].clear(); + } + else + { + if(!ipAddress.empty()) + ipv4Map[iface] = ipAddress; + else + return; + } + } + + Exchange::INetworkManager::IPStatus ipStatus{}; + if(acquired) + ipStatus = Exchange::INetworkManager::IP_ACQUIRED; + + if(_instance != nullptr) + _instance->ReportIPAddressChange(iface, isIPv6?"IPv6":"IPv4", ipAddress, ipStatus); + + NMLOG_INFO("iface:%s - ipaddress:%s - %s - %s", iface.c_str(), ipAddress.c_str(), acquired?"acquired":"lost", isIPv6?"isIPv6":"isIPv4"); + } + + void NetworkManagerEvents::onAvailableSSIDsCb(const char* wifiDevicePath) + { + GDBusProxy* wProxy = nullptr; + GError* error = nullptr; + + NMLOG_DEBUG("wifi scanning completed ..."); + if(_NetworkManagerEvents->doScanNotify == false) { + return; + } + + _NetworkManagerEvents->doScanNotify = false; + wProxy = _NetworkManagerEvents->eventDbus.getNetworkManagerWirelessProxy(wifiDevicePath); + if(wProxy == NULL) + return; + + GVariant* result = g_dbus_proxy_call_sync(wProxy, "GetAllAccessPoints", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + NMLOG_ERROR("Error creating proxy: %s", error->message); + g_error_free(error); + g_object_unref(wProxy); + return; + } + + GVariantIter* iter = NULL; + const gchar* apPath = NULL; + JsonArray ssidList = JsonArray(); + bool oneSSIDFound = false; + + g_variant_get(result, "(ao)", &iter); + if(iter == NULL) + return; + while (g_variant_iter_loop(iter, "o", &apPath)) { + Exchange::INetworkManager::WiFiSSIDInfo wifiInfo; + // NMLOG_DEBUG("Access Point Path: %s", apPath); + if(apPath != NULL && GnomeUtils::getApDetails(_NetworkManagerEvents->eventDbus, apPath, wifiInfo)) + { + JsonObject ssidObj; + if(GnomeUtils::convertSsidInfoToJsonObject(wifiInfo, ssidObj)) + { + ssidList.Add(ssidObj); + oneSSIDFound = true; + } + } + } + + if(oneSSIDFound) { + std::string ssids{}; + ssidList.ToString(ssids); + if(_instance != nullptr) + _instance->ReportAvailableSSIDs(ssidList); + NMLOG_DEBUG("scanned ssids: %s", ssids.c_str()); + } + + g_variant_iter_free(iter); + g_variant_unref(result); + g_object_unref(wProxy); + } + + void NetworkManagerEvents::setwifiScanOptions(bool doNotify) + { + doScanNotify.store(doNotify); + if(!doScanNotify) + NMLOG_DEBUG("stoped periodic wifi scan result notify"); + } + + } // Plugin +} // WPEFramework diff --git a/gdbus/NetworkManagerGdbusEvent.h b/gdbus/NetworkManagerGdbusEvent.h new file mode 100644 index 000000000..69b1f0f4b --- /dev/null +++ b/gdbus/NetworkManagerGdbusEvent.h @@ -0,0 +1,84 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include +#include +#include +#include + +#include "NetworkManagerGdbusMgr.h" +#include "INetworkManager.h" + +namespace WPEFramework +{ + namespace Plugin + { + + typedef struct {; + + GDBusProxy *wiredDeviceProxy; // eth0 dev + GDBusProxy *wirelessDeviceProxy; // wlan0 dev + GDBusProxy *wirelessProxy; // wireless interface + GDBusProxy *networkManagerProxy; // networkmanager main bus + GDBusProxy *settingsProxy; // settings + + GDBusProxy *ethIPv4Proxy; + GDBusProxy *ethIPv6Proxy; + GDBusProxy *wlanIPv4Proxy; + GDBusProxy *wlanIPv6Proxy; + + std::string wifiDevicePath; + std::string ethDevicePath; + + GMainLoop *loop; + } NMEvents; + + class NetworkManagerEvents + { + + public: + static void onInterfaceStateChangeCb(Exchange::INetworkManager::InterfaceState newState, std::string iface); // ReportInterfaceStateChangedEvent + static void onAddressChangeCb(std::string iface, bool acquired, bool isIPv6, std::string ipAddress = ""); // ReportIPAddressChangedEvent + static void onActiveInterfaceChangeCb(std::string newInterface); // ReportActiveInterfaceChangedEvent + static void onAvailableSSIDsCb(const char* wifiDevicePath); // ReportAvailableSSIDsEvent + static void onWIFIStateChanged(Exchange::INetworkManager::WiFiState state, std::string& wifiStateStr); // ReportWiFiStateChangedEvent + + public: + static NetworkManagerEvents* getInstance(); + bool startNetworkMangerEventMonitor(); + void stopNetworkMangerEventMonitor(); + void setwifiScanOptions(bool doNotify); + + private: + static void* networkMangerEventMonitor(void *arg); + NetworkManagerEvents(); + ~NetworkManagerEvents(); + std::atomicisEventThrdActive = {false}; + std::atomicdoScanNotify = {true}; + GThread *eventThrdID; + public: + NMEvents nmEvents{}; + DbusMgr eventDbus; + char wlanIfname[16]; + char ethIfname[16]; + }; + + } // Plugin +} // WPEFramework diff --git a/gdbus/NetworkManagerGdbusMgr.cpp b/gdbus/NetworkManagerGdbusMgr.cpp new file mode 100644 index 000000000..4b0f608cc --- /dev/null +++ b/gdbus/NetworkManagerGdbusMgr.cpp @@ -0,0 +1,262 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2022 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include +#include +#include + +#include "NetworkManagerGdbusMgr.h" +#include "NetworkManagerLogger.h" + +namespace WPEFramework +{ + namespace Plugin + { + + DbusMgr::DbusMgr() : connection(NULL) + { + GError* error = NULL; + NMLOG_INFO("DbusMgr"); + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!connection) { + NMLOG_FATAL("Error connecting to system D-Bus bus: %s ", error->message); + g_error_free(error); + } + flags = static_cast(G_DBUS_PROXY_FLAGS_NONE); + } + + DbusMgr::~DbusMgr() { + NMLOG_INFO("~DbusMgr"); + if (connection) { + g_object_unref(connection); + connection = NULL; + } + } + + GDBusConnection* DbusMgr::getConnection() + { + if (connection) { + return connection; + } + + GError* error = NULL; + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!connection && error) { + NMLOG_FATAL("Error reconnecting to system bus: %s ", error->message); + g_error_free(error); + return NULL; + } + + flags = static_cast(G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START); + return connection; + } + + GDBusProxy* DbusMgr::getNetworkManagerProxy() + { + GError* error = NULL; + nmProxy = NULL; + nmProxy = g_dbus_proxy_new_sync( + getConnection(), G_DBUS_PROXY_FLAGS_NONE, NULL, "org.freedesktop.NetworkManager", + "/org/freedesktop/NetworkManager", + "org.freedesktop.NetworkManager", + NULL, + &error + ); + + if (nmProxy == NULL || error != NULL) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating D-Bus proxy: %s", error->message); + g_error_free(error); + return NULL; + } + + return nmProxy; + } + + GDBusProxy* DbusMgr::getNetworkManagerSettingsProxy() + { + GError* error = NULL; + GDBusProxy* proxy = g_dbus_proxy_new_sync( + getConnection(), flags, NULL, "org.freedesktop.NetworkManager", + "/org/freedesktop/NetworkManager/Settings", + "org.freedesktop.NetworkManager.Settings", + NULL, + &error + ); + + if (error != NULL) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating proxy: %s", error->message); + g_clear_error(&error); + return NULL; + } + + return proxy; + } + + GDBusProxy* DbusMgr::getNetworkManagerSettingsConnectionProxy(const char* connPath) + { + GError* error = NULL; + GDBusProxy* proxy = g_dbus_proxy_new_sync( + getConnection(), flags, NULL, "org.freedesktop.NetworkManager", + connPath, + "org.freedesktop.NetworkManager.Settings.Connection", + NULL, + &error + ); + + if (error != NULL) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating proxy: %s", error->message); + g_clear_error(&error); + return NULL; + } + + return proxy; + } + + GDBusProxy* DbusMgr::getNetworkManagerDeviceProxy(const char* devicePath) + { + GError* error = NULL; + GDBusProxy* proxy = g_dbus_proxy_new_sync( + getConnection(), flags, NULL, "org.freedesktop.NetworkManager", + devicePath, + "org.freedesktop.NetworkManager.Device", + NULL, + &error + ); + + if (error != NULL) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating proxy: %s", error->message); + g_clear_error(&error); + return NULL; + } + + return proxy; + } + + GDBusProxy* DbusMgr::getNetworkManagerActiveConnProxy(const char* activePath) + { + GError* error = NULL; + GDBusProxy* proxy = g_dbus_proxy_new_sync( + getConnection(), flags, NULL, "org.freedesktop.NetworkManager", + activePath, + "org.freedesktop.NetworkManager.Connection.Active", + NULL, + &error + ); + + if (error != NULL) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating proxy: %s", error->message); + g_clear_error(&error); + return NULL; + } + + return proxy; + } + + GDBusProxy* DbusMgr::getNetworkManagerAccessPointProxy(const char* apPath) + { + GError* error = NULL; + GDBusProxy* proxy = g_dbus_proxy_new_sync( + getConnection(), flags, NULL, "org.freedesktop.NetworkManager", + apPath, + "org.freedesktop.NetworkManager.AccessPoint", + NULL, + &error + ); + + if (error != NULL) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating proxy: %s", error->message); + g_clear_error(&error); + return NULL; + } + + return proxy; + } + + GDBusProxy* DbusMgr::getNetworkManagerWirelessProxy(const char* wirelessDevPath) + { + GError* error = NULL; + GDBusProxy* proxy = g_dbus_proxy_new_sync( + getConnection(), flags, NULL, "org.freedesktop.NetworkManager", + wirelessDevPath, + "org.freedesktop.NetworkManager.Device.Wireless", + NULL, + &error + ); + + if (error != NULL) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating proxy: %s", error->message); + g_clear_error(&error); + return NULL; + } + + return proxy; + } + + GDBusProxy* DbusMgr::getNetworkManagerIpv4Proxy(const char* ipConfigPath) + { + GError* error = NULL; + GDBusProxy* proxy = g_dbus_proxy_new_sync( + getConnection(), flags, NULL, "org.freedesktop.NetworkManager", + ipConfigPath, + "org.freedesktop.NetworkManager.IP4Config", + NULL, + &error + ); + + if (error != NULL) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating proxy: %s", error->message); + g_clear_error(&error); + return NULL; + } + + return proxy; + } + + GDBusProxy* DbusMgr::getNetworkManagerIpv6Proxy(const char* ipConfigPath) + { + GError* error = NULL; + GDBusProxy* proxy = g_dbus_proxy_new_sync( + getConnection(), flags, NULL, "org.freedesktop.NetworkManager", + ipConfigPath, + "org.freedesktop.NetworkManager.IP6Config", + NULL, + &error + ); + + if (error != NULL) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating proxy: %s", error->message); + g_clear_error(&error); + return NULL; + } + + return proxy; + } + + } // Plugin +} // WPEFramework + diff --git a/gdbus/NetworkManagerGdbusMgr.h b/gdbus/NetworkManagerGdbusMgr.h new file mode 100644 index 000000000..c75915fa0 --- /dev/null +++ b/gdbus/NetworkManagerGdbusMgr.h @@ -0,0 +1,56 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include +#include +#include +#include + +/* include NetworkManager.h for the defines, but we don't link against libnm. */ +#include + +namespace WPEFramework +{ + namespace Plugin + { + class DbusMgr { + public: + DbusMgr(); + ~DbusMgr(); + + GDBusProxy* getNetworkManagerProxy(); + GDBusProxy* getNetworkManagerSettingsProxy(); + GDBusProxy* getNetworkManagerSettingsConnectionProxy(const char* connPath); + GDBusProxy* getNetworkManagerDeviceProxy(const char* devicePath); + GDBusProxy* getNetworkManagerWirelessProxy(const char* wirelessDevPath); + GDBusProxy* getNetworkManagerIpv4Proxy(const char* ipConfigPath); + GDBusProxy* getNetworkManagerIpv6Proxy(const char* ipConfigPath); + GDBusProxy* getNetworkManagerActiveConnProxy(const char* activePath); + GDBusProxy* getNetworkManagerAccessPointProxy(const char* apPath); + GDBusConnection* getConnection(); + + private: + GDBusConnection* connection; + GDBusProxyFlags flags; + GDBusProxy *nmProxy = NULL; + }; + + } +} \ No newline at end of file diff --git a/gdbus/NetworkManagerGdbusProxy.cpp b/gdbus/NetworkManagerGdbusProxy.cpp new file mode 100644 index 000000000..2067d4bd2 --- /dev/null +++ b/gdbus/NetworkManagerGdbusProxy.cpp @@ -0,0 +1,197 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2022 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include "NetworkManagerImplementation.h" +#include "NetworkManagerGdbusClient.h" +#include "NetworkManagerGdbusEvent.h" + +using namespace WPEFramework; +using namespace WPEFramework::Plugin; +using namespace std; + +namespace WPEFramework +{ + namespace Plugin + { + NetworkManagerImplementation* _instance = nullptr; + NetworkManagerClient* _nmGdbusClient = nullptr; + NetworkManagerEvents* _nmGdbusEvents = nullptr; + void NetworkManagerInternalEventHandler(const char *owner, int eventId, void *data, size_t len) + { + return; + } + + void NetworkManagerImplementation::platform_init() + { + ::_instance = this; + _nmGdbusClient = NetworkManagerClient::getInstance(); + _nmGdbusEvents = NetworkManagerEvents::getInstance(); + } + + uint32_t NetworkManagerImplementation::GetAvailableInterfaces (Exchange::INetworkManager::IInterfaceDetailsIterator*& interfacesItr/* @out */) + { + return Core::ERROR_NONE; + } + + uint32_t NetworkManagerImplementation::GetPrimaryInterface (string& interface /* @out */) + { + return Core::ERROR_NONE; + } + + uint32_t NetworkManagerImplementation::SetPrimaryInterface (const string& interface/* @in */) + { + return Core::ERROR_NONE; + } + uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) + { + return Core::ERROR_NONE; + } + + uint32_t NetworkManagerImplementation::GetInterfaceState(const string& interface/* @in */, bool& isEnabled /* @out */) + { + return Core::ERROR_NONE; + } + + /* @brief Get IP Address Of the Interface */ + uint32_t NetworkManagerImplementation::GetIPSettings(string& interface /* @inout */, const string &ipversion /* @in */, IPAddress& result /* @out */) + { + return Core::ERROR_NONE; + } + + /* @brief Set IP Address Of the Interface */ + uint32_t NetworkManagerImplementation::SetIPSettings(const string& interface /* @in */, const IPAddress& address /* @in */) + { + return Core::ERROR_NONE; + } + + uint32_t NetworkManagerImplementation::StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) + { + uint32_t rc = Core::ERROR_GENERAL; + _nmGdbusEvents->setwifiScanOptions(true); /* Enable event posting */ + if(_nmGdbusClient->startWifiScan()) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("StartWiFiScan failed"); + return rc; + } + + uint32_t NetworkManagerImplementation::StopWiFiScan(void) + { + uint32_t rc = Core::ERROR_GENERAL; + _nmGdbusEvents->setwifiScanOptions(false); /* disable event posting */ + rc = Core::ERROR_NONE; + return rc; + } + + uint32_t NetworkManagerImplementation::GetKnownSSIDs(IStringIterator*& ssids /* @out */) + { + uint32_t rc = Core::ERROR_GENERAL; + std::list ssidList; + if(_nmGdbusClient->getKnownSSIDs(ssidList) && !ssidList.empty()) + { + ssids = Core::Service::Create(ssidList); + rc = Core::ERROR_NONE; + } + else + NMLOG_ERROR("GetKnownSSIDs failed"); + + return rc; + } + + uint32_t NetworkManagerImplementation::AddToKnownSSIDs(const WiFiConnectTo& ssid /* @in */) + { + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->addToKnownSSIDs(ssid)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("addToKnownSSIDs failed"); + return rc; + } + + uint32_t NetworkManagerImplementation::RemoveKnownSSID(const string& ssid /* @in */) + { + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->removeKnownSSIDs(ssid)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("RemoveKnownSSID failed"); + return rc; + } + + uint32_t NetworkManagerImplementation::WiFiConnect(const WiFiConnectTo& ssid /* @in */) + { + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->wifiConnect(ssid)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("WiFiConnect failed"); + return rc; + } + + uint32_t NetworkManagerImplementation::WiFiDisconnect(void) + { + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->wifiDisconnect()) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("WiFiDisconnect failed"); + return rc; + } + + uint32_t NetworkManagerImplementation::GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) + { + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->getConnectedSSID(ssidInfo)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("getConnectedSSID failed"); + return rc; + } + + uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& signalStrength /* @out */, WiFiSignalQuality& quality /* @out */) + { + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->getWiFiSignalStrength(ssid, signalStrength, quality)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("GetWiFiSignalStrength failed"); + return rc; + } + + uint32_t NetworkManagerImplementation::GetWifiState(WiFiState &state) + { + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->getWifiState(state)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("GetWifiState failed"); + return rc; + } + + uint32_t NetworkManagerImplementation::StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) + { + return Core::ERROR_NONE; + } + + uint32_t NetworkManagerImplementation::StopWPS(void) + { + return Core::ERROR_NONE; + } + } +} \ No newline at end of file diff --git a/gdbus/NetworkManagerGdbusUtils.cpp b/gdbus/NetworkManagerGdbusUtils.cpp new file mode 100644 index 000000000..260d59df7 --- /dev/null +++ b/gdbus/NetworkManagerGdbusUtils.cpp @@ -0,0 +1,551 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2022 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include +#include +#include +#include + +#include "NetworkManagerLogger.h" +#include "NetworkManagerGdbusUtils.h" +#include "NetworkManagerGdbusMgr.h" +#include + +namespace WPEFramework +{ + namespace Plugin + { + static const char* ifnameEth = "eth0"; + static const char* ifnameWlan = "wlan0"; + + bool GnomeUtils::getIPv4AddrFromIPv4ConfigProxy(GDBusProxy *ipProxy, std::string& ipAddr, uint32_t& prefix) + { + GVariantIter *iter; + GVariantIter *dictIter; + const gchar *key; + GVariant *value; + gchar *address = nullptr; + bool ret = false; + + if(ipProxy == nullptr) + { + NMLOG_ERROR("ipv4 ipProxy is null"); + return false; + } + + GVariant *addressDataVariant = g_dbus_proxy_get_cached_property(ipProxy, "AddressData"); + if (addressDataVariant != NULL) { + g_variant_get(addressDataVariant, "aa{sv}", &iter); + while (g_variant_iter_loop(iter, "a{sv}", &dictIter)) { + while (g_variant_iter_loop(dictIter, "{&sv}", &key, &value)) { + if (g_strcmp0(key, "address") == 0) { + address = g_variant_dup_string(value, NULL); + if(address!= NULL) + { + ipAddr = address; // strlen of "255.255.255.255" + NMLOG_DEBUG("Address: %s", ipAddr.c_str()); + ret = true; + } + else + ret = false; + g_free(address); + } else if (g_strcmp0(key, "prefix") == 0) { + prefix = g_variant_get_uint32(value); + NMLOG_DEBUG("Prefix: %u", prefix); + } + } + } + g_variant_iter_free(iter); + g_variant_unref(addressDataVariant); + } + return ret; + } + + bool GnomeUtils::getIPv6AddrFromIPv6ConfigProxy( GDBusProxy *ipProxy, std::string& ipAddr, uint32_t& prefix) + { + GVariantIter *iter = NULL; + GVariantIter *dictIter = NULL; + const gchar *key = NULL; + GVariant *value = NULL; + gchar *address = NULL; + std::string ipAddress{}; + if(ipProxy == NULL) + { + NMLOG_ERROR("ipv6 ipProxy is null"); + return false; + } + + GVariant *addressDataVariant = g_dbus_proxy_get_cached_property(ipProxy, "AddressData"); + if (addressDataVariant != NULL) { + g_variant_get(addressDataVariant, "aa{sv}", &iter); + while (g_variant_iter_loop(iter, "a{sv}", &dictIter)) { + while (g_variant_iter_loop(dictIter, "{&sv}", &key, &value)) + { + if (g_strcmp0(key, "address") == 0) + { + address = g_variant_dup_string(value, NULL); + if(address!= NULL) + { + ipAddress = address; // strlen of "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF" + if (ipAddress.compare(0, 5, "fe80:") == 0 || + ipAddress.compare(0, 6, "fe80::") == 0) { // It's link-local starts with fe80 + NMLOG_DEBUG("link-local ip: %s", address); + } + else + { + // TODO use ip list multiple ipv6 SLACC adress may occure + ipAddr = ipAddress; + NMLOG_DEBUG("ipv6 addr: %s", ipAddress.c_str()); + } + } + g_free(address); + } + else if (g_strcmp0(key, "prefix") == 0) + { + prefix = g_variant_get_uint32(value); + NMLOG_DEBUG("Prefix: %u", prefix); + } + } + } + g_variant_iter_free(iter); + g_variant_unref(addressDataVariant); + } + + if(ipAddr.empty()) + return false; + return true; + } + + bool GnomeUtils::convertSsidInfoToJsonObject(Exchange::INetworkManager::WiFiSSIDInfo& wifiInfo, JsonObject& ssidObj) + { + std::string freq{}; + + ssidObj["ssid"] = wifiInfo.ssid; + ssidObj["security"] = static_cast(wifiInfo.security); + ssidObj["strength"] = wifiInfo.strength; + ssidObj["frequency"] = wifiInfo.frequency; + return true; + } + + // TODO change this function + const char* GnomeUtils::getWifiIfname() { return ifnameWlan; } + const char* GnomeUtils::getEthIfname() { return ifnameEth; } + + uint8_t GnomeUtils::wifiSecurityModeFromApFlags(guint32 flags, guint32 wpaFlags, guint32 rsnFlags) + { + uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; + if ((flags == NM_802_11_AP_FLAGS_NONE) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) + { + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE; + } + else if( (flags & NM_802_11_AP_FLAGS_PRIVACY) && ((wpaFlags & NM_802_11_AP_SEC_PAIR_WEP40) || (rsnFlags & NM_802_11_AP_SEC_PAIR_WEP40)) ) + { + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_64; + } + else if( (flags & NM_802_11_AP_FLAGS_PRIVACY) && ((wpaFlags & NM_802_11_AP_SEC_PAIR_WEP104) || (rsnFlags & NM_802_11_AP_SEC_PAIR_WEP104)) ) + { + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_128; + } + else if((wpaFlags & NM_802_11_AP_SEC_PAIR_TKIP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_TKIP)) + { + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_TKIP; + } + else if((wpaFlags & NM_802_11_AP_SEC_PAIR_CCMP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_CCMP)) + { + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES; + } + else if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) && (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + { + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_ENTERPRISE; + } + else if(rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) + { + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK; + } + else if((wpaFlags & NM_802_11_AP_SEC_GROUP_CCMP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_CCMP)) + { + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES; + } + else if((wpaFlags & NM_802_11_AP_SEC_GROUP_TKIP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_TKIP)) + { + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_TKIP; + } + else if((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE) || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) + { + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE; + } + else + NMLOG_WARNING("security mode not defined (flag: %d, wpaFlags: %d, rsnFlags: %d)", flags, wpaFlags, rsnFlags); + return security; + } + + bool GnomeUtils::getCachedPropertyU(GDBusProxy* proxy, const char* propertiy, uint32_t *value) + { + GVariant* result = NULL; + result = g_dbus_proxy_get_cached_property(proxy, propertiy); + if (result == NULL) { + NMLOG_ERROR("Failed to get '%s' properties", propertiy); + return false; + } + + if (g_variant_is_of_type (result, G_VARIANT_TYPE_UINT32)) { + *value = g_variant_get_uint32(result); + //NMLOG_DEBUG("%s: %d", propertiy, *value); + } + else + NMLOG_WARNING("Unexpected type returned property: %s", g_variant_get_type_string(result)); + g_variant_unref(result); + return true; + } + + bool GnomeUtils::getDevicePropertiesByPath(DbusMgr& m_dbus, const char* devicePath, deviceInfo& properties) + { + GVariant *devicesVar = NULL; + GDBusProxy* nmProxy = NULL; + u_int32_t value; + + nmProxy = m_dbus.getNetworkManagerDeviceProxy(devicePath); + if(nmProxy == NULL) + return false; + + if(GnomeUtils::getCachedPropertyU(nmProxy, "DeviceType", &value)) + properties.deviceType = static_cast(value); + else + NMLOG_ERROR("'DeviceType' property failed"); + + devicesVar = g_dbus_proxy_get_cached_property(nmProxy, "Interface"); + if (devicesVar) { + const gchar *iface = g_variant_get_string(devicesVar, NULL); + if(iface != NULL) + { + properties.interface = iface; + } + //NMLOG_DEBUG("Interface: %s", iface); + g_variant_unref(devicesVar); + } + else + NMLOG_ERROR("'Interface' property failed"); + + guint32 devState, stateReason; + devicesVar = g_dbus_proxy_get_cached_property(nmProxy, "StateReason"); + if (devicesVar) { + g_variant_get(devicesVar, "(uu)", &devState, &stateReason); + properties.state = static_cast(devState); + properties.stateReason = static_cast(stateReason); + g_variant_unref(devicesVar); + } + else + NMLOG_ERROR("'StateReason' property failed"); + + g_object_unref(nmProxy); + return true; + } + + bool GnomeUtils::getDeviceInfoByIfname(DbusMgr& m_dbus, const char* ifaceName, deviceInfo& properties) + { + GError *error = NULL; + GVariant *devicesVar = NULL; + bool ret = false; + + GDBusProxy* nmProxy = m_dbus.getNetworkManagerProxy(); + if(nmProxy == NULL) + return false; + + devicesVar = g_dbus_proxy_call_sync(nmProxy, "GetDevices", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + NMLOG_ERROR("Error calling GetDevices method: %s", error->message); + g_error_free(error); + g_object_unref(nmProxy); + return false; + } + + GVariantIter* iter = NULL; + gchar* devicePath = NULL; + g_variant_get(devicesVar, "(ao)", &iter); + while (iter != NULL && g_variant_iter_loop(iter, "o", &devicePath)) + { + if(devicePath == NULL ) + continue; + + if(getDevicePropertiesByPath(m_dbus, devicePath, properties) && properties.interface == ifaceName) + { + properties.path = devicePath; + g_free(devicePath); + ret = true; + break; + } + } + + g_variant_iter_free(iter); + if(!ret) + NMLOG_ERROR("'%s' interface not found", ifaceName); + if(devicesVar) + g_variant_unref(devicesVar); + if(nmProxy) + g_object_unref(nmProxy); + return ret; + } + + bool GnomeUtils::getDeviceByIpIface(DbusMgr& m_dbus, const gchar *iface_name, std::string& path) + { + // TODO Fix Error calling method: + // GDBus.Error:org.freedesktop.NetworkManager.UnknownDevice: No device found for the requested iface + // in wsl linux + GError *error = NULL; + GVariant *result; + gchar *device_path = NULL; + bool ret = false; + + result = g_dbus_connection_call_sync( + m_dbus.getConnection(), + "org.freedesktop.NetworkManager", // D-Bus name + "/org/freedesktop/NetworkManager", // Object path + "org.freedesktop.NetworkManager", // Interface + "GetDeviceByIpIface", // Method name + g_variant_new("(s)", iface_name), // Input parameter (the interface name) + G_VARIANT_TYPE("(o)"), // Expected return type (object path) + G_DBUS_CALL_FLAGS_NONE, + -1, // Default timeout + NULL, + &error + ); + + if (error != NULL) { + NMLOG_ERROR("calling GetDeviceByIpIface: %s", error->message); + g_error_free(error); + return ret; + } + + if (g_variant_is_of_type (result, (const GVariantType *) "(o)")) + { + g_variant_get(result, "(o)", &device_path); + if(device_path != NULL) + { + path = std::string(device_path); + ret = true; + g_free(device_path); + } + } + //NMLOG_DEBUG("%s device path %s", iface_name, path.c_str()); + g_variant_unref(result); + return ret; + } + + bool GnomeUtils::getApDetails(DbusMgr& m_dbus, const char* apPath, Exchange::INetworkManager::WiFiSSIDInfo& wifiInfo) + { + guint32 flags= 0, wpaFlags= 0, rsnFlags= 0, freq= 0, bitrate= 0; + uint8_t strength = 0; + NM80211Mode mode = NM_802_11_MODE_UNKNOWN; + bool ret = false; + GVariant* ssidVariant = NULL; + + GDBusProxy* proxy = m_dbus.getNetworkManagerAccessPointProxy(apPath); + if (proxy == NULL) { + return false; + } + + gsize ssid_length = 0; + ssidVariant = g_dbus_proxy_get_cached_property(proxy,"Ssid"); + if (!ssidVariant) { + NMLOG_ERROR("Failed to get AP properties."); + g_object_unref(proxy); + return false; + } + + const guchar *ssid_data = static_cast(g_variant_get_fixed_array(ssidVariant, &ssid_length, sizeof(guchar))); + if (ssid_data && ssid_length > 0 && ssid_length <= 32) + { + GVariant* result = NULL; + gchar *_bssid = NULL; + wifiInfo.ssid.assign(reinterpret_cast(ssid_data), ssid_length); + result = g_dbus_proxy_get_cached_property(proxy,"HwAddress"); + if (!result) { + NMLOG_ERROR("Failed to get AP properties."); + g_object_unref(proxy); + return false; + } + g_variant_get(result, "s", &_bssid); + if(_bssid != NULL) { + wifiInfo.bssid = _bssid; + g_free(_bssid); + } + g_variant_unref(result); + result = NULL; + result = g_dbus_proxy_get_cached_property(proxy,"Strength"); + if (!result) { + NMLOG_ERROR("Failed to get AP properties."); + g_object_unref(proxy); + return false; + } + g_variant_get(result, "y", &strength); + wifiInfo.strength = GnomeUtils::convertPercentageToSignalStrengtStr((int)strength); + g_variant_unref(result); + + GnomeUtils::getCachedPropertyU(proxy, "Flags", &flags); + GnomeUtils::getCachedPropertyU(proxy, "WpaFlags", &wpaFlags); + GnomeUtils::getCachedPropertyU(proxy, "RsnFlags", &rsnFlags); + GnomeUtils::getCachedPropertyU(proxy, "Mode", (guint32*)&mode); + GnomeUtils::getCachedPropertyU(proxy, "Frequency", &freq); + GnomeUtils::getCachedPropertyU(proxy, "MaxBitrate", &bitrate); + + wifiInfo.frequency = std::to_string((double)freq/1000); + wifiInfo.rate = std::to_string(bitrate); + wifiInfo.security = static_cast(wifiSecurityModeFromApFlags(flags, wpaFlags, rsnFlags)); + + // NMLOG_DEBUG("SSID: %s", wifiInfo.m_ssid.c_str()); + // NMLOG_DEBUG("bssid %s", wifiInfo.m_bssid.c_str()); + // NMLOG_DEBUG("strength : %s dbm (%d%%)", wifiInfo.m_signalStrength.c_str(), strength); + // NMLOG_DEBUG("frequency : %f MHz", wifiInfo.m_frequency); + // NMLOG_DEBUG("bitrate : %s kbit/s", wifiInfo.m_rate.c_str()); + // NMLOG_DEBUG("securityMode : %d", wifiInfo.m_securityMode); + + // TODO add noice + ret = true; + } + else { + // NMLOG_DEBUG("Invalid/hidden SSID: %zu (maximum is 32)", ssid_length); + ret = false; + } + + if(ssidVariant) + g_variant_unref(ssidVariant); + if(proxy) + g_object_unref(proxy); + + return ret; + } + + // Function to convert percentage (0-100) to dBm string + const char* GnomeUtils::convertPercentageToSignalStrengtStr(int percentage) { + + if (percentage <= 0 || percentage > 100) { + return ""; + } + + /* + * -30 dBm to -50 dBm: Excellent signal strength. + * -50 dBm to -60 dBm: Very good signal strength. + * -60 dBm to -70 dBm: Good signal strength; acceptable for basic internet browsing. + * -70 dBm to -80 dBm: Weak signal; performance may degrade, slower speeds, and possible dropouts. + * -80 dBm to -90 dBm: Very poor signal; likely unusable or highly unreliable. + * Below -90 dBm: Disconnected or too weak to establish a stable connection. + */ + + // dBm range: -30 dBm (strong) to -90 dBm (weak) + const int max_dBm = -30; + const int min_dBm = -90; + int dBm_value = max_dBm + ((min_dBm - max_dBm) * (100 - percentage)) / 100; + static char result[8]={0}; + snprintf(result, sizeof(result), "%d", dBm_value); + return result; + } + + bool GnomeUtils::getWifiConnectionPaths(DbusMgr& m_dbus, const char* devicePath, std::list& paths) + { + GDBusProxy* nmProxy = NULL; + GVariant* result = NULL; + bool ret = false; + nmProxy = m_dbus.getNetworkManagerDeviceProxy(devicePath); + if(nmProxy == NULL) + return false; + + result = g_dbus_proxy_get_cached_property(nmProxy, "AvailableConnections"); + if (!result) { + NMLOG_ERROR("Failed to get AvailableConnections property."); + g_object_unref(nmProxy); + return ret; + } + + GVariantIter* iter = NULL; + gchar* connPath = NULL; + g_variant_get(result, "ao", &iter); + while (g_variant_iter_loop(iter, "o", &connPath)) + { + if(connPath == NULL) + continue; + if(g_strcmp0(connPath, "/") != 0) + { + paths.push_back(connPath); + // NMLOG_DEBUG("AvailableConnections Path: %s", connPath); + ret = true; + } + } + + g_variant_iter_free(iter); + g_variant_unref(result); + g_object_unref(nmProxy); + return ret; + } + + bool GnomeUtils::getConnectionPaths(DbusMgr& m_dbus, std::list& pathsList) + { + GDBusProxy *sProxy= NULL; + GError *error= NULL; + GVariant *listProxy = NULL; + char **paths = NULL; + + sProxy = m_dbus.getNetworkManagerSettingsProxy(); + if(sProxy == NULL) + return false; + + listProxy = g_dbus_proxy_call_sync(sProxy, + "ListConnections", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if(listProxy == NULL) + { + if (!error) { + NMLOG_ERROR("ListConnections failed: %s", error->message); + g_error_free(error); + g_object_unref(sProxy); + return false; + } + else + NMLOG_ERROR("ListConnections proxy failed no error message"); + } + + g_variant_get(listProxy, "(^ao)", &paths); + g_variant_unref(listProxy); + + if(paths == NULL) + { + NMLOG_WARNING("no connection path available"); + g_object_unref(sProxy); + return false; + } + + for (int i = 0; paths[i]; i++) { + //NMLOG_DEBUG("Connection path: %s", paths[i]); + pathsList.push_back(paths[i]); + } + + g_strfreev(paths); + g_object_unref(sProxy); + if(pathsList.empty()) + return false; + + return true; + } + + } // Plugin +} // WPEFramework + diff --git a/gdbus/NetworkManagerGdbusUtils.h b/gdbus/NetworkManagerGdbusUtils.h new file mode 100644 index 000000000..4f9b8cef5 --- /dev/null +++ b/gdbus/NetworkManagerGdbusUtils.h @@ -0,0 +1,87 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include +#include +#include +#include + +/* include NetworkManager.h for the defines, but we don't link against libnm. */ +// #include +#include +#include "INetworkManager.h" +#include "NetworkManagerGdbusMgr.h" + +using namespace std; + +struct apInfo { + string ssid; + string bssid; + NM80211ApFlags flag; + NM80211ApSecurityFlags wpaFlag; + NM80211ApSecurityFlags rsnFlag; + NM80211Mode mode; + guint32 frequency; + guint32 bitrate; + guint32 strength; +}; + +struct deviceInfo +{ + std::string interface; + std::string activeConnPath; + std::string path; + NMDeviceState state; + NMDeviceStateReason stateReason; + NMDeviceType deviceType; +}; + +#define G_VARIANT_LOOKUP(dict, key, format, ...) \ + if (!g_variant_lookup(dict, key, format, __VA_ARGS__)) {\ + NMLOG_ERROR("g_variant Key '%s' not found", key); \ + return FALSE; \ + } + +namespace WPEFramework +{ + namespace Plugin + { + class GnomeUtils { + public: + static bool getDeviceByIpIface(DbusMgr& m_dbus, const gchar *iface_name, std::string& path); + static bool getApDetails(DbusMgr& m_dbus, const char* apPath, Exchange::INetworkManager::WiFiSSIDInfo& wifiInfo); + static bool getConnectionPaths(DbusMgr& m_dbus, std::list& pathsList); + static bool getWifiConnectionPaths(DbusMgr& m_dbus, const char* devicePath, std::list& paths); + static bool getDevicePropertiesByPath(DbusMgr& m_dbus, const char* devPath, deviceInfo& properties); + static bool getDeviceInfoByIfname(DbusMgr& m_dbus, const char* ifname, deviceInfo& properties); + static bool getCachedPropertyU(GDBusProxy* proxy, const char* propertiy, uint32_t *value); + static bool getIPv4AddrFromIPv4ConfigProxy(GDBusProxy *ipProxy, std::string& ipAddr, uint32_t& prifix); + static bool getIPv6AddrFromIPv6ConfigProxy(GDBusProxy *ipProxy, std::string& ipAddr, uint32_t& prifix); + + static bool convertSsidInfoToJsonObject(Exchange::INetworkManager::WiFiSSIDInfo& wifiInfo, JsonObject& ssidObj); + static const char* convertPercentageToSignalStrengtStr(int percentage); + static uint8_t wifiSecurityModeFromApFlags(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); + static const char* getWifiIfname(); + static const char* getEthIfname(); + }; + + } // Plugin +} // WPEFramework + From 5f3d786b921436ce4cf8da0973ac2c63b241e274 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Tue, 7 Jan 2025 23:15:22 +0530 Subject: [PATCH 071/271] ENABLE_GNOME_GDBUS flag added (#72) --- CMakeLists.txt | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 589df8816..eae055fe0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,13 +102,28 @@ set_target_properties(${MODULE_NAME} PROPERTIES if(ENABLE_GNOME_NETWORKMANAGER) - target_sources(${MODULE_NAME} PRIVATE NetworkManagerGnomeProxy.cpp - NetworkManagerGnomeWIFI.cpp - NetworkManagerGnomeEvents.cpp - NetworkManagerGnomeUtils.cpp ) - target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) - target_link_libraries(${MODULE_NAME} PRIVATE ${LIBNM_LIBRARIES}) + if(ENABLE_GNOME_GDBUS) + message("networkmanager building with gdbus") + target_sources(${MODULE_NAME} PRIVATE + gdbus/NetworkManagerGdbusProxy.cpp + gdbus/NetworkManagerGdbusClient.cpp + gdbus/NetworkManagerGdbusEvent.cpp + gdbus/NetworkManagerGdbusMgr.cpp + gdbus/NetworkManagerGdbusUtils.cpp ) + target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) + target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES} ${GIO_LIBRARIES}) + else() + message("networkmanager building with libnm") + target_sources(${MODULE_NAME} PRIVATE + NetworkManagerGnomeProxy.cpp + NetworkManagerGnomeWIFI.cpp + NetworkManagerGnomeEvents.cpp + NetworkManagerGnomeUtils.cpp ) + target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) + target_link_libraries(${MODULE_NAME} PRIVATE ${LIBNM_LIBRARIES}) + endif() else() + message("networkmanager building with netsrvmgr") target_sources(${MODULE_NAME} PRIVATE NetworkManagerRDKProxy.cpp) target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) target_link_libraries(${MODULE_NAME} PRIVATE ${IARMBUS_LIBRARIES}) From 57b1c899436958fec1eb8e57c197bdc069f6da98 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 13 Jan 2025 10:35:55 -0500 Subject: [PATCH 072/271] RDKEMW-1122 - Addressing Coverity Issues and OSCR Issues (#74) Reason for change: Addressed all the OSCR Issues Test Procedure: NA Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR --- CMakeLists.txt | 18 +++++++++ CONTRIBUTING.md | 2 +- COPYING | 1 + LegacyPlugin_NetworkAPIs.cpp | 2 +- LegacyPlugin_NetworkAPIs.h | 18 +++++++++ LegacyPlugin_WiFiManagerAPIs.cpp | 2 +- LegacyPlugin_WiFiManagerAPIs.h | 2 +- Module.cpp | 2 +- Module.h | 2 +- NOTICE | 8 ++++ NetworkManager.cpp | 2 +- NetworkManager.h | 2 +- NetworkManagerConnectivity.cpp | 36 +++++++++--------- NetworkManagerConnectivity.h | 36 +++++++++--------- NetworkManagerGnomeEvents.cpp | 36 +++++++++--------- NetworkManagerGnomeEvents.h | 36 +++++++++--------- NetworkManagerGnomeProxy.cpp | 18 +++++++++ NetworkManagerGnomeUtils.cpp | 18 +++++++++ NetworkManagerGnomeUtils.h | 38 +++++++++---------- NetworkManagerGnomeWIFI.cpp | 36 +++++++++--------- NetworkManagerGnomeWIFI.h | 36 +++++++++--------- NetworkManagerImplementation.cpp | 2 +- NetworkManagerImplementation.h | 2 +- NetworkManagerJsonEnum.h | 18 +++++++++ NetworkManagerJsonRpc.cpp | 2 +- NetworkManagerLogger.cpp | 36 +++++++++--------- NetworkManagerLogger.h | 36 +++++++++--------- NetworkManagerRDKProxy.cpp | 18 +++++++++ NetworkManagerStunClient.cpp | 18 +++++++++ NetworkManagerStunClient.h | 18 +++++++++ NetworkManagerTimer.h | 2 +- Tests/mocks/Iarm.h | 18 +++++++++ .../raspberrypi/NetworkManagerGdbusTest.cmake | 18 +++++++++ Tests/raspberrypi/NetworkManagerGdbusTest.cpp | 18 +++++++++ .../test_NetworkManagerConnectivity.cpp | 18 +++++++++ .../test_NetworkManagerStunClient.cpp | 18 +++++++++ .../test_WiFiSignalStrengthMonitor.cpp | 18 +++++++++ Tests/unit_test/unit_tests.cmake | 18 +++++++++ WiFiSignalStrengthMonitor.cpp | 18 +++++++++ WiFiSignalStrengthMonitor.h | 2 +- cmake/FindIARMBus.cmake | 6 ++- cmake/Findrdklogger.cmake | 7 ++-- gdbus/NetworkManagerGdbusClient.cpp | 2 +- gdbus/NetworkManagerGdbusClient.h | 38 +++++++++---------- gdbus/NetworkManagerGdbusEvent.cpp | 36 +++++++++--------- gdbus/NetworkManagerGdbusEvent.h | 36 +++++++++--------- gdbus/NetworkManagerGdbusMgr.cpp | 2 +- gdbus/NetworkManagerGdbusMgr.h | 38 +++++++++---------- gdbus/NetworkManagerGdbusProxy.cpp | 4 +- gdbus/NetworkManagerGdbusUtils.cpp | 2 +- gdbus/NetworkManagerGdbusUtils.h | 36 +++++++++--------- 51 files changed, 577 insertions(+), 279 deletions(-) create mode 120000 COPYING create mode 100644 NOTICE diff --git a/CMakeLists.txt b/CMakeLists.txt index eae055fe0..5b4666aea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,21 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2023 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# cmake_minimum_required(VERSION 3.3) project(NetworkManager) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 161c09284..e626c75e4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ Contributing ============ -If you would like to contribute code to this project you can do so through GitHub by forking the repository and sending a pull request. Before RDK accepts your code into the project you must sign the RDK Contributor License Agreement (CLA). \ No newline at end of file +If you would like to contribute code to this project you can do so through GitHub by forking the repository and sending a pull request. Before RDK accepts your code into the project you must sign the RDK Contributor License Agreement (CLA). diff --git a/COPYING b/COPYING new file mode 120000 index 000000000..7a694c969 --- /dev/null +++ b/COPYING @@ -0,0 +1 @@ +LICENSE \ No newline at end of file diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index d65c3ecc0..67b822464 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/LegacyPlugin_NetworkAPIs.h b/LegacyPlugin_NetworkAPIs.h index d61c045a6..72b82ddb5 100644 --- a/LegacyPlugin_NetworkAPIs.h +++ b/LegacyPlugin_NetworkAPIs.h @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #pragma once #include diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index 0cf50ca4d..651de85b3 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/LegacyPlugin_WiFiManagerAPIs.h b/LegacyPlugin_WiFiManagerAPIs.h index e596fd47f..96be2970b 100644 --- a/LegacyPlugin_WiFiManagerAPIs.h +++ b/LegacyPlugin_WiFiManagerAPIs.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2020 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/Module.cpp b/Module.cpp index d402f4409..ebecea700 100644 --- a/Module.cpp +++ b/Module.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/Module.h b/Module.h index b6552bb9d..6382d0d47 100644 --- a/Module.h +++ b/Module.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 000000000..422ac085c --- /dev/null +++ b/NOTICE @@ -0,0 +1,8 @@ +This component contains software that is Copyright (c) 2023 RDK Management. +The component is licensed to you under the Apache License, Version 2.0 (the "License"). +You may not use the component except in compliance with the License. + +The component may include material which is licensed under other licenses / copyrights as +listed below. Your use of this material within the component is also subject to the terms and +conditions of these licenses. The LICENSE file contains the text of all the licenses which apply +within this component. diff --git a/NetworkManager.cpp b/NetworkManager.cpp index f068565d4..870dcb87d 100644 --- a/NetworkManager.cpp +++ b/NetworkManager.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/NetworkManager.h b/NetworkManager.h index 353c34f78..c99b86158 100644 --- a/NetworkManager.h +++ b/NetworkManager.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/NetworkManagerConnectivity.cpp b/NetworkManagerConnectivity.cpp index 1a4667e1d..ce38c2467 100644 --- a/NetworkManagerConnectivity.cpp +++ b/NetworkManagerConnectivity.cpp @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include #include diff --git a/NetworkManagerConnectivity.h b/NetworkManagerConnectivity.h index 3a5b215a3..e98400352 100644 --- a/NetworkManagerConnectivity.h +++ b/NetworkManagerConnectivity.h @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #pragma once diff --git a/NetworkManagerGnomeEvents.cpp b/NetworkManagerGnomeEvents.cpp index 3b745b7e3..bf17d1cfe 100644 --- a/NetworkManagerGnomeEvents.cpp +++ b/NetworkManagerGnomeEvents.cpp @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include #include diff --git a/NetworkManagerGnomeEvents.h b/NetworkManagerGnomeEvents.h index 69f08bdd4..ccf631bc6 100644 --- a/NetworkManagerGnomeEvents.h +++ b/NetworkManagerGnomeEvents.h @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #pragma once #include diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index fe1faddd4..61606be7a 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include "NetworkManagerImplementation.h" #include "NetworkManagerGnomeWIFI.h" #include "NetworkManagerGnomeEvents.h" diff --git a/NetworkManagerGnomeUtils.cpp b/NetworkManagerGnomeUtils.cpp index 6b10ec2a1..921168211 100644 --- a/NetworkManagerGnomeUtils.cpp +++ b/NetworkManagerGnomeUtils.cpp @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include #include #include diff --git a/NetworkManagerGnomeUtils.h b/NetworkManagerGnomeUtils.h index d305fc7fd..1d7656030 100644 --- a/NetworkManagerGnomeUtils.h +++ b/NetworkManagerGnomeUtils.h @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #pragma once #include @@ -47,4 +47,4 @@ namespace WPEFramework }; } -} \ No newline at end of file +} diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index adcb4349f..685e17664 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include #include #include diff --git a/NetworkManagerGnomeWIFI.h b/NetworkManagerGnomeWIFI.h index 4a5bf2a72..128c52f91 100644 --- a/NetworkManagerGnomeWIFI.h +++ b/NetworkManagerGnomeWIFI.h @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #pragma once diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 6dad3144c..5719c7184 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 83fcc03d6..0c1d06459 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/NetworkManagerJsonEnum.h b/NetworkManagerJsonEnum.h index 54725b0b6..939411c6b 100644 --- a/NetworkManagerJsonEnum.h +++ b/NetworkManagerJsonEnum.h @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #pragma once #include diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index f1b8d76e8..f1269af13 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/NetworkManagerLogger.cpp b/NetworkManagerLogger.cpp index 313fdcbcc..5dc6dfe57 100644 --- a/NetworkManagerLogger.cpp +++ b/NetworkManagerLogger.cpp @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include "NetworkManagerLogger.h" #include diff --git a/NetworkManagerLogger.h b/NetworkManagerLogger.h index e7bc5e0b0..5982ba878 100644 --- a/NetworkManagerLogger.h +++ b/NetworkManagerLogger.h @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #ifndef NM_LOGGER_H #define NM_LOGGER_H diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index e6fe30c43..961193482 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include "NetworkManagerImplementation.h" #include "NetworkManagerConnectivity.h" #include "WiFiSignalStrengthMonitor.h" diff --git a/NetworkManagerStunClient.cpp b/NetworkManagerStunClient.cpp index 1960f0f91..cb6562957 100644 --- a/NetworkManagerStunClient.cpp +++ b/NetworkManagerStunClient.cpp @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2021 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include "NetworkManagerStunClient.h" #include #include diff --git a/NetworkManagerStunClient.h b/NetworkManagerStunClient.h index 09f093a56..c1a1203ac 100644 --- a/NetworkManagerStunClient.h +++ b/NetworkManagerStunClient.h @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #ifndef STUN_CLIENT_H #define STUN_CLIENT_H diff --git a/NetworkManagerTimer.h b/NetworkManagerTimer.h index 5fbeea352..5c8b5df17 100644 --- a/NetworkManagerTimer.h +++ b/NetworkManagerTimer.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2020 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/Tests/mocks/Iarm.h b/Tests/mocks/Iarm.h index cf753c2b2..b068e3891 100644 --- a/Tests/mocks/Iarm.h +++ b/Tests/mocks/Iarm.h @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #pragma once #include diff --git a/Tests/raspberrypi/NetworkManagerGdbusTest.cmake b/Tests/raspberrypi/NetworkManagerGdbusTest.cmake index bceae28dd..732011e09 100644 --- a/Tests/raspberrypi/NetworkManagerGdbusTest.cmake +++ b/Tests/raspberrypi/NetworkManagerGdbusTest.cmake @@ -1,3 +1,21 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2023 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# message("building rpi test build") # Define the project set(RPI_TEST "NetworkManagerGdbusTest") diff --git a/Tests/raspberrypi/NetworkManagerGdbusTest.cpp b/Tests/raspberrypi/NetworkManagerGdbusTest.cpp index 01d9a60e1..b65e23858 100644 --- a/Tests/raspberrypi/NetworkManagerGdbusTest.cpp +++ b/Tests/raspberrypi/NetworkManagerGdbusTest.cpp @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include "NetworkManagerGdbusClient.h" #include "NetworkManagerGdbusMgr.h" #include "NetworkManagerLogger.h" diff --git a/Tests/unit_test/test_NetworkManagerConnectivity.cpp b/Tests/unit_test/test_NetworkManagerConnectivity.cpp index a04520291..1b59920f7 100644 --- a/Tests/unit_test/test_NetworkManagerConnectivity.cpp +++ b/Tests/unit_test/test_NetworkManagerConnectivity.cpp @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include "NetworkManagerImplementation.h" #include "NetworkManagerConnectivity.h" #include diff --git a/Tests/unit_test/test_NetworkManagerStunClient.cpp b/Tests/unit_test/test_NetworkManagerStunClient.cpp index 5276344a1..a5da16708 100644 --- a/Tests/unit_test/test_NetworkManagerStunClient.cpp +++ b/Tests/unit_test/test_NetworkManagerStunClient.cpp @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include #include #include "NetworkManagerStunClient.h" diff --git a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp b/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp index 5618a6cb0..c292c0c40 100644 --- a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp +++ b/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include "WiFiSignalStrengthMonitor.h" #include "NetworkManagerImplementation.h" #include "NetworkManagerLogger.h" diff --git a/Tests/unit_test/unit_tests.cmake b/Tests/unit_test/unit_tests.cmake index 9c56c2428..453ef92ec 100644 --- a/Tests/unit_test/unit_tests.cmake +++ b/Tests/unit_test/unit_tests.cmake @@ -1,3 +1,21 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2023 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# set(UNIT_TEST "unit_tests") find_package(PkgConfig REQUIRED) diff --git a/WiFiSignalStrengthMonitor.cpp b/WiFiSignalStrengthMonitor.cpp index 32aaa4c95..ffe4cde8b 100644 --- a/WiFiSignalStrengthMonitor.cpp +++ b/WiFiSignalStrengthMonitor.cpp @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2020 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include #include #include diff --git a/WiFiSignalStrengthMonitor.h b/WiFiSignalStrengthMonitor.h index 56929aaeb..c3772f2de 100644 --- a/WiFiSignalStrengthMonitor.h +++ b/WiFiSignalStrengthMonitor.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2020 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/cmake/FindIARMBus.cmake b/cmake/FindIARMBus.cmake index 843e55c25..39a642aee 100644 --- a/cmake/FindIARMBus.cmake +++ b/cmake/FindIARMBus.cmake @@ -1,7 +1,8 @@ -# If not stated otherwise in this file or this component's license file the +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the # following copyright and licenses apply: # -# Copyright 2020 RDK Management +# Copyright 2023 RDK Management # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,6 +15,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +############################################################################# # - Try to find IARMBus # Once done this will define diff --git a/cmake/Findrdklogger.cmake b/cmake/Findrdklogger.cmake index 3e08fb53d..267692be7 100644 --- a/cmake/Findrdklogger.cmake +++ b/cmake/Findrdklogger.cmake @@ -1,8 +1,8 @@ ############################################################################# -# If not stated otherwise in this file or this component's Licenses.txt file -# the following copyright and licenses apply: +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: # -# Copyright 2016 RDK Management +# Copyright 2023 RDK Management # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -10,7 +10,6 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # -# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/gdbus/NetworkManagerGdbusClient.cpp b/gdbus/NetworkManagerGdbusClient.cpp index 59e4f678e..c99a56f36 100644 --- a/gdbus/NetworkManagerGdbusClient.cpp +++ b/gdbus/NetworkManagerGdbusClient.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/gdbus/NetworkManagerGdbusClient.h b/gdbus/NetworkManagerGdbusClient.h index 15b8eb11b..7e6466525 100644 --- a/gdbus/NetworkManagerGdbusClient.h +++ b/gdbus/NetworkManagerGdbusClient.h @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #pragma once #include @@ -64,4 +64,4 @@ namespace WPEFramework DbusMgr m_dbus; }; } // Plugin -} // WPEFramework \ No newline at end of file +} // WPEFramework diff --git a/gdbus/NetworkManagerGdbusEvent.cpp b/gdbus/NetworkManagerGdbusEvent.cpp index 21c035802..a7b920a72 100644 --- a/gdbus/NetworkManagerGdbusEvent.cpp +++ b/gdbus/NetworkManagerGdbusEvent.cpp @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #include diff --git a/gdbus/NetworkManagerGdbusEvent.h b/gdbus/NetworkManagerGdbusEvent.h index 69b1f0f4b..d25a198b9 100644 --- a/gdbus/NetworkManagerGdbusEvent.h +++ b/gdbus/NetworkManagerGdbusEvent.h @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #pragma once #include diff --git a/gdbus/NetworkManagerGdbusMgr.cpp b/gdbus/NetworkManagerGdbusMgr.cpp index 4b0f608cc..310b025dc 100644 --- a/gdbus/NetworkManagerGdbusMgr.cpp +++ b/gdbus/NetworkManagerGdbusMgr.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/gdbus/NetworkManagerGdbusMgr.h b/gdbus/NetworkManagerGdbusMgr.h index c75915fa0..8e00c8971 100644 --- a/gdbus/NetworkManagerGdbusMgr.h +++ b/gdbus/NetworkManagerGdbusMgr.h @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #pragma once #include @@ -53,4 +53,4 @@ namespace WPEFramework }; } -} \ No newline at end of file +} diff --git a/gdbus/NetworkManagerGdbusProxy.cpp b/gdbus/NetworkManagerGdbusProxy.cpp index 2067d4bd2..576654120 100644 --- a/gdbus/NetworkManagerGdbusProxy.cpp +++ b/gdbus/NetworkManagerGdbusProxy.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -194,4 +194,4 @@ namespace WPEFramework return Core::ERROR_NONE; } } -} \ No newline at end of file +} diff --git a/gdbus/NetworkManagerGdbusUtils.cpp b/gdbus/NetworkManagerGdbusUtils.cpp index 260d59df7..dc893292d 100644 --- a/gdbus/NetworkManagerGdbusUtils.cpp +++ b/gdbus/NetworkManagerGdbusUtils.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2022 RDK Management +* Copyright 2023 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/gdbus/NetworkManagerGdbusUtils.h b/gdbus/NetworkManagerGdbusUtils.h index 4f9b8cef5..6366ff715 100644 --- a/gdbus/NetworkManagerGdbusUtils.h +++ b/gdbus/NetworkManagerGdbusUtils.h @@ -1,21 +1,21 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #pragma once #include From c01ed111f32bd492f8765f4de9f63fc5a5a8708e Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 16 Jan 2025 01:37:51 +0530 Subject: [PATCH 073/271] RDK-55450 [NetworkManager] Improve Connectivity Monitoring (#71) * connectivity monitor clean up change * InetworkManager enums added * start and stop connectivity monitor api removed * log line added * code review comments updated * fix the limited timeout * Update NetworkManager.json * Update NetworkManagerPlugin.md * Update NetworkManager.json * Update NetworkManagerPlugin.md * remove cache logic form workflow --------- Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- .github/workflows/gnome_unit_test.yml | 18 - INetworkManager.h | 5 - LegacyPlugin_NetworkAPIs.cpp | 26 +- NetworkManager.h | 2 - NetworkManager.json | 100 +-- NetworkManagerConnectivity.cpp | 744 +++++++++--------- NetworkManagerConnectivity.h | 123 ++- NetworkManagerImplementation.cpp | 53 +- NetworkManagerImplementation.h | 5 - NetworkManagerJsonRpc.cpp | 32 - NetworkManagerRDKProxy.cpp | 1 - .../test_NetworkManagerConnectivity.cpp | 74 +- docs/NetworkManagerPlugin.md | 148 +--- 13 files changed, 512 insertions(+), 819 deletions(-) diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index 3d8fd2782..23be4d134 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -15,20 +15,6 @@ jobs: runs-on: ubuntu-22.04 steps: - - name: Configure cache - if: ${{ !env.ACT }} - id: cache - uses: actions/cache@v3 - with: - path: | - build/Thunder - build/ThunderInterfaces - build/ThunderTools - install - !install/etc/WPEFramework/plugins - !install/usr/lib/wpeframework/plugins - key: ${{ runner.os }}-${{ env.THUNDER_REF }} - - name: Install packages run: | sudo apt update @@ -46,14 +32,12 @@ jobs: cmake-version: '3.16.x' - name: Checkout thunder repositories - if: steps.cache.outputs.cache-hit != 'true' run: | git clone https://github.com/rdkcentral/ThunderTools ThunderTools --branch ${{ env.THUNDER_REF }} git clone https://github.com/rdkcentral/Thunder Thunder --branch ${{ env.THUNDER_REF }} git clone https://github.com/rdkcentral/ThunderInterfaces ThunderInterfaces --branch ${{ env.THUNDER_REF }} - name: Build ThunderTools - if: steps.cache.outputs.cache-hit != 'true' run: > cmake -S "${{github.workspace}}/ThunderTools" -B build/ThunderTools @@ -64,7 +48,6 @@ jobs: cmake --build build/ThunderTools --target install -j8 - name: Build Thunder - if: steps.cache.outputs.cache-hit != 'true' run: > cmake -S "${{github.workspace}}/Thunder" -B build/Thunder @@ -77,7 +60,6 @@ jobs: cmake --build build/Thunder --target install -j8 - name: Build ThunderInterfaces - if: steps.cache.outputs.cache-hit != 'true' run: > cmake -S "${{github.workspace}}/ThunderInterfaces" -B build/ThunderInterfaces diff --git a/INetworkManager.h b/INetworkManager.h index 6b67729f5..26d633746 100644 --- a/INetworkManager.h +++ b/INetworkManager.h @@ -237,11 +237,6 @@ namespace WPEFramework /* @brief Get Authentication URL if the device is behind Captive Portal */ virtual uint32_t GetCaptivePortalURI(string &uri/* @out */) const = 0; - /* @brief Start The Internet Connectivity Monitoring */ - virtual uint32_t StartConnectivityMonitoring(const uint32_t interval /* @in */) = 0; - /* @brief Stop The Internet Connectivity Monitoring */ - virtual uint32_t StopConnectivityMonitoring(void) const = 0; - /* @brief Get the Public IP used for external world communication */ virtual uint32_t GetPublicIP (string& interface /* @inout */, string &ipversion /* @inout */, string& ipaddress /* @out */) = 0; diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index 67b822464..8d49452eb 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -817,19 +817,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { uint32_t Network::startConnectivityMonitoring(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); - uint32_t rc = Core::ERROR_GENERAL; - uint32_t interval = parameters["interval"].Number(); - - NMLOG_DEBUG("connectivity interval = %d", interval); - auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); - if (_nwmgr) - rc = _nwmgr->StartConnectivityMonitoring(interval); - else - rc = Core::ERROR_UNAVAILABLE; - - if(_nwmgr) - _nwmgr->Release(); - + uint32_t rc = Core::ERROR_NONE; returnJson(rc); } @@ -857,17 +845,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { uint32_t Network::stopConnectivityMonitoring(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); - uint32_t rc = Core::ERROR_GENERAL; - - auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); - if (_nwmgr) - { - rc = _nwmgr->StopConnectivityMonitoring(); - _nwmgr->Release(); - } - else - rc = Core::ERROR_UNAVAILABLE; - + uint32_t rc = Core::ERROR_NONE; returnJson(rc); } diff --git a/NetworkManager.h b/NetworkManager.h index c99b86158..d4830dd07 100644 --- a/NetworkManager.h +++ b/NetworkManager.h @@ -247,8 +247,6 @@ namespace WPEFramework uint32_t SetConnectivityTestEndpoints(const JsonObject& parameters, JsonObject& response); uint32_t IsConnectedToInternet(const JsonObject& parameters, JsonObject& response); uint32_t GetCaptivePortalURI(const JsonObject& parameters, JsonObject& response); - uint32_t StartConnectivityMonitoring(const JsonObject& parameters, JsonObject& response); - uint32_t StopConnectivityMonitoring(const JsonObject& parameters, JsonObject& response); uint32_t GetPublicIP(const JsonObject& parameters, JsonObject& response); uint32_t Ping(const JsonObject& parameters, JsonObject& response); uint32_t Trace(const JsonObject& parameters, JsonObject& response); diff --git a/NetworkManager.json b/NetworkManager.json index 649a044b0..ed3e481ab 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -108,14 +108,14 @@ "example": "30" }, "ssid":{ - "summary": "The paired SSID", + "summary": "The WiFi SSID Name", "type": "string", - "example": "123412341234" + "example": "myHomeSSID" }, "bssid":{ - "summary": "The paired BSSID", + "summary": "The BSSID of given SSID", "type": "string", - "example": "ff:ff:ff:ff:ff:ff" + "example": "AA:BB:CC:DD:EE:FF" }, "passphrase": { "summary": "The access point password", @@ -128,10 +128,15 @@ "example": 6 }, "strength":{ - "summary": "The RSSI value in dBm", + "summary": "The Signal RSSI value in dBm", "type": "string", "example": "-27.000000" }, + "quality":{ + "summary": "Signal strength Quality", + "type": "string", + "example": "Excellent" + }, "frequency":{ "summary": "The supported frequency for this SSID in GHz", "type": "string", @@ -334,9 +339,7 @@ "type": "object", "properties": { "interface": { - "summary": "Disable the specified interface", - "type": "string", - "example": "wlan0" + "$ref": "#/definitions/interface" } }, "required": [ @@ -552,9 +555,10 @@ "type":"object", "properties": { "endpoints": { - "summary": "", + "summary": "A list of endpoint URLs used", "type": "array", "items": { + "summary": "The endpoint URL", "type": "string", "example": "http://clients3.google.com/generate_204" } @@ -578,6 +582,7 @@ "summary": "A list of endpoints to test", "type": "array", "items": { + "summary": "The endpoint URL", "type": "string", "example": "http://clients3.google.com/generate_204" } @@ -665,49 +670,6 @@ ] } }, - "StartConnectivityMonitoring":{ - "summary": "Enable a continuous monitoring of internet connectivity with heart beat interval thats given. If the monitoring is already happening, it will be restarted with new given interval. When the interval is not passed, it will be 60s by default.", - "events":{ - "onInternetStatusChange" : "Triggered when internet connection state changed." - }, - "params": { - "type":"object", - "properties": { - "interval": { - "summary": "Interval in sec.", - "type": "number", - "example": "30" - } - }, - "required": [ - ] - }, - "result": { - "type": "object", - "properties": { - "success":{ - "$ref": "#/definitions/success" - } - }, - "required": [ - "success" - ] - } - }, - "StopConnectivityMonitoring":{ - "summary": "Stops the connectivity monitoring", - "result": { - "type": "object", - "properties": { - "success":{ - "$ref": "#/definitions/success" - } - }, - "required": [ - "success" - ] - } - }, "GetPublicIP":{ "summary": "Gets the internet/public IP Address of the device.", "params": { @@ -915,6 +877,7 @@ "summary": "The list of SSIDs to be scanned.", "type": "array", "items": { + "summary": "The SSID to scan.", "type": "string", "example": "Xfinity Mobile" } @@ -955,9 +918,10 @@ "type": "object", "properties": { "ssids": { - "summary": "Known SSIDS", + "summary": "A list of known SSIDs", "type": "array", "items": { + "summary": "The WiFi SSID Name", "type": "string", "example": "Xfinity_Guest" } @@ -1263,9 +1227,7 @@ "$ref": "#/definitions/strength" }, "quality":{ - "summary": "Signal strength Quality", - "type": "string", - "example": "Excellent" + "$ref": "#/definitions/quality" }, "success":{ "$ref": "#/definitions/success" @@ -1514,24 +1476,18 @@ "type":"object", "properties": { "ssid":{ - "summary": "ssid", + "summary": "Discovered SSID", "type": "string", "example": "myAP-2.4" }, "security":{ - "summary": "security", - "type": "integer", - "example": 6 + "$ref": "#/definitions/security" }, "strength":{ - "summary": "strength", - "type": "string", - "example": "-27.000000" + "$ref": "#/definitions/strength" }, "frequency":{ - "summary": "frequency", - "type": "string", - "example": "2.442000" + "$ref": "#/definitions/frequency" } }, "required": [ @@ -1573,19 +1529,13 @@ "type": "object", "properties": { "ssid":{ - "summary": "Signal Strength changed SSID", - "type": "string", - "example": "home-new_123" + "$ref": "#/definitions/ssid" }, "strength":{ - "summary": "Signal Strength", - "type": "string", - "example": "-27.000000" + "$ref": "#/definitions/strength" }, "quality":{ - "summary": "Signal quality", - "type": "string", - "example": "Excellent" + "$ref": "#/definitions/quality" } }, "required": [ diff --git a/NetworkManagerConnectivity.cpp b/NetworkManagerConnectivity.cpp index ce38c2467..8140b2e96 100644 --- a/NetworkManagerConnectivity.cpp +++ b/NetworkManagerConnectivity.cpp @@ -19,14 +19,17 @@ #include #include -#include +#include #include #include -#include +#include +#include +#include #include "NetworkManagerImplementation.h" #include "NetworkManagerConnectivity.h" #include "NetworkManagerLogger.h" +#include "INetworkManager.h" namespace WPEFramework { @@ -35,27 +38,30 @@ namespace WPEFramework extern NetworkManagerImplementation* _instance; - static const char* getInternetStateString(nsm_internetState state) + constexpr auto INTERNET_NOT_AVAILABLE = Exchange::INetworkManager::InternetStatus::INTERNET_NOT_AVAILABLE; + constexpr auto INTERNET_LIMITED = Exchange::INetworkManager::InternetStatus::INTERNET_LIMITED; + constexpr auto INTERNET_CAPTIVE_PORTAL = Exchange::INetworkManager::InternetStatus::INTERNET_CAPTIVE_PORTAL; + constexpr auto INTERNET_FULLY_CONNECTED = Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED; + constexpr auto INTERNET_UNKNOWN = Exchange::INetworkManager::InternetStatus::INTERNET_UNKNOWN; + + constexpr auto IP_ADDRESS_V4 = Exchange::INetworkManager::IPVersion::IP_ADDRESS_V4; + constexpr auto IP_ADDRESS_V6 = Exchange::INetworkManager::IPVersion::IP_ADDRESS_V6; + + static const char* getInternetStateString(Exchange::INetworkManager::InternetStatus state) { switch(state) { - case NO_INTERNET: return "NO_INTERNET"; - case LIMITED_INTERNET: return "LIMITED_INTERNET"; - case CAPTIVE_PORTAL: return "CAPTIVE_PORTAL"; - case FULLY_CONNECTED: return "FULLY_CONNECTED"; + case INTERNET_NOT_AVAILABLE: return "NO_INTERNET"; + case INTERNET_LIMITED: return "LIMITED_INTERNET"; + case INTERNET_CAPTIVE_PORTAL: return "CAPTIVE_PORTAL"; + case INTERNET_FULLY_CONNECTED: return "FULLY_CONNECTED"; default: return "UNKNOWN"; } } - bool EndpointCache::isEndpointCashFileExist() - { - std::ifstream fileStream(CachefilePath); - return fileStream.is_open(); - } - - void EndpointCache::writeEnpointsToFile(const std::vector& endpoints) + void EndpointManager::writeEndpointsToFile(const std::vector& endpoints) { - std::ofstream outputFile(CachefilePath); + std::ofstream outputFile(m_CachefilePath); if (outputFile.is_open()) { for (const std::string& str : endpoints) @@ -70,10 +76,10 @@ namespace WPEFramework } } - std::vector EndpointCache::readEnpointsFromFile() + std::vector EndpointManager::readEndpointsFromFile() { std::vector readStrings; - std::ifstream inputFile(CachefilePath); + std::ifstream inputFile(m_CachefilePath); if (inputFile.is_open()) { std::string line; @@ -90,9 +96,152 @@ namespace WPEFramework return readStrings; } - TestConnectivity::TestConnectivity(const std::vector& endpoints, long timeout_ms, bool headReq, nsm_ipversion ipversion) + void EndpointManager::setConnectivityMonitorEndpoints(const std::vector& endpoints) + { + const std::lock_guard lock(m_endpointMutex); + if(endpoints.empty()) + { + NMLOG_ERROR("Empty endpoints"); + return; + } + + m_Endpoints.clear(); + for (auto endpoint : endpoints) { + if(!endpoint.empty() && endpoint.size() > 3) + m_Endpoints.push_back(endpoint.c_str()); + else + NMLOG_ERROR("endpoint not vallied = %s", endpoint.c_str()); + } + + // write the endpoints to a file + writeEndpointsToFile(m_Endpoints); + + std::string endpointsStr; + for (const auto& endpoint : m_Endpoints) + endpointsStr.append(endpoint).append(" "); + NMLOG_INFO("Connectivity monitor endpoints updated -: %d :- %s", static_cast(m_Endpoints.size()), endpointsStr.c_str()); + } + + EndpointManager::EndpointManager() + { + m_CachefilePath = NMCONNECTIVITY_MONITOR_CACHE_FILE; + m_Endpoints.clear(); // default value will be loaded from NetworkManagerImplementation configuration + + std::ifstream inputFile(m_CachefilePath); + if (inputFile.is_open()) + { + std::string line; + std::vector endpoints{}; + while (std::getline(inputFile, line)) + { + if(!line.empty() && line.size() > 3) + endpoints.push_back(line); + } + NMLOG_WARNING("cached connectivity endpoints loaded .."); + setConnectivityMonitorEndpoints(endpoints); + inputFile.close(); + } + else + { + NMLOG_ERROR("no endpoint cache file found"); + } + } + + std::vector EndpointManager::getConnectivityMonitorEndpoints() + { + const std::lock_guard lock(m_endpointMutex); + return m_Endpoints; + } + + bool DnsResolver::resolveIP(std::string& uri, Exchange::INetworkManager::IPVersion& ipversion) + { + struct addrinfo sockAddrProps, *resultAddr= NULL; + char ipStr[INET6_ADDRSTRLEN] = {0}; + + if(ipversion == IP_ADDRESS_V4) + sockAddrProps.ai_family = AF_INET; + else if(ipversion == IP_ADDRESS_V6) + sockAddrProps.ai_family = AF_INET6; + else + sockAddrProps.ai_family = AF_UNSPEC; + + sockAddrProps.ai_socktype = SOCK_STREAM; + sockAddrProps.ai_flags = 0; + sockAddrProps.ai_protocol = 0; + + int ret = getaddrinfo(uri.c_str(), NULL, &sockAddrProps, &resultAddr); + if (ret != 0) { + NMLOG_WARNING("Resolved IP Failed getaddrinfo: %s", gai_strerror(ret)); + return false; + } + + NMLOG_DEBUG("Resolved IP addresses for %s", uri.c_str()); + + for (struct addrinfo * resutIP = resultAddr; resutIP != NULL; resutIP = resutIP->ai_next) + { + void *addr= NULL; + if (resutIP->ai_family == AF_INET) { + struct sockaddr_in *ipv4 = (struct sockaddr_in *)resutIP->ai_addr; + addr = &(ipv4->sin_addr); + ipv4Resolved = true; + } else if (resutIP->ai_family == AF_INET6) { + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)resutIP->ai_addr; + addr = &(ipv6->sin6_addr); + ipv6Resolved = true; + } else { + continue; + } + + inet_ntop(resutIP->ai_family, addr, ipStr, sizeof(ipStr)); + NMLOG_DEBUG("Resolved IP --> %s", ipStr); + } + + freeaddrinfo(resultAddr); + return true; + } + + std::string DnsResolver::convertUrIToDomainName(std::string& url) { - internetSate = UNKNOWN; + size_t domainStart = 0; + size_t protocolEnd = url.find("://"); + if (protocolEnd != std::string::npos) { + domainStart = protocolEnd + 3; + } + + size_t domainEnd = url.find('/', domainStart); + if (domainEnd != std::string::npos) + return url.substr(domainStart, domainEnd - domainStart); + else + return url.substr(domainStart); + } + + DnsResolver::DnsResolver(std::string url, Exchange::INetworkManager::IPVersion ipversion, int curlErrorCode) + { + NMLOG_DEBUG("url %s - ipversion %d - curl error %d ", url.c_str(), ipversion, curlErrorCode); + if(url.empty()) { + NMLOG_ERROR("URI/hostname missing"); + return; + } + switch (curlErrorCode) + { + case CURLE_COULDNT_RESOLVE_HOST: // 6 - Could not resolve host + case CURLE_OPERATION_TIMEDOUT: // 28 - Operation timeout. time-out period + case CURLE_RECV_ERROR: // 56 - Failure with receiving network data + { + m_domain = convertUrIToDomainName(url); + resolveIP(m_domain, ipversion); + break; + } + default: + ipv4Resolved = false; + ipv6Resolved = false; + break; + } + } + + TestConnectivity::TestConnectivity(const std::vector& endpoints, long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion) + { + internetSate = INTERNET_UNKNOWN; if(endpoints.size() < 1) { NMLOG_ERROR("Endpoints size error ! curl check not possible"); return; @@ -119,7 +268,7 @@ namespace WPEFramework return size * nmemb; } - nsm_internetState TestConnectivity::checkCurlResponse(const std::vector& endpoints, long timeout_ms, bool headReq, nsm_ipversion ipversion) + Exchange::INetworkManager::InternetStatus TestConnectivity::checkCurlResponse(const std::vector& endpoints, long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion) { long deadline = current_time() + timeout_ms, time_now = 0, time_earlier = 0; @@ -127,7 +276,7 @@ namespace WPEFramework if (!curl_multi_handle) { NMLOG_ERROR("curl_multi_init returned NULL"); - return NO_INTERNET; + return INTERNET_NOT_AVAILABLE; } CURLMcode mc; @@ -156,15 +305,17 @@ namespace WPEFramework } curl_easy_setopt(curl_easy_handle, CURLOPT_WRITEFUNCTION, writeFunction); curl_easy_setopt(curl_easy_handle, CURLOPT_TIMEOUT_MS, deadline - current_time()); - if ((ipversion == CURL_IPRESOLVE_V4) || (ipversion == CURL_IPRESOLVE_V6)) - { - NMLOG_DEBUG("curlopt ipversion = %s reqtyp = %s", ipversion == CURL_IPRESOLVE_V4?"IPv4":"IPv6", headReq? "HEAD":"GET"); - curl_easy_setopt(curl_easy_handle, CURLOPT_IPRESOLVE, ipversion); + if (IP_ADDRESS_V4 == ipversion) { + curl_easy_setopt(curl_easy_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + NMLOG_DEBUG("curlopt ipversion = IPv4 reqtyp = %s", headReq? "HEAD":"GET"); + } + else if (IP_ADDRESS_V6 == ipversion) { + curl_easy_setopt(curl_easy_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); + NMLOG_DEBUG("curlopt ipversion = IPv6 reqtyp = %s", headReq? "HEAD":"GET"); } else - { NMLOG_DEBUG("curlopt ipversion = whatever reqtyp = %s", headReq? "HEAD":"GET"); - } + if(curlVerboseEnabled()) curl_easy_setopt(curl_easy_handle, CURLOPT_VERBOSE, 1L); if (CURLM_OK != (mc = curl_multi_add_handle(curl_multi_handle, curl_easy_handle))) @@ -205,8 +356,10 @@ namespace WPEFramework } } } - else + else { NMLOG_ERROR("endpoint = <%s> curl error = %d (%s)", endpoint, msg->data.result, curl_easy_strerror(msg->data.result)); + curlErrorCode = static_cast(msg->data.result); + } http_responses.push_back(response_code); } time_earlier = time_now; @@ -264,9 +417,9 @@ namespace WPEFramework * Return Internet State: FULLY_CONNECTED - 50 % */ - nsm_internetState TestConnectivity::checkInternetStateFromResponseCode(const std::vector& responses) + Exchange::INetworkManager::InternetStatus TestConnectivity::checkInternetStateFromResponseCode(const std::vector& responses) { - nsm_internetState InternetConnectionState = NO_INTERNET; + Exchange::INetworkManager::InternetStatus InternetConnectionState = INTERNET_NOT_AVAILABLE; nsm_connectivity_httpcode http_response_code = HttpStatus_response_error; int max_count = 0; @@ -289,20 +442,20 @@ namespace WPEFramework switch (http_response_code) { case HttpStatus_204_No_Content: - InternetConnectionState = FULLY_CONNECTED; + InternetConnectionState = INTERNET_FULLY_CONNECTED; NMLOG_INFO("Internet State: FULLY_CONNECTED - %.1f%%", (percentage*100)); break; case HttpStatus_200_OK: - InternetConnectionState = LIMITED_INTERNET; + InternetConnectionState = INTERNET_LIMITED; NMLOG_INFO("Internet State: LIMITED_INTERNET - %.1f%%", (percentage*100)); break; case HttpStatus_511_Authentication_Required: case HttpStatus_302_Found: - InternetConnectionState = CAPTIVE_PORTAL; + InternetConnectionState = INTERNET_CAPTIVE_PORTAL; NMLOG_INFO("Internet State: CAPTIVE_PORTAL - %.1f%%", (percentage*100)); break; default: - InternetConnectionState = NO_INTERNET; + InternetConnectionState = INTERNET_NOT_AVAILABLE; if(http_response_code == -1) NMLOG_ERROR("Internet State: NO_INTERNET (curl error)"); else @@ -315,202 +468,111 @@ namespace WPEFramework ConnectivityMonitor::ConnectivityMonitor() { - if(endpointCache.isEndpointCashFileExist()) - { - std::vector cachedEndPnt = endpointCache.readEnpointsFromFile(); - setConnectivityMonitorEndpoints(cachedEndPnt); - NMLOG_WARNING("cached connectivity endpoints loaded .."); - } - - doContinuousMonitor = false; - doConnectivityMonitor = false; - m_InternetState = nsm_internetState::UNKNOWN; - m_Ipv4InternetState = nsm_internetState::UNKNOWN; - m_Ipv6InternetState = nsm_internetState::UNKNOWN; + NMLOG_WARNING("ConnectivityMonitor"); + m_cmRunning = false; + m_notify = true; + m_InternetState = INTERNET_UNKNOWN; + m_Ipv4InternetState = INTERNET_UNKNOWN; + m_Ipv6InternetState = INTERNET_UNKNOWN; + startConnectivityMonitor(); } ConnectivityMonitor::~ConnectivityMonitor() { NMLOG_WARNING("~ConnectivityMonitor"); - doContinuousMonitor = false; - doConnectivityMonitor = false; - cvConnectivityMonitor.notify_one(); - cvContinuousMonitor.notify_one(); - if (continuousMonitorThrd.joinable()) - continuousMonitorThrd.join(); - if (connectivityMonitorThrd.joinable()) - connectivityMonitorThrd.join(); + stopConnectivityMonitor(); } std::vector ConnectivityMonitor::getConnectivityMonitorEndpoints() { - const std::lock_guard lock(endpointMutex); - std::vector endpoints; - for (auto endpoint : connectivityMonitorEndpt) { - endpoints.push_back(endpoint); - } - return endpoints; + return m_endpoint.getConnectivityMonitorEndpoints(); } void ConnectivityMonitor::setConnectivityMonitorEndpoints(const std::vector &endpoints) { - const std::lock_guard lock(endpointMutex); - connectivityMonitorEndpt.clear(); - for (auto endpoint : endpoints) { - if(!endpoint.empty() && endpoint.size() > 3) - connectivityMonitorEndpt.push_back(endpoint.c_str()); - else - NMLOG_ERROR("endpoint not vallied = %s", endpoint.c_str()); - } - - // write the endpoints to a file - endpointCache.writeEnpointsToFile(connectivityMonitorEndpt); - - std::string endpointsStr; - for (const auto& endpoint : connectivityMonitorEndpt) - endpointsStr.append(endpoint).append(" "); - NMLOG_INFO("Connectivity monitor endpoints -: %d :- %s", static_cast(connectivityMonitorEndpt.size()), endpointsStr.c_str()); - } - - bool ConnectivityMonitor::isConnectedToInternet(nsm_ipversion ipversion) - { - if (nsm_internetState::FULLY_CONNECTED == getInternetState(ipversion)) - { - NMLOG_INFO("isConnectedToInternet %s = true", (ipversion == nsm_ipversion::NSM_IPRESOLVE_WHATEVER)?"":(ipversion == nsm_ipversion::NSM_IPRESOLVE_V4? "IPv4":"IPv6")); - return true; - } - NMLOG_WARNING("isConnectedToInternet %s = false",(ipversion == nsm_ipversion::NSM_IPRESOLVE_WHATEVER)?"":(ipversion == nsm_ipversion::NSM_IPRESOLVE_V4? "IPv4":"IPv6") ); - return false; + m_endpoint.setConnectivityMonitorEndpoints(endpoints); } - nsm_internetState ConnectivityMonitor::getInternetState(nsm_ipversion& ipversion) + Exchange::INetworkManager::InternetStatus ConnectivityMonitor::getInternetState(Exchange::INetworkManager::IPVersion& ipversion, bool ipVersionNotSpecified) { - nsm_internetState internetState = nsm_internetState::UNKNOWN; - // If monitor connectivity is running take the cache value - - if ( doContinuousMonitor && (nsm_ipversion::NSM_IPRESOLVE_V4 == ipversion || nsm_ipversion::NSM_IPRESOLVE_WHATEVER == ipversion) - && m_Ipv4InternetState != nsm_internetState::UNKNOWN ) { - NMLOG_WARNING("Reading Ipv4 internet state cached value %s", getInternetStateString(m_Ipv4InternetState)); - internetState = m_Ipv4InternetState; - ipversion = NSM_IPRESOLVE_V4; - } - else if ( doContinuousMonitor && (nsm_ipversion::NSM_IPRESOLVE_V6 == ipversion || nsm_ipversion::NSM_IPRESOLVE_WHATEVER == ipversion) - && m_Ipv6InternetState != nsm_internetState::UNKNOWN ) { - NMLOG_WARNING("Reading Ipv6 internet state cached value %s", getInternetStateString(m_Ipv6InternetState)); - internetState = m_Ipv6InternetState; - ipversion = NSM_IPRESOLVE_V6; + if(ipVersionNotSpecified) { + ipversion = m_ipversion; + NMLOG_DEBUG("ipversion %s - %s", ipversion == IP_ADDRESS_V4? "IPv4":"IPv6", getInternetStateString(m_InternetState.load())); + return m_InternetState.load(); } + else if(ipversion == IP_ADDRESS_V4) + return m_Ipv4InternetState.load(); + else if(ipversion == IP_ADDRESS_V6) + return m_Ipv6InternetState.load(); else - { - TestConnectivity testInternet(getConnectivityMonitorEndpoints(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, NMCONNECTIVITY_CURL_GET_REQUEST, ipversion); - internetState = testInternet.getInternetState(); - // TODO : Lets not hard code here. - ipversion = NSM_IPRESOLVE_V4; - } - return internetState; + return INTERNET_UNKNOWN; } std::string ConnectivityMonitor::getCaptivePortalURI() { - TestConnectivity testInternet(getConnectivityMonitorEndpoints(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, NMCONNECTIVITY_CURL_GET_REQUEST, NSM_IPRESOLVE_WHATEVER); - if(nsm_internetState::CAPTIVE_PORTAL == testInternet.getInternetState()) + if(m_Ipv4InternetState == INTERNET_CAPTIVE_PORTAL || m_Ipv6InternetState == INTERNET_CAPTIVE_PORTAL) { - NMLOG_WARNING("captive portal URI = %s", testInternet.getCaptivePortal().c_str()); - return testInternet.getCaptivePortal(); + NMLOG_INFO("captive portal URI = %s", m_captiveURI.c_str()); + return m_captiveURI; } + NMLOG_WARNING("No captive portal found !"); return std::string(""); } - bool ConnectivityMonitor::startContinuousConnectivityMonitor(int timeoutInSeconds) + bool ConnectivityMonitor::startConnectivityMonitor() { - if(_instance != nullptr ) - NMLOG_INFO("interface status eth - %s wlan - %s ", _instance->m_ethConnected? "up":"down", _instance->m_wlanConnected? "up":"down"); - continuousMonitorTimeout.store(timeoutInSeconds >= NMCONNECTIVITY_MONITOR_MIN_INTERVAL ? timeoutInSeconds : NMCONNECTIVITY_MONITOR_DEFAULT_INTERVAL); - if (doContinuousMonitor) + if (m_cmRunning) { - if(doConnectivityMonitor) - { - NMLOG_INFO("continuous monitor new timeout updated %d Sec", continuousMonitorTimeout.load()); - } - else - { - NMLOG_INFO("continuous monitor restarted with %d Sec", continuousMonitorTimeout.load()); - cvContinuousMonitor.notify_one(); - } + m_cmCv.notify_one(); + NMLOG_DEBUG("connectivity monitor is already running"); return true; } - if (continuousMonitorThrd.joinable()) { - NMLOG_WARNING("continuous monitor joinable thread running"); - doContinuousMonitor = false; - continuousMonitorThrd.join(); - } + m_cmRunning = true; + m_cmThrdID = std::thread(&ConnectivityMonitor::connectivityMonitorFunction, this); - doContinuousMonitor = true; - continuousMonitorThrd = std::thread(&ConnectivityMonitor::continuousMonitorFunction, this); - NMLOG_INFO("continuous connectivity monitor started with %d Sec", continuousMonitorTimeout.load()); - if(!continuousMonitorThrd.joinable()) { - NMLOG_ERROR("continuous connectivity monitor start Failed"); - return false; + if(_instance != nullptr) { + NMLOG_INFO("connectivity monitor started - eth %s - wlan %s", + _instance->m_ethConnected? "up":"down", _instance->m_wlanConnected? "up":"down"); } + + NMLOG_INFO("connectivity monitor is started"); return true; } - bool ConnectivityMonitor::stopContinuousConnectivityMonitor() + bool ConnectivityMonitor::stopConnectivityMonitor() { - doContinuousMonitor = false; - cvContinuousMonitor.notify_one(); - if (continuousMonitorThrd.joinable()) - continuousMonitorThrd.join(); - NMLOG_INFO("continuous connectivity monitor stopped"); + m_cmRunning = false; + m_cmCv.notify_one(); + if(m_cmThrdID.joinable()) + m_cmThrdID.join(); + m_InternetState = INTERNET_UNKNOWN; + m_Ipv4InternetState = INTERNET_UNKNOWN; + m_Ipv6InternetState = INTERNET_UNKNOWN; + NMLOG_INFO("connectivity monitor stoped !!!"); return true; } - /* - * - * call startConnectivityMonitor function - * --> when IP address accuired - * --> when etherenet/wifi disconnected - */ - bool ConnectivityMonitor::startConnectivityMonitor() + bool ConnectivityMonitor::switchToInitialCheck() { - m_InternetState = nsm_internetState::UNKNOWN; - m_Ipv4InternetState = nsm_internetState::UNKNOWN; - m_Ipv6InternetState = nsm_internetState::UNKNOWN; - if (doConnectivityMonitor) - { - cvConnectivityMonitor.notify_one(); - NMLOG_DEBUG("trigger connectivity monitor thread"); - return true; - } - - if (connectivityMonitorThrd.joinable()) { // cleanup of previous thread - doConnectivityMonitor = false; - connectivityMonitorThrd.join(); - } - - doConnectivityMonitor = true; - connectivityMonitorThrd = std::thread(&ConnectivityMonitor::connectivityMonitorFunction, this); - if(!connectivityMonitorThrd.joinable()) { - NMLOG_ERROR("connectivity monitor start failed"); - return false; - } - + m_switchToInitial = true; + m_notify = true; // m_notify internet state because some network state change may happen + m_cmCv.notify_one(); if(_instance != nullptr) { - NMLOG_INFO("connectivity monitor started %d sec - eth %s - wlan %s", NMCONNECTIVITY_MONITOR_MIN_INTERVAL, - _instance->m_ethConnected? "up":"down", _instance->m_wlanConnected? "up":"down"); + NMLOG_INFO("switching to initial check - eth %s - wlan %s", + _instance->m_ethConnected? "up":"down", _instance->m_wlanConnected? "up":"down"); } return true; } - void ConnectivityMonitor::notifyInternetStatusChangedEvent(nsm_internetState newInternetState) + void ConnectivityMonitor::notifyInternetStatusChangedEvent(Exchange::INetworkManager::InternetStatus newInternetState) { - static Exchange::INetworkManager::InternetStatus oldState = Exchange::INetworkManager::InternetStatus::INTERNET_UNKNOWN; + static Exchange::INetworkManager::InternetStatus oldState = INTERNET_UNKNOWN; if(_instance != nullptr) { - NMLOG_INFO("notify internet state %s", getInternetStateString(newInternetState)); - Exchange::INetworkManager::InternetStatus newState = static_cast(newInternetState); + NMLOG_INFO("notifying internet state %s", getInternetStateString(newInternetState)); + Exchange::INetworkManager::InternetStatus newState = newInternetState; _instance->ReportInternetStatusChange(oldState , newState); m_InternetState = newInternetState; oldState = newState; // 'm_InternetState' not exactly previous state, it may change to unknow when interface changed @@ -519,223 +581,181 @@ namespace WPEFramework NMLOG_FATAL("NetworkManagerImplementation Instance NULL notifyInternetStatusChange failed."); } - void ConnectivityMonitor::continuousMonitorFunction() + void ConnectivityMonitor::connectivityMonitorFunction() { - int TempInterval = continuousMonitorTimeout.load(); - std::mutex connMutex; - nsm_ipversion ipResolveTyp = NSM_IPRESOLVE_WHATEVER; - int notifyPreRetry = 1; - nsm_internetState currentInternetState = nsm_internetState::UNKNOWN; - - do - { - if(_instance != nullptr && (!_instance->m_ethConnected && !_instance->m_wlanConnected)) // no wifi no ethernet connected - { - NMLOG_DEBUG("no interface connected; no ccm check"); - m_Ipv4InternetState = NO_INTERNET; - m_Ipv6InternetState = NO_INTERNET; - std::unique_lock lock(connMutex); - cvContinuousMonitor.wait_for(lock, std::chrono::seconds(continuousMonitorTimeout.load())); - ipResolveTyp = NSM_IPRESOLVE_WHATEVER; - continue; + int timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; + Exchange::INetworkManager::InternetStatus currentInternetState = INTERNET_NOT_AVAILABLE; + int InitialRetryCount = 0; + int IdealRetryCount = 0; + m_switchToInitial = true; + m_InternetState = INTERNET_UNKNOWN; + m_Ipv4InternetState = INTERNET_UNKNOWN; + m_Ipv6InternetState = INTERNET_UNKNOWN; + m_notify = true; + + while (m_cmRunning) { + // Check if no interfaces are connected + if (_instance != nullptr && !_instance->m_ethConnected && !_instance->m_wlanConnected) { + NMLOG_DEBUG("no interface connected, no ccm check"); + timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; + m_InternetState = INTERNET_NOT_AVAILABLE; + m_Ipv4InternetState = INTERNET_NOT_AVAILABLE; + m_Ipv6InternetState = INTERNET_NOT_AVAILABLE; + currentInternetState = INTERNET_NOT_AVAILABLE; + if (InitialRetryCount == 0) + m_notify = true; + InitialRetryCount = 1; } - - if(doConnectivityMonitor) - { - NMLOG_DEBUG("connectivity monitor running so skiping ccm check"); - m_Ipv4InternetState = nsm_internetState::UNKNOWN; - m_Ipv6InternetState = nsm_internetState::UNKNOWN; - std::unique_lock lock(connMutex); - cvContinuousMonitor.wait_for(lock, std::chrono::seconds(continuousMonitorTimeout.load())); - ipResolveTyp = NSM_IPRESOLVE_WHATEVER; /* some interface change happense */ - continue; - } - else if (ipResolveTyp == NSM_IPRESOLVE_WHATEVER) + else if (m_switchToInitial) { - nsm_internetState ipV4InternetState = nsm_internetState::UNKNOWN; - nsm_internetState ipV6InternetState = nsm_internetState::UNKNOWN; + NMLOG_INFO("Initial cm check - retry count %d - %s", InitialRetryCount, getInternetStateString(currentInternetState)); + timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; + + // Lambda functions to check connectivity for IPv4 and IPv6 auto curlCheckThrdIpv4 = [&]() { - TestConnectivity testInternet(getConnectivityMonitorEndpoints(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, - NMCONNECTIVITY_CURL_GET_REQUEST, NSM_IPRESOLVE_V4); - ipV4InternetState = testInternet.getInternetState(); + TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, + NMCONNECTIVITY_CURL_HEAD_REQUEST, IP_ADDRESS_V4); + m_Ipv4InternetState = testInternet.getInternetState(); + if(m_Ipv6InternetState == INTERNET_CAPTIVE_PORTAL) + m_captiveURI = testInternet.getCaptivePortal(); }; auto curlCheckThrdIpv6 = [&]() { - TestConnectivity testInternet(getConnectivityMonitorEndpoints(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, - NMCONNECTIVITY_CURL_GET_REQUEST, NSM_IPRESOLVE_V6); - ipV6InternetState = testInternet.getInternetState(); + TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, + NMCONNECTIVITY_CURL_HEAD_REQUEST, IP_ADDRESS_V6); + m_Ipv6InternetState = testInternet.getInternetState(); + if(m_Ipv6InternetState == INTERNET_CAPTIVE_PORTAL) + m_captiveURI = testInternet.getCaptivePortal(); }; + + // Start threads for IPv4 and IPv6 checks std::thread ipv4thread(curlCheckThrdIpv4); std::thread ipv6thread(curlCheckThrdIpv6); + // Wait for both threads to finish ipv4thread.join(); ipv6thread.join(); - if(ipV4InternetState == FULLY_CONNECTED) { - ipResolveTyp = NSM_IPRESOLVE_V4; - currentInternetState = ipV4InternetState; - NMLOG_INFO("connectivity monitor default ip resolve IPV4"); - } - else if(ipV6InternetState == FULLY_CONNECTED) { - ipResolveTyp = NSM_IPRESOLVE_V6; - currentInternetState = ipV6InternetState; - NMLOG_INFO("connectivity monitor default ip resolve IPV6"); - } - else /* not changing ip resolve type */ - currentInternetState = ipV4InternetState; - } - else /* IPV4 or IPV6 based on default values */ - { - TestConnectivity testInternet(getConnectivityMonitorEndpoints(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, - NMCONNECTIVITY_CURL_HEAD_REQUEST, ipResolveTyp); - currentInternetState = testInternet.getInternetState(); - if(ipResolveTyp == NSM_IPRESOLVE_V4) - m_Ipv4InternetState = currentInternetState; - else if(ipResolveTyp == NSM_IPRESOLVE_V6) - m_Ipv6InternetState = currentInternetState; - } - if (currentInternetState == NO_INTERNET) - { - if(m_InternetState == FULLY_CONNECTED && notifyPreRetry < NMCONNECTIVITY_NO_INTERNET_RETRY_COUNT) - { - /* it will prevent posting notification */ - currentInternetState = m_InternetState; - TempInterval = 5; - NMLOG_INFO("No internet retrying connection check %d ...", notifyPreRetry); - notifyPreRetry++; - /* no internet state retry do it in ipv4 and ipv6 sepratly in two thread */ - ipResolveTyp = NSM_IPRESOLVE_WHATEVER; + // Determine the current internet state based on the results + if (m_Ipv4InternetState == INTERNET_NOT_AVAILABLE && m_Ipv6InternetState == INTERNET_NOT_AVAILABLE) { + currentInternetState = INTERNET_NOT_AVAILABLE; + if (InitialRetryCount == 0) + m_notify = true; + InitialRetryCount = 1; // continue same check for 5 sec + } else { + if (m_Ipv4InternetState == INTERNET_FULLY_CONNECTED || m_Ipv6InternetState == INTERNET_FULLY_CONNECTED) + { + currentInternetState = INTERNET_FULLY_CONNECTED; + m_ipversion = (m_Ipv4InternetState == INTERNET_FULLY_CONNECTED) ? IP_ADDRESS_V4 : IP_ADDRESS_V6; + } + else if (m_Ipv4InternetState == INTERNET_CAPTIVE_PORTAL || m_Ipv6InternetState == INTERNET_CAPTIVE_PORTAL) + { + currentInternetState = INTERNET_CAPTIVE_PORTAL; + m_ipversion = (m_Ipv4InternetState == INTERNET_CAPTIVE_PORTAL) ? IP_ADDRESS_V4 : IP_ADDRESS_V6; + } else if (m_Ipv4InternetState == INTERNET_LIMITED || m_Ipv6InternetState == INTERNET_LIMITED) { + currentInternetState = INTERNET_LIMITED; + m_ipversion = (m_Ipv4InternetState == INTERNET_LIMITED) ? IP_ADDRESS_V4 : IP_ADDRESS_V6; + } else { + currentInternetState = INTERNET_NOT_AVAILABLE; + m_ipversion = IP_ADDRESS_V4; + } + + if (InitialRetryCount == 0) + m_notify = true; + + if (currentInternetState != m_InternetState) { + NMLOG_DEBUG("initial connectivity state change %s", getInternetStateString(m_InternetState)); + m_InternetState = currentInternetState; + InitialRetryCount = 1; // reset retry count to get continuous 3 same state + } + InitialRetryCount++; } - else - { - notifyPreRetry = 1; - TempInterval = continuousMonitorTimeout.load(); + + if (InitialRetryCount > NM_CONNECTIVITY_MONITOR_RETRY_COUNT) { + m_switchToInitial = false; + m_notify = true; + InitialRetryCount = 0; + IdealRetryCount = 0; } } + // Ideal case monitoring else { - notifyPreRetry = 1; - TempInterval = continuousMonitorTimeout.load(); - } - - if(m_InternetState != currentInternetState) - { - /* Notify Internet state change */ - notifyInternetStatusChangedEvent(currentInternetState); - } - - //NMLOG_INFO("icm %d, ccm %d", doConnectivityMonitor.load(), doContinuousMonitor.load()); - if(!doContinuousMonitor) - break; - /* wait for next interval */ - std::unique_lock lock(connMutex); - if (cvContinuousMonitor.wait_for(lock, std::chrono::seconds(TempInterval)) != std::cv_status::timeout) - NMLOG_INFO("continous connectivity monitor recieved signal. skping %d sec interval", TempInterval); + timeoutInSec = NMCONNECTIVITY_MONITOR_RETRY_INTERVAL; + InitialRetryCount = 0; - } while(doContinuousMonitor); - - m_Ipv4InternetState = nsm_internetState::UNKNOWN; - m_Ipv6InternetState = nsm_internetState::UNKNOWN; - NMLOG_DEBUG("continous connectivity monitor exit"); - } + TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, + NMCONNECTIVITY_CURL_HEAD_REQUEST, m_ipversion); + currentInternetState = testInternet.getInternetState(); - void ConnectivityMonitor::connectivityMonitorFunction() - { - int TempInterval = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; - std::mutex connMutex; - bool notifyNow = true; - int notifyPreRetry = 1; - nsm_internetState currentInternetState = nsm_internetState::UNKNOWN; - nsm_internetState tempInternetState = nsm_internetState::UNKNOWN; - - do - { - TestConnectivity testInternet(getConnectivityMonitorEndpoints(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, - NMCONNECTIVITY_CURL_GET_REQUEST, NSM_IPRESOLVE_WHATEVER); - currentInternetState = testInternet.getInternetState(); - if(currentInternetState == CAPTIVE_PORTAL) - { - /* set to every 30 sec interval */ - TempInterval = NMCONNECTIVITY_CONN_MONITOR_RETRY_INTERVAL; - } - else if(currentInternetState == LIMITED_INTERNET) - { - TempInterval = NMCONNECTIVITY_CONN_MONITOR_RETRY_INTERVAL; - } - else // fullyconnect / noInternet - { - if(notifyPreRetry <= NMCONNECTIVITY_CONN_MONITOR_RETRY_COUNT - 1) - { - if(tempInternetState != currentInternetState ) // check for continous same state - { - tempInternetState = currentInternetState; - notifyPreRetry = 1; - NMLOG_INFO("Connectivity check retrying %d ...", notifyPreRetry); - } - else - { - notifyPreRetry++; - NMLOG_INFO("Connectivity check retrying %d ...", notifyPreRetry); - } + if (currentInternetState == INTERNET_CAPTIVE_PORTAL) // if captive portal found copy the URL + m_captiveURI = testInternet.getCaptivePortal(); - if(m_InternetState != nsm_internetState::UNKNOWN) - currentInternetState = m_InternetState; - TempInterval = 5; - } - else if(tempInternetState != currentInternetState) // last state have change + if (currentInternetState != m_InternetState) { - tempInternetState = currentInternetState; - notifyPreRetry = 1; - TempInterval = 5; - NMLOG_INFO("Connectivity check retrying %d ...", notifyPreRetry); - } - else - { - if(currentInternetState == FULLY_CONNECTED) - { - doConnectivityMonitor = false; // self exit - notifyNow = true; // post current state when retry complete - } - else if(_instance != nullptr && (_instance->m_ethConnected | _instance->m_wlanConnected)) + if (currentInternetState == INTERNET_NOT_AVAILABLE && m_InternetState == INTERNET_FULLY_CONNECTED) { - /* interface is connected and still no internet, continue check every 30 sec */ - TempInterval = NMCONNECTIVITY_CONN_MONITOR_RETRY_INTERVAL; - /* notify if retry completed and state stil no internet state */ - if(notifyPreRetry == NMCONNECTIVITY_CONN_MONITOR_RETRY_COUNT) + DnsResolver dnsResolver(getConnectivityMonitorEndpoints()[0], m_ipversion, testInternet.getCurlError() ); // only first endpoint with specific ipversion + if (dnsResolver()) { + NMLOG_INFO("DNS resolved, success !!!"); + IdealRetryCount = 0; + currentInternetState = INTERNET_FULLY_CONNECTED; + } + else { - notifyPreRetry++; - notifyNow = true; + NMLOG_WARNING("DNS resolve failed !!!"); + timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; // retry in 5 sec + IdealRetryCount++; + if (IdealRetryCount >= NM_CONNECTIVITY_MONITOR_RETRY_COUNT) { + IdealRetryCount = 0; + m_InternetState = INTERNET_NOT_AVAILABLE; + m_Ipv4InternetState = INTERNET_NOT_AVAILABLE; + m_Ipv6InternetState = INTERNET_NOT_AVAILABLE; // reset all states to NO_INTERNET + currentInternetState = INTERNET_NOT_AVAILABLE; + m_switchToInitial = true; // switch to initial check after 3 retries + InitialRetryCount = 1; // reset initial retry count it will not post the event + m_notify = true; + NMLOG_DEBUG("No internet retrying completed notifying !!!"); + } else { + NMLOG_INFO("No internet retrying connection check %d ...", IdealRetryCount); + } } + } else { + // a state change happened but it is not fully connected to no internet + // switch to initial check to get the correct state + m_switchToInitial = true; + InitialRetryCount = 0; + IdealRetryCount = 0; + timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; // retry in 5 sec + + if (m_ipversion == IP_ADDRESS_V4) + m_Ipv4InternetState = currentInternetState; + else if (m_ipversion == IP_ADDRESS_V6) + m_Ipv6InternetState = currentInternetState; + else + m_InternetState = currentInternetState; } - else // no interface connected - { - doConnectivityMonitor = false; - notifyNow = true; - } + } else { // ideal case no change in network state + IdealRetryCount = 0; + m_InternetState = currentInternetState; } } - if(m_InternetState != currentInternetState || notifyNow) - { - notifyNow = false; - notifyInternetStatusChangedEvent(currentInternetState); + if (m_notify) { + m_InternetState = currentInternetState; + notifyInternetStatusChangedEvent(m_InternetState); + m_notify = false; } - if(!doConnectivityMonitor) + if (!m_cmRunning) break; - /* wait for next interval */ - std::unique_lock lock(connMutex); - if (cvConnectivityMonitor.wait_for(lock, std::chrono::seconds(TempInterval)) != std::cv_status::timeout) { - NMLOG_INFO("connectivity monitor recieved signal. skping %d sec interval", TempInterval); - notifyPreRetry = 1; - notifyNow = true; // new signal came should notify in next check - } - - } while(doConnectivityMonitor); - if(!doContinuousMonitor) - m_InternetState = nsm_internetState::UNKNOWN; // no continous monitor running reset to unknow - NMLOG_DEBUG("initial connectivity monitor exit"); + // Wait for next interval + std::unique_lock lock(m_cmMutex); + if (m_cmCv.wait_for(lock, std::chrono::seconds(timeoutInSec)) != std::cv_status::timeout) { + NMLOG_INFO("connectivity monitor received signal. skipping %d sec interval", timeoutInSec); + } + } } } // namespace Plugin diff --git a/NetworkManagerConnectivity.h b/NetworkManagerConnectivity.h index e98400352..38e12ebb6 100644 --- a/NetworkManagerConnectivity.h +++ b/NetworkManagerConnectivity.h @@ -19,35 +19,16 @@ #pragma once -#include #include #include #include -#include -#include -#include #include #include #include #include #include -#include -#include -enum nsm_ipversion -{ - NSM_IPRESOLVE_WHATEVER = 0, /* default, resolves addresses to all IP*/ - NSM_IPRESOLVE_V4 = 1, /* resolve to IPv4 addresses */ - NSM_IPRESOLVE_V6 = 2 /* resolve to IPv6 addresses */ -}; - -enum nsm_internetState { - NO_INTERNET, - LIMITED_INTERNET, - CAPTIVE_PORTAL, - FULLY_CONNECTED, - UNKNOWN, -}; +#include "INetworkManager.h" enum nsm_connectivity_httpcode { HttpStatus_response_error = 99, @@ -64,30 +45,50 @@ enum nsm_connectivity_httpcode { #define NMCONNECTIVITY_CURL_HEAD_REQUEST true #define NMCONNECTIVITY_CURL_GET_REQUEST false - -#define NMCONNECTIVITY_MONITOR_DEFAULT_INTERVAL 60 // sec -#define NMCONNECTIVITY_MONITOR_MIN_INTERVAL 5 // sec -#define NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS 5000 // ms -#define NMCONNECTIVITY_NO_INTERNET_RETRY_COUNT 4 // 4 retry -#define NMCONNECTIVITY_CONN_MONITOR_RETRY_COUNT 3 // 3 retry -#define NMCONNECTIVITY_CAPTIVE_MONITOR_INTERVAL 30 // sec -#define NMCONNECTIVITY_CONN_MONITOR_RETRY_INTERVAL 30 // sec +#define NMCONNECTIVITY_MONITOR_CACHE_FILE "/tmp/nm.plugin.endpoints" +#define NMCONNECTIVITY_MONITOR_MIN_INTERVAL 5 // sec +#define NMCONNECTIVITY_MONITOR_RETRY_INTERVAL 30 // sec +#define NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS 5000 // ms +#define NM_CONNECTIVITY_MONITOR_RETRY_COUNT 3 // 3 retry namespace WPEFramework { namespace Plugin { - /* save user specific endponint in to a chache file and load form the file if monitorEndpoints are empty case wpeframework restared */ - class EndpointCache { + + class DnsResolver + { public: - bool isEndpointCashFileExist(); - void writeEnpointsToFile(const std::vector& endpoints); - std::vector readEnpointsFromFile(); + DnsResolver(std::string url, Exchange::INetworkManager::IPVersion ipversion, int curlErrorCode); + ~DnsResolver(){}; + bool operator()() { return (ipv6Resolved || ipv4Resolved);} - EndpointCache() : CachefilePath("/tmp/nm.plugin.endpoints") {} - ~EndpointCache(){} private: - std::string CachefilePath; + std::string m_domain{}; + bool ipv4Resolved = false; + bool ipv6Resolved = false; + std::string convertUrIToDomainName(std::string& url); + bool resolveIP(std::string& uri, Exchange::INetworkManager::IPVersion& ipversion); + }; + + /* + * Save user specific endpoint into a cache file and load from the file + * if endpoints are empty in case plugin is restarted. + */ + class EndpointManager { + public: + EndpointManager(); + ~EndpointManager() {} + void writeEndpointsToFile(const std::vector& endpoints); + std::vector readEndpointsFromFile(); + void setConnectivityMonitorEndpoints(const std::vector& endpoints); + std::vector getConnectivityMonitorEndpoints(); + std::vector operator()() { return getConnectivityMonitorEndpoints(); } + + private: + std::string m_CachefilePath; + std::vector m_Endpoints; + std::mutex m_endpointMutex; }; class TestConnectivity @@ -96,15 +97,17 @@ namespace WPEFramework const TestConnectivity& operator=(const TestConnectivity&) = delete; public: - TestConnectivity(const std::vector& endpoints, long timeout_ms = 2000, bool = true, nsm_ipversion ipversion = NSM_IPRESOLVE_WHATEVER); + TestConnectivity(const std::vector& endpoints, long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion); ~TestConnectivity(){} std::string getCaptivePortal() {return captivePortalURI;} - nsm_internetState getInternetState(){return internetSate;} + Exchange::INetworkManager::InternetStatus getInternetState(){return internetSate;} + int getCurlError(){return curlErrorCode;} private: - nsm_internetState checkCurlResponse(const std::vector& endpoints, long timeout_ms, bool headReq, nsm_ipversion ipversion); - nsm_internetState checkInternetStateFromResponseCode(const std::vector& responses); + Exchange::INetworkManager::InternetStatus checkCurlResponse(const std::vector& endpoints, long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion); + Exchange::INetworkManager::InternetStatus checkInternetStateFromResponseCode(const std::vector& responses); std::string captivePortalURI; - nsm_internetState internetSate; + Exchange::INetworkManager::InternetStatus internetSate; + int curlErrorCode = 0; }; class ConnectivityMonitor @@ -112,37 +115,33 @@ namespace WPEFramework public: ConnectivityMonitor(); ~ConnectivityMonitor(); - bool startContinuousConnectivityMonitor(int timeoutInSeconds); - bool stopContinuousConnectivityMonitor(); + bool stopConnectivityMonitor(); bool startConnectivityMonitor(); + bool switchToInitialCheck(); void setConnectivityMonitorEndpoints(const std::vector &endpoints); std::vector getConnectivityMonitorEndpoints(); - bool isConnectedToInternet(nsm_ipversion ipversion); - nsm_internetState getInternetState(nsm_ipversion& ipversion); + Exchange::INetworkManager::InternetStatus getInternetState(Exchange::INetworkManager::IPVersion& ipversion, bool ipVersionNotSpecified = false); std::string getCaptivePortalURI(); private: ConnectivityMonitor(const ConnectivityMonitor&) = delete; ConnectivityMonitor& operator=(const ConnectivityMonitor&) = delete; void connectivityMonitorFunction(); - void notifyInternetStatusChangedEvent(nsm_internetState newState); + void notifyInternetStatusChangedEvent(Exchange::INetworkManager::InternetStatus newState); /* connectivity monitor */ - std::thread connectivityMonitorThrd; - std::condition_variable cvConnectivityMonitor; - std::atomic continuousMonitorTimeout; - std::atomic doConnectivityMonitor; - std::vector connectivityMonitorEndpt; - /*continuous connectivity monitor */ - std::atomic doContinuousMonitor; - std::thread continuousMonitorThrd; - std::condition_variable cvContinuousMonitor; - void continuousMonitorFunction(); - - EndpointCache endpointCache; - std::mutex endpointMutex; - std::atomic m_InternetState; - std::atomic m_Ipv4InternetState; - std::atomic m_Ipv6InternetState; + std::thread m_cmThrdID; + std::atomic m_cmRunning; + std::condition_variable m_cmCv; + std::mutex m_cmMutex; + std::atomic m_notify; + std::atomic m_switchToInitial; + std::string m_captiveURI; + std::atomic m_InternetState; // IPv4 or IPv6 + std::atomic m_Ipv4InternetState; // IPv4 + std::atomic m_Ipv6InternetState; // IPv6 + std::atomic m_ipversion; // IPv6 + /* manages endpoints */ + EndpointManager m_endpoint; }; } // namespace Plugin } // namespace WPEFramework diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 5719c7184..ee6b36879 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -53,11 +53,11 @@ namespace WPEFramework NetworkManagerImplementation::~NetworkManagerImplementation() { LOG_ENTRY_FUNCTION(); + if(m_registrationThread.joinable()) { m_registrationThread.join(); } - connectivityMonitor.stopContinuousConnectivityMonitor(); } /** @@ -244,27 +244,20 @@ namespace WPEFramework } /* @brief Get Internet Connectivty Status */ - uint32_t NetworkManagerImplementation::IsConnectedToInternet(string &ipversion /* @in */, InternetStatus &result /* @out */) + uint32_t NetworkManagerImplementation::IsConnectedToInternet(string &ipversion /* @inout */, InternetStatus &result /* @out */) { LOG_ENTRY_FUNCTION(); - nsm_internetState isconnected; - nsm_ipversion tmpVersion = NSM_IPRESOLVE_WHATEVER; + Exchange::INetworkManager::IPVersion curlIPversion = Exchange::INetworkManager::IP_ADDRESS_V4; + bool ipVersionNotSpecified = false; if(0 == strcasecmp("IPv4", ipversion.c_str())) - tmpVersion = NSM_IPRESOLVE_V4; + curlIPversion = Exchange::INetworkManager::IP_ADDRESS_V4; else if(0 == strcasecmp("IPv6", ipversion.c_str())) - tmpVersion = NSM_IPRESOLVE_V6; - - isconnected = connectivityMonitor.getInternetState(tmpVersion); - if (FULLY_CONNECTED == isconnected) - result = INTERNET_FULLY_CONNECTED; - else if (CAPTIVE_PORTAL == isconnected) - result = INTERNET_CAPTIVE_PORTAL; - else if (LIMITED_INTERNET == isconnected) - result = INTERNET_LIMITED; + curlIPversion = Exchange::INetworkManager::IP_ADDRESS_V6; else - result = INTERNET_NOT_AVAILABLE; + ipVersionNotSpecified = true; - if (NSM_IPRESOLVE_V6 == tmpVersion) + result = connectivityMonitor.getInternetState(curlIPversion, ipVersionNotSpecified); + if (Exchange::INetworkManager::IP_ADDRESS_V6 == curlIPversion) ipversion = "IPv6"; else ipversion = "IPv4"; @@ -280,26 +273,6 @@ namespace WPEFramework return Core::ERROR_NONE; } - /* @brief Start The Internet Connectivity Monitoring */ - uint32_t NetworkManagerImplementation::StartConnectivityMonitoring(const uint32_t interval/* @in */) - { - LOG_ENTRY_FUNCTION(); - if (connectivityMonitor.startContinuousConnectivityMonitor(interval)) - return Core::ERROR_NONE; - else - return Core::ERROR_GENERAL; - } - - /* @brief Stop The Internet Connectivity Monitoring */ - uint32_t NetworkManagerImplementation::StopConnectivityMonitoring(void) const - { - LOG_ENTRY_FUNCTION(); - if (connectivityMonitor.stopContinuousConnectivityMonitor()) - return Core::ERROR_NONE; - else - return Core::ERROR_GENERAL; - } - /* @brief Get the Public IP used for external world communication */ uint32_t NetworkManagerImplementation::GetPublicIP (string& interface /* @inout */, string &ipversion /* @inout */, string& ipaddress /* @out */) { @@ -614,8 +587,7 @@ namespace WPEFramework m_ethConnected = false; else if(interface == "wlan0") m_wlanConnected = false; - - connectivityMonitor.startConnectivityMonitor(); + connectivityMonitor.switchToInitialCheck(); } /* Only the Ethernet connection status is changing here. The WiFi status is updated in the WiFi state callback. */ @@ -653,6 +625,7 @@ namespace WPEFramework { LOG_ENTRY_FUNCTION(); if (Exchange::INetworkManager::IP_ACQUIRED == status) { + // Switch the connectivity monitor to initial check // if ipaddress is aquired means there should be interface connected if(interface == "eth0") m_ethConnected = true; @@ -665,9 +638,7 @@ namespace WPEFramework else m_defaultInterface = interface; - // Start the connectivity monitor with 'true' to indicate the interface is up. - // The monitor will conntinoue even after no internet retry completed, Exit when fully connectd. - connectivityMonitor.startConnectivityMonitor(); + connectivityMonitor.switchToInitialCheck(); } _notificationLock.Lock(); diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 0c1d06459..16fd2f79b 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -224,11 +224,6 @@ namespace WPEFramework /* @brief Get Authentication URL if the device is behind Captive Portal */ uint32_t GetCaptivePortalURI(string &endpoints/* @out */) const override; - /* @brief Start The Internet Connectivity Monitoring */ - uint32_t StartConnectivityMonitoring(const uint32_t interval/* @in */) override; - /* @brief Stop The Internet Connectivity Monitoring */ - uint32_t StopConnectivityMonitoring(void) const override; - /* @brief Get the Public IP used for external world communication */ uint32_t GetPublicIP (string& interface /* @inout */, string &ipversion /* @inout */, string& ipaddress /* @out */) override; diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index f1269af13..55be805be 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -67,8 +67,6 @@ namespace WPEFramework Register("SetConnectivityTestEndpoints", &NetworkManager::SetConnectivityTestEndpoints, this); Register("IsConnectedToInternet", &NetworkManager::IsConnectedToInternet, this); Register("GetCaptivePortalURI", &NetworkManager::GetCaptivePortalURI, this); - Register("StartConnectivityMonitoring", &NetworkManager::StartConnectivityMonitoring, this); - Register("StopConnectivityMonitoring", &NetworkManager::StopConnectivityMonitoring, this); Register("GetPublicIP", &NetworkManager::GetPublicIP, this); Register("Ping", &NetworkManager::Ping, this); Register("Trace", &NetworkManager::Trace, this); @@ -106,8 +104,6 @@ namespace WPEFramework Unregister("SetConnectivityTestEndpoints"); Unregister("IsConnectedToInternet"); Unregister("GetCaptivePortalURI"); - Unregister("StartConnectivityMonitoring"); - Unregister("StopConnectivityMonitoring"); Unregister("GetPublicIP"); Unregister("Ping"); Unregister("Trace"); @@ -503,34 +499,6 @@ namespace WPEFramework returnJson(rc); } - uint32_t NetworkManager::StartConnectivityMonitoring(const JsonObject& parameters, JsonObject& response) - { - LOG_INPARAM(); - uint32_t rc = Core::ERROR_GENERAL; - uint32_t interval = parameters["interval"].Number(); - - NMLOG_DEBUG("connectivity interval = %d", interval); - if (_networkManager) - rc = _networkManager->StartConnectivityMonitoring(interval); - else - rc = Core::ERROR_UNAVAILABLE; - - returnJson(rc); - } - - uint32_t NetworkManager::StopConnectivityMonitoring(const JsonObject& parameters, JsonObject& response) - { - LOG_INPARAM(); - uint32_t rc = Core::ERROR_GENERAL; - - if (_networkManager) - rc = _networkManager->StopConnectivityMonitoring(); - else - rc = Core::ERROR_UNAVAILABLE; - - returnJson(rc); - } - uint32_t NetworkManager::GetPublicIP(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 961193482..4b35e51eb 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -689,7 +689,6 @@ namespace WPEFramework */ getInitialConnectionState(); } - } uint32_t NetworkManagerImplementation::GetAvailableInterfaces (Exchange::INetworkManager::IInterfaceDetailsIterator*& interfacesItr/* @out */) diff --git a/Tests/unit_test/test_NetworkManagerConnectivity.cpp b/Tests/unit_test/test_NetworkManagerConnectivity.cpp index 1b59920f7..2f6cf144f 100644 --- a/Tests/unit_test/test_NetworkManagerConnectivity.cpp +++ b/Tests/unit_test/test_NetworkManagerConnectivity.cpp @@ -29,77 +29,11 @@ class ConnectivityMonitorTest : public ::testing::Test { WPEFramework::Plugin::ConnectivityMonitor cm; }; -TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_Success) { - int timeout = 30; - bool result = cm.startContinuousConnectivityMonitor(timeout); - EXPECT_TRUE(result); -} - -TEST_F(ConnectivityMonitorTest, StartContinuousMonitor_FailureNegativeTimeout) { - int timeout = -1; - bool result = cm.startContinuousConnectivityMonitor(timeout); - EXPECT_TRUE(result); -} - -TEST_F(ConnectivityMonitorTest, StartMonitorWithTimeoutLessThanMinimum) { - int timeout = 3; - bool result = cm.startContinuousConnectivityMonitor(timeout); - EXPECT_TRUE(result); -} - -TEST_F(ConnectivityMonitorTest, MonitorFailsToStart) { - int timeout = 0; - bool result = cm.startContinuousConnectivityMonitor(timeout); - EXPECT_TRUE(result); -} - -TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_WhenStarted) { - int timeout = 30; - cm.startContinuousConnectivityMonitor(timeout); - bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); -} - -TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_WhenNotStarted) { - bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); -} - -TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_AfterMultipleStartsAndStops) { - int timeout = 30; - cm.startContinuousConnectivityMonitor(timeout); - bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); - - cm.startContinuousConnectivityMonitor(timeout); - result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); - - cm.startContinuousConnectivityMonitor(timeout); - result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); -} - -TEST_F(ConnectivityMonitorTest, StopContinuousMonitor_LongRunningMonitor) { - int timeout = 1000; - cm.startContinuousConnectivityMonitor(timeout); - std::this_thread::sleep_for(std::chrono::seconds(2)); - - bool result = cm.stopContinuousConnectivityMonitor(); - EXPECT_TRUE(result); -} - -TEST_F(ConnectivityMonitorTest, StartMonitor_WithInterfaceStatus) { +TEST_F(ConnectivityMonitorTest, StartConnectivityMonitor_Success) { bool result = cm.startConnectivityMonitor(); EXPECT_TRUE(result); -} - -TEST_F(ConnectivityMonitorTest, StartMonitor_NotifyIfAlreadyMonitoring) { - bool result = false; result = cm.startConnectivityMonitor(); EXPECT_TRUE(result); - result = cm.startConnectivityMonitor(); - EXPECT_TRUE(result); } TEST_F(ConnectivityMonitorTest, SetEndpoints_Valid) { @@ -108,12 +42,6 @@ TEST_F(ConnectivityMonitorTest, SetEndpoints_Valid) { EXPECT_EQ(cm.getConnectivityMonitorEndpoints(), endpoints); } -TEST_F(ConnectivityMonitorTest, SetEndpoints_EmptyList) { - std::vector endpoints; - cm.setConnectivityMonitorEndpoints(endpoints); - EXPECT_TRUE(cm.getConnectivityMonitorEndpoints().empty()); -} - TEST_F(ConnectivityMonitorTest, SetEndpoints_InvalidShortEndpoints) { std::vector endpoints = {"ab", "htt", "xyz"}; cm.setConnectivityMonitorEndpoints(endpoints); diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 66203f5f8..3af6eff56 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -87,8 +87,6 @@ NetworkManager interface methods: | [SetConnectivityTestEndpoints](#method.SetConnectivityTestEndpoints) | This method used to set up to 5 endpoints for a connectivity test | | [IsConnectedToInternet](#method.IsConnectedToInternet) | Seeks whether the device has internet connectivity | | [GetCaptivePortalURI](#method.GetCaptivePortalURI) | Gets the captive portal URI if connected to any captive portal network | -| [StartConnectivityMonitoring](#method.StartConnectivityMonitoring) | Enable a continuous monitoring of internet connectivity with heart beat interval thats given | -| [StopConnectivityMonitoring](#method.StopConnectivityMonitoring) | Stops the connectivity monitoring | | [GetPublicIP](#method.GetPublicIP) | Gets the internet/public IP Address of the device | | [Ping](#method.Ping) | Pings the specified endpoint with the specified number of packets | | [Trace](#method.Trace) | Traces the specified endpoint with the specified number of packets using `traceroute` | @@ -404,7 +402,7 @@ Gets the current Status of the specified interface. | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.interface | string | Disable the specified interface | +| params.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | ### Result @@ -686,8 +684,8 @@ This method takes no parameters. | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.endpoints | array | | -| result.endpoints[#] | string | | +| result.endpoints | array | A list of endpoint URLs used | +| result.endpoints[#] | string | The endpoint URL | | result.success | boolean | Whether the request succeeded | ### Example @@ -728,7 +726,7 @@ This method used to set up to 5 endpoints for a connectivity test. Successful co | :-------- | :-------- | :-------- | | params | object | | | params.endpoints | array | A list of endpoints to test | -| params.endpoints[#] | string | | +| params.endpoints[#] | string | The endpoint URL | ### Result @@ -862,94 +860,6 @@ This method takes no parameters. } ``` - -## *StartConnectivityMonitoring [method](#head.Methods)* - -Enable a continuous monitoring of internet connectivity with heart beat interval thats given. If the monitoring is already happening, it will be restarted with new given interval. When the interval is not passed, it will be 60s by default. - -Also see: [onInternetStatusChange](#event.onInternetStatusChange) - -### Parameters - -| Name | Type | Description | -| :-------- | :-------- | :-------- | -| params | object | | -| params?.interval | integer | *(optional)* Interval in sec | - -### Result - -| Name | Type | Description | -| :-------- | :-------- | :-------- | -| result | object | | -| result.success | boolean | Whether the request succeeded | - -### Example - -#### Request - -```json -{ - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.1.StartConnectivityMonitoring", - "params": { - "interval": 30 - } -} -``` - -#### Response - -```json -{ - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } -} -``` - - -## *StopConnectivityMonitoring [method](#head.Methods)* - -Stops the connectivity monitoring. - -### Parameters - -This method takes no parameters. - -### Result - -| Name | Type | Description | -| :-------- | :-------- | :-------- | -| result | object | | -| result.success | boolean | Whether the request succeeded | - -### Example - -#### Request - -```json -{ - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.1.StopConnectivityMonitoring" -} -``` - -#### Response - -```json -{ - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } -} -``` - ## *GetPublicIP [method](#head.Methods)* @@ -1150,7 +1060,7 @@ Also see: [onAvailableSSIDs](#event.onAvailableSSIDs) | params | object | | | params?.frequency | string | *(optional)* The frequency to scan. An empty or `null` value scans all frequencies | | params?.ssids | array | *(optional)* The list of SSIDs to be scanned | -| params?.ssids[#] | string | *(optional)* | +| params?.ssids[#] | string | *(optional)* The SSID to scan | ### Result @@ -1243,8 +1153,8 @@ This method takes no parameters. | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.ssids | array | Known SSIDS | -| result.ssids[#] | string | | +| result.ssids | array | A list of known SSIDs | +| result.ssids[#] | string | The WiFi SSID Name | | result.success | boolean | Whether the request succeeded | ### Example @@ -1284,7 +1194,7 @@ Saves the SSID, passphrase, and security mode for upcoming and future sessions. | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.ssid | string | The paired SSID | +| params.ssid | string | The WiFi SSID Name | | params.passphrase | string | The access point password | | params.security | integer | The security mode. See `getSupportedsecurityModes` | @@ -1305,7 +1215,7 @@ Saves the SSID, passphrase, and security mode for upcoming and future sessions. "id": 42, "method": "org.rdk.NetworkManager.1.AddToKnownSSIDs", "params": { - "ssid": "123412341234", + "ssid": "myHomeSSID", "passphrase": "password", "security": 6 } @@ -1336,7 +1246,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#even | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.ssid | string | The paired SSID | +| params.ssid | string | The WiFi SSID Name | ### Result @@ -1355,7 +1265,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#even "id": 42, "method": "org.rdk.NetworkManager.1.RemoveKnownSSID", "params": { - "ssid": "123412341234" + "ssid": "myHomeSSID" } } ``` @@ -1384,7 +1294,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.ssid | string | The paired SSID | +| params.ssid | string | The WiFi SSID Name | | params.passphrase | string | The access point password | | params.security | integer | The security mode. See `getSupportedsecurityModes` | | params?.ca_cert | string | *(optional)* The ca_cert to be used for EAP | @@ -1415,7 +1325,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) "id": 42, "method": "org.rdk.NetworkManager.1.WiFiConnect", "params": { - "ssid": "123412341234", + "ssid": "myHomeSSID", "passphrase": "password", "security": 6, "ca_cert": "...", @@ -1500,10 +1410,10 @@ This method takes no parameters. | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.ssid | string | The paired SSID | -| result.bssid | string | The paired BSSID | +| result.ssid | string | The WiFi SSID Name | +| result.bssid | string | The BSSID of given SSID | | result.security | string | The security mode. See the `connect` method | -| result.strength | string | The RSSI value in dBm | +| result.strength | string | The Signal RSSI value in dBm | | result.frequency | string | The supported frequency for this SSID in GHz | | result.rate | string | The physical data rate in Mbps | | result.noise | string | The average noise strength in dBm | @@ -1528,8 +1438,8 @@ This method takes no parameters. "jsonrpc": "2.0", "id": 42, "result": { - "ssid": "123412341234", - "bssid": "ff:ff:ff:ff:ff:ff", + "ssid": "myHomeSSID", + "bssid": "AA:BB:CC:DD:EE:FF", "security": "5", "strength": "-27.000000", "frequency": "2.442000", @@ -1658,8 +1568,8 @@ This method takes no parameters. | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.ssid | string | The paired SSID | -| result.strength | string | The RSSI value in dBm | +| result.ssid | string | The WiFi SSID Name | +| result.strength | string | The Signal RSSI value in dBm | | result.quality | string | Signal strength Quality | | result.success | boolean | Whether the request succeeded | @@ -1682,7 +1592,7 @@ This method takes no parameters. "jsonrpc": "2.0", "id": 42, "result": { - "ssid": "123412341234", + "ssid": "myHomeSSID", "strength": "-27.000000", "quality": "Excellent", "success": true @@ -1974,10 +1884,10 @@ Triggered when scan completes or when scan cancelled. | params | object | | | params.ssids | array | On Available SSID's | | params.ssids[#] | object | | -| params.ssids[#].ssid | string | Ssid | -| params.ssids[#].security | integer | Security | -| params.ssids[#].strength | string | Strength | -| params.ssids[#].frequency | string | Frequency | +| params.ssids[#].ssid | string | Discovered SSID | +| params.ssids[#].security | integer | The security mode. See `getSupportedsecurityModes` | +| params.ssids[#].strength | string | The Signal RSSI value in dBm | +| params.ssids[#].frequency | string | The supported frequency for this SSID in GHz | ### Example @@ -2034,9 +1944,9 @@ Triggered when WIFI connection Signal Strength get changed. | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.ssid | string | Signal Strength changed SSID | -| params.strength | string | Signal Strength | -| params.quality | string | Signal quality | +| params.ssid | string | The WiFi SSID Name | +| params.strength | string | The Signal RSSI value in dBm | +| params.quality | string | Signal strength Quality | ### Example @@ -2045,7 +1955,7 @@ Triggered when WIFI connection Signal Strength get changed. "jsonrpc": "2.0", "method": "client.events.1.onWiFiSignalStrengthChange", "params": { - "ssid": "home-new_123", + "ssid": "myHomeSSID", "strength": "-27.000000", "quality": "Excellent" } From d5bae04391f2837607744175c5a9d688a3e29bce Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 22 Jan 2025 14:24:04 -0500 Subject: [PATCH 074/271] RDKEMW-1271 - Address coverity issues (#80) * RDKEMW-1271 - Address coverity issues Reason for change: For addressing the network manager coverity issues Test Procedure: Build and verified with curl commands Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR --- NetworkManagerConnectivity.cpp | 27 ++++++++++++++------------- NetworkManagerConnectivity.h | 10 ++++++++++ NetworkManagerLogger.cpp | 9 --------- NetworkManagerRDKProxy.cpp | 7 +++---- NetworkManagerStunClient.cpp | 4 ++-- WiFiSignalStrengthMonitor.h | 2 +- 6 files changed, 30 insertions(+), 29 deletions(-) diff --git a/NetworkManagerConnectivity.cpp b/NetworkManagerConnectivity.cpp index 8140b2e96..39a19a4d9 100644 --- a/NetworkManagerConnectivity.cpp +++ b/NetworkManagerConnectivity.cpp @@ -17,12 +17,10 @@ * limitations under the License. **/ -#include #include #include #include #include -#include #include #include @@ -106,7 +104,7 @@ namespace WPEFramework } m_Endpoints.clear(); - for (auto endpoint : endpoints) { + for (const auto &endpoint : endpoints) { if(!endpoint.empty() && endpoint.size() > 3) m_Endpoints.push_back(endpoint.c_str()); else @@ -293,31 +291,33 @@ namespace WPEFramework NMLOG_ERROR("endpoint = <%s> curl_easy_init returned NULL", endpoint.c_str()); continue; } - curl_easy_setopt(curl_easy_handle, CURLOPT_URL, endpoint.c_str()); - curl_easy_setopt(curl_easy_handle, CURLOPT_PRIVATE, endpoint.c_str()); + curlSetOpt(curl_easy_handle, CURLOPT_URL, endpoint.c_str()); + curlSetOpt(curl_easy_handle, CURLOPT_PRIVATE, endpoint.c_str()); /* set our custom set of headers */ - curl_easy_setopt(curl_easy_handle, CURLOPT_HTTPHEADER, chunk); - curl_easy_setopt(curl_easy_handle, CURLOPT_USERAGENT, "RDKCaptiveCheck/1.0"); + curlSetOpt(curl_easy_handle, CURLOPT_HTTPHEADER, chunk); + curlSetOpt(curl_easy_handle, CURLOPT_USERAGENT, "RDKCaptiveCheck/1.0"); if(!headReq) { /* HTTPGET request added insted of HTTPHEAD request fix for DELIA-61526 */ - curl_easy_setopt(curl_easy_handle, CURLOPT_HTTPGET, 1L); + curlSetOpt(curl_easy_handle, CURLOPT_HTTPGET, 1L); } - curl_easy_setopt(curl_easy_handle, CURLOPT_WRITEFUNCTION, writeFunction); - curl_easy_setopt(curl_easy_handle, CURLOPT_TIMEOUT_MS, deadline - current_time()); + curlSetOpt(curl_easy_handle, CURLOPT_WRITEFUNCTION, writeFunction); + curlSetOpt(curl_easy_handle, CURLOPT_TIMEOUT_MS, deadline - current_time()); if (IP_ADDRESS_V4 == ipversion) { - curl_easy_setopt(curl_easy_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + curlSetOpt(curl_easy_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); NMLOG_DEBUG("curlopt ipversion = IPv4 reqtyp = %s", headReq? "HEAD":"GET"); } else if (IP_ADDRESS_V6 == ipversion) { - curl_easy_setopt(curl_easy_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); + curlSetOpt(curl_easy_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); NMLOG_DEBUG("curlopt ipversion = IPv6 reqtyp = %s", headReq? "HEAD":"GET"); } else NMLOG_DEBUG("curlopt ipversion = whatever reqtyp = %s", headReq? "HEAD":"GET"); if(curlVerboseEnabled()) - curl_easy_setopt(curl_easy_handle, CURLOPT_VERBOSE, 1L); + { + curlSetOpt(curl_easy_handle, CURLOPT_VERBOSE, 1L); + } if (CURLM_OK != (mc = curl_multi_add_handle(curl_multi_handle, curl_easy_handle))) { NMLOG_ERROR("endpoint = <%s> curl_multi_add_handle returned %d (%s)", endpoint.c_str(), mc, curl_multi_strerror(mc)); @@ -472,6 +472,7 @@ namespace WPEFramework m_cmRunning = false; m_notify = true; m_InternetState = INTERNET_UNKNOWN; + m_ipversion = IP_ADDRESS_V4; m_Ipv4InternetState = INTERNET_UNKNOWN; m_Ipv6InternetState = INTERNET_UNKNOWN; startConnectivityMonitor(); diff --git a/NetworkManagerConnectivity.h b/NetworkManagerConnectivity.h index 38e12ebb6..6a9f7f195 100644 --- a/NetworkManagerConnectivity.h +++ b/NetworkManagerConnectivity.h @@ -27,6 +27,7 @@ #include #include #include +#include #include "INetworkManager.h" @@ -108,6 +109,15 @@ namespace WPEFramework std::string captivePortalURI; Exchange::INetworkManager::InternetStatus internetSate; int curlErrorCode = 0; + template + void curlSetOpt(CURL *curl, CURLoption option, curlValue value) + { + CURLcode response = curl_easy_setopt(curl, option, value); + if (response != CURLE_OK) { + NMLOG_ERROR("Error setting option %d with error: %s", option, curl_easy_strerror(response)); + } + return; + } }; class ConnectivityMonitor diff --git a/NetworkManagerLogger.cpp b/NetworkManagerLogger.cpp index 5dc6dfe57..342a140a1 100644 --- a/NetworkManagerLogger.cpp +++ b/NetworkManagerLogger.cpp @@ -75,15 +75,6 @@ namespace NetworkManagerLogger { return t; } - const char* methodName(const std::string& prettyFunction) - { - size_t colons = prettyFunction.find("::"); - size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1; - size_t end = prettyFunction.rfind("(") - begin; - - return prettyFunction.substr(begin,end).c_str(); - } - void Init() { #ifdef USE_RDK_LOGGER diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 4b35e51eb..c02172e00 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -499,9 +499,9 @@ namespace WPEFramework newInterface = e->newInterface; NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_DEFAULT_INTERFACE %s :: %s..", oldInterface.c_str(), newInterface.c_str()); if(oldInterface != "eth0" || oldInterface != "wlan0") - oldInterface == ""; /* assigning "null" if the interface is not eth0 or wlan0 */ + oldInterface = ""; /* assigning "null" if the interface is not eth0 or wlan0 */ if(newInterface != "eth0" || newInterface != "wlan0") - newInterface == ""; /* assigning "null" if the interface is not eth0 or wlan0 */ + newInterface = ""; /* assigning "null" if the interface is not eth0 or wlan0 */ ::_instance->ReportActiveInterfaceChange(oldInterface, newInterface); break; @@ -922,6 +922,7 @@ namespace WPEFramework address.prefix = std::atoi(iarmData.netmask); } + rc = Core::ERROR_NONE; /* Return the default interface information */ if (interface.empty()) { @@ -933,8 +934,6 @@ namespace WPEFramework else rc = Core::ERROR_BAD_REQUEST; } - - rc = Core::ERROR_NONE; } else { diff --git a/NetworkManagerStunClient.cpp b/NetworkManagerStunClient.cpp index cb6562957..05ac8f4a0 100644 --- a/NetworkManagerStunClient.cpp +++ b/NetworkManagerStunClient.cpp @@ -370,7 +370,7 @@ bool client::bind( auto time_in_cache = std::chrono::duration_cast( std::chrono::steady_clock::now() - m_last_cache_time); - NMLOG_DEBUG("client::bind cache time=%ld", time_in_cache.count()); + NMLOG_DEBUG("client::bind cache time=%lld", time_in_cache.count()); if(time_in_cache.count() < m_cache_timeout) { @@ -668,7 +668,7 @@ std::unique_ptr client::send_binding_request(std::chrono::milliseconds std::unique_ptr client::send_binding_request(sockaddr_storage const & addr, std::chrono::milliseconds wait_time) { - NMLOG_DEBUG("sending binding request with wait time:%ld ms", wait_time.count()); + NMLOG_DEBUG("sending binding request with wait time:%lld ms", wait_time.count()); this->create_udp_socket(addr.ss_family); std::unique_ptr binding_request(message_factory::create_binding_request()); std::unique_ptr binding_response(this->send_message(addr, *binding_request, wait_time)); diff --git a/WiFiSignalStrengthMonitor.h b/WiFiSignalStrengthMonitor.h index c3772f2de..4ce84e7c7 100644 --- a/WiFiSignalStrengthMonitor.h +++ b/WiFiSignalStrengthMonitor.h @@ -35,7 +35,7 @@ namespace WPEFramework class WiFiSignalStrengthMonitor { public: - WiFiSignalStrengthMonitor():isRunning(false) {} + WiFiSignalStrengthMonitor():isRunning(false), stopThread(false) {} ~WiFiSignalStrengthMonitor(){ NMLOG_INFO("~WiFiSignalStrengthMonitor"); } void startWiFiSignalStrengthMonitor(int interval); void getSignalData(std::string &ssid, Exchange::INetworkManager::WiFiSignalQuality &quality, std::string &strengthOut); From b89558b988438c5f3db1c7de3b84304e0d38f2a0 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 22 Jan 2025 21:44:03 -0500 Subject: [PATCH 075/271] RDKEMW-777 - Implement GNOME support via direct G-DBus Network APIs (#81) Reason for change: Added the gdbus implementation for Network APIs Test Procedure: Build and verified with ubuntu desktop Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR Gururaja_ErodeSriranganRamlingham@comcast.com --- CMakeLists.txt | 1 + Tests/raspberrypi/NetworkManagerGdbusTest.cpp | 160 ++- gdbus/NetworkManagerGdbusClient.cpp | 1121 ++++++++++++++++- gdbus/NetworkManagerGdbusClient.h | 9 + gdbus/NetworkManagerGdbusMgr.cpp | 71 +- gdbus/NetworkManagerGdbusMgr.h | 3 + gdbus/NetworkManagerGdbusProxy.cpp | 53 +- gdbus/NetworkManagerGdbusUtils.cpp | 271 +++- gdbus/NetworkManagerGdbusUtils.h | 10 + 9 files changed, 1646 insertions(+), 53 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b4666aea..ef239925c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ add_definitions(-DPLUGIN_BUILD_REFERENCE=${PLUGIN_BUILD_REFERENCE}) if(ENABLE_GNOME_NETWORKMANAGER) pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(LIBNM REQUIRED libnm) +pkg_check_modules(GLIB REQUIRED gio-2.0) else() find_package(IARMBus REQUIRED) endif () diff --git a/Tests/raspberrypi/NetworkManagerGdbusTest.cpp b/Tests/raspberrypi/NetworkManagerGdbusTest.cpp index b65e23858..5c0b34ea8 100644 --- a/Tests/raspberrypi/NetworkManagerGdbusTest.cpp +++ b/Tests/raspberrypi/NetworkManagerGdbusTest.cpp @@ -55,7 +55,7 @@ namespace WPEFramework { NMLOG_INFO("calling 'ReportInternetStatusChange' cb"); } - void NetworkManagerImplementation::ReportAvailableSSIDs(JsonArray &arrayofWiFiScanResults) + void NetworkManagerImplementation::ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults) { NMLOG_INFO("calling 'ReportAvailableSSIDs' cb"); } @@ -85,6 +85,13 @@ void displayMenu() std::cout << "8. WiFi Disconnect" << std::endl; std::cout << "9. Get WiFi State" << std::endl; std::cout << "10. Get WiFi Signal Strength" << std::endl; + std::cout << "11. GetAvailableInterface" << std::endl; + std::cout << "12. SetPrimaryInterface" << std::endl; + std::cout << "13. SetInterfaceState" << std::endl; + std::cout << "14. SetIPSettings" << std::endl; + std::cout << "15. GetPrimaryInterface" << std::endl; + std::cout << "16. GetInterfaceState" << std::endl; + std::cout << "17. GetIPSettings" << std::endl; std::cout << "0. Exit" << std::endl; std::cout << "-------------------------------------" << std::endl; } @@ -275,6 +282,157 @@ int main() } break; } + case 11: { + std::vector interfaceList; + if(nmClient->getAvailableInterfaces(interfaceList)){ + for (const auto& interface : interfaceList) { + NMLOG_INFO("interface.type = %d interface.name = %s interface.mac = %s interface.enabled = %d interface.connected = %d", interface.type, interface.name.c_str(), interface.mac.c_str(), interface.enabled, interface.connected); + } + } + else + { + NMLOG_ERROR("Failed to get Available Interfaces"); + } + break; + } + case 12: { + std::string interface; + std::cout << "Enter interface name to set as primary: "; + std::cin.ignore(); + std::getline(std::cin, interface); + + if(nmClient->setPrimaryInterface(interface)){ + NMLOG_INFO("setPrimaryInterface successful"); + } + else + { + NMLOG_ERROR("Failed to set Primary Interface"); + } + break; + } + case 13: { + std::string interface; + std::string input; + bool enable; + std::cout << "Enter interface name to change the state: "; + std::cin.ignore(); + std::getline(std::cin, interface); + std::cout << "Enable Interface(input true/false): "; + std::getline(std::cin, input); + enable = (input == "true")? true: false; + + if(nmClient->setInterfaceState(interface, enable)){ + NMLOG_INFO("setInterfaceState successful"); + } + else + { + NMLOG_ERROR("Failed to set Interface State"); + } + break; + } + case 14: { + std::string interface; + std::string ipVersion; + std::string input; + bool autoConfig; + std::string ipAddress; + uint32_t prefix = 0; + std::string gateway; + std::string primarydns; + std::string secondarydns; + Exchange::INetworkManager::IPAddress address; + std::cout << "Enter interface: "; + std::cin.ignore(); + std::getline(std::cin, interface); + + std::cout << "Enter IP version: (IPv4/IPv6)"; + std::getline(std::cin, ipVersion); + + std::cout << "Enter auto configuration setting(input true/false): "; + std::getline(std::cin, input); + autoConfig = (input == "true")? true: false; + + if(!autoConfig) + { + std::cout << "Enter IP address: "; + std::getline(std::cin, ipAddress); + + // For prefix, use std::cin because it's a uint32_t + std::cout << "Enter prefix length: "; + std::cin >> prefix; + std::cin.ignore(std::numeric_limits::max(), '\n'); // Ignore leftover newline + + std::cout << "Enter gateway: "; + std::getline(std::cin, gateway); + + std::cout << "Enter primary DNS: "; + std::getline(std::cin, primarydns); + + std::cout << "Enter secondary DNS: "; + std::getline(std::cin, secondarydns); + } + address.ipversion = ipVersion; + address.autoconfig = autoConfig; + address.ipaddress = ipAddress; + address.prefix = prefix; + address.gateway = gateway; + address.primarydns = primarydns; + address.secondarydns = secondarydns; + if(nmClient->setIPSettings(interface, address)){ + NMLOG_INFO("setIPSettings successful"); + } + else + { + NMLOG_ERROR("Failed to set IP settings"); + } + break; + } + case 15: { + std::string interface; + + if(nmClient->getPrimaryInterface(interface)){ + NMLOG_INFO("Primary Interface = %s", interface.c_str()); + } + else + { + NMLOG_ERROR("Failed to Get Primary Interface"); + } + break; + } + case 16: { + std::string interface; + bool isEnabled; + std::cout << "Enter interface: "; + std::cin.ignore(); + std::getline(std::cin, interface); + if(nmClient->getInterfaceState(interface, isEnabled)){ + NMLOG_INFO("Interface %s is %s", interface.c_str(), isEnabled ? "enabled": "disabled"); + } + else + { + NMLOG_ERROR("Failed to Get Interface state"); + } + break; + } + case 17: { + std::string interface; + std::string ipVersion; + Exchange::INetworkManager::IPAddress result; + std::cout << "Enter interface: "; + std::cin.ignore(); + std::getline(std::cin, interface); + std::cout << "Enter IP version(IPv4/IPv6): "; + std::getline(std::cin, ipVersion); + if(nmClient->getIPSettings(interface, ipVersion, result)){ + NMLOG_INFO("\nresult.ipversion = %s\n result.autoconfig = %d\n result.dhcpserver = %s\n result.ula = %s\n result.ipaddress = %s\n result.prefix = %d\nresult.gateway = %s\n result.primarydns = %s\n result.secondarydns = %s\n", result.ipversion.c_str(), result.autoconfig, result.dhcpserver.c_str(), result.ula.c_str(), result.ipaddress.c_str(), result.prefix, result.gateway.c_str(), result.primarydns.c_str(), result.secondarydns.c_str()); + } + else + { + NMLOG_ERROR("Failed to get IP Settings"); + } + break; + } + case 0: std::cout << "Exiting program." << std::endl; diff --git a/gdbus/NetworkManagerGdbusClient.cpp b/gdbus/NetworkManagerGdbusClient.cpp index c99a56f36..5e6f6a008 100644 --- a/gdbus/NetworkManagerGdbusClient.cpp +++ b/gdbus/NetworkManagerGdbusClient.cpp @@ -41,6 +41,1125 @@ namespace WPEFramework NMLOG_INFO("~NetworkManagerClient"); } + bool updateRouteMetric(DbusMgr& m_dbus, const std::string& connectionPath, gint64 route_metric, const gchar* interface, const std::string& activeConnectionPath) + { + GError *error = nullptr; + deviceInfo devInfo{}; + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, interface, devInfo)) + return false; + GDBusProxy *settingsProxy = m_dbus.getNetworkManagerSettingsConnectionProxy(connectionPath.c_str()); + + if (settingsProxy == nullptr) { + NMLOG_ERROR("Error creating connection settings proxy"); + return false; + } + + GVariant *connectionSettings = g_dbus_proxy_call_sync( + settingsProxy, + "GetSettings", + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (connectionSettings == nullptr) { + NMLOG_ERROR("Error retrieving connection settings: %s", error->message); + g_error_free(error); + g_object_unref(settingsProxy); + return false; + } + + GVariantIter *iterator; + GVariant *settingsDict; + const gchar *settingsKey; + const gchar *existingId = nullptr; + const gchar *existingType = nullptr; + const gchar *existingIPv4Method = nullptr; + const gchar *existingIPv6Method = nullptr; + const gchar *existingInterfaceName = nullptr; + + const gchar *existingKeyMgmt = nullptr; + const gchar *existingPSK = nullptr; + const gchar *existingSSID = nullptr; + GVariant *existingIPv4Settings = nullptr; + GVariant *existingIPv6Settings = nullptr; + + g_variant_get(connectionSettings, "(a{sa{sv}})", &iterator); + while (g_variant_iter_loop(iterator, "{&s@a{sv}}", &settingsKey, &settingsDict)) { + GVariantIter settingsIter; + const gchar *key; + GVariant *value; + + g_variant_iter_init(&settingsIter, settingsDict); + while (g_variant_iter_loop(&settingsIter, "{&sv}", &key, &value)) { + if (g_strcmp0(key, "id") == 0) { + existingId = g_variant_get_string(value, NULL); + NMLOG_DEBUG("Connection ID: %s\n", existingId); + } else if (g_strcmp0(key, "type") == 0) { + existingType = g_variant_get_string(value, NULL); + NMLOG_DEBUG("Connection Type: %s\n", existingType); + } else if (g_strcmp0(key, "interface-name") == 0) { + existingInterfaceName = g_variant_get_string(value, NULL); + NMLOG_DEBUG("Interface Name: %s\n", existingInterfaceName); + } else if (g_strcmp0(key, "method") == 0) { + if(g_strcmp0(settingsKey, "ipv4") == 0) + { + existingIPv4Method = g_variant_get_string(value, NULL); + NMLOG_DEBUG("IPV4 Method: %s\n", existingIPv4Method); + } + else if(g_strcmp0(settingsKey, "ipv6") == 0) + { + existingIPv6Method = g_variant_get_string(value, NULL); + NMLOG_DEBUG("IPV6 Method: %s\n", existingIPv6Method); + } + } else if (g_strcmp0(key, "ssid") == 0) { + gsize size; + const guint8 *ssid = (const guint8 *) g_variant_get_fixed_array(value, &size, sizeof(guint8)); + // Convert the ssid to a null-terminated string + existingSSID = g_strndup((const gchar *)ssid, size); + } else if (g_strcmp0(key, "key-mgmt") == 0) { + existingKeyMgmt = g_variant_get_string(value, NULL); + NMLOG_DEBUG("Key Management: %s\n", existingKeyMgmt); + } else if (g_strcmp0(key, "psk") == 0) { + existingPSK = g_variant_get_string(value, NULL); + NMLOG_DEBUG("psk: %s\n", existingPSK); + } else if (g_strcmp0(settingsKey, "ipv4") == 0) { + existingIPv4Settings = g_variant_ref(settingsDict); + } else if (g_strcmp0(settingsKey, "ipv6") == 0) { + existingIPv6Settings = g_variant_ref(settingsDict); + } + + } + } + g_variant_iter_free(iterator); + + GVariantBuilder connectionBuilder; + + GVariantBuilder wifiBuilder; + GVariantBuilder settingsBuilder; + GVariantBuilder wifiSecurityBuilder; + g_variant_builder_init(&settingsBuilder, G_VARIANT_TYPE("a{sa{sv}}")); + // Define the 'connection' dictionary with connection details + g_variant_builder_init(&connectionBuilder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&connectionBuilder, "{sv}", "id", g_variant_new_string(existingId)); + g_variant_builder_add(&connectionBuilder, "{sv}", "type", g_variant_new_string(existingType)); + g_variant_builder_add(&connectionBuilder, "{sv}", "interface-name", g_variant_new_string(existingInterfaceName)); + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "connection", &connectionBuilder); + + if (g_strcmp0(interface, GnomeUtils::getWifiIfname()) == 0) { + // Define the '802-11-wireless' dictionary with Wi-Fi specific details + g_variant_builder_init(&wifiBuilder, G_VARIANT_TYPE("a{sv}")); + GVariantBuilder ssidBuilder; + g_variant_builder_init(&ssidBuilder, G_VARIANT_TYPE("ay")); + while (*existingSSID) { + g_variant_builder_add(&ssidBuilder, "y", *(existingSSID++)); + } + g_variant_builder_add(&wifiBuilder, "{sv}", "ssid", g_variant_builder_end(&ssidBuilder)); + g_variant_builder_add(&wifiBuilder, "{sv}", "mode", g_variant_new_string("infrastructure")); // Set Wi-Fi mode + g_variant_builder_add(&wifiBuilder, "{sv}", "security", g_variant_new_string("802-11-wireless-security")); // Security type + + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "802-11-wireless", &wifiBuilder); + + // Define the '802-11-wireless-security' dictionary with security details + g_variant_builder_init(&wifiSecurityBuilder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&wifiSecurityBuilder, "{sv}", "key-mgmt", g_variant_new_string(existingKeyMgmt)); // Key management + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "802-11-wireless-security", &wifiSecurityBuilder); + } + + + GVariantBuilder ipv4Builder; + g_variant_builder_init(&ipv4Builder, G_VARIANT_TYPE("a{sv}")); + GVariantBuilder ipv6Builder; + g_variant_builder_init(&ipv6Builder, G_VARIANT_TYPE("a{sv}")); + + GnomeUtils::addGvariantToBuilder(existingIPv4Settings, &ipv4Builder, true); + GnomeUtils::addGvariantToBuilder(existingIPv6Settings, &ipv6Builder, true); + /*g_variant_builder_add(&ipv4Builder, "{sv}", "method", g_variant_new_string(existingIPv4Method)); + g_variant_builder_add(&ipv6Builder, "{sv}", "method", g_variant_new_string(existingIPv6Method));*/ + g_variant_builder_add(&ipv4Builder, "{sv}", "route-metric", g_variant_new_int64(route_metric)); + g_variant_builder_add(&ipv6Builder, "{sv}", "route-metric", g_variant_new_int64(route_metric)); + + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "ipv4", &ipv4Builder); + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "ipv6", &ipv6Builder); + + g_dbus_proxy_call_sync( + settingsProxy, + "Update", + g_variant_new("(a{sa{sv}})", &settingsBuilder), + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (error) { + NMLOG_ERROR("Error updating connection settings: %s", error->message); + g_error_free(error); + } else { + NMLOG_DEBUG("Successfully updated IPv4 settings for %s interface", interface); + } + if(!GnomeUtils::activateConnection(m_dbus, connectionPath, devInfo.path)) + { + NMLOG_INFO("activateConnection not successful"); + return false; + } + else + NMLOG_INFO("activateConnection successful"); + + g_variant_unref(connectionSettings); + g_object_unref(settingsProxy); + return true; + } + + bool updateIPSettings(DbusMgr& m_dbus, const std::string& connectionPath, const Exchange::INetworkManager::IPAddress& address, const std::string& interface) + { + GError *error = nullptr; + deviceInfo devInfo{}; + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, interface.c_str(), devInfo)) + return false; + GDBusProxy *settingsProxy = m_dbus.getNetworkManagerSettingsConnectionProxy(connectionPath.c_str()); + + if (settingsProxy == nullptr) { + NMLOG_ERROR("Error creating connection settings proxy"); + return false; + } + + GVariant *connectionSettings = g_dbus_proxy_call_sync( + settingsProxy, + "GetSettings", + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (connectionSettings == nullptr) { + NMLOG_ERROR("Error retrieving connection settings: %s", error->message); + g_error_free(error); + g_object_unref(settingsProxy); + return false; + } + + GVariantIter *iterator; + GVariant *settingsDict; + const gchar *settingsKey; + const gchar *existingId = nullptr; + const gchar *existingType = nullptr; + const gchar *existingInterfaceName = nullptr; + + const gchar *existingKeyMgmt = nullptr; + const gchar *existingPSK = nullptr; + const gchar *existingSSID = nullptr; + GVariant *existingIPv4Settings = nullptr; + GVariant *existingIPv6Settings = nullptr; + + + g_variant_get(connectionSettings, "(a{sa{sv}})", &iterator); + while (g_variant_iter_loop(iterator, "{&s@a{sv}}", &settingsKey, &settingsDict)) { + GVariantIter settingsIter; + const gchar *key; + GVariant *value; + + g_variant_iter_init(&settingsIter, settingsDict); + while (g_variant_iter_loop(&settingsIter, "{&sv}", &key, &value)) { + if (g_strcmp0(key, "id") == 0) { + existingId = g_variant_get_string(value, NULL); + NMLOG_DEBUG("Connection ID: %s\n", existingId); + } else if (g_strcmp0(key, "type") == 0) { + existingType = g_variant_get_string(value, NULL); + NMLOG_DEBUG("Connection Type: %s\n", existingType); + } else if (g_strcmp0(key, "interface-name") == 0) { + existingInterfaceName = g_variant_get_string(value, NULL); + NMLOG_DEBUG("Interface Name: %s\n", existingInterfaceName); + } else if (g_strcmp0(key, "ssid") == 0) { + gsize size; + const guint8 *ssid = (const guint8 *) g_variant_get_fixed_array(value, &size, sizeof(guint8)); + // Convert the ssid to a null-terminated string + existingSSID = g_strndup((const gchar *)ssid, size); + } else if (g_strcmp0(key, "key-mgmt") == 0) { + existingKeyMgmt = g_variant_get_string(value, NULL); + NMLOG_DEBUG("Key Management: %s\n", existingKeyMgmt); + } else if (g_strcmp0(key, "psk") == 0) { + existingPSK = g_variant_get_string(value, NULL); + NMLOG_DEBUG("psk: %s\n", existingPSK); + } else if (g_strcmp0(settingsKey, "ipv4") == 0) { + existingIPv4Settings = g_variant_ref(settingsDict); + } else if (g_strcmp0(settingsKey, "ipv6") == 0) { + existingIPv6Settings = g_variant_ref(settingsDict); + } + } + } + g_variant_iter_free(iterator); + + GVariantBuilder connectionBuilder; + + GVariantBuilder wifiBuilder; + GVariantBuilder settingsBuilder; + GVariantBuilder wifiSecurityBuilder; + GVariantBuilder addressesBuilder; + GVariantBuilder addressEntryBuilder; + GVariantBuilder dnsBuilder; + g_variant_builder_init(&settingsBuilder, G_VARIANT_TYPE("a{sa{sv}}")); + // Define the 'connection' dictionary with connection details + g_variant_builder_init(&connectionBuilder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&connectionBuilder, "{sv}", "id", g_variant_new_string(existingId)); + g_variant_builder_add(&connectionBuilder, "{sv}", "type", g_variant_new_string(existingType)); + g_variant_builder_add(&connectionBuilder, "{sv}", "interface-name", g_variant_new_string(existingInterfaceName)); + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "connection", &connectionBuilder); + + if (g_strcmp0(interface.c_str(), GnomeUtils::getWifiIfname()) == 0) { + // Define the '802-11-wireless' dictionary with Wi-Fi specific details + g_variant_builder_init(&wifiBuilder, G_VARIANT_TYPE("a{sv}")); + GVariantBuilder ssidBuilder; + g_variant_builder_init(&ssidBuilder, G_VARIANT_TYPE("ay")); + while (*existingSSID) { + g_variant_builder_add(&ssidBuilder, "y", *(existingSSID++)); + } + g_variant_builder_add(&wifiBuilder, "{sv}", "ssid", g_variant_builder_end(&ssidBuilder)); + g_variant_builder_add(&wifiBuilder, "{sv}", "mode", g_variant_new_string("infrastructure")); // Set Wi-Fi mode + g_variant_builder_add(&wifiBuilder, "{sv}", "security", g_variant_new_string("802-11-wireless-security")); // Security type + + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "802-11-wireless", &wifiBuilder); + + // Define the '802-11-wireless-security' dictionary with security details + g_variant_builder_init(&wifiSecurityBuilder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&wifiSecurityBuilder, "{sv}", "key-mgmt", g_variant_new_string(existingKeyMgmt)); // Key management + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "802-11-wireless-security", &wifiSecurityBuilder); + } + + GVariantBuilder ipv4Builder; + GVariantBuilder ipv6Builder; + + g_variant_builder_init(&ipv4Builder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_init(&ipv6Builder, G_VARIANT_TYPE("a{sv}")); + if (g_strcmp0(address.ipversion.c_str(), "IPv4") == 0) + { + g_variant_builder_add(&ipv4Builder, "{sv}", "method", g_variant_new_string(address.autoconfig ? "auto" : "manual")); + if(!address.autoconfig) + { + // addresses + g_variant_builder_init(&addressesBuilder, G_VARIANT_TYPE("aau")); + + g_variant_builder_init(&addressEntryBuilder, G_VARIANT_TYPE("au")); + + g_variant_builder_add(&addressEntryBuilder, "u", GnomeUtils::ip4StrToNBO(address.ipaddress)); + g_variant_builder_add(&addressEntryBuilder, "u", address.prefix); + g_variant_builder_add(&addressEntryBuilder, "u", GnomeUtils::ip4StrToNBO(address.gateway)); + g_variant_builder_add_value(&addressesBuilder, g_variant_builder_end(&addressEntryBuilder)); + + g_variant_builder_add(&ipv4Builder, "{sv}", "addresses", g_variant_builder_end(&addressesBuilder)); + + // dns + g_variant_builder_init(&dnsBuilder, G_VARIANT_TYPE("au")); + g_variant_builder_add(&dnsBuilder, "u", GnomeUtils::ip4StrToNBO(address.primarydns)); + g_variant_builder_add(&dnsBuilder, "u", GnomeUtils::ip4StrToNBO(address.secondarydns)); + + g_variant_builder_add(&ipv4Builder, "{sv}", "dns", g_variant_builder_end(&dnsBuilder)); + // Add gateway + g_variant_builder_add(&ipv4Builder, "{sv}", "gateway", g_variant_new_string(address.gateway.c_str())); + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "ipv4", &ipv4Builder); + } + if (existingIPv6Settings) { + GnomeUtils::addGvariantToBuilder(existingIPv6Settings, &ipv6Builder, false); + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "ipv6", &ipv6Builder); + g_variant_unref(existingIPv6Settings); + } + } + else if (g_strcmp0(address.ipversion.c_str(), "IPv6") == 0) + { + g_variant_builder_add(&ipv6Builder, "{sv}", "method", g_variant_new_string(address.autoconfig ? "auto" : "manual")); + if(!address.autoconfig) + { + // addresses + g_variant_builder_init(&addressesBuilder, G_VARIANT_TYPE("a(ayuay)")); + + g_variant_builder_init(&addressEntryBuilder, G_VARIANT_TYPE("(ayuay)")); + std::array ip6 = GnomeUtils::ip6StrToNBO(address.ipaddress); + std::array gateway6 = GnomeUtils::ip6StrToNBO(address.gateway); + g_variant_builder_add_value(&addressEntryBuilder, g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, ip6.data(), ip6.size(), sizeof(guint8))); + g_variant_builder_add(&addressEntryBuilder, "u", address.prefix); + g_variant_builder_add_value(&addressEntryBuilder, g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, gateway6.data(), gateway6.size(), sizeof(guint8))); + g_variant_builder_add_value(&addressesBuilder, g_variant_builder_end(&addressEntryBuilder)); + g_variant_builder_add(&ipv6Builder, "{sv}", "addresses", g_variant_builder_end(&addressesBuilder)); + + //DNS + g_variant_builder_init(&dnsBuilder, G_VARIANT_TYPE("aay")); + std::array primaryDns6 = GnomeUtils::ip6StrToNBO(address.primarydns); + std::array secondaryDns6 = GnomeUtils::ip6StrToNBO(address.secondarydns); + g_variant_builder_add_value(&dnsBuilder, g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, primaryDns6.data(), primaryDns6.size(), sizeof(guint8))); + g_variant_builder_add_value(&dnsBuilder, g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, secondaryDns6.data(), secondaryDns6.size(), sizeof(guint8))); + g_variant_builder_add(&ipv6Builder, "{sv}", "dns", g_variant_builder_end(&dnsBuilder)); + // Add gateway + g_variant_builder_add(&ipv6Builder, "{sv}", "gateway", g_variant_new_string(address.gateway.c_str())); + + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "ipv6", &ipv6Builder); + } + if (existingIPv4Settings) { + GnomeUtils::addGvariantToBuilder(existingIPv4Settings, &ipv4Builder, false); + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "ipv4", &ipv4Builder); + g_variant_unref(existingIPv4Settings); + } + } + + g_dbus_proxy_call_sync( + settingsProxy, + "Update", + g_variant_new("(a{sa{sv}})", &settingsBuilder), + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (error) { + NMLOG_ERROR("Error updating connection settings: %s", error->message); + g_error_free(error); + } else { + NMLOG_DEBUG("Successfully updated IPv4 settings for %s interface", interface.c_str()); + } + if(!GnomeUtils::activateConnection(m_dbus, connectionPath, devInfo.path)) + { + NMLOG_INFO("activateConnection not successful"); + return false; + } + else + NMLOG_INFO("activateConnection successful"); + + g_variant_unref(connectionSettings); + g_object_unref(settingsProxy); + return true; + } + + bool NetworkManagerClient::getAvailableInterfaces(std::vector& interfacesList) + { + deviceInfo ethDevInfo{}; + deviceInfo wifiDevInfo{}; + Exchange::INetworkManager::InterfaceDetails ethInterface; + Exchange::INetworkManager::InterfaceDetails wifiInterface; + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getEthIfname(), ethDevInfo)) + return false; + ethInterface.type = Exchange::INetworkManager::InterfaceType::INTERFACE_TYPE_ETHERNET; + ethInterface.name = ethDevInfo.interface; + ethInterface.mac = ethDevInfo.MAC; + ethInterface.enabled = ethDevInfo.managed?true:false; + ethInterface.connected = ethDevInfo.state == NM_DEVICE_STATE_ACTIVATED?true:false; + interfacesList.push_back(ethInterface); + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), wifiDevInfo)) + return false; + wifiInterface.type = Exchange::INetworkManager::InterfaceType::INTERFACE_TYPE_WIFI; + wifiInterface.name = wifiDevInfo.interface; + wifiInterface.mac = wifiDevInfo.MAC; + wifiInterface.enabled = wifiDevInfo.managed?true:false; + wifiInterface.connected = wifiDevInfo.state == NM_DEVICE_STATE_ACTIVATED?true:false; + interfacesList.push_back(wifiInterface); + + return true; + } + + bool NetworkManagerClient::setPrimaryInterface(const std::string& interface) + { + GError *error = nullptr; + GDBusProxy *nmProxy = nullptr; + std::string connectionPath; + nmProxy = m_dbus.getNetworkManagerProxy(); + if(nmProxy == nullptr) + return false; + GVariant *activeConnections = g_dbus_proxy_get_cached_property(nmProxy, "ActiveConnections"); + if (activeConnections == nullptr) { + NMLOG_ERROR("Error retrieving active connections"); + g_object_unref(nmProxy); + return false; + } + + GVariantIter iter; + g_variant_iter_init(&iter, activeConnections); + gchar *activeConnectionPath = nullptr; + gint64 routeMetric; + while (g_variant_iter_loop(&iter, "o", &activeConnectionPath)) { + GDBusProxy *activeConnectionProxy = m_dbus.getNetworkManagerActiveConnProxy(activeConnectionPath); + + if (activeConnectionProxy == nullptr) { + NMLOG_ERROR("Error creating active connection proxy"); + continue; + } + + GVariant *devicesVar = g_dbus_proxy_get_cached_property(activeConnectionProxy, "Devices"); + if (devicesVar == nullptr) { + NMLOG_ERROR("Error retrieving devices property"); + g_object_unref(activeConnectionProxy); + continue; + } + + GVariantIter devicesIter; + g_variant_iter_init(&devicesIter, devicesVar); + gchar *devicePath = nullptr; + + while (g_variant_iter_loop(&devicesIter, "o", &devicePath)) { + GDBusProxy *deviceProxy = m_dbus.getNetworkManagerDeviceProxy(devicePath); + + if (deviceProxy == nullptr) { + NMLOG_ERROR("Error creating device proxy: %s", error->message); + g_error_free(error); + continue; + } + + GVariant *ifaceProperty = g_dbus_proxy_get_cached_property(deviceProxy, "Interface"); + if (ifaceProperty) { + const gchar *iface = g_variant_get_string(ifaceProperty, nullptr); + GVariant *connectionProperty = g_dbus_proxy_get_cached_property(activeConnectionProxy, "Connection"); + if (connectionProperty) { + connectionPath = g_variant_get_string(connectionProperty, nullptr); + g_variant_unref(connectionProperty); + } else { + NMLOG_ERROR("Error retrieving connection property"); + } + if (!g_strcmp0(iface, GnomeUtils::getWifiIfname()) || !g_strcmp0(iface, GnomeUtils::getEthIfname())) { + if(interface == iface) + routeMetric = ROUTE_METRIC_PRIORITY_HIGH; + else + routeMetric = ROUTE_METRIC_PRIORITY_LOW; + if(!updateRouteMetric(m_dbus, connectionPath, routeMetric, iface, activeConnectionPath)) + { + NMLOG_ERROR("Error: Failed to update route metric for Interface %s", iface); + return false; + } + } + g_variant_unref(ifaceProperty); + g_object_unref(deviceProxy); + break; + } + g_variant_unref(ifaceProperty); + } + + g_variant_unref(devicesVar); + g_object_unref(activeConnectionProxy); + } + + g_variant_unref(activeConnections); + g_object_unref(nmProxy); + + return true; + } + + bool NetworkManagerClient::getPrimaryInterface(std::string& interface) + { + GError* error = nullptr; + std::string primaryConnectionPath; + GDBusProxy *nmProxy = nullptr; + nmProxy = m_dbus.getNetworkManagerPropertyProxy("/org/freedesktop/NetworkManager"); + if(nmProxy == nullptr) + return false; + + GVariant* result = g_dbus_proxy_call_sync( + nmProxy, + "Get", + g_variant_new("(ss)", "org.freedesktop.NetworkManager", "PrimaryConnection"), + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error + ); + + if (error) { + NMLOG_ERROR("Error: Getting primary connection path %s",error->message); + g_error_free(error); + return false; + } + + if (result != NULL) { + GVariant* value; + g_variant_get(result, "(v)", &value); + if (g_variant_is_of_type(value, G_VARIANT_TYPE_OBJECT_PATH)) { + primaryConnectionPath = g_variant_get_string(value, nullptr); + } else { + NMLOG_ERROR("Expected object path but got different type"); + } + g_variant_unref(value); + g_variant_unref(result); + } + + GDBusProxy* deviceProxy = m_dbus.getNetworkManagerPropertyProxy(primaryConnectionPath.c_str()); + if(deviceProxy == NULL) + return false; + + std::string defaultDevicePath; + + result = g_dbus_proxy_call_sync( + deviceProxy, + "Get", + g_variant_new("(ss)", "org.freedesktop.NetworkManager.Connection.Active", "Devices"), + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error + ); + + if (error) { + NMLOG_ERROR("Error: Getting default device path %s", error->message); + g_error_free(error); + return false; + } + + if (result != nullptr) { + GVariant* value; + g_variant_get(result, "(v)", &value); + if (g_variant_is_of_type(value, G_VARIANT_TYPE_ARRAY)) { + GVariantIter* iter; + const gchar* devicePath; + g_variant_get(value, "ao", &iter); + + if (g_variant_iter_loop(iter, "o", &devicePath)) { + defaultDevicePath = devicePath; + } + g_variant_iter_free(iter); + } else { + NMLOG_ERROR("Expected array of object paths but got different type"); + } + g_variant_unref(value); + g_variant_unref(result); + } + GDBusProxy* defaultDeviceProxy = m_dbus.getNetworkManagerPropertyProxy(defaultDevicePath.c_str()); + if(defaultDeviceProxy == NULL) + return false; + + error = nullptr; + result = g_dbus_proxy_call_sync( + defaultDeviceProxy, + "Get", + g_variant_new("(ss)", "org.freedesktop.NetworkManager.Device", "Interface"), + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error + ); + + if (error) { + NMLOG_ERROR("Error: Getting primary interface %s", error->message); + g_error_free(error); + return false; + } + + if (result != nullptr) { + GVariant* value; + g_variant_get(result, "(v)", &value); + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { + interface = g_variant_get_string(value, nullptr); + } else { + NMLOG_ERROR("Expected string but got different type"); + } + g_variant_unref(value); + g_variant_unref(result); + } + + g_object_unref(defaultDeviceProxy); + g_object_unref(deviceProxy); + g_object_unref(nmProxy); + return true; + } + + bool NetworkManagerClient::setInterfaceState(const std::string& interface, bool enable) + { + deviceInfo devInfo{}; + GError* error = nullptr; + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, interface.c_str(), devInfo)) + return false; + + GDBusProxy* deviceProxy = m_dbus.getNetworkManagerPropertyProxy(devInfo.path.c_str()); + if(deviceProxy == NULL) + return false; + + GVariant* result = g_dbus_proxy_call_sync( + deviceProxy, + "Set", + g_variant_new("(ssv)", "org.freedesktop.NetworkManager.Device", "Managed", g_variant_new_boolean(enable)), + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error + ); + + if (error) { + NMLOG_ERROR("Error %s network interface: %s", (enable ? "enabling" : "disabling"), error->message); + g_error_free(error); + } else { + NMLOG_DEBUG("Network interface %s successfully %s", (enable ? "enabled" : "disabled"), devInfo.path.c_str()); + if (result != nullptr) { + g_variant_unref(result); + } + } + g_object_unref(deviceProxy); + return true; + } + + bool NetworkManagerClient::getInterfaceState(const std::string& interface, bool& isEnabled) + { + deviceInfo devInfo{}; + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, interface.c_str(), devInfo)) + return false; + + GError* error = nullptr; + GDBusProxy* deviceProxy = m_dbus.getNetworkManagerPropertyProxy(devInfo.path.c_str()); + if(deviceProxy == nullptr) + return false; + + // Call the "Get" method using the proxy + GVariant* result = g_dbus_proxy_call_sync( + deviceProxy, + "Get", + g_variant_new("(ss)", "org.freedesktop.NetworkManager.Device", "Managed"), + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error + ); + + if (error != nullptr) { + NMLOG_ERROR("Error getting network interface state: %s", error->message); + g_error_free(error); + } else { + NMLOG_DEBUG("Network interface state retrieved successfully: %s",devInfo.path.c_str()); + GVariant* managedVariant; + g_variant_get(result, "(v)", &managedVariant); + + isEnabled = g_variant_get_boolean(managedVariant); + g_variant_unref(managedVariant); + + NMLOG_DEBUG("Interface %s is %s", interface.c_str(), isEnabled ? "enabled" : "disabled"); + + g_variant_unref(result); + } + + return true; + } + + bool NetworkManagerClient::setIPSettings(const std::string& interface, const Exchange::INetworkManager::IPAddress& address) + { + std::string connectionPath; + if (!GnomeUtils::getSettingsConnectionPath(m_dbus, connectionPath, interface)) + { + NMLOG_ERROR("Error: connection path not found for interface %s", interface.c_str()); + return false; + } + if (connectionPath.empty()) { + NMLOG_ERROR("Error: Interface %s not found in active connections", interface.c_str()); + return false; + } + if(!updateIPSettings(m_dbus, connectionPath, address, interface)) + { + NMLOG_ERROR("Error: Failed to update route metric for Interface %s", interface.c_str()); + return false; + } + + return true; + } + + bool NetworkManagerClient::getIPSettings(const std::string& interface, const std::string& ipversion, Exchange::INetworkManager::IPAddress& result) + { + std::string devicePath; + std::string addressStr; + guint32 prefix = 0; + const gchar *gatewayIp = nullptr; + gchar *dhcpServerIp = nullptr; + gchar **dnsList = nullptr; + gchar *ip4ConfigPath = nullptr; + gchar *dhcp4ConfigPath = nullptr; + gchar *dnsAddresses = nullptr; + gchar *dhcp6ConfigPath = nullptr; + gchar *ip6ConfigPath = nullptr; + GDBusProxy* ipv4Proxy = nullptr; + GDBusProxy* ipv6Proxy = nullptr; + const gchar *IPv4Method = nullptr; + const gchar *IPv6Method = nullptr; + deviceInfo devInfo{}; + GError *error = nullptr; + if(!GnomeUtils::getDeviceByIpIface(m_dbus, interface.c_str(), devicePath)) + return false; + GDBusProxy *deviceProxy = m_dbus.getNetworkManagerDeviceProxy(devicePath.c_str()); + if(deviceProxy == nullptr) + return false; + if (g_strcmp0(ipversion.c_str(), "IPv4") == 0) + { + GVariant *ip4Property = g_dbus_proxy_get_cached_property(deviceProxy, "Ip4Config"); + if (ip4Property != nullptr) + { + g_variant_get(ip4Property, "o", &ip4ConfigPath); + g_variant_unref(ip4Property); + } + else + { + NMLOG_ERROR("Failed to get Ip4Config property"); + g_object_unref(deviceProxy); + } + + GVariant *dhcp4Property = g_dbus_proxy_get_cached_property(deviceProxy, "Dhcp4Config"); + if (dhcp4Property != nullptr) + { + g_variant_get(dhcp4Property, "o", &dhcp4ConfigPath); + g_variant_unref(dhcp4Property); + } + else + { + NMLOG_ERROR("Failed to get Dhcp4Config property"); + g_object_unref(deviceProxy); + } + + ipv4Proxy = m_dbus.getNetworkManagerIpv4Proxy(ip4ConfigPath); + g_free(ip4ConfigPath); + // Get the 'Addresses' property + if(ipv4Proxy != nullptr) + { + GVariant *addressesProperty = g_dbus_proxy_get_cached_property(ipv4Proxy, "Addresses"); + + if(addressesProperty != nullptr) + { + gsize numAddresses = g_variant_n_children(addressesProperty); + for (gsize i = 0; i < numAddresses; ++i) { + GVariant *addressArray = g_variant_get_child_value(addressesProperty, i); + GVariantIter iter; + guint32 addr; + + g_variant_iter_init(&iter, addressArray); + + if (g_variant_iter_next(&iter, "u", &addr)) { + addressStr = GnomeUtils::ip4ToString(addr); + NMLOG_DEBUG("IP Address: %s", addressStr.c_str()); + } + if (g_variant_iter_next(&iter, "u", &prefix)) { + NMLOG_DEBUG("Prefix: %d", prefix); + } + + g_variant_unref(addressArray); + } + + g_variant_unref(addressesProperty); + } + else + { + NMLOG_ERROR("Failed to get Addresses property"); + g_object_unref(ipv4Proxy); + } + + // Get the 'Gateway' property + GVariant *gatewayProperty = g_dbus_proxy_get_cached_property(ipv4Proxy, "Gateway"); + if (gatewayProperty != nullptr) { + // Fetch and print the Gateway IP + gatewayIp = g_variant_get_string(gatewayProperty, nullptr); + NMLOG_DEBUG("Gateway: %s", gatewayIp); + g_variant_unref(gatewayProperty); + } + else + { + NMLOG_ERROR("Failed to get Gateway property"); + g_variant_unref(addressesProperty); + g_object_unref(ipv4Proxy); + } + } + GDBusProxy* dhcpv4Proxy = m_dbus.getNetworkManagerDhcpv4Proxy(dhcp4ConfigPath); + g_free(dhcp4ConfigPath); + + if(dhcpv4Proxy != nullptr) + { + // Get the 'Options' property + GVariant *optionsProperty = g_dbus_proxy_get_cached_property(dhcpv4Proxy, "Options"); + + if (optionsProperty != nullptr) { + + GVariantIter *iter; + gchar *key; + GVariant *value; + + // Print the whole options property for debugging + gchar *optionsStr = g_variant_print(optionsProperty, TRUE); + NMLOG_DEBUG("Options property: %s", optionsStr); + g_free(optionsStr); + + g_variant_get(optionsProperty, "a{sv}", &iter); + + while (g_variant_iter_next(iter, "{&sv}", &key, &value)) { + if (g_strcmp0(key, "dhcp_server_identifier") == 0) { + dhcpServerIp = g_strdup(g_variant_get_string(value, nullptr)); + } else if (g_strcmp0(key, "domain_name_servers") == 0) { + dnsAddresses = g_strdup(g_variant_get_string(value, nullptr)); + } + g_variant_unref(value); + + if (dhcpServerIp && dnsAddresses) { + break; + } + } + + g_variant_iter_free(iter); + g_variant_unref(optionsProperty); + g_object_unref(dhcpv4Proxy); + + if (dhcpServerIp) { + NMLOG_DEBUG("DHCP server IP address: %s", dhcpServerIp); + } else { + NMLOG_DEBUG("Failed to find DHCP server IP address"); + } + if (dnsAddresses) { + // DNS addresses are space-separated, we need to split them + dnsList = g_strsplit(dnsAddresses, " ", -1); + if (dnsList[0] != nullptr) { + NMLOG_DEBUG("Primary DNS: %s", dnsList[0]); + if (dnsList[1] != nullptr) { + NMLOG_DEBUG("Secondary DNS: %s", dnsList[1]); + } else { + NMLOG_DEBUG("Secondary DNS: Not available"); + } + } else { + NMLOG_DEBUG("Failed to parse DNS addresses"); + } + } else { + NMLOG_DEBUG("Failed to find DNS addresses"); + } + } + else + { + NMLOG_ERROR("Failed to get Options property"); + g_object_unref(dhcpv4Proxy); + } + } + } + else if (g_strcmp0(ipversion.c_str(), "IPv6") == 0) + { + GVariant *ip6Property = g_dbus_proxy_get_cached_property(deviceProxy, "Ip6Config"); + if (ip6Property != nullptr) { + g_variant_get(ip6Property, "o", &ip6ConfigPath); + g_variant_unref(ip6Property); + } + else + { + NMLOG_ERROR("Failed to get Ip6Config property"); + g_object_unref(deviceProxy); + } + + GVariant *dhcp6Property = g_dbus_proxy_get_cached_property(deviceProxy, "Dhcp6Config"); + if (dhcp6Property != nullptr) { + g_variant_get(dhcp6Property, "o", &dhcp6ConfigPath); + g_variant_unref(dhcp6Property); + } + else + { + NMLOG_ERROR("Failed to get Dhcp6Config property"); + g_object_unref(deviceProxy); + } + + + ipv6Proxy = m_dbus.getNetworkManagerIpv6Proxy(ip6ConfigPath); + g_free(ip6ConfigPath); + if(ipv6Proxy != nullptr) + { + // Get the 'Addresses' property + GVariant *addressesProperty = g_dbus_proxy_get_cached_property(ipv6Proxy, "Addresses"); + if (addressesProperty != nullptr) + { + gsize numAddresses = g_variant_n_children(addressesProperty); + for (gsize i = 0; i < numAddresses; ++i) { + GVariant *addressTuple = g_variant_get_child_value(addressesProperty, i); + GVariant *addressArray = g_variant_get_child_value(addressTuple, 0); // Get the first byte array (IPv6 address) + GVariant *prefixVariant = g_variant_get_child_value(addressTuple, 1); // Get the prefix + prefix = g_variant_get_uint32(prefixVariant); + + uint8_t ipv6Addr[16]; + gsize addrLen; + gconstpointer addrData = g_variant_get_fixed_array(addressArray, &addrLen, 1); + if (addrLen == 16) { + memcpy(ipv6Addr, addrData, addrLen); + addressStr = GnomeUtils::ip6ToString(ipv6Addr); + if ((ipv6Addr[0] & 0xE0) == 0x20) // Check if the first three bits are within the range for global + { + break; + } + NMLOG_DEBUG("IPv6 Address: %s Prefix: %d", addressStr.c_str(), prefix); + } + + g_variant_unref(addressArray); + g_variant_unref(prefixVariant); + g_variant_unref(addressTuple); + } + } + else + { + NMLOG_ERROR("Failed to get Addresses property for IPv6"); + g_object_unref(ipv6Proxy); + } + g_variant_unref(addressesProperty); + + // Get the 'Gateway' property + GVariant *gatewayProperty = g_dbus_proxy_get_cached_property(ipv6Proxy, "Gateway"); + if (gatewayProperty != nullptr) + { + // Fetch and print the Gateway IP + gatewayIp = g_variant_get_string(gatewayProperty, nullptr); + NMLOG_DEBUG("IPv6 Gateway: %s", gatewayIp); + g_variant_unref(gatewayProperty); + } + else + { + NMLOG_ERROR("Failed to get Gateway property for IPv6"); + g_object_unref(ipv6Proxy); + } + } + GDBusProxy* dhcpv6Proxy = m_dbus.getNetworkManagerDhcpv6Proxy(dhcp6ConfigPath); + g_free(dhcp6ConfigPath); + if(dhcpv6Proxy != nullptr) + { + // Get the 'Options' property + GVariant *optionsProperty = g_dbus_proxy_get_cached_property(dhcpv6Proxy, "Options"); + if (optionsProperty != nullptr) { + + GVariantIter *iter; + gchar *key; + GVariant *value; + gchar *ip6Address = nullptr; + + // Print the whole options property for debugging + gchar *optionsStr = g_variant_print(optionsProperty, TRUE); + NMLOG_DEBUG("Options property: %s", optionsStr); + g_free(optionsStr); + + g_variant_get(optionsProperty, "a{sv}", &iter); + + while (g_variant_iter_next(iter, "{&sv}", &key, &value)) { + gchar *valueStr = g_variant_print(value, TRUE); + NMLOG_DEBUG("Key: %s Value: %s", key, valueStr); + g_free(valueStr); + + if (g_strcmp0(key, "dhcp6_name_servers") == 0) { + dnsAddresses = g_strdup(g_variant_get_string(value, nullptr)); + } else if (g_strcmp0(key, "ip6_address") == 0) { + ip6Address = g_strdup(g_variant_get_string(value, nullptr)); + } + g_variant_unref(value); + } + + g_variant_iter_free(iter); + g_variant_unref(optionsProperty); + g_object_unref(dhcpv6Proxy); + + if (ip6Address) { + NMLOG_DEBUG("IPv6 Address: %s", ip6Address); + g_free(ip6Address); + } else { + NMLOG_ERROR("Failed to find the IPv6 address"); + } + + if (dnsAddresses) { + // DNS addresses are space-separated, we need to split them + dnsList = g_strsplit(dnsAddresses, " ", -1); + if (dnsList[0] != nullptr) { + NMLOG_DEBUG("Primary DNS: %s", dnsList[0]); + if (dnsList[1] != nullptr) { + NMLOG_DEBUG("Secondary DNS: %s ", dnsList[1]); + } else { + NMLOG_DEBUG("Secondary DNS: Not available"); + } + } else { + NMLOG_ERROR("Failed to parse DNS addresses"); + } + } else { + std::cerr << "Failed to find DNS addresses" << std::endl; + } + } + else + { + NMLOG_ERROR("Failed to get Options property for DHCP6"); + g_object_unref(dhcpv6Proxy); + } + } + } + std::string connectionPath; + if (!GnomeUtils::getSettingsConnectionPath(m_dbus, connectionPath, interface)) + { + NMLOG_ERROR("Error: connection path not found for interface %s", interface.c_str()); + return false; + } + + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, interface.c_str(), devInfo)) + return false; + GDBusProxy *settingsProxy = m_dbus.getNetworkManagerSettingsConnectionProxy(connectionPath.c_str()); + + if (settingsProxy == nullptr) { + NMLOG_ERROR("Error creating connection settings proxy: %s",error->message); + g_error_free(error); + return false; + } + + GVariant *connectionSettings = g_dbus_proxy_call_sync( + settingsProxy, + "GetSettings", + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (connectionSettings == nullptr) { + NMLOG_ERROR("Error retrieving connection settings: %s", error->message); + g_error_free(error); + g_object_unref(settingsProxy); + return false; + } + + GVariantIter *iterator; + GVariant *settingsDict; + const gchar *settingsKey; + + g_variant_get(connectionSettings, "(a{sa{sv}})", &iterator); + while (g_variant_iter_loop(iterator, "{&s@a{sv}}", &settingsKey, &settingsDict)) { + GVariantIter settingsIter; + const gchar *key; + GVariant *value; + + g_variant_iter_init(&settingsIter, settingsDict); + while (g_variant_iter_loop(&settingsIter, "{&sv}", &key, &value)) { + if (g_strcmp0(key, "method") == 0) { + if(g_strcmp0(settingsKey, "ipv4") == 0) + { + IPv4Method = g_variant_get_string(value, NULL); + NMLOG_DEBUG("IPV4 Method: %s\n", IPv4Method); + } + else if(g_strcmp0(settingsKey, "ipv6") == 0) + { + IPv6Method = g_variant_get_string(value, NULL); + NMLOG_DEBUG("IPV6 Method: %s\n", IPv6Method); + } + } + } + } + + result.ipversion = ipversion; + result.autoconfig = true; + if(g_strcmp0(ipversion.c_str(), "IPv4") == 0) + result.autoconfig = (g_strcmp0(IPv4Method, "auto") == 0); + else if(g_strcmp0(ipversion.c_str(), "IPv6") == 0) + result.autoconfig = (g_strcmp0(IPv6Method, "auto") == 0); + result.ipaddress = addressStr; + result.prefix = prefix; + result.ula = ""; + result.dhcpserver = (dhcpServerIp != NULL) ? std::string(dhcpServerIp) : ""; + result.gateway = (gatewayIp != NULL) ? std::string(gatewayIp) : ""; + if (dnsList != NULL) + { + result.primarydns = (dnsList[0] != NULL) ? std::string(dnsList[0]) : ""; + result.secondarydns = (dnsList[1] != NULL) ? std::string(dnsList[1]) : ""; + } + else + { + result.primarydns = ""; + result.secondarydns = ""; + } + if(ipv4Proxy != NULL) + g_object_unref(ipv4Proxy); + if(ipv6Proxy != NULL) + g_object_unref(ipv6Proxy); + g_strfreev(dnsList); + g_free(dnsAddresses); + g_free(dhcpServerIp); + + return true; + } + static bool getSSIDFromConnection(DbusMgr &m_dbus, const std::string connPath, std::string& ssid) { GError *error = NULL; @@ -735,7 +1854,7 @@ namespace WPEFramework ssid = ssidInfo.ssid; signalStrength = ssidInfo.strength; - float signalStrengthFloat = 0.0f; + float signalStrengthFloat = 0.0f; if(!signalStrength.empty()) signalStrengthFloat = std::stof(signalStrength.c_str()); diff --git a/gdbus/NetworkManagerGdbusClient.h b/gdbus/NetworkManagerGdbusClient.h index 7e6466525..d1a4bb8a7 100644 --- a/gdbus/NetworkManagerGdbusClient.h +++ b/gdbus/NetworkManagerGdbusClient.h @@ -27,6 +27,8 @@ #include "NetworkManagerGdbusMgr.h" #include "INetworkManager.h" +#define ROUTE_METRIC_PRIORITY_HIGH 10 +#define ROUTE_METRIC_PRIORITY_LOW 100 namespace WPEFramework { namespace Plugin @@ -44,6 +46,13 @@ namespace WPEFramework NetworkManagerClient(const NetworkManagerClient&) = delete; NetworkManagerClient& operator=(const NetworkManagerClient&) = delete; + bool getAvailableInterfaces(std::vector& interfaceList); + bool setPrimaryInterface(const std::string& interface); + bool setInterfaceState(const std::string& interface, bool enable); + bool setIPSettings(const std::string& interface, const Exchange::INetworkManager::IPAddress& address); + bool getPrimaryInterface(std::string& interface); + bool getInterfaceState(const std::string& interface, bool& isEnabled); + bool getIPSettings(const std::string& interface, const std::string& ipversion, Exchange::INetworkManager::IPAddress& result); bool getKnownSSIDs(std::list& ssids); bool getAvailableSSIDs(std::list& ssids); bool getConnectedSSID(Exchange::INetworkManager::WiFiSSIDInfo& ssidinfo); diff --git a/gdbus/NetworkManagerGdbusMgr.cpp b/gdbus/NetworkManagerGdbusMgr.cpp index 310b025dc..71d3374e2 100644 --- a/gdbus/NetworkManagerGdbusMgr.cpp +++ b/gdbus/NetworkManagerGdbusMgr.cpp @@ -38,7 +38,7 @@ namespace WPEFramework NMLOG_FATAL("Error connecting to system D-Bus bus: %s ", error->message); g_error_free(error); } - flags = static_cast(G_DBUS_PROXY_FLAGS_NONE); + flags = G_DBUS_PROXY_FLAGS_NONE; } DbusMgr::~DbusMgr() { @@ -63,7 +63,7 @@ namespace WPEFramework return NULL; } - flags = static_cast(G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START); + flags = G_DBUS_PROXY_FLAGS_NONE; return connection; } @@ -257,6 +257,73 @@ namespace WPEFramework return proxy; } + GDBusProxy* DbusMgr::getNetworkManagerDhcpv4Proxy(const char* dhcpConfigPath) + { + GError* error = nullptr; + GDBusProxy *proxy = g_dbus_proxy_new_sync( + getConnection(), + flags, + nullptr, + "org.freedesktop.NetworkManager", + dhcpConfigPath, + "org.freedesktop.NetworkManager.DHCP4Config", + nullptr, + &error); + + if (proxy == nullptr) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating dhcpv4 proxy: %s", error->message); + g_clear_error(&error); + return nullptr; + } + return proxy; + } + + GDBusProxy* DbusMgr::getNetworkManagerDhcpv6Proxy(const char* dhcpConfigPath) + { + GError* error = nullptr; + GDBusProxy *proxy = g_dbus_proxy_new_sync( + getConnection(), + flags, + nullptr, + "org.freedesktop.NetworkManager", + dhcpConfigPath, + "org.freedesktop.NetworkManager.DHCP6Config", + nullptr, + &error); + + if (proxy == nullptr) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating dhcpv6 proxy: %s", error->message); + g_clear_error(&error); + return nullptr; + } + return proxy; + } + + GDBusProxy* DbusMgr::getNetworkManagerPropertyProxy(const char* devicePath) + { + GError* error = nullptr; + GDBusProxy* proxy = g_dbus_proxy_new_sync( + getConnection(), + flags, + nullptr, + "org.freedesktop.NetworkManager", + devicePath, + "org.freedesktop.DBus.Properties", + nullptr, + &error + ); + + if (proxy == nullptr) { + g_dbus_error_strip_remote_error(error); + NMLOG_ERROR("Failed to create property proxy: %s", error->message); + g_clear_error(&error); + return nullptr; + } + return proxy; + } + } // Plugin } // WPEFramework diff --git a/gdbus/NetworkManagerGdbusMgr.h b/gdbus/NetworkManagerGdbusMgr.h index 8e00c8971..a6c2f81ed 100644 --- a/gdbus/NetworkManagerGdbusMgr.h +++ b/gdbus/NetworkManagerGdbusMgr.h @@ -45,6 +45,9 @@ namespace WPEFramework GDBusProxy* getNetworkManagerActiveConnProxy(const char* activePath); GDBusProxy* getNetworkManagerAccessPointProxy(const char* apPath); GDBusConnection* getConnection(); + GDBusProxy* getNetworkManagerPropertyProxy(const char* devicePath); + GDBusProxy* getNetworkManagerDhcpv4Proxy(const char* dhcpConfigPath); + GDBusProxy* getNetworkManagerDhcpv6Proxy(const char* dhcpConfigPath); private: GDBusConnection* connection; diff --git a/gdbus/NetworkManagerGdbusProxy.cpp b/gdbus/NetworkManagerGdbusProxy.cpp index 576654120..2c68201b2 100644 --- a/gdbus/NetworkManagerGdbusProxy.cpp +++ b/gdbus/NetworkManagerGdbusProxy.cpp @@ -46,38 +46,77 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::GetAvailableInterfaces (Exchange::INetworkManager::IInterfaceDetailsIterator*& interfacesItr/* @out */) { - return Core::ERROR_NONE; + uint32_t rc = Core::ERROR_GENERAL; + std::vector interfaceList; + if(_nmGdbusClient->getAvailableInterfaces(interfaceList)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("GetAvailableInterfaces failed"); + using Implementation = RPC::IteratorType; + interfacesItr = Core::Service::Create(interfaceList); + + return rc; } uint32_t NetworkManagerImplementation::GetPrimaryInterface (string& interface /* @out */) { - return Core::ERROR_NONE; + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->getPrimaryInterface(interface)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("GetPrimaryInterface failed"); + return rc; } uint32_t NetworkManagerImplementation::SetPrimaryInterface (const string& interface/* @in */) { - return Core::ERROR_NONE; + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->setPrimaryInterface(interface)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("SetPrimaryInterface failed"); + return rc; } uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) { - return Core::ERROR_NONE; + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->setInterfaceState(interface, enabled)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("SetInterfaceState failed"); + return rc; } uint32_t NetworkManagerImplementation::GetInterfaceState(const string& interface/* @in */, bool& isEnabled /* @out */) { - return Core::ERROR_NONE; + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->getInterfaceState(interface, isEnabled)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("GetInterfaceState failed"); + return rc; } /* @brief Get IP Address Of the Interface */ uint32_t NetworkManagerImplementation::GetIPSettings(string& interface /* @inout */, const string &ipversion /* @in */, IPAddress& result /* @out */) { - return Core::ERROR_NONE; + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->getIPSettings(interface, ipversion, result)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("GetIPSettings failed"); + return rc; } /* @brief Set IP Address Of the Interface */ uint32_t NetworkManagerImplementation::SetIPSettings(const string& interface /* @in */, const IPAddress& address /* @in */) { - return Core::ERROR_NONE; + uint32_t rc = Core::ERROR_GENERAL; + if(_nmGdbusClient->setIPSettings(interface, address)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("SetIPSettings failed"); + return rc; } uint32_t NetworkManagerImplementation::StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) diff --git a/gdbus/NetworkManagerGdbusUtils.cpp b/gdbus/NetworkManagerGdbusUtils.cpp index dc893292d..ad1ee6d82 100644 --- a/gdbus/NetworkManagerGdbusUtils.cpp +++ b/gdbus/NetworkManagerGdbusUtils.cpp @@ -20,12 +20,14 @@ #include #include #include +#include #include #include "NetworkManagerLogger.h" #include "NetworkManagerGdbusUtils.h" #include "NetworkManagerGdbusMgr.h" #include +#include // for struct in_addr namespace WPEFramework { @@ -214,20 +216,55 @@ namespace WPEFramework return true; } + bool GnomeUtils::getCachedPropertyBoolean(GDBusProxy* proxy, const char* property, bool *value) + { + GVariant* result = nullptr; + result = g_dbus_proxy_get_cached_property(proxy, property); + if (result == nullptr) { + NMLOG_ERROR("Failed to get '%s' properties", property); + return false; + } + + if (g_variant_is_of_type(result, G_VARIANT_TYPE_BOOLEAN)) { + *value = g_variant_get_boolean(result); + } + else + NMLOG_WARNING("Unexpected type returned property: %s", g_variant_get_type_string(result)); + g_variant_unref(result); + return true; + } + bool GnomeUtils::getDevicePropertiesByPath(DbusMgr& m_dbus, const char* devicePath, deviceInfo& properties) { GVariant *devicesVar = NULL; GDBusProxy* nmProxy = NULL; - u_int32_t value; + u_int32_t value = 0; + bool managedValue; nmProxy = m_dbus.getNetworkManagerDeviceProxy(devicePath); if(nmProxy == NULL) return false; if(GnomeUtils::getCachedPropertyU(nmProxy, "DeviceType", &value)) - properties.deviceType = static_cast(value); + properties.deviceType = static_cast(value); + else + NMLOG_ERROR("'DeviceType' property failed"); + + if(GnomeUtils::getCachedPropertyBoolean(nmProxy, "Managed", &managedValue)) + properties.managed = managedValue; else - NMLOG_ERROR("'DeviceType' property failed"); + NMLOG_ERROR("'Managed' property failed"); + devicesVar = g_dbus_proxy_get_cached_property(nmProxy, "HwAddress"); + if (devicesVar) { + const gchar *mac = g_variant_get_string(devicesVar, NULL); + if(mac != NULL) + { + properties.MAC = mac; + } + g_variant_unref(devicesVar); + } + else + NMLOG_ERROR("'mac' property failed"); devicesVar = g_dbus_proxy_get_cached_property(nmProxy, "Interface"); if (devicesVar) { @@ -236,7 +273,6 @@ namespace WPEFramework { properties.interface = iface; } - //NMLOG_DEBUG("Interface: %s", iface); g_variant_unref(devicesVar); } else @@ -302,49 +338,39 @@ namespace WPEFramework return ret; } - bool GnomeUtils::getDeviceByIpIface(DbusMgr& m_dbus, const gchar *iface_name, std::string& path) + bool GnomeUtils::getDeviceByIpIface(DbusMgr& m_dbus, const gchar *ifaceName, std::string& path) { - // TODO Fix Error calling method: - // GDBus.Error:org.freedesktop.NetworkManager.UnknownDevice: No device found for the requested iface - // in wsl linux - GError *error = NULL; - GVariant *result; - gchar *device_path = NULL; - bool ret = false; + GError *error = nullptr; + GDBusProxy* nmProxy = m_dbus.getNetworkManagerProxy(); + if(nmProxy == NULL) + return false; - result = g_dbus_connection_call_sync( - m_dbus.getConnection(), - "org.freedesktop.NetworkManager", // D-Bus name - "/org/freedesktop/NetworkManager", // Object path - "org.freedesktop.NetworkManager", // Interface - "GetDeviceByIpIface", // Method name - g_variant_new("(s)", iface_name), // Input parameter (the interface name) - G_VARIANT_TYPE("(o)"), // Expected return type (object path) - G_DBUS_CALL_FLAGS_NONE, - -1, // Default timeout - NULL, - &error - ); - - if (error != NULL) { - NMLOG_ERROR("calling GetDeviceByIpIface: %s", error->message); - g_error_free(error); - return ret; + GVariant *result = g_dbus_proxy_call_sync( + nmProxy, + "GetDeviceByIpIface", + g_variant_new("(s)", ifaceName), + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (result == nullptr) { + NMLOG_ERROR("Error calling GetDeviceByIpIface: %s", error->message); + g_clear_error(&error); + g_object_unref(nmProxy); + return false; } - if (g_variant_is_of_type (result, (const GVariantType *) "(o)")) - { - g_variant_get(result, "(o)", &device_path); - if(device_path != NULL) - { - path = std::string(device_path); - ret = true; - g_free(device_path); - } - } - //NMLOG_DEBUG("%s device path %s", iface_name, path.c_str()); + gchar *devicePath; + g_variant_get(result, "(o)", &devicePath); + g_variant_unref(result); - return ret; + g_object_unref(nmProxy); + + path = std::string(devicePath); + g_free(devicePath); + + return true; } bool GnomeUtils::getApDetails(DbusMgr& m_dbus, const char* apPath, Exchange::INetworkManager::WiFiSSIDInfo& wifiInfo) @@ -546,6 +572,167 @@ namespace WPEFramework return true; } + bool GnomeUtils::activateConnection(DbusMgr& m_dbus, const std::string& connectionProfile, const std::string& devicePath) + { + GError* error = nullptr; + GDBusProxy* nmProxy = m_dbus.getNetworkManagerProxy(); + if(nmProxy == NULL) + return false; + + GVariant* result = g_dbus_proxy_call_sync( + nmProxy, + "ActivateConnection", + g_variant_new("(ooo)", connectionProfile.c_str(), devicePath.c_str(), "/"), + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error + ); + + if (error) { + NMLOG_ERROR("ActivateConnection Error: %s", error->message); + g_error_free(error); + } else if (result != nullptr) { + g_variant_unref(result); + } + return true; + } + + bool GnomeUtils::getSettingsConnectionPath(DbusMgr &m_dbus, std::string& connectionPath, const std::string& interface) + { + GDBusProxy *nmProxy = nullptr; + bool found = false; + nmProxy = m_dbus.getNetworkManagerProxy(); + if(nmProxy == nullptr) + return false; + GVariant *activeConnections = g_dbus_proxy_get_cached_property(nmProxy, "ActiveConnections"); + if (activeConnections == nullptr) { + NMLOG_ERROR("Error retrieving active connections"); + g_object_unref(nmProxy); + return false; + } + + GVariantIter iter; + g_variant_iter_init(&iter, activeConnections); + gchar *activeConnectionPath = nullptr; + while (g_variant_iter_loop(&iter, "o", &activeConnectionPath)) { + GDBusProxy *activeConnectionProxy = m_dbus.getNetworkManagerActiveConnProxy(activeConnectionPath); + + if (activeConnectionProxy == nullptr) { + NMLOG_ERROR("Error creating active connection proxy"); + continue; + } + + GVariant *devicesVar = g_dbus_proxy_get_cached_property(activeConnectionProxy, "Devices"); + if (devicesVar == nullptr) { + NMLOG_ERROR("Error retrieving devices property"); + g_object_unref(activeConnectionProxy); + continue; + } + + GVariantIter devicesIter; + g_variant_iter_init(&devicesIter, devicesVar); + gchar *devicePath = nullptr; + + while (g_variant_iter_loop(&devicesIter, "o", &devicePath)) { + GDBusProxy *deviceProxy = m_dbus.getNetworkManagerDeviceProxy(devicePath); + + if (deviceProxy == nullptr) { + NMLOG_ERROR("Error creating device proxy"); + continue; + } + + GVariant *ifaceProperty = g_dbus_proxy_get_cached_property(deviceProxy, "Interface"); + if (ifaceProperty) { + const gchar *iface = g_variant_get_string(ifaceProperty, nullptr); + if (interface == iface) { + found = true; + GVariant *connectionProperty = g_dbus_proxy_get_cached_property(activeConnectionProxy, "Connection"); + if (connectionProperty) { + connectionPath = g_variant_get_string(connectionProperty, nullptr); + g_variant_unref(connectionProperty); + } else { + NMLOG_ERROR("Error retrieving connection property"); + } + + g_variant_unref(ifaceProperty); + g_object_unref(deviceProxy); + break; + } + g_variant_unref(ifaceProperty); + } + + g_object_unref(deviceProxy); + } + g_variant_unref(devicesVar); + g_object_unref(activeConnectionProxy); + + if (found) { + break; + } + } + + g_variant_unref(activeConnections); + g_object_unref(nmProxy); + return true; + } + + // Convert IPv4 string to network byte order (NBO) + uint32_t GnomeUtils::ip4StrToNBO(const std::string &ipAddress) + { + struct in_addr addr; + if (inet_pton(AF_INET, ipAddress.c_str(), &addr) != 1) { + NMLOG_ERROR("Invalid IPv4 address format: %s", ipAddress.c_str()); + } + return addr.s_addr; + } + + // Convert an IPv6 string address to an array of bytes + std::array GnomeUtils::ip6StrToNBO(const std::string &ipAddress) + { + struct in6_addr addr6; + inet_pton(AF_INET6, ipAddress.c_str(), &addr6); + std::array ip6{}; + std::memcpy(ip6.data(), &addr6, 16); + return ip6; + } + + // Helper function to convert a raw IPv4 address to human-readable format + std::string GnomeUtils::ip4ToString(uint32_t ip) { + ip = ntohl(ip); // Convert from network to host byte order + char buf[INET_ADDRSTRLEN] = {0}; + snprintf(buf, sizeof(buf), "%u.%u.%u.%u", + (ip >> 24) & 0xFF, + (ip >> 16) & 0xFF, + (ip >> 8) & 0xFF, + ip & 0xFF); + return std::string(buf); + } + + // Helper function to convert a raw IPv6 address to human-readable format + std::string GnomeUtils::ip6ToString(const uint8_t *ipv6) { + char buf[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, ipv6, buf, sizeof(buf)); + return std::string(buf); + } + + // Helper function to add elements from GVariant to GVariantBuilder + void GnomeUtils::addGvariantToBuilder(GVariant *variant, GVariantBuilder *builder, gboolean excludeRouteMetric) { + GVariantIter iter; + + const gchar *key; + GVariant *value; + g_variant_iter_init(&iter, variant); + + // Iterate through key-value pairs in the dictionary + while (g_variant_iter_loop(&iter, "{&sv}", &key, &value)) { + if (excludeRouteMetric && strcmp(key, "route-metric") == 0) { + // Skip adding this key-value pair if exclude_route_metric is TRUE and key is "route-metric" + continue; + } + g_variant_builder_add(builder, "{sv}", key, value); + } + } } // Plugin } // WPEFramework diff --git a/gdbus/NetworkManagerGdbusUtils.h b/gdbus/NetworkManagerGdbusUtils.h index 6366ff715..40f5d3450 100644 --- a/gdbus/NetworkManagerGdbusUtils.h +++ b/gdbus/NetworkManagerGdbusUtils.h @@ -48,6 +48,8 @@ struct deviceInfo std::string interface; std::string activeConnPath; std::string path; + std::string MAC; + bool managed; NMDeviceState state; NMDeviceStateReason stateReason; NMDeviceType deviceType; @@ -72,8 +74,16 @@ namespace WPEFramework static bool getDevicePropertiesByPath(DbusMgr& m_dbus, const char* devPath, deviceInfo& properties); static bool getDeviceInfoByIfname(DbusMgr& m_dbus, const char* ifname, deviceInfo& properties); static bool getCachedPropertyU(GDBusProxy* proxy, const char* propertiy, uint32_t *value); + static bool getCachedPropertyBoolean(GDBusProxy* proxy, const char* property, bool *value); static bool getIPv4AddrFromIPv4ConfigProxy(GDBusProxy *ipProxy, std::string& ipAddr, uint32_t& prifix); static bool getIPv6AddrFromIPv6ConfigProxy(GDBusProxy *ipProxy, std::string& ipAddr, uint32_t& prifix); + static bool activateConnection(DbusMgr& m_dbus, const std::string& connectionProfile, const std::string& devicePath); + static bool getSettingsConnectionPath(DbusMgr &m_dbus, std::string& connectionPath, const std::string& interface); + static uint32_t ip4StrToNBO(const std::string &ipAddress); + static std::array ip6StrToNBO(const std::string &ipAddress); + static std::string ip4ToString(uint32_t ip); + static std::string ip6ToString(const uint8_t *ipv6); + static void addGvariantToBuilder(GVariant *variant, GVariantBuilder *builder, gboolean excludeRouteMetric); static bool convertSsidInfoToJsonObject(Exchange::INetworkManager::WiFiSSIDInfo& wifiInfo, JsonObject& ssidObj); static const char* convertPercentageToSignalStrengtStr(int percentage); From 8f7b8d6f15d2a75f9c7593077cf98d234f3bc5c1 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 23 Jan 2025 11:57:57 -0500 Subject: [PATCH 076/271] RDK-55248 - Implement org.rdk.Wifi.retrieveSSID API (#78) * RDK-55248 - Implement org.rdk.Wifi.retrieveSSID API Reason for change: Implement retrieveSSID API for legacy WiFi plugin Test Procedure: Build and verified Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR RDK-55421 : Implement org.rdk.Wifi.retrieveSSID API (#82) Reason for change: Implement retrieveSSID API for legacy WiFi plugin Test Procedure: Build and verified Risks: Low Priority: P1 Signed-off-by: Anand N Co-Authored-By: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- LegacyPlugin_WiFiManagerAPIs.cpp | 95 ++++++++++++++++++++++++++++++++ LegacyPlugin_WiFiManagerAPIs.h | 1 + 2 files changed, 96 insertions(+) diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index 651de85b3..2c7f42541 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -16,6 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ +#include #include "LegacyPlugin_WiFiManagerAPIs.h" #include "NetworkManagerLogger.h" #include "NetworkManagerJsonEnum.h" @@ -27,6 +28,7 @@ using namespace WPEFramework::Plugin; #define API_VERSION_NUMBER_PATCH 0 #define NETWORK_MANAGER_CALLSIGN "org.rdk.NetworkManager.1" #define SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS 500 +#define WPA_SUPPLICANT_CONF "/opt/secure/wifi/wpa_supplicant.conf" #define LOG_INPARAM() { string json; parameters.ToString(json); NMLOG_INFO("params=%s", json.c_str() ); } #define LOG_OUTPARAM() { string json; response.ToString(json); NMLOG_INFO("response=%s", json.c_str() ); } @@ -209,6 +211,7 @@ namespace WPEFramework Register("saveSSID", &WiFiManager::saveSSID, this); Register("startScan", &WiFiManager::startScan, this); Register("stopScan", &WiFiManager::stopScan, this); + Register("retrieveSSID", &WiFiManager::retrieveSSID, this); } /** @@ -230,6 +233,7 @@ namespace WPEFramework Unregister("saveSSID"); Unregister("startScan"); Unregister("stopScan"); + Unregister("retrieveSSID"); } uint32_t WiFiManager::cancelWPSPairing (const JsonObject& parameters, JsonObject& response) @@ -607,6 +611,97 @@ namespace WPEFramework returnJson(rc); } + uint32_t WiFiManager::retrieveSSID (const JsonObject& parameters, JsonObject& response) + { + uint32_t rc = Core::ERROR_GENERAL; + std::string line; + std::string securityPattern = "key_mgmt="; + std::string ssidPattern = "ssid="; + std::string passphrasePattern = "psk="; + std::string security, ssid, passphrase; + + std::ifstream configFile(WPA_SUPPLICANT_CONF); + if (!configFile.is_open()) + { + NMLOG_ERROR("Not able to open the file %s", WPA_SUPPLICANT_CONF); + response["success"] = false; + rc = Core::ERROR_NOT_EXIST; + return rc; + } + + while (std::getline(configFile, line)) + { + NMLOG_DEBUG("Attempting to read the configuration to populate SSID specific information"); + size_t pos; + + // Fetch ssid value + if (ssid.empty()) { + pos = line.find(ssidPattern); + if (pos != std::string::npos) + { + pos += ssidPattern.length(); + size_t end = line.find('"', pos + 1); + if (end == std::string::npos) + { + end = line.length(); + } + ssid = line.substr(pos + 1, end - pos - 1); + NMLOG_DEBUG("SSID found"); + continue; + } + } + + if (!ssid.empty()) { + // Fetch security value + pos = line.find(securityPattern); + if (pos != std::string::npos) + { + pos += securityPattern.length(); + size_t end = line.find(' ', pos); + if (end == std::string::npos) + { + end = line.length(); + } + security = line.substr(pos, end - pos); + continue; + } + + // Fetch passphare value + pos = line.find(passphrasePattern); + if (pos != std::string::npos) + { + pos += passphrasePattern.length(); + size_t end = line.find('"', pos + 1); + if (end == std::string::npos) + { + end = line.length(); + } + passphrase = line.substr(pos + 1, end - pos - 1); + } + NMLOG_DEBUG("Fetched SSID = %s, security = %s", ssid.c_str(), security.c_str()); + } + } + configFile.close(); + if (!ssid.empty()) + { + response["ssid"] = ssid; + //As enterprise data is not persisted, WPA_EAP mode is not considered here + if(security == "NONE") + response["securityMode"] = JsonValue(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE); + else if(security == "SAE") + response["securityMode"] = JsonValue(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE); + else + response["securityMode"] = JsonValue(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES); + /* WPA3_PSK_AES has backward compatibility for PSK. So WPA-PSK is considered as default */ + response["passphrase"] = passphrase; + response["success"] = true; + rc = Core::ERROR_NONE; + } + else + response["success"] = false; + return rc; + } + /** Private */ void WiFiManager::subscribeToEvents(void) { diff --git a/LegacyPlugin_WiFiManagerAPIs.h b/LegacyPlugin_WiFiManagerAPIs.h index 96be2970b..d05fd1286 100644 --- a/LegacyPlugin_WiFiManagerAPIs.h +++ b/LegacyPlugin_WiFiManagerAPIs.h @@ -73,6 +73,7 @@ namespace WPEFramework { uint32_t getPairedSSIDInfo(const JsonObject& parameters, JsonObject& response); uint32_t isPaired(const JsonObject& parameters, JsonObject& response); uint32_t getSupportedSecurityModes(const JsonObject& parameters, JsonObject& response); + uint32_t retrieveSSID(const JsonObject& parameters, JsonObject& response); //End methods //Begin events From 7a1e2eac5be70993d930b1cfec4e9321b4af8011 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 27 Jan 2025 11:50:49 -0500 Subject: [PATCH 077/271] wpsAction() function modification (#84) * wpsAction() function modification Reason for change: Checked the ssid string is empty before finding the pattern in the file Test Procedure: Build and verified with ubuntu desktop Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR Gururaja_ErodeSriranganRamlingham@comcast.com --- NetworkManagerGnomeWIFI.cpp | 40 ++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 685e17664..4c909313a 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -960,11 +960,13 @@ namespace WPEFramework void wifiManager::wpsAction() { FILE *fp = nullptr; + const std::string securityPattern = "key_mgmt="; + const std::string ssidPattern = "ssid="; + const std::string passphrasePattern = "psk="; std::string line = ""; - std::string securityPattern = "key_mgmt="; - std::string ssidPattern = "ssid="; - std::string passphrasePattern = "psk="; - std::string security = "", ssid = "", passphrase = ""; + std::string security = ""; + std::string ssid = ""; + std::string passphrase = ""; std::string wpaCliResult = ""; gboolean wpsConnect = false; struct timespec startTime = {}, endTime = {}; @@ -1003,7 +1005,7 @@ namespace WPEFramework for (guint apCount = 0; apCount < aps->len; apCount++) { NMAccessPoint *ap = static_cast(g_ptr_array_index(aps, apCount)); guint32 flags = nm_access_point_get_flags(ap); - GBytes *ssid; + GBytes *ssidBytes; gsize size; std::string ssidStr; @@ -1017,8 +1019,8 @@ namespace WPEFramework apList[wpsApCount].bssid[sizeof(apList[wpsApCount].bssid) - 1] = '\0'; } NMLOG_DEBUG("PBC enabled access point bssid = %s", bssid); - ssid = nm_access_point_get_ssid(ap); - const guint8 *ssidData = static_cast(g_bytes_get_data(ssid, &size)); + ssidBytes = nm_access_point_get_ssid(ap); + const guint8 *ssidData = static_cast(g_bytes_get_data(ssidBytes, &size)); std::string ssidTmp(reinterpret_cast(ssidData), size); strncpy(apList[wpsApCount].ssid, ssidTmp.c_str(), sizeof(apList[wpsApCount].ssid) - 1); apList[wpsApCount].ssid[sizeof(apList[wpsApCount].ssid) - 1] = '\0'; @@ -1111,19 +1113,21 @@ namespace WPEFramework size_t pos; // Fetch ssid value - pos = line.find(ssidPattern); - if (pos != std::string::npos) - { - pos += ssidPattern.length(); - size_t end = line.find('"', pos + 1); - if (end == std::string::npos) + if (ssid.empty()) { + pos = line.find(ssidPattern); + if (pos != std::string::npos) { - end = line.length(); + pos += ssidPattern.length(); + size_t end = line.find('"', pos + 1); + if (end == std::string::npos) + { + end = line.length(); + } + ssid = line.substr(pos + 1, end - pos - 1); + wpsConnect = true; + NMLOG_DEBUG("SSID found"); + continue; } - ssid = line.substr(pos + 1, end - pos - 1); - wpsConnect = true; - NMLOG_DEBUG("SSID found"); - continue; } if (wpsConnect) { From 8d00d037a727c038a4df233ee979bec8c89cffd5 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 28 Jan 2025 15:49:55 -0500 Subject: [PATCH 078/271] DELIA-67307 - NetworkManager Thunder Plugin - Redefine Security Mode (#83) * DELIA-67307 - NetworkManager Thunder Plugin - Redefine Security Mode Reason for change: Redefined security modes to have only below types NONE WPA-PSK SAE WPA-EAP Test Procedure: Verify with curl commands Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR Gururaja_ErodeSriranganRamlingham@comcast.com Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- INetworkManager.h | 19 +-- LegacyPlugin_WiFiManagerAPIs.cpp | 145 ++++++++++++++---- LegacyPlugin_WiFiManagerAPIs.h | 13 -- NetworkManager.json | 63 ++------ NetworkManagerGnomeUtils.cpp | 47 +++--- NetworkManagerGnomeWIFI.cpp | 16 +- NetworkManagerImplementation.cpp | 19 +-- NetworkManagerJsonEnum.h | 18 --- NetworkManagerRDKProxy.cpp | 64 +++++++- Tests/raspberrypi/NetworkManagerGdbusTest.cpp | 8 +- docs/NetworkManagerPlugin.md | 38 +---- gdbus/NetworkManagerGdbusClient.cpp | 11 +- gdbus/NetworkManagerGdbusUtils.cpp | 22 +-- 13 files changed, 247 insertions(+), 236 deletions(-) diff --git a/INetworkManager.h b/INetworkManager.h index 26d633746..fa3663469 100644 --- a/INetworkManager.h +++ b/INetworkManager.h @@ -97,21 +97,10 @@ namespace WPEFramework enum WIFISecurityMode : uint8_t { - WIFI_SECURITY_NONE, - WIFI_SECURITY_WEP_64, - WIFI_SECURITY_WEP_128, - WIFI_SECURITY_WPA_PSK_TKIP, - WIFI_SECURITY_WPA_PSK_AES, - WIFI_SECURITY_WPA2_PSK_TKIP, - WIFI_SECURITY_WPA2_PSK_AES, - WIFI_SECURITY_WPA_ENTERPRISE_TKIP, - WIFI_SECURITY_WPA_ENTERPRISE_AES, - WIFI_SECURITY_WPA2_ENTERPRISE_TKIP, - WIFI_SECURITY_WPA2_ENTERPRISE_AES, - WIFI_SECURITY_WPA_WPA2_PSK, - WIFI_SECURITY_WPA_WPA2_ENTERPRISE, - WIFI_SECURITY_WPA3_PSK_AES, - WIFI_SECURITY_WPA3_SAE + WIFI_SECURITY_NONE /* @text: NONE */, + WIFI_SECURITY_WPA_PSK /* @text: WPA-PSK */, + WIFI_SECURITY_SAE /* @text: SAE */, + WIFI_SECURITY_EAP /* @text: EAP */, }; struct EXTERNAL WiFiScanResults { diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index 2c7f42541..b80eb0e1e 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -43,6 +43,39 @@ using namespace WPEFramework::Plugin; return rc; \ } +/*! Error code: A recoverable, unexpected error occurred, + * as defined by one of the following values */ +typedef enum _WiFiErrorCode_t { + WIFI_SSID_CHANGED, /**< The SSID of the network changed */ + WIFI_CONNECTION_LOST, /**< The connection to the network was lost */ + WIFI_CONNECTION_FAILED, /**< The connection failed for an unknown reason */ + WIFI_CONNECTION_INTERRUPTED, /**< The connection was interrupted */ + WIFI_INVALID_CREDENTIALS, /**< The connection failed due to invalid credentials */ + WIFI_NO_SSID, /**< The SSID does not exist */ + WIFI_UNKNOWN, /**< Any other error */ + WIFI_AUTH_FAILED /**< The connection failed due to auth failure */ +} WiFiErrorCode_t; + +typedef enum _SsidSecurity +{ + NET_WIFI_SECURITY_NONE = 0, + NET_WIFI_SECURITY_WEP_64, + NET_WIFI_SECURITY_WEP_128, + NET_WIFI_SECURITY_WPA_PSK_TKIP, + NET_WIFI_SECURITY_WPA_PSK_AES, + NET_WIFI_SECURITY_WPA2_PSK_TKIP, + NET_WIFI_SECURITY_WPA2_PSK_AES, + NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP, + NET_WIFI_SECURITY_WPA_ENTERPRISE_AES, + NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP, + NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES, + NET_WIFI_SECURITY_WPA_WPA2_PSK, + NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE, + NET_WIFI_SECURITY_WPA3_PSK_AES, + NET_WIFI_SECURITY_WPA3_SAE, + NET_WIFI_SECURITY_NOT_SUPPORTED = 99, +} SsidSecurity; + namespace WPEFramework { class Job : public Core::IDispatch { @@ -236,6 +269,53 @@ namespace WPEFramework Unregister("retrieveSSID"); } + static inline uint32_t mapToLegacySecurityMode(const uint32_t securityMode) + { + if (securityMode == 0) + return 0; /* NET_WIFI_SECURITY_NONE */ + else if (securityMode == 1) + return 6; /* NET_WIFI_SECURITY_WPA2_PSK_AES */ + else if (securityMode == 2) + return 14; /* NET_WIFI_SECURITY_WPA3_SAE */ + else if (securityMode == 3) + return 12; /* NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE */ + + return 0; /* NET_WIFI_SECURITY_NONE */ + } + + static inline uint32_t mapToNewSecurityMode(const uint32_t legacyMode) + { + if ((legacyMode == NET_WIFI_SECURITY_NONE) || + (legacyMode == NET_WIFI_SECURITY_WEP_64) || + (legacyMode == NET_WIFI_SECURITY_WEP_128)) + { + return 0; /* WIFI_SECURITY_NONE */ + } + else if ((legacyMode == NET_WIFI_SECURITY_WPA_PSK_TKIP) || + (legacyMode == NET_WIFI_SECURITY_WPA_PSK_AES) || + (legacyMode == NET_WIFI_SECURITY_WPA2_PSK_TKIP) || + (legacyMode == NET_WIFI_SECURITY_WPA2_PSK_AES) || + (legacyMode == NET_WIFI_SECURITY_WPA_WPA2_PSK) || + (legacyMode == NET_WIFI_SECURITY_WPA3_PSK_AES)) + { + return 1; /* WIFI_SECURITY_WPA_PSK */ + } + else if (legacyMode == NET_WIFI_SECURITY_WPA3_SAE) + { + return 2; /* WIFI_SECURITY_SAE */ + } + else if ((legacyMode == NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP) || + (legacyMode == NET_WIFI_SECURITY_WPA_ENTERPRISE_AES) || + (legacyMode == NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP) || + (legacyMode == NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES) || + (legacyMode == NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE)) + { + return 3; /* WIFI_SECURITY_EAP */ + } + + return 0; /* WIFI_SECURITY_NONE */ + } + uint32_t WiFiManager::cancelWPSPairing (const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); @@ -293,7 +373,7 @@ namespace WPEFramework ssid.passphrase = parameters["passphrase"].String(); if (parameters.HasLabel("securityMode")) - ssid.security= static_cast (parameters["securityMode"].Number()); + ssid.security= static_cast (mapToNewSecurityMode(parameters["securityMode"].Number())); ssid.persist = true; @@ -330,7 +410,7 @@ namespace WPEFramework response["bssid"] = ssidInfo.bssid; response["rate"] = ssidInfo.rate; response["noise"] = ssidInfo.noise; - response["security"] = JsonValue(ssidInfo.security); + response["security"] = JsonValue(mapToLegacySecurityMode(ssidInfo.security)); response["signalStrength"] = ssidInfo.strength; response["frequency"] = ssidInfo.frequency; } @@ -425,30 +505,26 @@ namespace WPEFramework { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - Exchange::INetworkManager::ISecurityModeIterator* securityModes{}; + JsonObject security_modes; + security_modes["NET_WIFI_SECURITY_NONE"] = (int)NET_WIFI_SECURITY_NONE; + security_modes["NET_WIFI_SECURITY_WEP_64"] = (int)NET_WIFI_SECURITY_WEP_64; + security_modes["NET_WIFI_SECURITY_WEP_128"] = (int)NET_WIFI_SECURITY_WEP_128; + security_modes["NET_WIFI_SECURITY_WPA_PSK_TKIP"] = (int)NET_WIFI_SECURITY_WPA_PSK_TKIP; + security_modes["NET_WIFI_SECURITY_WPA_PSK_AES"] = (int)NET_WIFI_SECURITY_WPA_PSK_AES; + security_modes["NET_WIFI_SECURITY_WPA2_PSK_TKIP"] = (int)NET_WIFI_SECURITY_WPA2_PSK_TKIP; + security_modes["NET_WIFI_SECURITY_WPA2_PSK_AES"] = (int)NET_WIFI_SECURITY_WPA2_PSK_AES; + security_modes["NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP"] = (int)NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP; + security_modes["NET_WIFI_SECURITY_WPA_ENTERPRISE_AES"] = (int)NET_WIFI_SECURITY_WPA_ENTERPRISE_AES; + security_modes["NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP"] = (int)NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP; + security_modes["NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES"] = (int)NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES; + security_modes["NET_WIFI_SECURITY_WPA_WPA2_PSK"] = (int)NET_WIFI_SECURITY_WPA_WPA2_PSK; + security_modes["NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE"] = (int)NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE; + security_modes["NET_WIFI_SECURITY_WPA3_PSK_AES"] = (int)NET_WIFI_SECURITY_WPA3_PSK_AES; + security_modes["NET_WIFI_SECURITY_WPA3_SAE"] = (int)NET_WIFI_SECURITY_WPA3_SAE; + security_modes["NET_WIFI_SECURITY_NOT_SUPPORTED"] = (int)NET_WIFI_SECURITY_NOT_SUPPORTED; + + response["security_modes"] = security_modes; - auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); - if (_nwmgr) - { - rc = _nwmgr->GetSupportedSecurityModes(securityModes); - _nwmgr->Release(); - } - else - rc = Core::ERROR_UNAVAILABLE; - - if (Core::ERROR_NONE == rc) - { - if (securityModes != nullptr) - { - JsonObject modes{}; - Exchange::INetworkManager::WIFISecurityModeInfo _resultItem_{}; - while (securityModes->Next(_resultItem_) == true) - { - response.Set(_resultItem_.securityName.c_str(), JsonValue(_resultItem_.security)); - } - securityModes->Release(); - } - } returnJson(rc); } @@ -480,7 +556,7 @@ namespace WPEFramework { ssid.ssid = parameters["ssid"].String(); ssid.passphrase = parameters["passphrase"].String(); - ssid.security = static_cast (parameters["security"].Number()); + ssid.security = static_cast (mapToNewSecurityMode(parameters["security"].Number())); auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); if (_nwmgr) @@ -689,9 +765,9 @@ namespace WPEFramework if(security == "NONE") response["securityMode"] = JsonValue(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE); else if(security == "SAE") - response["securityMode"] = JsonValue(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE); + response["securityMode"] = JsonValue(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE); else - response["securityMode"] = JsonValue(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES); + response["securityMode"] = JsonValue(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK); /* WPA3_PSK_AES has backward compatibility for PSK. So WPA-PSK is considered as default */ response["passphrase"] = passphrase; response["success"] = true; @@ -829,10 +905,21 @@ namespace WPEFramework void WiFiManager::onAvailableSSIDs(const JsonObject& parameters) { string json; + JsonArray ssidsUpdated; + JsonObject newParameters; + JsonArray ssids = parameters["ssids"].Array(); parameters.ToString(json); NMLOG_INFO("Posting onAvailableSSIDs Event as %s", json.c_str()); + for (int i = 0; i < ssids.Length(); i++) + { + JsonObject object = ssids[i].Object(); + uint32_t security = object["security"].Number(); + object["security"] = mapToLegacySecurityMode(security); + ssidsUpdated.Add(object); + } + newParameters["ssids"] = ssidsUpdated; if(_gWiFiInstance) - _gWiFiInstance->Notify("onAvailableSSIDs", parameters); + _gWiFiInstance->Notify("onAvailableSSIDs", newParameters); else NMLOG_WARNING("Ignoring %s", __FUNCTION__); diff --git a/LegacyPlugin_WiFiManagerAPIs.h b/LegacyPlugin_WiFiManagerAPIs.h index d05fd1286..8227fce00 100644 --- a/LegacyPlugin_WiFiManagerAPIs.h +++ b/LegacyPlugin_WiFiManagerAPIs.h @@ -22,19 +22,6 @@ #include "Module.h" #include "NetworkManagerTimer.h" -/*! Error code: A recoverable, unexpected error occurred, - * as defined by one of the following values */ -typedef enum _WiFiErrorCode_t { - WIFI_SSID_CHANGED, /**< The SSID of the network changed */ - WIFI_CONNECTION_LOST, /**< The connection to the network was lost */ - WIFI_CONNECTION_FAILED, /**< The connection failed for an unknown reason */ - WIFI_CONNECTION_INTERRUPTED, /**< The connection was interrupted */ - WIFI_INVALID_CREDENTIALS, /**< The connection failed due to invalid credentials */ - WIFI_NO_SSID, /**< The SSID does not exist */ - WIFI_UNKNOWN, /**< Any other error */ - WIFI_AUTH_FAILED /**< The connection failed due to auth failure */ -} WiFiErrorCode_t; - namespace WPEFramework { namespace Plugin { diff --git a/NetworkManager.json b/NetworkManager.json index ed3e481ab..d841e17e8 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -1250,68 +1250,33 @@ "summary": "The supported security modes and its associated integer value.", "type": "object", "properties": { - "NET_WIFI_SECURITY_NONE": { + "NONE": { + "summary": "Security mode for open network", "type": "integer", "example": 0 }, - "NET_WIFI_SECURITY_WEP_64": { + "WPA_PSK": { + "summary": "Supports security mode WPA,WPA-PSK,WPA2-PSK, WPA3-Personal-Transition", "type": "integer", "example": 1 }, - "NET_WIFI_SECURITY_WEP_128": { + "SAE": { + "summary": "Supports security mode WPA3-Personal", "type": "integer", "example": 2 }, - "NET_WIFI_SECURITY_WPA_PSK_TKIP": { + "EAP": { + "summary": "Supports security mode WPA enterpise", "type": "integer", "example": 3 - }, - "NET_WIFI_SECURITY_WPA_PSK_AES": { - "type": "integer", - "example": 4 - }, - "NET_WIFI_SECURITY_WPA2_PSK_TKIP": { - "type": "integer", - "example": 5 - }, - "NET_WIFI_SECURITY_WPA2_PSK_AES": { - "type": "integer", - "example": 6 - }, - "NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP": { - "type": "integer", - "example": 7 - }, - "NET_WIFI_SECURITY_WPA_ENTERPRISE_AES": { - "type": "integer", - "example": 8 - }, - "NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP": { - "type": "integer", - "example": 9 - }, - "NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES": { - "type": "integer", - "example": 10 - }, - "NET_WIFI_SECURITY_WPA_WPA2_PSK": { - "type": "integer", - "example": 11 - }, - "NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE": { - "type": "integer", - "example": 12 - }, - "NET_WIFI_SECURITY_WPA3_PSK_AES": { - "type": "integer", - "example": 13 - }, - "NET_WIFI_SECURITY_WPA3_SAE": { - "type": "integer", - "example": 14 } }, - "required": [] + "required": [ + "NONE", + "WPA_PSK", + "SAE", + "EAP" + ] }, "success":{ "$ref": "#/definitions/success" diff --git a/NetworkManagerGnomeUtils.cpp b/NetworkManagerGnomeUtils.cpp index 921168211..5a81695e0 100644 --- a/NetworkManagerGnomeUtils.cpp +++ b/NetworkManagerGnomeUtils.cpp @@ -60,30 +60,29 @@ namespace WPEFramework uint8_t nmUtils::wifiSecurityModeFromAp(guint32 flags, guint32 wpaFlags, guint32 rsnFlags) { - uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; - if ((flags == NM_802_11_AP_FLAGS_NONE) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE; - else if( (flags & NM_802_11_AP_FLAGS_PRIVACY) && ((wpaFlags & NM_802_11_AP_SEC_PAIR_WEP40) || (rsnFlags & NM_802_11_AP_SEC_PAIR_WEP40)) ) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_64; - else if( (flags & NM_802_11_AP_FLAGS_PRIVACY) && ((wpaFlags & NM_802_11_AP_SEC_PAIR_WEP104) || (rsnFlags & NM_802_11_AP_SEC_PAIR_WEP104)) ) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_128; - else if((wpaFlags & NM_802_11_AP_SEC_PAIR_TKIP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_TKIP)) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_TKIP; - else if((wpaFlags & NM_802_11_AP_SEC_PAIR_CCMP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_CCMP)) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES; - else if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) && (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_ENTERPRISE; - else if(rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK; - else if((wpaFlags & NM_802_11_AP_SEC_GROUP_CCMP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_CCMP)) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES; - else if((wpaFlags & NM_802_11_AP_SEC_GROUP_TKIP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_TKIP)) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_TKIP; - else if((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE) || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE; - else - NMLOG_WARNING("security mode not defined (flag: %d, wpaFlags: %d, rsnFlags: %d)", flags, wpaFlags, rsnFlags); - return security; + uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; + if ((flags == NM_802_11_AP_FLAGS_NONE) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE; + + else if((wpaFlags & NM_802_11_AP_SEC_PAIR_TKIP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_TKIP)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + else if((wpaFlags & NM_802_11_AP_SEC_PAIR_CCMP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_CCMP)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + + else if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) && (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP; + else if(rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + else if((wpaFlags & NM_802_11_AP_SEC_GROUP_CCMP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_CCMP)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + else if((wpaFlags & NM_802_11_AP_SEC_GROUP_TKIP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_TKIP)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + + else if((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE) || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE; + else + NMLOG_WARNING("security mode not defined (flag: %d, wpaFlags: %d, rsnFlags: %d)", flags, wpaFlags, rsnFlags); + return security; } // Function to convert percentage (0-100) to dBm string diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 4c909313a..d92247e7d 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -448,12 +448,8 @@ namespace WPEFramework NMSettingWirelessSecurity *sSecurity = NULL; switch(ssidinfo.security) { - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_TKIP: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_TKIP: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE: { if(ssidinfo.passphrase.empty() || ssidinfo.passphrase.length() < 8) { @@ -463,7 +459,7 @@ namespace WPEFramework sSecurity = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); nm_connection_add_setting(m_connection, NM_SETTING(sSecurity)); - if(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE == ssidinfo.security) + if(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE == ssidinfo.security) { NMLOG_INFO("key-mgmt: %s", "sae"); g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,"sae", NULL); @@ -477,11 +473,7 @@ namespace WPEFramework g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_PSK, ssidinfo.passphrase.c_str(), NULL); break; } - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_ENTERPRISE_TKIP: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_ENTERPRISE_AES: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_ENTERPRISE_TKIP: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_ENTERPRISE_AES: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_ENTERPRISE: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP: { NMSetting8021x *s8021X = NULL; GError *error = NULL; diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index ee6b36879..2a7f9dc48 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -555,21 +555,10 @@ namespace WPEFramework { LOG_ENTRY_FUNCTION(); std::vector modeInfo { - {WIFI_SECURITY_NONE, "WIFI_SECURITY_NONE"}, - {WIFI_SECURITY_WEP_64, "WIFI_SECURITY_WEP_64"}, - {WIFI_SECURITY_WEP_128, "WIFI_SECURITY_WEP_128"}, - {WIFI_SECURITY_WPA_PSK_TKIP, "WIFI_SECURITY_WPA_PSK_TKIP"}, - {WIFI_SECURITY_WPA_PSK_AES, "WIFI_SECURITY_WPA_PSK_AES"}, - {WIFI_SECURITY_WPA2_PSK_TKIP, "WIFI_SECURITY_WPA2_PSK_TKIP"}, - {WIFI_SECURITY_WPA2_PSK_AES, "WIFI_SECURITY_WPA2_PSK_AES"}, - {WIFI_SECURITY_WPA_ENTERPRISE_TKIP, "WIFI_SECURITY_WPA_ENTERPRISE_TKIP"}, - {WIFI_SECURITY_WPA_ENTERPRISE_AES, "WIFI_SECURITY_WPA_ENTERPRISE_AES"}, - {WIFI_SECURITY_WPA2_ENTERPRISE_TKIP, "WIFI_SECURITY_WPA2_ENTERPRISE_TKIP"}, - {WIFI_SECURITY_WPA2_ENTERPRISE_AES, "WIFI_SECURITY_WPA2_ENTERPRISE_AES"}, - {WIFI_SECURITY_WPA_WPA2_PSK, "WIFI_SECURITY_WPA_WPA2_PSK"}, - {WIFI_SECURITY_WPA_WPA2_ENTERPRISE, "WIFI_SECURITY_WPA_WPA2_ENTERPRISE"}, - {WIFI_SECURITY_WPA3_PSK_AES, "WIFI_SECURITY_WPA3_PSK_AES"}, - {WIFI_SECURITY_WPA3_SAE, "WIFI_SECURITY_WPA3_SAE"} + {WIFI_SECURITY_NONE, "NONE"}, + {WIFI_SECURITY_WPA_PSK, "WPA_PSK"}, + {WIFI_SECURITY_SAE, "SAE"}, + {WIFI_SECURITY_EAP, "EAP"}, }; using Implementation = RPC::IteratorType; diff --git a/NetworkManagerJsonEnum.h b/NetworkManagerJsonEnum.h index 939411c6b..07b9318a5 100644 --- a/NetworkManagerJsonEnum.h +++ b/NetworkManagerJsonEnum.h @@ -42,24 +42,6 @@ ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::InternetStatus) { Exchange::INetworkManager::InternetStatus::INTERNET_UNKNOWN, _TXT("UNKNOWN") }, ENUM_CONVERSION_END(Exchange::INetworkManager::InternetStatus) -ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::WIFISecurityMode) - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE, _TXT("0") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_64, _TXT("1") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_128, _TXT("2") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_TKIP, _TXT("3") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES, _TXT("4") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_TKIP, _TXT("5") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES, _TXT("6") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_ENTERPRISE_TKIP, _TXT("7") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_ENTERPRISE_AES, _TXT("8") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_ENTERPRISE_TKIP, _TXT("9") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_ENTERPRISE_AES, _TXT("10") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK, _TXT("11") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_ENTERPRISE, _TXT("12") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_PSK_AES, _TXT("13") }, - { Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE, _TXT("14") }, -ENUM_CONVERSION_END(Exchange::INetworkManager::WIFISecurityMode) - ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::WiFiWPS) { Exchange::INetworkManager::WiFiWPS::WIFI_WPS_PBC, _TXT("PBC") }, { Exchange::INetworkManager::WiFiWPS::WIFI_WPS_PIN, _TXT("PIN") }, diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index c02172e00..7b8b448f1 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -424,6 +424,53 @@ namespace WPEFramework return Exchange::INetworkManager::WIFI_STATE_INVALID; } + static inline uint32_t mapToLegacySecurityMode(const uint32_t securityMode) + { + if (securityMode == 0) + return 0; /* NET_WIFI_SECURITY_NONE */ + else if (securityMode == 1) + return 6; /* NET_WIFI_SECURITY_WPA2_PSK_AES */ + else if (securityMode == 2) + return 14; /* NET_WIFI_SECURITY_WPA3_SAE */ + else if (securityMode == 3) + return 12; /* NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE */ + + return 0; /* NET_WIFI_SECURITY_NONE */ + } + + static inline uint32_t mapToNewSecurityMode(const uint32_t legacyMode) + { + if ((legacyMode == NET_WIFI_SECURITY_NONE) || + (legacyMode == NET_WIFI_SECURITY_WEP_64) || + (legacyMode == NET_WIFI_SECURITY_WEP_128)) + { + return 0; /* WIFI_SECURITY_NONE */ + } + else if ((legacyMode == NET_WIFI_SECURITY_WPA_PSK_TKIP) || + (legacyMode == NET_WIFI_SECURITY_WPA_PSK_AES) || + (legacyMode == NET_WIFI_SECURITY_WPA2_PSK_TKIP) || + (legacyMode == NET_WIFI_SECURITY_WPA2_PSK_AES) || + (legacyMode == NET_WIFI_SECURITY_WPA_WPA2_PSK) || + (legacyMode == NET_WIFI_SECURITY_WPA3_PSK_AES)) + { + return 1; /* WIFI_SECURITY_WPA_PSK */ + } + else if (legacyMode == NET_WIFI_SECURITY_WPA3_SAE) + { + return 2; /* WIFI_SECURITY_SAE */ + } + else if ((legacyMode == NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP) || + (legacyMode == NET_WIFI_SECURITY_WPA_ENTERPRISE_AES) || + (legacyMode == NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP) || + (legacyMode == NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES) || + (legacyMode == NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE)) + { + return 3; /* WIFI_SECURITY_EAP */ + } + + return 0; /* WIFI_SECURITY_NONE */ + } + void NetworkManagerInternalEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) { LOG_ENTRY_FUNCTION(); @@ -512,6 +559,8 @@ namespace WPEFramework NMLOG_INFO ("IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs"); std::string serialized(e->data.wifiSSIDList.ssid_list); JsonObject eventDocument; + JsonArray ssidsUpdated; + uint32_t security; WPEC::OptionalType error; if (!WPEJ::IElement::FromString(serialized, eventDocument, error)) { NMLOG_ERROR("Failed to parse JSON document containing SSIDs. Due to: %s", WPEJ::ErrorDisplayMessage(error).c_str()); @@ -524,7 +573,14 @@ namespace WPEFramework JsonArray ssids = eventDocument["getAvailableSSIDs"].Array(); - ::_instance->ReportAvailableSSIDs(ssids); + for (int i = 0; i < ssids.Length(); i++) + { + JsonObject object = ssids[i].Object(); + security = object["security"].Number(); + object["security"] = mapToNewSecurityMode(security); + ssidsUpdated.Add(object); + } + ::_instance->ReportAvailableSSIDs(ssidsUpdated); break; } case IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged: @@ -1186,7 +1242,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { strncpy(param.data.connect.ssid, ssid.ssid.c_str(), SSID_SIZE - 1); strncpy(param.data.connect.passphrase, ssid.passphrase.c_str(), PASSPHRASE_BUFF - 1); - param.data.connect.security_mode = (SsidSecurity) ssid.security; + param.data.connect.security_mode = (SsidSecurity) mapToLegacySecurityMode(ssid.security); IARM_Result_t retVal = IARM_Bus_Call(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_API_saveSSID, (void *)¶m, sizeof(param)); if((retVal == IARM_RESULT_SUCCESS) && param.status) @@ -1238,7 +1294,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { { ssid.ssid.copy(param.data.connect.ssid, sizeof(param.data.connect.ssid) - 1); ssid.passphrase.copy(param.data.connect.passphrase, sizeof(param.data.connect.passphrase) - 1); - param.data.connect.security_mode = (SsidSecurity)ssid.security; + param.data.connect.security_mode = (SsidSecurity)mapToLegacySecurityMode(ssid.security); if(!ssid.eap_identity.empty()) ssid.eap_identity.copy(param.data.connect.eapIdentity, sizeof(param.data.connect.eapIdentity) - 1); if(!ssid.ca_cert.empty()) @@ -1303,7 +1359,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { ssidInfo.ssid = string(connectedSsid.ssid); ssidInfo.bssid = string(connectedSsid.bssid); - ssidInfo.security = (WIFISecurityMode) connectedSsid.securityMode; + ssidInfo.security = (WIFISecurityMode)mapToNewSecurityMode(connectedSsid.securityMode); ssidInfo.strength = to_string(connectedSsid.signalStrength); ssidInfo.rate = to_string(connectedSsid.rate); ssidInfo.noise = to_string(connectedSsid.noise); diff --git a/Tests/raspberrypi/NetworkManagerGdbusTest.cpp b/Tests/raspberrypi/NetworkManagerGdbusTest.cpp index 5c0b34ea8..fb78e2826 100644 --- a/Tests/raspberrypi/NetworkManagerGdbusTest.cpp +++ b/Tests/raspberrypi/NetworkManagerGdbusTest.cpp @@ -100,16 +100,16 @@ WPEFramework::Exchange::INetworkManager::WIFISecurityMode getSecurityType() { int securityChoice; std::cout << "Select Security Type:" << std::endl; - std::cout << "1. WPA/WPA2 PSK AES" << std::endl; - std::cout << "2. WPA/WPA2 PSK TKIP" << std::endl; + std::cout << "1. WPA-PSK" << std::endl; + std::cout << "2. SAE" << std::endl; std::cout << "3. Open (No Security)" << std::endl; std::cin >> securityChoice; switch (securityChoice) { case 1: - return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_WPA_PSK_AES; + return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_WPA_PSK; case 2: - return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_WPA_PSK_TKIP; + return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_SAE; case 3: return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_NONE; default: diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 3af6eff56..11a57c8af 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -1615,21 +1615,10 @@ This method takes no parameters. | :-------- | :-------- | :-------- | | result | object | | | result.security_modes | object | The supported security modes and its associated integer value | -| result.security_modes?.NET_WIFI_SECURITY_NONE | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WEP_64 | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WEP_128 | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WPA_PSK_TKIP | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WPA_PSK_AES | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WPA2_PSK_TKIP | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WPA2_PSK_AES | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WPA_ENTERPRISE_AES | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WPA_WPA2_PSK | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WPA3_PSK_AES | integer | *(optional)* | -| result.security_modes?.NET_WIFI_SECURITY_WPA3_SAE | integer | *(optional)* | +| result.security_modes.NONE | integer | Security mode for open network | +| result.security_modes.WPA_PSK | integer | Supports security mode WPA,WPA-PSK,WPA2-PSK, WPA3-Personal-Transition | +| result.security_modes.SAE | integer | Supports security mode WPA3-Personal | +| result.security_modes.EAP | integer | Supports security mode WPA enterpise | | result.success | boolean | Whether the request succeeded | ### Example @@ -1652,21 +1641,10 @@ This method takes no parameters. "id": 42, "result": { "security_modes": { - "NET_WIFI_SECURITY_NONE": 0, - "NET_WIFI_SECURITY_WEP_64": 1, - "NET_WIFI_SECURITY_WEP_128": 2, - "NET_WIFI_SECURITY_WPA_PSK_TKIP": 3, - "NET_WIFI_SECURITY_WPA_PSK_AES": 4, - "NET_WIFI_SECURITY_WPA2_PSK_TKIP": 5, - "NET_WIFI_SECURITY_WPA2_PSK_AES": 6, - "NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP": 7, - "NET_WIFI_SECURITY_WPA_ENTERPRISE_AES": 8, - "NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP": 9, - "NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES": 10, - "NET_WIFI_SECURITY_WPA_WPA2_PSK": 11, - "NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE": 12, - "NET_WIFI_SECURITY_WPA3_PSK_AES": 13, - "NET_WIFI_SECURITY_WPA3_SAE": 14 + "NONE": 0, + "WPA_PSK": 1, + "SAE": 2, + "EAP": 3 }, "success": true } diff --git a/gdbus/NetworkManagerGdbusClient.cpp b/gdbus/NetworkManagerGdbusClient.cpp index 5e6f6a008..480ae8edb 100644 --- a/gdbus/NetworkManagerGdbusClient.cpp +++ b/gdbus/NetworkManagerGdbusClient.cpp @@ -1645,13 +1645,8 @@ namespace WPEFramework switch(ssidinfo.security) { - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_TKIP: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_TKIP: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_PSK_AES: - case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK: + case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE: { if(ssidinfo.passphrase.empty() || ssidinfo.passphrase.length() < 8) { @@ -1662,7 +1657,7 @@ namespace WPEFramework return false; } - if(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE == ssidinfo.security) + if(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE == ssidinfo.security) { NMLOG_DEBUG("802-11-wireless-security key-mgmt: 'sae'"); g_variant_builder_add (&settingsBuilder, "{sv}", "key-mgmt", g_variant_new_string("sae")); diff --git a/gdbus/NetworkManagerGdbusUtils.cpp b/gdbus/NetworkManagerGdbusUtils.cpp index ad1ee6d82..e2ec58904 100644 --- a/gdbus/NetworkManagerGdbusUtils.cpp +++ b/gdbus/NetworkManagerGdbusUtils.cpp @@ -156,41 +156,33 @@ namespace WPEFramework { security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE; } - else if( (flags & NM_802_11_AP_FLAGS_PRIVACY) && ((wpaFlags & NM_802_11_AP_SEC_PAIR_WEP40) || (rsnFlags & NM_802_11_AP_SEC_PAIR_WEP40)) ) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_64; - } - else if( (flags & NM_802_11_AP_FLAGS_PRIVACY) && ((wpaFlags & NM_802_11_AP_SEC_PAIR_WEP104) || (rsnFlags & NM_802_11_AP_SEC_PAIR_WEP104)) ) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WEP_128; - } else if((wpaFlags & NM_802_11_AP_SEC_PAIR_TKIP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_TKIP)) { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_TKIP; + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; } else if((wpaFlags & NM_802_11_AP_SEC_PAIR_CCMP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_CCMP)) { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK_AES; + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; } else if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) && (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_ENTERPRISE; + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP; } else if(rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_WPA2_PSK; + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; } else if((wpaFlags & NM_802_11_AP_SEC_GROUP_CCMP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_CCMP)) { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_AES; + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; } else if((wpaFlags & NM_802_11_AP_SEC_GROUP_TKIP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_TKIP)) { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA2_PSK_TKIP; + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; } else if((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE) || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA3_SAE; + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE; } else NMLOG_WARNING("security mode not defined (flag: %d, wpaFlags: %d, rsnFlags: %d)", flags, wpaFlags, rsnFlags); From dab4feefb8b2368050f958fdfa1f12edcb5f7a99 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 30 Jan 2025 21:02:19 +0530 Subject: [PATCH 079/271] RDKEMW-1412 Unable to see Wifi Scan results on UI (#86) * move platfom_init() to the calling thread instead of having separate thread. --- NetworkManagerGnomeWIFI.cpp | 12 ++++++++---- NetworkManagerImplementation.cpp | 3 +-- NetworkManagerRDKProxy.cpp | 3 ++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index d92247e7d..837c7bbc4 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -619,11 +619,15 @@ namespace WPEFramework * libnm reuses the existing connection if new settings match the AP properties; * remove the old one because now only one connection per SSID is supported. */ + GError *error = NULL; NMLOG_WARNING(" '%s' connection exist but properties miss match; deleting...", ssidInfo.ssid.c_str()); - nm_remote_connection_delete_async(NM_REMOTE_CONNECTION(connection), - NULL, - removeKnownSSIDCb, - this); + nm_remote_connection_delete (NM_REMOTE_CONNECTION(connection), NULL, &error); + if (error) + NMLOG_ERROR("RemoveKnownSSID failed %s", error->message); + else { + NMLOG_INFO ("RemoveKnownSSID is success"); + connection = NULL; + } } } } diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 2a7f9dc48..fc1bfda89 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -176,8 +176,7 @@ namespace WPEFramework } /* As all the configuration is set, lets instantiate platform */ - std::thread platformThread = std::thread(&NetworkManagerImplementation::platform_init, this); - platformThread.join(); + NetworkManagerImplementation::platform_init(); return(Core::ERROR_NONE); } diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 7b8b448f1..fd2a86407 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -743,7 +743,8 @@ namespace WPEFramework * Useful if NetworkManager plugin or WPEFramework is restarted * or netsrvmgr misses to post iarm events during bootup. */ - getInitialConnectionState(); + std::thread connStateThread = std::thread(&NetworkManagerImplementation::getInitialConnectionState, this); + connStateThread.join(); // seprate thread will not use the wpeframework thread pool } } From 082ba8d12b8ff1b3dea6ac675d805b779335d0c7 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Thu, 30 Jan 2025 15:42:22 -0500 Subject: [PATCH 080/271] Release of v0.9.0 Signed-off-by: Karunakaran A --- CHANGELOG.md | 10 ++++++++++ CMakeLists.txt | 2 +- NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 553e999ad..ee2d76f00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,16 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.9.0] - 2025-01-30 +### Added +- Enhanced Internet Connectivity Monitoring +- Redefined the security modes +- Removed explict API to start/stop connectivity monitoring +- Added retriveSSID method for migration ready +- Implemented initial code for gdbus based methods to communicate with NetworkManager +- Fixed Coverity Issues +- Fixed minor bugs + ## [0.8.0] - 2025-01-03 ### Changed - Updated the definition of GetPublicIP method to take interface as additional input diff --git a/CMakeLists.txt b/CMakeLists.txt index ef239925c..0f777c836 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 8) +set(VERSION_MINOR 9) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/NetworkManager.json b/NetworkManager.json index d841e17e8..81886f83e 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json", - "version": "0.8.0" + "version": "0.9.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 11a57c8af..32b6e665e 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.8.0** +**Version: 0.9.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.8.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.9.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 5d176db2832cd556d8d947e19f22ff31af663e52 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 7 Feb 2025 15:20:21 -0500 Subject: [PATCH 081/271] Remove wpa_cli and call GetConnectedSSID (#91) * Remove wpa_cli and call GetConnectedSSID * Limit noise to be within 0 to -180 --- NetworkManagerGnomeWIFI.cpp | 6 +++++ NetworkManagerImplementation.h | 2 ++ NetworkManagerRDKProxy.cpp | 5 +++- WiFiSignalStrengthMonitor.cpp | 40 +++++++++--------------------- WiFiSignalStrengthMonitor.h | 1 - gdbus/NetworkManagerGdbusUtils.cpp | 6 +++++ 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 837c7bbc4..c9fb0552b 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -188,6 +188,7 @@ namespace WPEFramework { guint32 flags, wpaFlags, rsnFlags, freq, bitrate; guint8 strength; + gint16 noise; GBytes *ssid; const char *hwaddr; NM80211Mode mode; @@ -201,6 +202,7 @@ namespace WPEFramework mode = nm_access_point_get_mode(AccessPoint); bitrate = nm_access_point_get_max_bitrate(AccessPoint); strength = nm_access_point_get_strength(AccessPoint); + noise = 0; /* ToDo: Returning as 0 as of now. Need to fetch actual noise value */ /* Convert to strings */ if (ssid) { @@ -229,6 +231,10 @@ namespace WPEFramework NMLOG_DEBUG("bssid: %s", wifiInfo.bssid.c_str()); wifiInfo.frequency = std::to_string((double)freq/1000); wifiInfo.rate = std::to_string(bitrate); + if(noise <= 0 || noise >= DEFAULT_NOISE) + wifiInfo.noise = std::to_string(noise); + else + wifiInfo.noise = std::to_string(0); NMLOG_DEBUG("bitrate : %s kbit/s", wifiInfo.rate.c_str()); //TODO signal strenght to dBm wifiInfo.strength = std::string(nmUtils::convertPercentageToSignalStrengtStr(strength)); diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 16fd2f79b..1bf4a7d25 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -35,6 +35,8 @@ using namespace std; #include "NetworkManagerConnectivity.h" #include "NetworkManagerStunClient.h" +#define DEFAULT_NOISE -180 + namespace WPEFramework { namespace Plugin diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index fd2a86407..6c2f45e14 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -1363,7 +1363,10 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { ssidInfo.security = (WIFISecurityMode)mapToNewSecurityMode(connectedSsid.securityMode); ssidInfo.strength = to_string(connectedSsid.signalStrength); ssidInfo.rate = to_string(connectedSsid.rate); - ssidInfo.noise = to_string(connectedSsid.noise); + if(connectedSsid.noise <= 0 || connectedSsid.noise >= DEFAULT_NOISE) + ssidInfo.noise = to_string(connectedSsid.noise); + else + ssidInfo.noise = to_string(0); ssidInfo.frequency = to_string((double)connectedSsid.frequency/1000); NMLOG_INFO ("GetConnectedSSID Success"); diff --git a/WiFiSignalStrengthMonitor.cpp b/WiFiSignalStrengthMonitor.cpp index ffe4cde8b..204a164c3 100644 --- a/WiFiSignalStrengthMonitor.cpp +++ b/WiFiSignalStrengthMonitor.cpp @@ -26,8 +26,6 @@ #include "WiFiSignalStrengthMonitor.h" #define BUFFER_SIZE 512 -#define rssid_command "wpa_cli signal_poll" -#define ssid_command "wpa_cli status" namespace WPEFramework { @@ -38,38 +36,25 @@ namespace WPEFramework static const float signalStrengthThresholdFair = -67.0f; extern NetworkManagerImplementation* _instance; - std::string WiFiSignalStrengthMonitor::retrieveValues(const char *command, const char* keyword, char *output_buffer, size_t output_buffer_size) + void WiFiSignalStrengthMonitor::getSignalData(std::string &ssid, Exchange::INetworkManager::WiFiSignalQuality &quality, std::string &strengthOut) { - std::string key, value; - std::string keystr = ""; + float signalStrengthOut = 0.0f; + char buff[BUFFER_SIZE] = {'\0'}; + string signalStrength = ""; - FILE *fp = popen(command, "r"); - if (!fp) + if (_instance != nullptr) { - NMLOG_ERROR("Failed in getting output from command %s",command); - return keystr; + Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; + _instance->GetConnectedSSID(ssidInfo); + ssid = ssidInfo.ssid; + signalStrength = ssidInfo.strength; } - - while ((!feof(fp)) && (fgets(output_buffer, output_buffer_size, fp) != NULL)) + else { - std::istringstream mystream(output_buffer); - if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) - if (key == keyword) { - keystr = value; - break; - } + NMLOG_FATAL("NetworkManagerImplementation pointer error !"); + return; } - pclose(fp); - - return keystr; - } - - void WiFiSignalStrengthMonitor::getSignalData(std::string &ssid, Exchange::INetworkManager::WiFiSignalQuality &quality, std::string &strengthOut) - { - float signalStrengthOut = 0.0f; - char buff[BUFFER_SIZE] = {'\0'}; - ssid = retrieveValues(ssid_command, "ssid", buff, sizeof (buff)); if (ssid.empty()) { quality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; @@ -77,7 +62,6 @@ namespace WPEFramework return; } - string signalStrength = retrieveValues(rssid_command, "RSSI", buff, sizeof (buff)); if (!signalStrength.empty()) { signalStrengthOut = std::stof(signalStrength.c_str()); strengthOut = signalStrength; diff --git a/WiFiSignalStrengthMonitor.h b/WiFiSignalStrengthMonitor.h index 4ce84e7c7..aa9d83a21 100644 --- a/WiFiSignalStrengthMonitor.h +++ b/WiFiSignalStrengthMonitor.h @@ -40,7 +40,6 @@ namespace WPEFramework void startWiFiSignalStrengthMonitor(int interval); void getSignalData(std::string &ssid, Exchange::INetworkManager::WiFiSignalQuality &quality, std::string &strengthOut); private: - std::string retrieveValues(const char *command, const char* keyword, char *output_buffer, size_t output_buffer_size); std::thread monitorThread; std::atomic stopThread; std::atomic isRunning; diff --git a/gdbus/NetworkManagerGdbusUtils.cpp b/gdbus/NetworkManagerGdbusUtils.cpp index e2ec58904..df7854cc5 100644 --- a/gdbus/NetworkManagerGdbusUtils.cpp +++ b/gdbus/NetworkManagerGdbusUtils.cpp @@ -26,6 +26,7 @@ #include "NetworkManagerLogger.h" #include "NetworkManagerGdbusUtils.h" #include "NetworkManagerGdbusMgr.h" +#include "NetworkManagerImplementation.h" #include #include // for struct in_addr @@ -369,6 +370,7 @@ namespace WPEFramework { guint32 flags= 0, wpaFlags= 0, rsnFlags= 0, freq= 0, bitrate= 0; uint8_t strength = 0; + gint16 noise = 0; NM80211Mode mode = NM_802_11_MODE_UNKNOWN; bool ret = false; GVariant* ssidVariant = NULL; @@ -425,6 +427,10 @@ namespace WPEFramework wifiInfo.frequency = std::to_string((double)freq/1000); wifiInfo.rate = std::to_string(bitrate); wifiInfo.security = static_cast(wifiSecurityModeFromApFlags(flags, wpaFlags, rsnFlags)); + if(noise <= 0 || noise >= DEFAULT_NOISE) + wifiInfo.noise = std::to_string(noise); + else + wifiInfo.noise = std::to_string(0); // NMLOG_DEBUG("SSID: %s", wifiInfo.m_ssid.c_str()); // NMLOG_DEBUG("bssid %s", wifiInfo.m_bssid.c_str()); From 7e47315720e7925665b3ca68c688b78cb38bf7ae Mon Sep 17 00:00:00 2001 From: parvathika <131966254+parvathika@users.noreply.github.com> Date: Mon, 10 Feb 2025 08:07:18 +0530 Subject: [PATCH 082/271] Updated unittest code to have L1 test cases (#88) * Creation of separate binaries to make all unit test codes success * update rdk_yml file --------- Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- .github/workflows/gnome_unit_test.yml | 23 --- .github/workflows/rdk_unit_test.yml | 81 +++++--- Tests/mocks/Iarm.cpp | 98 ++++++++++ Tests/mocks/Iarm.h | 56 ++++-- Tests/mocks/IarmBusMock.h | 59 ++++++ Tests/mocks/thunder/COMLinkMock.h | 18 ++ Tests/mocks/thunder/DispatcherMock.h | 20 ++ Tests/mocks/thunder/FactoriesImplementation.h | 49 +++++ Tests/mocks/thunder/Module.cpp | 3 + Tests/mocks/thunder/Module.h | 8 + Tests/mocks/thunder/ServiceMock.h | 60 ++++++ Tests/mocks/thunder/SystemInfo.h | 65 ++++++ Tests/mocks/thunder/ThunderPortability.h | 13 ++ .../mocks/thunder/WorkerPoolImplementation.h | 45 +++++ .../thunder/Remove-SmartLinkType.patch | 21 ++ .../test_LegacyPlugin_NetworkAPIs.cpp | 79 ++++++++ .../test_LegacyPlugin_WiFiManagerAPIs.cpp | 140 +++++++++++++ Tests/unit_test/test_NetworkManager.cpp | 185 ++++++++++++++++++ Tests/unit_test/unit_tests.cmake | 166 ++++++++++++---- 19 files changed, 1087 insertions(+), 102 deletions(-) create mode 100644 Tests/mocks/Iarm.cpp create mode 100644 Tests/mocks/IarmBusMock.h create mode 100644 Tests/mocks/thunder/COMLinkMock.h create mode 100644 Tests/mocks/thunder/DispatcherMock.h create mode 100644 Tests/mocks/thunder/FactoriesImplementation.h create mode 100644 Tests/mocks/thunder/Module.cpp create mode 100644 Tests/mocks/thunder/Module.h create mode 100644 Tests/mocks/thunder/ServiceMock.h create mode 100644 Tests/mocks/thunder/SystemInfo.h create mode 100644 Tests/mocks/thunder/ThunderPortability.h create mode 100644 Tests/mocks/thunder/WorkerPoolImplementation.h create mode 100644 Tests/patches/thunder/Remove-SmartLinkType.patch create mode 100644 Tests/unit_test/test_LegacyPlugin_NetworkAPIs.cpp create mode 100644 Tests/unit_test/test_LegacyPlugin_WiFiManagerAPIs.cpp create mode 100644 Tests/unit_test/test_NetworkManager.cpp diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index 23be4d134..9d25d4ac7 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -83,30 +83,7 @@ jobs: -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" -DCMAKE_CXX_FLAGS=" -fprofile-arcs -ftest-coverage " -DENABLE_GNOME_NETWORKMANAGER=ON - -DENABLE_UNIT_TESTING=ON && cmake --build build/GnomeNetworkmanager --target install -j8 - - name: Run unit tests without valgrind - run: > - PATH=${{github.workspace}}/install/usr/bin:${PATH} - LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} - unit_tests - - - name: Generate coverage - run: | - lcov -c -o coverage.info -d build/GnomeNetworkmanager - lcov -r coverage.info '/usr/include/*' '*/build/GnomeNetworkmanager/*' \ - '*/install/usr/include/*' '*/Tests/*' 'googlemock/*' 'googletest/*' \ - -o filtered_coverage.info - - name: Generate the html report - run: | - genhtml filtered_coverage.info --output-directory /tmp/coverage_report - - - name: Upload the coverage report to Pull request using actions - uses: actions/upload-artifact@v4 - with: - name: coverage-report - path: /tmp/coverage_report - diff --git a/.github/workflows/rdk_unit_test.yml b/.github/workflows/rdk_unit_test.yml index 7a251b0a6..dc39e9975 100644 --- a/.github/workflows/rdk_unit_test.yml +++ b/.github/workflows/rdk_unit_test.yml @@ -12,27 +12,13 @@ env: jobs: unit-tests: name: Build and run unit tests - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - - name: Configure cache - if: ${{ !env.ACT }} - id: cache - uses: actions/cache@v3 - with: - path: | - build/Thunder - build/ThunderInterfaces - build/ThunderTools - install - !install/etc/WPEFramework/plugins - !install/usr/lib/wpeframework/plugins - key: ${{ runner.os }}-${{ env.THUNDER_REF }} - - name: Install packages run: | sudo apt update - sudo apt-get install -y pkg-config libglib2.0-dev libnm-dev libcurl4-openssl-dev ninja-build + sudo apt-get install -y pkg-config libglib2.0-dev libnm-dev libcurl4-openssl-dev lcov ninja-build - name: Configure Python uses: actions/setup-python@v4 @@ -46,14 +32,22 @@ jobs: cmake-version: '3.16.x' - name: Checkout thunder repositories - if: steps.cache.outputs.cache-hit != 'true' run: | git clone https://github.com/rdkcentral/ThunderTools ThunderTools --branch ${{ env.THUNDER_REF }} git clone https://github.com/rdkcentral/Thunder Thunder --branch ${{ env.THUNDER_REF }} git clone https://github.com/rdkcentral/ThunderInterfaces ThunderInterfaces --branch ${{ env.THUNDER_REF }} + + - name: Checkout networkmanager + uses: actions/checkout@v3 + with: + path: networkmanager + + - name: Apply Thunder Patches + run: | + cd ${{github.workspace}}/Thunder + git apply ${{github.workspace}}/networkmanager/Tests/patches/thunder/Remove-SmartLinkType.patch - name: Build ThunderTools - if: steps.cache.outputs.cache-hit != 'true' run: > cmake -S "${{github.workspace}}/ThunderTools" -B build/ThunderTools @@ -64,7 +58,6 @@ jobs: cmake --build build/ThunderTools --target install -j8 - name: Build Thunder - if: steps.cache.outputs.cache-hit != 'true' run: > cmake -S "${{github.workspace}}/Thunder" -B build/Thunder @@ -77,7 +70,6 @@ jobs: cmake --build build/Thunder --target install -j8 - name: Build ThunderInterfaces - if: steps.cache.outputs.cache-hit != 'true' run: > cmake -S "${{github.workspace}}/ThunderInterfaces" -B build/ThunderInterfaces @@ -86,11 +78,6 @@ jobs: && cmake --build build/ThunderInterfaces --target install -j8 - - name: Checkout networkmanager - uses: actions/checkout@v3 - with: - path: networkmanager - - name: Generate IARM headers run: | touch install/usr/lib/libIARMBus.so @@ -114,5 +101,49 @@ jobs: -I ${{github.workspace}}/networkmanager/Tests/headers/rdk/iarmbus --include ${{github.workspace}}/networkmanager/Tests/mocks/Iarm.h " + -DENABLE_UNIT_TESTING=ON && cmake --build build/RDKNetworkmanager --target install -j8 + + - name: Run unit tests for common class + run: > + PATH=${{github.workspace}}/install/usr/bin:${PATH} + LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} + common_class_tests + + - name: Run unit tests for rdk proxy + run: > + PATH=${{github.workspace}}/install/usr/bin:${PATH} + LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} + rdkproxy_tests + + - name: Run unit tests for Legacy_WiFi + run: > + PATH=${{github.workspace}}/install/usr/bin:${PATH} + LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} + legacywifi_tests + + - name: Run unit tests for Legacy_Network + run: > + PATH=${{github.workspace}}/install/usr/bin:${PATH} + LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} + legacynetwork_tests + + + - name: Generate coverage + run: | + lcov -c -o coverage.info -d build/RDKNetworkmanager + lcov -r coverage.info '/usr/include/*' '*/build/RDKNetworkmanager/*' \ + '*/install/usr/include/*' '*/Tests/*' 'googlemock/*' 'googletest/*' \ + -o filtered_coverage.info + - name: Generate the html report + run: | + genhtml filtered_coverage.info --output-directory /tmp/coverage_report + + - name: Upload the coverage report to Pull request using actions + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: /tmp/coverage_report + + diff --git a/Tests/mocks/Iarm.cpp b/Tests/mocks/Iarm.cpp new file mode 100644 index 000000000..24cb7b74d --- /dev/null +++ b/Tests/mocks/Iarm.cpp @@ -0,0 +1,98 @@ +#include "Iarm.h" +#include + +#define TEST_LOG(x, ...) fprintf(stderr, "\033[1;32m[%s:%d](%s)" x "\n\033[0m", __FILE__, __LINE__, __FUNCTION__, getpid(), gettid(), ##__VA_ARGS__); fflush(stderr); + +IarmBusImpl* IarmBus::impl = nullptr; + +IarmBus::IarmBus() {} + +void IarmBus::setImpl(IarmBusImpl* newImpl) +{ + // Handles both resetting 'impl' to nullptr and assigning a new value to 'impl' + EXPECT_TRUE ((nullptr == impl) || (nullptr == newImpl)); + impl = newImpl; +} + +IARM_Result_t IarmBus::IARM_Bus_Init(const char* name) +{ + TEST_LOG("Inside IARM_Bus_Init"); + + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_Init(name); +} + +IARM_Result_t IarmBus::IARM_Bus_Connect() +{ + TEST_LOG("Inside IARM_Bus_Connect"); + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_Connect(); +} + +IARM_Result_t IarmBus::IARM_Bus_IsConnected(const char* memberName, int* isRegistered) +{ + TEST_LOG("Inside IARM_Bus_IsConnected"); + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_IsConnected(memberName, isRegistered); +} + +IARM_Result_t IarmBus::IARM_Bus_RegisterEventHandler(const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) +{ + TEST_LOG("Inside IARM_Bus_RegisterEcnetHandler"); + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_RegisterEventHandler(ownerName, eventId, handler); +} + +IARM_Result_t IarmBus::IARM_Bus_UnRegisterEventHandler(const char* ownerName, IARM_EventId_t eventId) +{ + TEST_LOG("Inside IARM_Bus_UnRegisterEcnetHandler"); + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_UnRegisterEventHandler(ownerName, eventId); +} + +IARM_Result_t IarmBus::IARM_Bus_RemoveEventHandler(const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) +{ + TEST_LOG("Inside IARM_Bus_RemoveEventHandler"); + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_RemoveEventHandler(ownerName, eventId, handler); +} + +IARM_Result_t IarmBus::IARM_Bus_Call(const char* ownerName, const char* methodName, void* arg, size_t argLen) +{ + TEST_LOG("Inside IARM_Bus_Call"); + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_Call(ownerName, methodName, arg, argLen); +} + +IARM_Result_t IarmBus::IARM_Bus_BroadcastEvent(const char *ownerName, IARM_EventId_t eventId, void *arg, size_t argLen) +{ + TEST_LOG("Inside IARM_Bus_BroadcastEvent"); + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_BroadcastEvent(ownerName, eventId, arg, argLen); +} + + +IARM_Result_t IarmBus::IARM_Bus_RegisterCall(const char* methodName, IARM_BusCall_t handler) +{ + TEST_LOG("Inside IARM_Bus_registerCall"); + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_RegisterCall(methodName, handler); +} + +IARM_Result_t IarmBus::IARM_Bus_Call_with_IPCTimeout(const char *ownerName, const char *methodName, void *arg, size_t argLen, int timeout) +{ + EXPECT_NE(impl, nullptr); + return impl->IARM_Bus_Call_with_IPCTimeout(ownerName, methodName, arg, argLen, timeout); +} + +IARM_Result_t (*IARM_Bus_Init)(const char*) = &IarmBus::IARM_Bus_Init; +IARM_Result_t (*IARM_Bus_Connect)() = &IarmBus::IARM_Bus_Connect; +IARM_Result_t (*IARM_Bus_IsConnected)(const char*,int*) = &IarmBus::IARM_Bus_IsConnected; +IARM_Result_t (*IARM_Bus_RegisterEventHandler)(const char*,IARM_EventId_t,IARM_EventHandler_t) = &IarmBus::IARM_Bus_RegisterEventHandler; +IARM_Result_t (*IARM_Bus_UnRegisterEventHandler)(const char*,IARM_EventId_t) = &IarmBus::IARM_Bus_UnRegisterEventHandler; +IARM_Result_t (*IARM_Bus_RemoveEventHandler)(const char*,IARM_EventId_t,IARM_EventHandler_t) = &IarmBus::IARM_Bus_RemoveEventHandler; +IARM_Result_t (*IARM_Bus_Call)(const char*,const char*,void*,size_t) = &IarmBus::IARM_Bus_Call; +IARM_Result_t (*IARM_Bus_BroadcastEvent)(const char *ownerName, IARM_EventId_t eventId, void *arg, size_t argLen) = &IarmBus::IARM_Bus_BroadcastEvent; +IARM_Result_t (*IARM_Bus_RegisterCall)(const char*,IARM_BusCall_t) = &IarmBus::IARM_Bus_RegisterCall; +IARM_Result_t (*IARM_Bus_Call_with_IPCTimeout)(const char*,const char*,void*,size_t,int) = &IarmBus::IARM_Bus_Call_with_IPCTimeout; + diff --git a/Tests/mocks/Iarm.h b/Tests/mocks/Iarm.h index b068e3891..bd7390d23 100644 --- a/Tests/mocks/Iarm.h +++ b/Tests/mocks/Iarm.h @@ -1,21 +1,3 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2023 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ #pragma once #include @@ -35,6 +17,43 @@ typedef enum _IARM_Result_t { typedef IARM_Result_t (*IARM_BusCall_t)(void* arg); typedef void (*IARM_EventHandler_t)(const char* owner, IARM_EventId_t eventId, void* data, size_t len); +class IarmBusImpl { +public: + virtual ~IarmBusImpl() = default; + + virtual IARM_Result_t IARM_Bus_Init(const char* name) = 0; + virtual IARM_Result_t IARM_Bus_Connect() = 0; + virtual IARM_Result_t IARM_Bus_IsConnected(const char* memberName, int* isRegistered) = 0; + virtual IARM_Result_t IARM_Bus_RegisterEventHandler(const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) = 0; + virtual IARM_Result_t IARM_Bus_UnRegisterEventHandler(const char* ownerName, IARM_EventId_t eventId) = 0; + virtual IARM_Result_t IARM_Bus_RemoveEventHandler(const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) = 0; + virtual IARM_Result_t IARM_Bus_Call(const char* ownerName, const char* methodName, void* arg, size_t argLen) = 0; + virtual IARM_Result_t IARM_Bus_BroadcastEvent(const char *ownerName, IARM_EventId_t eventId, void *arg, size_t argLen) = 0; + virtual IARM_Result_t IARM_Bus_RegisterCall(const char* methodName, IARM_BusCall_t handler) = 0; + virtual IARM_Result_t IARM_Bus_Call_with_IPCTimeout(const char *ownerName, const char *methodName, void *arg, size_t argLen, int timeout) = 0; +}; + +class IarmBus { +protected: + static IarmBusImpl* impl; +public: + IarmBus(); + IarmBus(const IarmBus &obj) = delete; // deleted copy constructor so that copy of the instance cannot be created. + static void setImpl(IarmBusImpl* newImpl); + static IARM_Result_t IARM_Bus_Init(const char* name); + static IARM_Result_t IARM_Bus_Connect(); + static IARM_Result_t IARM_Bus_IsConnected(const char* memberName, int* isRegistered); + static IARM_Result_t IARM_Bus_RegisterEventHandler(const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler); + static IARM_Result_t IARM_Bus_UnRegisterEventHandler(const char* ownerName, IARM_EventId_t eventId); + static IARM_Result_t IARM_Bus_RemoveEventHandler(const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler); + static IARM_Result_t IARM_Bus_Call(const char* ownerName, const char* methodName, void* arg, size_t argLen); + static IARM_Result_t IARM_Bus_BroadcastEvent(const char *ownerName, IARM_EventId_t eventId, void *arg, size_t argLen) ; + + static IARM_Result_t IARM_Bus_RegisterCall(const char* methodName, IARM_BusCall_t handler); + static IARM_Result_t IARM_Bus_Call_with_IPCTimeout(const char *ownerName, const char *methodName, void *arg, size_t argLen, int timeout); +}; + + extern IARM_Result_t (*IARM_Bus_Init)(const char*); extern IARM_Result_t (*IARM_Bus_Connect)(); extern IARM_Result_t (*IARM_Bus_IsConnected)(const char*,int*); @@ -45,4 +64,3 @@ extern IARM_Result_t (*IARM_Bus_Call)(const char*,const char*,void*,size_t); extern IARM_Result_t (*IARM_Bus_BroadcastEvent)(const char *,IARM_EventId_t,void *,size_t); extern IARM_Result_t (*IARM_Bus_RegisterCall)(const char*,IARM_BusCall_t); extern IARM_Result_t (*IARM_Bus_Call_with_IPCTimeout)(const char*,const char*,void*,size_t,int); - diff --git a/Tests/mocks/IarmBusMock.h b/Tests/mocks/IarmBusMock.h new file mode 100644 index 000000000..fec66aa6d --- /dev/null +++ b/Tests/mocks/IarmBusMock.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include "libIBus.h" +#define TEST_LOG(x, ...) fprintf(stderr, "\033[1;32m[%s:%d](%s)" x "\n\033[0m", __FILE__, __LINE__, __FUNCTION__, getpid(), gettid(), ##__VA_ARGS__); fflush(stderr); + +class IarmBusImplMock : public IarmBusImpl { +public: + IarmBusImplMock() + : IarmBusImpl() + { + // Defaults: + ON_CALL(*this, IARM_Bus_IsConnected(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [](const char*, int* isRegistered) { + *isRegistered = 1; + TEST_LOG("Mock IARM_Bus_IsConnected called"); + return IARM_RESULT_SUCCESS; + })); + + ON_CALL(*this, IARM_Bus_Init(::testing::_)) + .WillByDefault(::testing::Invoke( + [](const char* name) { + TEST_LOG("Mock IARM_Bus_Init called"); + return IARM_RESULT_SUCCESS; + })); + ON_CALL(*this, IARM_Bus_Connect()) + .WillByDefault(::testing::Invoke( + []() { + TEST_LOG("Mock IARM_Bus_Connect called"); + return IARM_RESULT_SUCCESS; + })); + ON_CALL(*this, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + ON_CALL(*this, IARM_Bus_UnRegisterEventHandler(::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + ON_CALL(*this, IARM_Bus_Call(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + ON_CALL(*this, IARM_Bus_BroadcastEvent(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + ON_CALL(*this, IARM_Bus_RegisterCall(::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + ON_CALL(*this, IARM_Bus_Call_with_IPCTimeout(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(IARM_RESULT_SUCCESS)); + } + virtual ~IarmBusImplMock() = default; + + MOCK_METHOD(IARM_Result_t, IARM_Bus_Init, (const char* name), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_Connect, (), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_IsConnected, (const char* memberName, int* isRegistered), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_RegisterEventHandler, (const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_UnRegisterEventHandler, (const char* ownerName, IARM_EventId_t eventId), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_RemoveEventHandler, (const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_Call, (const char* ownerName, const char* methodName, void* arg, size_t argLen), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_RegisterCall, (const char* methodName, IARM_BusCall_t handler), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_BroadcastEvent, (const char *ownerName, IARM_EventId_t eventId, void *arg, size_t argLen), (override)); + MOCK_METHOD(IARM_Result_t, IARM_Bus_Call_with_IPCTimeout, (const char *ownerName, const char *methodName, void *arg, size_t argLen, int timeout), (override)); +}; + diff --git a/Tests/mocks/thunder/COMLinkMock.h b/Tests/mocks/thunder/COMLinkMock.h new file mode 100644 index 000000000..d9c02502a --- /dev/null +++ b/Tests/mocks/thunder/COMLinkMock.h @@ -0,0 +1,18 @@ +#ifndef RDKSERVICES_TESTS_MOCKS_COMLINKMOCK_H_ +#define RDKSERVICES_TESTS_MOCKS_COMLINKMOCK_H_ + +#include +#include "Module.h" + +class COMLinkMock : public WPEFramework::PluginHost::IShell::ICOMLink { +public: + virtual ~COMLinkMock() = default; + + MOCK_METHOD(void, Register, (WPEFramework::RPC::IRemoteConnection::INotification*), (override)); + MOCK_METHOD(void, Unregister, (WPEFramework::RPC::IRemoteConnection::INotification*), (override)); + MOCK_METHOD(WPEFramework::RPC::IRemoteConnection*, RemoteConnection, (const uint32_t), (override)); + MOCK_METHOD(void*, Instantiate, (const WPEFramework::RPC::Object&, const uint32_t, uint32_t&, const string&, const string&), (override)); +}; + +#endif //RDKSERVICES_TESTS_MOCKS_COMLINKMOCK_H_ + diff --git a/Tests/mocks/thunder/DispatcherMock.h b/Tests/mocks/thunder/DispatcherMock.h new file mode 100644 index 000000000..8d6502b46 --- /dev/null +++ b/Tests/mocks/thunder/DispatcherMock.h @@ -0,0 +1,20 @@ +#ifndef DISPATCHERMOCK_H +#define DISPATCHERMOCK_H + +#include + +#include "Module.h" + + class DispatcherMock: public WPEFramework::PluginHost::IDispatcher{ + public: + virtual ~DispatcherMock() = default; + MOCK_METHOD(void, AddRef, (), (const, override)); + MOCK_METHOD(uint32_t, Release, (), (const, override)); + MOCK_METHOD(void*, QueryInterface, (const uint32_t interfaceNummer), (override)); + MOCK_METHOD(void, Activate, (WPEFramework::PluginHost::IShell* service)); + MOCK_METHOD(void, Deactivate, ()); + MOCK_METHOD(WPEFramework::Core::ProxyType, Invoke, (const string&, uint32_t, const WPEFramework::Core::JSONRPC::Message&), (override)); +}; + +#endif //DISPATCHERMOCK_H + diff --git a/Tests/mocks/thunder/FactoriesImplementation.h b/Tests/mocks/thunder/FactoriesImplementation.h new file mode 100644 index 000000000..9259cb674 --- /dev/null +++ b/Tests/mocks/thunder/FactoriesImplementation.h @@ -0,0 +1,49 @@ + +#pragma once + +#include + +#include "Module.h" + +class FactoriesImplementation : public WPEFramework::PluginHost::IFactories { +public: + FactoriesImplementation(const FactoriesImplementation&) = delete; + FactoriesImplementation& operator=(const FactoriesImplementation&) = delete; + + FactoriesImplementation() + : _requestFactory(5) + , _responseFactory(5) + , _fileBodyFactory(5) + , _jsonRPCFactory(5) + { + // Defaults: + ON_CALL(*this, Request()) + .WillByDefault(::testing::Invoke( + [&]() { return (_requestFactory.Element()); })); + ON_CALL(*this, Response()) + .WillByDefault(::testing::Invoke( + [&]() { return (_responseFactory.Element()); })); + ON_CALL(*this, FileBody()) + .WillByDefault(::testing::Invoke( + [&]() { return (_fileBodyFactory.Element()); })); + ON_CALL(*this, JSONRPC()) + .WillByDefault(::testing::Invoke( + [&]() { + return (WPEFramework::Core::ProxyType>(_jsonRPCFactory.Element())); + })); + } + + virtual ~FactoriesImplementation() = default; + + MOCK_METHOD(WPEFramework::Core::ProxyType, Request, (), (override)); + MOCK_METHOD(WPEFramework::Core::ProxyType, Response, (), (override)); + MOCK_METHOD(WPEFramework::Core::ProxyType, FileBody, (), (override)); + MOCK_METHOD(WPEFramework::Core::ProxyType>, JSONRPC, (), (override)); + +private: + WPEFramework::Core::ProxyPoolType _requestFactory; + WPEFramework::Core::ProxyPoolType _responseFactory; + WPEFramework::Core::ProxyPoolType _fileBodyFactory; + WPEFramework::Core::ProxyPoolType _jsonRPCFactory; +}; + diff --git a/Tests/mocks/thunder/Module.cpp b/Tests/mocks/thunder/Module.cpp new file mode 100644 index 000000000..2d85ed902 --- /dev/null +++ b/Tests/mocks/thunder/Module.cpp @@ -0,0 +1,3 @@ +#include "Module.h" + +MODULE_NAME_DECLARATION(BUILD_REFERENCE) diff --git a/Tests/mocks/thunder/Module.h b/Tests/mocks/thunder/Module.h new file mode 100644 index 000000000..b14a5086a --- /dev/null +++ b/Tests/mocks/thunder/Module.h @@ -0,0 +1,8 @@ +#pragma once + +#ifndef MODULE_NAME +#define MODULE_NAME tests +#endif + +#include +#include diff --git a/Tests/mocks/thunder/ServiceMock.h b/Tests/mocks/thunder/ServiceMock.h new file mode 100644 index 000000000..728c69186 --- /dev/null +++ b/Tests/mocks/thunder/ServiceMock.h @@ -0,0 +1,60 @@ +#ifndef SERVICEMOCK_H +#define SERVICEMOCK_H + +#include + +#include "Module.h" + +class ServiceMock : public WPEFramework::PluginHost::IShell { +public: + virtual ~ServiceMock() = default; + + MOCK_METHOD(void, AddRef, (), (const, override)); + MOCK_METHOD(uint32_t, Release, (), (const, override)); + MOCK_METHOD(string, Versions, (), (const, override)); + MOCK_METHOD(string, Locator, (), (const, override)); + MOCK_METHOD(string, ClassName, (), (const, override)); + MOCK_METHOD(string, Callsign, (), (const, override)); + MOCK_METHOD(string, WebPrefix, (), (const, override)); + MOCK_METHOD(string, ConfigLine, (), (const, override)); + MOCK_METHOD(string, PersistentPath, (), (const, override)); + MOCK_METHOD(string, VolatilePath, (), (const, override)); + MOCK_METHOD(string, DataPath, (), (const, override)); + MOCK_METHOD(state, State, (), (const, override)); + MOCK_METHOD(WPEFramework::Core::hresult, Activate, (const reason), (override)); + MOCK_METHOD(WPEFramework::Core::hresult, Deactivate, (const reason), (override)); + MOCK_METHOD(WPEFramework::Core::hresult, Unavailable, (const reason), (override)); + MOCK_METHOD(WPEFramework::Core::hresult, ConfigLine, (const string& config), (override)); + MOCK_METHOD(WPEFramework::Core::hresult, SystemRootPath, (const string& systemRootPath), (override)); + MOCK_METHOD(WPEFramework::Core::hresult, Hibernate, (const uint32_t timeout), (override)); + MOCK_METHOD(string, SystemPath, (), (const, override)); + MOCK_METHOD(string, PluginPath, (), (const, override)); + MOCK_METHOD(WPEFramework::PluginHost::IShell::startup, Startup, (), (const, override)); + MOCK_METHOD(WPEFramework::Core::hresult, Startup, (const startup value), (override)); + MOCK_METHOD(WPEFramework::Core::hresult, Resumed, (const bool value), (override)); + MOCK_METHOD(WPEFramework::Core::hresult, Metadata, (string& info), (const, override)); + + MOCK_METHOD(bool, Resumed, (), (const, override)); + MOCK_METHOD(bool, IsSupported, (const uint8_t), (const, override)); + MOCK_METHOD(void, EnableWebServer, (const string&, const string&), (override)); + MOCK_METHOD(void, DisableWebServer, (), (override)); + MOCK_METHOD(WPEFramework::PluginHost::ISubSystem*, SubSystems, (), (override)); + MOCK_METHOD(uint32_t, Submit, (const uint32_t, const WPEFramework::Core::ProxyType&), (override)); + MOCK_METHOD(void, Notify, (const string&), (override)); + MOCK_METHOD(void*, QueryInterface, (const uint32_t), (override)); + MOCK_METHOD(void*, QueryInterfaceByCallsign, (const uint32_t, const string&), (override)); + MOCK_METHOD(void, Register, (WPEFramework::PluginHost::IPlugin::INotification*), (override)); + MOCK_METHOD(void, Unregister, (WPEFramework::PluginHost::IPlugin::INotification*), (override)); + MOCK_METHOD(string, Model, (), (const, override)); + MOCK_METHOD(bool, Background, (), (const, override)); + MOCK_METHOD(string, Accessor, (), (const, override)); + MOCK_METHOD(string, ProxyStubPath, (), (const, override)); + MOCK_METHOD(string, HashKey, (), (const, override)); + MOCK_METHOD(string, Substitute, (const string&), (const, override)); + MOCK_METHOD(WPEFramework::PluginHost::IShell::ICOMLink*, COMLink, (), (override)); + MOCK_METHOD(reason, Reason, (), (const, override)); + MOCK_METHOD(string, SystemRootPath, (), (const, override)); +}; + +#endif //SERVICEMOCK_H + diff --git a/Tests/mocks/thunder/SystemInfo.h b/Tests/mocks/thunder/SystemInfo.h new file mode 100644 index 000000000..871b10950 --- /dev/null +++ b/Tests/mocks/thunder/SystemInfo.h @@ -0,0 +1,65 @@ +#pragma once + +#include + +#include "Module.h" + +class SystemInfo : public WPEFramework::PluginHost::ISubSystem { +private: + SystemInfo(const SystemInfo&) = delete; + SystemInfo& operator=(const SystemInfo&) = delete; + +public: + SystemInfo() + : _flags(0) + { + // Defaults: + ON_CALL(*this, Set(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const subsystem type, WPEFramework::Core::IUnknown* information) { + _subsystems.emplace(type, information); + + if (type >= NEGATIVE_START) { + _flags &= ~(1 << (type - NEGATIVE_START)); + } else { + _flags |= (1 << type); + } + })); + ON_CALL(*this, Get(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const subsystem type) -> const WPEFramework::Core::IUnknown* { + const WPEFramework::Core::IUnknown* result(nullptr); + + auto it = _subsystems.find(type); + if (it != _subsystems.end()) { + result = it->second; + } + + return result; + })); + ON_CALL(*this, IsActive(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const subsystem type) -> bool { + return ((type < END_LIST) && ((_flags & (1 << type)) != 0)); + })); + } + virtual ~SystemInfo() = default; + +public: + MOCK_METHOD(void, Register, (WPEFramework::PluginHost::ISubSystem::INotification * notification), (override)); + MOCK_METHOD(void, Unregister, (WPEFramework::PluginHost::ISubSystem::INotification * notification), (override)); + MOCK_METHOD(string, BuildTreeHash, (), (const, override)); + MOCK_METHOD(void, Set, (const subsystem type, WPEFramework::Core::IUnknown* information), (override)); + MOCK_METHOD(const WPEFramework::Core::IUnknown*, Get, (const subsystem type), (const, override)); + MOCK_METHOD(bool, IsActive, (const subsystem type), (const, override)); + MOCK_METHOD(string, Version, (), (const, override)); + + BEGIN_INTERFACE_MAP(SystemInfo) + INTERFACE_ENTRY(WPEFramework::PluginHost::ISubSystem) + END_INTERFACE_MAP + +private: + std::map _subsystems; + uint32_t _flags; +}; + diff --git a/Tests/mocks/thunder/ThunderPortability.h b/Tests/mocks/thunder/ThunderPortability.h new file mode 100644 index 000000000..f0ddcf363 --- /dev/null +++ b/Tests/mocks/thunder/ThunderPortability.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +#define EVENT_SUBSCRIBE(__A__, __B__, __C__, __D__) { plugin->Subscribe(__A__, __B__, __C__); (void)__D__; } +#define EVENT_UNSUBSCRIBE(__A__, __B__, __C__, __D__) { plugin->Unsubscribe(__A__, __B__, __C__); (void)__D__; } + +#define DECL_CORE_JSONRPC_CONX Core::JSONRPC::Context +#define INIT_CONX(__X__, __Y__) connection(__X__, __Y__, "") +#define PLUGINHOST_DISPATCHER PluginHost::ILocalDispatcher +#define PLUGINHOST_DISPATCHER_ID PluginHost::ILocalDispatcher::ID + diff --git a/Tests/mocks/thunder/WorkerPoolImplementation.h b/Tests/mocks/thunder/WorkerPoolImplementation.h new file mode 100644 index 000000000..58bf84f14 --- /dev/null +++ b/Tests/mocks/thunder/WorkerPoolImplementation.h @@ -0,0 +1,45 @@ +#pragma once + +#include + +#include "Module.h" + +class WorkerPoolImplementation : public WPEFramework::Core::WorkerPool { +private: + class Dispatcher : public WPEFramework::Core::ThreadPool::IDispatcher { + public: + Dispatcher(const Dispatcher&) = delete; + Dispatcher& operator=(const Dispatcher&) = delete; + + Dispatcher() = default; + ~Dispatcher() override = default; + + private: + void Initialize() override {} + void Deinitialize() override {} + void Dispatch(WPEFramework::Core::IDispatch* job) override + { + job->Dispatch(); + } + }; + +public: + WorkerPoolImplementation() = delete; + WorkerPoolImplementation(const WorkerPoolImplementation&) = delete; + WorkerPoolImplementation& operator=(const WorkerPoolImplementation&) = delete; + + WorkerPoolImplementation(const uint8_t threads, const uint32_t stackSize, const uint32_t queueSize) + : WPEFramework::Core::WorkerPool(threads - 1, stackSize, queueSize, &_dispatcher) + , _dispatcher() + { + } + + virtual ~WorkerPoolImplementation() + { + WPEFramework::Core::WorkerPool::Stop(); + } + +private: + Dispatcher _dispatcher; +}; + diff --git a/Tests/patches/thunder/Remove-SmartLinkType.patch b/Tests/patches/thunder/Remove-SmartLinkType.patch new file mode 100644 index 000000000..ecf958589 --- /dev/null +++ b/Tests/patches/thunder/Remove-SmartLinkType.patch @@ -0,0 +1,21 @@ +diff --git a/Source/websocket/JSONRPCLink.h b/Source/websocket/JSONRPCLink.h +index 9652d7ec..aad19ab1 100644 +--- a/Source/websocket/JSONRPCLink.h ++++ b/Source/websocket/JSONRPCLink.h +@@ -1235,16 +1235,6 @@ namespace WPEFramework { + } + + public: +- template +- uint32_t Subscribe(const uint32_t waitTime, const string& eventName, const METHOD& method) +- { +- return Subscribe(waitTime, eventName, method); +- } +- template +- uint32_t Subscribe(const uint32_t waitTime, const string& eventName, const METHOD& method, REALOBJECT* objectPtr) +- { +- return Subscribe(waitTime, eventName, method, objectPtr); +- } + bool IsActivated() + { + return (_state == ACTIVATED); diff --git a/Tests/unit_test/test_LegacyPlugin_NetworkAPIs.cpp b/Tests/unit_test/test_LegacyPlugin_NetworkAPIs.cpp new file mode 100644 index 000000000..5664c501c --- /dev/null +++ b/Tests/unit_test/test_LegacyPlugin_NetworkAPIs.cpp @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include "ServiceMock.h" +#include "FactoriesImplementation.h" +#include "NetworkManagerLogger.h" +#include "LegacyPlugin_NetworkAPIs.h" +#include "ThunderPortability.h" + +using namespace std; +using namespace WPEFramework; +using ::testing::NiceMock; + +class NetworkTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + DECL_CORE_JSONRPC_CONX connection; + Core::JSONRPC::Message message; + string response; + ServiceMock services; + + NetworkTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , INIT_CONX(1, 0) + { + + } + virtual ~NetworkTest() override + { + } +}; + +class NetworkInitializedTest : public NetworkTest { +protected: + NiceMock service; + NetworkInitializedTest() + { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return nullptr; + })); + } + + virtual ~NetworkInitializedTest() override + { + plugin->Deinitialize(&service); + } + +}; + + +TEST_F(NetworkTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getStbIp"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getInterfaces"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isInterfaceEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setInterfaceEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getDefaultInterface"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getIPSettings"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isConnectedToInternet"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPublicIP"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSTBIPFamily"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setConnectivityTestEndpoints"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getCaptivePortalURI"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startConnectivityMonitoring"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopConnectivityMonitoring"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setDefaultInterface"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setIPSettings"))); +} + + diff --git a/Tests/unit_test/test_LegacyPlugin_WiFiManagerAPIs.cpp b/Tests/unit_test/test_LegacyPlugin_WiFiManagerAPIs.cpp new file mode 100644 index 000000000..1ca5049c3 --- /dev/null +++ b/Tests/unit_test/test_LegacyPlugin_WiFiManagerAPIs.cpp @@ -0,0 +1,140 @@ +#include +#include +#include +#include "ServiceMock.h" +#include "FactoriesImplementation.h" +#include "NetworkManagerLogger.h" +#include "LegacyPlugin_WiFiManagerAPIs.h" +#include "ThunderPortability.h" + +using namespace std; +using namespace WPEFramework; +using namespace WPEFramework::Plugin; +using ::testing::NiceMock; + +class WiFiManagerTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + DECL_CORE_JSONRPC_CONX connection; + Core::JSONRPC::Message message; + string response; + ServiceMock services; + + WiFiManagerTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , INIT_CONX(1, 0) + { + + } + + virtual ~WiFiManagerTest() override + { + } +}; + +class WiFiManagerInitializedTest : public WiFiManagerTest { +protected: + NiceMock service; + WiFiManagerInitializedTest() + { + EXPECT_EQ(string(""), plugin->Initialize(&service)); + + EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return nullptr; + })); + } + + virtual ~WiFiManagerInitializedTest() override + { + plugin->Deinitialize(&service); + } + +}; + +TEST_F(WiFiManagerTest, TestedAPIsShouldExist) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startScan"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopScan"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("connect"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("disconnect"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("initiateWPSPairing"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("cancelWPSPairing"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("saveSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("clearSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPairedSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPairedSSIDInfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isPaired"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getCurrentState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getConnectedSSID"))); +} + +TEST_F(WiFiManagerInitializedTest, startScan) +{ + EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("startScan"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(WiFiManagerInitializedTest, stopScan) +{ + EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("stopScan"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(WiFiManagerInitializedTest, isPaired) +{ + EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("isPaired"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(WiFiManagerInitializedTest, disconnect) +{ + EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("disconnect"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(WiFiManagerInitializedTest, initiateWPSPairing) +{ + EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("initiateWPSPairing"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(WiFiManagerInitializedTest, cancelWPSPairing) +{ + EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("cancelWPSPairing"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(WiFiManagerInitializedTest, clearSSID) +{ + EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("clearSSID"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} +TEST_F(WiFiManagerInitializedTest, getPairedSSID) +{ + EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("getPairedSSID"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(WiFiManagerInitializedTest, getPairedSSIDInfo) +{ + EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("getPairedSSIDInfo"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + +TEST_F(WiFiManagerInitializedTest, getCurrentState) +{ + EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("getCurrentState"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} +TEST_F(WiFiManagerInitializedTest, getConnectedSSID) +{ + EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("getConnectedSSID"), _T("{}"), response)); + EXPECT_EQ(response, string("")); +} + diff --git a/Tests/unit_test/test_NetworkManager.cpp b/Tests/unit_test/test_NetworkManager.cpp new file mode 100644 index 000000000..7cb316db3 --- /dev/null +++ b/Tests/unit_test/test_NetworkManager.cpp @@ -0,0 +1,185 @@ +#include +#include +#include +#include +#include "NetworkManagerLogger.h" +#include "NetworkManager.h" +#include "ServiceMock.h" +#include "FactoriesImplementation.h" +#include "IarmBusMock.h" +#include "ThunderPortability.h" + +using namespace std; +using namespace WPEFramework; +using namespace WPEFramework::Plugin; +using ::testing::NiceMock; + +class NetworkManagerTestBase : public ::testing::Test { +public: + IarmBusImplMock *p_iarmBusImplMock = nullptr ; + NetworkManagerTestBase() + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + } + + ~NetworkManagerTestBase() { + delete p_iarmBusImplMock; + IarmBus::setImpl(nullptr); + } + +}; + +class NetworkManagerTest : public NetworkManagerTestBase { +protected: + + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + DECL_CORE_JSONRPC_CONX connection; + string response; + + Core::JSONRPC::Message message; + + NetworkManagerTest() : plugin(Core::ProxyType::Create()), + handler(*plugin), + INIT_CONX(1, 0) + { + + } + +}; + +TEST_F(NetworkManagerTest, TestFunShouldExist) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetLogLevel"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetLogLevel"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetAvailableInterfaces"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetPrimaryInterface"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetPrimaryInterface"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetInterfaceState"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetInterfaceState"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetIPSettings"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetIPSettings"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetStunEndpoint"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetStunEndpoint"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetConnectivityTestEndpoints"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetConnectivityTestEndpoints"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("IsConnectedToInternet"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetCaptivePortalURI"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("StartConnectivityMonitoring"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("StopConnectivityMonitoring"))); + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetPublicIP"))); +} + + +TEST_F(NetworkManagerTest, SetLogLevel) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("SetLogLevel"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, GetLogLevel) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetLogLevel"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, GetAvailableInterfaces) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, GetPrimaryInterface) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetPrimaryInterface"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, SetPrimaryInterface) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("SetPrimaryInterface"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, GetInterfaceState) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetInterfaceState"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + + +TEST_F(NetworkManagerTest, SetInterfaceState) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("SetInterfaceState"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, GetIPSettings) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetIPSettings"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, SetIPSettings) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("SetIPSettings"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, GetStunEndpoint) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetStunEndpoint"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, SetStunEndpoint) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("SetStunEndpoint"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, GetConnectivityTestEndpoints) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetCOnnectivityTestEndpoints"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, SetConnectivityTestEndpoints) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("SetConnectivityTestEndpoints"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, IsConnectedToInternet) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("IsConnectedToInternet"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, GetCaptivePortalURI) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetCaptivePortalURI"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, StartConnectivityMonitoring) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("StartConnectivityMonitoring"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, StopConnectivityMonitoring) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("StopConnectivityMonitoring"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + +TEST_F(NetworkManagerTest, GetPublicIP) +{ + EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetPublicIP"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); + EXPECT_EQ(response, string("")); + } + + + diff --git a/Tests/unit_test/unit_tests.cmake b/Tests/unit_test/unit_tests.cmake index 453ef92ec..39984d44a 100644 --- a/Tests/unit_test/unit_tests.cmake +++ b/Tests/unit_test/unit_tests.cmake @@ -1,22 +1,9 @@ -############################################################################# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2023 RDK Management -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -############################################################################# -set(UNIT_TEST "unit_tests") +cmake_minimum_required(VERSION 3.10) + +set(NM_CLASS_UT "common_class_tests") +set(NM_RDKPROXY_UT "rdkproxy_tests") +set(NM_LEGACY_WIFI_UT "legacywifi_tests") +set(NM_LEGACY_NETWORK_UT "legacynetwork_tests") find_package(PkgConfig REQUIRED) pkg_check_modules(GLIB REQUIRED glib-2.0) @@ -25,40 +12,149 @@ pkg_check_modules(LIBNM REQUIRED libnm) include(FetchContent) FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip + googletest + URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip ) FetchContent_MakeAvailable(googletest) -add_executable(${UNIT_TEST} - Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp - Tests/unit_test/test_NetworkManagerConnectivity.cpp - Tests/unit_test/test_NetworkManagerStunClient.cpp - WiFiSignalStrengthMonitor.cpp + +add_executable(${NM_CLASS_UT} + Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp + Tests/unit_test/test_NetworkManagerConnectivity.cpp + Tests/unit_test/test_NetworkManagerStunClient.cpp + WiFiSignalStrengthMonitor.cpp + NetworkManagerLogger.cpp + NetworkManagerConnectivity.cpp + NetworkManagerStunClient.cpp +) + +add_executable(${NM_RDKPROXY_UT} + Tests/unit_test/test_NetworkManager.cpp + Tests/mocks/thunder/Module.cpp + Tests/mocks/Iarm.cpp + NetworkManager.cpp + NetworkManagerLogger.cpp + NetworkManagerJsonRpc.cpp + NetworkManagerImplementation.cpp + NetworkManagerConnectivity.cpp + NetworkManagerStunClient.cpp + WiFiSignalStrengthMonitor.cpp + NetworkManagerRDKProxy.cpp + ${PROXY_STUB_SOURCES} +) + +add_executable(${NM_LEGACY_WIFI_UT} + Tests/unit_test/test_LegacyPlugin_WiFiManagerAPIs.cpp + Tests/mocks/thunder/Module.cpp NetworkManagerLogger.cpp - NetworkManagerConnectivity.cpp - NetworkManagerStunClient.cpp + LegacyPlugin_WiFiManagerAPIs.cpp ) -set_target_properties(${UNIT_TEST} PROPERTIES +add_executable(${NM_LEGACY_NETWORK_UT} + Tests/unit_test/test_LegacyPlugin_NetworkAPIs.cpp + Tests/mocks/thunder/Module.cpp + NetworkManagerLogger.cpp + LegacyPlugin_NetworkAPIs.cpp +) + +set_target_properties(${NM_CLASS_UT} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES ) -target_compile_options(${UNIT_TEST} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) +set_target_properties(${NM_RDKPROXY_UT} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) + +set_target_properties(${NM_LEGACY_WIFI_UT} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) +set_target_properties(${NM_LEGACY_NETWORK_UT} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) + +target_compile_options(${NM_CLASS_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) +target_compile_options(${NM_RDKPROXY_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) +target_compile_options(${NM_LEGACY_WIFI_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) +target_compile_options(${NM_LEGACY_NETWORK_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") -target_include_directories(${UNIT_TEST} PRIVATE +target_include_directories(${NM_CLASS_UT} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} - ${PROJECT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} Tests + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include +) + +target_include_directories(${NM_RDKPROXY_UT} PRIVATE + ${CURL_INCLUDE_DIRS} + ${IARMBUS_INCLUDE_DIRS} + ${PROJECT_SOURCE_DIR} + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include + ${CMAKE_CURRENT_SOURCE_DIR}/install/usr/include/rdk/iarmbus + Tests + Tests/mocks + Tests/mocks/thunder +) +target_include_directories(${NM_LEGACY_WIFI_UT} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include + Tests + Tests/mocks + Tests/mocks/thunder +) + +target_include_directories(${NM_LEGACY_NETWORK_UT} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}/../googlemock/include + Tests + Tests/mocks + Tests/mocks/thunder +) + +target_link_libraries(${NM_CLASS_UT} PRIVATE + gmock_main + ${NAMESPACE}Core::${NAMESPACE}Core + ${GLIB_LIBRARIES} + ${GIO_LIBRARIES} + ${LIBNM_LIBRARIES} + ${CURL_LIBRARIES} +) + +target_link_libraries(${NM_RDKPROXY_UT} PRIVATE + gmock_main + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ${CURL_LIBRARIES} + ${IARMBUS_LIBRARIES} +) +target_link_libraries(${NM_LEGACY_WIFI_UT} PRIVATE + gmock_main + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ${NAMESPACE}Core::${NAMESPACE}Core + ${CURL_LIBRARIES} +) +target_link_libraries(${NM_LEGACY_NETWORK_UT} PRIVATE + gmock_main + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ${NAMESPACE}Core::${NAMESPACE}Core + ${CURL_LIBRARIES} ) -target_link_libraries(${UNIT_TEST} PRIVATE gmock_main ${NAMESPACE}Core::${NAMESPACE}Core ${GLIB_LIBRARIES} ${GIO_LIBRARIES} ${LIBNM_LIBRARIES} ${CURL_LIBRARIES}) -target_include_directories(${UNIT_TEST} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -install(TARGETS ${UNIT_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS ${NM_CLASS_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS ${NM_RDKPROXY_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS ${NM_LEGACY_WIFI_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS ${NM_LEGACY_NETWORK_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) From 92d45d902413a9e22a5f8437e3fdd4d1337a2a49 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Tue, 11 Feb 2025 09:50:59 +0530 Subject: [PATCH 083/271] RDKEMW-1447 Create user secret Agent for wps connection (#93) --- CMakeLists.txt | 3 +- NetworkManagerGnomeEvents.cpp | 2 +- NetworkManagerGnomeProxy.cpp | 21 +- NetworkManagerGnomeUtils.cpp | 22 +- NetworkManagerGnomeWIFI.cpp | 606 +++++++++++++++------------------- NetworkManagerGnomeWIFI.h | 27 +- NetworkManagerSecretAgent.cpp | 352 ++++++++++++++++++++ NetworkManagerSecretAgent.h | 53 +++ 8 files changed, 701 insertions(+), 385 deletions(-) create mode 100644 NetworkManagerSecretAgent.cpp create mode 100644 NetworkManagerSecretAgent.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f777c836..a12896bc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,7 +137,8 @@ if(ENABLE_GNOME_NETWORKMANAGER) NetworkManagerGnomeProxy.cpp NetworkManagerGnomeWIFI.cpp NetworkManagerGnomeEvents.cpp - NetworkManagerGnomeUtils.cpp ) + NetworkManagerGnomeUtils.cpp + NetworkManagerSecretAgent.cpp ) target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) target_link_libraries(${MODULE_NAME} PRIVATE ${LIBNM_LIBRARIES}) endif() diff --git a/NetworkManagerGnomeEvents.cpp b/NetworkManagerGnomeEvents.cpp index bf17d1cfe..ce8d1efe6 100644 --- a/NetworkManagerGnomeEvents.cpp +++ b/NetworkManagerGnomeEvents.cpp @@ -627,7 +627,7 @@ namespace WPEFramework ssidList.Add(ssidObj); } - NMLOG_INFO("No of AP Available = %d", static_cast(accessPoints->len)); + NMLOG_DEBUG("No of AP Available = %d", static_cast(accessPoints->len)); if(_nmEventInstance->doScanNotify) { _nmEventInstance->doScanNotify = false; diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index 61606be7a..4f979832f 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -397,7 +397,7 @@ namespace WPEFramework } if(ipversion.empty()) - NMLOG_WARNING("ipversion is empty default value IPv4"); + NMLOG_DEBUG("ipversion is empty default value IPv4"); const GPtrArray *connections = nm_client_get_active_connections(client); if(connections == NULL) @@ -711,17 +711,26 @@ namespace WPEFramework NMLOG_ERROR("WPS PIN method is not supported as of now"); return Core::ERROR_RPC_CALL_FAILED; } - if(wifi->initiateWPS()) - NMLOG_INFO ("startWPS success"); - else - rc = Core::ERROR_RPC_CALL_FAILED; + + if(!wifi->wifiScanRequest()) + { + NMLOG_WARNING("scanning reuest failed; trying to connect wps"); + } + + if(wifi->startWPS()) + NMLOG_INFO ("start WPS success"); + else { + rc = Core::ERROR_GENERAL; + NMLOG_ERROR("start WPS failed"); + } + return rc; } uint32_t NetworkManagerImplementation::StopWPS(void) { uint32_t rc = Core::ERROR_NONE; - if(wifi->cancelWPS()) + if(wifi->stopWPS()) NMLOG_INFO ("cancelWPS success"); else rc = Core::ERROR_RPC_CALL_FAILED; diff --git a/NetworkManagerGnomeUtils.cpp b/NetworkManagerGnomeUtils.cpp index 5a81695e0..c22bdf82c 100644 --- a/NetworkManagerGnomeUtils.cpp +++ b/NetworkManagerGnomeUtils.cpp @@ -63,25 +63,13 @@ namespace WPEFramework uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; if ((flags == NM_802_11_AP_FLAGS_NONE) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE; - - else if((wpaFlags & NM_802_11_AP_SEC_PAIR_TKIP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_TKIP)) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - else if((wpaFlags & NM_802_11_AP_SEC_PAIR_CCMP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_CCMP)) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - - else if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) && (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP; - else if(rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - else if((wpaFlags & NM_802_11_AP_SEC_GROUP_CCMP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_CCMP)) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - else if((wpaFlags & NM_802_11_AP_SEC_GROUP_TKIP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_TKIP)) - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - - else if((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE) || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) + else if (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE) security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE; + else if (wpaFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X || rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP; else - NMLOG_WARNING("security mode not defined (flag: %d, wpaFlags: %d, rsnFlags: %d)", flags, wpaFlags, rsnFlags); + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + // NMLOG_DEBUG("ap security str %s", nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); return security; } diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index c9fb0552b..de7589e2e 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -33,23 +33,11 @@ using namespace std; namespace WPEFramework { - class Job : public Core::IDispatch { - public: - Job(function work) - : _work(work) - { - } - void Dispatch() override - { - _work(); - } - private: - function _work; - }; namespace Plugin { extern NetworkManagerImplementation* _instance; + static std::atomic wpsProcessRun = {false}; wifiManager::wifiManager() : m_client(nullptr), m_loop(nullptr), m_createNewConnection(false) { NMLOG_INFO("wifiManager"); @@ -186,11 +174,11 @@ namespace WPEFramework static void getApInfo(NMAccessPoint *AccessPoint, Exchange::INetworkManager::WiFiSSIDInfo &wifiInfo) { - guint32 flags, wpaFlags, rsnFlags, freq, bitrate; - guint8 strength; - gint16 noise; - GBytes *ssid; - const char *hwaddr; + guint32 flags, wpaFlags, rsnFlags, freq, bitrate; + guint8 strength; + gint16 noise; + GBytes *ssid = NULL; + const char *hwaddr = NULL; NM80211Mode mode; /* Get AP properties */ flags = nm_access_point_get_flags(AccessPoint); @@ -212,7 +200,7 @@ namespace WPEFramework { std::string ssidTmp(reinterpret_cast(ssidData), size); wifiInfo.ssid = ssidTmp; - NMLOG_INFO("ssid: %s", wifiInfo.ssid.c_str()); + // NMLOG_INFO("ssid: %s", wifiInfo.ssid.c_str()); } else { @@ -223,12 +211,12 @@ namespace WPEFramework } else { - wifiInfo.ssid = "-----"; - NMLOG_DEBUG("ssid: %s", wifiInfo.ssid.c_str()); + /* hidden ssid */ + wifiInfo.ssid.clear(); + NMLOG_DEBUG("hidden ssid found bssid: %s", hwaddr); } wifiInfo.bssid = (hwaddr != nullptr) ? hwaddr : "-----"; - NMLOG_DEBUG("bssid: %s", wifiInfo.bssid.c_str()); wifiInfo.frequency = std::to_string((double)freq/1000); wifiInfo.rate = std::to_string(bitrate); if(noise <= 0 || noise >= DEFAULT_NOISE) @@ -238,9 +226,10 @@ namespace WPEFramework NMLOG_DEBUG("bitrate : %s kbit/s", wifiInfo.rate.c_str()); //TODO signal strenght to dBm wifiInfo.strength = std::string(nmUtils::convertPercentageToSignalStrengtStr(strength)); - NMLOG_DEBUG("sterngth: %s dbm", wifiInfo.strength.c_str()); wifiInfo.security = static_cast(nmUtils::wifiSecurityModeFromAp(flags, wpaFlags, rsnFlags)); - NMLOG_DEBUG("security %s", nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); + NMLOG_INFO("ssid: %s, frequency: %s, sterngth: %s, security: %u", wifiInfo.ssid.c_str(), + wifiInfo.frequency.c_str(), wifiInfo.strength.c_str(), wifiInfo.security); + NMLOG_DEBUG("security string %s", nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); NMLOG_DEBUG("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); } @@ -257,7 +246,7 @@ namespace WPEFramework NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(wifiDevice); if(activeAP == NULL) { - NMLOG_INFO("No active access point found !"); + NMLOG_DEBUG("No active access point found !"); return false; } else @@ -283,7 +272,6 @@ namespace WPEFramework } else NMLOG_DEBUG("active access point found !"); - getApInfo(activeAP, ssidinfo); return true; } @@ -327,17 +315,15 @@ namespace WPEFramework return m_isSuccess; } - static NMAccessPoint *checkSSIDAvailable(NMDevice *device, const char *ssid) + static NMAccessPoint* findMatchingSSID(const GPtrArray* ApList, std::string& ssid) { NMAccessPoint *AccessPoint = NULL; - const GPtrArray *aps = NULL; - if(ssid == NULL) + if(ssid.empty()) return NULL; - aps = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(device)); - for (guint i = 0; i < aps->len; i++) + for (guint i = 0; i < ApList->len; i++) { - NMAccessPoint *ap = static_cast(g_ptr_array_index(aps, i)); + NMAccessPoint *ap = static_cast(g_ptr_array_index(ApList, i)); GBytes *ssidGBytes; ssidGBytes = nm_access_point_get_ssid(ap); if (!ssidGBytes) @@ -345,9 +331,8 @@ namespace WPEFramework gsize size; const guint8 *ssidData = static_cast(g_bytes_get_data(ssidGBytes, &size)); std::string ssidstr(reinterpret_cast(ssidData), size); - //g_bytes_unref(ssidGBytes); // NMLOG_DEBUG("ssid < %s >", ssidstr.c_str()); - if (strcmp(ssid, ssidstr.c_str()) == 0) + if (ssid == ssidstr) { AccessPoint = ap; break; @@ -424,7 +409,7 @@ namespace WPEFramework _wifiManager->m_client, NM_CONNECTION(remote_con), _wifiManager->m_wifidevice, _wifiManager->m_objectPath, NULL, wifiConnectCb, _wifiManager); } - static bool connectionBuilder(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo, NMConnection *m_connection) + static bool connectionBuilder(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo, NMConnection *m_connection, bool iswpsAP = false) { if(ssidinfo.ssid.empty() || ssidinfo.ssid.length() > 32) { @@ -457,11 +442,6 @@ namespace WPEFramework case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK: case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE: { - if(ssidinfo.passphrase.empty() || ssidinfo.passphrase.length() < 8) - { - NMLOG_WARNING("password legth should be > 8"); - return false; - } sSecurity = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); nm_connection_add_setting(m_connection, NM_SETTING(sSecurity)); @@ -475,8 +455,17 @@ namespace WPEFramework NMLOG_INFO("key-mgmt: %s", "wpa-psk"); g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,"wpa-psk", NULL); } - g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", NULL); - g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_PSK, ssidinfo.passphrase.c_str(), NULL); + + /* if ap is not a wps network */ + if(!iswpsAP) + { + if(ssidinfo.passphrase.empty() || ssidinfo.passphrase.length() < 8) + { + NMLOG_WARNING("password legth should be >= 8"); + return false; + } + g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_PSK, ssidinfo.passphrase.c_str(), NULL); + } break; } case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP: @@ -565,31 +554,41 @@ namespace WPEFramework bool wifiManager::wifiConnect(Exchange::INetworkManager::WiFiConnectTo ssidInfo) { NMAccessPoint *AccessPoint = NULL; + const GPtrArray* ApList = NULL; NMConnection *m_connection = NULL; - const GPtrArray *availableConnections; - bool SSIDmatch = false; - m_isSuccess = false; + const GPtrArray *availableConnections = NULL; + + Exchange::INetworkManager::WiFiSSIDInfo apinfo; + std::string activeSSID{}; + m_isSuccess = false; if(!createClientNewConnection()) return false; - NMDevice *device = getWifiDevice(); - if(device == NULL) + m_wifidevice = getWifiDevice(); + if(m_wifidevice == NULL) return false; - std::string activeSSID; - if(getConnectedSSID(device, activeSSID)) + if(getConnectedSSID(m_wifidevice, activeSSID)) { if(ssidInfo.ssid == activeSSID) { - NMLOG_INFO("ssid already connected !"); + NMLOG_INFO("'%s' already connected !", activeSSID.c_str()); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); return true; } else NMLOG_DEBUG("wifi already connected with %s AP", activeSSID.c_str()); } - AccessPoint = checkSSIDAvailable(device, ssidInfo.ssid.c_str()); + ApList = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(m_wifidevice)); + if(ApList == NULL) + { + NMLOG_ERROR("Aplist Error !"); + return false; + } + + AccessPoint = findMatchingSSID(ApList, ssidInfo.ssid); if(AccessPoint == NULL) { NMLOG_WARNING("SSID '%s' not found !", ssidInfo.ssid.c_str()); if(_instance != nullptr) @@ -597,52 +596,57 @@ namespace WPEFramework return false; } - Exchange::INetworkManager::WiFiSSIDInfo apinfo; getApInfo(AccessPoint, apinfo); - availableConnections = nm_device_get_available_connections(device); - for (guint i = 0; i < availableConnections->len; i++) + if(ssidInfo.security != apinfo.security) { - NMConnection *connection = static_cast(g_ptr_array_index(availableConnections, i)); - const char *connId = nm_connection_get_id(NM_CONNECTION(connection)); - if (connId != NULL && strcmp(connId, ssidInfo.ssid.c_str()) == 0) + NMLOG_WARNING("user requested wifi security '%d' != AP supported security %d ", ssidInfo.security, apinfo.security); + ssidInfo.security = apinfo.security; + } + + availableConnections = nm_device_get_available_connections(m_wifidevice); + if(availableConnections != NULL) + { + for (guint i = 0; i < availableConnections->len; i++) { - if (nm_access_point_connection_valid(AccessPoint, NM_CONNECTION(connection))) { - m_connection = g_object_ref(connection); - NMLOG_DEBUG("connection '%s' exists !", ssidInfo.ssid.c_str()); - if (m_connection == NULL) - { - NMLOG_ERROR("m_connection == NULL smothing went worng"); - return false; - } - break; - } - else + NMConnection *connection = static_cast(g_ptr_array_index(availableConnections, i)); + const char *connId = nm_connection_get_id(NM_CONNECTION(connection)); + if (connId != NULL && strcmp(connId, ssidInfo.ssid.c_str()) == 0) { - if (NM_IS_REMOTE_CONNECTION(connection)) + if (nm_access_point_connection_valid(AccessPoint, NM_CONNECTION(connection))) { + m_connection = g_object_ref(connection); + NMLOG_DEBUG("connection '%s' exists !", ssidInfo.ssid.c_str()); + if (m_connection == NULL) + { + NMLOG_ERROR("m_connection == NULL smothing went worng"); + return false; + } + break; + } + else { - /* - * libnm reuses the existing connection if new settings match the AP properties; - * remove the old one because now only one connection per SSID is supported. - */ - GError *error = NULL; - NMLOG_WARNING(" '%s' connection exist but properties miss match; deleting...", ssidInfo.ssid.c_str()); - nm_remote_connection_delete (NM_REMOTE_CONNECTION(connection), NULL, &error); - if (error) - NMLOG_ERROR("RemoveKnownSSID failed %s", error->message); - else { - NMLOG_INFO ("RemoveKnownSSID is success"); - connection = NULL; + if (NM_IS_REMOTE_CONNECTION(connection)) + { + /* + * libnm reuses the existing connection if new settings match the AP properties; + * remove the old one because now only one connection per SSID is supported. + */ + GError *error = NULL; + NMLOG_WARNING(" '%s' connection existing but properties mismatch; deleting...", ssidInfo.ssid.c_str()); + nm_remote_connection_delete (NM_REMOTE_CONNECTION(connection), NULL, &error); + if (error) + NMLOG_ERROR("deleting connection failed %s", error->message); + else + connection = NULL; } } } } } - if (NM_IS_REMOTE_CONNECTION(m_connection)) + if (m_connection != NULL && NM_IS_REMOTE_CONNECTION(m_connection)) { - if(!connectionBuilder(ssidInfo, m_connection)) - { + if(!connectionBuilder(ssidInfo, m_connection)) { NMLOG_ERROR("connection builder failed"); return false; } @@ -666,7 +670,7 @@ namespace WPEFramework return false; } m_createNewConnection = true; - nm_client_add_and_activate_connection_async(m_client, m_connection, device, m_objectPath, NULL, wifiConnectCb, this); + nm_client_add_and_activate_connection_async(m_client, m_connection, m_wifidevice, m_objectPath, NULL, wifiConnectCb, this); } wait(m_loop); @@ -739,7 +743,7 @@ namespace WPEFramework if (NM_IS_REMOTE_CONNECTION(m_connection)) { - if(!connectionBuilder(ssidinfo, m_connection)) + if(!connectionBuilder(ssidinfo, m_connection, true)) { NMLOG_ERROR("connection builder failed"); return false; @@ -758,7 +762,7 @@ namespace WPEFramework { NMLOG_DEBUG("creating new connection '%s' ", ssidinfo.ssid.c_str()); m_connection = nm_simple_connection_new(); - if(!connectionBuilder(ssidinfo, m_connection)) + if(!connectionBuilder(ssidinfo, m_connection, true)) { NMLOG_ERROR("connection builder failed"); return false; @@ -942,302 +946,222 @@ namespace WPEFramework return false; } - std::string wifiManager::executeWpaCliCommand(const std::string& wpaCliCommand) { - std::array buffer; - std::string wpaCliResult; - FILE* fp = popen(wpaCliCommand.c_str(), "r"); - if (fp == nullptr) { - NMLOG_ERROR("Failed to run command: %s", wpaCliCommand.c_str()); - return "ERROR"; - } + static void wpsWifiConnectCb(GObject *client, GAsyncResult *result, gpointer user_data) + { + GError *error = NULL; + GMainLoop *loop = static_cast(user_data); + nm_client_add_and_activate_connection_finish(NM_CLIENT(client), result, &error); - while (fgets(buffer.data(), buffer.size(), fp) != nullptr) { - wpaCliResult += buffer.data(); - } - pclose(fp); - NMLOG_DEBUG("Command output: %s", wpaCliResult.c_str()); - return wpaCliResult; + if (error) + NMLOG_ERROR("Failed to add/activate new connection: %s", error->message); + + g_main_loop_quit(loop); } - void wifiManager::wpsAction() + static gboolean wpsGmainLoopTimoutCB(gpointer user_data) { - FILE *fp = nullptr; - const std::string securityPattern = "key_mgmt="; - const std::string ssidPattern = "ssid="; - const std::string passphrasePattern = "psk="; - std::string line = ""; - std::string security = ""; - std::string ssid = ""; - std::string passphrase = ""; - std::string wpaCliResult = ""; - gboolean wpsConnect = false; - struct timespec startTime = {}, endTime = {}; - long timeDiff = 0; - long wpsPBCDuration = 0; - int count = 0; - bool scanResult = false; - const char* bssid = nullptr; - gboolean pbcFound = false; - const GPtrArray *aps; - wifi_wps_pbc_ap_t apList[MAX_WPS_AP_COUNT]; - int wpsApCount = 0; - - if (!m_wpsContext || !g_main_context_acquire(m_wpsContext)) - { - NMLOG_ERROR("Failed to acquire wpsContext"); - if (m_wpsContext) { - g_main_context_unref(m_wpsContext); - m_wpsContext = nullptr; - } - return; - } + GMainLoop *loop = static_cast(user_data); + NMLOG_WARNING("GmainLoop ERROR_TIMEDOUT"); + g_main_loop_quit(loop); + return true; + } - g_main_context_push_thread_default(m_wpsContext); + static bool removeSameNmConnection(NMDevice* wifidevice, std::string ssid) + { + const GPtrArray *deviceConns = NULL; - clock_gettime(CLOCK_MONOTONIC, &startTime); - do{ - sleep(10); - m_loop = g_main_loop_new(m_wpsContext, FALSE); - scanResult = wifiScanRequest(""); - m_loop = g_main_loop_new(m_nmContext, FALSE); - NMLOG_DEBUG("Wifi scan result = %d", scanResult); - if(scanResult) + deviceConns = nm_device_get_available_connections(wifidevice); + if(deviceConns != NULL) + { + for (guint i = 0; i < deviceConns->len; i++) { - aps = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(getWifiDevice())); - for (guint apCount = 0; apCount < aps->len; apCount++) { - NMAccessPoint *ap = static_cast(g_ptr_array_index(aps, apCount)); - guint32 flags = nm_access_point_get_flags(ap); - GBytes *ssidBytes; - gsize size; - std::string ssidStr; - - if ((flags & NM_802_11_AP_FLAGS_WPS_PBC) && (wpsApCount < MAX_WPS_AP_COUNT)) - { - clock_gettime(CLOCK_MONOTONIC, &endTime); - NMLOG_DEBUG("WPS Push button event is received"); - bssid = nm_access_point_get_bssid(ap); - if (bssid != NULL) { - strncpy(apList[wpsApCount].bssid, bssid, sizeof(apList[wpsApCount].bssid) - 1); - apList[wpsApCount].bssid[sizeof(apList[wpsApCount].bssid) - 1] = '\0'; - } - NMLOG_DEBUG("PBC enabled access point bssid = %s", bssid); - ssidBytes = nm_access_point_get_ssid(ap); - const guint8 *ssidData = static_cast(g_bytes_get_data(ssidBytes, &size)); - std::string ssidTmp(reinterpret_cast(ssidData), size); - strncpy(apList[wpsApCount].ssid, ssidTmp.c_str(), sizeof(apList[wpsApCount].ssid) - 1); - apList[wpsApCount].ssid[sizeof(apList[wpsApCount].ssid) - 1] = '\0'; - NMLOG_INFO("PBC enabled access point ssid: %s", apList[wpsApCount].ssid); - pbcFound = true; - wpsApCount++; + NMConnection* connection = static_cast(g_ptr_array_index(deviceConns, i)); + if(connection == NULL) + continue; + const char* connId = nm_connection_get_id(NM_CONNECTION(connection)); + if (connId != NULL && strcmp(connId, ssid.c_str()) == 0) + { + GError* error = NULL; + NMLOG_WARNING(" '%s' wps connection existing deleting...", ssid.c_str()); + nm_remote_connection_delete (NM_REMOTE_CONNECTION(connection), NULL, &error); + if(error) { + NMLOG_ERROR("deleting connection failed %s", error->message); + return false; } } - if(pbcFound) - break; } - count++; - clock_gettime(CLOCK_MONOTONIC, &endTime); - }while(count < 10 && !pbcFound && !wpsStop.load()); - wpsPBCDuration = (endTime.tv_sec - startTime.tv_sec); + } + + return true; + } - if(!pbcFound || wpsStop.load()) + static bool findWpsPbcSSID(const GPtrArray* ApList, std::string& wpsApSsid, NMAccessPoint** wpsAp) + { + Exchange::INetworkManager::WiFiSSIDInfo wpsApInfo{}; + for (guint i = 0; i < ApList->len; i++) { - NMLOG_ERROR("PBC enabled SSID not found in the scan results"); - g_main_context_pop_thread_default(m_wpsContext); - g_main_context_release(m_wpsContext); - if (m_wpsContext) { - g_main_context_unref(m_wpsContext); - m_wpsContext = nullptr; + NMAccessPoint *Ap = static_cast(g_ptr_array_index(ApList, i)); + guint32 flags = nm_access_point_get_flags(Ap); + if (flags & NM_802_11_AP_FLAGS_WPS_PBC) + { + *wpsAp = Ap; + const char *bssid = nm_access_point_get_bssid(Ap); + if (bssid != NULL) { + NMLOG_INFO("WPS PBC AP found bssid = %s", bssid); + } + getApInfo(Ap, wpsApInfo); + wpsApSsid = wpsApInfo.ssid; + return true; } - return; } - std::string command1 = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " disconnect && "; - std::string command2 = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " remove_network 0 && "; - std::string command3 = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " save_config && "; - std::string command4 = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " abort_scan && "; - std::string command5 = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " bss_flush 0"; - std::string wpaCliCommand = command1 + command2 + command3 + command4 + command5; - NMLOG_DEBUG("Initial wps command = %s", wpaCliCommand.c_str()); - wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliCommand); - if (wpaCliResult == "ERROR") + NMLOG_INFO("WPS PBC Not found !!!"); + return false; + } + + static void wpsProcess() + { + wpsProcessRun = true; + GError *error = NULL; + const GPtrArray* ApList = NULL; + std::string wpsApSsid{}; + GMainContext *wpsContext = NULL; + NMAccessPoint *wpsAp = NULL; + GMainLoop *loop = NULL; + Exchange::INetworkManager::WiFiConnectTo ssidInfo{}; + bool wpsComplete= false; + + for(int retry =0; retry < WPS_RETRY_COUNT; retry++) { - NMLOG_ERROR("WPS failed to connect with the SSID"); - g_main_context_pop_thread_default(m_wpsContext); - g_main_context_release(m_wpsContext); - if (m_wpsContext) { - g_main_context_unref(m_wpsContext); - m_wpsContext = nullptr; + sleep(WPS_RETRY_WAIT_IN_MS); + if(wpsProcessRun.load() == false) // stop wps process if reuested + break; + + wpsContext = g_main_context_new(); + if(wpsContext == NULL) + { + NMLOG_ERROR("wpsContext create failed !!"); + return; } - return ; - } - NMLOG_DEBUG("Initial wps command output = %s", wpaCliResult.c_str()); - wpaCliCommand.clear(); - for(guint wpsPbcAp=0; wpsPbcAp < wpsApCount && !wpsConnect && !wpsStop.load(); wpsPbcAp++) - { - wpaCliCommand = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_pbc " + std::string(apList[wpsPbcAp].bssid); - NMLOG_DEBUG("wpacli pbc command with bssid = %s", wpaCliCommand.c_str()); - NMLOG_INFO("Connecting with the SSID = %s", apList[wpsPbcAp].ssid); - wpaCliResult.clear(); - wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliCommand); - if (wpaCliResult == "ERROR") + + if(!g_main_context_acquire(wpsContext)) { - NMLOG_ERROR("WPS failed to connect with the SSID"); - g_main_context_pop_thread_default(m_wpsContext); - g_main_context_release(m_wpsContext); - if (m_wpsContext) { - g_main_context_unref(m_wpsContext); - m_wpsContext = nullptr; - } - return ; + NMLOG_ERROR("acquire wpsContext failed !!"); + break; + } + + g_main_context_push_thread_default(wpsContext); + + NMClient* client = nm_client_new(NULL, &error); + if (!client && error != NULL) { + NMLOG_ERROR("Could not connect to NetworkManager: %s.", error->message); + g_error_free(error); + return; } - startTime = {}, endTime = {}; - int waitTime = (MAX_WPS_WAIT_DURATION - wpsPBCDuration)/wpsApCount; - clock_gettime(CLOCK_MONOTONIC, &startTime); - while(!wpsConnect && !wpsStop.load()) + NMDevice* wifidevice = nm_client_get_device_by_iface(client, nmUtils::wlanIface()); + if(wifidevice == NULL) { - std::ifstream configFile(WPA_SUPPLICANT_CONF); - if (!configFile.is_open()) - { - NMLOG_ERROR("WPS connected with an SSID but not able to fetch IP address"); - g_main_context_pop_thread_default(m_wpsContext); - g_main_context_release(m_wpsContext); - if (m_wpsContext) { - g_main_context_unref(m_wpsContext); - m_wpsContext = nullptr; + NMLOG_ERROR("Failed to get device list."); + return; + } + + ApList = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(wifidevice)); + if(ApList == NULL) + { + NMLOG_ERROR("Aplist Error !"); + return; + } + + if(findWpsPbcSSID(ApList, wpsApSsid, &wpsAp) && wpsAp != NULL) + { + Exchange::INetworkManager::WiFiSSIDInfo activeApInfo{}; + NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(NM_DEVICE_WIFI(wifidevice)); + if(activeAP != NULL) { + NMLOG_DEBUG("active access point found !"); + getApInfo(activeAP, activeApInfo); + if(activeApInfo.ssid == wpsApSsid) + { + NMLOG_INFO("WPS process stoped connected to '%s' wps ap ", wpsApSsid.c_str()); + wpsComplete = true; + } + else { + // some other ssid connected; wps need a disconnected wifi device + nm_device_disconnect(wifidevice, NULL, &error); + if (error) + NMLOG_ERROR("disconnect connection failed %s", error->message); } - return; } - while (std::getline(configFile, line)) + if(wpsComplete) + break; + + ssidInfo.ssid = wpsApSsid; + NMConnection* connection = NULL; + /* if same connection name exsist we remove and add new one */ + removeSameNmConnection(wifidevice, wpsApSsid); + NMLOG_DEBUG("creating new connection '%s' ", wpsApSsid.c_str()); + connection = nm_simple_connection_new(); + const char* apObjPath = nm_object_get_path(NM_OBJECT(wpsAp)); + if(!connectionBuilder(ssidInfo, connection, true)) { - NMLOG_DEBUG("Attempting to read the configuration to populate SSID specific information"); - size_t pos; + NMLOG_ERROR("wps connection builder failed"); + return; + } - // Fetch ssid value - if (ssid.empty()) { - pos = line.find(ssidPattern); - if (pos != std::string::npos) - { - pos += ssidPattern.length(); - size_t end = line.find('"', pos + 1); - if (end == std::string::npos) - { - end = line.length(); - } - ssid = line.substr(pos + 1, end - pos - 1); - wpsConnect = true; - NMLOG_DEBUG("SSID found"); - continue; - } + loop = g_main_loop_new(wpsContext, FALSE); + nm_client_add_and_activate_connection_async(client, connection, wifidevice, apObjPath, NULL, wpsWifiConnectCb, loop); + GSource *source = g_timeout_source_new(10000); // 10000ms interval + if(source != nullptr) { + g_source_set_callback(source, (GSourceFunc)wpsGmainLoopTimoutCB, loop, NULL); + g_source_attach(source, NULL); + g_main_loop_run(loop); + if(g_source_is_destroyed(source)) { + NMLOG_WARNING("Source has been destroyed"); } - - if (wpsConnect) { - // Fetch security value - pos = line.find(securityPattern); - if (pos != std::string::npos) - { - pos += securityPattern.length(); - size_t end = line.find(' ', pos); - if (end == std::string::npos) - { - end = line.length(); - } - security = line.substr(pos, end - pos); - continue; - } - - // Fetch passphare value - pos = line.find(passphrasePattern); - if (pos != std::string::npos) - { - pos += passphrasePattern.length(); - size_t end = line.find('"', pos + 1); - if (end == std::string::npos) - { - end = line.length(); - } - passphrase = line.substr(pos + 1, end - pos - 1); - } - NMLOG_DEBUG("Fetched SSID = %s, security = %s", ssid.c_str(), security.c_str()); + else { + g_source_destroy(source); } + g_source_unref(source); } - configFile.close(); - clock_gettime(CLOCK_MONOTONIC, &endTime); - timeDiff = (endTime.tv_sec - startTime.tv_sec); - NMLOG_DEBUG("Time elapsed in getting SSID = %ld", timeDiff); - if(ssid.empty() && timeDiff < waitTime) - { - NMLOG_INFO("connected successfully; attempting to retrive SSID info to persist"); - sleep(5); - } - else - break; + wpsComplete = true; } - } - if(wpsConnect) - { - std::string nmCliCommand1 = "nmcli connection add type wifi ifname " + std::string(nmUtils::wlanIface()) + " con-name " + ssid + " ssid " + ssid + " wifi-sec.psk " + passphrase + " wifi-sec.key-mgmt wpa-psk && "; - std::string nmCliCommand2 = "nmcli connection up " + ssid; - std::string nmCliCommand = nmCliCommand1 + nmCliCommand2; - std::string nmCliResult = ""; - nmCliResult = wifiManager::executeWpaCliCommand(nmCliCommand); - if (nmCliResult != "ERROR") - NMLOG_INFO("NetworkManager updated with WPS status - connected successfully"); else { - NMLOG_ERROR("NetworkManager is not able to sync up with underneath wpa_supplicant/hal regarding the WPS connect"); /* TODO: Need to disconnect the wpa_cli connection, as the libnm is not aware of the connection created by wpa_cli */ - wpaCliCommand.clear(); - wpaCliResult.clear(); - wpaCliCommand = "wpa_cli -i " + std::string(nmUtils::wlanIface()) + " wps_cancel"; - wpaCliResult = wifiManager::executeWpaCliCommand(wpaCliCommand); - if (wpaCliResult == "ERROR") - { - NMLOG_ERROR("WPS cancel failed"); - } + //TODO Post SSID lost event ? + NMLOG_ERROR("request for wifi scanning"); + nm_device_wifi_request_scan(NM_DEVICE_WIFI(wifidevice), NULL, &error); } + + g_main_context_pop_thread_default(wpsContext); + + if(wpsComplete) + break; + + g_main_context_unref(wpsContext); } - g_main_context_pop_thread_default(m_wpsContext); - g_main_context_release(m_wpsContext); - if (m_wpsContext) { - g_main_context_unref(m_wpsContext); - m_wpsContext = nullptr; - } - return; + wpsProcessRun = false; } - bool wifiManager::initiateWPS() + bool wifiManager::startWPS() { - if(!m_wpsContext){ - if (wpsThread.joinable()) { - wpsThread.join(); - } - m_wpsContext = g_main_context_new(); - if (!m_wpsContext) { - NMLOG_ERROR("Failed to create new main context for WPS"); - return false; - } - wpsThread = std::thread(&wifiManager::wpsAction, this); + NMLOG_DEBUG("Start WPS %s", __FUNCTION__); + if(wpsProcessRun.load()) + { + NMLOG_WARNING("wps process WPS already running"); + return true; } - else - NMLOG_INFO("Start WPS is already in progress"); + m_secretAgent.RegisterAgent(); + std::thread wpsthread(&wpsProcess); + wpsthread.detach(); return true; } - bool wifiManager::cancelWPS() - { - NMLOG_INFO ("Stop WPS %s", __FUNCTION__); - wpsStop.store(true); - if (wpsThread.joinable()) { - wpsThread.join(); - } - if (m_wpsContext) { - g_main_context_unref(m_wpsContext); - m_wpsContext = nullptr; - } - wpsStop.store(false); - return true; + bool wifiManager::stopWPS() { + NMLOG_DEBUG("Stop WPS %s", __FUNCTION__); + wpsProcessRun = false; + return m_secretAgent.UnregisterAgent(); } static void deviceManagedCb(GObject *object, GAsyncResult *result, gpointer user_data) diff --git a/NetworkManagerGnomeWIFI.h b/NetworkManagerGnomeWIFI.h index 128c52f91..222c23909 100644 --- a/NetworkManagerGnomeWIFI.h +++ b/NetworkManagerGnomeWIFI.h @@ -23,6 +23,7 @@ #include #include "NetworkManagerLogger.h" #include "INetworkManager.h" +#include "NetworkManagerSecretAgent.h" #include #include #include @@ -30,16 +31,8 @@ #include #include -#define WPA_SUPPLICANT_CONF "/opt/secure/wifi/wpa_supplicant.conf" -#define WPA_CLI_STATUS "wpa_cli status" -#define MAX_WPS_AP_COUNT 3 -#define MAX_WPS_WAIT_DURATION 120 - -typedef struct _wifi_wps_pbc_ap -{ - char bssid[32]; - char ssid[32]; -} wifi_wps_pbc_ap_t; +#define WPS_RETRY_WAIT_IN_MS 10 // 10 sec +#define WPS_RETRY_COUNT 10 namespace WPEFramework { @@ -57,18 +50,16 @@ namespace WPEFramework bool isWifiConnected(); bool wifiDisconnect(); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); - bool wifiConnect(Exchange::INetworkManager::WiFiConnectTo wifiData); + bool wifiConnect(Exchange::INetworkManager::WiFiConnectTo ssidInfo); bool wifiScanRequest(std::string ssidReq = ""); - bool isWifiScannedRecently(int timelimitInSec = 5); // default 10 sec as shotest scanning interval + bool isWifiScannedRecently(int timelimitInSec = 5); // default 5 sec as shotest scanning interval bool getKnownSSIDs(std::list& ssids); bool addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo ssidinfo); bool removeKnownSSID(const string& ssid); bool quit(NMDevice *wifiNMDevice); bool wait(GMainLoop *loop, int timeOutMs = 10000); // default maximium set as 10 sec - bool initiateWPS(); - bool cancelWPS(); - void wpsAction(); - std::string executeWpaCliCommand(const std::string& wpaCliCommand); + bool startWPS(); + bool stopWPS(); bool setInterfaceState(std::string interface, bool enabled); bool setIpSettings(const string interface, const Exchange::INetworkManager::IPAddress address); private: @@ -93,19 +84,17 @@ namespace WPEFramework void operator=(wifiManager const&) = delete; bool createClientNewConnection(); - std::atomic wpsStop = {false}; - std::thread wpsThread; public: NMClient *m_client; GMainLoop *m_loop; gboolean m_createNewConnection; GMainContext *m_nmContext = nullptr; - GMainContext *m_wpsContext = nullptr; const char* m_objectPath; NMDevice *m_wifidevice; GSource *m_source; bool m_isSuccess = false; + SecretAgent m_secretAgent; }; } // Plugin } // WPEFramework diff --git a/NetworkManagerSecretAgent.cpp b/NetworkManagerSecretAgent.cpp new file mode 100644 index 000000000..7bfec9664 --- /dev/null +++ b/NetworkManagerSecretAgent.cpp @@ -0,0 +1,352 @@ + +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2022 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include +#include +#include + +#include +#include + +#include +#include + +#include "NetworkManagerLogger.h" +#include "NetworkManagerSecretAgent.h" + +namespace WPEFramework +{ + namespace Plugin + { + std::atomicstopwait; + static const gchar interfaceXml[] = + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; + + static void handleSecretsAgentMethods( GDBusConnection *connection, const gchar *sender, + const gchar *object_path, const gchar *interface_name, const gchar *method_name, + GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { + + NMLOG_DEBUG("handleSecretsAgentMethods called for sender: %s", sender); + char *string = g_variant_print(parameters, TRUE); + NMLOG_DEBUG("GVariant: %s", string); + g_free(string); + + if (g_strcmp0(method_name, "GetSecrets") == 0) + { + GVariant *settingConn = NULL; + GVariant *connectionPath = NULL; + GVariant *settingName = NULL; + GVariant *hints = NULL; + GVariant *flagVar = NULL; + guint flags=0; + + g_variant_get(parameters, "(@a{sa{sv}}@o@s@as@u)", &settingConn, &connectionPath, &settingName, &hints, &flagVar); + + if (g_variant_is_of_type (connectionPath, G_VARIANT_TYPE_OBJECT_PATH)) { + const char* connPath = g_variant_get_string(connectionPath, NULL); + NMLOG_DEBUG("connection path %s", connPath); + } + + if (g_variant_is_of_type (flagVar, G_VARIANT_TYPE_UINT32)) + { + std::string flagStr; + flags = g_variant_get_uint32(flagVar); + if(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE) + flagStr += ", wps_pbc_active"; + if(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION) + flagStr += ", allow_interaction"; + if(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED) { + flagStr += ", user_requested"; + stopwait.store(false); + /* wait for 10 sec mean time in the background networkmanager will do wps operation */ + SecretAgent::wait(static_cast(10)); + } + NMLOG_INFO("SecretAgent GetSecrets Flags = %u %s", flags, flagStr.c_str()); + } + + if(settingConn) + g_variant_unref(settingConn); + if(connectionPath) + g_variant_unref(connectionPath); + if(hints) + g_variant_unref(hints); + if(flagVar) + g_variant_unref(flagVar); + + g_dbus_method_invocation_return_value(invocation, g_variant_new("(a{sa{sv}})", NULL)); + } + else if (g_strcmp0(method_name, "CancelGetSecrets") == 0) + { + NMLOG_DEBUG("CancelGetSecrets method called"); + SecretAgent::stopWait(); + g_dbus_method_invocation_return_value(invocation, NULL); + } + else if (g_strcmp0(method_name, "SaveSecrets") == 0) + { + NMLOG_DEBUG("SaveSecrets method called"); + g_dbus_method_invocation_return_value(invocation, NULL); + } + else if (g_strcmp0(method_name, "DeleteSecrets") == 0) + { + NMLOG_DEBUG("DeleteSecrets method called"); + g_dbus_method_invocation_return_value(invocation, NULL); + } + + NMLOG_DEBUG("method: %s", method_name); + } + + static const GDBusInterfaceVTable interfaceVtable = { + .method_call = handleSecretsAgentMethods, + .get_property = NULL, + .set_property = NULL, + }; + + SecretAgent::SecretAgent() + { + GError *error = NULL; + isSecretAgentLoopRunning = false; + NMLOG_INFO("SecretAgent Constructor"); + GDBusconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!GDBusconn) { + NMLOG_ERROR("Failed to connect to system bus: %s", error->message); + g_error_free(error); + return; + } + + isSecurityAgentRegistered = false; + startSecurityAgent(); + } + + SecretAgent::~SecretAgent() + { + NMLOG_INFO("SecretAgent Destructor"); + stopSecurityAgent(); + if(GDBusconn) + g_object_unref(GDBusconn); + } + + void SecretAgent::wait(const std::chrono::seconds timeout) + { + NMLOG_INFO("wait started %ld Sec", timeout.count()); + auto start = std::chrono::high_resolution_clock::now(); + while (stopwait.load() == false) + { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + if (std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start) >= timeout) + { + return; + } + } + } + + void SecretAgent::stopWait() + { + stopwait.store(true); + NMLOG_INFO("wait exit"); + } + + void SecretAgent::SecretAgentLoop(SecretAgent* SecretAgentPtr) + { + GError *error = NULL; + GMainContext *secretAgentContext = NULL; + SecretAgent* agent = static_cast(SecretAgentPtr); + secretAgentContext = g_main_context_new(); + if(secretAgentContext == NULL) + { + NMLOG_ERROR("Failed to create Security Agent gmain loop context"); + return; + } + + g_main_context_push_thread_default(secretAgentContext); + agent->agentGmainLoop = g_main_loop_new(secretAgentContext, FALSE); + if(agent->agentGmainLoop == NULL) + { + NMLOG_ERROR("Failed to create Security Agent gmain loop"); + g_main_context_pop_thread_default(secretAgentContext); + g_main_context_unref(secretAgentContext); + return; + } + + GDBusNodeInfo *node_info = g_dbus_node_info_new_for_xml(interfaceXml, &error); + if (!node_info) { + NMLOG_ERROR("Failed to parse XML: %s", error->message); + g_error_free(error); + return; + } + + guint agentRegID = g_dbus_connection_register_object( + agent->GDBusconn, + "/org/freedesktop/NetworkManager/SecretAgent", + g_dbus_node_info_lookup_interface(node_info, "org.freedesktop.NetworkManager.SecretAgent"), // Interface, + &interfaceVtable, + NULL, + NULL, + &error); + + if (!agentRegID) { + NMLOG_ERROR("Failed to register object: %s", error->message); + g_error_free(error); + g_dbus_node_info_unref(node_info); + return ; + } + + NMLOG_INFO("Object registered with ID: %u", agentRegID); + NMLOG_DEBUG("Security Agent gmain loop running..."); + g_main_loop_run(agent->agentGmainLoop); + + g_main_loop_unref(agent->agentGmainLoop); + g_dbus_connection_unregister_object(agent->GDBusconn, agentRegID); + g_dbus_node_info_unref(node_info); + g_main_context_pop_thread_default(secretAgentContext); + g_main_context_unref(secretAgentContext); + agent->isSecretAgentLoopRunning = false; + NMLOG_WARNING("Security Agent loop ended !"); + } + + void SecretAgent::startSecurityAgent() + { + NMLOG_DEBUG("staring Security Agent..."); + if(isSecretAgentLoopRunning) + { + NMLOG_INFO("Security Agent already running."); + return; + } + + isSecretAgentLoopRunning = true; + agentThrID = std::thread(&SecretAgentLoop, this); + } + + void SecretAgent::stopSecurityAgent() + { + if (agentGmainLoop) { + g_main_loop_quit(agentGmainLoop); + } + + if (agentThrID.joinable()) { + agentThrID.join(); + } + + NMLOG_INFO("Security Agent stopped."); + } + + bool SecretAgent::RegisterAgent() + { + if(isSecurityAgentRegistered) + { + NMLOG_INFO("'rdk.nm.agent' alreday registered to NetworkManager"); + return true; + } + + GError *error = NULL; + GDBusProxy *nmAgentProxy = g_dbus_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.freedesktop.NetworkManager", + "/org/freedesktop/NetworkManager/AgentManager", + "org.freedesktop.NetworkManager.AgentManager", + NULL, + &error + ); + + if (error != NULL && nmAgentProxy == NULL) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating proxy: %s", error->message); + g_clear_error(&error); + return false; + } + + g_dbus_proxy_call_sync( nmAgentProxy, "Register", + g_variant_new("(s)", "rdk.nm.agent"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + + if (error != NULL) { + NMLOG_ERROR("Failed to register agent: %s", error->message); + g_error_free(error); + return false; + } + + NMLOG_INFO("'rdk.nm.agent' registered to NetworkManager"); + isSecurityAgentRegistered = true; + if(nmAgentProxy) + g_object_unref(nmAgentProxy); + return true; + } + + bool SecretAgent::UnregisterAgent() + { + if(!isSecurityAgentRegistered) + { + NMLOG_INFO("'rdk.nm.agent' not registered to NetworkManager"); + return true; + } + + GError *error = NULL; + GDBusProxy *nmAgentProxy = g_dbus_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.freedesktop.NetworkManager", + "/org/freedesktop/NetworkManager/AgentManager", + "org.freedesktop.NetworkManager.AgentManager", + NULL, + &error + ); + + if (error != NULL && nmAgentProxy == NULL) { + g_dbus_error_strip_remote_error(error); + NMLOG_FATAL("Error creating proxy: %s", error->message); + g_clear_error(&error); + return false; + } + + g_dbus_proxy_call_sync(nmAgentProxy, "Unregister", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + + if (error != NULL) { + NMLOG_FATAL("Failed to call Unregister agent: %s", error->message); + g_error_free(error); + return false; + } + + NMLOG_INFO("'rdk.nm.agent' successfully Unregister"); + isSecurityAgentRegistered = false; + if(nmAgentProxy) + g_object_unref(nmAgentProxy); + return true; + } + + } // WPEFramework +} // Plugin diff --git a/NetworkManagerSecretAgent.h b/NetworkManagerSecretAgent.h new file mode 100644 index 000000000..4c2ccb9d2 --- /dev/null +++ b/NetworkManagerSecretAgent.h @@ -0,0 +1,53 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include +#include +#include +#include + +#include "NetworkManagerLogger.h" +#include "INetworkManager.h" + +namespace WPEFramework +{ + namespace Plugin + { + class SecretAgent + { + public: + SecretAgent(); + ~SecretAgent(); + void startSecurityAgent(); + void stopSecurityAgent(); + bool RegisterAgent(); + bool UnregisterAgent(); + static void SecretAgentLoop(SecretAgent* agent); + static void wait(const std::chrono::seconds timeout); + static void stopWait(); + private: + std::atomic isSecretAgentLoopRunning; + GMainLoop *agentGmainLoop = nullptr; + GDBusConnection *GDBusconn; + std::thread agentThrID; + std::atomic isSecurityAgentRegistered; + }; + } // Plugin +} // WPEFramework From eb8f200bd08b80dbba917e5163d7014fe99790f1 Mon Sep 17 00:00:00 2001 From: parvathika <131966254+parvathika@users.noreply.github.com> Date: Tue, 11 Feb 2025 21:38:17 +0530 Subject: [PATCH 084/271] Remove Thunder Interface Build from workflow (#94) * Update gnome_unit_test.yml * Update rdk_unit_test.yml --- .github/workflows/gnome_unit_test.yml | 12 +----------- .github/workflows/rdk_unit_test.yml | 10 ---------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index 9d25d4ac7..870d95222 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -35,8 +35,7 @@ jobs: run: | git clone https://github.com/rdkcentral/ThunderTools ThunderTools --branch ${{ env.THUNDER_REF }} git clone https://github.com/rdkcentral/Thunder Thunder --branch ${{ env.THUNDER_REF }} - git clone https://github.com/rdkcentral/ThunderInterfaces ThunderInterfaces --branch ${{ env.THUNDER_REF }} - + - name: Build ThunderTools run: > cmake @@ -59,15 +58,6 @@ jobs: && cmake --build build/Thunder --target install -j8 - - name: Build ThunderInterfaces - run: > - cmake - -S "${{github.workspace}}/ThunderInterfaces" -B build/ThunderInterfaces - -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" - -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" - && - cmake --build build/ThunderInterfaces --target install -j8 - - name: Checkout networkmanager uses: actions/checkout@v3 with: diff --git a/.github/workflows/rdk_unit_test.yml b/.github/workflows/rdk_unit_test.yml index dc39e9975..eab2497af 100644 --- a/.github/workflows/rdk_unit_test.yml +++ b/.github/workflows/rdk_unit_test.yml @@ -35,7 +35,6 @@ jobs: run: | git clone https://github.com/rdkcentral/ThunderTools ThunderTools --branch ${{ env.THUNDER_REF }} git clone https://github.com/rdkcentral/Thunder Thunder --branch ${{ env.THUNDER_REF }} - git clone https://github.com/rdkcentral/ThunderInterfaces ThunderInterfaces --branch ${{ env.THUNDER_REF }} - name: Checkout networkmanager uses: actions/checkout@v3 @@ -69,15 +68,6 @@ jobs: && cmake --build build/Thunder --target install -j8 - - name: Build ThunderInterfaces - run: > - cmake - -S "${{github.workspace}}/ThunderInterfaces" -B build/ThunderInterfaces - -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" - -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" - && - cmake --build build/ThunderInterfaces --target install -j8 - - name: Generate IARM headers run: | touch install/usr/lib/libIARMBus.so From 68c01c3cf234798ee8b15548f80790880fdb002c Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 11 Feb 2025 19:44:29 -0500 Subject: [PATCH 085/271] RDK-56182 - NetworkManager Thunder Plugin - Report WiFi SNR (#92) * RDK-56182 - NetworkManager Thunder Plugin - Report WiFi SNR Reason for change: Added the SNR approach to calculate the signal strength and cleaned up the code Test Procedure: Test and verified Risks: Medium Priority: P1 Signed-off-by: Gururaaja ESR --- CMakeLists.txt | 1 - NetworkManager.json | 17 ++- NetworkManagerGnomeProxy.cpp | 136 ++++++++++++++--- NetworkManagerImplementation.cpp | 76 +++++++++- NetworkManagerImplementation.h | 18 ++- NetworkManagerJsonRpc.cpp | 6 +- NetworkManagerRDKProxy.cpp | 51 ++++--- .../test_NetworkManagerConnectivity.cpp | 12 ++ Tests/unit_test/unit_tests.cmake | 3 - WiFiSignalStrengthMonitor.cpp | 143 ------------------ WiFiSignalStrengthMonitor.h | 49 ------ docs/NetworkManagerPlugin.md | 30 ++-- gdbus/NetworkManagerGdbusClient.cpp | 55 ++++--- gdbus/NetworkManagerGdbusProxy.cpp | 4 +- 14 files changed, 314 insertions(+), 287 deletions(-) delete mode 100644 WiFiSignalStrengthMonitor.cpp delete mode 100644 WiFiSignalStrengthMonitor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a12896bc7..eabcfa6f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,7 +105,6 @@ add_library(${MODULE_NAME} SHARED NetworkManagerImplementation.cpp NetworkManagerConnectivity.cpp NetworkManagerStunClient.cpp - WiFiSignalStrengthMonitor.cpp Module.cpp ${PROXY_STUB_SOURCES}) diff --git a/NetworkManager.json b/NetworkManager.json index 81886f83e..5ac07a8f3 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -122,13 +122,13 @@ "type": "string", "example": "password" }, - "security": { + "security":{ "summary": "The security mode. See `getSupportedsecurityModes`.", "type": "integer", "example": 6 }, "strength":{ - "summary": "The Signal RSSI value in dBm", + "summary": "Signal to Noise Ratio(SNR) in dBm", "type": "string", "example": "-27.000000" }, @@ -1014,7 +1014,9 @@ "$ref": "#/definitions/passphrase" }, "security": { - "$ref": "#/definitions/security" + "summary": "The security mode is decided based on the highest security mode provided by the SSID", + "type": "integer", + "example": 2 }, "ca_cert": { "summary": "The ca_cert to be used for EAP", @@ -1069,8 +1071,7 @@ }, "required": [ "ssid", - "passphrase", - "security" + "passphrase" ] }, "result": { @@ -1121,7 +1122,9 @@ "example": "5" }, "strength": { - "$ref": "#/definitions/strength" + "summary": "The Signal RSSI value in dBm", + "type": "string", + "example": "-27.000000" }, "frequency": { "$ref": "#/definitions/frequency" @@ -1213,7 +1216,7 @@ } }, "GetWiFiSignalStrength":{ - "summary": "Get WiFiSignalStrength of connected SSID. The signal quality is identifed based on the signal strength. The possible states are\n* 'Excellent'\n* 'Good'\n* 'Fair'\n* 'Weak'\n* 'Disconnected'\n", + "summary": "Get WiFiSignalStrength of connected SSID. The signal quality is identifed based on the Signal to Noise ratio which is calculated as SNR = rssi - noise. The possible states are\n* 'Excellent' : More than 40 dBm\n* 'Good' : 40 dBm to 25 dBm\n* 'Fair' : 25 dBm to 18 dBm\n* 'Weak' : 18 dBm to 0 dBm\n* 'Disconnected' : 0 dBm\n", "events":{ "onWiFiSignalStrengthChange" : "Triggered when Wifi signal strength switches between Excellent, Good, Fair, Weak." }, diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index 4f979832f..a56980c79 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -24,6 +24,9 @@ #include #include +#define rssid_command "wpa_cli signal_poll" +#define ssid_command "wpa_cli status" + static NMClient *client = NULL; using namespace WPEFramework; using namespace WPEFramework::Plugin; @@ -35,9 +38,6 @@ namespace WPEFramework { wifiManager *wifi = nullptr; GnomeNetworkManagerEvents *nmEvent = nullptr; - const float signalStrengthThresholdExcellent = -50.0f; - const float signalStrengthThresholdGood = -60.0f; - const float signalStrengthThresholdFair = -67.0f; NetworkManagerImplementation* _instance = nullptr; void NetworkManagerInternalEventHandler(const char *owner, int eventId, void *data, size_t len) @@ -661,35 +661,135 @@ namespace WPEFramework return rc; } - uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& signalStrength /* @out */, WiFiSignalQuality& quality /* @out */) + uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; + uint16_t strengthOut = 0; + + std::string key, value; + std::string noiseStr = ""; + std::string rssiStr = ""; + uint16_t rssi = 0; + uint16_t noise = 0; + char buff[512] = {'\0'}; + + FILE *fp = NULL; + fp = popen(rssid_command, "r"); + if (!fp) + { + NMLOG_ERROR("Failed in getting output from command %s",rssid_command); + return Core::ERROR_RPC_CALL_FAILED; + } + while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) + { + std::istringstream mystream(buff); + if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) + if (key == "RSSI") { + rssiStr = value; + } + else if (key == "NOISE") { + noiseStr = value; + } + if (!rssiStr.empty() && !noiseStr.empty()) + break; + } + pclose(fp); + fp = popen(ssid_command, "r"); + if (!fp) + { + NMLOG_ERROR("Failed in getting output from command %s",ssid_command); + return Core::ERROR_RPC_CALL_FAILED; + } + while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) + { + std::istringstream mystream(buff); + if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) + if (key == "ssid") { + ssid = value; + break; + } + } + pclose(fp); + rssi = std::stoi(rssiStr); + noise = std::stoi(noiseStr); + strengthOut = (rssi - noise); + NMLOG_INFO ("WiFiSignalStrength in dB = %u",strengthOut); - WiFiSSIDInfo ssidInfo; - if(wifi->wifiConnectedSSIDInfo(ssidInfo)) + if (strengthOut == 0) + { + quality = WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; + strength = "0"; + } + else if (strengthOut > 0 && strengthOut < NM_WIFI_SNR_THRESHOLD_FAIR) { - ssid = ssidInfo.ssid; - signalStrength = ssidInfo.strength; + quality = WiFiSignalQuality::WIFI_SIGNAL_WEAK; + } + else if (strengthOut > NM_WIFI_SNR_THRESHOLD_FAIR && strengthOut < NM_WIFI_SNR_THRESHOLD_GOOD) + { + quality = WiFiSignalQuality::WIFI_SIGNAL_FAIR; + } + else if (strengthOut > NM_WIFI_SNR_THRESHOLD_GOOD && strengthOut < NM_WIFI_SNR_THRESHOLD_EXCELLENT) + { + quality = WiFiSignalQuality::WIFI_SIGNAL_GOOD; + } + else + { + quality = WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT; + } + + strength = std::to_string(strengthOut); - float signalStrengthFloat = 0.0f; - if(!signalStrength.empty()) - signalStrengthFloat = std::stof(signalStrength.c_str()); + NMLOG_INFO ("GetWiFiSignalStrength success"); - if (signalStrengthFloat == 0) + rc = Core::ERROR_NONE; +#if 0 + float rssi = 0.0f; + float noise = 0.0f; + float floatSignalStrength = 0.0f; + WiFiSSIDInfo ssidInfo; + if(wifi->wifiConnectedSSIDInfo(ssidInfo)) + { + ssid = ssidInfo.ssid; + if (!ssidInfo.strength.empty()) + rssi = std::stof(ssidInfo.strength.c_str()); + if (!ssidInfo.noise.empty()) + noise = std::stof(ssidInfo.noise.c_str()); + floatSignalStrength = (rssi - noise); + if (floatSignalStrength < 0) + floatSignalStrength = 0.0; + + strengthOut = static_cast(floatSignalStrength); + NMLOG_INFO ("WiFiSignalStrength in dB = %u",strengthOut); + + if (strengthOut == 0) + { quality = WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; - else if (signalStrengthFloat >= signalStrengthThresholdExcellent && signalStrengthFloat < 0) - quality = WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT; - else if (signalStrengthFloat >= signalStrengthThresholdGood && signalStrengthFloat < signalStrengthThresholdExcellent) - quality = WiFiSignalQuality::WIFI_SIGNAL_GOOD; - else if (signalStrengthFloat >= signalStrengthThresholdFair && signalStrengthFloat < signalStrengthThresholdGood) + signalStrength = "0"; + } + else if (strengthOut > 0 && strengthOut < NM_WIFI_SNR_THRESHOLD_FAIR) + { + quality = WiFiSignalQuality::WIFI_SIGNAL_WEAK; + } + else if (strengthOut > NM_WIFI_SNR_THRESHOLD_FAIR && strengthOut < NM_WIFI_SNR_THRESHOLD_GOOD) + { quality = WiFiSignalQuality::WIFI_SIGNAL_FAIR; + } + else if (strengthOut > NM_WIFI_SNR_THRESHOLD_GOOD && strengthOut < NM_WIFI_SNR_THRESHOLD_EXCELLENT) + { + quality = WiFiSignalQuality::WIFI_SIGNAL_GOOD; + } else - quality = WiFiSignalQuality::WIFI_SIGNAL_WEAK; + { + quality = WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT; + } + + signalStrength = std::to_string(strengthOut); NMLOG_INFO ("GetWiFiSignalStrength success"); rc = Core::ERROR_NONE; } +#endif return rc; } diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index fc1bfda89..91cf82d04 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -17,8 +17,9 @@ * limitations under the License. **/ +#include +#include #include "NetworkManagerImplementation.h" -#include "WiFiSignalStrengthMonitor.h" using namespace WPEFramework; using namespace WPEFramework::Plugin; @@ -58,6 +59,7 @@ namespace WPEFramework { m_registrationThread.join(); } + stopWiFiSignalStrengthMonitor(); } /** @@ -668,16 +670,86 @@ namespace WPEFramework _notificationLock.Unlock(); } + void NetworkManagerImplementation::startWiFiSignalStrengthMonitor(int interval) + { + if (m_isRunning) { + NMLOG_INFO("WiFiSignalStrengthMonitor Thread is already running."); + return; + } + m_isRunning = true; + m_stopThread = false; + m_monitorThread = std::thread(&NetworkManagerImplementation::monitorThreadFunction, this, interval); + } + + void NetworkManagerImplementation::stopWiFiSignalStrengthMonitor() + { + if (!m_isRunning) { + return; // No thread to stop + } + std::lock_guard lock(m_condVariableMutex); + m_stopThread = true; + m_condVariable.notify_one(); + if (m_monitorThread.joinable()) { + m_monitorThread.join(); + } + m_isRunning = false; + } + + void NetworkManagerImplementation::monitorThreadFunction(int interval) + { + static Exchange::INetworkManager::WiFiSignalQuality oldSignalQuality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; + NMLOG_INFO("WiFiSignalStrengthMonitor thread started ! (%d)", interval); + while (!m_stopThread) { + std::string ssid; + std::string strength; + std::unique_lock lock(m_condVariableMutex); + Exchange::INetworkManager::WiFiSignalQuality newSignalQuality; + + NMLOG_DEBUG("checking WiFi signal strength"); + NetworkManagerImplementation::GetWiFiSignalStrength(ssid, strength, newSignalQuality); + + if (oldSignalQuality != newSignalQuality) { + NMLOG_INFO("Notifying WiFiSignalStrengthChangedEvent %s", strength.c_str()); + oldSignalQuality = newSignalQuality; + NetworkManagerImplementation::ReportWiFiSignalStrengthChange(ssid, strength, newSignalQuality); + } + + if (newSignalQuality == Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED) { + NMLOG_WARNING("WiFiSignalStrengthChanged to disconnect - WiFiSignalStrengthMonitor exiting"); + m_stopThread = true; // Signal thread to stop + break; // Exit the loop + } + + // Wait for the specified interval or until notified to stop + if (m_condVariable.wait_for(lock, std::chrono::seconds(interval), [this](){ return m_stopThread == true; })) + { + NMLOG_INFO("WiFiSignalStrengthMonitor received stop signal or timed out"); + } + } + m_isRunning = false; + } + void NetworkManagerImplementation::ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state) { /* start signal strength monitor when wifi connected */ if(INetworkManager::WiFiState::WIFI_STATE_CONNECTED == state) { m_wlanConnected = true; - m_wifiSignalMonitor.startWiFiSignalStrengthMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC); + if (!m_monitoringStarted) + { + startWiFiSignalStrengthMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC); + m_monitoringStarted = true; + } } else + { + if (m_monitoringStarted) + { + stopWiFiSignalStrengthMonitor(); + m_monitoringStarted = false; + } m_wlanConnected = false; /* Any other state is considered as WiFi not connected. */ + } _notificationLock.Lock(); NMLOG_INFO("Posting onWiFiStateChange (%d)", state); diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 1bf4a7d25..85b0be825 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -31,12 +31,16 @@ using namespace std; #include "INetworkManager.h" #include "NetworkManagerLogger.h" -#include "WiFiSignalStrengthMonitor.h" #include "NetworkManagerConnectivity.h" #include "NetworkManagerStunClient.h" #define DEFAULT_NOISE -180 +#define DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC 60 +#define NM_WIFI_SNR_THRESHOLD_EXCELLENT 40 +#define NM_WIFI_SNR_THRESHOLD_GOOD 25 +#define NM_WIFI_SNR_THRESHOLD_FAIR 18 + namespace WPEFramework { namespace Plugin @@ -211,7 +215,7 @@ namespace WPEFramework uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) override; uint32_t StopWPS(void) override; uint32_t GetWifiState(WiFiState &state) override; - uint32_t GetWiFiSignalStrength(string& ssid /* @out */, string& signalStrength /* @out */, WiFiSignalQuality& quality /* @out */) override; + uint32_t GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) override; uint32_t SetStunEndpoint (string const endpoint /* @in */, const uint32_t port /* @in */, const uint32_t bindTimeout /* @in */, const uint32_t cacheTimeout /* @in */) override; uint32_t GetStunEndpoint (string &endpoint /* @out */, uint32_t& port /* @out */, uint32_t& bindTimeout /* @out */, uint32_t& cacheTimeout /* @out */) const override; @@ -259,6 +263,9 @@ namespace WPEFramework void executeExternally(NetworkEvents event, const string commandToExecute, string& response); void threadEventRegistration(void); void filterScanResults(JsonArray &ssids); + void startWiFiSignalStrengthMonitor(int interval); + void stopWiFiSignalStrengthMonitor(); + void monitorThreadFunction(int interval); private: std::list _notificationCallbacks; @@ -273,11 +280,16 @@ namespace WPEFramework std::thread m_registrationThread; string m_filterfrequency; std::vector m_filterSsidslist; + std::thread m_monitorThread; + std::atomic m_stopThread{false}; + std::atomic m_isRunning{false}; + bool m_monitoringStarted = false; + std::mutex m_condVariableMutex; + std::condition_variable m_condVariable; public: std::atomic m_ethConnected; std::atomic m_wlanConnected; - WiFiSignalStrengthMonitor m_wifiSignalMonitor; mutable ConnectivityMonitor connectivityMonitor; }; } diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 55be805be..7fdccb401 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -890,11 +890,11 @@ namespace WPEFramework LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string ssid{}; - string signalStrength{}; + string strength{}; Exchange::INetworkManager::WiFiSignalQuality quality{}; if (_networkManager) - rc = _networkManager->GetWiFiSignalStrength(ssid, signalStrength, quality); + rc = _networkManager->GetWiFiSignalStrength(ssid, strength, quality); else rc = Core::ERROR_UNAVAILABLE; @@ -902,7 +902,7 @@ namespace WPEFramework { Core::JSON::EnumType iquality(quality); response["ssid"] = ssid; - response["strength"] = signalStrength; + response["strength"] = strength; response["quality"] = iquality.Data(); } returnJson(rc); diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 6c2f45e14..ab044b413 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -18,7 +18,6 @@ **/ #include "NetworkManagerImplementation.h" #include "NetworkManagerConnectivity.h" -#include "WiFiSignalStrengthMonitor.h" #include "libIBus.h" using namespace WPEFramework; @@ -375,9 +374,6 @@ namespace WPEFramework { namespace Plugin { - const float signalStrengthThresholdExcellent = -50.0f; - const float signalStrengthThresholdGood = -60.0f; - const float signalStrengthThresholdFair = -67.0f; NetworkManagerImplementation* _instance = nullptr; Exchange::INetworkManager::WiFiState to_wifi_state(WiFiStatusCode_t code) { @@ -1379,46 +1375,53 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { return rc; } - uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& signalStrength /* @out */, WiFiSignalQuality& quality /* @out */) + uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; WiFiSSIDInfo ssidInfo{}; - float signalStrengthOut = 0.0f; + float rssi = 0.0f; + float noise = 0.0f; + float floatStrength = 0.0f; + unsigned int strengthOut = 0; if (Core::ERROR_NONE == GetConnectedSSID(ssidInfo)) { - ssid = ssidInfo.ssid; - signalStrength = ssidInfo.strength; - - if (!signalStrength.empty()) - { - signalStrengthOut = std::stof(signalStrength.c_str()); - NMLOG_INFO ("WiFiSignalStrength in dB = %f",signalStrengthOut); - } - - if (signalStrengthOut == 0) + ssid = ssidInfo.ssid; + if (!ssidInfo.strength.empty()) + rssi = std::stof(ssidInfo.strength.c_str()); + if (!ssidInfo.noise.empty()) + noise = std::stof(ssidInfo.noise.c_str()); + floatStrength = (rssi - noise); + if (floatStrength < 0) + floatStrength = 0.0; + + strengthOut = static_cast(floatStrength); + NMLOG_INFO ("WiFiSignalStrength in dB = %u",strengthOut); + + if (strengthOut == 0) { quality = WIFI_SIGNAL_DISCONNECTED; - signalStrength = "0"; + strength = "0"; } - else if (signalStrengthOut >= signalStrengthThresholdExcellent && signalStrengthOut < 0) + else if (strengthOut > 0 && strengthOut < NM_WIFI_SNR_THRESHOLD_FAIR) { - quality = WIFI_SIGNAL_EXCELLENT; + quality = WIFI_SIGNAL_WEAK; } - else if (signalStrengthOut >= signalStrengthThresholdGood && signalStrengthOut < signalStrengthThresholdExcellent) + else if (strengthOut > NM_WIFI_SNR_THRESHOLD_FAIR && strengthOut < NM_WIFI_SNR_THRESHOLD_GOOD) { - quality = WIFI_SIGNAL_GOOD; + quality = WIFI_SIGNAL_FAIR; } - else if (signalStrengthOut >= signalStrengthThresholdFair && signalStrengthOut < signalStrengthThresholdGood) + else if (strengthOut > NM_WIFI_SNR_THRESHOLD_GOOD && strengthOut < NM_WIFI_SNR_THRESHOLD_EXCELLENT) { - quality = WIFI_SIGNAL_FAIR; + quality = WIFI_SIGNAL_GOOD; } else { - quality = WIFI_SIGNAL_WEAK; + quality = WIFI_SIGNAL_EXCELLENT; } + strength = std::to_string(strengthOut); NMLOG_INFO ("GetWiFiSignalStrength success"); rc = Core::ERROR_NONE; } diff --git a/Tests/unit_test/test_NetworkManagerConnectivity.cpp b/Tests/unit_test/test_NetworkManagerConnectivity.cpp index 2f6cf144f..8716b6257 100644 --- a/Tests/unit_test/test_NetworkManagerConnectivity.cpp +++ b/Tests/unit_test/test_NetworkManagerConnectivity.cpp @@ -23,6 +23,18 @@ using namespace std; using namespace WPEFramework; +using namespace WPEFramework::Plugin; +namespace WPEFramework +{ + namespace Plugin + { + NetworkManagerImplementation* _instance = nullptr; + void NetworkManagerImplementation::ReportInternetStatusChange(const InternetStatus prevState, const InternetStatus currState) + { + return; + } + } +} class ConnectivityMonitorTest : public ::testing::Test { protected: diff --git a/Tests/unit_test/unit_tests.cmake b/Tests/unit_test/unit_tests.cmake index 39984d44a..7b19385fb 100644 --- a/Tests/unit_test/unit_tests.cmake +++ b/Tests/unit_test/unit_tests.cmake @@ -19,10 +19,8 @@ FetchContent_Declare( FetchContent_MakeAvailable(googletest) add_executable(${NM_CLASS_UT} - Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp Tests/unit_test/test_NetworkManagerConnectivity.cpp Tests/unit_test/test_NetworkManagerStunClient.cpp - WiFiSignalStrengthMonitor.cpp NetworkManagerLogger.cpp NetworkManagerConnectivity.cpp NetworkManagerStunClient.cpp @@ -38,7 +36,6 @@ add_executable(${NM_RDKPROXY_UT} NetworkManagerImplementation.cpp NetworkManagerConnectivity.cpp NetworkManagerStunClient.cpp - WiFiSignalStrengthMonitor.cpp NetworkManagerRDKProxy.cpp ${PROXY_STUB_SOURCES} ) diff --git a/WiFiSignalStrengthMonitor.cpp b/WiFiSignalStrengthMonitor.cpp deleted file mode 100644 index 204a164c3..000000000 --- a/WiFiSignalStrengthMonitor.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2020 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ -#include -#include -#include -#include -#include -#include "NetworkManagerLogger.h" -#include "NetworkManagerImplementation.h" -#include "WiFiSignalStrengthMonitor.h" - -#define BUFFER_SIZE 512 - -namespace WPEFramework -{ - namespace Plugin - { - static const float signalStrengthThresholdExcellent = -50.0f; - static const float signalStrengthThresholdGood = -60.0f; - static const float signalStrengthThresholdFair = -67.0f; - extern NetworkManagerImplementation* _instance; - - void WiFiSignalStrengthMonitor::getSignalData(std::string &ssid, Exchange::INetworkManager::WiFiSignalQuality &quality, std::string &strengthOut) - { - float signalStrengthOut = 0.0f; - char buff[BUFFER_SIZE] = {'\0'}; - string signalStrength = ""; - - if (_instance != nullptr) - { - Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; - _instance->GetConnectedSSID(ssidInfo); - ssid = ssidInfo.ssid; - signalStrength = ssidInfo.strength; - } - else - { - NMLOG_FATAL("NetworkManagerImplementation pointer error !"); - return; - } - - if (ssid.empty()) - { - quality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; - strengthOut = "0.00"; - return; - } - - if (!signalStrength.empty()) { - signalStrengthOut = std::stof(signalStrength.c_str()); - strengthOut = signalStrength; - } - else - NMLOG_ERROR("signalStrength is empty"); - - NMLOG_DEBUG("SSID = %s Signal Strength %f db", ssid.c_str(), signalStrengthOut); - if (signalStrengthOut == 0.0f) - { - quality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; - strengthOut = "0.00"; - } - else if (signalStrengthOut >= signalStrengthThresholdExcellent && signalStrengthOut < 0) - { - quality = Exchange::INetworkManager::WIFI_SIGNAL_EXCELLENT; - } - else if (signalStrengthOut >= signalStrengthThresholdGood && signalStrengthOut < signalStrengthThresholdExcellent) - { - quality = Exchange::INetworkManager::WIFI_SIGNAL_GOOD; - } - else if (signalStrengthOut >= signalStrengthThresholdFair && signalStrengthOut < signalStrengthThresholdGood) - { - quality = Exchange::INetworkManager::WIFI_SIGNAL_FAIR; - } - else - { - quality = Exchange::INetworkManager::WIFI_SIGNAL_WEAK; - }; - } - - void WiFiSignalStrengthMonitor::startWiFiSignalStrengthMonitor(int interval) - { - stopThread = false; - if (isRunning) { - NMLOG_INFO("WiFiSignalStrengthMonitor Thread is already running."); - return; - } - isRunning = true; - monitorThread = std::thread(&WiFiSignalStrengthMonitor::monitorThreadFunction, this, interval); - monitorThread.detach(); - } - - void WiFiSignalStrengthMonitor::monitorThreadFunction(int interval) - { - static Exchange::INetworkManager::WiFiSignalQuality oldSignalQuality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; - NMLOG_INFO("WiFiSignalStrengthMonitor thread started ! (%d)", interval); - while (!stopThread) - { - string ssid = ""; - string signalStrength; - Exchange::INetworkManager::WiFiSignalQuality newSignalQuality; - if (_instance != nullptr) - { - NMLOG_DEBUG("checking WiFi signal strength"); - getSignalData(ssid, newSignalQuality, signalStrength); - if(oldSignalQuality != newSignalQuality) - { - NMLOG_INFO("Notifying WiFiSignalStrengthChangedEvent %s", signalStrength.c_str()); - oldSignalQuality = newSignalQuality; - _instance->ReportWiFiSignalStrengthChange(ssid, signalStrength, newSignalQuality); - } - - if(newSignalQuality == Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED) - { - NMLOG_WARNING("WiFiSignalStrengthChanged to disconnect - WiFiSignalStrengthMonitor exiting"); - stopThread= false; - break; // Let the thread exit naturally - } - } - else - NMLOG_FATAL("NetworkManagerImplementation pointer error !"); - // Wait for the specified interval or until notified to stop - std::this_thread::sleep_for(std::chrono::seconds(interval)); - } - isRunning = false; - } - } -} diff --git a/WiFiSignalStrengthMonitor.h b/WiFiSignalStrengthMonitor.h deleted file mode 100644 index aa9d83a21..000000000 --- a/WiFiSignalStrengthMonitor.h +++ /dev/null @@ -1,49 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2023 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -#pragma once - -#include -#include -#include -#include -#include -#include "Module.h" -#include "NetworkManagerLogger.h" - -#define DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC 60 -namespace WPEFramework -{ - namespace Plugin - { - class WiFiSignalStrengthMonitor - { - public: - WiFiSignalStrengthMonitor():isRunning(false), stopThread(false) {} - ~WiFiSignalStrengthMonitor(){ NMLOG_INFO("~WiFiSignalStrengthMonitor"); } - void startWiFiSignalStrengthMonitor(int interval); - void getSignalData(std::string &ssid, Exchange::INetworkManager::WiFiSignalQuality &quality, std::string &strengthOut); - private: - std::thread monitorThread; - std::atomic stopThread; - std::atomic isRunning; - void monitorThreadFunction(int interval); - }; - } -} diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 32b6e665e..b53d62f86 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -1296,7 +1296,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) | params | object | | | params.ssid | string | The WiFi SSID Name | | params.passphrase | string | The access point password | -| params.security | integer | The security mode. See `getSupportedsecurityModes` | +| params?.security | integer | *(optional)* The security mode is decided based on the highest security mode provided by the SSID | | params?.ca_cert | string | *(optional)* The ca_cert to be used for EAP | | params?.client_cert | string | *(optional)* The client_cert to be used for EAP | | params?.private_key | string | *(optional)* The private_key to be used for EAP | @@ -1327,7 +1327,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) "params": { "ssid": "myHomeSSID", "passphrase": "password", - "security": 6, + "security": 2, "ca_cert": "...", "client_cert": "...", "private_key": "...", @@ -1549,12 +1549,12 @@ This method takes no parameters. ## *GetWiFiSignalStrength [method](#head.Methods)* -Get WiFiSignalStrength of connected SSID. The signal quality is identifed based on the signal strength. The possible states are -* 'Excellent' -* 'Good' -* 'Fair' -* 'Weak' -* 'Disconnected' +Get WiFiSignalStrength of connected SSID. The signal quality is identifed based on the Signal to Noise ratio which is calculated as SNR = rssi - noise. The possible states are +* 'Excellent' : More than 40 dBm +* 'Good' : 40 dBm to 25 dBm +* 'Fair' : 25 dBm to 18 dBm +* 'Weak' : 18 dBm to 0 dBm +* 'Disconnected' : 0 dBm . Also see: [onWiFiSignalStrengthChange](#event.onWiFiSignalStrengthChange) @@ -1569,7 +1569,7 @@ This method takes no parameters. | :-------- | :-------- | :-------- | | result | object | | | result.ssid | string | The WiFi SSID Name | -| result.strength | string | The Signal RSSI value in dBm | +| result.strength | string | Signal to Noise Ratio(SNR) in dBm | | result.quality | string | Signal strength Quality | | result.success | boolean | Whether the request succeeded | @@ -1615,10 +1615,10 @@ This method takes no parameters. | :-------- | :-------- | :-------- | | result | object | | | result.security_modes | object | The supported security modes and its associated integer value | -| result.security_modes.NONE | integer | Security mode for open network | -| result.security_modes.WPA_PSK | integer | Supports security mode WPA,WPA-PSK,WPA2-PSK, WPA3-Personal-Transition | -| result.security_modes.SAE | integer | Supports security mode WPA3-Personal | -| result.security_modes.EAP | integer | Supports security mode WPA enterpise | +| result.security_modes.NONE | integer | Security mode for open network | +| result.security_modes.WPA_PSK | integer | Supports security mode WPA,WPA-PSK,WPA2-PSK, WPA3-Personal-Transition | +| result.security_modes.SAE | integer | Supports security mode WPA3-Personal | +| result.security_modes.EAP | integer | Supports security mode WPA enterpise | | result.success | boolean | Whether the request succeeded | ### Example @@ -1864,7 +1864,7 @@ Triggered when scan completes or when scan cancelled. | params.ssids[#] | object | | | params.ssids[#].ssid | string | Discovered SSID | | params.ssids[#].security | integer | The security mode. See `getSupportedsecurityModes` | -| params.ssids[#].strength | string | The Signal RSSI value in dBm | +| params.ssids[#].strength | string | Signal to Noise Ratio(SNR) in dBm | | params.ssids[#].frequency | string | The supported frequency for this SSID in GHz | ### Example @@ -1923,7 +1923,7 @@ Triggered when WIFI connection Signal Strength get changed. | :-------- | :-------- | :-------- | | params | object | | | params.ssid | string | The WiFi SSID Name | -| params.strength | string | The Signal RSSI value in dBm | +| params.strength | string | Signal to Noise Ratio(SNR) in dBm | | params.quality | string | Signal strength Quality | ### Example diff --git a/gdbus/NetworkManagerGdbusClient.cpp b/gdbus/NetworkManagerGdbusClient.cpp index 480ae8edb..00d58aeec 100644 --- a/gdbus/NetworkManagerGdbusClient.cpp +++ b/gdbus/NetworkManagerGdbusClient.cpp @@ -27,6 +27,7 @@ #include "NetworkManagerLogger.h" #include "NetworkManagerGdbusClient.h" #include "NetworkManagerGdbusUtils.h" +#include "NetworkManagerImplementation.h" namespace WPEFramework { @@ -1835,9 +1836,10 @@ namespace WPEFramework bool NetworkManagerClient::getWiFiSignalStrength(string& ssid, string& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality) { Exchange::INetworkManager::WiFiSSIDInfo ssidInfo; - const float signalStrengthThresholdExcellent = -50.0f; - const float signalStrengthThresholdGood = -60.0f; - const float signalStrengthThresholdFair = -67.0f; + float rssi = 0.0f; + float noise = 0.0f; + float floatSignalStrength = 0.0f; + unsigned int signalStrengthOut = 0; if(!getConnectedSSID(ssidInfo)) { @@ -1846,23 +1848,42 @@ namespace WPEFramework } else { - ssid = ssidInfo.ssid; - signalStrength = ssidInfo.strength; - - float signalStrengthFloat = 0.0f; - if(!signalStrength.empty()) - signalStrengthFloat = std::stof(signalStrength.c_str()); - - if (signalStrengthFloat == 0) + ssid = ssidInfo.ssid; + if (!ssidInfo.strength.empty()) + rssi = std::stof(ssidInfo.strength.c_str()); + if (!ssidInfo.noise.empty()) + noise = std::stof(ssidInfo.noise.c_str()); + floatSignalStrength = (rssi - noise); + if (floatSignalStrength < 0) + floatSignalStrength = 0.0; + + signalStrengthOut = static_cast(floatSignalStrength); + NMLOG_INFO ("WiFiSignalStrength in dB = %u",signalStrengthOut); + + if (signalStrengthOut == 0) + { quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; - else if (signalStrengthFloat >= signalStrengthThresholdExcellent && signalStrengthFloat < 0) - quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT; - else if (signalStrengthFloat >= signalStrengthThresholdGood && signalStrengthFloat < signalStrengthThresholdExcellent) - quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_GOOD; - else if (signalStrengthFloat >= signalStrengthThresholdFair && signalStrengthFloat < signalStrengthThresholdGood) + signalStrength = "0"; + } + else if (signalStrengthOut > 0 && signalStrengthOut < NM_WIFI_SNR_THRESHOLD_FAIR) + { + quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_WEAK; + } + else if (signalStrengthOut > NM_WIFI_SNR_THRESHOLD_FAIR && signalStrengthOut < NM_WIFI_SNR_THRESHOLD_GOOD) + { quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_FAIR; + } + else if (signalStrengthOut > NM_WIFI_SNR_THRESHOLD_GOOD && signalStrengthOut < NM_WIFI_SNR_THRESHOLD_EXCELLENT) + { + quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_GOOD; + } else - quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_WEAK; + { + quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT; + } + + signalStrength = std::to_string(signalStrengthOut); + NMLOG_INFO("strength success %s dBm", signalStrength.c_str()); } diff --git a/gdbus/NetworkManagerGdbusProxy.cpp b/gdbus/NetworkManagerGdbusProxy.cpp index 2c68201b2..3eeccb1f3 100644 --- a/gdbus/NetworkManagerGdbusProxy.cpp +++ b/gdbus/NetworkManagerGdbusProxy.cpp @@ -203,10 +203,10 @@ namespace WPEFramework return rc; } - uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& signalStrength /* @out */, WiFiSignalQuality& quality /* @out */) + uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) { uint32_t rc = Core::ERROR_GENERAL; - if(_nmGdbusClient->getWiFiSignalStrength(ssid, signalStrength, quality)) + if(_nmGdbusClient->getWiFiSignalStrength(ssid, strength, quality)) rc = Core::ERROR_NONE; else NMLOG_ERROR("GetWiFiSignalStrength failed"); From 056038cd196594d03938484a13638f9df4a37ca0 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 18 Feb 2025 13:10:12 -0500 Subject: [PATCH 086/271] RDK-55734 - NetworkManager Thunder Plugin - Report WiFi SNR (#95) * RDK-55734 - NetworkManager Thunder Plugin - Report WiFi SNR Reason for change: Modified the GetWifiSignalStrength to read from the wpa_cli command and extract the values out of it Test Procedure: Test and verified Risks: Medium Priority: P1 Signed-off-by: Gururaaja ESR --- NetworkManagerGnomeProxy.cpp | 86 +---------------------------- NetworkManagerImplementation.cpp | 87 +++++++++++++++++++++++++++++- NetworkManagerImplementation.h | 2 +- NetworkManagerRDKProxy.cpp | 2 + gdbus/NetworkManagerGdbusProxy.cpp | 2 + 5 files changed, 93 insertions(+), 86 deletions(-) diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index a56980c79..fc5c76009 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -24,9 +24,6 @@ #include #include -#define rssid_command "wpa_cli signal_poll" -#define ssid_command "wpa_cli status" - static NMClient *client = NULL; using namespace WPEFramework; using namespace WPEFramework::Plugin; @@ -661,88 +658,9 @@ namespace WPEFramework return rc; } +#if 0 uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) { - uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - uint16_t strengthOut = 0; - - std::string key, value; - std::string noiseStr = ""; - std::string rssiStr = ""; - uint16_t rssi = 0; - uint16_t noise = 0; - char buff[512] = {'\0'}; - - FILE *fp = NULL; - fp = popen(rssid_command, "r"); - if (!fp) - { - NMLOG_ERROR("Failed in getting output from command %s",rssid_command); - return Core::ERROR_RPC_CALL_FAILED; - } - while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) - { - std::istringstream mystream(buff); - if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) - if (key == "RSSI") { - rssiStr = value; - } - else if (key == "NOISE") { - noiseStr = value; - } - if (!rssiStr.empty() && !noiseStr.empty()) - break; - } - pclose(fp); - fp = popen(ssid_command, "r"); - if (!fp) - { - NMLOG_ERROR("Failed in getting output from command %s",ssid_command); - return Core::ERROR_RPC_CALL_FAILED; - } - while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) - { - std::istringstream mystream(buff); - if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) - if (key == "ssid") { - ssid = value; - break; - } - } - pclose(fp); - rssi = std::stoi(rssiStr); - noise = std::stoi(noiseStr); - strengthOut = (rssi - noise); - NMLOG_INFO ("WiFiSignalStrength in dB = %u",strengthOut); - - if (strengthOut == 0) - { - quality = WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; - strength = "0"; - } - else if (strengthOut > 0 && strengthOut < NM_WIFI_SNR_THRESHOLD_FAIR) - { - quality = WiFiSignalQuality::WIFI_SIGNAL_WEAK; - } - else if (strengthOut > NM_WIFI_SNR_THRESHOLD_FAIR && strengthOut < NM_WIFI_SNR_THRESHOLD_GOOD) - { - quality = WiFiSignalQuality::WIFI_SIGNAL_FAIR; - } - else if (strengthOut > NM_WIFI_SNR_THRESHOLD_GOOD && strengthOut < NM_WIFI_SNR_THRESHOLD_EXCELLENT) - { - quality = WiFiSignalQuality::WIFI_SIGNAL_GOOD; - } - else - { - quality = WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT; - } - - strength = std::to_string(strengthOut); - - NMLOG_INFO ("GetWiFiSignalStrength success"); - - rc = Core::ERROR_NONE; -#if 0 float rssi = 0.0f; float noise = 0.0f; float floatSignalStrength = 0.0f; @@ -789,9 +707,9 @@ namespace WPEFramework rc = Core::ERROR_NONE; } -#endif return rc; } +#endif uint32_t NetworkManagerImplementation::GetWifiState(WiFiState &state) { diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 91cf82d04..154e15da5 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -26,6 +26,8 @@ using namespace WPEFramework::Plugin; using namespace NetworkManagerLogger; #define CIDR_NETMASK_IP_LEN 32 +#define RSSID_COMMAND "wpa_cli signal_poll" +#define SSID_COMMAND "wpa_cli status" namespace WPEFramework { @@ -695,6 +697,89 @@ namespace WPEFramework m_isRunning = false; } + /* The below implementation of GetWiFiSignalStrength is a temporary mitigation. Need to be revisited */ + uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) + { + uint32_t rc = Core::ERROR_RPC_CALL_FAILED; + uint16_t strengthOut = 0; + + std::string key, value; + std::string noiseStr = ""; + std::string rssiStr = ""; + uint16_t rssi = 0; + uint16_t noise = 0; + char buff[512] = {'\0'}; + + FILE *fp = NULL; + fp = popen(RSSID_COMMAND, "r"); + if (!fp) + { + NMLOG_ERROR("Failed in getting output from command %s",RSSID_COMMAND); + return Core::ERROR_RPC_CALL_FAILED; + } + while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) + { + std::istringstream mystream(buff); + if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) + if (key == "RSSI") { + rssiStr = value; + } + else if (key == "NOISE") { + noiseStr = value; + } + if (!rssiStr.empty() && !noiseStr.empty()) + break; + } + pclose(fp); + fp = popen(SSID_COMMAND, "r"); + if (!fp) + { + NMLOG_ERROR("Failed in getting output from command %s",SSID_COMMAND); return Core::ERROR_RPC_CALL_FAILED; + } + while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) { + std::istringstream mystream(buff); + if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) + if (key == "ssid") { + ssid = value; + break; + } + } + pclose(fp); + rssi = std::stoi(rssiStr); + noise = std::stoi(noiseStr); + strengthOut = (rssi - noise); + NMLOG_INFO ("WiFiSignalStrength in dB = %u",strengthOut); + if (strengthOut == 0) + { + quality = WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; + strength = "0"; + } + else if (strengthOut > 0 && strengthOut < NM_WIFI_SNR_THRESHOLD_FAIR) + { + quality = WiFiSignalQuality::WIFI_SIGNAL_WEAK; + } + else if (strengthOut > NM_WIFI_SNR_THRESHOLD_FAIR && strengthOut < NM_WIFI_SNR_THRESHOLD_GOOD) + { + quality = WiFiSignalQuality::WIFI_SIGNAL_FAIR; + } + else if (strengthOut > NM_WIFI_SNR_THRESHOLD_GOOD && strengthOut < NM_WIFI_SNR_THRESHOLD_EXCELLENT) + { + quality = WiFiSignalQuality::WIFI_SIGNAL_GOOD; + } + else + { + quality = WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT; + } + + strength = std::to_string(strengthOut); + + NMLOG_INFO ("GetWiFiSignalStrength success"); + + rc = Core::ERROR_NONE; + + return rc; + } + void NetworkManagerImplementation::monitorThreadFunction(int interval) { static Exchange::INetworkManager::WiFiSignalQuality oldSignalQuality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; @@ -706,7 +791,7 @@ namespace WPEFramework Exchange::INetworkManager::WiFiSignalQuality newSignalQuality; NMLOG_DEBUG("checking WiFi signal strength"); - NetworkManagerImplementation::GetWiFiSignalStrength(ssid, strength, newSignalQuality); + GetWiFiSignalStrength(ssid, strength, newSignalQuality); if (oldSignalQuality != newSignalQuality) { NMLOG_INFO("Notifying WiFiSignalStrengthChangedEvent %s", strength.c_str()); diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 85b0be825..9c725b6bd 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -34,7 +34,7 @@ using namespace std; #include "NetworkManagerConnectivity.h" #include "NetworkManagerStunClient.h" -#define DEFAULT_NOISE -180 +#define DEFAULT_NOISE -180 #define DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC 60 #define NM_WIFI_SNR_THRESHOLD_EXCELLENT 40 diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index ab044b413..fdf103ed7 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -1375,6 +1375,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { return rc; } +#if 0 uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) { LOG_ENTRY_FUNCTION(); @@ -1431,6 +1432,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { } return rc; } +#endif uint32_t NetworkManagerImplementation::StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) { diff --git a/gdbus/NetworkManagerGdbusProxy.cpp b/gdbus/NetworkManagerGdbusProxy.cpp index 3eeccb1f3..1d0195034 100644 --- a/gdbus/NetworkManagerGdbusProxy.cpp +++ b/gdbus/NetworkManagerGdbusProxy.cpp @@ -203,6 +203,7 @@ namespace WPEFramework return rc; } +#if 0 uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) { uint32_t rc = Core::ERROR_GENERAL; @@ -212,6 +213,7 @@ namespace WPEFramework NMLOG_ERROR("GetWiFiSignalStrength failed"); return rc; } +#endif uint32_t NetworkManagerImplementation::GetWifiState(WiFiState &state) { From ac1892876b769766e24ecc52f17320880a1beb78 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 18 Feb 2025 16:15:39 -0500 Subject: [PATCH 087/271] RDKEMW-1849 - SetPrimaryInterface method returns failure (#97) * RDKEMW-1849 - SetPrimaryInterface method returns failure Reason for change: Modified the SetPrimaryInterface to return proper value in the success scenario Test Procedure: Test and verified Risks: Medium Priority: P1 Signed-off-by: Gururaaja ESR --- NetworkManagerGnomeProxy.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index fc5c76009..ad6ac062a 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -187,6 +187,8 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::SetPrimaryInterface (const string& interface/* @in */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; + gboolean result; + GError *error = NULL; std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); if(client == nullptr) @@ -234,7 +236,27 @@ namespace WPEFramework NULL); const char *uuid = nm_connection_get_uuid(conn); remoteConnection = nm_client_get_connection_by_uuid(client, uuid); - nm_remote_connection_commit_changes(remoteConnection, false, NULL, NULL); + if (!remoteConnection) + { + NMLOG_ERROR("Failed to get remote connection"); + return rc; + } + result = nm_remote_connection_commit_changes(remoteConnection, false, NULL, &error); + if (result) + rc = Core::ERROR_NONE; + else + { + if (error) + { + NMLOG_ERROR("Failed to commit changes: %s", error->message); + g_error_free(error); + } + else + { + NMLOG_ERROR("Failed to commit changes: unknown error"); + } + rc = Core::ERROR_GENERAL; + } return rc; } From 965dfaa986f21756898e4bf67d6233494cecbfe0 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Wed, 19 Feb 2025 18:45:13 +0530 Subject: [PATCH 088/271] RDKEMW-1848: Fail to connect to open wifi endpoints (#98) --- NetworkManagerGnomeWIFI.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index de7589e2e..e9d4bcbe3 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -525,11 +525,7 @@ namespace WPEFramework } case Exchange::INetworkManager::WIFI_SECURITY_NONE: { - NMLOG_INFO("key-mgmt: %s", "none"); - sSecurity = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); - nm_connection_add_setting(m_connection, NM_SETTING(sSecurity)); - g_object_set(G_OBJECT(sSecurity), NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,"none", NULL); - NMLOG_WARNING("open wifi network configuration"); + NMLOG_WARNING("open wifi network configuration key-mgmt: none"); break; } default: From 26e977470fbe810e48ca0eabf42c32e3cb2211da Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Thu, 20 Feb 2025 15:56:45 -0500 Subject: [PATCH 089/271] RDK-56182 : Updated `GetWiFiSignalQuality` to include SNR (#99) Reason for change: 1. Updated `GetWiFiSignalQuality` method to include SNR & Noise 2. Updated `onWiFiSignalQualityChange` event to include SNR & Noise. 3. Updated the documentation 4. Added logging for the instantiation and exit Test Procedure: Verify the APIs Risks: Medium Signed-off-by: kamirt573_comcast --- INetworkManager.h | 4 +- LegacyPlugin_WiFiManagerAPIs.cpp | 6 +- LegacyPlugin_WiFiManagerAPIs.h | 2 +- NetworkManager.cpp | 24 +++-- NetworkManager.h | 8 +- NetworkManager.json | 79 ++++++++------ NetworkManagerGnomeProxy.cpp | 6 +- NetworkManagerGnomeWIFI.cpp | 4 +- NetworkManagerImplementation.cpp | 102 +++++++++++------- NetworkManagerImplementation.h | 8 +- NetworkManagerJsonRpc.cpp | 26 +++-- NetworkManagerRDKProxy.cpp | 20 ++-- NetworkManagerStunClient.cpp | 4 +- Tests/raspberrypi/NetworkManagerGdbusTest.cpp | 6 +- .../test_WiFiSignalStrengthMonitor.cpp | 13 ++- docs/NetworkManagerPlugin.md | 92 ++++++++-------- gdbus/NetworkManagerGdbusClient.cpp | 4 +- gdbus/NetworkManagerGdbusClient.h | 2 +- gdbus/NetworkManagerGdbusProxy.cpp | 6 +- gdbus/NetworkManagerGdbusUtils.cpp | 3 +- 20 files changed, 244 insertions(+), 175 deletions(-) diff --git a/INetworkManager.h b/INetworkManager.h index fa3663469..b491dd7db 100644 --- a/INetworkManager.h +++ b/INetworkManager.h @@ -252,7 +252,7 @@ namespace WPEFramework virtual uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& pin /* @in */) = 0; virtual uint32_t StopWPS(void) = 0; virtual uint32_t GetWifiState(WiFiState &state /* @out */) = 0; - virtual uint32_t GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) = 0; + virtual uint32_t GetWiFiSignalQuality(string& ssid /* @out */, string& strength /* @out */, string& noise /* @out */, string& snr /* @out */, WiFiSignalQuality& quality /* @out */) = 0; virtual uint32_t GetSupportedSecurityModes(ISecurityModeIterator*& modes/* @out */) const = 0; /* @brief Set the network manager plugin log level */ @@ -276,7 +276,7 @@ namespace WPEFramework // WiFi Notifications that other processes can subscribe to virtual void onAvailableSSIDs(const string jsonOfScanResults /* @in */) = 0; virtual void onWiFiStateChange(const WiFiState state /* @in */) = 0; - virtual void onWiFiSignalStrengthChange(const string ssid /* @in */, const string strength /* @in */, const WiFiSignalQuality quality /* @in */) = 0; + virtual void onWiFiSignalQualityChange(const string ssid /* @in */, const string strength /* @in */, const string noise /* @in */, const string snr /* @in */, const WiFiSignalQuality quality /* @in */) = 0; }; // Allow other processes to register/unregister from our notifications diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index b80eb0e1e..f1aac187d 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -804,11 +804,11 @@ namespace WPEFramework if (!m_subsWiFiStrengthChange) { - errCode = m_networkmanager->Subscribe(5000, _T("onWiFiSignalStrengthChange"), &WiFiManager::onWiFiSignalStrengthChange); + errCode = m_networkmanager->Subscribe(5000, _T("onWiFiSignalQualityChange"), &WiFiManager::onWiFiSignalQualityChange); if (Core::ERROR_NONE == errCode) m_subsWiFiStrengthChange = true; else - NMLOG_ERROR("Subscribe to onWiFiSignalStrengthChange failed, errCode: %u", errCode); + NMLOG_ERROR("Subscribe to onWiFiSignalQualityChange failed, errCode: %u", errCode); } } else @@ -926,7 +926,7 @@ namespace WPEFramework return; } - void WiFiManager::onWiFiSignalStrengthChange(const JsonObject& parameters) + void WiFiManager::onWiFiSignalQualityChange(const JsonObject& parameters) { JsonObject legacyParams; legacyParams["signalStrength"] = parameters["strength"]; diff --git a/LegacyPlugin_WiFiManagerAPIs.h b/LegacyPlugin_WiFiManagerAPIs.h index 8227fce00..c6c594e9d 100644 --- a/LegacyPlugin_WiFiManagerAPIs.h +++ b/LegacyPlugin_WiFiManagerAPIs.h @@ -66,7 +66,7 @@ namespace WPEFramework { //Begin events static void onWiFiStateChange(const JsonObject& parameters); static void onAvailableSSIDs(const JsonObject& parameters); - static void onWiFiSignalStrengthChange(const JsonObject& parameters); + static void onWiFiSignalQualityChange(const JsonObject& parameters); //End events diff --git a/NetworkManager.cpp b/NetworkManager.cpp index 870dcb87d..18e636750 100644 --- a/NetworkManager.cpp +++ b/NetworkManager.cpp @@ -66,7 +66,6 @@ namespace WPEFramework // Syslog Startup messages are always printed by default SYSLOG(Logging::Startup, (_T("Initializing NetworkManager"))); - SYSLOG(Logging::Startup, (_T("Initialize running in process %d"), Core::ProcessInfo().Id())); NetworkManagerLogger::Init(); // Register the Connection::Notification first. Do this before we start our actual plugin // in case something goes wrong or is disconnected - this way we know we're at least registered @@ -85,9 +84,10 @@ namespace WPEFramework // Still running inside the main WPEFramework process - the child process will have now been spawned and registered if necessary if (_networkManager != nullptr) { + SYSLOG(Logging::Startup, (_T("Configuring NetworkManager"))); if (_networkManager->Configure(service) != Core::ERROR_NONE) { - SYSLOG(Logging::Startup, (_T("Configuring NetworkManager"))); + SYSLOG(Logging::Shutdown, (_T("NetworkManager failed to configure"))); message = _T("NetworkManager failed to configure"); } @@ -97,18 +97,22 @@ namespace WPEFramework NetworkManagerLogger::SetLevel(static_cast (_loglevel)); // Register Notifications + SYSLOG(Logging::Startup, (_T("Registering Notification to NetworkManager"))); _networkManager->Register(&_notification); // Register all custom JSON-RPC methods + SYSLOG(Logging::Startup, (_T("Registering JSONRPC Methods"))); RegisterAllMethods(); // Get IPlugin interface for this plugin + SYSLOG(Logging::Startup, (_T("Retrieve ComRPC Interface for NetworkManager"))); _networkManagerImpl = _networkManager->QueryInterface(); } else { // Something went wrong, clean up + SYSLOG(Logging::Shutdown, (_T("NetworkManager out-of-process creation failed"))); TRACE(Trace::Error, (_T("Failed to initialize NetworkManager"))); _service->Unregister(&_notification); _service = nullptr; @@ -131,28 +135,34 @@ namespace WPEFramework ASSERT(_service == service); ASSERT(_networkManager != nullptr); - TRACE(Trace::Information, (_T("Deinitializing NetworkManager"))); - TRACE(Trace::Information, (_T("Deinitialize running in process %d"), Core::ProcessInfo().Id())); - + SYSLOG(Logging::Shutdown, (_T("Deinitializing NetworkManager"))); if (_networkManager != nullptr) { - // TODO:: Work out exactly what triggers the shutdown of the out-of-process host + SYSLOG(Logging::Shutdown, (_T("Unregister Thunder Notifications for NetworkManager"))); _service->Unregister(&_notification); + + SYSLOG(Logging::Shutdown, (_T("Unregister Event Notifications of NetworkManager"))); _networkManager->Unregister(&_notification); // Unregister all our JSON-RPC methods + SYSLOG(Logging::Shutdown, (_T("Unregister JSON RPC Methods of NetworkManager"))); UnregisterAllMethods(); // Release the IPlugin if(_networkManagerImpl) { + SYSLOG(Logging::Shutdown, (_T("Release of IPlugin of NetworkManager"))); _networkManagerImpl->Release(); _networkManagerImpl = nullptr; } RPC::IRemoteConnection* connection = service->RemoteConnection(_connectionId); + + SYSLOG(Logging::Shutdown, (_T("Release of COMRPC Interface of NetworkManager"))); _networkManager->Release(); - if (connection != nullptr) { + if (connection != nullptr) + { + SYSLOG(Logging::Shutdown, (_T("Release of Thunder COMRPC Connection of NetworkManager"))); // Lets trigger the cleanup sequence for // out-of-process code. Which will guard // that unwilling processes, get shot if diff --git a/NetworkManager.h b/NetworkManager.h index d4830dd07..1d768bfee 100644 --- a/NetworkManager.h +++ b/NetworkManager.h @@ -94,9 +94,9 @@ namespace WPEFramework _parent.onWiFiStateChange(state); } - void onWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) override + void onWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality) override { - _parent.onWiFiSignalStrengthChange(ssid, strength, quality); + _parent.onWiFiSignalQualityChange(ssid, strength, noise, snr, quality); } // The activated/deactived methods are part of the RPC::IRemoteConnection::INotification @@ -261,7 +261,7 @@ namespace WPEFramework uint32_t StartWPS(const JsonObject& parameters, JsonObject& response); uint32_t StopWPS(const JsonObject& parameters, JsonObject& response); uint32_t GetWifiState(const JsonObject& parameters, JsonObject& response); - uint32_t GetWiFiSignalStrength(const JsonObject& parameters, JsonObject& response); + uint32_t GetWiFiSignalQuality(const JsonObject& parameters, JsonObject& response); uint32_t GetSupportedSecurityModes(const JsonObject& parameters, JsonObject& response); void onInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface); @@ -270,7 +270,7 @@ namespace WPEFramework void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState); void onAvailableSSIDs(const string jsonOfScanResults); void onWiFiStateChange(const Exchange::INetworkManager::WiFiState state); - void onWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality); + void onWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality); private: uint32_t _connectionId; diff --git a/NetworkManager.json b/NetworkManager.json index 5ac07a8f3..c7826d91c 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -123,24 +123,34 @@ "example": "password" }, "security":{ - "summary": "The security mode. See `getSupportedsecurityModes`.", + "summary": "The security mode. See `GetSupportedSecurityModes`.", "type": "integer", - "example": 6 + "example": 2 }, "strength":{ + "summary": "The WiFi Signal RSSI value in dBm", + "type": "string", + "example": "-32" + }, + "noise":{ + "summary": "The WiFi Signal Noise detected in dBm", + "type": "string", + "example": "-106" + }, + "snr":{ "summary": "Signal to Noise Ratio(SNR) in dBm", "type": "string", - "example": "-27.000000" + "example": "74" }, "quality":{ - "summary": "Signal strength Quality", + "summary": "WiFi Quality based on Signal to Noise Ratio (SNR)", "type": "string", "example": "Excellent" }, "frequency":{ "summary": "The supported frequency for this SSID in GHz", "type": "string", - "example": "2.442000" + "example": "2.4420" }, "errors": { "summary": "Error string of scan failure", @@ -1000,7 +1010,7 @@ } }, "WiFiConnect":{ - "summary": "Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. When called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`.", + "summary": "Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. The security mode is decided based on the highest security mode provided by the SSID. Also when called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`.", "events":{ "onWiFiStateChange" : "Triggered when Wifi state changes to CONNECTING, CONNECTED ." }, @@ -1013,11 +1023,6 @@ "passphrase": { "$ref": "#/definitions/passphrase" }, - "security": { - "summary": "The security mode is decided based on the highest security mode provided by the SSID", - "type": "integer", - "example": 2 - }, "ca_cert": { "summary": "The ca_cert to be used for EAP", "type": "string", @@ -1119,12 +1124,10 @@ "security":{ "summary": "The security mode. See the `connect` method", "type": "string", - "example": "5" + "example": "2" }, "strength": { - "summary": "The Signal RSSI value in dBm", - "type": "string", - "example": "-27.000000" + "$ref": "#/definitions/strength" }, "frequency": { "$ref": "#/definitions/frequency" @@ -1132,12 +1135,10 @@ "rate":{ "summary": "The physical data rate in Mbps", "type": "string", - "example": "144.000000" + "example": "144" }, "noise":{ - "summary": "The average noise strength in dBm", - "type": "string", - "example": "-121.000000" + "$ref": "#/definitions/noise" }, "success":{ "$ref": "#/definitions/success" @@ -1215,10 +1216,10 @@ ] } }, - "GetWiFiSignalStrength":{ - "summary": "Get WiFiSignalStrength of connected SSID. The signal quality is identifed based on the Signal to Noise ratio which is calculated as SNR = rssi - noise. The possible states are\n* 'Excellent' : More than 40 dBm\n* 'Good' : 40 dBm to 25 dBm\n* 'Fair' : 25 dBm to 18 dBm\n* 'Weak' : 18 dBm to 0 dBm\n* 'Disconnected' : 0 dBm\n", + "GetWiFiSignalQuality":{ + "summary": "Get WiFi signal quality of currently connected SSID. The signal quality is identifed based on the Signal to Noise ratio which is calculated as SNR = rssi - noise. The possible states are\n* 'Excellent' : More than 40 dBm\n* 'Good' : 40 dBm to 25 dBm\n* 'Fair' : 25 dBm to 18 dBm\n* 'Weak' : 18 dBm to 0 dBm\n* 'Disconnected' : 0 dBm\n", "events":{ - "onWiFiSignalStrengthChange" : "Triggered when Wifi signal strength switches between Excellent, Good, Fair, Weak." + "onWiFiSignalQualityChange" : "Triggered when Wifi signal strength switches between Excellent, Good, Fair, Weak." }, "result": { "type": "object", @@ -1226,11 +1227,17 @@ "ssid": { "$ref": "#/definitions/ssid" }, + "quality":{ + "$ref": "#/definitions/quality" + }, + "snr": { + "$ref": "#/definitions/snr" + }, "strength": { "$ref": "#/definitions/strength" }, - "quality":{ - "$ref": "#/definitions/quality" + "noise": { + "$ref": "#/definitions/noise" }, "success":{ "$ref": "#/definitions/success" @@ -1238,13 +1245,15 @@ }, "required": [ "ssid", - "strength", "quality", + "snr", + "strength", + "noise", "success" ] } }, - "GetSupportedsecurityModes":{ + "GetSupportedSecurityModes":{ "summary": "Returns the Wifi security modes that the device supports.", "result": { "type": "object", @@ -1491,25 +1500,33 @@ ] } }, - "onWiFiSignalStrengthChange":{ - "summary": "Triggered when WIFI connection Signal Strength get changed.", + "onWiFiSignalQualityChange":{ + "summary": "Triggered when WIFI Signal quality changed which is decided based on SNR value which is defined in `GetWiFiSignalQuality`", "params": { "type": "object", "properties": { "ssid":{ "$ref": "#/definitions/ssid" }, + "quality":{ + "$ref": "#/definitions/quality" + }, + "snr":{ + "$ref": "#/definitions/snr" + }, "strength":{ "$ref": "#/definitions/strength" }, - "quality":{ - "$ref": "#/definitions/quality" + "noise":{ + "$ref": "#/definitions/noise" } }, "required": [ "ssid", + "quality", + "snr", "strength", - "quality" + "noise" ] } } diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index ad6ac062a..8b72b933a 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -681,7 +681,7 @@ namespace WPEFramework } #if 0 - uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) + uint32_t NetworkManagerImplementation::GetWiFiSignalQuality(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) { float rssi = 0.0f; float noise = 0.0f; @@ -699,7 +699,7 @@ namespace WPEFramework floatSignalStrength = 0.0; strengthOut = static_cast(floatSignalStrength); - NMLOG_INFO ("WiFiSignalStrength in dB = %u",strengthOut); + NMLOG_INFO ("WiFiSignalQuality in dB = %u",strengthOut); if (strengthOut == 0) { @@ -725,7 +725,7 @@ namespace WPEFramework signalStrength = std::to_string(strengthOut); - NMLOG_INFO ("GetWiFiSignalStrength success"); + NMLOG_INFO ("GetWiFiSignalQuality success"); rc = Core::ERROR_NONE; } diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index e9d4bcbe3..a2b17ee54 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -217,7 +217,9 @@ namespace WPEFramework } wifiInfo.bssid = (hwaddr != nullptr) ? hwaddr : "-----"; - wifiInfo.frequency = std::to_string((double)freq/1000); + std::string freqStr = std::to_string((double)freq/1000); + wifiInfo.frequency = freqStr.substr(0, 5); + wifiInfo.rate = std::to_string(bitrate); if(noise <= 0 || noise >= DEFAULT_NOISE) wifiInfo.noise = std::to_string(noise); diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 154e15da5..f4fbd2220 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -50,18 +50,17 @@ namespace WPEFramework /* Initialize Network Manager */ NetworkManagerLogger::Init(); - LOG_ENTRY_FUNCTION(); + NMLOG_INFO((_T("NetworkManager Out-Of-Process Instantiation; SHA:" _T(EXPAND_AND_QUOTE(PLUGIN_BUILD_REFERENCE))))); } NetworkManagerImplementation::~NetworkManagerImplementation() { - LOG_ENTRY_FUNCTION(); - + NMLOG_INFO("NetworkManager Out-Of-Process Shutdown/Cleanup"); if(m_registrationThread.joinable()) { m_registrationThread.join(); } - stopWiFiSignalStrengthMonitor(); + stopWiFiSignalQualityMonitor(); } /** @@ -532,7 +531,7 @@ namespace WPEFramework double frequencyValue = std::stod(frequency); - //Debug to print log + //Debug to print log NMLOG_DEBUG("Processing Frequency after double conversion: %lf\n", frequencyValue); bool ssidMatches = scanForSsidsSet.empty() || scanForSsidsSet.find(ssid) != scanForSsidsSet.end(); @@ -672,10 +671,10 @@ namespace WPEFramework _notificationLock.Unlock(); } - void NetworkManagerImplementation::startWiFiSignalStrengthMonitor(int interval) + void NetworkManagerImplementation::startWiFiSignalQualityMonitor(int interval) { if (m_isRunning) { - NMLOG_INFO("WiFiSignalStrengthMonitor Thread is already running."); + NMLOG_INFO("WiFiSignalQualityMonitor Thread is already running."); return; } m_isRunning = true; @@ -683,7 +682,7 @@ namespace WPEFramework m_monitorThread = std::thread(&NetworkManagerImplementation::monitorThreadFunction, this, interval); } - void NetworkManagerImplementation::stopWiFiSignalStrengthMonitor() + void NetworkManagerImplementation::stopWiFiSignalQualityMonitor() { if (!m_isRunning) { return; // No thread to stop @@ -697,20 +696,22 @@ namespace WPEFramework m_isRunning = false; } - /* The below implementation of GetWiFiSignalStrength is a temporary mitigation. Need to be revisited */ - uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) + /* The below implementation of GetWiFiSignalQuality is a temporary mitigation. Need to be revisited */ + uint32_t NetworkManagerImplementation::GetWiFiSignalQuality(string& ssid /* @out */, string& strength /* @out */, string& noise /* @out */, string& snr /* @out */, WiFiSignalQuality& quality /* @out */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - uint16_t strengthOut = 0; + int16_t strengthOut = 0; std::string key, value; - std::string noiseStr = ""; - std::string rssiStr = ""; - uint16_t rssi = 0; - uint16_t noise = 0; + string noiseStr{}; + string rssiStr{}; + int16_t readRSSI = 0; + int16_t readNoise = 0; char buff[512] = {'\0'}; FILE *fp = NULL; + + /* Noise n RSSI */ fp = popen(RSSID_COMMAND, "r"); if (!fp) { @@ -731,10 +732,13 @@ namespace WPEFramework break; } pclose(fp); + + /* SSID */ fp = popen(SSID_COMMAND, "r"); if (!fp) { - NMLOG_ERROR("Failed in getting output from command %s",SSID_COMMAND); return Core::ERROR_RPC_CALL_FAILED; + NMLOG_ERROR("Failed in getting output from command %s",SSID_COMMAND); + return Core::ERROR_RPC_CALL_FAILED; } while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) { std::istringstream mystream(buff); @@ -745,11 +749,34 @@ namespace WPEFramework } } pclose(fp); - rssi = std::stoi(rssiStr); - noise = std::stoi(noiseStr); - strengthOut = (rssi - noise); - NMLOG_INFO ("WiFiSignalStrength in dB = %u",strengthOut); - if (strengthOut == 0) + + /* NOTE: The std::stoi() will throw exception if the string input is empty; so set to 0 */ + if (rssiStr.empty()) + rssiStr = "0"; + if (noiseStr.empty()) + noiseStr= "0"; + + readRSSI = std::stoi(rssiStr); + readNoise = std::stoi(noiseStr); + + /* Check the Noise is within range */ + if(!(readNoise <= 0 || readNoise >= DEFAULT_NOISE)) + { + NMLOG_WARNING("Received Noise (%d) from wifi driver is not valid", readNoise); + readNoise = 0; + } + + /* Calculate the SNR */ + strengthOut = readRSSI - readNoise; + + /* Update the results */ + strength = rssiStr; + noise = noiseStr; + snr = std::to_string(strengthOut); + + NMLOG_INFO ("RSSI: %d dBm; Noise: %d dBm; SNR: %d dBm", readRSSI, readNoise, strengthOut); + + if (strengthOut == 0) { quality = WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; strength = "0"; @@ -771,10 +798,7 @@ namespace WPEFramework quality = WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT; } - strength = std::to_string(strengthOut); - - NMLOG_INFO ("GetWiFiSignalStrength success"); - + NMLOG_INFO ("GetWiFiSignalQuality success"); rc = Core::ERROR_NONE; return rc; @@ -783,24 +807,26 @@ namespace WPEFramework void NetworkManagerImplementation::monitorThreadFunction(int interval) { static Exchange::INetworkManager::WiFiSignalQuality oldSignalQuality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; - NMLOG_INFO("WiFiSignalStrengthMonitor thread started ! (%d)", interval); + NMLOG_INFO("WiFiSignalQualityMonitor thread started ! (%d)", interval); while (!m_stopThread) { - std::string ssid; - std::string strength; + std::string ssid{}; + std::string strength{}; + std::string noise{}; + std::string snr{}; std::unique_lock lock(m_condVariableMutex); Exchange::INetworkManager::WiFiSignalQuality newSignalQuality; NMLOG_DEBUG("checking WiFi signal strength"); - GetWiFiSignalStrength(ssid, strength, newSignalQuality); + GetWiFiSignalQuality(ssid, strength, noise, snr, newSignalQuality); if (oldSignalQuality != newSignalQuality) { - NMLOG_INFO("Notifying WiFiSignalStrengthChangedEvent %s", strength.c_str()); + NMLOG_INFO("Notifying WiFiSignalQualityChangedEvent %s", strength.c_str()); oldSignalQuality = newSignalQuality; - NetworkManagerImplementation::ReportWiFiSignalStrengthChange(ssid, strength, newSignalQuality); + NetworkManagerImplementation::ReportWiFiSignalQualityChange(ssid, strength, noise, snr, newSignalQuality); } if (newSignalQuality == Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED) { - NMLOG_WARNING("WiFiSignalStrengthChanged to disconnect - WiFiSignalStrengthMonitor exiting"); + NMLOG_WARNING("WiFiSignalQualityChanged to disconnect - WiFiSignalQualityMonitor exiting"); m_stopThread = true; // Signal thread to stop break; // Exit the loop } @@ -808,7 +834,7 @@ namespace WPEFramework // Wait for the specified interval or until notified to stop if (m_condVariable.wait_for(lock, std::chrono::seconds(interval), [this](){ return m_stopThread == true; })) { - NMLOG_INFO("WiFiSignalStrengthMonitor received stop signal or timed out"); + NMLOG_INFO("WiFiSignalQualityMonitor received stop signal or timed out"); } } m_isRunning = false; @@ -822,7 +848,7 @@ namespace WPEFramework m_wlanConnected = true; if (!m_monitoringStarted) { - startWiFiSignalStrengthMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC); + startWiFiSignalQualityMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC); m_monitoringStarted = true; } } @@ -830,7 +856,7 @@ namespace WPEFramework { if (m_monitoringStarted) { - stopWiFiSignalStrengthMonitor(); + stopWiFiSignalQualityMonitor(); m_monitoringStarted = false; } m_wlanConnected = false; /* Any other state is considered as WiFi not connected. */ @@ -844,12 +870,12 @@ namespace WPEFramework _notificationLock.Unlock(); } - void NetworkManagerImplementation::ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) + void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality) { _notificationLock.Lock(); - NMLOG_INFO("Posting onWiFiSignalStrengthChange %s", strength.c_str()); + NMLOG_INFO("Posting onWiFiSignalQualityChange %s", strength.c_str()); for (const auto callback : _notificationCallbacks) { - callback->onWiFiSignalStrengthChange(ssid, strength, quality); + callback->onWiFiSignalQualityChange(ssid, strength, noise, snr, quality); } _notificationLock.Unlock(); } diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 9c725b6bd..8a9ff2025 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -215,7 +215,7 @@ namespace WPEFramework uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) override; uint32_t StopWPS(void) override; uint32_t GetWifiState(WiFiState &state) override; - uint32_t GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) override; + uint32_t GetWiFiSignalQuality(string& ssid /* @out */, string& strength /* @out */, string& noise /* @out */, string& snr /* @out */, WiFiSignalQuality& quality /* @out */) override; uint32_t SetStunEndpoint (string const endpoint /* @in */, const uint32_t port /* @in */, const uint32_t bindTimeout /* @in */, const uint32_t cacheTimeout /* @in */) override; uint32_t GetStunEndpoint (string &endpoint /* @out */, uint32_t& port /* @out */, uint32_t& bindTimeout /* @out */, uint32_t& cacheTimeout /* @out */) const override; @@ -255,7 +255,7 @@ namespace WPEFramework void ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState); void ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults); void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); - void ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality); + void ReportWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality); private: void platform_init(void); @@ -263,8 +263,8 @@ namespace WPEFramework void executeExternally(NetworkEvents event, const string commandToExecute, string& response); void threadEventRegistration(void); void filterScanResults(JsonArray &ssids); - void startWiFiSignalStrengthMonitor(int interval); - void stopWiFiSignalStrengthMonitor(); + void startWiFiSignalQualityMonitor(int interval); + void stopWiFiSignalQualityMonitor(); void monitorThreadFunction(int interval); private: diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 7fdccb401..b415ffed4 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -81,7 +81,7 @@ namespace WPEFramework Register("StartWPS", &NetworkManager::StartWPS, this); Register("StopWPS", &NetworkManager::StopWPS, this); Register("GetWifiState", &NetworkManager::GetWifiState, this); - Register("GetWiFiSignalStrength", &NetworkManager::GetWiFiSignalStrength, this); + Register("GetWiFiSignalQuality", &NetworkManager::GetWiFiSignalQuality, this); Register("GetSupportedSecurityModes", &NetworkManager::GetSupportedSecurityModes, this); } @@ -118,7 +118,7 @@ namespace WPEFramework Unregister("StartWPS"); Unregister("StopWPS"); Unregister("GetWifiState"); - Unregister("GetWiFiSignalStrength"); + Unregister("GetWiFiSignalQuality"); Unregister("GetSupportedSecurityModes"); } @@ -885,25 +885,29 @@ namespace WPEFramework returnJson(rc); } - uint32_t NetworkManager::GetWiFiSignalStrength(const JsonObject& parameters, JsonObject& response) + uint32_t NetworkManager::GetWiFiSignalQuality(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string ssid{}; string strength{}; + string noise{}; + string snr{}; Exchange::INetworkManager::WiFiSignalQuality quality{}; if (_networkManager) - rc = _networkManager->GetWiFiSignalStrength(ssid, strength, quality); + rc = _networkManager->GetWiFiSignalQuality(ssid, strength, noise, snr, quality); else rc = Core::ERROR_UNAVAILABLE; if (Core::ERROR_NONE == rc) { Core::JSON::EnumType iquality(quality); - response["ssid"] = ssid; + response["ssid"] = ssid; + response["quality"] = iquality.Data(); + response["snr"] = snr; response["strength"] = strength; - response["quality"] = iquality.Data(); + response["noise"] = noise; } returnJson(rc); } @@ -1006,16 +1010,18 @@ namespace WPEFramework Notify(_T("onWiFiStateChange"), parameters); } - void NetworkManager::onWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) + void NetworkManager::onWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality) { Core::JSON::EnumType iquality(quality); JsonObject parameters; - parameters["ssid"] = ssid; + parameters["ssid"] = ssid; + parameters["quality"] = iquality.Data(); + parameters["snr"] = snr; parameters["strength"] = strength; - parameters["quality"] = iquality.Data(); + parameters["noise"] = noise; LOG_INPARAM(); - Notify(_T("onWiFiSignalStrengthChange"), parameters); + Notify(_T("onWiFiSignalQualityChange"), parameters); } } } diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index fdf103ed7..2d2423baa 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -262,7 +262,7 @@ typedef struct _WiFiConnectedSSIDInfo char bssid[BSSID_BUFF]; /**< The the Basic Service Set ID (mac address). */ char band[BUFF_MIN]; /**< The frequency band at which the client is conneted to. */ int securityMode; /**< Current WiFi Security Mode used for connection. */ - int frequency; /**< The Frequency wt which the client is connected to. */ + int frequency; /**< The Frequency wt which the client is connected to. */ float rate; /**< The Physical data rate in Mbps */ float noise; /**< The average noise strength in dBm. */ float signalStrength; /**< The RSSI value in dBm. */ @@ -1357,13 +1357,15 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { ssidInfo.ssid = string(connectedSsid.ssid); ssidInfo.bssid = string(connectedSsid.bssid); ssidInfo.security = (WIFISecurityMode)mapToNewSecurityMode(connectedSsid.securityMode); - ssidInfo.strength = to_string(connectedSsid.signalStrength); - ssidInfo.rate = to_string(connectedSsid.rate); + ssidInfo.strength = to_string((int)connectedSsid.signalStrength); + ssidInfo.rate = to_string((int)connectedSsid.rate); if(connectedSsid.noise <= 0 || connectedSsid.noise >= DEFAULT_NOISE) - ssidInfo.noise = to_string(connectedSsid.noise); + ssidInfo.noise = to_string((int)connectedSsid.noise); else ssidInfo.noise = to_string(0); - ssidInfo.frequency = to_string((double)connectedSsid.frequency/1000); + + std::string freqStr = to_string((double)connectedSsid.frequency/1000); + ssidInfo.frequency = freqStr.substr(0, 5); NMLOG_INFO ("GetConnectedSSID Success"); rc = Core::ERROR_NONE; @@ -1376,7 +1378,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { } #if 0 - uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) + uint32_t NetworkManagerImplementation::GetWiFiSignalQuality(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; @@ -1398,7 +1400,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { floatStrength = 0.0; strengthOut = static_cast(floatStrength); - NMLOG_INFO ("WiFiSignalStrength in dB = %u",strengthOut); + NMLOG_INFO ("WiFiSignalQuality in dB = %u",strengthOut); if (strengthOut == 0) { @@ -1423,12 +1425,12 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { } strength = std::to_string(strengthOut); - NMLOG_INFO ("GetWiFiSignalStrength success"); + NMLOG_INFO ("GetWiFiSignalQuality success"); rc = Core::ERROR_NONE; } else { - NMLOG_ERROR ("GetWiFiSignalStrength failed"); + NMLOG_ERROR ("GetWiFiSignalQuality failed"); } return rc; } diff --git a/NetworkManagerStunClient.cpp b/NetworkManagerStunClient.cpp index 05ac8f4a0..65eaa8c12 100644 --- a/NetworkManagerStunClient.cpp +++ b/NetworkManagerStunClient.cpp @@ -370,7 +370,7 @@ bool client::bind( auto time_in_cache = std::chrono::duration_cast( std::chrono::steady_clock::now() - m_last_cache_time); - NMLOG_DEBUG("client::bind cache time=%lld", time_in_cache.count()); + NMLOG_DEBUG("client::bind cache time=%lld", (long long int) time_in_cache.count()); if(time_in_cache.count() < m_cache_timeout) { @@ -668,7 +668,7 @@ std::unique_ptr client::send_binding_request(std::chrono::milliseconds std::unique_ptr client::send_binding_request(sockaddr_storage const & addr, std::chrono::milliseconds wait_time) { - NMLOG_DEBUG("sending binding request with wait time:%lld ms", wait_time.count()); + NMLOG_DEBUG("sending binding request with wait time:%lld ms", (long long int) wait_time.count()); this->create_udp_socket(addr.ss_family); std::unique_ptr binding_request(message_factory::create_binding_request()); std::unique_ptr binding_response(this->send_message(addr, *binding_request, wait_time)); diff --git a/Tests/raspberrypi/NetworkManagerGdbusTest.cpp b/Tests/raspberrypi/NetworkManagerGdbusTest.cpp index fb78e2826..d1421204c 100644 --- a/Tests/raspberrypi/NetworkManagerGdbusTest.cpp +++ b/Tests/raspberrypi/NetworkManagerGdbusTest.cpp @@ -63,9 +63,9 @@ namespace WPEFramework { NMLOG_INFO("calling 'ReportWiFiStateChange' cb"); } - void NetworkManagerImplementation::ReportWiFiSignalStrengthChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) + void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) { - NMLOG_INFO("calling 'ReportWiFiSignalStrengthChange' cb"); + NMLOG_INFO("calling 'ReportWiFiSignalQualityChange' cb"); } NetworkManagerImplementation* _instance = nullptr; @@ -275,7 +275,7 @@ int main() case 10: { std::string ssid, signalStrength; Exchange::INetworkManager::WiFiSignalQuality quality; - if (nmClient->getWiFiSignalStrength(ssid, signalStrength, quality)) { + if (nmClient->getWiFiSignalQuality(ssid, signalStrength, quality)) { NMLOG_INFO("SSID: %s, Signal Strength: %s, Quality: %d", ssid.c_str(), signalStrength.c_str(), quality); } else { NMLOG_ERROR("Failed to get WiFi signal strength"); diff --git a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp b/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp index c292c0c40..b3876a76d 100644 --- a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp +++ b/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp @@ -16,7 +16,6 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -#include "WiFiSignalStrengthMonitor.h" #include "NetworkManagerImplementation.h" #include "NetworkManagerLogger.h" #include "INetworkManager.h" @@ -36,7 +35,7 @@ namespace WPEFramework namespace Plugin { NetworkManagerImplementation* _instance = nullptr; - void NetworkManagerImplementation::ReportWiFiSignalStrengthChange(const string ssid, const string strength, const WiFiSignalQuality quality) + void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const string strength, const WiFiSignalQuality quality) { return; } @@ -48,20 +47,20 @@ namespace WPEFramework } } -class WiFiSignalStrengthMonitorTest : public ::testing::Test { +class WiFiSignalQualityMonitorTest : public ::testing::Test { protected: - WPEFramework::Plugin::WiFiSignalStrengthMonitor monitor; + WPEFramework::Plugin::WiFiSignalQualityMonitor monitor; }; -TEST_F(WiFiSignalStrengthMonitorTest, GetSignalData_Connected) { +TEST_F(WiFiSignalQualityMonitorTest, GetSignalData_Connected) { std::string ssid = "TestSSID"; Exchange::INetworkManager::WiFiSignalQuality quality; std::string strengthOut= "-55"; monitor.getSignalData(ssid, quality, strengthOut); } -TEST_F(WiFiSignalStrengthMonitorTest, StartWiFiSignalStrengthMonitor) { - monitor.startWiFiSignalStrengthMonitor(1); +TEST_F(WiFiSignalQualityMonitorTest, StartWiFiSignalQualityMonitor) { + monitor.startWiFiSignalQualityMonitor(1); } int main(int argc, char **argv) { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index b53d62f86..4b7852227 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -100,8 +100,8 @@ NetworkManager interface methods: | [GetConnectedSSID](#method.GetConnectedSSID) | Returns the connected SSID information | | [StartWPS](#method.StartWPS) | Initiates a connection using Wifi Protected Setup (WPS) | | [StopWPS](#method.StopWPS) | Cancels the in-progress WPS pairing operation | -| [GetWiFiSignalStrength](#method.GetWiFiSignalStrength) | Get WiFiSignalStrength of connected SSID | -| [GetSupportedsecurityModes](#method.GetSupportedsecurityModes) | Returns the Wifi security modes that the device supports | +| [GetWiFiSignalQuality](#method.GetWiFiSignalQuality) | Get WiFi signal quality of currently connected SSID | +| [GetSupportedSecurityModes](#method.GetSupportedSecurityModes) | Returns the Wifi security modes that the device supports | | [GetWifiState](#method.GetWifiState) | Returns the current Wifi State | @@ -1196,7 +1196,7 @@ Saves the SSID, passphrase, and security mode for upcoming and future sessions. | params | object | | | params.ssid | string | The WiFi SSID Name | | params.passphrase | string | The access point password | -| params.security | integer | The security mode. See `getSupportedsecurityModes` | +| params.security | integer | The security mode. See `GetSupportedSecurityModes` | ### Result @@ -1217,7 +1217,7 @@ Saves the SSID, passphrase, and security mode for upcoming and future sessions. "params": { "ssid": "myHomeSSID", "passphrase": "password", - "security": 6 + "security": 2 } } ``` @@ -1285,7 +1285,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#even ## *WiFiConnect [method](#head.Methods)* -Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. When called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`. +Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. The security mode is decided based on the highest security mode provided by the SSID. Also when called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`. Also see: [onWiFiStateChange](#event.onWiFiStateChange) @@ -1296,7 +1296,6 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) | params | object | | | params.ssid | string | The WiFi SSID Name | | params.passphrase | string | The access point password | -| params?.security | integer | *(optional)* The security mode is decided based on the highest security mode provided by the SSID | | params?.ca_cert | string | *(optional)* The ca_cert to be used for EAP | | params?.client_cert | string | *(optional)* The client_cert to be used for EAP | | params?.private_key | string | *(optional)* The private_key to be used for EAP | @@ -1327,7 +1326,6 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) "params": { "ssid": "myHomeSSID", "passphrase": "password", - "security": 2, "ca_cert": "...", "client_cert": "...", "private_key": "...", @@ -1413,10 +1411,10 @@ This method takes no parameters. | result.ssid | string | The WiFi SSID Name | | result.bssid | string | The BSSID of given SSID | | result.security | string | The security mode. See the `connect` method | -| result.strength | string | The Signal RSSI value in dBm | +| result.strength | string | The WiFi Signal RSSI value in dBm | | result.frequency | string | The supported frequency for this SSID in GHz | | result.rate | string | The physical data rate in Mbps | -| result.noise | string | The average noise strength in dBm | +| result.noise | string | The WiFi Signal Noise detected in dBm | | result.success | boolean | Whether the request succeeded | ### Example @@ -1440,11 +1438,11 @@ This method takes no parameters. "result": { "ssid": "myHomeSSID", "bssid": "AA:BB:CC:DD:EE:FF", - "security": "5", - "strength": "-27.000000", - "frequency": "2.442000", - "rate": "144.000000", - "noise": "-121.000000", + "security": "2", + "strength": "-32", + "frequency": "2.4420", + "rate": "144", + "noise": "-106", "success": true } } @@ -1546,18 +1544,18 @@ This method takes no parameters. } ``` - -## *GetWiFiSignalStrength [method](#head.Methods)* + +## *GetWiFiSignalQuality [method](#head.Methods)* -Get WiFiSignalStrength of connected SSID. The signal quality is identifed based on the Signal to Noise ratio which is calculated as SNR = rssi - noise. The possible states are -* 'Excellent' : More than 40 dBm -* 'Good' : 40 dBm to 25 dBm -* 'Fair' : 25 dBm to 18 dBm -* 'Weak' : 18 dBm to 0 dBm +Get WiFi signal quality of currently connected SSID. The signal quality is identifed based on the Signal to Noise ratio which is calculated as SNR = rssi - noise. The possible states are +* 'Excellent' : More than 40 dBm +* 'Good' : 40 dBm to 25 dBm +* 'Fair' : 25 dBm to 18 dBm +* 'Weak' : 18 dBm to 0 dBm * 'Disconnected' : 0 dBm . -Also see: [onWiFiSignalStrengthChange](#event.onWiFiSignalStrengthChange) +Also see: [onWiFiSignalQualityChange](#event.onWiFiSignalQualityChange) ### Parameters @@ -1569,8 +1567,10 @@ This method takes no parameters. | :-------- | :-------- | :-------- | | result | object | | | result.ssid | string | The WiFi SSID Name | -| result.strength | string | Signal to Noise Ratio(SNR) in dBm | -| result.quality | string | Signal strength Quality | +| result.quality | string | WiFi Quality based on Signal to Noise Ratio (SNR) | +| result.snr | string | Signal to Noise Ratio(SNR) in dBm | +| result.strength | string | The WiFi Signal RSSI value in dBm | +| result.noise | string | The WiFi Signal Noise detected in dBm | | result.success | boolean | Whether the request succeeded | ### Example @@ -1581,7 +1581,7 @@ This method takes no parameters. { "jsonrpc": "2.0", "id": 42, - "method": "org.rdk.NetworkManager.1.GetWiFiSignalStrength" + "method": "org.rdk.NetworkManager.1.GetWiFiSignalQuality" } ``` @@ -1593,15 +1593,17 @@ This method takes no parameters. "id": 42, "result": { "ssid": "myHomeSSID", - "strength": "-27.000000", "quality": "Excellent", + "snr": "74", + "strength": "-32", + "noise": "-106", "success": true } } ``` - -## *GetSupportedsecurityModes [method](#head.Methods)* + +## *GetSupportedSecurityModes [method](#head.Methods)* Returns the Wifi security modes that the device supports. @@ -1629,7 +1631,7 @@ This method takes no parameters. { "jsonrpc": "2.0", "id": 42, - "method": "org.rdk.NetworkManager.1.GetSupportedsecurityModes" + "method": "org.rdk.NetworkManager.1.GetSupportedSecurityModes" } ``` @@ -1727,7 +1729,7 @@ NetworkManager interface events: | [onInternetStatusChange](#event.onInternetStatusChange) | Triggered when internet connection state changed | | [onAvailableSSIDs](#event.onAvailableSSIDs) | Triggered when scan completes or when scan cancelled | | [onWiFiStateChange](#event.onWiFiStateChange) | Triggered when WIFI connection state get changed | -| [onWiFiSignalStrengthChange](#event.onWiFiSignalStrengthChange) | Triggered when WIFI connection Signal Strength get changed | +| [onWiFiSignalQualityChange](#event.onWiFiSignalQualityChange) | Triggered when WIFI Signal quality changed which is decided based on SNR value which is defined in `GetWiFiSignalQuality` | ## *onInterfaceStateChange [event](#head.Notifications)* @@ -1863,8 +1865,8 @@ Triggered when scan completes or when scan cancelled. | params.ssids | array | On Available SSID's | | params.ssids[#] | object | | | params.ssids[#].ssid | string | Discovered SSID | -| params.ssids[#].security | integer | The security mode. See `getSupportedsecurityModes` | -| params.ssids[#].strength | string | Signal to Noise Ratio(SNR) in dBm | +| params.ssids[#].security | integer | The security mode. See `GetSupportedSecurityModes` | +| params.ssids[#].strength | string | The WiFi Signal RSSI value in dBm | | params.ssids[#].frequency | string | The supported frequency for this SSID in GHz | ### Example @@ -1877,9 +1879,9 @@ Triggered when scan completes or when scan cancelled. "ssids": [ { "ssid": "myAP-2.4", - "security": 6, - "strength": "-27.000000", - "frequency": "2.442000" + "security": 2, + "strength": "-32", + "frequency": "2.4420" } ] } @@ -1912,10 +1914,10 @@ Triggered when WIFI connection state get changed. The possible states are define } ``` - -## *onWiFiSignalStrengthChange [event](#head.Notifications)* + +## *onWiFiSignalQualityChange [event](#head.Notifications)* -Triggered when WIFI connection Signal Strength get changed. +Triggered when WIFI Signal quality changed which is decided based on SNR value which is defined in `GetWiFiSignalQuality`. ### Parameters @@ -1923,19 +1925,23 @@ Triggered when WIFI connection Signal Strength get changed. | :-------- | :-------- | :-------- | | params | object | | | params.ssid | string | The WiFi SSID Name | -| params.strength | string | Signal to Noise Ratio(SNR) in dBm | -| params.quality | string | Signal strength Quality | +| params.quality | string | WiFi Quality based on Signal to Noise Ratio (SNR) | +| params.snr | string | Signal to Noise Ratio(SNR) in dBm | +| params.strength | string | The WiFi Signal RSSI value in dBm | +| params.noise | string | The WiFi Signal Noise detected in dBm | ### Example ```json { "jsonrpc": "2.0", - "method": "client.events.1.onWiFiSignalStrengthChange", + "method": "client.events.1.onWiFiSignalQualityChange", "params": { "ssid": "myHomeSSID", - "strength": "-27.000000", - "quality": "Excellent" + "quality": "Excellent", + "snr": "74", + "strength": "-32", + "noise": "-106" } } ``` diff --git a/gdbus/NetworkManagerGdbusClient.cpp b/gdbus/NetworkManagerGdbusClient.cpp index 00d58aeec..c2145fd8b 100644 --- a/gdbus/NetworkManagerGdbusClient.cpp +++ b/gdbus/NetworkManagerGdbusClient.cpp @@ -1833,7 +1833,7 @@ namespace WPEFramework return ret; } - bool NetworkManagerClient::getWiFiSignalStrength(string& ssid, string& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality) + bool NetworkManagerClient::getWiFiSignalQuality(string& ssid, string& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality) { Exchange::INetworkManager::WiFiSSIDInfo ssidInfo; float rssi = 0.0f; @@ -1858,7 +1858,7 @@ namespace WPEFramework floatSignalStrength = 0.0; signalStrengthOut = static_cast(floatSignalStrength); - NMLOG_INFO ("WiFiSignalStrength in dB = %u",signalStrengthOut); + NMLOG_INFO ("WiFiSignalQuality in dB = %u",signalStrengthOut); if (signalStrengthOut == 0) { diff --git a/gdbus/NetworkManagerGdbusClient.h b/gdbus/NetworkManagerGdbusClient.h index d1a4bb8a7..c50fe3898 100644 --- a/gdbus/NetworkManagerGdbusClient.h +++ b/gdbus/NetworkManagerGdbusClient.h @@ -62,7 +62,7 @@ namespace WPEFramework bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo); bool wifiDisconnect(); bool getWifiState(Exchange::INetworkManager::WiFiState &state); - bool getWiFiSignalStrength(std::string& ssid, std::string& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality); + bool getWiFiSignalQuality(std::string& ssid, std::string& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality); bool startWPS(); bool stopWPS(); diff --git a/gdbus/NetworkManagerGdbusProxy.cpp b/gdbus/NetworkManagerGdbusProxy.cpp index 1d0195034..0e32e7782 100644 --- a/gdbus/NetworkManagerGdbusProxy.cpp +++ b/gdbus/NetworkManagerGdbusProxy.cpp @@ -204,13 +204,13 @@ namespace WPEFramework } #if 0 - uint32_t NetworkManagerImplementation::GetWiFiSignalStrength(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) + uint32_t NetworkManagerImplementation::GetWiFiSignalQuality(string& ssid /* @out */, string& strength /* @out */, WiFiSignalQuality& quality /* @out */) { uint32_t rc = Core::ERROR_GENERAL; - if(_nmGdbusClient->getWiFiSignalStrength(ssid, strength, quality)) + if(_nmGdbusClient->getWiFiSignalQuality(ssid, strength, quality)) rc = Core::ERROR_NONE; else - NMLOG_ERROR("GetWiFiSignalStrength failed"); + NMLOG_ERROR("GetWiFiSignalQuality failed"); return rc; } #endif diff --git a/gdbus/NetworkManagerGdbusUtils.cpp b/gdbus/NetworkManagerGdbusUtils.cpp index df7854cc5..dc95c7e70 100644 --- a/gdbus/NetworkManagerGdbusUtils.cpp +++ b/gdbus/NetworkManagerGdbusUtils.cpp @@ -424,7 +424,8 @@ namespace WPEFramework GnomeUtils::getCachedPropertyU(proxy, "Frequency", &freq); GnomeUtils::getCachedPropertyU(proxy, "MaxBitrate", &bitrate); - wifiInfo.frequency = std::to_string((double)freq/1000); + std::string freqStr = std::to_string((double)freq/1000); + wifiInfo.frequency = freqStr.substr(0, 5); wifiInfo.rate = std::to_string(bitrate); wifiInfo.security = static_cast(wifiSecurityModeFromApFlags(flags, wpaFlags, rsnFlags)); if(noise <= 0 || noise >= DEFAULT_NOISE) From d3e5015dbcf24a5eeb37a97125df1149a94b8644 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 21 Feb 2025 14:18:35 -0500 Subject: [PATCH 090/271] RDKEMW-1928 - GetPrimaryInterface is returning false (#100) * RDKEMW-1928 - GetPrimaryInterface is returning false Reason for change: Temporary mitigation for GetPrimaryInterface failure Test Procedure: Verify with curl commands Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR * RDKEMW-1928 - GetPrimaryInterface is returning false Reason for change: Temporary mitigation for GetPrimaryInterface failure Test Procedure: Verify with curl commands Risks: Low Priority: P1 Signed-off-by: Gururaaja ESR --- NetworkManagerGnomeProxy.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index 8b72b933a..b36e9a790 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -167,7 +167,11 @@ namespace WPEFramework if(ifacePtr == NULL) { NMLOG_ERROR("nm_connection_get_interface_name is failed"); - return Core::ERROR_GENERAL; + /* Temporary mitigation for nm_connection_get_interface_name failure */ + if(m_wlanConnected) + ifacePtr = wifiname.c_str(); + if(m_ethConnected) + ifacePtr = ethname.c_str(); } interface = ifacePtr; From 36ba91a73c4a7c61c05929e09bfc30b4f4a94534 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Mon, 24 Feb 2025 14:01:08 -0500 Subject: [PATCH 091/271] Release of v0.10.0 Release of v0.10.0 --- CHANGELOG.md | 9 +++++++++ CMakeLists.txt | 2 +- NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee2d76f00..f56f1d3f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,15 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.10.0] - 2025-02-24 +### Added +- Implemented Security Agent to support WPS +- Implemented WiFi Signal Quality Monitoring using SNR value. +- Implemented L1 unit test code +- Fixed SetPrimaryInterface for Gnome support +- Fixed WiFiConnect failure to connect to unsecured SSIDs +- Fixed GetPrimaryInterface to gracefully handle libnm failure + ## [0.9.0] - 2025-01-30 ### Added - Enhanced Internet Connectivity Monitoring diff --git a/CMakeLists.txt b/CMakeLists.txt index eabcfa6f9..4d73ac67a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 9) +set(VERSION_MINOR 10) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/NetworkManager.json b/NetworkManager.json index c7826d91c..4ac0cd298 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json", - "version": "0.9.0" + "version": "0.10.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 4b7852227..dc48417e1 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.9.0** +**Version: 0.10.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.9.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.10.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From f6afe4d56408442e67f79e6b152488cc1f9cc0cd Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Wed, 26 Feb 2025 22:36:56 +0530 Subject: [PATCH 092/271] Fix addToknow ssid connection builder (#102) --- NetworkManagerGnomeWIFI.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index a2b17ee54..04b6fc5a8 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -741,7 +741,7 @@ namespace WPEFramework if (NM_IS_REMOTE_CONNECTION(m_connection)) { - if(!connectionBuilder(ssidinfo, m_connection, true)) + if(!connectionBuilder(ssidinfo, m_connection)) { NMLOG_ERROR("connection builder failed"); return false; @@ -760,7 +760,7 @@ namespace WPEFramework { NMLOG_DEBUG("creating new connection '%s' ", ssidinfo.ssid.c_str()); m_connection = nm_simple_connection_new(); - if(!connectionBuilder(ssidinfo, m_connection, true)) + if(!connectionBuilder(ssidinfo, m_connection)) { NMLOG_ERROR("connection builder failed"); return false; From 1c3ebf09386ea7df4712c84aac49e767d8e7b988 Mon Sep 17 00:00:00 2001 From: Simon Chung Date: Thu, 27 Feb 2025 09:25:56 +0000 Subject: [PATCH 093/271] Merge pull request #103 from rdkcentral/feature/test-workflows RDKECMF-223 Add fossid workflow RDKECMF-223 Add fossid workflow --- ..._integration_stateless_diffscan_target_repo.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/fossid_integration_stateless_diffscan_target_repo.yml diff --git a/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml b/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml new file mode 100644 index 000000000..f5989a6cb --- /dev/null +++ b/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml @@ -0,0 +1,14 @@ +name: Fossid Stateless Diff Scan + +on: + pull_request: + branches: + - develop +jobs: + call-fossid-workflow: + uses: rdkcentral/build_tools_workflows/.github/workflows/fossid_integration_stateless_diffscan.yml@develop + secrets: + FOSSID_CONTAINER_USERNAME: ${{ secrets.FOSSID_CONTAINER_USERNAME }} + FOSSID_CONTAINER_PASSWORD: ${{ secrets.FOSSID_CONTAINER_PASSWORD }} + FOSSID_HOST_USERNAME: ${{ secrets.FOSSID_HOST_USERNAME }} + FOSSID_HOST_TOKEN: ${{ secrets.FOSSID_HOST_TOKEN }} From 7d3191e1322af33b799d1bd7997f152ad52c675a Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 28 Feb 2025 00:47:19 +0530 Subject: [PATCH 094/271] RDKEMW-2006: [RDKE][Xumo] Network reset taking more time and landing on error page (#104) The Network Reset from UI, makes 1. RemoveKnownSSID 2. WiFiDisconnect 3. Enable WIFI 4. SetIPSettings (eth0, autoconfig=true) 5. SetIPSettings (wlan0, autoconfig=true) In the given scenario, when SetIPSettings called for wlan0, it returns failure as it already disconnected; We suspect this failure could be causing the delay in UI. It is decided to return success as SetIPSettings at this scenario is just a no-op. --- LegacyPlugin_WiFiManagerAPIs.cpp | 1 - NetworkManagerGnomeProxy.cpp | 25 +++++++-- NetworkManagerGnomeWIFI.cpp | 94 ++++++++++++++++++-------------- NetworkManagerJsonRpc.cpp | 11 ++-- 4 files changed, 77 insertions(+), 54 deletions(-) diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/LegacyPlugin_WiFiManagerAPIs.cpp index f1aac187d..699cdd75f 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/LegacyPlugin_WiFiManagerAPIs.cpp @@ -342,7 +342,6 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; string ssid{}; - ssid = parameters["ssid"].String(); auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); if (_nwmgr) { diff --git a/NetworkManagerGnomeProxy.cpp b/NetworkManagerGnomeProxy.cpp index b36e9a790..4808c99d3 100644 --- a/NetworkManagerGnomeProxy.cpp +++ b/NetworkManagerGnomeProxy.cpp @@ -159,8 +159,14 @@ namespace WPEFramework remoteConn = nm_active_connection_get_connection(activeConn); if(remoteConn == NULL) { - NMLOG_ERROR("remote connection error"); - return Core::ERROR_GENERAL; + NMLOG_WARNING("primary connection but remote connection error"); + NMDeviceState ethState = nmUtils::ifaceState(client, nmUtils::ethIface()); + /* if ethernet is connected but not completely activate then ethernet is taken as primary else wifi */ + if(ethState > NM_DEVICE_STATE_DISCONNECTED && ethState < NM_DEVICE_STATE_DEACTIVATING) + m_defaultInterface = interface = ethname; + else + m_defaultInterface = interface = wifiname; // default is wifi + return Core::ERROR_NONE; } const char *ifacePtr = nm_connection_get_interface_name(NM_CONNECTION(remoteConn)); @@ -375,7 +381,7 @@ namespace WPEFramework NMDhcpConfig *dhcp4_config = NULL; NMDhcpConfig *dhcp6_config = NULL; const char* dhcpserver; - NMSettingConnection *settings; + NMSettingConnection *settings = NULL; NMDevice *device = NULL; std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); @@ -431,11 +437,22 @@ namespace WPEFramework for (guint i = 0; i < connections->len; i++) { + if(connections->pdata[i] == NULL) + continue; + NMActiveConnection *connection = NM_ACTIVE_CONNECTION(connections->pdata[i]); if (connection == nullptr) continue; - settings = nm_connection_get_setting_connection(NM_CONNECTION(nm_active_connection_get_connection(connection))); + NMRemoteConnection* retConn = nm_active_connection_get_connection(connection); + if(retConn == NULL) { + NMLOG_INFO("remote connection is null"); + continue; + } + + settings = nm_connection_get_setting_connection(NM_CONNECTION(retConn)); + if(settings == NULL) + continue; if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) { conn = connection; break; diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 04b6fc5a8..1eb6f0e96 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -303,6 +303,7 @@ namespace WPEFramework bool wifiManager::wifiDisconnect() { + NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; if(!createClientNewConnection()) return false; @@ -312,6 +313,14 @@ namespace WPEFramework return true; } + NMLOG_DEBUG("wifi device current state is %d !", deviceState); + deviceState = nm_device_get_state(wifiNMDevice); + if (deviceState <= NM_DEVICE_STATE_DISCONNECTED || deviceState == NM_DEVICE_STATE_FAILED || deviceState == NM_DEVICE_STATE_DEACTIVATING) + { + NMLOG_WARNING("wifi already disconnected !"); + return true; + } + nm_device_disconnect_async(wifiNMDevice, NULL, disconnectCb, this); wait(m_loop); return m_isSuccess; @@ -372,24 +381,6 @@ namespace WPEFramework g_main_loop_quit(_wifiManager->m_loop); } - static void removeKnownSSIDCb(GObject *client, GAsyncResult *result, gpointer user_data) - { - GError *error = NULL; - wifiManager *_wifiManager = (static_cast(user_data)); - NMRemoteConnection *connection = NM_REMOTE_CONNECTION(client); - if (!nm_remote_connection_delete_finish(connection, result, &error)) { - NMLOG_ERROR("RemoveKnownSSID failed %s", error->message); - _wifiManager->m_isSuccess = false; - } - else - { - NMLOG_INFO ("RemoveKnownSSID is success"); - _wifiManager->m_isSuccess = true; - } - - _wifiManager->quit(NULL); - } - static void wifiConnectionUpdate(GObject *rmObject, GAsyncResult *res, gpointer user_data) { NMRemoteConnection *remote_con = NM_REMOTE_CONNECTION(rmObject); @@ -780,47 +771,60 @@ namespace WPEFramework bool wifiManager::removeKnownSSID(const string& ssid) { NMConnection *m_connection = NULL; - m_isSuccess = false; + bool ssidSpecified = false; if(!createClientNewConnection()) return false; - if(ssid.empty()) - { - NMLOG_ERROR("ssid is empty"); - return false; - } + if(!ssid.empty()) + ssidSpecified = true; + else + NMLOG_WARNING("ssid is not specified, Deleting all availble wifi connection !"); const GPtrArray *allconnections = nm_client_get_connections(m_client); for (guint i = 0; i < allconnections->len; i++) { + GError *error = NULL; NMConnection *connection = static_cast(g_ptr_array_index(allconnections, i)); + if(connection == NULL) + { + NMLOG_WARNING("ssid connection null !"); + continue; + } if (!NM_IS_SETTING_WIRELESS(nm_connection_get_setting_wireless(connection))) continue; // if not wireless connection skipt const char *connId = nm_connection_get_id(NM_CONNECTION(connection)); if(connId == NULL) + { + NMLOG_WARNING("ssid connection id null !"); continue; + } + NMLOG_DEBUG("wireless connection '%s'", connId); - if (strcmp(connId, ssid.c_str()) == 0) + if (ssidSpecified && strcmp(connId, ssid.c_str()) != 0) + continue; + + m_connection = g_object_ref(connection); + if (NM_IS_REMOTE_CONNECTION(connection)) { - m_connection = g_object_ref(connection); - if (NM_IS_REMOTE_CONNECTION(m_connection)) - { - NMLOG_INFO("deleting '%s' connection...", ssid.c_str()); - nm_remote_connection_delete_async(NM_REMOTE_CONNECTION(m_connection), - NULL, - removeKnownSSIDCb, - this); + nm_remote_connection_delete(NM_REMOTE_CONNECTION(connection), NULL, &error); + if(error) { + NMLOG_ERROR("deleting connection failed %s", error->message); } - wait(m_loop); - break; // multiple connection with same name not handiled + else + NMLOG_INFO("delete '%s' connection ...", connId); } } if(!m_connection) - NMLOG_INFO("'%s' no such connection profile", ssid.c_str()); + { + if(ssidSpecified) + NMLOG_WARNING("'%s' no such connection profile", ssid.c_str()); + else + NMLOG_WARNING("No wifi connection profiles found !!"); + } - return m_isSuccess; + return true; } bool wifiManager::getKnownSSIDs(std::list& ssids) @@ -1302,7 +1306,7 @@ namespace WPEFramework if (connections == NULL || connections->len == 0) { NMLOG_WARNING("no connections availble to edit "); - return false; + return true; } for (guint i = 0; i < connections->len; i++) @@ -1310,7 +1314,9 @@ namespace WPEFramework NMConnection *tmpConn = NM_CONNECTION(connections->pdata[i]); if(tmpConn == nullptr) continue; - settings = nm_connection_get_setting_connection(connection); + settings = nm_connection_get_setting_connection(tmpConn); + if(settings == NULL) + continue; if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) { connection = tmpConn; @@ -1332,10 +1338,14 @@ namespace WPEFramework activeConnection = nm_device_get_active_connection(device); if(activeConnection == NULL) { - NMLOG_ERROR("no active connection for wifi"); + NMLOG_WARNING("no active connection for wifi"); return false; } remoteConn = nm_active_connection_get_connection(activeConnection); + if(remoteConn == NULL) { + NMLOG_WARNING("no remote connection for wifi"); + return false; + } connection = NM_CONNECTION(remoteConn); } else @@ -1344,14 +1354,14 @@ namespace WPEFramework if(connection == nullptr) { NMLOG_WARNING("not a single connection availble for %s", interface.c_str()); - return false; + return true; } if(address.autoconfig) { NMSettingIP4Config *sIp4 = nullptr; NMSettingIP6Config *sIp6 = nullptr; - if (nmUtils::caseInsensitiveCompare("IPv4", address.ipversion)) + if(address.ipversion.empty() || nmUtils::caseInsensitiveCompare("IPv4", address.ipversion)) { if(checkAutoConnectEnabledInIPv4Conn(connection)) // already auto connect true connection { diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index b415ffed4..5f9a70edc 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -730,15 +730,12 @@ namespace WPEFramework string ssid{}; if (parameters.HasLabel("ssid")) - { ssid = parameters["ssid"].String(); - if (_networkManager) - rc = _networkManager->RemoveKnownSSID(ssid); - else - rc = Core::ERROR_UNAVAILABLE; - } + + if (_networkManager) + rc = _networkManager->RemoveKnownSSID(ssid); else - rc = Core::ERROR_BAD_REQUEST; + rc = Core::ERROR_UNAVAILABLE; returnJson(rc); } From 75c176389509045012253b06e097e6e49837092d Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 3 Mar 2025 15:43:36 -0500 Subject: [PATCH 095/271] =?UTF-8?q?RDKEMW-2006=20-=20[RDKE][Xumo]=20Networ?= =?UTF-8?q?k=20reset=20taking=20more=20time=20and=20landing=E2=80=A6=20(#1?= =?UTF-8?q?07)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * RDKEMW-2006 - [RDKE][Xumo] Network reset taking more time and landing on error page later Reason for change: Moved the lock to a proper place in monitorThreadFunction() and also changed the lock to be present only for m_stopThread variable in stopWiFiSignalQualityMonitor. Test Procedure: Test and verified Risks: Medium Priority: P1 Signed-off-by: Gururaaja ESR --- NetworkManagerImplementation.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index f4fbd2220..25bf49436 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -687,9 +687,11 @@ namespace WPEFramework if (!m_isRunning) { return; // No thread to stop } - std::lock_guard lock(m_condVariableMutex); - m_stopThread = true; - m_condVariable.notify_one(); + { + std::unique_lock lock(m_condVariableMutex); + m_stopThread = true; + m_condVariable.notify_one(); + } if (m_monitorThread.joinable()) { m_monitorThread.join(); } @@ -813,7 +815,6 @@ namespace WPEFramework std::string strength{}; std::string noise{}; std::string snr{}; - std::unique_lock lock(m_condVariableMutex); Exchange::INetworkManager::WiFiSignalQuality newSignalQuality; NMLOG_DEBUG("checking WiFi signal strength"); @@ -831,6 +832,7 @@ namespace WPEFramework break; // Exit the loop } + std::unique_lock lock(m_condVariableMutex); // Wait for the specified interval or until notified to stop if (m_condVariable.wait_for(lock, std::chrono::seconds(interval), [this](){ return m_stopThread == true; })) { From 93566a1af67dd3cb0b8b890beef84b718ab0f972 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 7 Mar 2025 01:59:10 +0530 Subject: [PATCH 096/271] RDK-55586: Bring up both WiFi and Ethernet Interface (#101) Updated the isConnectedToInternet Method to have `interface` as argument. Updated the documentation for the same. --- INetworkManager.h | 2 +- LegacyPlugin_NetworkAPIs.cpp | 13 ++++--------- NetworkManager.json | 9 ++++++++- NetworkManagerConnectivity.cpp | 32 ++++++++++++++++++++++++++++---- NetworkManagerConnectivity.h | 8 +++++--- NetworkManagerImplementation.cpp | 32 +++++++++++++++++++++++++------- NetworkManagerImplementation.h | 2 +- NetworkManagerJsonRpc.cpp | 12 +++++++++--- docs/NetworkManagerPlugin.md | 8 ++++++-- 9 files changed, 87 insertions(+), 31 deletions(-) diff --git a/INetworkManager.h b/INetworkManager.h index b491dd7db..0064587ce 100644 --- a/INetworkManager.h +++ b/INetworkManager.h @@ -222,7 +222,7 @@ namespace WPEFramework virtual uint32_t SetConnectivityTestEndpoints(IStringIterator* const endpoints /* @in */) = 0; /* @brief Get Internet Connectivty Status */ - virtual uint32_t IsConnectedToInternet(string &ipversion /* @inout */, InternetStatus& status /* @out */) = 0; + virtual uint32_t IsConnectedToInternet(string &ipversion /* @inout */, string &interface /* @inout */, InternetStatus& status /* @out */) = 0; /* @brief Get Authentication URL if the device is behind Captive Portal */ virtual uint32_t GetCaptivePortalURI(string &uri/* @out */) const = 0; diff --git a/LegacyPlugin_NetworkAPIs.cpp b/LegacyPlugin_NetworkAPIs.cpp index 8d49452eb..a5c68192b 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/LegacyPlugin_NetworkAPIs.cpp @@ -281,13 +281,6 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { "255.255.255.255", }; - static bool caseInsensitiveCompare(const std::string& str1, const char* str2) - { - std::string upperStr1 = str1; - std::transform(upperStr1.begin(), upperStr1.end(), upperStr1.begin(), ::toupper); - return upperStr1 == str2; - } - uint32_t Network::getInterfaces (const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; @@ -573,6 +566,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { uint32_t rc = Core::ERROR_GENERAL; LOG_INPARAM(); string ipversion{}; + string interface{}; Exchange::INetworkManager::InternetStatus status{}; if (parameters.HasLabel("ipversion")) @@ -581,7 +575,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); if (_nwmgr != nullptr) { - rc = _nwmgr->IsConnectedToInternet(ipversion, status); + rc = _nwmgr->IsConnectedToInternet(ipversion, interface, status); _nwmgr->Release(); if (Core::ERROR_NONE == rc) @@ -599,6 +593,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { uint32_t rc = Core::ERROR_GENERAL; LOG_INPARAM(); string ipversion{}; + string interface{}; Exchange::INetworkManager::InternetStatus status{}; if (parameters.HasLabel("ipversion")) @@ -607,7 +602,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); if (_nwmgr != nullptr) { - rc = _nwmgr->IsConnectedToInternet(ipversion, status); + rc = _nwmgr->IsConnectedToInternet(ipversion, interface, status); if (Core::ERROR_NONE == rc) { diff --git a/NetworkManager.json b/NetworkManager.json index 4ac0cd298..c35ebbb84 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -615,12 +615,15 @@ } }, "IsConnectedToInternet":{ - "summary": "Seeks whether the device has internet connectivity. This API might take up to 3s to validate internet connectivity.", + "summary": "Seeks whether the device has internet connectivity. This API might take up to 5s to validate internet connectivity. If an interface is provided, connectivity is validated through that specific network interface. If an IP version is specified, connectivity is checked using that IP protocol.", "params": { "type":"object", "properties": { "ipversion": { "$ref": "#/definitions/ipversion" + }, + "interface": { + "$ref": "#/definitions/interface" } }, "required": [ @@ -632,6 +635,9 @@ "ipversion": { "$ref": "#/definitions/ipversion" }, + "interface": { + "$ref": "#/definitions/interface" + }, "connected": { "summary": "`true` if internet connectivity is detected, otherwise `false`", "type": "boolean", @@ -653,6 +659,7 @@ }, "required": [ "ipversion", + "interface", "connected", "state", "status", diff --git a/NetworkManagerConnectivity.cpp b/NetworkManagerConnectivity.cpp index 39a19a4d9..64f29089d 100644 --- a/NetworkManagerConnectivity.cpp +++ b/NetworkManagerConnectivity.cpp @@ -237,7 +237,8 @@ namespace WPEFramework } } - TestConnectivity::TestConnectivity(const std::vector& endpoints, long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion) + TestConnectivity::TestConnectivity(const std::vector& endpoints, + long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion, std::string interface) { internetSate = INTERNET_UNKNOWN; if(endpoints.size() < 1) { @@ -245,7 +246,7 @@ namespace WPEFramework return; } - internetSate = checkCurlResponse(endpoints, timeout_ms, headReq, ipversion); + internetSate = checkCurlResponse(endpoints, timeout_ms, headReq, ipversion, interface); } static bool curlVerboseEnabled() { @@ -266,7 +267,8 @@ namespace WPEFramework return size * nmemb; } - Exchange::INetworkManager::InternetStatus TestConnectivity::checkCurlResponse(const std::vector& endpoints, long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion) + Exchange::INetworkManager::InternetStatus TestConnectivity::checkCurlResponse(const std::vector& endpoints, + long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion, std::string interface) { long deadline = current_time() + timeout_ms, time_now = 0, time_earlier = 0; @@ -314,6 +316,17 @@ namespace WPEFramework else NMLOG_DEBUG("curlopt ipversion = whatever reqtyp = %s", headReq? "HEAD":"GET"); + if(interface == "wlan0") + { + curlSetOpt(curl_easy_handle, CURLOPT_INTERFACE, "wlan0"); + NMLOG_DEBUG("curlopt interface = wlan0"); + } + else if(interface == "eth0") + { + curlSetOpt(curl_easy_handle, CURLOPT_INTERFACE, "eth0"); + NMLOG_DEBUG("curlopt interface = eth0"); + } + if(curlVerboseEnabled()) { curlSetOpt(curl_easy_handle, CURLOPT_VERBOSE, 1L); @@ -494,8 +507,19 @@ namespace WPEFramework m_endpoint.setConnectivityMonitorEndpoints(endpoints); } - Exchange::INetworkManager::InternetStatus ConnectivityMonitor::getInternetState(Exchange::INetworkManager::IPVersion& ipversion, bool ipVersionNotSpecified) + Exchange::INetworkManager::InternetStatus ConnectivityMonitor::getInternetState(std::string& interface, Exchange::INetworkManager::IPVersion& ipversion, bool ipVersionNotSpecified) { + if(!interface.empty()) /* interface is specified, so doing a fresh curl check not taking cache value */ + { + NMLOG_WARNING("getInternetState specified interface %s", interface.c_str()); + if(ipVersionNotSpecified) + ipversion = m_ipversion; /* ipversion not specified, taking global ip version */ + + TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, + NMCONNECTIVITY_CURL_HEAD_REQUEST, ipversion, interface); + return testInternet.getInternetState(); + } + if(ipVersionNotSpecified) { ipversion = m_ipversion; NMLOG_DEBUG("ipversion %s - %s", ipversion == IP_ADDRESS_V4? "IPv4":"IPv6", getInternetStateString(m_InternetState.load())); diff --git a/NetworkManagerConnectivity.h b/NetworkManagerConnectivity.h index 6a9f7f195..98f9c3675 100644 --- a/NetworkManagerConnectivity.h +++ b/NetworkManagerConnectivity.h @@ -98,13 +98,15 @@ namespace WPEFramework const TestConnectivity& operator=(const TestConnectivity&) = delete; public: - TestConnectivity(const std::vector& endpoints, long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion); + TestConnectivity(const std::vector& endpoints, long timeout_ms, bool headReq, + Exchange::INetworkManager::IPVersion ipversion, std::string interface = ""); ~TestConnectivity(){} std::string getCaptivePortal() {return captivePortalURI;} Exchange::INetworkManager::InternetStatus getInternetState(){return internetSate;} int getCurlError(){return curlErrorCode;} private: - Exchange::INetworkManager::InternetStatus checkCurlResponse(const std::vector& endpoints, long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion); + Exchange::INetworkManager::InternetStatus checkCurlResponse(const std::vector& endpoints, + long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion, std::string interface); Exchange::INetworkManager::InternetStatus checkInternetStateFromResponseCode(const std::vector& responses); std::string captivePortalURI; Exchange::INetworkManager::InternetStatus internetSate; @@ -130,7 +132,7 @@ namespace WPEFramework bool switchToInitialCheck(); void setConnectivityMonitorEndpoints(const std::vector &endpoints); std::vector getConnectivityMonitorEndpoints(); - Exchange::INetworkManager::InternetStatus getInternetState(Exchange::INetworkManager::IPVersion& ipversion, bool ipVersionNotSpecified = false); + Exchange::INetworkManager::InternetStatus getInternetState(std::string& interface, Exchange::INetworkManager::IPVersion& ipversion, bool ipVersionNotSpecified = false); std::string getCaptivePortalURI(); private: diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 25bf49436..80dffface 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -246,24 +246,42 @@ namespace WPEFramework } /* @brief Get Internet Connectivty Status */ - uint32_t NetworkManagerImplementation::IsConnectedToInternet(string &ipversion /* @inout */, InternetStatus &result /* @out */) + uint32_t NetworkManagerImplementation::IsConnectedToInternet(string &ipversion /* @inout */, string &interface /* @inout */, InternetStatus &result /* @out */) { LOG_ENTRY_FUNCTION(); Exchange::INetworkManager::IPVersion curlIPversion = Exchange::INetworkManager::IP_ADDRESS_V4; bool ipVersionNotSpecified = false; - if(0 == strcasecmp("IPv4", ipversion.c_str())) - curlIPversion = Exchange::INetworkManager::IP_ADDRESS_V4; - else if(0 == strcasecmp("IPv6", ipversion.c_str())) - curlIPversion = Exchange::INetworkManager::IP_ADDRESS_V6; + + if(!ipversion.empty() && ipversion != "IPv4" && ipversion != "IPv6") + { + NMLOG_WARNING("Invalid Ipversion argument %s", ipversion.c_str()); + return Core::ERROR_BAD_REQUEST; + } else - ipVersionNotSpecified = true; + { + if(ipversion == "IPv4") + curlIPversion = Exchange::INetworkManager::IP_ADDRESS_V4; + else if(ipversion == "IPv6") + curlIPversion = Exchange::INetworkManager::IP_ADDRESS_V6; + else + ipVersionNotSpecified = true; + } - result = connectivityMonitor.getInternetState(curlIPversion, ipVersionNotSpecified); + if(!interface.empty()&& interface != "wlan0" && interface != "eth0") + { + NMLOG_WARNING("Invalid Interface argument %s", interface.c_str()); + return Core::ERROR_BAD_REQUEST; + } + + result = connectivityMonitor.getInternetState(interface, curlIPversion, ipVersionNotSpecified); if (Exchange::INetworkManager::IP_ADDRESS_V6 == curlIPversion) ipversion = "IPv6"; else ipversion = "IPv4"; + if(interface.empty()) + interface = m_defaultInterface; + return Core::ERROR_NONE; } diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index 8a9ff2025..c140c979b 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -226,7 +226,7 @@ namespace WPEFramework uint32_t SetConnectivityTestEndpoints(IStringIterator* const endpoints /* @in */) override; /* @brief Get Internet Connectivty Status */ - uint32_t IsConnectedToInternet(string &ipversion /* @inout */, InternetStatus &result /* @out */) override; + uint32_t IsConnectedToInternet(string &ipversion /* @inout */, string &interface /* @inout */, InternetStatus &result /* @out */) override; /* @brief Get Authentication URL if the device is behind Captive Portal */ uint32_t GetCaptivePortalURI(string &endpoints/* @out */) const override; diff --git a/NetworkManagerJsonRpc.cpp b/NetworkManagerJsonRpc.cpp index 5f9a70edc..cb05dcbde 100644 --- a/NetworkManagerJsonRpc.cpp +++ b/NetworkManagerJsonRpc.cpp @@ -463,12 +463,17 @@ namespace WPEFramework { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string ipversion = parameters["ipversion"].String(); Exchange::INetworkManager::InternetStatus result; - + string ipversion{}; + string interface{}; + + if (parameters.HasLabel("ipversion")) + ipversion = parameters["ipversion"].String(); + if (parameters.HasLabel("interface")) + interface = parameters["interface"].String(); if (_networkManager) - rc = _networkManager->IsConnectedToInternet(ipversion, result); + rc = _networkManager->IsConnectedToInternet(ipversion, interface, result); else rc = Core::ERROR_UNAVAILABLE; @@ -476,6 +481,7 @@ namespace WPEFramework { Core::JSON::EnumType status(result); response["ipversion"] = ipversion; + response["interface"] = interface; response["connected"] = (Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED == result); response["state"] = JsonValue(status); response["status"] = status.Data(); diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index dc48417e1..1bb8bdc90 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -767,7 +767,7 @@ This method used to set up to 5 endpoints for a connectivity test. Successful co ## *IsConnectedToInternet [method](#head.Methods)* -Seeks whether the device has internet connectivity. This API might take up to 3s to validate internet connectivity. +Seeks whether the device has internet connectivity. This API might take up to 5s to validate internet connectivity. If an interface is provided, connectivity is validated through that specific network interface. If an IP version is specified, connectivity is checked using that IP protocol. ### Parameters @@ -775,6 +775,7 @@ Seeks whether the device has internet connectivity. This API might take up to 3s | :-------- | :-------- | :-------- | | params | object | | | params?.ipversion | string | *(optional)* Either IPv4 or IPv6 | +| params?.interface | string | *(optional)* An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | ### Result @@ -782,6 +783,7 @@ Seeks whether the device has internet connectivity. This API might take up to 3s | :-------- | :-------- | :-------- | | result | object | | | result.ipversion | string | Either IPv4 or IPv6 | +| result.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | | result.connected | boolean | `true` if internet connectivity is detected, otherwise `false` | | result.state | integer | Internet state | | result.status | string | Internet status | @@ -797,7 +799,8 @@ Seeks whether the device has internet connectivity. This API might take up to 3s "id": 42, "method": "org.rdk.NetworkManager.1.IsConnectedToInternet", "params": { - "ipversion": "IPv4" + "ipversion": "IPv4", + "interface": "wlan0" } } ``` @@ -810,6 +813,7 @@ Seeks whether the device has internet connectivity. This API might take up to 3s "id": 42, "result": { "ipversion": "IPv4", + "interface": "wlan0", "connected": true, "state": 3, "status": "FULLY_CONNECTED", From 146393d6aa5d881148e055cb115314175493aea8 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 7 Mar 2025 12:27:35 -0500 Subject: [PATCH 097/271] RDK-56182 - NetworkManager Thunder Plugin - Report WiFi SNR (#108) * RDK-56182 - NetworkManager Thunder Plugin - Report WiFi SNR Reason for change: Modified the SNR value to read from the wpa_cli bss command Test Procedure: check with the curl command for GetWiFiSignalQuality Risks: low Priority: P1 Signed-off-by: Gururaaja ESR Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- NetworkManagerGnomeWIFI.cpp | 2 +- NetworkManagerImplementation.cpp | 94 +++++++++++++++++------------- NetworkManagerImplementation.h | 1 + NetworkManagerRDKProxy.cpp | 2 +- gdbus/NetworkManagerGdbusUtils.cpp | 2 +- 5 files changed, 56 insertions(+), 45 deletions(-) diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 1eb6f0e96..37b57a448 100644 --- a/NetworkManagerGnomeWIFI.cpp +++ b/NetworkManagerGnomeWIFI.cpp @@ -221,7 +221,7 @@ namespace WPEFramework wifiInfo.frequency = freqStr.substr(0, 5); wifiInfo.rate = std::to_string(bitrate); - if(noise <= 0 || noise >= DEFAULT_NOISE) + if(noise <= 0 && noise >= DEFAULT_NOISE) wifiInfo.noise = std::to_string(noise); else wifiInfo.noise = std::to_string(0); diff --git a/NetworkManagerImplementation.cpp b/NetworkManagerImplementation.cpp index 80dffface..1a9983ddb 100644 --- a/NetworkManagerImplementation.cpp +++ b/NetworkManagerImplementation.cpp @@ -26,8 +26,8 @@ using namespace WPEFramework::Plugin; using namespace NetworkManagerLogger; #define CIDR_NETMASK_IP_LEN 32 -#define RSSID_COMMAND "wpa_cli signal_poll" #define SSID_COMMAND "wpa_cli status" +#define BSS_COMMAND "wpa_cli bss" namespace WPEFramework { @@ -720,96 +720,106 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::GetWiFiSignalQuality(string& ssid /* @out */, string& strength /* @out */, string& noise /* @out */, string& snr /* @out */, WiFiSignalQuality& quality /* @out */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - int16_t strengthOut = 0; + int16_t readSnr = 0; std::string key, value; - string noiseStr{}; - string rssiStr{}; - int16_t readRSSI = 0; int16_t readNoise = 0; + string bssid{}; char buff[512] = {'\0'}; FILE *fp = NULL; - /* Noise n RSSI */ - fp = popen(RSSID_COMMAND, "r"); + /* SSID */ + fp = popen(SSID_COMMAND, "r"); if (!fp) { - NMLOG_ERROR("Failed in getting output from command %s",RSSID_COMMAND); + NMLOG_ERROR("Failed in getting output from command %s",SSID_COMMAND); return Core::ERROR_RPC_CALL_FAILED; } - while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) - { + while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) { std::istringstream mystream(buff); if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) - if (key == "RSSI") { - rssiStr = value; - } - else if (key == "NOISE") { - noiseStr = value; - } - if (!rssiStr.empty() && !noiseStr.empty()) + if (key == "bssid") { + bssid = value; break; + } } pclose(fp); - /* SSID */ - fp = popen(SSID_COMMAND, "r"); + /* Noise n RSSI */ + std::string bssCommand = std::string(BSS_COMMAND) + " " + bssid; + fp = popen(bssCommand.c_str(), "r"); if (!fp) { - NMLOG_ERROR("Failed in getting output from command %s",SSID_COMMAND); + NMLOG_ERROR("Failed in getting output from command %s",BSS_COMMAND); return Core::ERROR_RPC_CALL_FAILED; } - while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) { + while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) + { std::istringstream mystream(buff); if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) - if (key == "ssid") { + if (key == "level") { + strength = value; + } + else if (key == "noise") { + noise = value; + } + else if (key == "ssid") { ssid = value; - break; } + else if (key == "snr") { + snr = value; + } + if (!strength.empty() && !noise.empty() && !ssid.empty() && !snr.empty()) + break; } pclose(fp); /* NOTE: The std::stoi() will throw exception if the string input is empty; so set to 0 */ - if (rssiStr.empty()) - rssiStr = "0"; - if (noiseStr.empty()) - noiseStr= "0"; + if (noise.empty()) + noise= "0"; + if (snr.empty()) + snr = "0"; + if (strength.empty()) + strength = "0"; - readRSSI = std::stoi(rssiStr); - readNoise = std::stoi(noiseStr); + readNoise = std::stoi(noise); + readSnr = std::stoi(snr); /* Check the Noise is within range */ - if(!(readNoise <= 0 || readNoise >= DEFAULT_NOISE)) + if(!(readNoise < 0 && readNoise >= DEFAULT_NOISE)) { NMLOG_WARNING("Received Noise (%d) from wifi driver is not valid", readNoise); - readNoise = 0; + noise = "0"; } - /* Calculate the SNR */ - strengthOut = readRSSI - readNoise; + /* mapping rssi value when the SNR value is not proper */ + if(!(readSnr > 0 && readSnr <= MAX_SNR_VALUE)) + { + NMLOG_WARNING("Received SNR (%d) from wifi driver is not valid; Lets map with RSSI (%s)", readSnr, strength.c_str()); + readSnr = std::stoi(strength); + /* Take the absolute value */ + readSnr = (readSnr < 0) ? -readSnr : readSnr; - /* Update the results */ - strength = rssiStr; - noise = noiseStr; - snr = std::to_string(strengthOut); + snr = std::to_string(readSnr); + } - NMLOG_INFO ("RSSI: %d dBm; Noise: %d dBm; SNR: %d dBm", readRSSI, readNoise, strengthOut); + NMLOG_INFO ("RSSI: %s dBm; Noise: %s dBm; SNR: %s dBm", strength.c_str(), noise.c_str(), snr.c_str()); - if (strengthOut == 0) + if (readSnr == 0) { quality = WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; strength = "0"; } - else if (strengthOut > 0 && strengthOut < NM_WIFI_SNR_THRESHOLD_FAIR) + else if (readSnr > 0 && readSnr < NM_WIFI_SNR_THRESHOLD_FAIR) { quality = WiFiSignalQuality::WIFI_SIGNAL_WEAK; } - else if (strengthOut > NM_WIFI_SNR_THRESHOLD_FAIR && strengthOut < NM_WIFI_SNR_THRESHOLD_GOOD) + else if (readSnr > NM_WIFI_SNR_THRESHOLD_FAIR && readSnr < NM_WIFI_SNR_THRESHOLD_GOOD) { quality = WiFiSignalQuality::WIFI_SIGNAL_FAIR; } - else if (strengthOut > NM_WIFI_SNR_THRESHOLD_GOOD && strengthOut < NM_WIFI_SNR_THRESHOLD_EXCELLENT) + else if (readSnr > NM_WIFI_SNR_THRESHOLD_GOOD && readSnr < NM_WIFI_SNR_THRESHOLD_EXCELLENT) { quality = WiFiSignalQuality::WIFI_SIGNAL_GOOD; } diff --git a/NetworkManagerImplementation.h b/NetworkManagerImplementation.h index c140c979b..1c7d3d949 100644 --- a/NetworkManagerImplementation.h +++ b/NetworkManagerImplementation.h @@ -35,6 +35,7 @@ using namespace std; #include "NetworkManagerStunClient.h" #define DEFAULT_NOISE -180 +#define MAX_SNR_VALUE 180 #define DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC 60 #define NM_WIFI_SNR_THRESHOLD_EXCELLENT 40 diff --git a/NetworkManagerRDKProxy.cpp b/NetworkManagerRDKProxy.cpp index 2d2423baa..a357a3dc8 100644 --- a/NetworkManagerRDKProxy.cpp +++ b/NetworkManagerRDKProxy.cpp @@ -1359,7 +1359,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { ssidInfo.security = (WIFISecurityMode)mapToNewSecurityMode(connectedSsid.securityMode); ssidInfo.strength = to_string((int)connectedSsid.signalStrength); ssidInfo.rate = to_string((int)connectedSsid.rate); - if(connectedSsid.noise <= 0 || connectedSsid.noise >= DEFAULT_NOISE) + if(connectedSsid.noise <= 0 && connectedSsid.noise >= DEFAULT_NOISE) ssidInfo.noise = to_string((int)connectedSsid.noise); else ssidInfo.noise = to_string(0); diff --git a/gdbus/NetworkManagerGdbusUtils.cpp b/gdbus/NetworkManagerGdbusUtils.cpp index dc95c7e70..099b1ad69 100644 --- a/gdbus/NetworkManagerGdbusUtils.cpp +++ b/gdbus/NetworkManagerGdbusUtils.cpp @@ -428,7 +428,7 @@ namespace WPEFramework wifiInfo.frequency = freqStr.substr(0, 5); wifiInfo.rate = std::to_string(bitrate); wifiInfo.security = static_cast(wifiSecurityModeFromApFlags(flags, wpaFlags, rsnFlags)); - if(noise <= 0 || noise >= DEFAULT_NOISE) + if(noise <= 0 && noise >= DEFAULT_NOISE) wifiInfo.noise = std::to_string(noise); else wifiInfo.noise = std::to_string(0); From b8e7adf44acccd3b047cd6d1be361b3d3d967fe3 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 7 Mar 2025 14:06:41 -0500 Subject: [PATCH 098/271] Release of v0.11.0 Release of v0.11.0 --- CHANGELOG.md | 8 ++++++++ CMakeLists.txt | 2 +- NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f56f1d3f5..64075d5ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,14 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.11.0] - 2025-03-07 +### Added +- Implemented concurrent interface support in public APIs +- Changed the approach to get the SNR value. +- Fixed RemoveKnownSSID() API to clear all the SSIDs when called with empty input +- Fixed minor bug in AddtoKnownSSID() API for Gnome backend +- Fixed Network Reset Flow + ## [0.10.0] - 2025-02-24 ### Added - Implemented Security Agent to support WPS diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d73ac67a..47fc86880 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 10) +set(VERSION_MINOR 11) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/NetworkManager.json b/NetworkManager.json index c35ebbb84..ae03aff46 100644 --- a/NetworkManager.json +++ b/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json", - "version": "0.10.0" + "version": "0.11.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 1bb8bdc90..c9ba3fc88 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.10.0** +**Version: 0.11.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.10.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.11.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From d1db5e81cc00f1692bba95ead8640353e1e3433b Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Tue, 11 Mar 2025 02:23:18 +0530 Subject: [PATCH 099/271] RDKEMW-1808 [RDE] - Implement GNOME support via direct G-DBus WPS APIs (#111) - On boot interface check added - Workflow added with gdbus proxy - Add wps initial commit change - WiFi connect security read updated - Connection updated --- .github/workflows/gnome_unit_test.yml | 22 +- CMakeLists.txt | 5 +- gdbus/NetworkManagerGdbusClient.cpp | 283 +++++++++++++++++++++++--- gdbus/NetworkManagerGdbusClient.h | 13 +- gdbus/NetworkManagerGdbusProxy.cpp | 93 ++++++++- gdbus/NetworkManagerGdbusUtils.cpp | 35 +--- 6 files changed, 374 insertions(+), 77 deletions(-) diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index 870d95222..200895161 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -62,18 +62,32 @@ jobs: uses: actions/checkout@v3 with: path: networkmanager - - - name: Build networkmanager with Gnome Proxy + + - name: Build networkmanager with Gnome libnm Proxy + run: > + cmake + -S "${{github.workspace}}/networkmanager" + -B build/GnomeLibnmNetworkmanager + -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DCMAKE_CXX_FLAGS=" -fprofile-arcs -ftest-coverage " + -DENABLE_GNOME_NETWORKMANAGER=ON + && + cmake --build build/GnomeLibnmNetworkmanager --target install -j8 + + - name: Build networkmanager with Gnome GDBUS Proxy run: > cmake -S "${{github.workspace}}/networkmanager" - -B build/GnomeNetworkmanager + -B build/GnomeGdbusNetworkmanager -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" -DCMAKE_CXX_FLAGS=" -fprofile-arcs -ftest-coverage " -DENABLE_GNOME_NETWORKMANAGER=ON + -DENABLE_GNOME_GDBUS=ON && - cmake --build build/GnomeNetworkmanager --target install -j8 + cmake --build build/GnomeGdbusNetworkmanager --target install -j8 diff --git a/CMakeLists.txt b/CMakeLists.txt index 47fc86880..083cae825 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,9 +127,10 @@ if(ENABLE_GNOME_NETWORKMANAGER) gdbus/NetworkManagerGdbusClient.cpp gdbus/NetworkManagerGdbusEvent.cpp gdbus/NetworkManagerGdbusMgr.cpp - gdbus/NetworkManagerGdbusUtils.cpp ) + gdbus/NetworkManagerGdbusUtils.cpp + NetworkManagerSecretAgent.cpp ) target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) - target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES} ${GIO_LIBRARIES}) + target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES} ${GIO_LIBRARIES} uuid) else() message("networkmanager building with libnm") target_sources(${MODULE_NAME} PRIVATE diff --git a/gdbus/NetworkManagerGdbusClient.cpp b/gdbus/NetworkManagerGdbusClient.cpp index c2145fd8b..de74f3f12 100644 --- a/gdbus/NetworkManagerGdbusClient.cpp +++ b/gdbus/NetworkManagerGdbusClient.cpp @@ -1215,7 +1215,7 @@ namespace WPEFramework const guchar *ssid_data = static_cast(g_variant_get_fixed_array(value, &ssid_length, sizeof(guchar))); if (ssid_data && ssid_length > 0 && ssid_length <= 32) { ssid.assign(reinterpret_cast(ssid_data), ssid_length); - NMLOG_DEBUG("SSID: %s", ssid.c_str()); + //NMLOG_DEBUG("SSID: %s", ssid.c_str()); } else { NMLOG_ERROR("Invalid SSID length: %zu (maximum is 32)", ssid_length); ssid.empty(); @@ -1239,7 +1239,7 @@ namespace WPEFramework { G_VARIANT_LOOKUP(setting, "key-mgmt", "&s", &keyMgmt); if(keyMgmt != NULL) - NMLOG_DEBUG("802-11-wireless-security.key-mgmt: %s", keyMgmt); + NMLOG_DEBUG("ssid: %s key-mgmt: %s", ssid.c_str(), keyMgmt); g_variant_unref(setting); setting = NULL; } @@ -1260,7 +1260,7 @@ namespace WPEFramework return ret; } - static bool deleteConnection(DbusMgr m_dbus, const std::string& path, std::string& ssid) + static bool deleteConnection(DbusMgr& m_dbus, const std::string& path, std::string& ssid) { GError *error = NULL; GDBusProxy *ConnProxy = NULL; @@ -1360,11 +1360,13 @@ namespace WPEFramework return ret; } - bool NetworkManagerClient::getAvailableSSIDs(std::list& ssids) + bool NetworkManagerClient::getMatchingSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo& ssidInfo, std::string& apPathStr) { GError* error = nullptr; GDBusProxy* wProxy = nullptr; deviceInfo devProperty{}; + Exchange::INetworkManager::WiFiSSIDInfo apInfo{}; + bool ret = false; if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), devProperty)) return false; @@ -1392,17 +1394,26 @@ namespace WPEFramework g_variant_get(result, "(ao)", &iter); while (g_variant_iter_loop(iter, "o", &apPath)) { - Exchange::INetworkManager::WiFiSSIDInfo wifiInfo{}; - NMLOG_DEBUG("Access Point Path: %s", apPath); - if(GnomeUtils::getApDetails(m_dbus, apPath, wifiInfo)) - ssids.push_back(wifiInfo.ssid); + if(apPath == NULL) + continue; + // NMLOG_DEBUG("Access Point Path: %s", apPath); + if(GnomeUtils::getApDetails(m_dbus, apPath, apInfo)) + { + if(ssidInfo.ssid == apInfo.ssid) + { + ssidInfo = apInfo; + apPathStr = apPath; + ret = true; + break; + } + } } g_variant_iter_free(iter); g_variant_unref(result); g_object_unref(wProxy); - return true; + return ret; } bool NetworkManagerClient::startWifiScan(const std::string ssid) @@ -1536,7 +1547,7 @@ namespace WPEFramework return true; } - bool addNewConnctionAndactivate(DbusMgr& m_dbus, GVariantBuilder connBuilder, const char* devicePath, bool persist) + bool addNewConnctionAndactivate(DbusMgr& m_dbus, GVariantBuilder& connBuilder, const char* devicePath, bool persist, const char* specificObject) { GDBusProxy* proxy = nullptr; GError* error = nullptr; @@ -1546,7 +1557,13 @@ namespace WPEFramework if(proxy == NULL) return false; - const char* specific_object = "/"; + GVariant *connBuilderVariant = g_variant_builder_end(&connBuilder); + if(connBuilderVariant == NULL) + { + NMLOG_ERROR("Failed to build connection settings"); + g_object_unref(proxy); + return false; + } GVariantBuilder optionsBuilder; g_variant_builder_init (&optionsBuilder, G_VARIANT_TYPE ("a{sv}")); @@ -1558,8 +1575,17 @@ namespace WPEFramework //else //g_variant_builder_add(&optionsBuilder, "{sv}", "persist", g_variant_new_string("disk")); + GVariant *optionBuilderVariant = g_variant_builder_end(&optionsBuilder); + if(optionBuilderVariant == NULL) + { + NMLOG_ERROR("Failed to build options settings"); + g_object_unref(proxy); + return false; + } + + NMLOG_DEBUG("devicePath %s, specificObject %s", devicePath, specificObject); result = g_dbus_proxy_call_sync (proxy, "AddAndActivateConnection2", - g_variant_new("(a{sa{sv}}ooa{sv})", connBuilder, devicePath, specific_object, optionsBuilder), + g_variant_new("(@a{sa{sv}}oo@a{sv})", connBuilderVariant, devicePath?: "/", specificObject?: "/", optionBuilderVariant), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); if (result == NULL) { @@ -1572,6 +1598,8 @@ namespace WPEFramework return false; } + NMLOG_DEBUG("AddAndActivateConnection2 success !!!"); + GVariant* pathVariant = NULL; GVariant* activeConnVariant = NULL; GVariant* resultDict = NULL; @@ -1607,7 +1635,7 @@ namespace WPEFramework return std::string(""); } - static bool connectionBuilder(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo, GVariantBuilder& connBuilder) + static bool connectionBuilder(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo, GVariantBuilder& connBuilder, bool iswpsAP = false) { GVariantBuilder settingsBuilder; @@ -1649,15 +1677,6 @@ namespace WPEFramework case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK: case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE: { - if(ssidinfo.passphrase.empty() || ssidinfo.passphrase.length() < 8) - { - NMLOG_WARNING("wifi securtity type password erro length > 8"); - GVariant *sVariant = g_variant_builder_end(&settingsBuilder); - if(sVariant) - g_variant_unref(sVariant); - return false; - } - if(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE == ssidinfo.security) { NMLOG_DEBUG("802-11-wireless-security key-mgmt: 'sae'"); @@ -1668,18 +1687,31 @@ namespace WPEFramework NMLOG_DEBUG("802-11-wireless-security key-mgmt: 'wpa-psk'"); g_variant_builder_add (&settingsBuilder, "{sv}", "key-mgmt", g_variant_new_string("wpa-psk")); // WPA + WPA2 + WPA3 personal } - g_variant_builder_add (&settingsBuilder, "{sv}", "psk", g_variant_new_string(ssidinfo.passphrase.c_str())); // password + + /* if ap is not a wps network */ + if(!iswpsAP) + { + if(ssidinfo.passphrase.empty() || ssidinfo.passphrase.length() < 8) + { + NMLOG_WARNING("wifi securtity type password erro length > 8"); + GVariant *sVariant = g_variant_builder_end(&settingsBuilder); + if(sVariant) + g_variant_unref(sVariant); + return false; + } + g_variant_builder_add (&settingsBuilder, "{sv}", "psk", g_variant_new_string(ssidinfo.passphrase.c_str())); // password + } break; } - case Exchange::INetworkManager::WIFI_SECURITY_NONE: { NMLOG_DEBUG("802-11-wireless-security key-mgmt: 'none'"); - g_variant_builder_add (&settingsBuilder, "{sv}", "key-mgmt", g_variant_new_string("none")); // no password protection + // g_variant_builder_add (&settingsBuilder, "{sv}", "key-mgmt", g_variant_new_string("none")); // no password protection break; } default: { + // ToDo handile Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP NMLOG_WARNING("connection wifi securtity type not supported %d", ssidinfo.security); GVariant *sVariant = g_variant_builder_end(&settingsBuilder); if(sVariant) @@ -1926,7 +1958,7 @@ namespace WPEFramework return true; } - bool NetworkManagerClient::wifiConnect(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo) + bool NetworkManagerClient::wifiConnect(const Exchange::INetworkManager::WiFiConnectTo& connectInfo, bool iswpsAP) { // TODO check sudo nmcli device wifi connect HomeNet password rafi@123 // Error: Connection activation failed: Device disconnected by user or client error ? @@ -1934,6 +1966,7 @@ namespace WPEFramework bool reuseConnection = false; deviceInfo deviceProp; std::string exsistingConn; + Exchange::INetworkManager::WiFiConnectTo ssidinfo = connectInfo; if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), deviceProp)) return false; @@ -1959,10 +1992,26 @@ namespace WPEFramework } } + /* if ap is avilable check the security is maching to user requested */ + Exchange::INetworkManager::WiFiSSIDInfo apInfo{}; + apInfo.ssid = ssidinfo.ssid; + std::string apPathStr = "/"; // default specific object path is "/" + if(getMatchingSSIDInfo(apInfo, apPathStr)) + { + if(ssidinfo.security != apInfo.security) + { + NMLOG_WARNING("user requested wifi security '%d' != AP supported security %d ", ssidinfo.security, apInfo.security); + ssidinfo.security = apInfo.security; + // NMLOG_DEBUG("ap path %s", apPathStr.c_str()); + } + } + else + NMLOG_WARNING("matching ssid (%s) not found in scanning result", ssidinfo.ssid.c_str()); + if(reuseConnection) { NMLOG_INFO("activating connection..."); - if(!connectionBuilder(ssidinfo, connBuilder)) { + if(!connectionBuilder(ssidinfo, connBuilder, iswpsAP)) { NMLOG_WARNING("connection builder failed"); return false; } @@ -1976,11 +2025,11 @@ namespace WPEFramework } else { - if(!connectionBuilder(ssidinfo, connBuilder)) { + if(!connectionBuilder(ssidinfo, connBuilder, iswpsAP)) { NMLOG_WARNING("connection builder failed"); return false; } - if(addNewConnctionAndactivate(m_dbus, connBuilder, deviceProp.path.c_str(), ssidinfo.persist)) + if(addNewConnctionAndactivate(m_dbus, connBuilder, deviceProp.path.c_str(), ssidinfo.persist, apPathStr.c_str())) NMLOG_INFO("wifi connect request success"); else { NMLOG_ERROR("wifi connect request failed"); @@ -2025,14 +2074,182 @@ namespace WPEFramework return true; } - bool NetworkManagerClient::startWPS() + static bool getWpsPbcSSIDDetails(DbusMgr& m_dbus, const char* apPath, std::string& wpsApSsid) + { + guint32 flags = 0; + bool ret = false; + GVariant* ssidVariant = NULL; + GDBusProxy* proxy = m_dbus.getNetworkManagerAccessPointProxy(apPath); + if (proxy == NULL) + return false; + + if (GnomeUtils::getCachedPropertyU(proxy, "Flags", &flags) && flags & NM_802_11_AP_FLAGS_WPS_PBC) + { + gsize ssid_length = 0; + ssidVariant = g_dbus_proxy_get_cached_property(proxy,"Ssid"); + if (!ssidVariant) { + NMLOG_ERROR("Failed to get AP ssid properties."); + g_object_unref(proxy); + return false; + } + + const guchar *ssid_data = static_cast(g_variant_get_fixed_array(ssidVariant, &ssid_length, sizeof(guchar))); + if (ssid_data && ssid_length > 0 && ssid_length <= 32) + { + GVariant* result = NULL; + gchar *_bssid = NULL; + wpsApSsid.assign(reinterpret_cast(ssid_data), ssid_length); + result = g_dbus_proxy_get_cached_property(proxy,"HwAddress"); + if (!result) { + NMLOG_ERROR("Failed to get AP properties."); + g_object_unref(proxy); + return false; + } + g_variant_get(result, "s", &_bssid); + if(_bssid != NULL) { + NMLOG_INFO("WPS PBC AP found ssid: %s, bssid: %s", wpsApSsid.c_str(), _bssid); + ret = true; + g_free(_bssid); + } + g_variant_unref(result); + } + else + NMLOG_ERROR("WPS PBC Ap ssid Error !"); + + if(ssidVariant) + g_variant_unref(ssidVariant); + } + + if(proxy) + g_object_unref(proxy); + + return ret; + } + + static bool findWpsPbcSSID(DbusMgr& m_dbus, std::string& wpsApSsid) + { + GError* error = nullptr; + GDBusProxy* wProxy = nullptr; + deviceInfo devProperty{}; + bool isfound = false; + + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), devProperty)) + return false; + + if(devProperty.path.empty() || devProperty.state < NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_ERROR("no wifi device found"); + return false; + } + + wProxy = m_dbus.getNetworkManagerWirelessProxy(devProperty.path.c_str()); + if (wProxy == NULL) + return false; + + GVariant* result = g_dbus_proxy_call_sync(wProxy, "GetAllAccessPoints", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + NMLOG_ERROR("Error creating proxy: %s", error->message); + g_error_free(error); + g_object_unref(wProxy); + return false; + } + + GVariantIter* iter = NULL; + const gchar* apPath = NULL; + g_variant_get(result, "(ao)", &iter); + + while (g_variant_iter_loop(iter, "o", &apPath)) + { + guint32 flags = 0; + if(apPath == NULL) + continue; + // NMLOG_DEBUG("Access Point Path: %s", apPath); + isfound = getWpsPbcSSIDDetails(m_dbus, apPath, wpsApSsid); + if(isfound) + break; + } + + if(!isfound) + NMLOG_WARNING("WPS PBC AP not found in scanned result !"); + + g_variant_iter_free(iter); + g_variant_unref(result); + g_object_unref(wProxy); + + return isfound; + } + + void NetworkManagerClient::wpsProcess() { - return false; + m_wpsProcessRun = true; + Exchange::INetworkManager::WiFiConnectTo ssidinfo{}; + Exchange::INetworkManager::WiFiState state; + NMLOG_INFO("WPS process started !"); + + if(!getWifiState(state)) + { + NMLOG_ERROR("wifi state error ! wps process stoped !"); + m_wpsProcessRun = false; + return; + } + + for(int retry =0; retry < GDBUS_WPS_RETRY_COUNT; retry++) + { + if(m_wpsProcessRun.load() == false) // stop wps process if reuested + break; + sleep(GDBUS_WPS_RETRY_WAIT_IN_MS); + if(m_wpsProcessRun.load() == false) + break; + if(!findWpsPbcSSID(m_dbus, ssidinfo.ssid)) + { + startWifiScan(); + NMLOG_DEBUG("WPS process retrying: %d ", retry+1); + continue; + } + + if(!getWifiState(state)) + { + NMLOG_ERROR("wifi state error ! wps process stoped !"); + m_wpsProcessRun = false; + return; + } + + if(Exchange::INetworkManager::WiFiState::WIFI_STATE_DISCONNECTED != state) + { + /* we need a wifi disconnected state to proceed wifi PBC process */ + wifiDisconnect(); + } + + ssidinfo.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + ssidinfo.persist = true; + /* security mode will be updated in wifi connect function, if not mathing to wpa-psk */ + wifiConnect(ssidinfo, true); // isWps = true + break; + } + + NMLOG_INFO("wps process complete !!"); + m_wpsProcessRun = false; } - bool NetworkManagerClient::stopWPS() + bool NetworkManagerClient::startWPS() { - return false; + NMLOG_DEBUG("Start WPS %s", __FUNCTION__); + if(m_wpsProcessRun.load()) + { + NMLOG_WARNING("wps process WPS already running"); + return true; + } + + m_secretAgent.RegisterAgent(); + m_wpsthread = std::thread(&NetworkManagerClient::wpsProcess, this); + m_wpsthread.detach(); + return true; + } + + bool NetworkManagerClient::stopWPS() { + NMLOG_DEBUG("Stop WPS %s", __FUNCTION__); + m_wpsProcessRun = false; + return m_secretAgent.UnregisterAgent(); } } // WPEFramework diff --git a/gdbus/NetworkManagerGdbusClient.h b/gdbus/NetworkManagerGdbusClient.h index c50fe3898..22c550445 100644 --- a/gdbus/NetworkManagerGdbusClient.h +++ b/gdbus/NetworkManagerGdbusClient.h @@ -25,10 +25,14 @@ #include "NetworkManagerLogger.h" #include "NetworkManagerGdbusMgr.h" +#include "NetworkManagerSecretAgent.h" #include "INetworkManager.h" #define ROUTE_METRIC_PRIORITY_HIGH 10 #define ROUTE_METRIC_PRIORITY_LOW 100 +#define GDBUS_WPS_RETRY_WAIT_IN_MS 10 // 10 sec +#define GDBUS_WPS_RETRY_COUNT 10 + namespace WPEFramework { namespace Plugin @@ -54,12 +58,11 @@ namespace WPEFramework bool getInterfaceState(const std::string& interface, bool& isEnabled); bool getIPSettings(const std::string& interface, const std::string& ipversion, Exchange::INetworkManager::IPAddress& result); bool getKnownSSIDs(std::list& ssids); - bool getAvailableSSIDs(std::list& ssids); bool getConnectedSSID(Exchange::INetworkManager::WiFiSSIDInfo& ssidinfo); bool addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo); bool removeKnownSSIDs(const std::string& ssid); bool startWifiScan(const std::string ssid = ""); - bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo); + bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo& connectInfo, bool iswpsAP = false); bool wifiDisconnect(); bool getWifiState(Exchange::INetworkManager::WiFiState &state); bool getWiFiSignalQuality(std::string& ssid, std::string& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality); @@ -69,7 +72,11 @@ namespace WPEFramework private: NetworkManagerClient(); ~NetworkManagerClient(); - + void wpsProcess(); + bool getMatchingSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo& ssidInfo, std::string& apPathStr); + std::thread m_wpsthread; + std::atomic m_wpsProcessRun; + SecretAgent m_secretAgent; DbusMgr m_dbus; }; } // Plugin diff --git a/gdbus/NetworkManagerGdbusProxy.cpp b/gdbus/NetworkManagerGdbusProxy.cpp index 0e32e7782..533cfa0a3 100644 --- a/gdbus/NetworkManagerGdbusProxy.cpp +++ b/gdbus/NetworkManagerGdbusProxy.cpp @@ -37,11 +37,55 @@ namespace WPEFramework return; } + void NetworkManagerImplementation::getInitialConnectionState() + { + // check the connection state and post event + Exchange::INetworkManager::IInterfaceDetailsIterator* _interfaces{}; + uint32_t rc = GetAvailableInterfaces(_interfaces); + + if (Core::ERROR_NONE == rc) + { + if (_interfaces != nullptr) + { + Exchange::INetworkManager::InterfaceDetails iface{}; + while (_interfaces->Next(iface) == true) + { + Core::JSON::EnumType type{iface.type}; + if(iface.enabled) + { + NMLOG_INFO("'%s' interface is enabled", iface.name.c_str()); + // ReportInterfaceStateChange(Exchange::INetworkManager::INTERFACE_ADDED, iface.name); + if(iface.connected) + { + NMLOG_INFO("'%s' interface is connected", iface.name.c_str()); + ReportActiveInterfaceChange(iface.name, iface.name); + std::string ipversion = {}; + Exchange::INetworkManager::IPAddress addr; + rc = GetIPSettings(iface.name, ipversion, addr); + if (Core::ERROR_NONE == rc) + { + if(!addr.ipaddress.empty()) { + NMLOG_INFO("'%s' interface have ip '%s'", iface.name.c_str(), addr.ipaddress.c_str()); + ReportIPAddressChange(iface.name, addr.ipversion, addr.ipaddress, Exchange::INetworkManager::IP_ACQUIRED); + } + } + } + } + } + + _interfaces->Release(); + } + } + else + NMLOG_INFO("GetAvailableInterfaces Failed"); + } + void NetworkManagerImplementation::platform_init() { ::_instance = this; _nmGdbusClient = NetworkManagerClient::getInstance(); _nmGdbusEvents = NetworkManagerEvents::getInstance(); + getInitialConnectionState(); } uint32_t NetworkManagerImplementation::GetAvailableInterfaces (Exchange::INetworkManager::IInterfaceDetailsIterator*& interfacesItr/* @out */) @@ -176,10 +220,23 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::WiFiConnect(const WiFiConnectTo& ssid /* @in */) { uint32_t rc = Core::ERROR_GENERAL; - if(_nmGdbusClient->wifiConnect(ssid)) - rc = Core::ERROR_NONE; + if(ssid.ssid.empty()) + { + NMLOG_WARNING("ssid is not sepecified; so attampting to connect know ssids !"); + _nmGdbusEvents->setwifiScanOptions(false); /* Enable event posting */ + if(_nmGdbusClient->startWifiScan()) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("StartWiFiScan failed"); + } else - NMLOG_ERROR("WiFiConnect failed"); + { + if(_nmGdbusClient->wifiConnect(ssid)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("WiFiConnect failed"); + } + return rc; } @@ -227,12 +284,38 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) { - return Core::ERROR_NONE; + uint32_t rc = Core::ERROR_NONE; + if(method == WIFI_WPS_SERIALIZED_PIN || method == WIFI_WPS_PIN) + { + NMLOG_ERROR("WPS PIN method is not supported as of now"); + return Core::ERROR_RPC_CALL_FAILED; + } + _nmGdbusEvents->setwifiScanOptions(false); + if(!_nmGdbusClient->startWifiScan()) + { + NMLOG_WARNING("scanning reuest failed; trying to connect wps"); + } + + if(_nmGdbusClient->startWPS()) + NMLOG_INFO ("start WPS success"); + else { + rc = Core::ERROR_GENERAL; + NMLOG_ERROR("start WPS failed"); + } + + return rc; } uint32_t NetworkManagerImplementation::StopWPS(void) { - return Core::ERROR_NONE; + uint32_t rc = Core::ERROR_NONE; + if(_nmGdbusClient->stopWPS()) + NMLOG_INFO ("stop success"); + else { + NMLOG_ERROR("stop WPS failed"); + rc = Core::ERROR_GENERAL; + } + return rc; } } } diff --git a/gdbus/NetworkManagerGdbusUtils.cpp b/gdbus/NetworkManagerGdbusUtils.cpp index 099b1ad69..4251fb336 100644 --- a/gdbus/NetworkManagerGdbusUtils.cpp +++ b/gdbus/NetworkManagerGdbusUtils.cpp @@ -154,39 +154,14 @@ namespace WPEFramework { uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; if ((flags == NM_802_11_AP_FLAGS_NONE) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) - { security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE; - } - else if((wpaFlags & NM_802_11_AP_SEC_PAIR_TKIP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_TKIP)) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - } - else if((wpaFlags & NM_802_11_AP_SEC_PAIR_CCMP) || (rsnFlags & NM_802_11_AP_SEC_PAIR_CCMP)) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - } - else if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) && (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP; - } - else if(rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - } - else if((wpaFlags & NM_802_11_AP_SEC_GROUP_CCMP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_CCMP)) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - } - else if((wpaFlags & NM_802_11_AP_SEC_GROUP_TKIP) || (rsnFlags & NM_802_11_AP_SEC_GROUP_TKIP)) - { - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - } - else if((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE) || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) - { + else if (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE) security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE; - } + else if (wpaFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X || rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP; else - NMLOG_WARNING("security mode not defined (flag: %d, wpaFlags: %d, rsnFlags: %d)", flags, wpaFlags, rsnFlags); + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + // NMLOG_DEBUG("ap security str %s", nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); return security; } From d2ae4285cbf26e4c63997968f3c794cd9ccd84d6 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 14 Mar 2025 00:56:27 +0530 Subject: [PATCH 100/271] DELIA-67624 Handle the invalid timeout in Connectivity Monitoring (#109) * DELIA-67624 Handle the invalid timeout in Connectivity Monitoring * Added log handling. --------- Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- NetworkManagerConnectivity.cpp | 65 +++++++++++++++++----------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/NetworkManagerConnectivity.cpp b/NetworkManagerConnectivity.cpp index 64f29089d..3540d8b45 100644 --- a/NetworkManagerConnectivity.cpp +++ b/NetworkManagerConnectivity.cpp @@ -267,10 +267,16 @@ namespace WPEFramework return size * nmemb; } + /* + * It is calculated as the current time plus the specified timeout duration. + * This ensures that the entire operation does not exceed the given timeout, providing a hard limit + * for the network connectivity check. + */ Exchange::INetworkManager::InternetStatus TestConnectivity::checkCurlResponse(const std::vector& endpoints, long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion, std::string interface) { - long deadline = current_time() + timeout_ms, time_now = 0, time_earlier = 0; + long deadline = 0, startTime = current_time(), time_now = 0, time_earlier = 0; + std::string logmsg =""; CURLM *curl_multi_handle = curl_multi_init(); if (!curl_multi_handle) @@ -294,7 +300,7 @@ namespace WPEFramework continue; } curlSetOpt(curl_easy_handle, CURLOPT_URL, endpoint.c_str()); - curlSetOpt(curl_easy_handle, CURLOPT_PRIVATE, endpoint.c_str()); + logmsg += endpoint; /* set our custom set of headers */ curlSetOpt(curl_easy_handle, CURLOPT_HTTPHEADER, chunk); curlSetOpt(curl_easy_handle, CURLOPT_USERAGENT, "RDKCaptiveCheck/1.0"); @@ -302,31 +308,35 @@ namespace WPEFramework { /* HTTPGET request added insted of HTTPHEAD request fix for DELIA-61526 */ curlSetOpt(curl_easy_handle, CURLOPT_HTTPGET, 1L); + logmsg += ", Get"; } + else + logmsg += ", Head"; curlSetOpt(curl_easy_handle, CURLOPT_WRITEFUNCTION, writeFunction); - curlSetOpt(curl_easy_handle, CURLOPT_TIMEOUT_MS, deadline - current_time()); + curlSetOpt(curl_easy_handle, CURLOPT_TIMEOUT_MS, timeout_ms); if (IP_ADDRESS_V4 == ipversion) { curlSetOpt(curl_easy_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - NMLOG_DEBUG("curlopt ipversion = IPv4 reqtyp = %s", headReq? "HEAD":"GET"); + logmsg +=", IPv4"; } else if (IP_ADDRESS_V6 == ipversion) { curlSetOpt(curl_easy_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); - NMLOG_DEBUG("curlopt ipversion = IPv6 reqtyp = %s", headReq? "HEAD":"GET"); + logmsg +=", IPv6"; } else - NMLOG_DEBUG("curlopt ipversion = whatever reqtyp = %s", headReq? "HEAD":"GET"); + logmsg +=", IPv4/IPv6"; if(interface == "wlan0") { curlSetOpt(curl_easy_handle, CURLOPT_INTERFACE, "wlan0"); - NMLOG_DEBUG("curlopt interface = wlan0"); + logmsg +=", wlan0"; } else if(interface == "eth0") { curlSetOpt(curl_easy_handle, CURLOPT_INTERFACE, "eth0"); - NMLOG_DEBUG("curlopt interface = eth0"); + logmsg +=", eth0"; } - + + curlSetOpt(curl_easy_handle, CURLOPT_PRIVATE, logmsg.c_str()); if(curlVerboseEnabled()) { curlSetOpt(curl_easy_handle, CURLOPT_VERBOSE, 1L); @@ -339,12 +349,19 @@ namespace WPEFramework } curl_easy_handles.push_back(curl_easy_handle); } + int handles, msgs_left; char *url = nullptr; - #if LIBCURL_VERSION_NUM < 0x074200 - int numfds, repeats = 0; - #endif - char *endpoint = nullptr; + char *endpntConf = nullptr; + if((current_time() - startTime) > 1000) // 1 sec + { + NMLOG_WARNING("curl init taken more than 1000 ms; ie: %d ms", (int)(current_time() - startTime)); + } + + /* The deadline variable represents the absolute time by which the curl_multi_perform + operation must complete.providing a hard limit for the network connectivity check */ + deadline = current_time() + timeout_ms; + while (1) { if (CURLM_OK != (mc = curl_multi_perform(curl_multi_handle, &handles))) @@ -357,7 +374,7 @@ namespace WPEFramework long response_code = -1; if (msg->msg != CURLMSG_DONE) continue; - curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &endpoint); + curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &endpntConf); if (CURLE_OK == msg->data.result) { if (curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &response_code) == CURLE_OK) { @@ -370,7 +387,7 @@ namespace WPEFramework } } else { - NMLOG_ERROR("endpoint = <%s> curl error = %d (%s)", endpoint, msg->data.result, curl_easy_strerror(msg->data.result)); + NMLOG_ERROR("%s, curl error = %d (%s)", endpntConf, msg->data.result, curl_easy_strerror(msg->data.result)); curlErrorCode = static_cast(msg->data.result); } http_responses.push_back(response_code); @@ -379,27 +396,11 @@ namespace WPEFramework time_now = current_time(); if (handles == 0 || time_now >= deadline) break; - #if LIBCURL_VERSION_NUM < 0x074200 - if (CURLM_OK != (mc = curl_multi_wait(curl_multi_handle, NULL, 0, deadline - time_now, &numfds))) - { - LOGERR("curl_multi_wait returned %d (%s)", mc, curl_multi_strerror(mc)); - break; - } - if (numfds == 0) - { - repeats++; - if (repeats > 1) - usleep(10*1000); /* sleep 10 ms */ - } - else - repeats = 0; - #else if (CURLM_OK != (mc = curl_multi_poll(curl_multi_handle, NULL, 0, deadline - time_now, NULL))) { NMLOG_ERROR("curl_multi_poll returned %d (%s)", mc, curl_multi_strerror(mc)); break; } - #endif } if(curlVerboseEnabled()) { @@ -409,7 +410,7 @@ namespace WPEFramework for (const auto& curl_easy_handle : curl_easy_handles) { - curl_easy_getinfo(curl_easy_handle, CURLINFO_PRIVATE, &endpoint); + curl_easy_getinfo(curl_easy_handle, CURLINFO_PRIVATE, &endpntConf); //LOG_DBG("endpoint = <%s> terminating attempt", endpoint); curl_multi_remove_handle(curl_multi_handle, curl_easy_handle); curl_easy_cleanup(curl_easy_handle); From 76bc7df332f079e043bdde0cf5549fe6c654cf3a Mon Sep 17 00:00:00 2001 From: jincysam87 <167995204+jincysam87@users.noreply.github.com> Date: Thu, 13 Mar 2025 22:34:24 -0400 Subject: [PATCH 101/271] RDK-56442: Implement Router Discovery Tool (#112) * RDK-56442: Implement Router Discovery Tool Reason for change: Implement a tool by using gupnp library to fetch gateway details Test Procedure: Gateway details will be available in log file Risk: Low --- CMakeLists.txt | 3 + upnp/CMakeLists.txt | 43 +++++ upnp/UpnpDiscoveryManager.cpp | 199 +++++++++++++++++++++ upnp/UpnpDiscoveryManager.h | 76 ++++++++ upnp/cmake/Findtelemetry_msgsender.cmake | 37 ++++ upnp/scripts/getRouterInfo-NMdispatcher.sh | 28 +++ upnp/scripts/getRouterInfo-nlmon.sh | 39 ++++ upnp/scripts/readyToGetRouterInfo.sh | 29 +++ upnp/scripts/routerDiscovery@.service | 6 + 9 files changed, 460 insertions(+) create mode 100644 upnp/CMakeLists.txt create mode 100644 upnp/UpnpDiscoveryManager.cpp create mode 100644 upnp/UpnpDiscoveryManager.h create mode 100644 upnp/cmake/Findtelemetry_msgsender.cmake create mode 100644 upnp/scripts/getRouterInfo-NMdispatcher.sh create mode 100644 upnp/scripts/getRouterInfo-nlmon.sh create mode 100644 upnp/scripts/readyToGetRouterInfo.sh create mode 100644 upnp/scripts/routerDiscovery@.service diff --git a/CMakeLists.txt b/CMakeLists.txt index 083cae825..76a26f4a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -208,3 +208,6 @@ if(ENABLE_UNIT_TESTING) include(Tests/unit_test/unit_tests.cmake) endif(ENABLE_UNIT_TESTING) +if(ENABLE_ROUTER_DISCOVERY_TOOL) + add_subdirectory(upnp) +endif(ENABLE_ROUTER_DISCOVERY_TOOL) diff --git a/upnp/CMakeLists.txt b/upnp/CMakeLists.txt new file mode 100644 index 000000000..e2a7d133e --- /dev/null +++ b/upnp/CMakeLists.txt @@ -0,0 +1,43 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2025 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# +cmake_minimum_required(VERSION 3.3) + +set(MODULE_NAME routerDiscovery) +find_package(PkgConfig REQUIRED) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") + +pkg_check_modules(GLIB REQUIRED glib-2.0) +pkg_check_modules(LIBSOUP REQUIRED libsoup-2.4) +pkg_check_modules(GUPNP REQUIRED gupnp-1.0) +pkg_check_modules(GSSDP REQUIRED gssdp-1.2) + +if (USE_TELEMETRY) + find_package(telemetry_msgsender REQUIRED) + add_definitions(-DUSE_TELEMETRY) + include_directories(${TELEMETRY_INCLUDE_DIRS}) +endif (USE_TELEMETRY) + +add_executable(${MODULE_NAME} UpnpDiscoveryManager.cpp) +target_include_directories(${MODULE_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${GLIB_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS} ${GUPNP_INCLUDE_DIRS} ${GSSDP_INCLUDE_DIRS}) +target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES} ${LIBSOUP_LIBRARIES} ${GUPNP_LIBRARIES} ${GSSDP_LIBRARIES}) + +if (USE_TELEMETRY) + target_link_libraries(${MODULE_NAME} PRIVATE ${TELEMETRY_LIBRARIES}) +endif (USE_TELEMETRY) diff --git a/upnp/UpnpDiscoveryManager.cpp b/upnp/UpnpDiscoveryManager.cpp new file mode 100644 index 000000000..c1e1f1b7b --- /dev/null +++ b/upnp/UpnpDiscoveryManager.cpp @@ -0,0 +1,199 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2025 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include +#include "UpnpDiscoveryManager.h" + +UpnpDiscoveryManager::UpnpDiscoveryManager() +{ + m_context = NULL; + m_controlPoint = NULL; + m_mainLoop = NULL; + m_gatewayDetails.str(""); + m_gatewayDetails.clear(); + m_deviceInternetGateway = "urn:schemas-upnp-org:device:InternetGatewayDevice:1"; +#if USE_TELEMETRY + // Initialize Telemtry + t2_init("upnpdiscover"); +#endif +} + +UpnpDiscoveryManager::~UpnpDiscoveryManager() +{ + if (m_controlPoint) + g_object_unref(m_controlPoint); + if (m_context) + g_object_unref(m_context); + if (m_mainLoop) + { + g_main_loop_quit(m_mainLoop); + g_main_loop_unref(m_mainLoop); + } +} + +/* @brief Initialise GUPNP context */ +gboolean UpnpDiscoveryManager::initialiseUpnp(const std::string& interface) +{ + GError *error = NULL; + uint8_t errCount = 0; + + do + { + // Create a gupnp context + m_context = gupnp_context_new(NULL, interface.c_str(), UPNP_DISCOVERY_PORT, &error); + if (!m_context) + { + LOG_ERR("Error creating Upnp context: %s", error->message); + g_clear_error(&error); + errCount++; + sleep(2); + } + } while ((m_context == NULL) && (errCount < UPNP_MAX_CONTEXT_FAIL)); + if (errCount == UPNP_MAX_CONTEXT_FAIL) + { + LOG_ERR("Context creation failed"); + return false; + } + + // Create a control point for InternetGatewayDevice + m_controlPoint = gupnp_control_point_new(m_context, m_deviceInternetGateway.c_str()); + if (!m_controlPoint) + { + LOG_ERR("Error creating control point"); + return false; + } + + // Connects a callback function to a signal for InternetGatewayDevice + g_signal_connect(m_controlPoint, "device-proxy-available", + G_CALLBACK(&UpnpDiscoveryManager::deviceProxyAvailableCallback), this); + return true; +} + +/* @brief Telemetry Logging */ +void UpnpDiscoveryManager::logTelemetry(std::string message) +{ +#if USE_TELEMETRY + //T2 telemtery logging + T2ERROR t2error = t2_event_s("Router_Discovered", (char*)message.c_str()); + if (t2error != T2ERROR_SUCCESS) + { + LOG_ERR("t2_event_s(\"%s\", \"%s\") returned error code %d", "Router_Discovered", message.c_str(), t2error); + } +#endif +} + +/* @brief SSDP Discovery Timeout */ +gboolean UpnpDiscoveryManager::discoveryTimeout(void *arg) +{ + auto manager = static_cast(arg); + manager->stopSearchGatewayDevice(); + manager->m_gatewayDetails << "Unknown"; + LOG_INFO("Router_Discovered : %s", manager->m_gatewayDetails.str().c_str()); + manager->logTelemetry(manager->m_gatewayDetails.str().c_str()); + manager->exitWait(); + return true; +} + +/* @brief Find the gateway details by sending SSDP discovery on wifi/ethernet interface */ +bool UpnpDiscoveryManager::findGatewayDevice(const std::string& interface) +{ + m_interface = interface; + //Initialise gupnp context + if (true == initialiseUpnp(interface)) + { + //Create timer to handle upnp discovery timeout + g_timeout_add_seconds (UPNP_DISCOVERY_TIMEOUT_IN_SEC, GSourceFunc(&UpnpDiscoveryManager::discoveryTimeout), this); + // Start discovery to find InternetGatewayDevice + gssdp_resource_browser_set_active(GSSDP_RESOURCE_BROWSER(m_controlPoint), TRUE); + return true; + } + else + { + m_gatewayDetails << "Unknown"; + LOG_INFO("Router_Discovered : %s", m_gatewayDetails.str().c_str()); + logTelemetry(m_gatewayDetails.str().c_str()); + return false; + } +} + +/* @brief Callback getting invoked when SSDP reply is received from gateway */ +void UpnpDiscoveryManager::on_device_proxy_available(GUPnPControlPoint *controlPoint, GUPnPDeviceProxy *proxy) +{ + m_apMake = gupnp_device_info_get_manufacturer(GUPNP_DEVICE_INFO(proxy)); + m_apModelName = gupnp_device_info_get_model_name(GUPNP_DEVICE_INFO(proxy)); + m_apModelNumber = gupnp_device_info_get_model_number(GUPNP_DEVICE_INFO(proxy)); + // Remove the string after symbol <,> For example: NETGEAR,Inc. + m_apMake = m_apMake.substr(0, m_apMake.find(',')); + m_apModelName = m_apModelName.substr(0, m_apModelName.find(',')); + m_apModelNumber = m_apModelNumber.substr(0, m_apModelNumber.find(',')); + // Stop discovery to find InternetGatewayDevice + stopSearchGatewayDevice(); + m_gatewayDetails << m_apMake << "," << m_apModelName << "," << m_apModelNumber; + LOG_INFO("Router_Discovered : %s", m_gatewayDetails.str().c_str()); + if (m_gatewayDetails.str().length() >= UPNP_T2_EVENT_DATA_LEN) + { + m_gatewayDetails.str(""); + m_gatewayDetails.clear(); + m_gatewayDetails << m_apModelName << "," << m_apModelNumber; + } + logTelemetry(m_gatewayDetails.str()); + exitWait(); +} + +/* @brief Stop sending SSDP discovery */ +void UpnpDiscoveryManager::stopSearchGatewayDevice() +{ + gssdp_resource_browser_set_active(GSSDP_RESOURCE_BROWSER(m_controlPoint), FALSE); +} + +/* @brief Wait in gmain() loop */ +void UpnpDiscoveryManager::enterWait() +{ + m_mainLoop = g_main_loop_new(NULL, FALSE); + // gmain loop need to be running for upnp discovery + g_main_loop_run(m_mainLoop); +} + +/* @brief Exit the gmain() loop */ +void UpnpDiscoveryManager::exitWait() +{ + if (m_mainLoop) + { + g_main_loop_quit(m_mainLoop); + g_main_loop_unref(m_mainLoop); + m_mainLoop = NULL; + } +} + +int main(int argc, char *argv[]) +{ + if (argc < 2) + { + LOG_INFO("Usage: %s ", argv[0]); + return 1; + } + UpnpDiscoveryManager ssdpDiscover; + LOG_INFO("SSDP discover to fetch InternetGatewayDevice on interface %s", argv[1]); + if (true == ssdpDiscover.findGatewayDevice(argv[1])) + { + ssdpDiscover.enterWait(); + return 0; + } + return 1; +} diff --git a/upnp/UpnpDiscoveryManager.h b/upnp/UpnpDiscoveryManager.h new file mode 100644 index 000000000..55b3f0584 --- /dev/null +++ b/upnp/UpnpDiscoveryManager.h @@ -0,0 +1,76 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2025 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#ifndef __UPNPDISCOVERYMANAGER_H__ +#define __UPNPDISCOVERYMANAGER_H__ + +#include +#include +#include +#if USE_TELEMETRY +#include +#endif + +#define LOG_ERR(msg, ...) g_printerr("ERROR: " msg "\n", ##__VA_ARGS__) +#define LOG_INFO(msg, ...) g_print("INFO: " msg "\n", ##__VA_ARGS__) + +#define UPNP_MAX_CONTEXT_FAIL 15 +#define UPNP_T2_EVENT_DATA_LEN 128 + +class UpnpDiscoveryManager +{ +public: + UpnpDiscoveryManager(); + ~UpnpDiscoveryManager(); + /* @brief Find the gateway details by sending SSDP discovery on wifi/ethernet interface */ + bool findGatewayDevice(const std::string& interface); + /* @brief Wait in gmain() loop */ + void enterWait(); + +private: + /* @brief Telemetry Logging */ + void logTelemetry(std::string message); + /* @brief SSDP Discovery Timeout */ + static gboolean discoveryTimeout(void* arg); + /* @brief Exit the gmain() loop */ + void exitWait(); + /* @brief Initialise GUPNP context */ + gboolean initialiseUpnp(const std::string& interface); + /* @brief Stop sending SSDP discovery */ + void stopSearchGatewayDevice(); + /* @brief Callback getting invoked when SSDP reply is received from gateway */ + void on_device_proxy_available(GUPnPControlPoint *control_point, GUPnPDeviceProxy *proxy); + static void deviceProxyAvailableCallback(GUPnPControlPoint *control_point, GUPnPDeviceProxy *proxy, gpointer user_data) + { + auto* self = static_cast(user_data); + self->on_device_proxy_available(control_point, proxy); + } + GUPnPContext* m_context; + GUPnPControlPoint* m_controlPoint; + GMainLoop* m_mainLoop; + std::string m_interface; + std::string m_apMake; + std::string m_apModelName; + std::string m_apModelNumber; + std::ostringstream m_gatewayDetails; + std::string m_deviceInternetGateway; + static const guint UPNP_DISCOVERY_PORT = 1901; + static const int UPNP_DISCOVERY_TIMEOUT_IN_SEC = 180; +}; +#endif /* __UPNPDISCOVERYMANAGER_H__ */ diff --git a/upnp/cmake/Findtelemetry_msgsender.cmake b/upnp/cmake/Findtelemetry_msgsender.cmake new file mode 100644 index 000000000..64ef7f51a --- /dev/null +++ b/upnp/cmake/Findtelemetry_msgsender.cmake @@ -0,0 +1,37 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2023 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# + +find_package(PkgConfig) + +find_library(TELEMETRY_LIBRARIES NAMES telemetry_msgsender) +find_path(TELEMETRY_INCLUDE_DIRS NAMES telemetry_busmessage_sender.h) + +set(TELEMETRY_LIBRARIES ${TELEMETRY_LIBRARIES} CACHE PATH "Path to telemetry library") +set(TELEMETRY_INCLUDE_DIRS ${TELEMETRY_INCLUDE_DIRS} ) +set(TELEMETRY_INCLUDE_DIRS ${TELEMETRY_INCLUDE_DIRS} CACHE PATH "Path to telemetry include") + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(TELEMETRY DEFAULT_MSG TELEMETRY_INCLUDE_DIRS TELEMETRY_LIBRARIES) + +mark_as_advanced( + TELEMETRY_FOUND + TELEMETRY_INCLUDE_DIRS + TELEMETRY_LIBRARIES + TELEMETRY_LIBRARY_DIRS + TELEMETRY_FLAGS) diff --git a/upnp/scripts/getRouterInfo-NMdispatcher.sh b/upnp/scripts/getRouterInfo-NMdispatcher.sh new file mode 100644 index 000000000..11872b793 --- /dev/null +++ b/upnp/scripts/getRouterInfo-NMdispatcher.sh @@ -0,0 +1,28 @@ +#!/bin/sh +############################################################################## +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2025 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################## +. /etc/device.properties + +ifc=$1 +pid=`pidof routerDiscovery` +if [ -n "$pid" ]; then + kill -9 $pid +fi +echo "Starting routerDiscovery on $ifc" >> /opt/logs/routerInfo.log +systemctl start routerDiscovery@$ifc diff --git a/upnp/scripts/getRouterInfo-nlmon.sh b/upnp/scripts/getRouterInfo-nlmon.sh new file mode 100644 index 000000000..2d9345199 --- /dev/null +++ b/upnp/scripts/getRouterInfo-nlmon.sh @@ -0,0 +1,39 @@ +#!/bin/sh +############################################################################## +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2025 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################## +. /etc/device.properties + +cmd=$1 +mode=$2 +ifc=$3 +flags=$5 +file="/tmp/.routerdiscover" +if [[ "$ifc" == "$WIFI_INTERFACE" || "$ifc" == "$ETHERNET_INTERFACE" ]]; then + if [ "$cmd" == "add" ] && [ "$flags" = "global" ]; then + if [ ! -f $file ]; then + touch /tmp/.routerdiscover + pid=`pidof routerDiscovery` + if [ -n "$pid" ]; then + kill -9 $pid + fi + echo "Starting routerDiscovery on $ifc" >> /opt/logs/routerInfo.log + systemctl start routerDiscovery@$ifc + fi + fi +fi diff --git a/upnp/scripts/readyToGetRouterInfo.sh b/upnp/scripts/readyToGetRouterInfo.sh new file mode 100644 index 000000000..b7ce58b94 --- /dev/null +++ b/upnp/scripts/readyToGetRouterInfo.sh @@ -0,0 +1,29 @@ +#!/bin/sh +############################################################################## +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2025 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################## +. /etc/device.properties + +ifc=$1 +file="/tmp/.routerdiscover" +if [[ "$ifc" == "$WIFI_INTERFACE" || "$ifc" == "$ETHERNET_INTERFACE" ]]; then + if [ -f "$file" ]; then + echo "Ready to read router details" >> /opt/logs/routerInfo.log + rm "$file" + fi +fi diff --git a/upnp/scripts/routerDiscovery@.service b/upnp/scripts/routerDiscovery@.service new file mode 100644 index 000000000..78a1a4f20 --- /dev/null +++ b/upnp/scripts/routerDiscovery@.service @@ -0,0 +1,6 @@ +[Unit] +Description=Router Discovery Service %i + +[Service] +Type=simple +ExecStart=/usr/bin/routerDiscovery %i From e6050e3ec32a3f387512e229248563e63687d34c Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Tue, 18 Mar 2025 19:30:18 -0400 Subject: [PATCH 102/271] Re-structure the source & header file locations (#119) * Re-positioned the source files, header files, unittest code & the tools. Signed-off-by: kamirt573_comcast --- .github/workflows/rdk_unit_test.yml | 12 +- CMakeLists.txt | 177 ++---------------- Tests/mocks/thunder/Module.cpp | 3 - Tests/mocks/thunder/Module.h | 8 - Tests/mocks/thunder/ThunderPortability.h | 13 -- definition/CMakeLists.txt | 29 +++ .../NetworkManager.json | 0 interface/CMakeLists.txt | 32 ++++ .../INetworkManager.h | 0 legacy/CMakeLists.txt | 80 ++++++++ .../LegacyNetworkAPIs.conf.in | 0 .../LegacyNetworkAPIs.config | 0 .../LegacyNetworkAPIs.cpp | 2 +- .../LegacyNetworkAPIs.h | 0 .../LegacyWiFiManagerAPIs.conf.in | 0 .../LegacyWiFiManagerAPIs.config | 0 .../LegacyWiFiManagerAPIs.cpp | 2 +- .../LegacyWiFiManagerAPIs.h | 0 plugin/CMakeLists.txt | 119 ++++++++++++ Module.cpp => plugin/Module.cpp | 0 Module.h => plugin/Module.h | 0 .../NetworkManager.conf.in | 0 .../NetworkManager.config | 0 .../NetworkManager.cpp | 0 NetworkManager.h => plugin/NetworkManager.h | 0 .../NetworkManagerConnectivity.cpp | 0 .../NetworkManagerConnectivity.h | 0 .../NetworkManagerImplementation.cpp | 0 .../NetworkManagerImplementation.h | 0 .../NetworkManagerJsonEnum.h | 0 .../NetworkManagerJsonRpc.cpp | 0 .../NetworkManagerLogger.cpp | 0 .../NetworkManagerLogger.h | 0 .../NetworkManagerSecretAgent.cpp | 0 .../NetworkManagerSecretAgent.h | 0 .../NetworkManagerStunClient.cpp | 0 .../NetworkManagerStunClient.h | 0 .../NetworkManagerTimer.h | 0 .../gnome/NetworkManagerGnomeEvents.cpp | 0 .../gnome/NetworkManagerGnomeEvents.h | 0 .../gnome/NetworkManagerGnomeProxy.cpp | 0 .../gnome/NetworkManagerGnomeUtils.cpp | 0 .../gnome/NetworkManagerGnomeUtils.h | 0 .../gnome/NetworkManagerGnomeWIFI.cpp | 0 .../gnome/NetworkManagerGnomeWIFI.h | 0 .../gdbus}/NetworkManagerGdbusClient.cpp | 0 .../gnome/gdbus}/NetworkManagerGdbusClient.h | 0 .../gnome/gdbus}/NetworkManagerGdbusEvent.cpp | 0 .../gnome/gdbus}/NetworkManagerGdbusEvent.h | 0 .../gnome/gdbus}/NetworkManagerGdbusMgr.cpp | 0 .../gnome/gdbus}/NetworkManagerGdbusMgr.h | 0 .../gnome/gdbus}/NetworkManagerGdbusProxy.cpp | 0 .../gnome/gdbus}/NetworkManagerGdbusUtils.cpp | 0 .../gnome/gdbus}/NetworkManagerGdbusUtils.h | 0 .../rdk/NetworkManagerRDKProxy.cpp | 0 {Tests => tests}/mocks/Iarm.cpp | 19 ++ {Tests => tests}/mocks/Iarm.h | 19 ++ {Tests => tests}/mocks/IarmBusMock.h | 19 ++ {Tests => tests}/mocks/thunder/COMLinkMock.h | 19 ++ .../mocks/thunder/DispatcherMock.h | 19 ++ .../mocks/thunder/FactoriesImplementation.h | 18 ++ tests/mocks/thunder/Module.cpp | 22 +++ tests/mocks/thunder/Module.h | 27 +++ {Tests => tests}/mocks/thunder/ServiceMock.h | 19 ++ {Tests => tests}/mocks/thunder/SystemInfo.h | 19 ++ tests/mocks/thunder/ThunderPortability.h | 32 ++++ .../mocks/thunder/WorkerPoolImplementation.h | 19 ++ .../thunder/Remove-SmartLinkType.patch | 0 .../unittest/CMakeLists.txt | 100 ++++++---- .../test_LegacyPlugin_NetworkAPIs.cpp | 21 ++- .../test_LegacyPlugin_WiFiManagerAPIs.cpp | 21 ++- .../unittest}/test_NetworkManager.cpp | 19 ++ .../test_NetworkManagerConnectivity.cpp | 2 +- .../test_NetworkManagerStunClient.cpp | 2 +- .../test_WiFiSignalStrengthMonitor.cpp | 2 +- tools/CMakeLists.txt | 30 +++ .../plugincli/CMakeLists.txt | 2 +- .../plugincli}/NetworkManagerGdbusTest.cpp | 0 {upnp => tools/upnp}/CMakeLists.txt | 0 {upnp => tools/upnp}/UpnpDiscoveryManager.cpp | 0 {upnp => tools/upnp}/UpnpDiscoveryManager.h | 0 .../upnp}/cmake/Findtelemetry_msgsender.cmake | 0 .../scripts/getRouterInfo-NMdispatcher.sh | 0 .../upnp}/scripts/getRouterInfo-nlmon.sh | 0 .../upnp}/scripts/readyToGetRouterInfo.sh | 0 .../upnp}/scripts/routerDiscovery@.service | 0 86 files changed, 682 insertions(+), 245 deletions(-) delete mode 100644 Tests/mocks/thunder/Module.cpp delete mode 100644 Tests/mocks/thunder/Module.h delete mode 100644 Tests/mocks/thunder/ThunderPortability.h create mode 100644 definition/CMakeLists.txt rename NetworkManager.json => definition/NetworkManager.json (100%) create mode 100644 interface/CMakeLists.txt rename INetworkManager.h => interface/INetworkManager.h (100%) create mode 100644 legacy/CMakeLists.txt rename LegacyPlugin_NetworkAPIs.conf.in => legacy/LegacyNetworkAPIs.conf.in (100%) rename LegacyPlugin_NetworkAPIs.config => legacy/LegacyNetworkAPIs.config (100%) rename LegacyPlugin_NetworkAPIs.cpp => legacy/LegacyNetworkAPIs.cpp (99%) rename LegacyPlugin_NetworkAPIs.h => legacy/LegacyNetworkAPIs.h (100%) rename LegacyPlugin_WiFiManagerAPIs.conf.in => legacy/LegacyWiFiManagerAPIs.conf.in (100%) rename LegacyPlugin_WiFiManagerAPIs.config => legacy/LegacyWiFiManagerAPIs.config (100%) rename LegacyPlugin_WiFiManagerAPIs.cpp => legacy/LegacyWiFiManagerAPIs.cpp (99%) rename LegacyPlugin_WiFiManagerAPIs.h => legacy/LegacyWiFiManagerAPIs.h (100%) create mode 100644 plugin/CMakeLists.txt rename Module.cpp => plugin/Module.cpp (100%) rename Module.h => plugin/Module.h (100%) rename NetworkManager.conf.in => plugin/NetworkManager.conf.in (100%) rename NetworkManager.config => plugin/NetworkManager.config (100%) rename NetworkManager.cpp => plugin/NetworkManager.cpp (100%) rename NetworkManager.h => plugin/NetworkManager.h (100%) rename NetworkManagerConnectivity.cpp => plugin/NetworkManagerConnectivity.cpp (100%) rename NetworkManagerConnectivity.h => plugin/NetworkManagerConnectivity.h (100%) rename NetworkManagerImplementation.cpp => plugin/NetworkManagerImplementation.cpp (100%) rename NetworkManagerImplementation.h => plugin/NetworkManagerImplementation.h (100%) rename NetworkManagerJsonEnum.h => plugin/NetworkManagerJsonEnum.h (100%) rename NetworkManagerJsonRpc.cpp => plugin/NetworkManagerJsonRpc.cpp (100%) rename NetworkManagerLogger.cpp => plugin/NetworkManagerLogger.cpp (100%) rename NetworkManagerLogger.h => plugin/NetworkManagerLogger.h (100%) rename NetworkManagerSecretAgent.cpp => plugin/NetworkManagerSecretAgent.cpp (100%) rename NetworkManagerSecretAgent.h => plugin/NetworkManagerSecretAgent.h (100%) rename NetworkManagerStunClient.cpp => plugin/NetworkManagerStunClient.cpp (100%) rename NetworkManagerStunClient.h => plugin/NetworkManagerStunClient.h (100%) rename NetworkManagerTimer.h => plugin/NetworkManagerTimer.h (100%) rename NetworkManagerGnomeEvents.cpp => plugin/gnome/NetworkManagerGnomeEvents.cpp (100%) rename NetworkManagerGnomeEvents.h => plugin/gnome/NetworkManagerGnomeEvents.h (100%) rename NetworkManagerGnomeProxy.cpp => plugin/gnome/NetworkManagerGnomeProxy.cpp (100%) rename NetworkManagerGnomeUtils.cpp => plugin/gnome/NetworkManagerGnomeUtils.cpp (100%) rename NetworkManagerGnomeUtils.h => plugin/gnome/NetworkManagerGnomeUtils.h (100%) rename NetworkManagerGnomeWIFI.cpp => plugin/gnome/NetworkManagerGnomeWIFI.cpp (100%) rename NetworkManagerGnomeWIFI.h => plugin/gnome/NetworkManagerGnomeWIFI.h (100%) rename {gdbus => plugin/gnome/gdbus}/NetworkManagerGdbusClient.cpp (100%) rename {gdbus => plugin/gnome/gdbus}/NetworkManagerGdbusClient.h (100%) rename {gdbus => plugin/gnome/gdbus}/NetworkManagerGdbusEvent.cpp (100%) rename {gdbus => plugin/gnome/gdbus}/NetworkManagerGdbusEvent.h (100%) rename {gdbus => plugin/gnome/gdbus}/NetworkManagerGdbusMgr.cpp (100%) rename {gdbus => plugin/gnome/gdbus}/NetworkManagerGdbusMgr.h (100%) rename {gdbus => plugin/gnome/gdbus}/NetworkManagerGdbusProxy.cpp (100%) rename {gdbus => plugin/gnome/gdbus}/NetworkManagerGdbusUtils.cpp (100%) rename {gdbus => plugin/gnome/gdbus}/NetworkManagerGdbusUtils.h (100%) rename NetworkManagerRDKProxy.cpp => plugin/rdk/NetworkManagerRDKProxy.cpp (100%) rename {Tests => tests}/mocks/Iarm.cpp (85%) rename {Tests => tests}/mocks/Iarm.h (83%) rename {Tests => tests}/mocks/IarmBusMock.h (83%) rename {Tests => tests}/mocks/thunder/COMLinkMock.h (52%) rename {Tests => tests}/mocks/thunder/DispatcherMock.h (52%) rename {Tests => tests}/mocks/thunder/FactoriesImplementation.h (74%) create mode 100644 tests/mocks/thunder/Module.cpp create mode 100644 tests/mocks/thunder/Module.h rename {Tests => tests}/mocks/thunder/ServiceMock.h (83%) rename {Tests => tests}/mocks/thunder/SystemInfo.h (77%) create mode 100644 tests/mocks/thunder/ThunderPortability.h rename {Tests => tests}/mocks/thunder/WorkerPoolImplementation.h (63%) rename {Tests => tests}/patches/thunder/Remove-SmartLinkType.patch (100%) rename Tests/unit_test/unit_tests.cmake => tests/unittest/CMakeLists.txt (52%) rename {Tests/unit_test => tests/unittest}/test_LegacyPlugin_NetworkAPIs.cpp (77%) rename {Tests/unit_test => tests/unittest}/test_LegacyPlugin_WiFiManagerAPIs.cpp (86%) rename {Tests/unit_test => tests/unittest}/test_NetworkManager.cpp (91%) rename {Tests/unit_test => tests/unittest}/test_NetworkManagerConnectivity.cpp (98%) rename {Tests/unit_test => tests/unittest}/test_NetworkManagerStunClient.cpp (98%) rename {Tests/unit_test => tests/unittest}/test_WiFiSignalStrengthMonitor.cpp (98%) create mode 100644 tools/CMakeLists.txt rename Tests/raspberrypi/NetworkManagerGdbusTest.cmake => tools/plugincli/CMakeLists.txt (98%) rename {Tests/raspberrypi => tools/plugincli}/NetworkManagerGdbusTest.cpp (100%) rename {upnp => tools/upnp}/CMakeLists.txt (100%) rename {upnp => tools/upnp}/UpnpDiscoveryManager.cpp (100%) rename {upnp => tools/upnp}/UpnpDiscoveryManager.h (100%) rename {upnp => tools/upnp}/cmake/Findtelemetry_msgsender.cmake (100%) rename {upnp => tools/upnp}/scripts/getRouterInfo-NMdispatcher.sh (100%) rename {upnp => tools/upnp}/scripts/getRouterInfo-nlmon.sh (100%) rename {upnp => tools/upnp}/scripts/readyToGetRouterInfo.sh (100%) rename {upnp => tools/upnp}/scripts/routerDiscovery@.service (100%) diff --git a/.github/workflows/rdk_unit_test.yml b/.github/workflows/rdk_unit_test.yml index eab2497af..3a98536e6 100644 --- a/.github/workflows/rdk_unit_test.yml +++ b/.github/workflows/rdk_unit_test.yml @@ -44,7 +44,7 @@ jobs: - name: Apply Thunder Patches run: | cd ${{github.workspace}}/Thunder - git apply ${{github.workspace}}/networkmanager/Tests/patches/thunder/Remove-SmartLinkType.patch + git apply ${{github.workspace}}/networkmanager/tests/patches/thunder/Remove-SmartLinkType.patch - name: Build ThunderTools run: > @@ -73,7 +73,7 @@ jobs: touch install/usr/lib/libIARMBus.so mkdir -p install/usr/include/rdk/iarmbus touch install/usr/include/rdk/iarmbus/libIARM.h - cd "${{github.workspace}}/networkmanager/Tests/" + cd "${{github.workspace}}/networkmanager/tests/" mkdir -p headers/rdk/iarmbus cd headers touch rdk/iarmbus/libIARM.h rdk/iarmbus/libIBus.h @@ -87,9 +87,9 @@ jobs: -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" -DCMAKE_CXX_FLAGS=" - -I ${{github.workspace}}/networkmanager/Tests/headers - -I ${{github.workspace}}/networkmanager/Tests/headers/rdk/iarmbus - --include ${{github.workspace}}/networkmanager/Tests/mocks/Iarm.h + -I ${{github.workspace}}/networkmanager/tests/headers + -I ${{github.workspace}}/networkmanager/tests/headers/rdk/iarmbus + --include ${{github.workspace}}/networkmanager/tests/mocks/Iarm.h " -DENABLE_UNIT_TESTING=ON && @@ -124,7 +124,7 @@ jobs: run: | lcov -c -o coverage.info -d build/RDKNetworkmanager lcov -r coverage.info '/usr/include/*' '*/build/RDKNetworkmanager/*' \ - '*/install/usr/include/*' '*/Tests/*' 'googlemock/*' 'googletest/*' \ + '*/install/usr/include/*' '*/tests/*' 'googlemock/*' 'googletest/*' \ -o filtered_coverage.info - name: Generate the html report run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 76a26f4a1..24ed09f33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,180 +34,25 @@ set(PROJECT_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) include(CmakeHelperFunctions) -option(USE_RDK_LOGGER "Enable RDK Logger for logging" OFF ) -option(ENABLE_UNIT_TESTING "Enable unit tests" OFF) - - string(TOLOWER ${NAMESPACE} STORAGE_DIRECTORY) get_directory_property(SEVICES_DEFINES COMPILE_DEFINITIONS) -set(PLUGIN_NAME NetworkManager) -set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) -set(PLUGIN_LEGACY_DEPRECATED_NETWORK ${NAMESPACE}Network) -set(PLUGIN_LEGACY_DEPRECATED_WIFI ${NAMESPACE}WiFiManager) - -find_package(${NAMESPACE}Core REQUIRED) -find_package(${NAMESPACE}Plugins REQUIRED) -find_package(CURL) - -set(PLUGIN_NETWORKMANAGER_STARTUPORDER "25" CACHE STRING "To configure startup order of Unified NetworkManager plugin") -set(PLUGIN_LEGACY_NW_STARTUPORDER "35" CACHE STRING "To configure startup order of Legacy Network plugin") -set(PLUGIN_LEGACY_WIFI_STARTUPORDER "35" CACHE STRING "To configure startup order of Legacy WiFi plugin") - -set(PLUGIN_BUILD_REFERENCE ${PROJECT_VERSION} CACHE STRING "To Set the Hash for the plugin") -add_definitions(-DPLUGIN_BUILD_REFERENCE=${PLUGIN_BUILD_REFERENCE}) - -if(ENABLE_GNOME_NETWORKMANAGER) -pkg_check_modules(GLIB REQUIRED glib-2.0) -pkg_check_modules(LIBNM REQUIRED libnm) -pkg_check_modules(GLIB REQUIRED gio-2.0) -else() -find_package(IARMBus REQUIRED) -endif () - - -message("Setup ProxyStub for INetworkManager.h") -find_package(CompileSettingsDebug CONFIG REQUIRED) -find_package(ProxyStubGenerator REQUIRED) -find_package(JsonGenerator REQUIRED) - -set(ProxyStubGenerator_DIR ${CMAKE_SYSROOT}${CMAKE_INSTALL_PREFIX}/tools/cmake ${ProxyStubGenerator_DIR}) - -if(NOT GENERATOR_SEARCH_PATH) - set(GENERATOR_SEARCH_PATH ${CMAKE_SYSROOT}${CMAKE_INSTALL_PREFIX}/include/${NAMESPACE}) -endif() - -message("The Search path is, ${GENERATOR_SEARCH_PATH}") -ProxyStubGenerator(INPUT "${CMAKE_CURRENT_SOURCE_DIR}" OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/generated" INCLUDE_PATH ${GENERATOR_SEARCH_PATH}) - -set(JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/NetworkManager.json") -JsonGenerator(CODE INPUT ${JSON_FILE} OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/generated" INCLUDE_PATH ${GENERATOR_SEARCH_PATH} CPPIFDIR "${CMAKE_CURRENT_SOURCE_DIR}" DOCS) - -file(GLOB PROXY_STUB_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/generated/ProxyStubs*.cpp") - -message("Setup ${PROJECT_NAME} v${PROJECT_VERSION}") - -set(PLUGIN_NETWORKMANAGER_LOGLEVEL "5" CACHE STRING "To configure default loglevel NetworkManager plugin") - -if (USE_RDK_LOGGER) - find_package(rdklogger REQUIRED) - add_definitions(-DUSE_RDK_LOGGER) - - include_directories(${RDKLOGGER_INCLUDE_DIRS}) -endif (USE_RDK_LOGGER) - -include_directories(${PROJECT_SOURCE_DIR}) -# Build the main plugin that runs inside the WPEFramework daemon -add_library(${MODULE_NAME} SHARED - NetworkManager.cpp - NetworkManagerJsonRpc.cpp - NetworkManagerLogger.cpp - NetworkManagerImplementation.cpp - NetworkManagerConnectivity.cpp - NetworkManagerStunClient.cpp - Module.cpp - ${PROXY_STUB_SOURCES}) - -target_link_libraries(${MODULE_NAME} PRIVATE - ${NAMESPACE}Core::${NAMESPACE}Core - ${NAMESPACE}Plugins::${NAMESPACE}Plugins - ) - -set_target_properties(${MODULE_NAME} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES - FRAMEWORK FALSE) - - -if(ENABLE_GNOME_NETWORKMANAGER) - if(ENABLE_GNOME_GDBUS) - message("networkmanager building with gdbus") - target_sources(${MODULE_NAME} PRIVATE - gdbus/NetworkManagerGdbusProxy.cpp - gdbus/NetworkManagerGdbusClient.cpp - gdbus/NetworkManagerGdbusEvent.cpp - gdbus/NetworkManagerGdbusMgr.cpp - gdbus/NetworkManagerGdbusUtils.cpp - NetworkManagerSecretAgent.cpp ) - target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) - target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES} ${GIO_LIBRARIES} uuid) - else() - message("networkmanager building with libnm") - target_sources(${MODULE_NAME} PRIVATE - NetworkManagerGnomeProxy.cpp - NetworkManagerGnomeWIFI.cpp - NetworkManagerGnomeEvents.cpp - NetworkManagerGnomeUtils.cpp - NetworkManagerSecretAgent.cpp ) - target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) - target_link_libraries(${MODULE_NAME} PRIVATE ${LIBNM_LIBRARIES}) - endif() -else() - message("networkmanager building with netsrvmgr") - target_sources(${MODULE_NAME} PRIVATE NetworkManagerRDKProxy.cpp) - target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) - target_link_libraries(${MODULE_NAME} PRIVATE ${IARMBUS_LIBRARIES}) -endif() - -target_link_libraries(${MODULE_NAME} PRIVATE ${CURL_LIBRARIES}) -target_include_directories(${MODULE_NAME} PRIVATE ${CURL_INCLUDE_DIRS}) - -if (USE_RDK_LOGGER) - target_link_libraries(${MODULE_NAME} PRIVATE ${RDKLOGGER_LIBRARIES}) -endif (USE_RDK_LOGGER) - -install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) - -add_library(${PLUGIN_LEGACY_DEPRECATED_NETWORK} SHARED - LegacyPlugin_NetworkAPIs.cpp - NetworkManagerLogger.cpp - Module.cpp -) - -target_link_libraries(${PLUGIN_LEGACY_DEPRECATED_NETWORK} PRIVATE - ${NAMESPACE}Core::${NAMESPACE}Core - ${NAMESPACE}Plugins::${NAMESPACE}Plugins - ) - -if (USE_RDK_LOGGER) - target_link_libraries(${PLUGIN_LEGACY_DEPRECATED_NETWORK} PRIVATE ${RDKLOGGER_LIBRARIES}) -endif (USE_RDK_LOGGER) - -set_target_properties(${PLUGIN_LEGACY_DEPRECATED_NETWORK} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES) - -install(TARGETS ${PLUGIN_LEGACY_DEPRECATED_NETWORK} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) - -add_library(${PLUGIN_LEGACY_DEPRECATED_WIFI} SHARED - LegacyPlugin_WiFiManagerAPIs.cpp - NetworkManagerLogger.cpp - Module.cpp -) - -target_link_libraries(${PLUGIN_LEGACY_DEPRECATED_WIFI} PRIVATE - ${NAMESPACE}Core::${NAMESPACE}Core - ${NAMESPACE}Plugins::${NAMESPACE}Plugins - ) +option(ENABLE_LEGACY_PLUGINS "Enable Legacy Plugins" ON) +option(USE_RDK_LOGGER "Enable RDK Logger for logging" OFF ) +option(ENABLE_UNIT_TESTING "Enable unit tests" OFF) -if (USE_RDK_LOGGER) - target_link_libraries(${PLUGIN_LEGACY_DEPRECATED_WIFI} PRIVATE ${RDKLOGGER_LIBRARIES}) -endif (USE_RDK_LOGGER) -set_target_properties(${PLUGIN_LEGACY_DEPRECATED_WIFI} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES) +add_subdirectory(interface) +add_subdirectory(definition) +add_subdirectory(plugin) -install(TARGETS ${PLUGIN_LEGACY_DEPRECATED_WIFI} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) +if (ENABLE_LEGACY_PLUGINS) + add_subdirectory(legacy) +endif (ENABLE_LEGACY_PLUGINS) -write_config() -write_config(PLUGINS LegacyPlugin_NetworkAPIs CLASSNAME Network LOCATOR lib${PLUGIN_LEGACY_DEPRECATED_NETWORK}.so) -write_config(PLUGINS LegacyPlugin_WiFiManagerAPIs CLASSNAME WiFiManager LOCATOR lib${PLUGIN_LEGACY_DEPRECATED_WIFI}.so) +add_subdirectory(tools) if(ENABLE_UNIT_TESTING) - include(Tests/unit_test/unit_tests.cmake) + add_subdirectory(tests/unittest) endif(ENABLE_UNIT_TESTING) -if(ENABLE_ROUTER_DISCOVERY_TOOL) - add_subdirectory(upnp) -endif(ENABLE_ROUTER_DISCOVERY_TOOL) diff --git a/Tests/mocks/thunder/Module.cpp b/Tests/mocks/thunder/Module.cpp deleted file mode 100644 index 2d85ed902..000000000 --- a/Tests/mocks/thunder/Module.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "Module.h" - -MODULE_NAME_DECLARATION(BUILD_REFERENCE) diff --git a/Tests/mocks/thunder/Module.h b/Tests/mocks/thunder/Module.h deleted file mode 100644 index b14a5086a..000000000 --- a/Tests/mocks/thunder/Module.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#ifndef MODULE_NAME -#define MODULE_NAME tests -#endif - -#include -#include diff --git a/Tests/mocks/thunder/ThunderPortability.h b/Tests/mocks/thunder/ThunderPortability.h deleted file mode 100644 index f0ddcf363..000000000 --- a/Tests/mocks/thunder/ThunderPortability.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include - -#define EVENT_SUBSCRIBE(__A__, __B__, __C__, __D__) { plugin->Subscribe(__A__, __B__, __C__); (void)__D__; } -#define EVENT_UNSUBSCRIBE(__A__, __B__, __C__, __D__) { plugin->Unsubscribe(__A__, __B__, __C__); (void)__D__; } - -#define DECL_CORE_JSONRPC_CONX Core::JSONRPC::Context -#define INIT_CONX(__X__, __Y__) connection(__X__, __Y__, "") -#define PLUGINHOST_DISPATCHER PluginHost::ILocalDispatcher -#define PLUGINHOST_DISPATCHER_ID PluginHost::ILocalDispatcher::ID - diff --git a/definition/CMakeLists.txt b/definition/CMakeLists.txt new file mode 100644 index 000000000..1bd873f20 --- /dev/null +++ b/definition/CMakeLists.txt @@ -0,0 +1,29 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2024 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# +message("Generate JsonRPC Documentation for NetworkManager.json") + +find_package(JsonGenerator REQUIRED) + +if(NOT GENERATOR_SEARCH_PATH) + set(GENERATOR_SEARCH_PATH ${CMAKE_SYSROOT}${CMAKE_INSTALL_PREFIX}/include/${NAMESPACE}) +endif() + +set(JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/NetworkManager.json") +JsonGenerator(CODE INPUT ${JSON_FILE} OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/generated" INCLUDE_PATH ${GENERATOR_SEARCH_PATH} CPPIFDIR "${CMAKE_CURRENT_SOURCE_DIR}" DOCS) + diff --git a/NetworkManager.json b/definition/NetworkManager.json similarity index 100% rename from NetworkManager.json rename to definition/NetworkManager.json diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt new file mode 100644 index 000000000..080eef63a --- /dev/null +++ b/interface/CMakeLists.txt @@ -0,0 +1,32 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2024 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# +message("Generate ProxyStub for INetworkManager.h") + +find_package(${NAMESPACE}Core REQUIRED) +find_package(${NAMESPACE}Plugins REQUIRED) +find_package(CompileSettingsDebug CONFIG REQUIRED) +find_package(ProxyStubGenerator REQUIRED) + +set(ProxyStubGenerator_DIR ${CMAKE_SYSROOT}${CMAKE_INSTALL_PREFIX}/tools/cmake ${ProxyStubGenerator_DIR}) + +if(NOT GENERATOR_SEARCH_PATH) + set(GENERATOR_SEARCH_PATH ${CMAKE_SYSROOT}${CMAKE_INSTALL_PREFIX}/include/${NAMESPACE}) +endif() + +ProxyStubGenerator(INPUT "${CMAKE_CURRENT_SOURCE_DIR}" OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/generated" INCLUDE_PATH ${GENERATOR_SEARCH_PATH}) diff --git a/INetworkManager.h b/interface/INetworkManager.h similarity index 100% rename from INetworkManager.h rename to interface/INetworkManager.h diff --git a/legacy/CMakeLists.txt b/legacy/CMakeLists.txt new file mode 100644 index 000000000..e3b11dd70 --- /dev/null +++ b/legacy/CMakeLists.txt @@ -0,0 +1,80 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2024 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# +message("Build Legacy Plugins") + +find_package(${NAMESPACE}Core REQUIRED) +find_package(${NAMESPACE}Plugins REQUIRED) + +set(PLUGIN_LEGACY_NETWORK ${NAMESPACE}Network) +set(PLUGIN_LEGACY_WIFI ${NAMESPACE}WiFiManager) + +set(PLUGIN_LEGACY_NW_STARTUPORDER "35" CACHE STRING "To configure startup order of Legacy Network plugin") +set(PLUGIN_LEGACY_WIFI_STARTUPORDER "35" CACHE STRING "To configure startup order of Legacy WiFi plugin") + +set(PLUGIN_BUILD_REFERENCE ${PROJECT_VERSION} CACHE STRING "To Set the Hash for the plugin") +add_definitions(-DPLUGIN_BUILD_REFERENCE=${PLUGIN_BUILD_REFERENCE}) + +if (USE_RDK_LOGGER) + find_package(rdklogger REQUIRED) + add_definitions(-DUSE_RDK_LOGGER) + + include_directories(${RDKLOGGER_INCLUDE_DIRS}) +endif (USE_RDK_LOGGER) + +include_directories(${PROJECT_SOURCE_DIR}/interface) +include_directories(${PROJECT_SOURCE_DIR}/plugin) + +add_library(${PLUGIN_LEGACY_NETWORK} SHARED + LegacyNetworkAPIs.cpp + ../plugin/NetworkManagerLogger.cpp + ../plugin/Module.cpp +) + +target_link_libraries(${PLUGIN_LEGACY_NETWORK} PRIVATE ${NAMESPACE}Core::${NAMESPACE}Core ${NAMESPACE}Plugins::${NAMESPACE}Plugins) + +if (USE_RDK_LOGGER) + target_link_libraries(${PLUGIN_LEGACY_NETWORK} PRIVATE ${RDKLOGGER_LIBRARIES}) +endif (USE_RDK_LOGGER) + +set_target_properties(${PLUGIN_LEGACY_NETWORK} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +install(TARGETS ${PLUGIN_LEGACY_NETWORK} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) + +add_library(${PLUGIN_LEGACY_WIFI} SHARED + LegacyWiFiManagerAPIs.cpp + ../plugin/NetworkManagerLogger.cpp + ../plugin/Module.cpp +) + +target_link_libraries(${PLUGIN_LEGACY_WIFI} PRIVATE ${NAMESPACE}Core::${NAMESPACE}Core ${NAMESPACE}Plugins::${NAMESPACE}Plugins) + +if (USE_RDK_LOGGER) + target_link_libraries(${PLUGIN_LEGACY_WIFI} PRIVATE ${RDKLOGGER_LIBRARIES}) +endif (USE_RDK_LOGGER) + +set_target_properties(${PLUGIN_LEGACY_WIFI} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +install(TARGETS ${PLUGIN_LEGACY_WIFI} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) + +write_config(PLUGINS LegacyNetworkAPIs CLASSNAME Network LOCATOR lib${PLUGIN_LEGACY_NETWORK}.so) +write_config(PLUGINS LegacyWiFiManagerAPIs CLASSNAME WiFiManager LOCATOR lib${PLUGIN_LEGACY_WIFI}.so) diff --git a/LegacyPlugin_NetworkAPIs.conf.in b/legacy/LegacyNetworkAPIs.conf.in similarity index 100% rename from LegacyPlugin_NetworkAPIs.conf.in rename to legacy/LegacyNetworkAPIs.conf.in diff --git a/LegacyPlugin_NetworkAPIs.config b/legacy/LegacyNetworkAPIs.config similarity index 100% rename from LegacyPlugin_NetworkAPIs.config rename to legacy/LegacyNetworkAPIs.config diff --git a/LegacyPlugin_NetworkAPIs.cpp b/legacy/LegacyNetworkAPIs.cpp similarity index 99% rename from LegacyPlugin_NetworkAPIs.cpp rename to legacy/LegacyNetworkAPIs.cpp index a5c68192b..b56d50a27 100644 --- a/LegacyPlugin_NetworkAPIs.cpp +++ b/legacy/LegacyNetworkAPIs.cpp @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -#include "LegacyPlugin_NetworkAPIs.h" +#include "LegacyNetworkAPIs.h" #include "NetworkManagerLogger.h" #include "NetworkManagerJsonEnum.h" diff --git a/LegacyPlugin_NetworkAPIs.h b/legacy/LegacyNetworkAPIs.h similarity index 100% rename from LegacyPlugin_NetworkAPIs.h rename to legacy/LegacyNetworkAPIs.h diff --git a/LegacyPlugin_WiFiManagerAPIs.conf.in b/legacy/LegacyWiFiManagerAPIs.conf.in similarity index 100% rename from LegacyPlugin_WiFiManagerAPIs.conf.in rename to legacy/LegacyWiFiManagerAPIs.conf.in diff --git a/LegacyPlugin_WiFiManagerAPIs.config b/legacy/LegacyWiFiManagerAPIs.config similarity index 100% rename from LegacyPlugin_WiFiManagerAPIs.config rename to legacy/LegacyWiFiManagerAPIs.config diff --git a/LegacyPlugin_WiFiManagerAPIs.cpp b/legacy/LegacyWiFiManagerAPIs.cpp similarity index 99% rename from LegacyPlugin_WiFiManagerAPIs.cpp rename to legacy/LegacyWiFiManagerAPIs.cpp index 699cdd75f..625e4d328 100644 --- a/LegacyPlugin_WiFiManagerAPIs.cpp +++ b/legacy/LegacyWiFiManagerAPIs.cpp @@ -17,7 +17,7 @@ * limitations under the License. **/ #include -#include "LegacyPlugin_WiFiManagerAPIs.h" +#include "LegacyWiFiManagerAPIs.h" #include "NetworkManagerLogger.h" #include "NetworkManagerJsonEnum.h" diff --git a/LegacyPlugin_WiFiManagerAPIs.h b/legacy/LegacyWiFiManagerAPIs.h similarity index 100% rename from LegacyPlugin_WiFiManagerAPIs.h rename to legacy/LegacyWiFiManagerAPIs.h diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt new file mode 100644 index 000000000..42b6e60b0 --- /dev/null +++ b/plugin/CMakeLists.txt @@ -0,0 +1,119 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2024 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# +message("Build ${PROJECT_NAME} v${PROJECT_VERSION}") + +set(PLUGIN_NAME NetworkManager) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Core REQUIRED) +find_package(${NAMESPACE}Plugins REQUIRED) +find_package(CURL) + +if (USE_RDK_LOGGER) + find_package(rdklogger REQUIRED) + add_definitions(-DUSE_RDK_LOGGER) + + include_directories(${RDKLOGGER_INCLUDE_DIRS}) +endif (USE_RDK_LOGGER) + + + +if(ENABLE_GNOME_NETWORKMANAGER) +pkg_check_modules(GLIB REQUIRED glib-2.0) +pkg_check_modules(LIBNM REQUIRED libnm) +pkg_check_modules(GLIB REQUIRED gio-2.0) +else() +find_package(IARMBus REQUIRED) +endif () + +set(PLUGIN_NETWORKMANAGER_LOGLEVEL "5" CACHE STRING "To configure default loglevel NetworkManager plugin") +set(PLUGIN_NETWORKMANAGER_STARTUPORDER "25" CACHE STRING "To configure startup order of Unified NetworkManager plugin") + +set(PLUGIN_BUILD_REFERENCE ${PROJECT_VERSION} CACHE STRING "To Set the Hash for the plugin") +add_definitions(-DPLUGIN_BUILD_REFERENCE=${PLUGIN_BUILD_REFERENCE}) + +include_directories(${PROJECT_SOURCE_DIR}/interface) +include_directories(${PROJECT_SOURCE_DIR}/plugin) + +#Setting up source files +file(GLOB PROXY_STUB_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/../interface/generated/ProxyStubs*.cpp") + +# Build the main plugin that runs inside the WPEFramework daemon +add_library(${MODULE_NAME} SHARED + NetworkManager.cpp + NetworkManagerJsonRpc.cpp + NetworkManagerLogger.cpp + NetworkManagerImplementation.cpp + NetworkManagerConnectivity.cpp + NetworkManagerStunClient.cpp + Module.cpp + ${PROXY_STUB_SOURCES}) + +target_link_libraries(${MODULE_NAME} PRIVATE + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES + FRAMEWORK FALSE) + + +if(ENABLE_GNOME_NETWORKMANAGER) + if(ENABLE_GNOME_GDBUS) + message("networkmanager building with gdbus") + target_sources(${MODULE_NAME} PRIVATE + gnome/gdbus/NetworkManagerGdbusProxy.cpp + gnome/gdbus/NetworkManagerGdbusClient.cpp + gnome/gdbus/NetworkManagerGdbusEvent.cpp + gnome/gdbus/NetworkManagerGdbusMgr.cpp + gnome/gdbus/NetworkManagerGdbusUtils.cpp + NetworkManagerSecretAgent.cpp) + target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) + target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES} ${GIO_LIBRARIES} uuid) + else() + message("networkmanager building with libnm") + target_sources(${MODULE_NAME} PRIVATE + gnome/NetworkManagerGnomeProxy.cpp + gnome/NetworkManagerGnomeWIFI.cpp + gnome/NetworkManagerGnomeEvents.cpp + gnome/NetworkManagerGnomeUtils.cpp + NetworkManagerSecretAgent.cpp ) + target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) + target_link_libraries(${MODULE_NAME} PRIVATE ${LIBNM_LIBRARIES}) + endif() +else() + message("networkmanager building with RDK netsrvmgr") + target_sources(${MODULE_NAME} PRIVATE rdk/NetworkManagerRDKProxy.cpp) + target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) + target_link_libraries(${MODULE_NAME} PRIVATE ${IARMBUS_LIBRARIES}) +endif() + +target_link_libraries(${MODULE_NAME} PRIVATE ${CURL_LIBRARIES}) +target_include_directories(${MODULE_NAME} PRIVATE ${CURL_INCLUDE_DIRS}) + +if (USE_RDK_LOGGER) + target_link_libraries(${MODULE_NAME} PRIVATE ${RDKLOGGER_LIBRARIES}) +endif (USE_RDK_LOGGER) + +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) + +#Generate Plugin configuration file +write_config() diff --git a/Module.cpp b/plugin/Module.cpp similarity index 100% rename from Module.cpp rename to plugin/Module.cpp diff --git a/Module.h b/plugin/Module.h similarity index 100% rename from Module.h rename to plugin/Module.h diff --git a/NetworkManager.conf.in b/plugin/NetworkManager.conf.in similarity index 100% rename from NetworkManager.conf.in rename to plugin/NetworkManager.conf.in diff --git a/NetworkManager.config b/plugin/NetworkManager.config similarity index 100% rename from NetworkManager.config rename to plugin/NetworkManager.config diff --git a/NetworkManager.cpp b/plugin/NetworkManager.cpp similarity index 100% rename from NetworkManager.cpp rename to plugin/NetworkManager.cpp diff --git a/NetworkManager.h b/plugin/NetworkManager.h similarity index 100% rename from NetworkManager.h rename to plugin/NetworkManager.h diff --git a/NetworkManagerConnectivity.cpp b/plugin/NetworkManagerConnectivity.cpp similarity index 100% rename from NetworkManagerConnectivity.cpp rename to plugin/NetworkManagerConnectivity.cpp diff --git a/NetworkManagerConnectivity.h b/plugin/NetworkManagerConnectivity.h similarity index 100% rename from NetworkManagerConnectivity.h rename to plugin/NetworkManagerConnectivity.h diff --git a/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp similarity index 100% rename from NetworkManagerImplementation.cpp rename to plugin/NetworkManagerImplementation.cpp diff --git a/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h similarity index 100% rename from NetworkManagerImplementation.h rename to plugin/NetworkManagerImplementation.h diff --git a/NetworkManagerJsonEnum.h b/plugin/NetworkManagerJsonEnum.h similarity index 100% rename from NetworkManagerJsonEnum.h rename to plugin/NetworkManagerJsonEnum.h diff --git a/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp similarity index 100% rename from NetworkManagerJsonRpc.cpp rename to plugin/NetworkManagerJsonRpc.cpp diff --git a/NetworkManagerLogger.cpp b/plugin/NetworkManagerLogger.cpp similarity index 100% rename from NetworkManagerLogger.cpp rename to plugin/NetworkManagerLogger.cpp diff --git a/NetworkManagerLogger.h b/plugin/NetworkManagerLogger.h similarity index 100% rename from NetworkManagerLogger.h rename to plugin/NetworkManagerLogger.h diff --git a/NetworkManagerSecretAgent.cpp b/plugin/NetworkManagerSecretAgent.cpp similarity index 100% rename from NetworkManagerSecretAgent.cpp rename to plugin/NetworkManagerSecretAgent.cpp diff --git a/NetworkManagerSecretAgent.h b/plugin/NetworkManagerSecretAgent.h similarity index 100% rename from NetworkManagerSecretAgent.h rename to plugin/NetworkManagerSecretAgent.h diff --git a/NetworkManagerStunClient.cpp b/plugin/NetworkManagerStunClient.cpp similarity index 100% rename from NetworkManagerStunClient.cpp rename to plugin/NetworkManagerStunClient.cpp diff --git a/NetworkManagerStunClient.h b/plugin/NetworkManagerStunClient.h similarity index 100% rename from NetworkManagerStunClient.h rename to plugin/NetworkManagerStunClient.h diff --git a/NetworkManagerTimer.h b/plugin/NetworkManagerTimer.h similarity index 100% rename from NetworkManagerTimer.h rename to plugin/NetworkManagerTimer.h diff --git a/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp similarity index 100% rename from NetworkManagerGnomeEvents.cpp rename to plugin/gnome/NetworkManagerGnomeEvents.cpp diff --git a/NetworkManagerGnomeEvents.h b/plugin/gnome/NetworkManagerGnomeEvents.h similarity index 100% rename from NetworkManagerGnomeEvents.h rename to plugin/gnome/NetworkManagerGnomeEvents.h diff --git a/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp similarity index 100% rename from NetworkManagerGnomeProxy.cpp rename to plugin/gnome/NetworkManagerGnomeProxy.cpp diff --git a/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp similarity index 100% rename from NetworkManagerGnomeUtils.cpp rename to plugin/gnome/NetworkManagerGnomeUtils.cpp diff --git a/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h similarity index 100% rename from NetworkManagerGnomeUtils.h rename to plugin/gnome/NetworkManagerGnomeUtils.h diff --git a/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp similarity index 100% rename from NetworkManagerGnomeWIFI.cpp rename to plugin/gnome/NetworkManagerGnomeWIFI.cpp diff --git a/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h similarity index 100% rename from NetworkManagerGnomeWIFI.h rename to plugin/gnome/NetworkManagerGnomeWIFI.h diff --git a/gdbus/NetworkManagerGdbusClient.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp similarity index 100% rename from gdbus/NetworkManagerGdbusClient.cpp rename to plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp diff --git a/gdbus/NetworkManagerGdbusClient.h b/plugin/gnome/gdbus/NetworkManagerGdbusClient.h similarity index 100% rename from gdbus/NetworkManagerGdbusClient.h rename to plugin/gnome/gdbus/NetworkManagerGdbusClient.h diff --git a/gdbus/NetworkManagerGdbusEvent.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp similarity index 100% rename from gdbus/NetworkManagerGdbusEvent.cpp rename to plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp diff --git a/gdbus/NetworkManagerGdbusEvent.h b/plugin/gnome/gdbus/NetworkManagerGdbusEvent.h similarity index 100% rename from gdbus/NetworkManagerGdbusEvent.h rename to plugin/gnome/gdbus/NetworkManagerGdbusEvent.h diff --git a/gdbus/NetworkManagerGdbusMgr.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusMgr.cpp similarity index 100% rename from gdbus/NetworkManagerGdbusMgr.cpp rename to plugin/gnome/gdbus/NetworkManagerGdbusMgr.cpp diff --git a/gdbus/NetworkManagerGdbusMgr.h b/plugin/gnome/gdbus/NetworkManagerGdbusMgr.h similarity index 100% rename from gdbus/NetworkManagerGdbusMgr.h rename to plugin/gnome/gdbus/NetworkManagerGdbusMgr.h diff --git a/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp similarity index 100% rename from gdbus/NetworkManagerGdbusProxy.cpp rename to plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp diff --git a/gdbus/NetworkManagerGdbusUtils.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp similarity index 100% rename from gdbus/NetworkManagerGdbusUtils.cpp rename to plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp diff --git a/gdbus/NetworkManagerGdbusUtils.h b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h similarity index 100% rename from gdbus/NetworkManagerGdbusUtils.h rename to plugin/gnome/gdbus/NetworkManagerGdbusUtils.h diff --git a/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp similarity index 100% rename from NetworkManagerRDKProxy.cpp rename to plugin/rdk/NetworkManagerRDKProxy.cpp diff --git a/Tests/mocks/Iarm.cpp b/tests/mocks/Iarm.cpp similarity index 85% rename from Tests/mocks/Iarm.cpp rename to tests/mocks/Iarm.cpp index 24cb7b74d..a4a7babdc 100644 --- a/Tests/mocks/Iarm.cpp +++ b/tests/mocks/Iarm.cpp @@ -1,3 +1,22 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + #include "Iarm.h" #include diff --git a/Tests/mocks/Iarm.h b/tests/mocks/Iarm.h similarity index 83% rename from Tests/mocks/Iarm.h rename to tests/mocks/Iarm.h index bd7390d23..3dd11b620 100644 --- a/Tests/mocks/Iarm.h +++ b/tests/mocks/Iarm.h @@ -1,3 +1,22 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + #pragma once #include diff --git a/Tests/mocks/IarmBusMock.h b/tests/mocks/IarmBusMock.h similarity index 83% rename from Tests/mocks/IarmBusMock.h rename to tests/mocks/IarmBusMock.h index fec66aa6d..ad18629a2 100644 --- a/Tests/mocks/IarmBusMock.h +++ b/tests/mocks/IarmBusMock.h @@ -1,3 +1,22 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + #pragma once #include diff --git a/Tests/mocks/thunder/COMLinkMock.h b/tests/mocks/thunder/COMLinkMock.h similarity index 52% rename from Tests/mocks/thunder/COMLinkMock.h rename to tests/mocks/thunder/COMLinkMock.h index d9c02502a..28557ca0d 100644 --- a/Tests/mocks/thunder/COMLinkMock.h +++ b/tests/mocks/thunder/COMLinkMock.h @@ -1,3 +1,22 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + #ifndef RDKSERVICES_TESTS_MOCKS_COMLINKMOCK_H_ #define RDKSERVICES_TESTS_MOCKS_COMLINKMOCK_H_ diff --git a/Tests/mocks/thunder/DispatcherMock.h b/tests/mocks/thunder/DispatcherMock.h similarity index 52% rename from Tests/mocks/thunder/DispatcherMock.h rename to tests/mocks/thunder/DispatcherMock.h index 8d6502b46..5229c6783 100644 --- a/Tests/mocks/thunder/DispatcherMock.h +++ b/tests/mocks/thunder/DispatcherMock.h @@ -1,3 +1,22 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + #ifndef DISPATCHERMOCK_H #define DISPATCHERMOCK_H diff --git a/Tests/mocks/thunder/FactoriesImplementation.h b/tests/mocks/thunder/FactoriesImplementation.h similarity index 74% rename from Tests/mocks/thunder/FactoriesImplementation.h rename to tests/mocks/thunder/FactoriesImplementation.h index 9259cb674..e1f381b8d 100644 --- a/Tests/mocks/thunder/FactoriesImplementation.h +++ b/tests/mocks/thunder/FactoriesImplementation.h @@ -1,3 +1,21 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ #pragma once diff --git a/tests/mocks/thunder/Module.cpp b/tests/mocks/thunder/Module.cpp new file mode 100644 index 000000000..ab461e818 --- /dev/null +++ b/tests/mocks/thunder/Module.cpp @@ -0,0 +1,22 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include "Module.h" + +MODULE_NAME_DECLARATION(BUILD_REFERENCE) diff --git a/tests/mocks/thunder/Module.h b/tests/mocks/thunder/Module.h new file mode 100644 index 000000000..4c34d4669 --- /dev/null +++ b/tests/mocks/thunder/Module.h @@ -0,0 +1,27 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +#ifndef MODULE_NAME +#define MODULE_NAME tests +#endif + +#include +#include diff --git a/Tests/mocks/thunder/ServiceMock.h b/tests/mocks/thunder/ServiceMock.h similarity index 83% rename from Tests/mocks/thunder/ServiceMock.h rename to tests/mocks/thunder/ServiceMock.h index 728c69186..e14547d55 100644 --- a/Tests/mocks/thunder/ServiceMock.h +++ b/tests/mocks/thunder/ServiceMock.h @@ -1,3 +1,22 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + #ifndef SERVICEMOCK_H #define SERVICEMOCK_H diff --git a/Tests/mocks/thunder/SystemInfo.h b/tests/mocks/thunder/SystemInfo.h similarity index 77% rename from Tests/mocks/thunder/SystemInfo.h rename to tests/mocks/thunder/SystemInfo.h index 871b10950..12ee47ec8 100644 --- a/Tests/mocks/thunder/SystemInfo.h +++ b/tests/mocks/thunder/SystemInfo.h @@ -1,3 +1,22 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + #pragma once #include diff --git a/tests/mocks/thunder/ThunderPortability.h b/tests/mocks/thunder/ThunderPortability.h new file mode 100644 index 000000000..48f2407d5 --- /dev/null +++ b/tests/mocks/thunder/ThunderPortability.h @@ -0,0 +1,32 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +#include +#include + +#define EVENT_SUBSCRIBE(__A__, __B__, __C__, __D__) { plugin->Subscribe(__A__, __B__, __C__); (void)__D__; } +#define EVENT_UNSUBSCRIBE(__A__, __B__, __C__, __D__) { plugin->Unsubscribe(__A__, __B__, __C__); (void)__D__; } + +#define DECL_CORE_JSONRPC_CONX Core::JSONRPC::Context +#define INIT_CONX(__X__, __Y__) connection(__X__, __Y__, "") +#define PLUGINHOST_DISPATCHER PluginHost::ILocalDispatcher +#define PLUGINHOST_DISPATCHER_ID PluginHost::ILocalDispatcher::ID + diff --git a/Tests/mocks/thunder/WorkerPoolImplementation.h b/tests/mocks/thunder/WorkerPoolImplementation.h similarity index 63% rename from Tests/mocks/thunder/WorkerPoolImplementation.h rename to tests/mocks/thunder/WorkerPoolImplementation.h index 58bf84f14..2a0f924e9 100644 --- a/Tests/mocks/thunder/WorkerPoolImplementation.h +++ b/tests/mocks/thunder/WorkerPoolImplementation.h @@ -1,3 +1,22 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + #pragma once #include diff --git a/Tests/patches/thunder/Remove-SmartLinkType.patch b/tests/patches/thunder/Remove-SmartLinkType.patch similarity index 100% rename from Tests/patches/thunder/Remove-SmartLinkType.patch rename to tests/patches/thunder/Remove-SmartLinkType.patch diff --git a/Tests/unit_test/unit_tests.cmake b/tests/unittest/CMakeLists.txt similarity index 52% rename from Tests/unit_test/unit_tests.cmake rename to tests/unittest/CMakeLists.txt index 7b19385fb..751f2088b 100644 --- a/Tests/unit_test/unit_tests.cmake +++ b/tests/unittest/CMakeLists.txt @@ -1,14 +1,36 @@ -cmake_minimum_required(VERSION 3.10) +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2024 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# +message ("Unittest binary is built here") set(NM_CLASS_UT "common_class_tests") set(NM_RDKPROXY_UT "rdkproxy_tests") set(NM_LEGACY_WIFI_UT "legacywifi_tests") set(NM_LEGACY_NETWORK_UT "legacynetwork_tests") + +find_package(${NAMESPACE}Core REQUIRED) +find_package(${NAMESPACE}Plugins REQUIRED) +find_package(CURL) find_package(PkgConfig REQUIRED) -pkg_check_modules(GLIB REQUIRED glib-2.0) -pkg_check_modules(GIO REQUIRED gio-2.0) -pkg_check_modules(LIBNM REQUIRED libnm) +#pkg_check_modules(GLIB REQUIRED glib-2.0) +#pkg_check_modules(GIO REQUIRED gio-2.0) +#pkg_check_modules(LIBNM REQUIRED libnm) include(FetchContent) FetchContent_Declare( @@ -19,39 +41,39 @@ FetchContent_Declare( FetchContent_MakeAvailable(googletest) add_executable(${NM_CLASS_UT} - Tests/unit_test/test_NetworkManagerConnectivity.cpp - Tests/unit_test/test_NetworkManagerStunClient.cpp - NetworkManagerLogger.cpp - NetworkManagerConnectivity.cpp - NetworkManagerStunClient.cpp + ${CMAKE_SOURCE_DIR}/tests/unittest/test_NetworkManagerConnectivity.cpp + ${CMAKE_SOURCE_DIR}/tests/unittest/test_NetworkManagerStunClient.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp ) add_executable(${NM_RDKPROXY_UT} - Tests/unit_test/test_NetworkManager.cpp - Tests/mocks/thunder/Module.cpp - Tests/mocks/Iarm.cpp - NetworkManager.cpp - NetworkManagerLogger.cpp - NetworkManagerJsonRpc.cpp - NetworkManagerImplementation.cpp - NetworkManagerConnectivity.cpp - NetworkManagerStunClient.cpp - NetworkManagerRDKProxy.cpp + ${CMAKE_SOURCE_DIR}/tests/unittest/test_NetworkManager.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerJsonRpc.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerImplementation.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp + ${CMAKE_SOURCE_DIR}/plugin/rdk/NetworkManagerRDKProxy.cpp ${PROXY_STUB_SOURCES} ) add_executable(${NM_LEGACY_WIFI_UT} - Tests/unit_test/test_LegacyPlugin_WiFiManagerAPIs.cpp - Tests/mocks/thunder/Module.cpp - NetworkManagerLogger.cpp - LegacyPlugin_WiFiManagerAPIs.cpp + ${CMAKE_SOURCE_DIR}/tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/legacy/LegacyWiFiManagerAPIs.cpp ) add_executable(${NM_LEGACY_NETWORK_UT} - Tests/unit_test/test_LegacyPlugin_NetworkAPIs.cpp - Tests/mocks/thunder/Module.cpp - NetworkManagerLogger.cpp - LegacyPlugin_NetworkAPIs.cpp + ${CMAKE_SOURCE_DIR}/tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/legacy/LegacyNetworkAPIs.cpp ) set_target_properties(${NM_CLASS_UT} PROPERTIES @@ -73,20 +95,25 @@ set_target_properties(${NM_LEGACY_NETWORK_UT} PROPERTIES CXX_STANDARD_REQUIRED YES ) -target_compile_options(${NM_CLASS_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) -target_compile_options(${NM_RDKPROXY_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) -target_compile_options(${NM_LEGACY_WIFI_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) -target_compile_options(${NM_LEGACY_NETWORK_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) +target_compile_options(${NM_CLASS_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) +target_compile_options(${NM_RDKPROXY_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) +target_compile_options(${NM_LEGACY_WIFI_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) +target_compile_options(${NM_LEGACY_NETWORK_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") +include_directories(${PROJECT_SOURCE_DIR}/interface) +include_directories(${PROJECT_SOURCE_DIR}/plugin) +include_directories(${PROJECT_SOURCE_DIR}/legacy) +include_directories(${PROJECT_SOURCE_DIR}/tests/mocks) +include_directories(${PROJECT_SOURCE_DIR}/tests/mocks/thunder) + target_include_directories(${NM_CLASS_UT} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} - Tests ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}/../googlemock/include ) @@ -98,26 +125,17 @@ target_include_directories(${NM_RDKPROXY_UT} PRIVATE ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}/../googlemock/include ${CMAKE_CURRENT_SOURCE_DIR}/install/usr/include/rdk/iarmbus - Tests - Tests/mocks - Tests/mocks/thunder ) target_include_directories(${NM_LEGACY_WIFI_UT} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}/../googlemock/include - Tests - Tests/mocks - Tests/mocks/thunder ) target_include_directories(${NM_LEGACY_NETWORK_UT} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}/../googlemock/include - Tests - Tests/mocks - Tests/mocks/thunder ) target_link_libraries(${NM_CLASS_UT} PRIVATE diff --git a/Tests/unit_test/test_LegacyPlugin_NetworkAPIs.cpp b/tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp similarity index 77% rename from Tests/unit_test/test_LegacyPlugin_NetworkAPIs.cpp rename to tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp index 5664c501c..2df0804ac 100644 --- a/Tests/unit_test/test_LegacyPlugin_NetworkAPIs.cpp +++ b/tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp @@ -1,3 +1,22 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + #include #include #include @@ -5,7 +24,7 @@ #include "ServiceMock.h" #include "FactoriesImplementation.h" #include "NetworkManagerLogger.h" -#include "LegacyPlugin_NetworkAPIs.h" +#include "LegacyNetworkAPIs.h" #include "ThunderPortability.h" using namespace std; diff --git a/Tests/unit_test/test_LegacyPlugin_WiFiManagerAPIs.cpp b/tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp similarity index 86% rename from Tests/unit_test/test_LegacyPlugin_WiFiManagerAPIs.cpp rename to tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp index 1ca5049c3..6e7f51117 100644 --- a/Tests/unit_test/test_LegacyPlugin_WiFiManagerAPIs.cpp +++ b/tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp @@ -1,10 +1,29 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + #include #include #include #include "ServiceMock.h" #include "FactoriesImplementation.h" #include "NetworkManagerLogger.h" -#include "LegacyPlugin_WiFiManagerAPIs.h" +#include "LegacyWiFiManagerAPIs.h" #include "ThunderPortability.h" using namespace std; diff --git a/Tests/unit_test/test_NetworkManager.cpp b/tests/unittest/test_NetworkManager.cpp similarity index 91% rename from Tests/unit_test/test_NetworkManager.cpp rename to tests/unittest/test_NetworkManager.cpp index 7cb316db3..09fdf0edd 100644 --- a/Tests/unit_test/test_NetworkManager.cpp +++ b/tests/unittest/test_NetworkManager.cpp @@ -1,3 +1,22 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + #include #include #include diff --git a/Tests/unit_test/test_NetworkManagerConnectivity.cpp b/tests/unittest/test_NetworkManagerConnectivity.cpp similarity index 98% rename from Tests/unit_test/test_NetworkManagerConnectivity.cpp rename to tests/unittest/test_NetworkManagerConnectivity.cpp index 8716b6257..a1b5d7b01 100644 --- a/Tests/unit_test/test_NetworkManagerConnectivity.cpp +++ b/tests/unittest/test_NetworkManagerConnectivity.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2023 RDK Management +* Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/Tests/unit_test/test_NetworkManagerStunClient.cpp b/tests/unittest/test_NetworkManagerStunClient.cpp similarity index 98% rename from Tests/unit_test/test_NetworkManagerStunClient.cpp rename to tests/unittest/test_NetworkManagerStunClient.cpp index a5da16708..82de8406b 100644 --- a/Tests/unit_test/test_NetworkManagerStunClient.cpp +++ b/tests/unittest/test_NetworkManagerStunClient.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2023 RDK Management +* Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp b/tests/unittest/test_WiFiSignalStrengthMonitor.cpp similarity index 98% rename from Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp rename to tests/unittest/test_WiFiSignalStrengthMonitor.cpp index b3876a76d..15d9a6c0d 100644 --- a/Tests/unit_test/test_WiFiSignalStrengthMonitor.cpp +++ b/tests/unittest/test_WiFiSignalStrengthMonitor.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2023 RDK Management +* Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 000000000..dd13d9bbe --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,30 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2024 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# +message("building tools") + +option(ENABLE_PLUGIN_CLI "Enable Plugin cli" OFF) +option(ENABLE_ROUTER_DISCOVERY_TOOL "Enable UPNP based Router Details discovery tool" OFF) + +if(ENABLE_PLUGIN_CLI) + add_subdirectory(plugincli) +endif(ENABLE_PLUGIN_CLI) + +if(ENABLE_ROUTER_DISCOVERY_TOOL) + add_subdirectory(upnp) +endif(ENABLE_ROUTER_DISCOVERY_TOOL) diff --git a/Tests/raspberrypi/NetworkManagerGdbusTest.cmake b/tools/plugincli/CMakeLists.txt similarity index 98% rename from Tests/raspberrypi/NetworkManagerGdbusTest.cmake rename to tools/plugincli/CMakeLists.txt index 732011e09..ac0bce1d0 100644 --- a/Tests/raspberrypi/NetworkManagerGdbusTest.cmake +++ b/tools/plugincli/CMakeLists.txt @@ -2,7 +2,7 @@ # If not stated otherwise in this file or this component's LICENSE file the # following copyright and licenses apply: # -# Copyright 2023 RDK Management +# Copyright 2024 RDK Management # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tests/raspberrypi/NetworkManagerGdbusTest.cpp b/tools/plugincli/NetworkManagerGdbusTest.cpp similarity index 100% rename from Tests/raspberrypi/NetworkManagerGdbusTest.cpp rename to tools/plugincli/NetworkManagerGdbusTest.cpp diff --git a/upnp/CMakeLists.txt b/tools/upnp/CMakeLists.txt similarity index 100% rename from upnp/CMakeLists.txt rename to tools/upnp/CMakeLists.txt diff --git a/upnp/UpnpDiscoveryManager.cpp b/tools/upnp/UpnpDiscoveryManager.cpp similarity index 100% rename from upnp/UpnpDiscoveryManager.cpp rename to tools/upnp/UpnpDiscoveryManager.cpp diff --git a/upnp/UpnpDiscoveryManager.h b/tools/upnp/UpnpDiscoveryManager.h similarity index 100% rename from upnp/UpnpDiscoveryManager.h rename to tools/upnp/UpnpDiscoveryManager.h diff --git a/upnp/cmake/Findtelemetry_msgsender.cmake b/tools/upnp/cmake/Findtelemetry_msgsender.cmake similarity index 100% rename from upnp/cmake/Findtelemetry_msgsender.cmake rename to tools/upnp/cmake/Findtelemetry_msgsender.cmake diff --git a/upnp/scripts/getRouterInfo-NMdispatcher.sh b/tools/upnp/scripts/getRouterInfo-NMdispatcher.sh similarity index 100% rename from upnp/scripts/getRouterInfo-NMdispatcher.sh rename to tools/upnp/scripts/getRouterInfo-NMdispatcher.sh diff --git a/upnp/scripts/getRouterInfo-nlmon.sh b/tools/upnp/scripts/getRouterInfo-nlmon.sh similarity index 100% rename from upnp/scripts/getRouterInfo-nlmon.sh rename to tools/upnp/scripts/getRouterInfo-nlmon.sh diff --git a/upnp/scripts/readyToGetRouterInfo.sh b/tools/upnp/scripts/readyToGetRouterInfo.sh similarity index 100% rename from upnp/scripts/readyToGetRouterInfo.sh rename to tools/upnp/scripts/readyToGetRouterInfo.sh diff --git a/upnp/scripts/routerDiscovery@.service b/tools/upnp/scripts/routerDiscovery@.service similarity index 100% rename from upnp/scripts/routerDiscovery@.service rename to tools/upnp/scripts/routerDiscovery@.service From c9a899a5231e4d2b8bc4cd55469c05629de735c5 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 20 Mar 2025 08:14:05 +0530 Subject: [PATCH 103/271] DELIA-67341 WPEFramework crash with signature getDefaultInterface (#113) * networkplugin retry added * legacy wifi retry added * workflow updated --- legacy/LegacyNetworkAPIs.cpp | 40 +++++++++++++------ legacy/LegacyWiFiManagerAPIs.cpp | 40 +++++++++++++------ .../test_LegacyPlugin_NetworkAPIs.cpp | 2 +- .../test_LegacyPlugin_WiFiManagerAPIs.cpp | 2 +- 4 files changed, 57 insertions(+), 27 deletions(-) diff --git a/legacy/LegacyNetworkAPIs.cpp b/legacy/LegacyNetworkAPIs.cpp index b56d50a27..d3cc6bc5c 100644 --- a/legacy/LegacyNetworkAPIs.cpp +++ b/legacy/LegacyNetworkAPIs.cpp @@ -118,6 +118,7 @@ namespace WPEFramework { m_service = service; m_service->AddRef(); + string message{}; string callsign(NETWORK_MANAGER_CALLSIGN); @@ -142,25 +143,38 @@ namespace WPEFramework auto interface = m_service->QueryInterfaceByCallsign(callsign); if (interface != nullptr) { - PluginHost::IShell::state state = interface->State(); - if((PluginHost::IShell::state::ACTIVATED == state) || (PluginHost::IShell::state::ACTIVATION == state)) + int retry = 0; + PluginHost::IShell::state state = PluginHost::IShell::state::UNAVAILABLE; + do{ + state = interface->State(); + if(PluginHost::IShell::state::ACTIVATED == state) + { + NMLOG_INFO("Dependency Plugin '%s' Ready", callsign.c_str()); + break; + } + else + { + NMLOG_INFO("Lets attempt to activate the Plugin '%s', retry %d", callsign.c_str(), retry+1); + activatePrimaryPlugin(); + } + usleep(500*1000); + } while(retry++ < 5); + + if(PluginHost::IShell::state::ACTIVATED == state) { - NMLOG_INFO("Dependency Plugin '%s' Ready", callsign.c_str()); + Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); + m_networkmanager = make_shared >(_T(NETWORK_MANAGER_CALLSIGN), _T("org.rdk.Network"), query); + subscribeToEvents(); } else - { - NMLOG_INFO("Lets attempt to activate the Plugin '%s'", callsign.c_str()); - activatePrimaryPlugin(); - } + message = _T("dependency Plugin 'NetworkManager' not Ready"); + interface->Release(); } - - Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); - m_networkmanager = make_shared >(_T(NETWORK_MANAGER_CALLSIGN), _T("org.rdk.Network"), query); - - subscribeToEvents(); + else + message = _T("Failed to get IShell for 'NetworkManager'"); - return string(); + return message; } void Network::Deinitialize(PluginHost::IShell* /* service */) diff --git a/legacy/LegacyWiFiManagerAPIs.cpp b/legacy/LegacyWiFiManagerAPIs.cpp index 625e4d328..036cca6a5 100644 --- a/legacy/LegacyWiFiManagerAPIs.cpp +++ b/legacy/LegacyWiFiManagerAPIs.cpp @@ -151,6 +151,8 @@ namespace WPEFramework const string WiFiManager::Initialize(PluginHost::IShell* service ) { m_service = service; + string message{}; + m_service->AddRef(); string callsign(NETWORK_MANAGER_CALLSIGN); @@ -178,24 +180,38 @@ namespace WPEFramework auto interface = m_service->QueryInterfaceByCallsign(callsign); if (interface != nullptr) { - PluginHost::IShell::state state = interface->State(); - if((PluginHost::IShell::state::ACTIVATED == state) || (PluginHost::IShell::state::ACTIVATION == state)) + int retry = 0; + PluginHost::IShell::state state = PluginHost::IShell::state::UNAVAILABLE; + do{ + state = interface->State(); + if(PluginHost::IShell::state::ACTIVATED == state) + { + NMLOG_INFO("Dependency Plugin '%s' Ready", callsign.c_str()); + break; + } + else + { + NMLOG_INFO("Lets attempt to activate the Plugin '%s', retry %d", callsign.c_str(), retry+1); + activatePrimaryPlugin(); + } + usleep(500*1000); + } while(retry++ < 5); + + if(PluginHost::IShell::state::ACTIVATED == state) { - NMLOG_INFO("Dependency Plugin '%s' Ready", callsign.c_str()); + Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); + m_networkmanager = make_shared >(_T(NETWORK_MANAGER_CALLSIGN), _T("org.rdk.Wifi"), query); + subscribeToEvents(); } else - { - NMLOG_INFO("Lets attempt to activate the Plugin '%s'", callsign.c_str()); - activatePrimaryPlugin(); - } + message = _T("dependency Plugin 'NetworkManager' not Ready"); + interface->Release(); } - - Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); - m_networkmanager = make_shared >(_T(NETWORK_MANAGER_CALLSIGN), _T("org.rdk.Wifi"), query); + else + message = _T("Failed to get IShell for 'NetworkManager'"); - subscribeToEvents(); - return string(); + return message; } void WiFiManager::Deinitialize(PluginHost::IShell* /* service */) diff --git a/tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp b/tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp index 2df0804ac..88f7fb308 100644 --- a/tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp +++ b/tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp @@ -57,7 +57,7 @@ class NetworkInitializedTest : public NetworkTest { NiceMock service; NetworkInitializedTest() { - EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(string("Failed to get IShell for 'NetworkManager'"), plugin->Initialize(&service)); EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) .Times(1) diff --git a/tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp b/tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp index 6e7f51117..515c5e76e 100644 --- a/tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp +++ b/tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp @@ -58,7 +58,7 @@ class WiFiManagerInitializedTest : public WiFiManagerTest { NiceMock service; WiFiManagerInitializedTest() { - EXPECT_EQ(string(""), plugin->Initialize(&service)); + EXPECT_EQ(string("Failed to get IShell for 'NetworkManager'"), plugin->Initialize(&service)); EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) .Times(1) From ce1ca48a1200e9fc9d37be637cf5931ba4222150 Mon Sep 17 00:00:00 2001 From: jincysam87 <167995204+jincysam87@users.noreply.github.com> Date: Fri, 21 Mar 2025 11:47:25 -0400 Subject: [PATCH 104/271] RDK-56730: Unit test framework for routerDiscovery (#121) * RDK-56730: Unit test framework for routerDiscovery Reason for change: Integrate unit test framework Test Procedure: Invoked unit test on every PR --- .github/workflows/rdk_unit_test.yml | 9 +- tests/unittest/CMakeLists.txt | 27 ++++- tests/unittest/test_UpnpDiscoveryManager.cpp | 100 +++++++++++++++++++ tools/upnp/CMakeLists.txt | 16 ++- tools/upnp/UpnpDiscoveryManager.cpp | 7 +- 5 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 tests/unittest/test_UpnpDiscoveryManager.cpp diff --git a/.github/workflows/rdk_unit_test.yml b/.github/workflows/rdk_unit_test.yml index 3a98536e6..4964d6489 100644 --- a/.github/workflows/rdk_unit_test.yml +++ b/.github/workflows/rdk_unit_test.yml @@ -18,7 +18,7 @@ jobs: - name: Install packages run: | sudo apt update - sudo apt-get install -y pkg-config libglib2.0-dev libnm-dev libcurl4-openssl-dev lcov ninja-build + sudo apt-get install -y pkg-config libglib2.0-dev libnm-dev libcurl4-openssl-dev lcov ninja-build libgupnp-1.2-1 libgupnp-1.2-dev libgssdp-1.2-0 libsoup2.4-1 - name: Configure Python uses: actions/setup-python@v4 @@ -92,6 +92,7 @@ jobs: --include ${{github.workspace}}/networkmanager/tests/mocks/Iarm.h " -DENABLE_UNIT_TESTING=ON + -DENABLE_ROUTER_DISCOVERY_TOOL=ON && cmake --build build/RDKNetworkmanager --target install -j8 @@ -118,7 +119,11 @@ jobs: PATH=${{github.workspace}}/install/usr/bin:${PATH} LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} legacynetwork_tests - + + - name: Run unit tests for routerDiscovery + run: > + PATH=${{github.workspace}}/install/usr/bin:${PATH} + routerDiscovery_tests - name: Generate coverage run: | diff --git a/tests/unittest/CMakeLists.txt b/tests/unittest/CMakeLists.txt index 751f2088b..13855cb15 100644 --- a/tests/unittest/CMakeLists.txt +++ b/tests/unittest/CMakeLists.txt @@ -22,7 +22,7 @@ set(NM_CLASS_UT "common_class_tests") set(NM_RDKPROXY_UT "rdkproxy_tests") set(NM_LEGACY_WIFI_UT "legacywifi_tests") set(NM_LEGACY_NETWORK_UT "legacynetwork_tests") - +set(NM_ROUTER_DISCOVERY_UT "routerDiscovery_tests") find_package(${NAMESPACE}Core REQUIRED) find_package(${NAMESPACE}Plugins REQUIRED) @@ -76,6 +76,11 @@ add_executable(${NM_LEGACY_NETWORK_UT} ${CMAKE_SOURCE_DIR}/legacy/LegacyNetworkAPIs.cpp ) +add_executable(${NM_ROUTER_DISCOVERY_UT} + ${CMAKE_SOURCE_DIR}/tests/unittest/test_UpnpDiscoveryManager.cpp + ${CMAKE_SOURCE_DIR}/tools/upnp/UpnpDiscoveryManager.cpp +) + set_target_properties(${NM_CLASS_UT} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES @@ -95,6 +100,11 @@ set_target_properties(${NM_LEGACY_NETWORK_UT} PROPERTIES CXX_STANDARD_REQUIRED YES ) +set_target_properties(${NM_ROUTER_DISCOVERY_UT} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) + target_compile_options(${NM_CLASS_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) target_compile_options(${NM_RDKPROXY_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) target_compile_options(${NM_LEGACY_WIFI_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) @@ -137,6 +147,13 @@ target_include_directories(${NM_LEGACY_NETWORK_UT} PRIVATE ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}/../googlemock/include ) +target_include_directories(${NM_ROUTER_DISCOVERY_UT} PRIVATE + ${PROJECT_SOURCE_DIR}/tools/upnp + ${GUPNP_INCLUDE_DIRS} + ${GLIB_INCLUDE_DIRS} + ${LIBSOUP_INCLUDE_DIRS} + ${GSSDP_INCLUDE_DIRS} +) target_link_libraries(${NM_CLASS_UT} PRIVATE gmock_main @@ -168,8 +185,16 @@ target_link_libraries(${NM_LEGACY_NETWORK_UT} PRIVATE ${NAMESPACE}Core::${NAMESPACE}Core ${CURL_LIBRARIES} ) +target_link_libraries(${NM_ROUTER_DISCOVERY_UT} PRIVATE + gmock_main + ${GLIB_LIBRARIES} + ${LIBSOUP_LIBRARIES} + ${GUPNP_LIBRARIES} + ${GSSDP_LIBRARIES} +) install(TARGETS ${NM_CLASS_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(TARGETS ${NM_RDKPROXY_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(TARGETS ${NM_LEGACY_WIFI_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(TARGETS ${NM_LEGACY_NETWORK_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS ${NM_ROUTER_DISCOVERY_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/unittest/test_UpnpDiscoveryManager.cpp b/tests/unittest/test_UpnpDiscoveryManager.cpp new file mode 100644 index 000000000..49b817165 --- /dev/null +++ b/tests/unittest/test_UpnpDiscoveryManager.cpp @@ -0,0 +1,100 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2025 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include +#include +#include +#include + +using ::testing::_; +using ::testing::Return; +using ::testing::Mock; + +class UpnpDiscoveryManagerTest : public ::testing::Test { +protected: + UpnpDiscoveryManager upnpDiscover; + GMainLoop* mainLoop; + void SetUp() override { + mainLoop = g_main_loop_new(nullptr, FALSE); + } +}; + +std::string getInterfaceWithDefaultRoute() { + std::string command = "ip -4 route show | grep default | awk '{print $5}'"; + std::array buffer; + std::string result; + + std::unique_ptr pipe(popen(command.c_str(), "r"), pclose); + if (!pipe) { + throw std::runtime_error("popen() failed!"); + } + + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + result += buffer.data(); + } + + // Remove trailing newline character + if (!result.empty() && result.back() == '\n') { + result.pop_back(); + } + return result; +} + +TEST_F(UpnpDiscoveryManagerTest, FindGatewayDeviceTest) +{ + // Invalid interface name + EXPECT_EQ(false, upnpDiscover.findGatewayDevice("123")); + + // Get router details on actual interface + std::string interfaceName = getInterfaceWithDefaultRoute(); + if (!interfaceName.empty()) { + std::cout << "Interface with default route: " << interfaceName << std::endl; + } else { + std::cout << "No default route interface found." << std::endl; + } + + // Valid interface name + EXPECT_EQ(true, upnpDiscover.findGatewayDevice(interfaceName)); +} + +TEST_F(UpnpDiscoveryManagerTest, routerDiscovery) +{ + auto threadHandler = [&]() { + std::this_thread::sleep_for(std::chrono::seconds(10)); + std::cout << "Thread finished sleeping." << std::endl; + if (this->mainLoop) + { + g_main_loop_quit(this->mainLoop); + g_main_loop_unref(this->mainLoop); + } + }; + // Get router details on actual interface + std::string interfaceName = getInterfaceWithDefaultRoute(); + if (!interfaceName.empty()) { + std::cout << "Interface with default route: " << interfaceName << std::endl; + } else { + std::cout << "No default route interface found." << std::endl; + } + mainLoop = g_main_loop_new(NULL, FALSE); + std::thread workerThread(threadHandler); + // Get the router details, mostly will timeout in corporate network + EXPECT_EQ(true, upnpDiscover.findGatewayDevice(interfaceName)); + g_main_loop_run(mainLoop); + workerThread.join(); +} diff --git a/tools/upnp/CMakeLists.txt b/tools/upnp/CMakeLists.txt index e2a7d133e..110c6e2d8 100644 --- a/tools/upnp/CMakeLists.txt +++ b/tools/upnp/CMakeLists.txt @@ -25,8 +25,14 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(LIBSOUP REQUIRED libsoup-2.4) -pkg_check_modules(GUPNP REQUIRED gupnp-1.0) pkg_check_modules(GSSDP REQUIRED gssdp-1.2) +if (NOT ENABLE_UNIT_TESTING) + pkg_check_modules(GUPNP REQUIRED gupnp-1.0) + add_definitions(-DGUPNP_1_0) + add_definitions(-DENABLE_ROUTER_DISCOVERY_MAIN) +else () + pkg_check_modules(GUPNP REQUIRED gupnp-1.2) +endif (ENABLE_UNIT_TESTING) if (USE_TELEMETRY) find_package(telemetry_msgsender REQUIRED) @@ -34,9 +40,11 @@ if (USE_TELEMETRY) include_directories(${TELEMETRY_INCLUDE_DIRS}) endif (USE_TELEMETRY) -add_executable(${MODULE_NAME} UpnpDiscoveryManager.cpp) -target_include_directories(${MODULE_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${GLIB_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS} ${GUPNP_INCLUDE_DIRS} ${GSSDP_INCLUDE_DIRS}) -target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES} ${LIBSOUP_LIBRARIES} ${GUPNP_LIBRARIES} ${GSSDP_LIBRARIES}) +if (NOT ENABLE_UNIT_TESTING) + add_executable(${MODULE_NAME} UpnpDiscoveryManager.cpp) + target_include_directories(${MODULE_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${GLIB_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS} ${GUPNP_INCLUDE_DIRS} ${GSSDP_INCLUDE_DIRS}) + target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES} ${LIBSOUP_LIBRARIES} ${GUPNP_LIBRARIES} ${GSSDP_LIBRARIES}) +endif (ENABLE_UNIT_TESTING) if (USE_TELEMETRY) target_link_libraries(${MODULE_NAME} PRIVATE ${TELEMETRY_LIBRARIES}) diff --git a/tools/upnp/UpnpDiscoveryManager.cpp b/tools/upnp/UpnpDiscoveryManager.cpp index c1e1f1b7b..657aaff78 100644 --- a/tools/upnp/UpnpDiscoveryManager.cpp +++ b/tools/upnp/UpnpDiscoveryManager.cpp @@ -56,7 +56,11 @@ gboolean UpnpDiscoveryManager::initialiseUpnp(const std::string& interface) do { // Create a gupnp context + #ifdef GUPNP_1_0 m_context = gupnp_context_new(NULL, interface.c_str(), UPNP_DISCOVERY_PORT, &error); + #else + m_context = gupnp_context_new(interface.c_str(), UPNP_DISCOVERY_PORT, &error); + #endif if (!m_context) { LOG_ERR("Error creating Upnp context: %s", error->message); @@ -180,7 +184,7 @@ void UpnpDiscoveryManager::exitWait() m_mainLoop = NULL; } } - +#if ENABLE_ROUTER_DISCOVERY_MAIN int main(int argc, char *argv[]) { if (argc < 2) @@ -197,3 +201,4 @@ int main(int argc, char *argv[]) } return 1; } +#endif From 55649ef95a152d4ff4a46f3410c960804bf89a96 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Mon, 24 Mar 2025 15:36:54 -0400 Subject: [PATCH 105/271] RDKEMW-2673 : Build separate library NetworkManagerImpl.so for out-of-process & Update Makefiles to install all (#122) * RDKEMW-2673 : Split the Plugin library into in-process and out-of-process libraries * Updated CMakeLists.txt * Updated the workflow Signed-off-by: kamirt573_comcast --- ...gration_stateless_diffscan_target_repo.yml | 6 +-- .github/workflows/gnome_unit_test.yml | 4 +- .github/workflows/rdk_unit_test.yml | 4 +- .../FindT2.cmake | 22 ++++----- interface/CMakeLists.txt | 6 ++- plugin/CMakeLists.txt | 45 +++++++++++++------ plugin/NetworkManager.conf.in | 1 + tools/upnp/CMakeLists.txt | 45 ++++++++++++++----- .../scripts/getRouterInfo-NMdispatcher.sh | 0 tools/upnp/scripts/getRouterInfo-nlmon.sh | 0 tools/upnp/scripts/readyToGetRouterInfo.sh | 0 11 files changed, 87 insertions(+), 46 deletions(-) rename tools/upnp/cmake/Findtelemetry_msgsender.cmake => cmake/FindT2.cmake (61%) mode change 100644 => 100755 tools/upnp/scripts/getRouterInfo-NMdispatcher.sh mode change 100644 => 100755 tools/upnp/scripts/getRouterInfo-nlmon.sh mode change 100644 => 100755 tools/upnp/scripts/readyToGetRouterInfo.sh diff --git a/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml b/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml index f5989a6cb..704552151 100644 --- a/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml +++ b/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml @@ -1,9 +1,7 @@ name: Fossid Stateless Diff Scan -on: - pull_request: - branches: - - develop +on: pull_request + jobs: call-fossid-workflow: uses: rdkcentral/build_tools_workflows/.github/workflows/fossid_integration_stateless_diffscan.yml@develop diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index 200895161..05edeca5c 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -2,9 +2,9 @@ name: gnome_unit_test on: push: - branches: [ main, develop, 'release/**'] + branches: [ main, develop, 'release/**', 'hotfix/**', 'feature/**'] pull_request: - branches: [ main, develop, 'release/**'] + branches: [ main, develop, 'release/**', 'hotfix/**', 'feature/**'] env: THUNDER_REF: "R4.4.1" diff --git a/.github/workflows/rdk_unit_test.yml b/.github/workflows/rdk_unit_test.yml index 4964d6489..6c23ab3c1 100644 --- a/.github/workflows/rdk_unit_test.yml +++ b/.github/workflows/rdk_unit_test.yml @@ -2,9 +2,9 @@ name: rdk_unit_test on: push: - branches: [ main, develop, 'release/**'] + branches: [ main, develop, 'release/**', 'hotfix/**', 'feature/**'] pull_request: - branches: [ main, develop, 'release/**'] + branches: [ main, develop, 'release/**', 'hotfix/**', 'feature/**'] env: THUNDER_REF: "R4.4.1" diff --git a/tools/upnp/cmake/Findtelemetry_msgsender.cmake b/cmake/FindT2.cmake similarity index 61% rename from tools/upnp/cmake/Findtelemetry_msgsender.cmake rename to cmake/FindT2.cmake index 64ef7f51a..e26c834a2 100644 --- a/tools/upnp/cmake/Findtelemetry_msgsender.cmake +++ b/cmake/FindT2.cmake @@ -19,19 +19,19 @@ find_package(PkgConfig) -find_library(TELEMETRY_LIBRARIES NAMES telemetry_msgsender) -find_path(TELEMETRY_INCLUDE_DIRS NAMES telemetry_busmessage_sender.h) +find_library(T2_LIBRARIES NAMES telemetry_msgsender) +find_path(T2_INCLUDE_DIRS NAMES telemetry_busmessage_sender.h) -set(TELEMETRY_LIBRARIES ${TELEMETRY_LIBRARIES} CACHE PATH "Path to telemetry library") -set(TELEMETRY_INCLUDE_DIRS ${TELEMETRY_INCLUDE_DIRS} ) -set(TELEMETRY_INCLUDE_DIRS ${TELEMETRY_INCLUDE_DIRS} CACHE PATH "Path to telemetry include") +set(T2_LIBRARIES ${T2_LIBRARIES} CACHE PATH "Path to telemetry library") +set(T2_INCLUDE_DIRS ${T2_INCLUDE_DIRS} ) +set(T2_INCLUDE_DIRS ${T2_INCLUDE_DIRS} CACHE PATH "Path to telemetry include") include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(TELEMETRY DEFAULT_MSG TELEMETRY_INCLUDE_DIRS TELEMETRY_LIBRARIES) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(T2 DEFAULT_MSG T2_INCLUDE_DIRS T2_LIBRARIES) mark_as_advanced( - TELEMETRY_FOUND - TELEMETRY_INCLUDE_DIRS - TELEMETRY_LIBRARIES - TELEMETRY_LIBRARY_DIRS - TELEMETRY_FLAGS) + T2_FOUND + T2_INCLUDE_DIRS + T2_LIBRARIES + T2_LIBRARY_DIRS + T2_FLAGS) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 080eef63a..2f3a0bbba 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -29,4 +29,8 @@ if(NOT GENERATOR_SEARCH_PATH) set(GENERATOR_SEARCH_PATH ${CMAKE_SYSROOT}${CMAKE_INSTALL_PREFIX}/include/${NAMESPACE}) endif() -ProxyStubGenerator(INPUT "${CMAKE_CURRENT_SOURCE_DIR}" OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/generated" INCLUDE_PATH ${GENERATOR_SEARCH_PATH}) +file(GLOB INTERFACE_HEADER ${CMAKE_CURRENT_SOURCE_DIR}) + +ProxyStubGenerator(INPUT "${INTERFACE_HEADER}" OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/generated" INCLUDE_PATH ${GENERATOR_SEARCH_PATH}) + +install(FILES INetworkManager.h DESTINATION include/${NAMESPACE}/interfaces) diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 42b6e60b0..d94067aa0 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -20,6 +20,7 @@ message("Build ${PROJECT_NAME} v${PROJECT_VERSION}") set(PLUGIN_NAME NetworkManager) set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) +set(MODULE_IMPL_NAME ${NAMESPACE}${PLUGIN_NAME}Impl) find_package(${NAMESPACE}Core REQUIRED) find_package(${NAMESPACE}Plugins REQUIRED) @@ -59,9 +60,6 @@ add_library(${MODULE_NAME} SHARED NetworkManager.cpp NetworkManagerJsonRpc.cpp NetworkManagerLogger.cpp - NetworkManagerImplementation.cpp - NetworkManagerConnectivity.cpp - NetworkManagerStunClient.cpp Module.cpp ${PROXY_STUB_SOURCES}) @@ -75,45 +73,64 @@ set_target_properties(${MODULE_NAME} PROPERTIES CXX_STANDARD_REQUIRED YES FRAMEWORK FALSE) +add_library(${MODULE_IMPL_NAME} SHARED + NetworkManagerImplementation.cpp + NetworkManagerConnectivity.cpp + NetworkManagerStunClient.cpp + NetworkManagerLogger.cpp + Module.cpp + ${PROXY_STUB_SOURCES}) if(ENABLE_GNOME_NETWORKMANAGER) if(ENABLE_GNOME_GDBUS) message("networkmanager building with gdbus") - target_sources(${MODULE_NAME} PRIVATE + target_sources(${MODULE_IMPL_NAME} PRIVATE gnome/gdbus/NetworkManagerGdbusProxy.cpp gnome/gdbus/NetworkManagerGdbusClient.cpp gnome/gdbus/NetworkManagerGdbusEvent.cpp gnome/gdbus/NetworkManagerGdbusMgr.cpp gnome/gdbus/NetworkManagerGdbusUtils.cpp NetworkManagerSecretAgent.cpp) - target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) - target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES} ${GIO_LIBRARIES} uuid) + target_include_directories(${MODULE_IMPL_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) + target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${GLIB_LIBRARIES} ${GIO_LIBRARIES} uuid) else() message("networkmanager building with libnm") - target_sources(${MODULE_NAME} PRIVATE + target_sources(${MODULE_IMPL_NAME} PRIVATE gnome/NetworkManagerGnomeProxy.cpp gnome/NetworkManagerGnomeWIFI.cpp gnome/NetworkManagerGnomeEvents.cpp gnome/NetworkManagerGnomeUtils.cpp NetworkManagerSecretAgent.cpp ) - target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) - target_link_libraries(${MODULE_NAME} PRIVATE ${LIBNM_LIBRARIES}) + target_include_directories(${MODULE_IMPL_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) + target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${LIBNM_LIBRARIES}) endif() else() message("networkmanager building with RDK netsrvmgr") - target_sources(${MODULE_NAME} PRIVATE rdk/NetworkManagerRDKProxy.cpp) - target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) - target_link_libraries(${MODULE_NAME} PRIVATE ${IARMBUS_LIBRARIES}) + target_sources(${MODULE_IMPL_NAME} PRIVATE rdk/NetworkManagerRDKProxy.cpp) + target_include_directories(${MODULE_IMPL_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) + target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${IARMBUS_LIBRARIES}) endif() -target_link_libraries(${MODULE_NAME} PRIVATE ${CURL_LIBRARIES}) -target_include_directories(${MODULE_NAME} PRIVATE ${CURL_INCLUDE_DIRS}) +set_target_properties(${MODULE_IMPL_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES + FRAMEWORK FALSE) + +target_link_libraries(${MODULE_IMPL_NAME} PRIVATE + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ) + +target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${CURL_LIBRARIES}) +target_include_directories(${MODULE_IMPL_NAME} PRIVATE ${CURL_INCLUDE_DIRS}) if (USE_RDK_LOGGER) target_link_libraries(${MODULE_NAME} PRIVATE ${RDKLOGGER_LIBRARIES}) + target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${RDKLOGGER_LIBRARIES}) endif (USE_RDK_LOGGER) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) +install(TARGETS ${MODULE_IMPL_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) #Generate Plugin configuration file write_config() diff --git a/plugin/NetworkManager.conf.in b/plugin/NetworkManager.conf.in index 49b18e465..379907bb0 100644 --- a/plugin/NetworkManager.conf.in +++ b/plugin/NetworkManager.conf.in @@ -4,6 +4,7 @@ autostart = "true" process= JSON() process.add("outofprocess", "true") +process.add("locator", "lib@MODULE_IMPL_NAME@.so") connectivity = JSON() connectivity.add("endpoint_1", "@PLUGIN_NETWORKMANAGER_CONN_ENDPOINT_1@") diff --git a/tools/upnp/CMakeLists.txt b/tools/upnp/CMakeLists.txt index 110c6e2d8..1cfa40e84 100644 --- a/tools/upnp/CMakeLists.txt +++ b/tools/upnp/CMakeLists.txt @@ -26,26 +26,47 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(LIBSOUP REQUIRED libsoup-2.4) pkg_check_modules(GSSDP REQUIRED gssdp-1.2) -if (NOT ENABLE_UNIT_TESTING) +pkg_check_modules(GUPNP gupnp-1.2) + +if (NOT GUPNP_FOUND) pkg_check_modules(GUPNP REQUIRED gupnp-1.0) add_definitions(-DGUPNP_1_0) - add_definitions(-DENABLE_ROUTER_DISCOVERY_MAIN) -else () - pkg_check_modules(GUPNP REQUIRED gupnp-1.2) -endif (ENABLE_UNIT_TESTING) +endif () if (USE_TELEMETRY) - find_package(telemetry_msgsender REQUIRED) + find_package(T2 REQUIRED) add_definitions(-DUSE_TELEMETRY) include_directories(${TELEMETRY_INCLUDE_DIRS}) endif (USE_TELEMETRY) -if (NOT ENABLE_UNIT_TESTING) - add_executable(${MODULE_NAME} UpnpDiscoveryManager.cpp) - target_include_directories(${MODULE_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${GLIB_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS} ${GUPNP_INCLUDE_DIRS} ${GSSDP_INCLUDE_DIRS}) - target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES} ${LIBSOUP_LIBRARIES} ${GUPNP_LIBRARIES} ${GSSDP_LIBRARIES}) -endif (ENABLE_UNIT_TESTING) +add_definitions(-DENABLE_ROUTER_DISCOVERY_MAIN) + +add_executable(${MODULE_NAME} UpnpDiscoveryManager.cpp) +target_include_directories(${MODULE_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${GLIB_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS} ${GUPNP_INCLUDE_DIRS} ${GSSDP_INCLUDE_DIRS}) +target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES} ${LIBSOUP_LIBRARIES} ${GUPNP_LIBRARIES} ${GSSDP_LIBRARIES}) if (USE_TELEMETRY) - target_link_libraries(${MODULE_NAME} PRIVATE ${TELEMETRY_LIBRARIES}) + target_link_libraries(${MODULE_NAME} PRIVATE ${T2_LIBRARIES}) endif (USE_TELEMETRY) + +install(TARGETS ${MODULE_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +if(ENABLE_GNOME_NETWORKMANAGER) +install(PROGRAMS scripts/getRouterInfo-NMdispatcher.sh + DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/rdk + RENAME getRouterInfo.sh) +else () +install(PROGRAMS scripts/getRouterInfo-nlmon.sh + DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/rdk + RENAME getRouterInfo.sh) +endif () + +install(PROGRAMS + scripts/readyToGetRouterInfo.sh + DESTINATION + ${CMAKE_INSTALL_PREFIX}/../lib/rdk) + +install(FILES + scripts/routerDiscovery@.service + DESTINATION + ${CMAKE_INSTALL_PREFIX}/../lib/systemd/system) diff --git a/tools/upnp/scripts/getRouterInfo-NMdispatcher.sh b/tools/upnp/scripts/getRouterInfo-NMdispatcher.sh old mode 100644 new mode 100755 diff --git a/tools/upnp/scripts/getRouterInfo-nlmon.sh b/tools/upnp/scripts/getRouterInfo-nlmon.sh old mode 100644 new mode 100755 diff --git a/tools/upnp/scripts/readyToGetRouterInfo.sh b/tools/upnp/scripts/readyToGetRouterInfo.sh old mode 100644 new mode 100755 From 1687b5a0a6edcad71a63f159ab0b962f53772854 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Tue, 25 Mar 2025 08:31:04 +0530 Subject: [PATCH 106/271] RDKEMW-1892 WifiConnect fails for NetworkManager (#125) Calling WifiConnect without SSID must attempt to connect to last connected or to any of the available known SSID. --- plugin/NetworkManagerImplementation.cpp | 2 + plugin/NetworkManagerImplementation.h | 1 + plugin/NetworkManagerJsonRpc.cpp | 50 ++++++++-------- plugin/gnome/NetworkManagerGnomeProxy.cpp | 16 ++--- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 72 ++++++++++++++++++++++- plugin/gnome/NetworkManagerGnomeWIFI.h | 1 + 6 files changed, 108 insertions(+), 34 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 1a9983ddb..99e0399d8 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -848,6 +848,8 @@ namespace WPEFramework NMLOG_DEBUG("checking WiFi signal strength"); GetWiFiSignalQuality(ssid, strength, noise, snr, newSignalQuality); + m_lastConnectedSSID = ssid; // last connected ssid used in wifiConnect + if (oldSignalQuality != newSignalQuality) { NMLOG_INFO("Notifying WiFiSignalQualityChangedEvent %s", strength.c_str()); oldSignalQuality = newSignalQuality; diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 1c7d3d949..3612d6a61 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -291,6 +291,7 @@ namespace WPEFramework public: std::atomic m_ethConnected; std::atomic m_wlanConnected; + std::string m_lastConnectedSSID; mutable ConnectivityMonitor connectivityMonitor; }; } diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index cb05dcbde..e4ab123cc 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -753,33 +753,35 @@ namespace WPEFramework NMLOG_INFO("Entry to %s", __FUNCTION__); if (parameters.HasLabel("ssid")) + { ssid.ssid = parameters["ssid"].String(); - else - returnJson(rc); - if (parameters.HasLabel("passphrase")) - ssid.passphrase = parameters["passphrase"].String(); - - if (parameters.HasLabel("security")) - ssid.security= static_cast (parameters["security"].Number()); - - // Check Security modes - if (parameters.HasLabel("eap")) - ssid.eap = parameters["eap"].String(); - if (parameters.HasLabel("eap_identity")) - ssid.eap_identity = parameters["eap_identity"].String(); - if (parameters.HasLabel("ca_cert")) - ssid.ca_cert = parameters["ca_cert"].String(); - if (parameters.HasLabel("client_cert")) - ssid.client_cert = parameters["client_cert"].String(); - if (parameters.HasLabel("private_key")) - ssid.private_key = parameters["private_key"].String(); - if (parameters.HasLabel("private_key_passwd")) - ssid.private_key_passwd = parameters["private_key_passwd"].String(); - if (parameters.HasLabel("persist")) - ssid.persist = parameters["persist"].Boolean(); + if (parameters.HasLabel("passphrase")) + ssid.passphrase = parameters["passphrase"].String(); + + if (parameters.HasLabel("security")) + ssid.security= static_cast (parameters["security"].Number()); + + // Check Security modes + if (parameters.HasLabel("eap")) + ssid.eap = parameters["eap"].String(); + if (parameters.HasLabel("eap_identity")) + ssid.eap_identity = parameters["eap_identity"].String(); + if (parameters.HasLabel("ca_cert")) + ssid.ca_cert = parameters["ca_cert"].String(); + if (parameters.HasLabel("client_cert")) + ssid.client_cert = parameters["client_cert"].String(); + if (parameters.HasLabel("private_key")) + ssid.private_key = parameters["private_key"].String(); + if (parameters.HasLabel("private_key_passwd")) + ssid.private_key_passwd = parameters["private_key_passwd"].String(); + if (parameters.HasLabel("persist")) + ssid.persist = parameters["persist"].Boolean(); + else + ssid.persist = true; + } else - ssid.persist = true; + NMLOG_WARNING("ssid not included in wifi connect request !"); if (_networkManager) rc = _networkManager->WiFiConnect(ssid); diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 4808c99d3..a4670c08f 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -664,24 +664,24 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::WiFiConnect(const WiFiConnectTo& ssid /* @in */) { uint32_t rc = Core::ERROR_GENERAL; - if(ssid.ssid.empty() || ssid.ssid.size() > 32) - { - NMLOG_WARNING("ssid is invalied"); - return rc; - } // Check the last scanning time and if it exceeds 5 sec do a rescanning if(!wifi->isWifiScannedRecently()) { nmEvent->setwifiScanOptions(false); if(!wifi->wifiScanRequest()) - { NMLOG_WARNING("scanning failed but try to connect"); - } } - if(wifi->wifiConnect(ssid)) + if(ssid.ssid.empty() && _instance != NULL) + { + NMLOG_WARNING("ssid is empty activating last connectd ssid !"); + if(wifi->activateKnownWifiConnection(_instance->m_lastConnectedSSID)) + rc = Core::ERROR_NONE; + } + else if(wifi->wifiConnect(ssid)) rc = Core::ERROR_NONE; + return rc; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 37b57a448..f7d0f5149 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -383,7 +383,7 @@ namespace WPEFramework static void wifiConnectionUpdate(GObject *rmObject, GAsyncResult *res, gpointer user_data) { - NMRemoteConnection *remote_con = NM_REMOTE_CONNECTION(rmObject); + NMRemoteConnection *remote_con = NM_REMOTE_CONNECTION(rmObject); wifiManager *_wifiManager = (static_cast(user_data)); GVariant *ret = NULL; GError *error = NULL; @@ -540,6 +540,74 @@ namespace WPEFramework return true; } + bool wifiManager::activateKnownWifiConnection(std::string knownssid) + { + NMAccessPoint *AccessPoint = NULL; + const GPtrArray *wifiConnections = NULL; + NMConnection *m_connection = NULL; + const GPtrArray* ApList = NULL; + const char* specificObjPath = "/"; + + if(!createClientNewConnection()) + return false; + + NMDevice *m_wifidevice = getWifiDevice(); + if(m_wifidevice == NULL) { + NMLOG_WARNING("wifi state is unmanaged !"); + return false; + } + + nm_device_set_autoconnect(m_wifidevice, true); // set autoconnect true + + if(knownssid.empty()) + { + NMLOG_WARNING("ssid not specified !"); + return false; + } + + wifiConnections = nm_device_get_available_connections(m_wifidevice); + if(wifiConnections == NULL) + { + NMLOG_WARNING("No wifi connection found !"); + return false; + } + + for (guint i = 0; i < wifiConnections->len; i++) + { + NMConnection *connection = static_cast(g_ptr_array_index(wifiConnections, i)); + if(connection == NULL) + continue; + + const char *connId = nm_connection_get_id(NM_CONNECTION(connection)); + if (connId != NULL && strcmp(connId, knownssid.c_str()) == 0) + { + m_connection = g_object_ref(connection); + NMLOG_DEBUG("connection '%s' exists !", knownssid.c_str()); + if (m_connection == NULL) + { + NMLOG_ERROR("m_connection == NULL smothing went worng"); + return false; + } + break; + } + } + + m_isSuccess = false; + if (m_connection != NULL && NM_IS_REMOTE_CONNECTION(m_connection)) + { + NMLOG_INFO("activating known wifi '%s' connection", knownssid.c_str()); + m_createNewConnection = false; // no need to create new connection + nm_client_activate_connection_async(m_client, NM_CONNECTION(m_connection), m_wifidevice, specificObjPath, NULL, wifiConnectCb, this); + wait(m_loop); + } + else + { + NMLOG_ERROR("'%s' connection not found !", knownssid.c_str()); + } + + return m_isSuccess; + } + bool wifiManager::wifiConnect(Exchange::INetworkManager::WiFiConnectTo ssidInfo) { NMAccessPoint *AccessPoint = NULL; @@ -856,7 +924,7 @@ namespace WPEFramework } if (!ssids.empty()) { - NMLOG_DEBUG("known wifi connections are %s", ssidPrint.c_str()); + NMLOG_INFO("known wifi connections are %s", ssidPrint.c_str()); return true; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 222c23909..136a29d5b 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -49,6 +49,7 @@ namespace WPEFramework bool isWifiConnected(); bool wifiDisconnect(); + bool activateKnownWifiConnection(std::string knownssid); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); bool wifiConnect(Exchange::INetworkManager::WiFiConnectTo ssidInfo); bool wifiScanRequest(std::string ssidReq = ""); From 44015c7b33489c9be24915c321f15d2ef86c32ff Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 27 Mar 2025 21:46:08 +0530 Subject: [PATCH 107/271] RDKEMW-1447, RDKEMW-2788, RDKEMW-2666 WPS - Screen is stuck Issue (#127) * WPS operation time out updated * WPS Wait updated * Event posting added * SSID restriction added * GetConnectedSSID changed to return only when its valid/usable (ie IP address set) --- plugin/NetworkManagerSecretAgent.cpp | 40 ++++++++----- plugin/NetworkManagerSecretAgent.h | 2 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 19 ++++-- plugin/gnome/NetworkManagerGnomeProxy.cpp | 9 ++- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 68 ++++++++++++++++------ 5 files changed, 96 insertions(+), 42 deletions(-) diff --git a/plugin/NetworkManagerSecretAgent.cpp b/plugin/NetworkManagerSecretAgent.cpp index 7bfec9664..fa487a0cd 100644 --- a/plugin/NetworkManagerSecretAgent.cpp +++ b/plugin/NetworkManagerSecretAgent.cpp @@ -21,7 +21,9 @@ #include #include #include - +#include +#include +#include #include #include @@ -35,7 +37,9 @@ namespace WPEFramework { namespace Plugin { - std::atomicstopwait; + std::condition_variable m_SecretsAgentCv; + std::mutex m_SecretsAgentMutex; + bool cvCondition = false; // avoid spurious wakeup static const gchar interfaceXml[] = "" " " @@ -97,9 +101,8 @@ namespace WPEFramework flagStr += ", allow_interaction"; if(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED) { flagStr += ", user_requested"; - stopwait.store(false); /* wait for 10 sec mean time in the background networkmanager will do wps operation */ - SecretAgent::wait(static_cast(10)); + SecretAgent::wait(10); // 10 sec } NMLOG_INFO("SecretAgent GetSecrets Flags = %u %s", flags, flagStr.c_str()); } @@ -165,24 +168,28 @@ namespace WPEFramework g_object_unref(GDBusconn); } - void SecretAgent::wait(const std::chrono::seconds timeout) + void SecretAgent::wait(int timeoutInSec) { - NMLOG_INFO("wait started %ld Sec", timeout.count()); - auto start = std::chrono::high_resolution_clock::now(); - while (stopwait.load() == false) - { - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - if (std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start) >= timeout) - { - return; - } + NMLOG_INFO("wait started %d Sec", timeoutInSec); + std::unique_lock lock(m_SecretsAgentMutex); + if (m_SecretsAgentCv.wait_for(lock, std::chrono::seconds(timeoutInSec), [] { return cvCondition; })) { + NMLOG_INFO("SecretAgent received a cancel request. skipping %d sec wait", timeoutInSec); + // Reset the flag to avoid spurious wakeup on a condition variable + cvCondition = false; + } else { + NMLOG_INFO("SecretAgent wait time %d sec complete", timeoutInSec); } } void SecretAgent::stopWait() { - stopwait.store(true); - NMLOG_INFO("wait exit"); + NMLOG_INFO("stopWait Entry"); + { + std::unique_lock lock(m_SecretsAgentMutex); + cvCondition = true; + } + m_SecretsAgentCv.notify_one(); + NMLOG_INFO("stopWait Exit"); } void SecretAgent::SecretAgentLoop(SecretAgent* SecretAgentPtr) @@ -258,6 +265,7 @@ namespace WPEFramework void SecretAgent::stopSecurityAgent() { + stopWait(); if (agentGmainLoop) { g_main_loop_quit(agentGmainLoop); } diff --git a/plugin/NetworkManagerSecretAgent.h b/plugin/NetworkManagerSecretAgent.h index 4c2ccb9d2..816f05196 100644 --- a/plugin/NetworkManagerSecretAgent.h +++ b/plugin/NetworkManagerSecretAgent.h @@ -40,7 +40,7 @@ namespace WPEFramework bool RegisterAgent(); bool UnregisterAgent(); static void SecretAgentLoop(SecretAgent* agent); - static void wait(const std::chrono::seconds timeout); + static void wait(int timeout); static void stopWait(); private: std::atomic isSecretAgentLoopRunning; diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index ce8d1efe6..7fcbff2ed 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -79,15 +79,14 @@ namespace WPEFramework NMDeviceState deviceState; deviceState = nm_device_get_state(device); std::string ifname = nm_device_get_iface(device); + NMDeviceStateReason reason = nm_device_get_state_reason(device); if(ifname == nmUtils::wlanIface()) { if(!NM_IS_DEVICE_WIFI(device)) { NMLOG_FATAL("not a wifi device !"); return; } - NMDeviceStateReason reason = nm_device_get_state_reason(device); std::string wifiState; - // NMLOG_DEBUG("\033[0;31m NMDeviceStateReason %d \033[0m",reason); switch (reason) { case NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE: @@ -139,13 +138,21 @@ namespace WPEFramework case NM_DEVICE_STATE_PREPARE: wifiState = "WIFI_STATE_PAIRING"; GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_PAIRING); - GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_UP, nmUtils::wlanIface()); break; case NM_DEVICE_STATE_CONFIG: wifiState = "WIFI_STATE_CONNECTING"; GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTING); break; + case NM_DEVICE_STATE_IP_CONFIG: + wifiState = "NM_DEVICE_STATE_IP_CONFIG"; + GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_UP, nmUtils::wlanIface()); + break; case NM_DEVICE_STATE_IP_CHECK: + wifiState = "NM_DEVICE_STATE_IP_CHECK"; + //GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP, nmUtils::wlanIface()); + break; + case NM_DEVICE_STATE_SECONDARIES: + wifiState = "NM_DEVICE_STATE_SECONDARIES"; GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP, nmUtils::wlanIface()); break; case NM_DEVICE_STATE_ACTIVATED: @@ -178,7 +185,7 @@ namespace WPEFramework break; } } - NMLOG_DEBUG("wifi state: %s", wifiState.c_str()); + NMLOG_INFO("wifi state: %s; reason: %d", wifiState.c_str(), static_cast(reason)); } else if(ifname == nmUtils::ethIface()) { @@ -211,9 +218,9 @@ namespace WPEFramework isEthDisabled = false; GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, nmUtils::ethIface()); } - } - NMLOG_DEBUG("%s state: (%d)", ifname.c_str(), deviceState); + NMLOG_INFO("eth0 state: %d; reason: %d", static_cast(deviceState), static_cast(reason)); + } } static void ip4ChangedCb(NMIPConfig *ipConfig, GParamSpec *pspec, gpointer userData) diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index a4670c08f..bbd0ab8ad 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -679,8 +679,13 @@ namespace WPEFramework if(wifi->activateKnownWifiConnection(_instance->m_lastConnectedSSID)) rc = Core::ERROR_NONE; } - else if(wifi->wifiConnect(ssid)) - rc = Core::ERROR_NONE; + else if(ssid.ssid.size() < 32) + { + if(wifi->wifiConnect(ssid)) + rc = Core::ERROR_NONE; + } + else + NMLOG_WARNING("SSID is invalid"); return rc; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index f7d0f5149..8be6ab862 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -261,20 +261,27 @@ namespace WPEFramework if(!createClientNewConnection()) return false; - NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getWifiDevice()); + NMDevice* wifiDevice = getWifiDevice(); if(wifiDevice == NULL) { NMLOG_FATAL("NMDeviceWifi * NULL !"); return false; } - NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(wifiDevice); - if(activeAP == NULL) { - NMLOG_DEBUG("No active access point found !"); - return false; + NMDeviceState deviceState = nm_device_get_state(wifiDevice); + if(deviceState >= NM_DEVICE_STATE_IP_CONFIG) + { + NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(NM_DEVICE_WIFI(wifiDevice)); + if(activeAP == NULL) { + NMLOG_ERROR("NMAccessPoint = NULL !"); + return false; + } + NMLOG_DEBUG("active access point found !"); + getApInfo(activeAP, ssidinfo); + return true; } else - NMLOG_DEBUG("active access point found !"); - getApInfo(activeAP, ssidinfo); + NMLOG_WARNING("no active access point!; wifi device state: (%d)", deviceState); + return true; } @@ -425,7 +432,8 @@ namespace WPEFramework GBytes *ssid = g_bytes_new(ssidinfo.ssid.c_str(), strlen(ssidinfo.ssid.c_str())); g_object_set(G_OBJECT(sWireless), NM_SETTING_WIRELESS_SSID, ssid, NULL); // ssid in Gbyte g_object_set(G_OBJECT(sWireless), NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA, NULL); // infra mode - g_object_set(G_OBJECT(sWireless), NM_SETTING_WIRELESS_HIDDEN, true, NULL); // hidden = true + if(!iswpsAP) // wps never be a hidden AP, it will be always visible + g_object_set(G_OBJECT(sWireless), NM_SETTING_WIRELESS_HIDDEN, true, NULL); // hidden = true // 'bssid' parameter is used to restrict the connection only to the BSSID // g_object_set(s_wifi, NM_SETTING_WIRELESS_BSSID, bssid, NULL); @@ -618,6 +626,8 @@ namespace WPEFramework Exchange::INetworkManager::WiFiSSIDInfo apinfo; std::string activeSSID{}; + NMLOG_INFO("wifi connect ssid: %s, security %d persist %d", ssidInfo.ssid.c_str(), ssidInfo.security, ssidInfo.persist); + m_isSuccess = false; if(!createClientNewConnection()) return false; @@ -1101,17 +1111,23 @@ namespace WPEFramework Exchange::INetworkManager::WiFiConnectTo ssidInfo{}; bool wpsComplete= false; - for(int retry =0; retry < WPS_RETRY_COUNT; retry++) + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTING); + + for(int retry = 0; retry < WPS_RETRY_COUNT; retry++) { sleep(WPS_RETRY_WAIT_IN_MS); if(wpsProcessRun.load() == false) // stop wps process if reuested + { + NMLOG_INFO("stop wps process reuested"); break; + } wpsContext = g_main_context_new(); if(wpsContext == NULL) { NMLOG_ERROR("wpsContext create failed !!"); - return; + break; } if(!g_main_context_acquire(wpsContext)) @@ -1121,26 +1137,26 @@ namespace WPEFramework } g_main_context_push_thread_default(wpsContext); - + NMClient* client = nm_client_new(NULL, &error); if (!client && error != NULL) { NMLOG_ERROR("Could not connect to NetworkManager: %s.", error->message); g_error_free(error); - return; + break; } NMDevice* wifidevice = nm_client_get_device_by_iface(client, nmUtils::wlanIface()); if(wifidevice == NULL) { NMLOG_ERROR("Failed to get device list."); - return; + break; } ApList = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(wifidevice)); if(ApList == NULL) { NMLOG_ERROR("Aplist Error !"); - return; + break; } if(findWpsPbcSSID(ApList, wpsApSsid, &wpsAp) && wpsAp != NULL) @@ -1155,8 +1171,12 @@ namespace WPEFramework NMLOG_INFO("WPS process stoped connected to '%s' wps ap ", wpsApSsid.c_str()); wpsComplete = true; } - else { - // some other ssid connected; wps need a disconnected wifi device + + NMDeviceState state = nm_device_get_state(wifidevice); + if(!wpsComplete && state > NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_INFO("stopping the ongoing Wi-Fi connection"); + // some other ssid connected or connecting; wps need a disconnected wifi state nm_device_disconnect(wifidevice, NULL, &error); if (error) NMLOG_ERROR("disconnect connection failed %s", error->message); @@ -1199,7 +1219,6 @@ namespace WPEFramework else { //TODO Post SSID lost event ? - NMLOG_ERROR("request for wifi scanning"); nm_device_wifi_request_scan(NM_DEVICE_WIFI(wifidevice), NULL, &error); } @@ -1210,7 +1229,22 @@ namespace WPEFramework g_main_context_unref(wpsContext); } + + if(wpsAp == NULL) + { + NMLOG_WARNING("WPS AP not found"); + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + } + else if(!wpsComplete) + { + NMLOG_INFO("WPS process Error"); + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED); + } + wpsProcessRun = false; + NMLOG_INFO("WPS process thread exist"); } bool wifiManager::startWPS() From 5e5d72897c11de889c50e9065e2f276d5a3ed8f8 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Mon, 31 Mar 2025 11:35:16 -0400 Subject: [PATCH 108/271] Update the method to Identify Open SSIDs & Filtering method of scan results (#128) - Update the method used to detect open SSID - Print the Discovered SSIDs in format - Print the WIFI Security Mode detected as INFO - Frequency Filtering of scan results updated Signed-off-by: kamirt573_comcast --- legacy/LegacyWiFiManagerAPIs.cpp | 5 ++- plugin/NetworkManagerImplementation.cpp | 40 +++++++++++-------- plugin/NetworkManagerImplementation.h | 1 + plugin/NetworkManagerJsonRpc.cpp | 2 +- plugin/NetworkManagerLogger.cpp | 2 - plugin/gnome/NetworkManagerGnomeUtils.cpp | 10 +++-- plugin/gnome/NetworkManagerGnomeUtils.h | 2 +- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 5 +-- .../gnome/gdbus/NetworkManagerGdbusUtils.cpp | 7 ++-- plugin/gnome/gdbus/NetworkManagerGdbusUtils.h | 2 +- 10 files changed, 43 insertions(+), 33 deletions(-) diff --git a/legacy/LegacyWiFiManagerAPIs.cpp b/legacy/LegacyWiFiManagerAPIs.cpp index 036cca6a5..6d9734196 100644 --- a/legacy/LegacyWiFiManagerAPIs.cpp +++ b/legacy/LegacyWiFiManagerAPIs.cpp @@ -923,8 +923,6 @@ namespace WPEFramework JsonArray ssidsUpdated; JsonObject newParameters; JsonArray ssids = parameters["ssids"].Array(); - parameters.ToString(json); - NMLOG_INFO("Posting onAvailableSSIDs Event as %s", json.c_str()); for (int i = 0; i < ssids.Length(); i++) { JsonObject object = ssids[i].Object(); @@ -933,6 +931,9 @@ namespace WPEFramework ssidsUpdated.Add(object); } newParameters["ssids"] = ssidsUpdated; + + newParameters.ToString(json); + NMLOG_INFO("Event with %d SSIDs as, %s", ssids.Length(), json.c_str()); if(_gWiFiInstance) _gWiFiInstance->Notify("onAvailableSSIDs", newParameters); else diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 99e0399d8..60bf250f3 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -536,7 +536,6 @@ namespace WPEFramework if (!m_filterfrequency.empty()) { filterFreq = std::stod(m_filterfrequency); - NMLOG_DEBUG("Frequency provided: %lf\n", filterFreq); } for (int i = 0; i < ssids.Length(); i++) @@ -545,25 +544,13 @@ namespace WPEFramework string ssid = object["ssid"].String(); string frequency = object["frequency"].String(); - NMLOG_DEBUG("Processing SSID: %s, Frequency: %s\n", ssid.c_str(), frequency.c_str()); double frequencyValue = std::stod(frequency); - - //Debug to print log - NMLOG_DEBUG("Processing Frequency after double conversion: %lf\n", frequencyValue); - bool ssidMatches = scanForSsidsSet.empty() || scanForSsidsSet.find(ssid) != scanForSsidsSet.end(); bool freqMatches = m_filterfrequency.empty() || (filterFreq == frequencyValue); if (ssidMatches && freqMatches) - { result.Add(object); - NMLOG_DEBUG("Match found: SSID = %s, Frequency = %lf\n", ssid.c_str(), frequencyValue); - } - else - { - NMLOG_DEBUG("No match: SSID = %s, Frequency = %lf\n", ssid.c_str(), frequencyValue); - } } ssids = result; NMLOG_DEBUG("After filtering, found %d SSIDs.", ssids.Length()); @@ -668,6 +655,25 @@ namespace WPEFramework _notificationLock.Unlock(); } + int32_t NetworkManagerImplementation::logSSIDs(Logging level, const JsonArray &ssids) + { + Logging inLevel; + GetLogLevel(inLevel); + if (level > inLevel) + return ssids.Length(); + + printf ("{\n"); fflush(stdout); + for (int i = 0; i < ssids.Length(); i++) + { + JsonObject ssid = ssids[i].Object(); + string json; + ssid.ToString(json); + printf("\t%s\n", json.c_str()); fflush(stdout); + } + printf("}\n"); fflush(stdout); + return ssids.Length(); + } + void NetworkManagerImplementation::ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults) { _notificationLock.Lock(); @@ -676,13 +682,15 @@ namespace WPEFramework JsonArray filterResult = arrayofWiFiScanResults; arrayofWiFiScanResults.ToString(jsonOfWiFiScanResults); - NMLOG_DEBUG("onAvailableSSIDs Filtering is, %s", jsonOfWiFiScanResults.c_str()); + NMLOG_DEBUG("Discovered %d SSIDs before filtering as,", filterResult.Length()); + logSSIDs(LOG_LEVEL_DEBUG, filterResult); filterScanResults(filterResult); - filterResult.ToString(jsonOfFilterScanResults); - NMLOG_INFO("Posting onAvailableSSIDs event as, %s", jsonOfFilterScanResults.c_str()); + NMLOG_INFO("Posting onAvailableSSIDs event with %d SSIDs as,", filterResult.Length()); + logSSIDs(LOG_LEVEL_INFO, filterResult); + for (const auto callback : _notificationCallbacks) { callback->onAvailableSSIDs(jsonOfFilterScanResults); } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 3612d6a61..d0918b75a 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -267,6 +267,7 @@ namespace WPEFramework void startWiFiSignalQualityMonitor(int interval); void stopWiFiSignalQualityMonitor(); void monitorThreadFunction(int interval); + int32_t logSSIDs(Logging level, const JsonArray &ssids); private: std::list _notificationCallbacks; diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index e4ab123cc..e0567a0fb 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -1000,7 +1000,7 @@ namespace WPEFramework scanResults.FromString(jsonOfScanResults); parameters["ssids"] = scanResults; - LOG_INPARAM(); + NMLOG_INFO("Event with %d SSIDs as, %s", scanResults.Length(), jsonOfScanResults.c_str()); Notify(_T("onAvailableSSIDs"), parameters); } diff --git a/plugin/NetworkManagerLogger.cpp b/plugin/NetworkManagerLogger.cpp index 342a140a1..7b631d37e 100644 --- a/plugin/NetworkManagerLogger.cpp +++ b/plugin/NetworkManagerLogger.cpp @@ -132,10 +132,8 @@ namespace NetworkManagerLogger { void GetLevel(LogLevel& level) { level = gDefaultLogLevel; - NMLOG_INFO("NetworkManager logLevel:%d", level); #ifdef USE_RDK_LOGGER // TODO : Inform RDKLogger to change the log level #endif } - } // namespace NetworkManagerLogger diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index c22bdf82c..4c2685990 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -58,10 +58,12 @@ namespace WPEFramework return deviceState; } - uint8_t nmUtils::wifiSecurityModeFromAp(guint32 flags, guint32 wpaFlags, guint32 rsnFlags) + uint8_t nmUtils::wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags) { uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; - if ((flags == NM_802_11_AP_FLAGS_NONE) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) + NMLOG_INFO("ap [%s] security str %s", ssid.c_str(), nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); + + if ((flags != NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE; else if (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE) security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE; @@ -69,7 +71,7 @@ namespace WPEFramework security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP; else security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - // NMLOG_DEBUG("ap security str %s", nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); + return security; } @@ -225,7 +227,7 @@ namespace WPEFramework wpaFlags = nm_access_point_get_wpa_flags(ap); rsnFlags = nm_access_point_get_rsn_flags(ap); freq = nmUtils::wifiFrequencyFromAp(apFreq); - security = nmUtils::wifiSecurityModeFromAp(flags, wpaFlags, rsnFlags); + security = nmUtils::wifiSecurityModeFromAp(ssidString, flags, wpaFlags, rsnFlags); ssidObj["security"] = security; ssidObj["strength"] = nmUtils::convertPercentageToSignalStrengtStr(strength); diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index 1d7656030..897bb1619 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -38,7 +38,7 @@ namespace WPEFramework static const char* ethIface(); static const char* convertPercentageToSignalStrengtStr(int percentage); static bool caseInsensitiveCompare(const std::string& str1, const std::string& str2); - static uint8_t wifiSecurityModeFromAp(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); + static uint8_t wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags); static std::string wifiFrequencyFromAp(guint32 apFreq); static std::string getSecurityModeString(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); static bool apToJsonObject(NMAccessPoint *ap, JsonObject& ssidObj); diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 8be6ab862..c562652d4 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -228,11 +228,10 @@ namespace WPEFramework NMLOG_DEBUG("bitrate : %s kbit/s", wifiInfo.rate.c_str()); //TODO signal strenght to dBm wifiInfo.strength = std::string(nmUtils::convertPercentageToSignalStrengtStr(strength)); - wifiInfo.security = static_cast(nmUtils::wifiSecurityModeFromAp(flags, wpaFlags, rsnFlags)); + wifiInfo.security = static_cast(nmUtils::wifiSecurityModeFromAp(wifiInfo.ssid, flags, wpaFlags, rsnFlags)); NMLOG_INFO("ssid: %s, frequency: %s, sterngth: %s, security: %u", wifiInfo.ssid.c_str(), wifiInfo.frequency.c_str(), wifiInfo.strength.c_str(), wifiInfo.security); - NMLOG_DEBUG("security string %s", nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); - NMLOG_DEBUG("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); + NMLOG_INFO("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); } bool wifiManager::isWifiConnected() diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp index 4251fb336..746e29efe 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp @@ -150,7 +150,7 @@ namespace WPEFramework const char* GnomeUtils::getWifiIfname() { return ifnameWlan; } const char* GnomeUtils::getEthIfname() { return ifnameEth; } - uint8_t GnomeUtils::wifiSecurityModeFromApFlags(guint32 flags, guint32 wpaFlags, guint32 rsnFlags) + uint8_t GnomeUtils::wifiSecurityModeFromApFlags(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags) { uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; if ((flags == NM_802_11_AP_FLAGS_NONE) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) @@ -161,7 +161,8 @@ namespace WPEFramework security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP; else security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - // NMLOG_DEBUG("ap security str %s", nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); + + //NMLOG_INFO("ap [%s] security str %s", ssid.c_str(), nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); return security; } @@ -402,7 +403,7 @@ namespace WPEFramework std::string freqStr = std::to_string((double)freq/1000); wifiInfo.frequency = freqStr.substr(0, 5); wifiInfo.rate = std::to_string(bitrate); - wifiInfo.security = static_cast(wifiSecurityModeFromApFlags(flags, wpaFlags, rsnFlags)); + wifiInfo.security = static_cast(wifiSecurityModeFromApFlags(wifiInfo.ssid, flags, wpaFlags, rsnFlags)); if(noise <= 0 && noise >= DEFAULT_NOISE) wifiInfo.noise = std::to_string(noise); else diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h index 40f5d3450..3b46bbef0 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h +++ b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h @@ -87,7 +87,7 @@ namespace WPEFramework static bool convertSsidInfoToJsonObject(Exchange::INetworkManager::WiFiSSIDInfo& wifiInfo, JsonObject& ssidObj); static const char* convertPercentageToSignalStrengtStr(int percentage); - static uint8_t wifiSecurityModeFromApFlags(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); + static uint8_t wifiSecurityModeFromApFlags(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags); static const char* getWifiIfname(); static const char* getEthIfname(); }; From 9882b856b697c8e215f825b6b8da558823f6112a Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Mon, 31 Mar 2025 11:53:39 -0400 Subject: [PATCH 109/271] Release of v0.12.0 Release of v0.12.0 --- CHANGELOG.md | 13 +++++++++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64075d5ca..f3362e316 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,19 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.12.0] - 2025-03-31 +### Added +- The file and folder structure of NetworkManager repo is re-organized +- Implemented a separate library for out-of-process plugin +- Implemented GDbus based APIs for all the NetworkManager APIs +- Implmented a Router Discovery tool +- Changed the approach to identify Open SSIDs +- Added INFO logging for the discovered SSIDs and the security methods discovered. +- Fixed Invalid Timeout in Connectivity Monitoring +- Fixed WiFiConnect Failure for previously saved SSID +- Fixed the missing Events on WPS Connect failure + + ## [0.11.0] - 2025-03-07 ### Added - Implemented concurrent interface support in public APIs diff --git a/CMakeLists.txt b/CMakeLists.txt index 24ed09f33..70bd32b04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 11) +set(VERSION_MINOR 12) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index ae03aff46..c12a83e81 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json", - "version": "0.11.0" + "version": "0.12.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index c9ba3fc88..2596da554 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.11.0** +**Version: 0.12.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.11.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.12.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From b35cab3a199e3ac20e16859467dd4db2a36855ff Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Wed, 2 Apr 2025 10:48:45 -0400 Subject: [PATCH 110/271] RDKEMW-3079 : Change the Name of the Out-of-Process Thunder NetworkManager Plugin. (#129) Reason for change: Change the Name of the Out-of-Process Thunder NetworkManager Plugin as `NWMgrPlugin` Test Procedure: Verify in `top -p ` Risks: Low Signed-off-by: kamirt573_comcast --- plugin/NetworkManagerImplementation.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 60bf250f3..96594d615 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -48,9 +48,12 @@ namespace WPEFramework m_ethConnected = false; m_wlanConnected = false; + /* Set NetworkManager Out-Process name to be NWMgrPlugin */ + Core::ProcessInfo().Name("NWMgrPlugin"); + /* Initialize Network Manager */ NetworkManagerLogger::Init(); - NMLOG_INFO((_T("NetworkManager Out-Of-Process Instantiation; SHA:" _T(EXPAND_AND_QUOTE(PLUGIN_BUILD_REFERENCE))))); + NMLOG_INFO((_T("NWMgrPlugin Out-Of-Process Instantiation; SHA: " _T(EXPAND_AND_QUOTE(PLUGIN_BUILD_REFERENCE))))); } NetworkManagerImplementation::~NetworkManagerImplementation() @@ -106,7 +109,9 @@ namespace WPEFramework { LOG_ENTRY_FUNCTION(); Configuration config; - + NMLOG_INFO("NWMgrPlugin Process Memory Size Allocated: %lld KB, Resident: %lld KB, Shared: %lld KB", (long long int) Core::ProcessInfo().Allocated() >> 10, + (long long int) Core::ProcessInfo().Resident() >> 10, + (long long int) Core::ProcessInfo().Shared() >> 10); if (service) { string configLine = service->ConfigLine(); From 8b73d0e4fd636b639923cbdf7dc13e81d651c41f Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 4 Apr 2025 01:33:22 +0530 Subject: [PATCH 111/271] RDKEMW-3088 WiFiConnect api getting failed at first time (#131) * RDKEMW-3088 WiFiConnect api getting failed at first time Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- legacy/LegacyNetworkAPIs.cpp | 1 - plugin/NetworkManagerImplementation.cpp | 6 +--- plugin/NetworkManagerJsonRpc.cpp | 18 ++++++++-- plugin/gnome/NetworkManagerGnomeEvents.cpp | 1 - plugin/gnome/NetworkManagerGnomeProxy.cpp | 4 +-- plugin/gnome/NetworkManagerGnomeUtils.cpp | 9 +++-- plugin/gnome/NetworkManagerGnomeUtils.h | 2 +- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 42 ++++++++++++---------- 8 files changed, 50 insertions(+), 33 deletions(-) diff --git a/legacy/LegacyNetworkAPIs.cpp b/legacy/LegacyNetworkAPIs.cpp index d3cc6bc5c..ff9b37f65 100644 --- a/legacy/LegacyNetworkAPIs.cpp +++ b/legacy/LegacyNetworkAPIs.cpp @@ -641,7 +641,6 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { string result{}; string endpoint{}; uint32_t rc = Core::ERROR_GENERAL; - LOG_INPARAM(); if (parameters.HasLabel("endpoint")) { string guid{}; diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 96594d615..fd5990a64 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -494,7 +494,6 @@ namespace WPEFramework // Check the exit status to determine if the command was successful if (WIFEXITED(exitStatus) && WEXITSTATUS(exitStatus) == 0) { pingResult["success"] = true; - pingResult["error"] = ""; } else { pingResult["success"] = false; pingResult["error"] = "Could not ping endpoint"; @@ -817,7 +816,7 @@ namespace WPEFramework snr = std::to_string(readSnr); } - NMLOG_INFO ("RSSI: %s dBm; Noise: %s dBm; SNR: %s dBm", strength.c_str(), noise.c_str(), snr.c_str()); + NMLOG_INFO("RSSI: %s dBm; Noise: %s dBm; SNR: %s dBm", strength.c_str(), noise.c_str(), snr.c_str()); if (readSnr == 0) { @@ -841,7 +840,6 @@ namespace WPEFramework quality = WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT; } - NMLOG_INFO ("GetWiFiSignalQuality success"); rc = Core::ERROR_NONE; return rc; @@ -858,13 +856,11 @@ namespace WPEFramework std::string snr{}; Exchange::INetworkManager::WiFiSignalQuality newSignalQuality; - NMLOG_DEBUG("checking WiFi signal strength"); GetWiFiSignalQuality(ssid, strength, noise, snr, newSignalQuality); m_lastConnectedSSID = ssid; // last connected ssid used in wifiConnect if (oldSignalQuality != newSignalQuality) { - NMLOG_INFO("Notifying WiFiSignalQualityChangedEvent %s", strength.c_str()); oldSignalQuality = newSignalQuality; NetworkManagerImplementation::ReportWiFiSignalQualityChange(ssid, strength, noise, snr, newSignalQuality); } diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index e0567a0fb..d1b77784f 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -708,11 +708,25 @@ namespace WPEFramework returnJson(rc); } + static inline void logWifiParameters(const JsonObject& parameters) + { + string json; + JsonObject ssidObj = JsonObject(parameters); + if (ssidObj.HasLabel("passphrase")) + ssidObj["passphrase"] = std::string("*******"); + if (ssidObj.HasLabel("private_key")) + ssidObj["private_key"] = std::string("*******"); + if (ssidObj.HasLabel("private_key_passwd")) + ssidObj["private_key_passwd"] = std::string("*******"); + ssidObj.ToString(json); + NMLOG_INFO("params=%s", json.c_str() ); + } + uint32_t NetworkManager::AddToKnownSSIDs(const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::WiFiConnectTo ssid{}; - NMLOG_INFO("Entry to %s", __FUNCTION__); + logWifiParameters(parameters); if (parameters.HasLabel("ssid") && parameters.HasLabel("passphrase")) { @@ -750,7 +764,7 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::WiFiConnectTo ssid{}; - NMLOG_INFO("Entry to %s", __FUNCTION__); + logWifiParameters(parameters); if (parameters.HasLabel("ssid")) { diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 7fcbff2ed..36b304e3e 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -617,7 +617,6 @@ namespace WPEFramework void GnomeNetworkManagerEvents::onAvailableSSIDsCb(NMDeviceWifi *wifiDevice, GParamSpec *pspec, gpointer userData) { - NMLOG_DEBUG("wifi scanning completed ..."); if(!NM_IS_DEVICE_WIFI(wifiDevice)) { NMLOG_ERROR("Not a wifi object "); diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index bbd0ab8ad..8f86bd6e5 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -425,8 +425,8 @@ namespace WPEFramework return Core::ERROR_GENERAL; } - if(ipversion.empty()) - NMLOG_DEBUG("ipversion is empty default value IPv4"); + // if(ipversion.empty()) + // NMLOG_DEBUG("ipversion is empty default value IPv4"); const GPtrArray *connections = nm_client_get_active_connections(client); if(connections == NULL) diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index 4c2685990..7125c5d2d 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -58,10 +58,13 @@ namespace WPEFramework return deviceState; } - uint8_t nmUtils::wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags) + uint8_t nmUtils::wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags, bool doPrint) { uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; - NMLOG_INFO("ap [%s] security str %s", ssid.c_str(), nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); + if(!doPrint) + NMLOG_DEBUG("ap [%s] security str %s", ssid.c_str(), nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); + else + NMLOG_INFO("ap [%s] security str %s", ssid.c_str(), nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); if ((flags != NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE; @@ -227,7 +230,7 @@ namespace WPEFramework wpaFlags = nm_access_point_get_wpa_flags(ap); rsnFlags = nm_access_point_get_rsn_flags(ap); freq = nmUtils::wifiFrequencyFromAp(apFreq); - security = nmUtils::wifiSecurityModeFromAp(ssidString, flags, wpaFlags, rsnFlags); + security = nmUtils::wifiSecurityModeFromAp(ssidString, flags, wpaFlags, rsnFlags, false); ssidObj["security"] = security; ssidObj["strength"] = nmUtils::convertPercentageToSignalStrengtStr(strength); diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index 897bb1619..96ace01a5 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -38,7 +38,7 @@ namespace WPEFramework static const char* ethIface(); static const char* convertPercentageToSignalStrengtStr(int percentage); static bool caseInsensitiveCompare(const std::string& str1, const std::string& str2); - static uint8_t wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags); + static uint8_t wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags, bool doPrint = true); static std::string wifiFrequencyFromAp(guint32 apFreq); static std::string getSecurityModeString(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); static bool apToJsonObject(NMAccessPoint *ap, JsonObject& ssidObj); diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index c562652d4..397d2c4b0 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -172,7 +172,7 @@ namespace WPEFramework return false; } - static void getApInfo(NMAccessPoint *AccessPoint, Exchange::INetworkManager::WiFiSSIDInfo &wifiInfo) + static void getApInfo(NMAccessPoint *AccessPoint, Exchange::INetworkManager::WiFiSSIDInfo &wifiInfo, bool doPrint = true) { guint32 flags, wpaFlags, rsnFlags, freq, bitrate; guint8 strength; @@ -228,10 +228,17 @@ namespace WPEFramework NMLOG_DEBUG("bitrate : %s kbit/s", wifiInfo.rate.c_str()); //TODO signal strenght to dBm wifiInfo.strength = std::string(nmUtils::convertPercentageToSignalStrengtStr(strength)); - wifiInfo.security = static_cast(nmUtils::wifiSecurityModeFromAp(wifiInfo.ssid, flags, wpaFlags, rsnFlags)); - NMLOG_INFO("ssid: %s, frequency: %s, sterngth: %s, security: %u", wifiInfo.ssid.c_str(), - wifiInfo.frequency.c_str(), wifiInfo.strength.c_str(), wifiInfo.security); - NMLOG_INFO("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); + wifiInfo.security = static_cast(nmUtils::wifiSecurityModeFromAp(wifiInfo.ssid, flags, wpaFlags, rsnFlags, doPrint)); + if(doPrint) + { + NMLOG_INFO("ssid: %s, frequency: %s, sterngth: %s, security: %u", wifiInfo.ssid.c_str(), wifiInfo.frequency.c_str(), wifiInfo.strength.c_str(), wifiInfo.security); + NMLOG_INFO("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); + } + else + { + NMLOG_DEBUG("ssid: %s, frequency: %s, sterngth: %s, security: %u", wifiInfo.ssid.c_str(), wifiInfo.frequency.c_str(), wifiInfo.strength.c_str(), wifiInfo.security); + NMLOG_DEBUG("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); + } } bool wifiManager::isWifiConnected() @@ -275,7 +282,7 @@ namespace WPEFramework return false; } NMLOG_DEBUG("active access point found !"); - getApInfo(activeAP, ssidinfo); + getApInfo(activeAP, ssidinfo, false); return true; } else @@ -625,7 +632,7 @@ namespace WPEFramework Exchange::INetworkManager::WiFiSSIDInfo apinfo; std::string activeSSID{}; - NMLOG_INFO("wifi connect ssid: %s, security %d persist %d", ssidInfo.ssid.c_str(), ssidInfo.security, ssidInfo.persist); + NMLOG_DEBUG("wifi connect ssid: %s, security %d persist %d", ssidInfo.ssid.c_str(), ssidInfo.security, ssidInfo.persist); m_isSuccess = false; if(!createClientNewConnection()) @@ -657,8 +664,14 @@ namespace WPEFramework AccessPoint = findMatchingSSID(ApList, ssidInfo.ssid); if(AccessPoint == NULL) { NMLOG_WARNING("SSID '%s' not found !", ssidInfo.ssid.c_str()); - if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + // if(_instance != nullptr) + // _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + /* ssid not found in scan list so add to known ssid it will do a scanning and connect */ + if(addToKnownSSIDs(ssidInfo)) + { + NMLOG_DEBUG("Adding to known ssid '%s' ", ssidInfo.ssid.c_str()); + return activateKnownWifiConnection(ssidInfo.ssid); + } return false; } @@ -945,7 +958,6 @@ namespace WPEFramework GError *error = NULL; wifiManager *_wifiManager = (static_cast(user_data)); if(nm_device_wifi_request_scan_finish(NM_DEVICE_WIFI(object), result, &error)) { - NMLOG_DEBUG("Scanning success"); _wifiManager->m_isSuccess = true; } else @@ -987,7 +999,6 @@ namespace WPEFramework nm_device_wifi_request_scan_options_async(wifiDevice, options, NULL, wifiScanCb, this); } else { - NMLOG_DEBUG("staring normal wifi scanning"); nm_device_wifi_request_scan_async(wifiDevice, NULL, wifiScanCb, this); } wait(m_loop); @@ -1013,15 +1024,9 @@ namespace WPEFramework gint64 current_time_in_msec = nm_utils_get_timestamp_msec(); gint64 time_difference_in_seconds = (current_time_in_msec - last_scan_time) / 1000; - - NMLOG_DEBUG("Current time in milliseconds: %" G_GINT64_FORMAT, current_time_in_msec); - NMLOG_DEBUG("Last scan time in milliseconds: %" G_GINT64_FORMAT, last_scan_time); - NMLOG_DEBUG("Time difference in seconds: %" G_GINT64_FORMAT, time_difference_in_seconds); - if (time_difference_in_seconds <= timelimitInSec) { return true; } - NMLOG_DEBUG("Last Wi-Fi scan exceeded time limit."); return false; } @@ -1088,7 +1093,8 @@ namespace WPEFramework if (bssid != NULL) { NMLOG_INFO("WPS PBC AP found bssid = %s", bssid); } - getApInfo(Ap, wpsApInfo); + + getApInfo(Ap, wpsApInfo, false); wpsApSsid = wpsApInfo.ssid; return true; } From fbdaec7de52222ad4b53261ddaf87348b45f72f2 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 4 Apr 2025 16:14:26 -0400 Subject: [PATCH 112/271] RDKEMW-2148 - [Gnome] IPv6 Only device, GetIPSettings() method returns failure when ipversion is empty (#123) Reason for change: The GetIPSettings is called, the IPv4 must be called. If the IPv4 is not there., we must return IPv6. Test Procedure: Connect to different router that provides only v4, only v6 and returns both. Risks: None --- plugin/gnome/NetworkManagerGnomeProxy.cpp | 183 +++++++++++----------- 1 file changed, 95 insertions(+), 88 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 8f86bd6e5..c184294b0 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -370,9 +370,8 @@ namespace WPEFramework } /* @brief Get IP Address Of the Interface */ - uint32_t NetworkManagerImplementation::GetIPSettings(string& interface /* @inout */, const string &ipversion /* @in */, IPAddress& result /* @out */) + uint32_t NetworkManagerImplementation::GetIPSettings(string& interface /* @inout */, const string &ipversion /* @in */, IPAddress& result /* @out */) { - uint32_t rc = Core::ERROR_RPC_CALL_FAILED; NMActiveConnection *conn = NULL; NMIPConfig *ip4_config = NULL; NMIPConfig *ip6_config = NULL; @@ -412,7 +411,8 @@ namespace WPEFramework } device = nm_client_get_device_by_iface(client, interface.c_str()); - if (device == NULL) { + if (device == NULL) + { NMLOG_FATAL("libnm doesn't have device corresponding to %s", interface.c_str()); return Core::ERROR_GENERAL; } @@ -445,7 +445,8 @@ namespace WPEFramework continue; NMRemoteConnection* retConn = nm_active_connection_get_connection(connection); - if(retConn == NULL) { + if(retConn == NULL) + { NMLOG_INFO("remote connection is null"); continue; } @@ -453,125 +454,131 @@ namespace WPEFramework settings = nm_connection_get_setting_connection(NM_CONNECTION(retConn)); if(settings == NULL) continue; - if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) { + if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) + { conn = connection; break; } } - if (conn == NULL) { + if (conn == NULL) + { NMLOG_WARNING("no active connection on %s interface", interface.c_str()); return Core::ERROR_GENERAL; } result.autoconfig = isAutoConnectEnabled(conn); - if(ipversion.empty() || nmUtils::caseInsensitiveCompare(ipversion, "IPV4")) // default ipversion ipv4 + if(ipversion.empty() || nmUtils::caseInsensitiveCompare(ipversion, "IPV4")) { + const GPtrArray *ipByte = nullptr; + result.ipversion = "IPv4"; ip4_config = nm_active_connection_get_ip4_config(conn); NMIPAddress *ipAddr = NULL; std::string ipStr; - if (ip4_config == nullptr) { + if (ip4_config) + ipByte = nm_ip_config_get_addresses(ip4_config); + else NMLOG_WARNING("no IPv4 configurtion on %s", interface.c_str()); - return Core::ERROR_GENERAL; - } - - const GPtrArray *ipByte = nullptr; - ipByte = nm_ip_config_get_addresses(ip4_config); - if (ipByte == nullptr) { - NMLOG_WARNING("No IPv4 data found on %s", interface.c_str()); - return Core::ERROR_GENERAL; - } - - for (int i = 0; i < ipByte->len; i++) + if(ipByte) { - ipAddr = static_cast(ipByte->pdata[i]); - if(ipAddr) - ipStr = nm_ip_address_get_address(ipAddr); - if(!ipStr.empty()) + for (int i = 0; i < ipByte->len; i++) + { + ipAddr = static_cast(ipByte->pdata[i]); + if(ipAddr) + ipStr = nm_ip_address_get_address(ipAddr); + if(!ipStr.empty()) + { + result.ipaddress = nm_ip_address_get_address(ipAddr); + result.prefix = nm_ip_address_get_prefix(ipAddr); + NMLOG_INFO("IPv4 addr: %s/%d", result.ipaddress.c_str(), result.prefix); + } + } + gateway = nm_ip_config_get_gateway(ip4_config); + if(gateway) + result.gateway = gateway; + dnsArr = (char **)nm_ip_config_get_nameservers(ip4_config); + if(dnsArr) + { + if(dnsArr[0]) + result.primarydns = std::string(dnsArr[0]); + if(dnsArr[1]) + result.secondarydns = std::string(dnsArr[1]); + } + dhcp4_config = nm_active_connection_get_dhcp4_config(conn); + if(dhcp4_config) { - result.ipaddress = nm_ip_address_get_address(ipAddr); - result.prefix = nm_ip_address_get_prefix(ipAddr); - NMLOG_INFO("IPv4 addr: %s/%d", result.ipaddress.c_str(), result.prefix); - result.ipversion = "IPv4"; // if null add as default + dhcpserver = nm_dhcp_config_get_one_option (dhcp4_config, "dhcp_server_identifier"); + if(dhcpserver) + result.dhcpserver = dhcpserver; } + result.ula = ""; } - - gateway = nm_ip_config_get_gateway(ip4_config); - - dnsArr = (char **)nm_ip_config_get_nameservers(ip4_config); - dhcp4_config = nm_active_connection_get_dhcp4_config(conn); - if(dhcp4_config) - dhcpserver = nm_dhcp_config_get_one_option (dhcp4_config, "dhcp_server_identifier"); - if(dhcpserver) - result.dhcpserver = dhcpserver; - result.ula = ""; - if(gateway) - result.gateway = gateway; - if((*(&dnsArr[0]))!=NULL) - result.primarydns = *(&dnsArr[0]); - if((*(&dnsArr[1]))!=NULL ) - result.secondarydns = *(&dnsArr[1]); - - rc = Core::ERROR_NONE; } - else if(nmUtils::caseInsensitiveCompare(ipversion, "IPV6")) + if((result.ipaddress.empty() && !(nmUtils::caseInsensitiveCompare(ipversion, "IPV4"))) || nmUtils::caseInsensitiveCompare(ipversion, "IPV6")) { - result.ipversion = ipversion.c_str(); + std::string ipStr; + const GPtrArray *ipArray = nullptr; + result.ipversion = "IPv6"; NMIPAddress *ipAddr = nullptr; ip6_config = nm_active_connection_get_ip6_config(conn); - if(ip6_config == nullptr) - { + if(ip6_config) + ipArray = nm_ip_config_get_addresses(ip6_config); + else NMLOG_WARNING("no IPv6 configurtion on %s", interface.c_str()); - return Core::ERROR_GENERAL; - } - - std::string ipStr; - const GPtrArray *ipArray = nullptr; - ipArray = nm_ip_config_get_addresses(ip6_config); - for (int i = 0; i < ipArray->len; i++) + if(ipArray) { - ipAddr = static_cast(ipArray->pdata[i]); - if(ipAddr) - ipStr = nm_ip_address_get_address(ipAddr); - if(!ipStr.empty()) + for (int i = 0; i < ipArray->len; i++) { - if (ipStr.compare(0, 5, "fe80:") == 0 || ipStr.compare(0, 6, "fe80::") == 0) { - result.ula = ipStr; - NMLOG_INFO("link-local ip: %s", result.ula.c_str()); - } - else { - result.prefix = nm_ip_address_get_prefix(ipAddr); - if(result.ipaddress.empty()) // SLAAC mutiple ip not added - result.ipaddress = ipStr; - NMLOG_INFO("global ip %s/%d", ipStr.c_str(), result.prefix); + ipAddr = static_cast(ipArray->pdata[i]); + if(ipAddr) + ipStr = nm_ip_address_get_address(ipAddr); + if(!ipStr.empty()) + { + if (ipStr.compare(0, 5, "fe80:") == 0 || ipStr.compare(0, 6, "fe80::") == 0) + { + result.ula = ipStr; + NMLOG_INFO("link-local ip: %s", result.ula.c_str()); + } + else + { + result.prefix = nm_ip_address_get_prefix(ipAddr); + if(result.ipaddress.empty()) // SLAAC mutiple ip not added + result.ipaddress = ipStr; + NMLOG_INFO("global ip %s/%d", ipStr.c_str(), result.prefix); + } } } - } - gateway = nm_ip_config_get_gateway(ip6_config); - if(gateway) - result.gateway= gateway; - dnsArr = (char **)nm_ip_config_get_nameservers(ip6_config); - if((*(&dnsArr[0]))!= NULL) - result.primarydns = *(&dnsArr[0]); - if((*(&dnsArr[1]))!=NULL ) - result.secondarydns = *(&dnsArr[1]); - - dhcp6_config = nm_active_connection_get_dhcp6_config(conn); - if(dhcp6_config) - { - dhcpserver = nm_dhcp_config_get_one_option (dhcp6_config, "dhcp_server_identifier"); - if(dhcpserver) { - result.dhcpserver = dhcpserver; + gateway = nm_ip_config_get_gateway(ip6_config); + if(gateway) + result.gateway= gateway; + dnsArr = (char **)nm_ip_config_get_nameservers(ip6_config); + if(dnsArr) + { + if(dnsArr[0]) + result.primarydns = std::string(dnsArr[0]); + if(dnsArr[1]) + result.secondarydns = std::string(dnsArr[1]); + } + dhcp6_config = nm_active_connection_get_dhcp6_config(conn); + if(dhcp6_config) + { + dhcpserver = nm_dhcp_config_get_one_option (dhcp6_config, "dhcp_server_identifier"); + if(dhcpserver) + result.dhcpserver = dhcpserver; } } - result.ipversion = "IPv6"; - rc = Core::ERROR_NONE; } else NMLOG_WARNING("ipversion error IPv4/IPv6"); - return rc; + if(result.ipaddress.empty()) + { + result.autoconfig = true; + if(ipversion.empty()) + result.ipversion = "IPv4"; + } + return Core::ERROR_NONE; } /* @brief Set IP Address Of the Interface */ From 16f0c712abf59b63d13fea9f26269226bd70b005 Mon Sep 17 00:00:00 2001 From: cmuhammedrafi Date: Fri, 4 Apr 2025 06:53:41 +0000 Subject: [PATCH 113/271] RDKEMW-3249: GetInterfaceState API Returns Ethernet Enabled on Wi-Fi Only Devices --- plugin/gnome/NetworkManagerGnomeEvents.cpp | 48 ++++++++-- plugin/gnome/NetworkManagerGnomeEvents.h | 1 + plugin/gnome/NetworkManagerGnomeProxy.cpp | 31 ++++++- plugin/gnome/NetworkManagerGnomeUtils.cpp | 103 +++------------------ plugin/gnome/NetworkManagerGnomeUtils.h | 4 - plugin/gnome/NetworkManagerGnomeWIFI.cpp | 14 ++- 6 files changed, 94 insertions(+), 107 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 36b304e3e..f2336cca1 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -54,12 +54,14 @@ namespace WPEFramework connectionTyp = nm_active_connection_get_connection_type(primaryConn); NMLOG_INFO("active connection - %s (%s)", activeConnId, connectionTyp); - if (0 == strncmp("802-3-ethernet", connectionTyp, sizeof("802-3-ethernet"))) + if (0 == strncmp("802-3-ethernet", connectionTyp, sizeof("802-3-ethernet")) && string("eth0_missing") != nmUtils::ethIface()) newIface = nmUtils::ethIface(); - else if(0 == strncmp("802-11-wireless", connectionTyp, sizeof("802-11-wireless"))) + else if(0 == strncmp("802-11-wireless", connectionTyp, sizeof("802-11-wireless")) && string("wlan0_missing") != nmUtils::wlanIface()) newIface = nmUtils::wlanIface(); - else - NMLOG_WARNING("active connection not an ethernet/wifi %s", connectionTyp); + else { + NMLOG_WARNING("Active connection not valid: Ethernet/WiFi ID: %s", connectionTyp); + return; // if not good don't report the evnet + } GnomeNetworkManagerEvents::onActiveInterfaceChangeCb(newIface); } @@ -402,7 +404,7 @@ namespace WPEFramework g_signal_connect(nmEvents->client, "notify::" NM_CLIENT_STATE, G_CALLBACK (clientStateChangedCb),nmEvents); g_signal_connect(nmEvents->client, "notify::" NM_CLIENT_PRIMARY_CONNECTION, G_CALLBACK(primaryConnectionCb), nmEvents); - const GPtrArray *devices = nullptr; + const GPtrArray *devices = nullptr; devices = nm_client_get_devices(nmEvents->client); g_signal_connect(nmEvents->client, NM_CLIENT_DEVICE_ADDED, G_CALLBACK(deviceAddedCB), nmEvents); @@ -615,6 +617,40 @@ namespace WPEFramework NMLOG_INFO("iface:%s - ipaddress:%s - %s - %s", iface.c_str(), ipAddress.c_str(), acquired?"acquired":"lost", isIPv6?"isIPv6":"isIPv4"); } + bool GnomeNetworkManagerEvents::apToJsonObject(NMAccessPoint *ap, JsonObject& ssidObj) + { + GBytes *ssid = NULL; + int strength = 0; + std::string freq; + int security; + guint32 flags, wpaFlags, rsnFlags, apFreq; + if(ap == nullptr) + return false; + ssid = nm_access_point_get_ssid(ap); + if (ssid) + { + char *ssidStr = nullptr; + ssidStr = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid)); + string ssidString(ssidStr); + ssidObj["ssid"] = ssidString; + strength = nm_access_point_get_strength(ap); + apFreq = nm_access_point_get_frequency(ap); + flags = nm_access_point_get_flags(ap); + wpaFlags = nm_access_point_get_wpa_flags(ap); + rsnFlags = nm_access_point_get_rsn_flags(ap); + freq = nmUtils::wifiFrequencyFromAp(apFreq); + security = nmUtils::wifiSecurityModeFromAp(ssidString, flags, wpaFlags, rsnFlags, false); + + ssidObj["security"] = security; + ssidObj["strength"] = nmUtils::convertPercentageToSignalStrengtStr(strength); + ssidObj["frequency"] = freq; + return true; + } + // else + // NMLOG_DEBUG("hidden ssid found, bssid: %s", nm_access_point_get_bssid(ap)); + return false; + } + void GnomeNetworkManagerEvents::onAvailableSSIDsCb(NMDeviceWifi *wifiDevice, GParamSpec *pspec, gpointer userData) { if(!NM_IS_DEVICE_WIFI(wifiDevice)) @@ -629,7 +665,7 @@ namespace WPEFramework { JsonObject ssidObj; ap = static_cast(accessPoints->pdata[i]); - if(nmUtils::apToJsonObject(ap, ssidObj)) + if(GnomeNetworkManagerEvents::apToJsonObject(ap, ssidObj)) ssidList.Add(ssidObj); } diff --git a/plugin/gnome/NetworkManagerGnomeEvents.h b/plugin/gnome/NetworkManagerGnomeEvents.h index ccf631bc6..0c19957c4 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.h +++ b/plugin/gnome/NetworkManagerGnomeEvents.h @@ -57,6 +57,7 @@ namespace WPEFramework private: static void* networkMangerEventMonitor(void *arg); + static bool apToJsonObject(NMAccessPoint *ap, JsonObject& ssidObj); GnomeNetworkManagerEvents(); ~GnomeNetworkManagerEvents(); std::atomicisEventThrdActive = {false}; diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index c184294b0..313a30fa0 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -42,6 +42,29 @@ namespace WPEFramework return; } + static NMDeviceState ifaceState(NMClient *client, const char* interface) + { + NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; + NMDevice *device = NULL; + if(client == NULL) + return deviceState; + + if(string("eth0_missing") == interface || string("wlan0_missing") == interface) + { + NMLOG_DEBUG("interface %s is not valid", interface); + return deviceState; + } + + device = nm_client_get_device_by_iface(client, interface); + if (device == NULL) { + NMLOG_FATAL("libnm doesn't have device corresponding to %s", interface); + return deviceState; + } + + deviceState = nm_device_get_state(device); + return deviceState; + } + void NetworkManagerImplementation::platform_init() { ::_instance = this; @@ -56,7 +79,7 @@ namespace WPEFramework } nmUtils::getInterfacesName(); // get interface name form '/etc/device.proprties' - NMDeviceState ethState = nmUtils::ifaceState(client, nmUtils::ethIface()); + NMDeviceState ethState = ifaceState(client, nmUtils::ethIface()); if(ethState > NM_DEVICE_STATE_DISCONNECTED && ethState < NM_DEVICE_STATE_DEACTIVATING) m_defaultInterface = nmUtils::ethIface(); else @@ -147,7 +170,7 @@ namespace WPEFramework activeConn = nm_client_get_primary_connection(client); if (activeConn == NULL) { NMLOG_WARNING("no active activeConn Interface found"); - NMDeviceState ethState = nmUtils::ifaceState(client, nmUtils::ethIface()); + NMDeviceState ethState = ifaceState(client, nmUtils::ethIface()); /* if ethernet is connected but not completely activate then ethernet is taken as primary else wifi */ if(ethState > NM_DEVICE_STATE_DISCONNECTED && ethState < NM_DEVICE_STATE_DEACTIVATING) m_defaultInterface = interface = ethname; @@ -160,7 +183,7 @@ namespace WPEFramework if(remoteConn == NULL) { NMLOG_WARNING("primary connection but remote connection error"); - NMDeviceState ethState = nmUtils::ifaceState(client, nmUtils::ethIface()); + NMDeviceState ethState = ifaceState(client, nmUtils::ethIface()); /* if ethernet is connected but not completely activate then ethernet is taken as primary else wifi */ if(ethState > NM_DEVICE_STATE_DISCONNECTED && ethState < NM_DEVICE_STATE_DEACTIVATING) m_defaultInterface = interface = ethname; @@ -391,7 +414,7 @@ namespace WPEFramework return Core::ERROR_RPC_CALL_FAILED; } - if(interface.empty() || interface == "null") + if(interface.empty()) { if(Core::ERROR_NONE != GetPrimaryInterface(interface)) { diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index 7125c5d2d..33ac54b7d 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -41,23 +41,6 @@ namespace WPEFramework const char* nmUtils::wlanIface() {return m_wlanifname.c_str();} const char* nmUtils::ethIface() {return m_ethifname.c_str();} - NMDeviceState nmUtils::ifaceState(NMClient *client, const char* interface) - { - NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; - NMDevice *device = NULL; - if(client == NULL) - return deviceState; - - device = nm_client_get_device_by_iface(client, interface); - if (device == NULL) { - NMLOG_FATAL("libnm doesn't have device corresponding to %s", interface); - return deviceState; - } - - deviceState = nm_device_get_state(device); - return deviceState; - } - uint8_t nmUtils::wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags, bool doPrint) { uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; @@ -208,77 +191,8 @@ namespace WPEFramework return freq; } - bool nmUtils::apToJsonObject(NMAccessPoint *ap, JsonObject& ssidObj) + bool nmUtils::caseInsensitiveCompare(const std::string& str1, const std::string& str2) { - GBytes *ssid = NULL; - int strength = 0; - std::string freq; - int security; - guint32 flags, wpaFlags, rsnFlags, apFreq; - if(ap == nullptr) - return false; - ssid = nm_access_point_get_ssid(ap); - if (ssid) - { - char *ssidStr = nullptr; - ssidStr = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid)); - string ssidString(ssidStr); - ssidObj["ssid"] = ssidString; - strength = nm_access_point_get_strength(ap); - apFreq = nm_access_point_get_frequency(ap); - flags = nm_access_point_get_flags(ap); - wpaFlags = nm_access_point_get_wpa_flags(ap); - rsnFlags = nm_access_point_get_rsn_flags(ap); - freq = nmUtils::wifiFrequencyFromAp(apFreq); - security = nmUtils::wifiSecurityModeFromAp(ssidString, flags, wpaFlags, rsnFlags, false); - - ssidObj["security"] = security; - ssidObj["strength"] = nmUtils::convertPercentageToSignalStrengtStr(strength); - ssidObj["frequency"] = freq; - return true; - } - // else - // NMLOG_DEBUG("hidden ssid found, bssid: %s", nm_access_point_get_bssid(ap)); - return false; - } - - void nmUtils::printActiveSSIDsOnly(NMDeviceWifi *wifiDevice) - { - if(!NM_IS_DEVICE_WIFI(wifiDevice)) - { - NMLOG_ERROR("Not a wifi object "); - return; - } - const GPtrArray *accessPointsArray = nm_device_wifi_get_access_points(wifiDevice); - for (guint i = 0; i < accessPointsArray->len; i++) - { - NMAccessPoint *ap = NULL; - GBytes *ssidGByte = NULL; - std::string ssid; - - ap = (NMAccessPoint*)accessPointsArray->pdata[i]; - ssidGByte = nm_access_point_get_ssid(ap); - if(ssidGByte) - { - char* ssidStr = NULL; - gsize len; - const guint8 *ssidData = static_cast(g_bytes_get_data(ssidGByte, &len)); - ssidStr = nm_utils_ssid_to_utf8(ssidData, len); - if(ssidStr != NULL) { - std::string ssidTmp(ssidStr, len); - ssid = ssidTmp; - } - else - ssid = "---"; - } - else - ssid = "---"; - - NMLOG_INFO("ssid: %s", ssid.c_str()); - } - } - - bool nmUtils::caseInsensitiveCompare(const std::string& str1, const std::string& str2) { std::string upperStr1 = str1; std::string upperStr2 = str2; @@ -310,19 +224,26 @@ namespace WPEFramework ethIfname = line.substr(line.find('=') + 1); ethIfname.erase(ethIfname.find_last_not_of("\r\n\t") + 1); ethIfname.erase(0, ethIfname.find_first_not_of("\r\n\t")); + if(ethIfname.empty()) + { + NMLOG_WARNING("ETHERNET_INTERFACE is empty in /etc/device.properties"); + ethIfname = "eth0_missing"; // means device doesnot have ethernet interface invalid name + } } if (line.find("WIFI_INTERFACE=") != std::string::npos) { wifiIfname = line.substr(line.find('=') + 1); wifiIfname.erase(wifiIfname.find_last_not_of("\r\n\t") + 1); wifiIfname.erase(0, wifiIfname.find_first_not_of("\r\n\t")); + if(wifiIfname.empty()) + { + NMLOG_WARNING("WIFI_INTERFACE is empty in /etc/device.properties"); + wifiIfname = "wlan0_missing"; // means device doesnot have wifi interface + } } } file.close(); - if (ethIfname.empty() && wifiIfname.empty()) { - NMLOG_FATAL("Could not find any interface name in /etc/device.properties"); - return false; - } + m_wlanifname = wifiIfname; m_ethifname = ethIfname; NMLOG_INFO("/etc/device.properties eth: %s, wlan: %s", m_ethifname.c_str(), m_wlanifname.c_str()); diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index 96ace01a5..8b319c128 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -41,10 +41,6 @@ namespace WPEFramework static uint8_t wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags, bool doPrint = true); static std::string wifiFrequencyFromAp(guint32 apFreq); static std::string getSecurityModeString(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); - static bool apToJsonObject(NMAccessPoint *ap, JsonObject& ssidObj); - static void printActiveSSIDsOnly(NMDeviceWifi *wifiDevice); - static NMDeviceState ifaceState(NMClient *client, const char* interface); }; - } } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 397d2c4b0..6a38d7607 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -1300,6 +1300,12 @@ namespace WPEFramework m_isSuccess = false; NMDevice *device = nullptr; + if(interface.empty() || (interface != nmUtils::ethIface() && interface != nmUtils::wlanIface())) + { + NMLOG_ERROR("Invalid interface name: %s", interface.c_str()); + return false; + } + if (!createClientNewConnection()) return false; @@ -1396,6 +1402,12 @@ namespace WPEFramework NMDevice *device = NULL; const char *specObject = NULL; + if(interface.empty() || (interface != nmUtils::ethIface() && interface != nmUtils::wlanIface())) + { + NMLOG_ERROR("Invalid interface name: %s", interface.c_str()); + return false; + } + if (!createClientNewConnection()) return false; @@ -1455,8 +1467,6 @@ namespace WPEFramework } connection = NM_CONNECTION(remoteConn); } - else - return false; // interface is not eth0 or wlan0 if(connection == nullptr) { From a60170ab9f49615f5003399b910e4e671a002a1d Mon Sep 17 00:00:00 2001 From: cmuhammedrafi Date: Mon, 7 Apr 2025 10:59:40 +0000 Subject: [PATCH 114/271] RDKEMW-3191: Enabled NetworkManager DEBUG logs when SetLogLevel(DEBUG) called Signed-off-by: cmuhammedrafi tets noise updated --- plugin/gnome/NetworkManagerGnomeProxy.cpp | 1 + plugin/gnome/NetworkManagerGnomeUtils.cpp | 36 +++++++++++++++++++++++ plugin/gnome/NetworkManagerGnomeUtils.h | 1 + plugin/gnome/NetworkManagerGnomeWIFI.cpp | 5 +--- 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 313a30fa0..8aeca7542 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -89,6 +89,7 @@ namespace WPEFramework nmEvent = GnomeNetworkManagerEvents::getInstance(); nmEvent->startNetworkMangerEventMonitor(); wifi = wifiManager::getInstance(); + nmUtils::configureNetworkManagerDaemonLoglevel(); return; } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index 33ac54b7d..d299217c0 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -249,5 +249,41 @@ namespace WPEFramework NMLOG_INFO("/etc/device.properties eth: %s, wlan: %s", m_ethifname.c_str(), m_wlanifname.c_str()); return true; } + + bool nmUtils::configureNetworkManagerDaemonLoglevel() + { + /* set networkmanager daemon log level based on current plugin log level */ + const char* command = "nmcli general logging level TRACE domains ALL"; + NetworkManagerLogger::LogLevel level; + NetworkManagerLogger::GetLevel(level); + + if(NetworkManagerLogger::DEBUG_LEVEL != level) + return false; + + // Execute the command using popen + FILE *pipe = popen(command, "r"); + + if (pipe == NULL) { + NMLOG_ERROR("popen failed %s ", command); + return false; + } + + // Close the pipe and retrieve the command's exit status + int status = pclose(pipe); + if (status == -1) { + perror("pclose failed"); + return false; + } + + // Extract the exit status from the status code + int exitCode = WEXITSTATUS(status); + if (exitCode == 0) + NMLOG_INFO("NetworkManager daemon log level changed ! logLevel: %d", level); + else + NMLOG_INFO(" '%s' failed with exit code %d.", command, exitCode); + + return exitCode == 0; + } + } // Plugin } // WPEFramework diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index 8b319c128..a5c701ff3 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -41,6 +41,7 @@ namespace WPEFramework static uint8_t wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags, bool doPrint = true); static std::string wifiFrequencyFromAp(guint32 apFreq); static std::string getSecurityModeString(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); + static bool configureNetworkManagerDaemonLoglevel(); }; } } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 6a38d7607..58379e439 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -221,10 +221,7 @@ namespace WPEFramework wifiInfo.frequency = freqStr.substr(0, 5); wifiInfo.rate = std::to_string(bitrate); - if(noise <= 0 && noise >= DEFAULT_NOISE) - wifiInfo.noise = std::to_string(noise); - else - wifiInfo.noise = std::to_string(0); + wifiInfo.noise = std::to_string(noise); NMLOG_DEBUG("bitrate : %s kbit/s", wifiInfo.rate.c_str()); //TODO signal strenght to dBm wifiInfo.strength = std::string(nmUtils::convertPercentageToSignalStrengtStr(strength)); From 49c3bcb4b4bdddd0edd7cb6773f01807bee3434f Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Mon, 7 Apr 2025 16:05:26 -0400 Subject: [PATCH 115/271] Release of v0.13.0 Release of v0.13.0 --- CHANGELOG.md | 9 ++++++++- CMakeLists.txt | 2 +- definition/NetworkManager.json | 4 ++-- docs/NetworkManagerPlugin.md | 6 +++--- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3362e316..b08e05105 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,14 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.13.0] - 2025-04-07 +### Changed +- Changed the out-of-process name +- Changed the WIFIConnect API scan & connect if the scan-result is empty +- Changed the GetIPSettings API to check the ipversion passed, and if empty, return IPv4 when available other IPv6. +- Fixed the GetAvailableInterfaces to return only the interfaces that are defined in device.properties +- Enable DEBUG to NetworkManager Gnome daemon when SetLogLevel called with DEBUG. + ## [0.12.0] - 2025-03-31 ### Added - The file and folder structure of NetworkManager repo is re-organized @@ -26,7 +34,6 @@ All notable changes to this RDK Service will be documented in this file. - Fixed WiFiConnect Failure for previously saved SSID - Fixed the missing Events on WPS Connect failure - ## [0.11.0] - 2025-03-07 ### Added - Implemented concurrent interface support in public APIs diff --git a/CMakeLists.txt b/CMakeLists.txt index 70bd32b04..b8b5b4eff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 12) +set(VERSION_MINOR 13) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index c12a83e81..f75aee64a 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,8 +8,8 @@ "locator": "libWPEFrameworkNetworkManager.so", "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", - "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json", - "version": "0.12.0" + "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", + "version": "0.13.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 2596da554..dbc10a3ff 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,13 +2,13 @@ # NetworkManager Plugin -**Version: 0.12.0** +**Version: 0.13.0** **Status: :white_circle::white_circle::white_circle:** org.rdk.NetworkManager interface for Thunder framework. -(Defined by [NetworkManager.json](https://github.com/rdkcentral/networkmanager/blob/main/NetworkManager.json)) +(Defined by [NetworkManager.json](https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json)) ### Table of Contents @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.12.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.13.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From c736300c5cf2b9b5007703de23437a8ad221d766 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Wed, 9 Apr 2025 19:26:48 +0530 Subject: [PATCH 116/271] RDKEMW-3086, RDKEMW-1839 : Memmory leak fix (#133) The libnm API to get the SSID Name returns a allocated buffer and its caller responsibility to free that. Fixed now. --- plugin/gnome/NetworkManagerGnomeEvents.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index f2336cca1..7aafcabfa 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -255,6 +255,11 @@ namespace WPEFramework for (guint i = 0; i < addresses->len; ++i) { NMIPAddress *address = (NMIPAddress *)g_ptr_array_index(addresses, i); + if(address == NULL) + { + NMLOG_WARNING("IPv4 address is null"); + continue; + } if (nm_ip_address_get_family(address) == AF_INET) { const char *ipAddress = nm_ip_address_get_address(address); if(ipAddress != NULL) @@ -291,6 +296,11 @@ namespace WPEFramework for (guint i = 0; i < addresses->len; ++i) { NMIPAddress *address = (NMIPAddress *)g_ptr_array_index(addresses, i); + if(address == NULL) + { + NMLOG_WARNING("IPv6 address is null"); + continue; + } if (nm_ip_address_get_family(address) == AF_INET6) { const char *ipaddr = nm_ip_address_get_address(address); //int prefix = nm_ip_address_get_prefix(address); @@ -631,7 +641,12 @@ namespace WPEFramework { char *ssidStr = nullptr; ssidStr = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid)); - string ssidString(ssidStr); + string ssidString = "---"; + if(ssidStr) + { + ssidString = ssidStr; + free(ssidStr); + } ssidObj["ssid"] = ssidString; strength = nm_access_point_get_strength(ap); apFreq = nm_access_point_get_frequency(ap); From 6a86b6a24bf540ae31b560f7691796d6b28db9e7 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Wed, 9 Apr 2025 15:40:08 -0400 Subject: [PATCH 117/271] RDKEMW-3086 : Add Process Memory Monitoring (#134) Reason for change: Add Process Memory Monitoring thread which reads n prints the RSS & USS periodically every 1 min Test Procedure: watch for RSS print in wpeframework.log Risks: Medium Signed-off-by: kamirt573_comcast --- plugin/NetworkManagerImplementation.cpp | 35 ++++++++++++++++++++++--- plugin/NetworkManagerImplementation.h | 8 ++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index fd5990a64..7f94d1e40 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -54,6 +54,7 @@ namespace WPEFramework /* Initialize Network Manager */ NetworkManagerLogger::Init(); NMLOG_INFO((_T("NWMgrPlugin Out-Of-Process Instantiation; SHA: " _T(EXPAND_AND_QUOTE(PLUGIN_BUILD_REFERENCE))))); + m_processMonThread = std::thread(&NetworkManagerImplementation::processMonitor, this, NM_PROCESS_MONITOR_INTERVAL_SEC); } NetworkManagerImplementation::~NetworkManagerImplementation() @@ -64,6 +65,16 @@ namespace WPEFramework m_registrationThread.join(); } stopWiFiSignalQualityMonitor(); + + { + std::unique_lock lock(m_processMonMutex); + m_processMonThreadStop = true; + m_processMonCondVar.notify_one(); + } + + if (m_processMonThread.joinable()) { + m_processMonThread.join(); + } } /** @@ -109,9 +120,6 @@ namespace WPEFramework { LOG_ENTRY_FUNCTION(); Configuration config; - NMLOG_INFO("NWMgrPlugin Process Memory Size Allocated: %lld KB, Resident: %lld KB, Shared: %lld KB", (long long int) Core::ProcessInfo().Allocated() >> 10, - (long long int) Core::ProcessInfo().Resident() >> 10, - (long long int) Core::ProcessInfo().Shared() >> 10); if (service) { string configLine = service->ConfigLine(); @@ -845,6 +853,27 @@ namespace WPEFramework return rc; } + void NetworkManagerImplementation::processMonitor(uint16_t interval) + { + pid_t pid = getpid(); + Core::ProcessInfo processInfo(pid); + + do + { + processInfo.MemoryStats(); + NMLOG_INFO("RSS: %lu KB PSS: %lu KB USS: %lu KB VSS: %lu KB", processInfo.RSS(), processInfo.PSS(), processInfo.USS(), processInfo.VSS()); + + std::unique_lock lock(m_processMonMutex); + // Wait for the specified interval or until notified to stop + if (m_processMonCondVar.wait_for(lock, std::chrono::seconds(interval), [this](){ return m_processMonThreadStop == true; })) + { + NMLOG_INFO("processMonitor received stop signal"); + } + } while (!m_processMonThreadStop); + + return; + } + void NetworkManagerImplementation::monitorThreadFunction(int interval) { static Exchange::INetworkManager::WiFiSignalQuality oldSignalQuality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index d0918b75a..1426124fc 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -38,6 +38,7 @@ using namespace std; #define MAX_SNR_VALUE 180 #define DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC 60 +#define NM_PROCESS_MONITOR_INTERVAL_SEC 60 #define NM_WIFI_SNR_THRESHOLD_EXCELLENT 40 #define NM_WIFI_SNR_THRESHOLD_GOOD 25 #define NM_WIFI_SNR_THRESHOLD_FAIR 18 @@ -268,6 +269,7 @@ namespace WPEFramework void stopWiFiSignalQualityMonitor(); void monitorThreadFunction(int interval); int32_t logSSIDs(Logging level, const JsonArray &ssids); + void processMonitor(uint16_t interval); private: std::list _notificationCallbacks; @@ -283,6 +285,12 @@ namespace WPEFramework string m_filterfrequency; std::vector m_filterSsidslist; std::thread m_monitorThread; + + std::thread m_processMonThread; + std::mutex m_processMonMutex; + std::atomic m_processMonThreadStop{false}; + std::condition_variable m_processMonCondVar; + std::atomic m_stopThread{false}; std::atomic m_isRunning{false}; bool m_monitoringStarted = false; From 19ae17ace934d0d4c6960e8854d3a6d170c93cae Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Mon, 14 Apr 2025 11:45:44 -0400 Subject: [PATCH 118/271] RDKEMW-3086 : Read /proc/PID/statm to print RSS (#137) Reason for change: Reading of /proc/PID/smaps is failing for some platforms; so lets use /proc/PID/statm as standard for now Test Procedure: Grep the logs for RSS Risks: Low Signed-off-by: kamirt573_comcast --- plugin/NetworkManagerImplementation.cpp | 38 ++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 7f94d1e40..2a4851d86 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -856,18 +856,48 @@ namespace WPEFramework void NetworkManagerImplementation::processMonitor(uint16_t interval) { pid_t pid = getpid(); - Core::ProcessInfo processInfo(pid); + + string path = "/proc/"; + path += std::to_string(pid); + path += "/statm"; + const uint32_t pageSize = getpagesize(); do { - processInfo.MemoryStats(); - NMLOG_INFO("RSS: %lu KB PSS: %lu KB USS: %lu KB VSS: %lu KB", processInfo.RSS(), processInfo.PSS(), processInfo.USS(), processInfo.VSS()); + int fd; + char buffer[128] = ""; + int processSize = 0; + int processRSS = 0; + int processShare = 0; + + if ((fd = open(path.c_str(), O_RDONLY)) >= 0) + { + ssize_t readAmount = 0; + if ((readAmount = read(fd, buffer, sizeof(buffer))) > 0) + { + ssize_t nulIndex = std::min(readAmount, static_cast(sizeof(buffer) - 1)); + buffer[nulIndex] = '\0'; + sscanf(buffer, "%d %d %d", &processSize, &processRSS, &processShare); + + /* Update the sizes */ + processSize *= pageSize; + processRSS *= pageSize; + processShare *= pageSize; + + /* Convert to KB */ + processSize >>= 10; + processRSS >>= 10; + processShare >>= 10; + } + close(fd); + NMLOG_INFO("VSS = %d KB RSS = %d KB", processSize, processRSS); + } std::unique_lock lock(m_processMonMutex); // Wait for the specified interval or until notified to stop if (m_processMonCondVar.wait_for(lock, std::chrono::seconds(interval), [this](){ return m_processMonThreadStop == true; })) { - NMLOG_INFO("processMonitor received stop signal"); + NMLOG_INFO("Received stop signal"); } } while (!m_processMonThreadStop); From ace4af49832a81068af702874aa4ef2964415e79 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 14 Apr 2025 14:48:42 -0400 Subject: [PATCH 119/271] RDKEMW-2191 - GetPrimaryInterface is returning wrong value for WLAN0 (#138) Reason for change: Changed the way of setting primary interface from autoconnect priority to route metric Test Procedure: Check with GetPrimaryInterface and SetPrimaryInterface curl commands Risks: Medium Priority: P1 Signed-off-by: Gururaaja ESR --- plugin/NetworkManagerImplementation.h | 2 + plugin/gnome/NetworkManagerGnomeProxy.cpp | 73 +----------------- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 77 +++++++++++++++++++ plugin/gnome/NetworkManagerGnomeWIFI.h | 1 + .../gnome/gdbus/NetworkManagerGdbusClient.h | 2 - 5 files changed, 82 insertions(+), 73 deletions(-) diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 1426124fc..3a1d92afe 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -42,6 +42,8 @@ using namespace std; #define NM_WIFI_SNR_THRESHOLD_EXCELLENT 40 #define NM_WIFI_SNR_THRESHOLD_GOOD 25 #define NM_WIFI_SNR_THRESHOLD_FAIR 18 +#define ROUTE_METRIC_PRIORITY_HIGH 1 +#define ROUTE_METRIC_PRIORITY_LOW 100 namespace WPEFramework { diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 8aeca7542..9bde044e6 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -220,78 +220,9 @@ namespace WPEFramework /* @brief Set the active Interface used for external world communication */ uint32_t NetworkManagerImplementation::SetPrimaryInterface (const string& interface/* @in */) { - uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - gboolean result; - GError *error = NULL; - std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); - - if(client == nullptr) - { - NMLOG_WARNING("client connection null:"); - return Core::ERROR_RPC_CALL_FAILED; - } - - if(interface.empty() || (wifiname != interface && ethname != interface)) - { - NMLOG_FATAL("interface is not valied %s", interface.c_str()!=nullptr? interface.c_str():"empty"); - return Core::ERROR_GENERAL; - } - - NMDevice *device = nm_client_get_device_by_iface(client, interface.c_str()); - if (device == NULL) { - NMLOG_FATAL("libnm doesn't have device corresponding to %s", interface.c_str()); - return Core::ERROR_GENERAL; - } - - const GPtrArray *connections = nm_client_get_connections(client); - NMConnection *conn = NULL; - NMSettingConnection *settings; - NMRemoteConnection *remoteConnection; - for (guint i = 0; i < connections->len; i++) { - NMConnection *connection = NM_CONNECTION(connections->pdata[i]); - settings = nm_connection_get_setting_connection(connection); - - /* Check if the interface name matches */ - if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) { - conn = connection; - break; - } - } - if(conn == NULL) - { - NMLOG_WARNING("no nm setting available for the interface"); - return Core::ERROR_GENERAL; - } - g_object_set(settings, - NM_SETTING_CONNECTION_AUTOCONNECT, - true, - NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, - NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX, - NULL); - const char *uuid = nm_connection_get_uuid(conn); - remoteConnection = nm_client_get_connection_by_uuid(client, uuid); - if (!remoteConnection) - { - NMLOG_ERROR("Failed to get remote connection"); - return rc; - } - result = nm_remote_connection_commit_changes(remoteConnection, false, NULL, &error); - if (result) + uint32_t rc = Core::ERROR_GENERAL; + if(wifi->setPrimaryInterface(interface)) rc = Core::ERROR_NONE; - else - { - if (error) - { - NMLOG_ERROR("Failed to commit changes: %s", error->message); - g_error_free(error); - } - else - { - NMLOG_ERROR("Failed to commit changes: unknown error"); - } - rc = Core::ERROR_GENERAL; - } - return rc; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 58379e439..516991387 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -1552,5 +1552,82 @@ namespace WPEFramework wait(m_loop); return m_isSuccess; } + + bool wifiManager::setPrimaryInterface(const string interface) + { + uint32_t rc = Core::ERROR_RPC_CALL_FAILED; + gboolean result; + GError *error = NULL; + std::string otherInterface; + std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); + const char *specObject = NULL; + if (!createClientNewConnection()) return false; + if(interface.empty() || (wifiname != interface && ethname != interface)) + { NMLOG_FATAL("interface is not valied %s", interface.c_str()!=nullptr? interface.c_str():"empty"); + return false; } + otherInterface = (interface == wifiname)?ethname:wifiname; + + // Retrieve the active connections by interface name + const GPtrArray* activeConnections = nm_client_get_active_connections(m_client); + if (!activeConnections) { + NMLOG_ERROR("Failed to retrieve active connections"); + return false; + } + for (guint i = 0; i < activeConnections->len; i++) + { + gpointer elem = g_ptr_array_index(activeConnections, i); + if (!elem || !NM_IS_ACTIVE_CONNECTION(elem)) { + NMLOG_WARNING("Invalid or null active connection at index %u", i); + continue; + } + NMActiveConnection *activeConnection = NM_ACTIVE_CONNECTION(elem); + const GPtrArray* activeDevices = nm_active_connection_get_devices(activeConnection); + for (guint j = 0; j < activeDevices->len; j++) + { + NMDevice* device = NM_DEVICE(g_ptr_array_index(activeDevices, j)); + const char *iface = nm_device_get_iface(device); + if (g_strcmp0(iface, interface.c_str()) == 0 || g_strcmp0(iface, otherInterface.c_str()) == 0) { + NMRemoteConnection* connection = NM_REMOTE_CONNECTION(nm_active_connection_get_connection(activeConnection)); + NMSettingIPConfig *s_ip4 = nm_connection_get_setting_ip4_config(NM_CONNECTION(connection)); + NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config(NM_CONNECTION(connection)); + if (!s_ip4 || !s_ip6) + { + NMLOG_ERROR("Failed to retrieve IP settings for connection on interface: %s\n", iface); + continue; + } + + int metric_value = (g_strcmp0(iface, interface.c_str()) == 0) ? ROUTE_METRIC_PRIORITY_HIGH:ROUTE_METRIC_PRIORITY_LOW; + g_object_set(G_OBJECT(s_ip4),NM_SETTING_IP_CONFIG_ROUTE_METRIC, metric_value, NULL); + g_object_set(G_OBJECT(s_ip6),NM_SETTING_IP_CONFIG_ROUTE_METRIC, metric_value, NULL); + // TODO fix depricated api + if (!nm_remote_connection_commit_changes(connection, FALSE, NULL, &error)) + { + if (error) { + NMLOG_ERROR("Failed to commit changes to the remote connection: %s", error->message); + g_error_free(error); // Free the GError object after handling it + } + else { + NMLOG_ERROR("Failed to commit changes to the remote connection (unknown error)."); } + return false; + } + if (activeConnection != NULL) + { + specObject = nm_object_get_path(NM_OBJECT(activeConnection)); + GError *deactivate_error = NULL; + // TODO fix depricated api + if (!nm_client_deactivate_connection(m_client, activeConnection, NULL, &deactivate_error)) + { + NMLOG_ERROR("Failed to deactivate connection: %s", deactivate_error->message); + g_clear_error(&deactivate_error); + return false; + } + } + nm_client_activate_connection_async(m_client, NM_CONNECTION(connection), device, specObject, NULL, onActivateComplete, this); + } + } + } + wait(m_loop); + return rc; + } } // namespace Plugin } // namespace WPEFramework diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 136a29d5b..449a7d29c 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -63,6 +63,7 @@ namespace WPEFramework bool stopWPS(); bool setInterfaceState(std::string interface, bool enabled); bool setIpSettings(const string interface, const Exchange::INetworkManager::IPAddress address); + bool setPrimaryInterface(const string interface); private: NMDevice *getWifiDevice(); diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusClient.h b/plugin/gnome/gdbus/NetworkManagerGdbusClient.h index 22c550445..9a727b923 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusClient.h +++ b/plugin/gnome/gdbus/NetworkManagerGdbusClient.h @@ -28,8 +28,6 @@ #include "NetworkManagerSecretAgent.h" #include "INetworkManager.h" -#define ROUTE_METRIC_PRIORITY_HIGH 10 -#define ROUTE_METRIC_PRIORITY_LOW 100 #define GDBUS_WPS_RETRY_WAIT_IN_MS 10 // 10 sec #define GDBUS_WPS_RETRY_COUNT 10 From 5a566b17aff2c00262df7f421927cc21375eb544 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Wed, 16 Apr 2025 15:36:35 +0530 Subject: [PATCH 120/271] =?UTF-8?q?RDKEMW-3191:=20Enabled=20NetworkManager?= =?UTF-8?q?=20DEBUG=20logs=20when=20SetLogLevel(DEBUG=E2=80=A6=20(#135)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * RDKEMW-3191: Enabled NetworkManager DEBUG logs when SetLogLevel(DEBUG) called * update platfom logging * set log level function move to utils --- plugin/CMakeLists.txt | 1 + plugin/NetworkManagerImplementation.cpp | 9 ++++++--- plugin/NetworkManagerImplementation.h | 1 + plugin/gnome/NetworkManagerGnomeProxy.cpp | 9 ++++++++- plugin/gnome/NetworkManagerGnomeUtils.cpp | 12 +++--------- plugin/gnome/NetworkManagerGnomeUtils.h | 2 +- plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp | 9 +++++++++ plugin/rdk/NetworkManagerRDKProxy.cpp | 9 +++++++-- 8 files changed, 36 insertions(+), 16 deletions(-) diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index d94067aa0..aad6155ec 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -90,6 +90,7 @@ if(ENABLE_GNOME_NETWORKMANAGER) gnome/gdbus/NetworkManagerGdbusEvent.cpp gnome/gdbus/NetworkManagerGdbusMgr.cpp gnome/gdbus/NetworkManagerGdbusUtils.cpp + gnome/NetworkManagerGnomeUtils.cpp NetworkManagerSecretAgent.cpp) target_include_directories(${MODULE_IMPL_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${GLIB_LIBRARIES} ${GIO_LIBRARIES} uuid) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 2a4851d86..342a9b249 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -20,7 +20,6 @@ #include #include #include "NetworkManagerImplementation.h" - using namespace WPEFramework; using namespace WPEFramework::Plugin; using namespace NetworkManagerLogger; @@ -193,6 +192,8 @@ namespace WPEFramework /* As all the configuration is set, lets instantiate platform */ NetworkManagerImplementation::platform_init(); + /* change gnome networkmanager or netsrvmgr logg level */ + NetworkManagerImplementation::platform_logging(static_cast (config.loglevel.Value())); return(Core::ERROR_NONE); } @@ -343,8 +344,10 @@ namespace WPEFramework /* @brief Set the network manager plugin log level */ uint32_t NetworkManagerImplementation::SetLogLevel(const Logging& level /* @in */) { - NetworkManagerLogger::SetLevel((LogLevel)level); - return Core::ERROR_NONE; + NetworkManagerLogger::SetLevel(static_cast(level)); + platform_logging(static_cast(level)); + NMLOG_DEBUG("loglevel %d", level); + return Core::ERROR_NONE; } /* @brief Get the network manager plugin log level */ diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 3a1d92afe..779feb61b 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -263,6 +263,7 @@ namespace WPEFramework private: void platform_init(void); + void platform_logging(const NetworkManagerLogger::LogLevel& level); void getInitialConnectionState(void); void executeExternally(NetworkEvents event, const string commandToExecute, string& response); void threadEventRegistration(void); diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 9bde044e6..11c4701d7 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -65,6 +65,14 @@ namespace WPEFramework return deviceState; } + void NetworkManagerImplementation::platform_logging(const NetworkManagerLogger::LogLevel& level) + { + /* set networkmanager daemon log level based on current plugin log level */ + if(NetworkManagerLogger::DEBUG_LEVEL != level) + return; + nmUtils::setNetworkManagerlogLevelToTrace(); + } + void NetworkManagerImplementation::platform_init() { ::_instance = this; @@ -89,7 +97,6 @@ namespace WPEFramework nmEvent = GnomeNetworkManagerEvents::getInstance(); nmEvent->startNetworkMangerEventMonitor(); wifi = wifiManager::getInstance(); - nmUtils::configureNetworkManagerDaemonLoglevel(); return; } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index d299217c0..13a4166c0 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -250,16 +250,11 @@ namespace WPEFramework return true; } - bool nmUtils::configureNetworkManagerDaemonLoglevel() + bool nmUtils::setNetworkManagerlogLevelToTrace() { /* set networkmanager daemon log level based on current plugin log level */ const char* command = "nmcli general logging level TRACE domains ALL"; - NetworkManagerLogger::LogLevel level; - NetworkManagerLogger::GetLevel(level); - if(NetworkManagerLogger::DEBUG_LEVEL != level) - return false; - // Execute the command using popen FILE *pipe = popen(command, "r"); @@ -267,7 +262,7 @@ namespace WPEFramework NMLOG_ERROR("popen failed %s ", command); return false; } - + // Close the pipe and retrieve the command's exit status int status = pclose(pipe); if (status == -1) { @@ -278,12 +273,11 @@ namespace WPEFramework // Extract the exit status from the status code int exitCode = WEXITSTATUS(status); if (exitCode == 0) - NMLOG_INFO("NetworkManager daemon log level changed ! logLevel: %d", level); + NMLOG_INFO("NetworkManager daemon log level changed to trace"); else NMLOG_INFO(" '%s' failed with exit code %d.", command, exitCode); return exitCode == 0; } - } // Plugin } // WPEFramework diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index a5c701ff3..ec12d3cb1 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -41,7 +41,7 @@ namespace WPEFramework static uint8_t wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags, bool doPrint = true); static std::string wifiFrequencyFromAp(guint32 apFreq); static std::string getSecurityModeString(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); - static bool configureNetworkManagerDaemonLoglevel(); + static bool setNetworkManagerlogLevelToTrace(); }; } } diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp index 533cfa0a3..9e34eb0f5 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp @@ -20,6 +20,7 @@ #include "NetworkManagerImplementation.h" #include "NetworkManagerGdbusClient.h" #include "NetworkManagerGdbusEvent.h" +#include "../NetworkManagerGnomeUtils.h" using namespace WPEFramework; using namespace WPEFramework::Plugin; @@ -80,6 +81,14 @@ namespace WPEFramework NMLOG_INFO("GetAvailableInterfaces Failed"); } + void NetworkManagerImplementation::platform_logging(const NetworkManagerLogger::LogLevel& level) + { + /* set networkmanager daemon log level based on current plugin log level */ + if(NetworkManagerLogger::DEBUG_LEVEL != level) + return; + nmUtils::setNetworkManagerlogLevelToTrace(); + } + void NetworkManagerImplementation::platform_init() { ::_instance = this; diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index a357a3dc8..931a9f109 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -690,6 +690,12 @@ namespace WPEFramework } } + void NetworkManagerImplementation::platform_logging(const NetworkManagerLogger::LogLevel& level) + { + // TODO set the netsrvmgr logLevel + return; + } + void NetworkManagerImplementation::platform_init() { LOG_ENTRY_FUNCTION(); @@ -705,8 +711,7 @@ namespace WPEFramework } else { NMLOG_ERROR("IARM_Bus_Init failure: %d", res); } - - + IARM_Result_t retVal = IARM_RESULT_SUCCESS; uint32_t retry = 0; From c2c0f26147bd213e51323931b6ab15335a0eeda4 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 18 Apr 2025 19:47:59 +0530 Subject: [PATCH 121/271] RDKEMW-3561 Internet precondition is not satisfied by networkmanager (#139) * RDKEMW-3561 Internet precondition is not satisfied by networkmanager plugin --- plugin/NetworkManagerJsonRpc.cpp | 36 ++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index d1b77784f..801aa41db 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -531,28 +531,31 @@ namespace WPEFramework m_publicIPAddress = ipaddress; m_publicIPAddressType = ipversion; - PublishToThunderAboutInternet(); + if (!m_publicIPAddress.empty()) + { + PublishToThunderAboutInternet(); + } } returnJson(rc); } void NetworkManager::PublishToThunderAboutInternet() { - if (!m_publicIPAddress.empty()) + PluginHost::ISubSystem* subSystem = _service->SubSystems(); + if (subSystem != nullptr) { - PluginHost::ISubSystem* subSystem = _service->SubSystems(); - - if (subSystem != nullptr) + const PluginHost::ISubSystem::IInternet* internet(subSystem->Get()); + if (nullptr == internet) { - const PluginHost::ISubSystem::IInternet* internet(subSystem->Get()); - if (nullptr == internet) - { - NMLOG_INFO("Setting INTERNET ISubSystem"); - subSystem->Set(PluginHost::ISubSystem::INTERNET, this); - } - - subSystem->Release(); + NMLOG_INFO("Setting INTERNET ISubSystem"); + subSystem->Set(PluginHost::ISubSystem::INTERNET, this); } + + subSystem->Release(); + } + else + { + NMLOG_ERROR("Failed to get ISubSystem interface"); } } @@ -1005,6 +1008,13 @@ namespace WPEFramework LOG_INPARAM(); Notify(_T("onInternetStatusChange"), parameters); + /* if new state is fully connectd set the internet subsystem only once */ + static bool isInternetSet = false; + if(!isInternetSet && currState == Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED) + { + PublishToThunderAboutInternet(); + isInternetSet = true; + } } void NetworkManager::onAvailableSSIDs(const string jsonOfScanResults) From d8b40a1adab34f817a835345d74d1e26216425fa Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 18 Apr 2025 14:07:27 -0400 Subject: [PATCH 122/271] Release of v0.14.0 Release of v0.14.0 --- CHANGELOG.md | 8 ++++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b08e05105..6d3807692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,14 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.14.0] - 2025-04-18 +### Added +- Process Monitoring for the out-of-process plugin added +- Added support Enable/Disable Logs to the Gnome NetworkManager daemon +- Fixed publishing of INTERNET Thunder Subsystem. +- Fixed the Memory Leak from the Scanned SSID names +- Fixed Set/Get Primary interface when both Ethernet and WiFi connected. + ## [0.13.0] - 2025-04-07 ### Changed - Changed the out-of-process name diff --git a/CMakeLists.txt b/CMakeLists.txt index b8b5b4eff..c650d6a57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 13) +set(VERSION_MINOR 14) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index f75aee64a..e7a8d8933 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.13.0" + "version": "0.14.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index dbc10a3ff..76fe5ccf0 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.13.0** +**Version: 0.14.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.13.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.14.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 0b91d426700fe49a481cd53d269ad28ffa87edeb Mon Sep 17 00:00:00 2001 From: parvathika <131966254+parvathika@users.noreply.github.com> Date: Wed, 23 Apr 2025 19:11:12 +0530 Subject: [PATCH 123/271] DELIA-67427-NetworkManager Thunder Plugin, Handling of IARM Connection Failure (#130) Handling of iarmbus Init and Connect API failures --- plugin/NetworkManagerImplementation.h | 2 +- plugin/rdk/NetworkManagerRDKProxy.cpp | 168 +++++++++++++++++--------- 2 files changed, 110 insertions(+), 60 deletions(-) diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 779feb61b..930c6f76a 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -266,7 +266,7 @@ namespace WPEFramework void platform_logging(const NetworkManagerLogger::LogLevel& level); void getInitialConnectionState(void); void executeExternally(NetworkEvents event, const string commandToExecute, string& response); - void threadEventRegistration(void); + void threadEventRegistration(bool iarmInit, bool iarmConnect); void filterScanResults(JsonArray &ssids); void startWiFiSignalQualityMonitor(int interval); void stopWiFiSignalQualityMonitor(); diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 931a9f109..7693f404c 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -607,46 +607,67 @@ namespace WPEFramework NMLOG_WARNING("WARNING - cannot handle IARM events without a Network plugin instance!"); } - void NetworkManagerImplementation::threadEventRegistration() + void NetworkManagerImplementation::threadEventRegistration(bool iarmInit, bool iarmConnect) { - IARM_Result_t res = IARM_RESULT_SUCCESS; - IARM_Result_t retVal = IARM_RESULT_SUCCESS; - do + uint32_t retry = 0; + char c; + IARM_Result_t retInit = IARM_RESULT_IPCCORE_FAIL; + IARM_Result_t retConnect = IARM_RESULT_IPCCORE_FAIL; + IARM_Result_t retIPC = IARM_RESULT_IPCCORE_FAIL; + do { - char c; - uint32_t retry = 0; - retVal = IARM_Bus_Call(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_isAvailable, (void *)&c, sizeof(c)); - if(retVal != IARM_RESULT_SUCCESS){ - NMLOG_ERROR("threadEventRegistration: NetSrvMgr is not available. Failed to activate NetworkManager Plugin, retrying count = %d", retry); - usleep(500*1000); - retry++; + if(iarmInit != true) + { + retInit= IARM_Bus_Init("netsrvmgr-thunder"); + if(retInit != IARM_RESULT_SUCCESS && retInit != IARM_RESULT_INVALID_STATE) + { + NMLOG_ERROR("IARM_Bus_Init failure, retrying. %d: %d", retry, retInit); + usleep(500 * 1000); + retry++; + continue; + } + iarmInit = true; } - }while(retVal != IARM_RESULT_SUCCESS); - - if(retVal != IARM_RESULT_SUCCESS) - { - NMLOG_ERROR("threadEventRegistration NetSrvMgr is not available. Failed to activate NetworkManager Plugin, retrying new cycle"); - } - else - { - IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS, NetworkManagerInternalEventHandler); - IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, NetworkManagerInternalEventHandler); - IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, NetworkManagerInternalEventHandler); - IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_DEFAULT_INTERFACE, NetworkManagerInternalEventHandler); - IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERNET_CONNECTION_CHANGED, NetworkManagerInternalEventHandler); - IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged, NetworkManagerInternalEventHandler); - IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onError, NetworkManagerInternalEventHandler); - IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, NetworkManagerInternalEventHandler); - NMLOG_INFO("threadEventRegistration successfully subscribed to IARM event for NetworkManager Plugin"); - /* - * Read current network state and post the event. - * Useful if NetworkManager plugin or WPEFramework is restarted - * or netsrvmgr misses to post iarm events during bootup. - */ - getInitialConnectionState(); - } + if(iarmConnect != true) + { + retConnect = IARM_Bus_Connect(); + if(retConnect != IARM_RESULT_SUCCESS) + { + NMLOG_ERROR("IARM_Bus_Connect failure, retrying. %d: %d", retry, retConnect); + usleep(500 * 1000); + retry++; + continue; + } + iarmConnect = true; + } + retIPC = IARM_Bus_Call_with_IPCTimeout(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_isAvailable, (void *)&c, sizeof(c), (1000*10)); + if (retIPC != IARM_RESULT_SUCCESS) + { + NMLOG_ERROR("NetSrvMgr is not available. Failed to activate NetworkManager Plugin.%d: %d", retry, retIPC); + usleep(500 * 1000); + retry++; + continue; + } + } while(retIPC != IARM_RESULT_SUCCESS); + + IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS, NetworkManagerInternalEventHandler); + IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, NetworkManagerInternalEventHandler); + IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, NetworkManagerInternalEventHandler); + IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_DEFAULT_INTERFACE, NetworkManagerInternalEventHandler); + IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERNET_CONNECTION_CHANGED, NetworkManagerInternalEventHandler); + IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged, NetworkManagerInternalEventHandler); + IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onError, NetworkManagerInternalEventHandler); + IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, NetworkManagerInternalEventHandler); + + NMLOG_INFO("threadEventRegistration successfully subscribed to IARM event for NetworkManager Plugin"); + /* + * Read current network state and post the event. + * Useful if NetworkManager plugin or WPEFramework is restarted + * or netsrvmgr misses to post iarm events during bootup. + */ + getInitialConnectionState(); } void NetworkManagerImplementation::getInitialConnectionState() @@ -702,35 +723,64 @@ namespace WPEFramework char c; ::_instance = this; + uint32_t retry = 0; + bool iarmInit = false; + bool iarmConnect = false; + + IARM_Result_t retInit = IARM_RESULT_IPCCORE_FAIL; + IARM_Result_t retConnect = IARM_RESULT_IPCCORE_FAIL; + IARM_Result_t retIPC = IARM_RESULT_IPCCORE_FAIL; - IARM_Result_t res = IARM_Bus_Init("netsrvmgr-thunder"); - NMLOG_INFO("IARM_Bus_Init: %d", res); - if (res == IARM_RESULT_SUCCESS || res == IARM_RESULT_INVALID_STATE /* already inited or connected */) { - res = IARM_Bus_Connect(); - NMLOG_INFO("IARM_Bus_Connect: %d", res); - } else { - NMLOG_ERROR("IARM_Bus_Init failure: %d", res); - } - - IARM_Result_t retVal = IARM_RESULT_SUCCESS; + do + { + if(iarmInit != true) + { + retInit = IARM_Bus_Init("netsrvmgr-thunder"); + if(retInit != IARM_RESULT_SUCCESS && retInit != IARM_RESULT_INVALID_STATE) + { + NMLOG_ERROR("IARM_Bus_Init failure,retrying.%d: %d", retry, retInit); + usleep(500 * 1000); + retry++; + continue; + } + retInit = IARM_RESULT_SUCCESS; + iarmInit = true; + } + if(iarmConnect != true) + { + retConnect = IARM_Bus_Connect(); + if(retConnect != IARM_RESULT_SUCCESS) + { + NMLOG_ERROR("IARM_Bus_Connect failed,retrying. %d: %d", retry, retConnect); + usleep(500 * 1000); + retry++; + continue; + } + iarmConnect = true; + } - uint32_t retry = 0; - do{ - retVal = IARM_Bus_Call_with_IPCTimeout(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_isAvailable, (void *)&c, sizeof(c), (1000*10)); - if(retVal != IARM_RESULT_SUCCESS){ - NMLOG_INFO("NetSrvMgr is not available. Failed to activate NetworkManager Plugin, retry = %d", retry); - usleep(500*1000); + retIPC = IARM_Bus_Call_with_IPCTimeout(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_isAvailable, (void *)&c, sizeof(c), (1000*10)); + if (retIPC != IARM_RESULT_SUCCESS) + { + NMLOG_ERROR("NetSrvMgr is not available. Failed to activate NetworkManager Plugin. %d: %d", retry, retIPC); + usleep(500 * 1000); retry++; + continue; + } + if(retIPC == IARM_RESULT_SUCCESS && retConnect == IARM_RESULT_SUCCESS && retInit == IARM_RESULT_SUCCESS) + { + break; } - }while((retVal != IARM_RESULT_SUCCESS) && (retry < 3)); + }while(retry < 3); - if(retVal != IARM_RESULT_SUCCESS) + if(retIPC != IARM_RESULT_SUCCESS) { string msg = "NetSrvMgr is not available"; - NMLOG_INFO("NETWORK_NOT_READY: The NetSrvMgr Component is not available.Retrying in separate thread ::%s::", msg.c_str()); - m_registrationThread = thread(&NetworkManagerImplementation::threadEventRegistration, this); + NMLOG_ERROR("NETWORK_NOT_READY: The NetSrvMgr Component is not available.Retrying in separate thread ::%s::", msg.c_str()); + m_registrationThread = thread(&NetworkManagerImplementation::threadEventRegistration, this, iarmInit, iarmConnect); } - else { + else + { IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS, NetworkManagerInternalEventHandler); IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, NetworkManagerInternalEventHandler); IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, NetworkManagerInternalEventHandler); @@ -739,9 +789,9 @@ namespace WPEFramework IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged, NetworkManagerInternalEventHandler); IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onError, NetworkManagerInternalEventHandler); IARM_Bus_RegisterEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, NetworkManagerInternalEventHandler); - /* + /* * Read current network state and post the event. - * Useful if NetworkManager plugin or WPEFramework is restarted + * Useful if NetworkManager plugin or WPEFramework is restarted * or netsrvmgr misses to post iarm events during bootup. */ std::thread connStateThread = std::thread(&NetworkManagerImplementation::getInitialConnectionState, this); @@ -1162,7 +1212,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { while (ssids->Next(ssidlist) == true) { m_filterSsidslist.push_back(ssidlist.c_str()); - NMLOG_DEBUG("%s added to SSID filtering", ssidlist.c_str()); + NMLOG_DEBUG("%s added to SSID filtering", ssidlist.c_str()); } } From 742248c6b9e88e25382ddb62157dd6813c73da1f Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 24 Apr 2025 07:10:50 +0530 Subject: [PATCH 124/271] RDKEMW-3682, RDKEMW-3086, RDKEMW-3414 Issue Fixes (#142) * RDKEMW-3682: Enable CLI Tool in NetworkManager-Plugin * RDKEMW-3086: Memmory leak fix * RDKEMW-3414: Unable to Reconnect to WiFi using WPS -Screen stuck at Searching page Signed-off-by: cmuhammedrafi --- plugin/NetworkManagerSecretAgent.cpp | 30 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 15 +- plugin/gnome/NetworkManagerGnomeProxy.cpp | 8 +- plugin/gnome/NetworkManagerGnomeUtils.cpp | 2 +- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 397 +++++++++++++++----- plugin/gnome/NetworkManagerGnomeWIFI.h | 4 +- tools/plugincli/CMakeLists.txt | 117 ++++-- tools/plugincli/NetworkManagerGdbusTest.cpp | 12 +- tools/plugincli/NetworkManagerLibnmTest.cpp | 391 +++++++++++++++++++ 9 files changed, 822 insertions(+), 154 deletions(-) create mode 100644 tools/plugincli/NetworkManagerLibnmTest.cpp diff --git a/plugin/NetworkManagerSecretAgent.cpp b/plugin/NetworkManagerSecretAgent.cpp index fa487a0cd..e8ab57ed5 100644 --- a/plugin/NetworkManagerSecretAgent.cpp +++ b/plugin/NetworkManagerSecretAgent.cpp @@ -72,8 +72,10 @@ namespace WPEFramework NMLOG_DEBUG("handleSecretsAgentMethods called for sender: %s", sender); char *string = g_variant_print(parameters, TRUE); - NMLOG_DEBUG("GVariant: %s", string); - g_free(string); + if(string != NULL) { + NMLOG_DEBUG("GVariant: %s", string); + g_free(string); + } if (g_strcmp0(method_name, "GetSecrets") == 0) { @@ -294,14 +296,16 @@ namespace WPEFramework &error ); - if (error != NULL && nmAgentProxy == NULL) { + if (error != NULL) { g_dbus_error_strip_remote_error(error); NMLOG_FATAL("Error creating proxy: %s", error->message); - g_clear_error(&error); + g_error_free(error); + if(nmAgentProxy) + g_object_unref(nmAgentProxy); return false; } - g_dbus_proxy_call_sync( nmAgentProxy, "Register", + GVariant *result = g_dbus_proxy_call_sync( nmAgentProxy, "Register", g_variant_new("(s)", "rdk.nm.agent"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { @@ -310,8 +314,13 @@ namespace WPEFramework return false; } + if (result != NULL) { + g_variant_unref(result); + } + NMLOG_INFO("'rdk.nm.agent' registered to NetworkManager"); isSecurityAgentRegistered = true; + if(nmAgentProxy) g_object_unref(nmAgentProxy); return true; @@ -334,20 +343,25 @@ namespace WPEFramework &error ); - if (error != NULL && nmAgentProxy == NULL) { + if (error != NULL) { g_dbus_error_strip_remote_error(error); NMLOG_FATAL("Error creating proxy: %s", error->message); - g_clear_error(&error); + g_error_free(error); + if(nmAgentProxy) + g_object_unref(nmAgentProxy); return false; } - g_dbus_proxy_call_sync(nmAgentProxy, "Unregister", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + GVariant *result = g_dbus_proxy_call_sync(nmAgentProxy, "Unregister", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { NMLOG_FATAL("Failed to call Unregister agent: %s", error->message); g_error_free(error); return false; } + if (result != NULL) { + g_variant_unref(result); + } NMLOG_INFO("'rdk.nm.agent' successfully Unregister"); isSecurityAgentRegistered = false; diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 7aafcabfa..413a0aadd 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -178,7 +178,7 @@ namespace WPEFramework wifiState += std::to_string(deviceState); } - if(isWlanDisabled & deviceState > NM_DEVICE_STATE_UNMANAGED) + if(isWlanDisabled && deviceState > NM_DEVICE_STATE_UNMANAGED) { isWlanDisabled = false; GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, nmUtils::wlanIface()); @@ -215,7 +215,12 @@ namespace WPEFramework NMLOG_WARNING("Unhandiled state change %d", deviceState); } - if(isEthDisabled & deviceState > NM_DEVICE_STATE_UNMANAGED) + /* + * Post interface added event: + * When the Ethernet interface is removed, its state goes to UNKNOWN or UNMANAGED. + * normaly interface is always up and we are not removing it + */ + if(isEthDisabled && deviceState > NM_DEVICE_STATE_UNMANAGED) { isEthDisabled = false; GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, nmUtils::ethIface()); @@ -584,6 +589,10 @@ namespace WPEFramework void GnomeNetworkManagerEvents::onAddressChangeCb(std::string iface, std::string ipAddress, bool acquired, bool isIPv6) { + /* + * notify::addresses g signal only send ipaddress when accuired time only. + * we need to post ip address when ipaddress lost case also so we caching the ip address per interface + */ static std::map ipv6Map; static std::map ipv4Map; @@ -617,11 +626,9 @@ namespace WPEFramework if(ipAddress.empty()) return; // empty ip address not posting event } - Exchange::INetworkManager::IPStatus ipStatus{}; if (acquired) ipStatus = Exchange::INetworkManager::IP_ACQUIRED; - if(_instance != nullptr) _instance->ReportIPAddressChange(iface, isIPv6?"IPv6":"IPv4", ipAddress, ipStatus); NMLOG_INFO("iface:%s - ipaddress:%s - %s - %s", iface.c_str(), ipAddress.c_str(), acquired?"acquired":"lost", isIPv6?"isIPv6":"isIPv4"); diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 11c4701d7..76e7eff3f 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -730,11 +730,9 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::GetWifiState(WiFiState &state) { - uint32_t rc = Core::ERROR_NONE; - if(wifi->isWifiConnected()) - state = Exchange::INetworkManager::WIFI_STATE_CONNECTED; - else - state = Exchange::INetworkManager::WIFI_STATE_DISCONNECTED; + uint32_t rc = Core::ERROR_GENERAL; + if(wifi->getWifiState(state)) + rc = Core::ERROR_NONE; return rc; } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index 13a4166c0..3bfd3ce69 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -178,7 +178,7 @@ namespace WPEFramework std::string nmUtils::wifiFrequencyFromAp(guint32 apFreq) { - std:string freq; + std::string freq; if (apFreq >= 2400 && apFreq < 5000) freq = "2.4"; else if (apFreq >= 5000 && apFreq < 6000) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 516991387..602b9425f 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -156,16 +156,29 @@ namespace WPEFramework bool static getConnectedSSID(NMDevice *device, std::string& ssidin) { - GBytes *ssid; - NMDeviceState device_state = nm_device_get_state(device); - if (device_state == NM_DEVICE_STATE_ACTIVATED) + GBytes *ssid = nullptr; + NMDeviceState deviceState = nm_device_get_state(device); + if (deviceState == NM_DEVICE_STATE_ACTIVATED) { NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(NM_DEVICE_WIFI(device)); + if(activeAP == nullptr) + return false; ssid = nm_access_point_get_ssid(activeAP); - gsize size; - const guint8 *ssidData = static_cast(g_bytes_get_data(ssid, &size)); - std::string ssidTmp(reinterpret_cast(ssidData), size); - ssidin = ssidTmp; + if(ssid) + { + char* ssidStr = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid)); + if(ssidStr != nullptr) + { + ssidin = ssidStr; + free(ssidStr); + } + else + { + NMLOG_ERROR("Invalid ssid length Error"); + ssidin.clear(); + return false; + } + } NMLOG_INFO("connected ssid: %s", ssidin.c_str()); return true; } @@ -193,18 +206,17 @@ namespace WPEFramework noise = 0; /* ToDo: Returning as 0 as of now. Need to fetch actual noise value */ /* Convert to strings */ - if (ssid) { - gsize size; - const guint8 *ssidData = static_cast(g_bytes_get_data(ssid, &size)); - if(size<=32) + if (ssid) + { + char* ssidStr = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid)); + if(ssidStr != nullptr) { - std::string ssidTmp(reinterpret_cast(ssidData), size); - wifiInfo.ssid = ssidTmp; - // NMLOG_INFO("ssid: %s", wifiInfo.ssid.c_str()); + wifiInfo.ssid = ssidStr; + free(ssidStr); } else { - NMLOG_ERROR("Invallied ssid length Error"); + NMLOG_ERROR("Invalid ssid length Error"); wifiInfo.ssid.clear(); return; } @@ -229,7 +241,7 @@ namespace WPEFramework if(doPrint) { NMLOG_INFO("ssid: %s, frequency: %s, sterngth: %s, security: %u", wifiInfo.ssid.c_str(), wifiInfo.frequency.c_str(), wifiInfo.strength.c_str(), wifiInfo.security); - NMLOG_INFO("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); + NMLOG_DEBUG("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); } else { @@ -238,24 +250,43 @@ namespace WPEFramework } } - bool wifiManager::isWifiConnected() + bool wifiManager::getWifiState(Exchange::INetworkManager::WiFiState& state) { if(!createClientNewConnection()) return false; - NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getWifiDevice()); + NMDevice *wifiDevice = getWifiDevice(); if(wifiDevice == NULL) { NMLOG_FATAL("NMDeviceWifi * NULL !"); return false; } - - NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(wifiDevice); - if(activeAP == NULL) { - NMLOG_DEBUG("No active access point found !"); - return false; + NMDeviceState deviceState = nm_device_get_state(wifiDevice); + // Todo check NMDeviceStateReason for more information + switch(deviceState) + { + case NM_DEVICE_STATE_ACTIVATED: + state = Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTED; + break; + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + state = Exchange::INetworkManager::WiFiState::WIFI_STATE_PAIRING; + break; + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_IP_CHECK: + case NM_DEVICE_STATE_SECONDARIES: + state = Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTING; + break; + case NM_DEVICE_STATE_DEACTIVATING: + case NM_DEVICE_STATE_DISCONNECTED: + case NM_DEVICE_STATE_UNAVAILABLE: + state = Exchange::INetworkManager::WiFiState::WIFI_STATE_DISCONNECTED; + break; + default: + state = Exchange::INetworkManager::WiFiState::WIFI_STATE_DISABLED; } - else - NMLOG_DEBUG("active access point found !"); + + NMLOG_INFO("wifi state (%d) mapped state (%d) ", (int)deviceState, (int)state); return true; } @@ -338,25 +369,34 @@ namespace WPEFramework static NMAccessPoint* findMatchingSSID(const GPtrArray* ApList, std::string& ssid) { - NMAccessPoint *AccessPoint = NULL; + NMAccessPoint *AccessPoint = nullptr; if(ssid.empty()) - return NULL; + return nullptr; for (guint i = 0; i < ApList->len; i++) { + std::string ssidstr{}; NMAccessPoint *ap = static_cast(g_ptr_array_index(ApList, i)); - GBytes *ssidGBytes; - ssidGBytes = nm_access_point_get_ssid(ap); - if (!ssidGBytes) - continue; - gsize size; - const guint8 *ssidData = static_cast(g_bytes_get_data(ssidGBytes, &size)); - std::string ssidstr(reinterpret_cast(ssidData), size); - // NMLOG_DEBUG("ssid < %s >", ssidstr.c_str()); - if (ssid == ssidstr) + GBytes *ssidGBytes = nm_access_point_get_ssid(ap); + if(ssidGBytes) { - AccessPoint = ap; - break; + char* ssidUtf8 = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssidGBytes, NULL), g_bytes_get_size(ssidGBytes)); + if(ssidUtf8 != nullptr) + { + ssidstr = ssidUtf8; + if(ssid == ssidstr) + { + AccessPoint = ap; + free(ssidUtf8); + break; + } + // NMLOG_DEBUG("ssid < %s >", ssidstr.c_str()); + } + else + NMLOG_WARNING("Invalid ssid length Error"); + + if(ssidUtf8 != nullptr) + free(ssidUtf8); } } @@ -367,15 +407,16 @@ namespace WPEFramework { GError *error = NULL; wifiManager *_wifiManager = (static_cast(user_data)); + NMActiveConnection *activeConnection = NULL; if (_wifiManager->m_createNewConnection) { NMLOG_DEBUG("nm_client_add_and_activate_connection_finish"); - nm_client_add_and_activate_connection_finish(NM_CLIENT(_wifiManager->m_client), result, &error); + activeConnection = nm_client_add_and_activate_connection_finish(NM_CLIENT(_wifiManager->m_client), result, &error); _wifiManager->m_isSuccess = true; } else { NMLOG_DEBUG("nm_client_activate_connection_finish "); - nm_client_activate_connection_finish(NM_CLIENT(_wifiManager->m_client), result, &error); + activeConnection = nm_client_activate_connection_finish(NM_CLIENT(_wifiManager->m_client), result, &error); _wifiManager->m_isSuccess = true; } @@ -386,8 +427,11 @@ namespace WPEFramework } else { NMLOG_ERROR("Failed to activate connection: %s", error->message); } + g_error_free(error); } + if(activeConnection) + g_object_unref(activeConnection); g_main_loop_quit(_wifiManager->m_loop); } @@ -400,13 +444,18 @@ namespace WPEFramework ret = nm_remote_connection_update2_finish(remote_con, res, &error); - if (!ret) { - NMLOG_ERROR("Error: %s.", error->message); - g_error_free(error); + if (!ret || error) { + if(error) { + NMLOG_ERROR("Error: %s.", error->message); + g_error_free(error); + } _wifiManager->m_isSuccess = false; _wifiManager->quit(NULL); return; } + else + g_variant_unref(ret); + _wifiManager->m_createNewConnection = false; // no need to create new connection nm_client_activate_connection_async( _wifiManager->m_client, NM_CONNECTION(remote_con), _wifiManager->m_wifidevice, _wifiManager->m_objectPath, NULL, wifiConnectCb, _wifiManager); @@ -416,7 +465,7 @@ namespace WPEFramework { if(ssidinfo.ssid.empty() || ssidinfo.ssid.length() > 32) { - NMLOG_WARNING("ssid name is missing or invalied"); + NMLOG_WARNING("ssid name is missing or invalid"); return false; } /* Build up the 'connection' Setting */ @@ -427,6 +476,8 @@ namespace WPEFramework g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_INTERFACE_NAME, "wlan0", NULL); // interface name g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_TYPE, "802-11-wireless", NULL); // type 802.11wireless nm_connection_add_setting(m_connection, NM_SETTING(sConnection)); + if(uuid) + g_free((void *)uuid); /* Build up the '802-11-wireless-security' settings */ NMSettingWireless *sWireless = NULL; @@ -437,6 +488,8 @@ namespace WPEFramework g_object_set(G_OBJECT(sWireless), NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA, NULL); // infra mode if(!iswpsAP) // wps never be a hidden AP, it will be always visible g_object_set(G_OBJECT(sWireless), NM_SETTING_WIRELESS_HIDDEN, true, NULL); // hidden = true + if(ssid) + g_bytes_unref(ssid); // 'bssid' parameter is used to restrict the connection only to the BSSID // g_object_set(s_wifi, NM_SETTING_WIRELESS_BSSID, bssid, NULL); @@ -553,10 +606,8 @@ namespace WPEFramework bool wifiManager::activateKnownWifiConnection(std::string knownssid) { - NMAccessPoint *AccessPoint = NULL; const GPtrArray *wifiConnections = NULL; NMConnection *m_connection = NULL; - const GPtrArray* ApList = NULL; const char* specificObjPath = "/"; if(!createClientNewConnection()) @@ -743,10 +794,14 @@ namespace WPEFramework if(!connectionBuilder(ssidInfo, m_connection)) { NMLOG_ERROR("connection builder failed"); + if(m_connection) + g_object_unref(m_connection); return false; } m_createNewConnection = true; nm_client_add_and_activate_connection_async(m_client, m_connection, m_wifidevice, m_objectPath, NULL, wifiConnectCb, this); + if(m_connection) + g_object_unref(m_connection); } wait(m_loop); @@ -773,6 +828,10 @@ namespace WPEFramework _wifiManager->m_isSuccess = true; NMLOG_INFO("AddToKnownSSIDs success"); } + + if(ret) + g_variant_unref(ret); + _wifiManager->quit(NULL); } @@ -780,8 +839,7 @@ namespace WPEFramework { GError *error = NULL; wifiManager *_wifiManager = (static_cast(user_data)); - GVariant **outResult = NULL; - if (!nm_client_add_connection2_finish(NM_CLIENT(client), result, outResult, &error)) { + if (!nm_client_add_connection2_finish(NM_CLIENT(client), result, NULL, &error)) { NMLOG_ERROR("AddToKnownSSIDs Failed"); _wifiManager->m_isSuccess = false; } @@ -791,6 +849,11 @@ namespace WPEFramework _wifiManager->m_isSuccess = true; } + if(error) { + NMLOG_ERROR("AddToKnownSSIDs Failed: %s", error->message); + _wifiManager->m_isSuccess = false; + g_error_free(error); + } g_main_loop_quit(_wifiManager->m_loop); } @@ -807,6 +870,12 @@ namespace WPEFramework return false; const GPtrArray *availableConnections = nm_device_get_available_connections(device); + if(availableConnections == NULL) + { + NMLOG_ERROR("No available connections found !"); + return false; + } + for (guint i = 0; i < availableConnections->len; i++) { NMConnection *connection = static_cast(g_ptr_array_index(availableConnections, i)); @@ -869,6 +938,11 @@ namespace WPEFramework NMLOG_WARNING("ssid is not specified, Deleting all availble wifi connection !"); const GPtrArray *allconnections = nm_client_get_connections(m_client); + if(allconnections == NULL) + { + NMLOG_ERROR("nm connections list null "); + return false; + } for (guint i = 0; i < allconnections->len; i++) { GError *error = NULL; @@ -916,29 +990,44 @@ namespace WPEFramework bool wifiManager::getKnownSSIDs(std::list& ssids) { + std::string ssidPrint{}; + if(!createClientNewConnection()) return false; + const GPtrArray *connections = nm_client_get_connections(m_client); - std::string ssidPrint; + if(connections == nullptr) + { + NMLOG_ERROR("nm connections list null "); + return false; + } for (guint i = 0; i < connections->len; i++) { NMConnection *connection = NM_CONNECTION(connections->pdata[i]); - - if (NM_IS_SETTING_WIRELESS(nm_connection_get_setting_wireless(connection))) + if(NM_IS_SETTING_WIRELESS(nm_connection_get_setting_wireless(connection))) { GBytes *ssidBytes = nm_setting_wireless_get_ssid(nm_connection_get_setting_wireless(connection)); if (ssidBytes) { - gsize ssidSize; - const guint8 *ssidData = static_cast(g_bytes_get_data(ssidBytes, &ssidSize)); - std::string ssidstr(reinterpret_cast(ssidData), ssidSize); - if (!ssidstr.empty()) + char* ssidStr = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssidBytes, NULL), g_bytes_get_size(ssidBytes)); + if(ssidStr != nullptr) { - ssids.push_back(ssidstr); - ssidPrint += ssidstr; + ssids.push_back(string(ssidStr)); + ssidPrint += ssidStr; ssidPrint += ", "; + free(ssidStr); + } + else + { + NMLOG_ERROR("Invalid ssid length Error"); + continue; } } + else + { + /* hidden ssid */ + NMLOG_WARNING("wifi connection list have hidden ssid also !"); + } } } if (!ssids.empty()) @@ -1035,7 +1124,8 @@ namespace WPEFramework if (error) NMLOG_ERROR("Failed to add/activate new connection: %s", error->message); - + else + NMLOG_INFO("WPS connection added/activated successfully"); g_main_loop_quit(loop); } @@ -1076,23 +1166,19 @@ namespace WPEFramework return true; } - static bool findWpsPbcSSID(const GPtrArray* ApList, std::string& wpsApSsid, NMAccessPoint** wpsAp) + static bool findWpsPbcSSID(const GPtrArray* ApList, Exchange::INetworkManager::WiFiSSIDInfo& wpsApInfo, const char** apObjPath) { - Exchange::INetworkManager::WiFiSSIDInfo wpsApInfo{}; for (guint i = 0; i < ApList->len; i++) { NMAccessPoint *Ap = static_cast(g_ptr_array_index(ApList, i)); guint32 flags = nm_access_point_get_flags(Ap); if (flags & NM_802_11_AP_FLAGS_WPS_PBC) { - *wpsAp = Ap; - const char *bssid = nm_access_point_get_bssid(Ap); - if (bssid != NULL) { - NMLOG_INFO("WPS PBC AP found bssid = %s", bssid); - } - - getApInfo(Ap, wpsApInfo, false); - wpsApSsid = wpsApInfo.ssid; + getApInfo(Ap, wpsApInfo, true); + *apObjPath = nm_object_get_path(NM_OBJECT(Ap)); + if(*apObjPath == NULL) + return false; + NMLOG_INFO("WPS PBC AP found! bssid: %s, Ap Path: %s", wpsApInfo.bssid.c_str(), *apObjPath); return true; } } @@ -1101,17 +1187,20 @@ namespace WPEFramework return false; } - static void wpsProcess() + void wifiManager::wpsProcess() { wpsProcessRun = true; GError *error = NULL; const GPtrArray* ApList = NULL; std::string wpsApSsid{}; GMainContext *wpsContext = NULL; - NMAccessPoint *wpsAp = NULL; + const char *wpsApPath = NULL; GMainLoop *loop = NULL; - Exchange::INetworkManager::WiFiConnectTo ssidInfo{}; + Exchange::INetworkManager::WiFiConnectTo wifiConnectInfo{}; + Exchange::INetworkManager::WiFiSSIDInfo wpsApInfo{}; + bool wpsComplete= false; + bool wpsActionTriggerd = false; if(_instance != nullptr) _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTING); @@ -1137,13 +1226,21 @@ namespace WPEFramework NMLOG_ERROR("acquire wpsContext failed !!"); break; } - + g_main_context_push_thread_default(wpsContext); NMClient* client = nm_client_new(NULL, &error); - if (!client && error != NULL) { - NMLOG_ERROR("Could not connect to NetworkManager: %s.", error->message); - g_error_free(error); + if (!client) + { + if(error != NULL) { + NMLOG_ERROR("Could not connect to NetworkManager: %s.", error->message); + g_error_free(error); + } + else + NMLOG_ERROR("NetworkManager cleint create failed"); + + g_main_context_pop_thread_default(wpsContext); + g_main_context_unref(wpsContext); break; } @@ -1151,58 +1248,136 @@ namespace WPEFramework if(wifidevice == NULL) { NMLOG_ERROR("Failed to get device list."); + g_main_context_pop_thread_default(wpsContext); + g_main_context_unref(wpsContext); + if(client != NULL) { + g_object_unref(client); + client = NULL; + } break; } + if(wpsActionTriggerd) + { + /* if wps action started we need to check the status of wifi device and post event based on that */ + NMDeviceState state = nm_device_get_state(wifidevice); + if(state <= NM_DEVICE_STATE_DISCONNECTED) + { + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + // TODO post correct error code insted of WIFI_STATE_SSID_NOT_FOUND + // sedning WIFI_STATE_SSID_NOT_FOUND to avoid UI stuck issue + break; + } + else if(state > NM_DEVICE_STATE_NEED_AUTH) + { + NMLOG_INFO("WPS process completed successfully"); + wpsComplete = true; + // TODO stop Secret agenet ? + break; + } + + NMLOG_INFO("WPS process not completed yet, state: %d", state); + if(retry >= WPS_RETRY_COUNT - 1) // 3 times retry to check the status + { + // wifi state stuck in betwen disconnected and connected + NMLOG_ERROR("WPS process failed"); + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + // TODO post correct error code insted of WIFI_STATE_SSID_NOT_FOUND + // sedning WIFI_STATE_SSID_NOT_FOUND to avoid UI stuck issue + } + } + ApList = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(wifidevice)); if(ApList == NULL) { NMLOG_ERROR("Aplist Error !"); + g_main_context_pop_thread_default(wpsContext); + g_main_context_unref(wpsContext); + if(client != NULL) { + g_object_unref(client); + client = NULL; + } break; } - if(findWpsPbcSSID(ApList, wpsApSsid, &wpsAp) && wpsAp != NULL) + if(!wpsActionTriggerd && findWpsPbcSSID(ApList, wpsApInfo, &wpsApPath) && wpsApPath != NULL) { Exchange::INetworkManager::WiFiSSIDInfo activeApInfo{}; NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(NM_DEVICE_WIFI(wifidevice)); - if(activeAP != NULL) { - NMLOG_DEBUG("active access point found !"); + if(activeAP != NULL) + { + NMLOG_WARNING("active access point found during wps operation !"); getApInfo(activeAP, activeApInfo); - if(activeApInfo.ssid == wpsApSsid) + if(activeApInfo.ssid == wpsApInfo.ssid) { - NMLOG_INFO("WPS process stoped connected to '%s' wps ap ", wpsApSsid.c_str()); + NMLOG_INFO("WPS process stoped connected to same '%s' wps ap ", wpsApInfo.ssid.c_str()); wpsComplete = true; - } + //TODO Post SSID connected event ? + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); - NMDeviceState state = nm_device_get_state(wifidevice); - if(!wpsComplete && state > NM_DEVICE_STATE_DISCONNECTED) + } + else { - NMLOG_INFO("stopping the ongoing Wi-Fi connection"); - // some other ssid connected or connecting; wps need a disconnected wifi state - nm_device_disconnect(wifidevice, NULL, &error); - if (error) - NMLOG_ERROR("disconnect connection failed %s", error->message); + NMDeviceState state = nm_device_get_state(wifidevice); + if(state > NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_INFO("stopping the ongoing Wi-Fi connection"); + // some other ssid connected or connecting; wps need a disconnected wifi state + nm_device_disconnect(wifidevice, NULL, &error); + if (error) + NMLOG_ERROR("disconnect connection failed %s", error->message); + sleep(3); // wait for 3 sec to complete disconnect process + } } } if(wpsComplete) + { + g_main_context_pop_thread_default(wpsContext); + g_main_context_unref(wpsContext); + if(client != NULL) { + g_object_unref(client); + client = NULL; + } break; + } - ssidInfo.ssid = wpsApSsid; + wifiConnectInfo.ssid = wpsApInfo.ssid; + wifiConnectInfo.security = wpsApInfo.security; NMConnection* connection = NULL; /* if same connection name exsist we remove and add new one */ - removeSameNmConnection(wifidevice, wpsApSsid); - NMLOG_DEBUG("creating new connection '%s' ", wpsApSsid.c_str()); + removeSameNmConnection(wifidevice, wifiConnectInfo.ssid); + NMLOG_DEBUG("creating new connection '%s' ", wifiConnectInfo.ssid.c_str()); connection = nm_simple_connection_new(); - const char* apObjPath = nm_object_get_path(NM_OBJECT(wpsAp)); - if(!connectionBuilder(ssidInfo, connection, true)) + if(!connectionBuilder(wifiConnectInfo, connection, true)) { NMLOG_ERROR("wps connection builder failed"); + g_main_context_pop_thread_default(wpsContext); + g_main_context_unref(wpsContext); + if(client != NULL) { + g_object_unref(client); + client = NULL; + } return; } loop = g_main_loop_new(wpsContext, FALSE); - nm_client_add_and_activate_connection_async(client, connection, wifidevice, apObjPath, NULL, wpsWifiConnectCb, loop); + if(loop == NULL) + { + NMLOG_ERROR("g_main_loop_new failed"); + g_main_context_pop_thread_default(wpsContext); + g_main_context_unref(wpsContext); + if(client != NULL) { + g_object_unref(client); + client = NULL; + } + break; + } + + nm_client_add_and_activate_connection_async(client, connection, wifidevice, wpsApPath, NULL, wpsWifiConnectCb, loop); GSource *source = g_timeout_source_new(10000); // 10000ms interval if(source != nullptr) { g_source_set_callback(source, (GSourceFunc)wpsGmainLoopTimoutCB, loop, NULL); @@ -1216,23 +1391,36 @@ namespace WPEFramework } g_source_unref(source); } - wpsComplete = true; + if(loop != NULL) { + g_main_loop_unref(loop); + loop = NULL; + } + if(connection != NULL) { + g_object_unref(connection); + connection = NULL; + } + + wpsActionTriggerd = true; + retry = WPS_RETRY_COUNT - 3; // expecting wps process will be completed in 30 sec(3 10sec retry) (Ex: retry = 10-3) } - else + else if(!wpsActionTriggerd) { - //TODO Post SSID lost event ? + /* if wps action not triggerd do a scanning request */ nm_device_wifi_request_scan(NM_DEVICE_WIFI(wifidevice), NULL, &error); } g_main_context_pop_thread_default(wpsContext); + g_main_context_unref(wpsContext); + if(client != NULL) { + g_object_unref(client); + client = NULL; + } - if(wpsComplete) + if(wpsComplete || wpsProcessRun.load() == false) // stop wps process if user requested break; - - g_main_context_unref(wpsContext); } - if(wpsAp == NULL) + if(wpsApPath == NULL) { NMLOG_WARNING("WPS AP not found"); if(_instance != nullptr) @@ -1245,8 +1433,10 @@ namespace WPEFramework _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED); } - wpsProcessRun = false; + // wps success ! wifi connect event will be send by wifi event monitor + m_secretAgent.UnregisterAgent(); NMLOG_INFO("WPS process thread exist"); + wpsProcessRun = false; } bool wifiManager::startWPS() @@ -1259,7 +1449,7 @@ namespace WPEFramework } m_secretAgent.RegisterAgent(); - std::thread wpsthread(&wpsProcess); + std::thread wpsthread(&wifiManager::wpsProcess, this); wpsthread.detach(); return true; } @@ -1556,7 +1746,6 @@ namespace WPEFramework bool wifiManager::setPrimaryInterface(const string interface) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - gboolean result; GError *error = NULL; std::string otherInterface; std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 449a7d29c..0e95dfef0 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -33,6 +33,7 @@ #define WPS_RETRY_WAIT_IN_MS 10 // 10 sec #define WPS_RETRY_COUNT 10 +#define WPS_PROCESS_WAIT_IN_MS 5 namespace WPEFramework { @@ -47,7 +48,7 @@ namespace WPEFramework return &instance; } - bool isWifiConnected(); + bool getWifiState(Exchange::INetworkManager::WiFiState& state); bool wifiDisconnect(); bool activateKnownWifiConnection(std::string knownssid); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); @@ -82,6 +83,7 @@ namespace WPEFramework } } + void wpsProcess(); wifiManager(wifiManager const&) = delete; void operator=(wifiManager const&) = delete; diff --git a/tools/plugincli/CMakeLists.txt b/tools/plugincli/CMakeLists.txt index ac0bce1d0..e1f5fd621 100644 --- a/tools/plugincli/CMakeLists.txt +++ b/tools/plugincli/CMakeLists.txt @@ -16,42 +16,109 @@ # See the License for the specific language governing permissions and # limitations under the License. ############################################################################# -message("building rpi test build") -# Define the project -set(RPI_TEST "NetworkManagerGdbusTest") +message("Building plugin CLI tools") # Required packages find_package(PkgConfig REQUIRED) +find_package(${NAMESPACE}Core REQUIRED) + pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(GIO REQUIRED gio-2.0) pkg_check_modules(LIBNM REQUIRED libnm) -# Create the executable target -add_executable(${RPI_TEST} - NetworkManagerLogger.cpp - gdbus/NetworkManagerGdbusClient.cpp - gdbus/NetworkManagerGdbusUtils.cpp - gdbus/NetworkManagerGdbusMgr.cpp - gdbus/NetworkManagerGdbusEvent.cpp - Tests/raspberrypi/NetworkManagerGdbusTest.cpp +set(COMMON_COMPILE_OPTIONS + -g + -Wall + -Wno-deprecated-declarations + -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h +) + +set(COMMON_SOURCES + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerSecretAgent.cpp + ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeUtils.cpp +) + +set(COMMON_INCLUDES + ${GLIB_INCLUDE_DIRS} + ${GIO_INCLUDE_DIRS} + ${LIBNM_INCLUDE_DIRS} + ${CMAKE_SOURCE_DIR}/plugin + ${CMAKE_SOURCE_DIR}/interface + ${CMAKE_SOURCE_DIR}/plugin/gnome + ${CMAKE_SOURCE_DIR}/plugin/gnome/gdbus ) -# Set target properties for C++ standard -set_target_properties(${RPI_TEST} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES +set(COMMON_LIBS + ${NAMESPACE}Core::${NAMESPACE}Core + ${GLIB_LIBRARIES} + ${GIO_LIBRARIES} ) -# Add compiler options, such as forced include of a specific header -target_compile_options(${RPI_TEST} PRIVATE -g -Wall -include ${CMAKE_SOURCE_DIR}/INetworkManager.h) +if(ENABLE_GNOME_GDBUS) + + message("Building plugin GDBUS CLI tool...") + + set(PLUGIN_GDBUS_CLI "nm-cli-gdbus") + set(GDBUS_SOURCES + ${CMAKE_SOURCE_DIR}/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp + ${CMAKE_SOURCE_DIR}/plugin/gnome/gdbus/NetworkManagerGdbusMgr.cpp + ${CMAKE_SOURCE_DIR}/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp + ${CMAKE_SOURCE_DIR}/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/NetworkManagerGdbusTest.cpp + ) + + add_executable(${PLUGIN_GDBUS_CLI} + ${COMMON_SOURCES} + ${GDBUS_SOURCES} + ) + + set_target_properties(${PLUGIN_GDBUS_CLI} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES + ) + + set_source_files_properties( + ${CMAKE_CURRENT_SOURCE_DIR}/NetworkManagerGdbusTest.cpp + PROPERTIES COMPILE_FLAGS "-w" + ) + + target_compile_options(${PLUGIN_GDBUS_CLI} PRIVATE ${COMMON_COMPILE_OPTIONS}) + target_include_directories(${PLUGIN_GDBUS_CLI} PRIVATE ${COMMON_INCLUDES}) + target_link_libraries(${PLUGIN_GDBUS_CLI} PRIVATE ${COMMON_LIBS} uuid) + + install(TARGETS ${PLUGIN_GDBUS_CLI} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) + +else() + + message("Building plugin Libnm CLI tool...") + + set(PLUGIN_LIBNM_CLI "nm-cli-libnm") + set(LIBNM_SOURCES + ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeEvents.cpp + ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeWIFI.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/NetworkManagerLibnmTest.cpp + ) + + add_executable(${PLUGIN_LIBNM_CLI} + ${COMMON_SOURCES} + ${LIBNM_SOURCES} + ) + + set_target_properties(${PLUGIN_LIBNM_CLI} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES + ) + + set_source_files_properties( + ${CMAKE_CURRENT_SOURCE_DIR}/NetworkManagerLibnmTest.cpp + PROPERTIES COMPILE_FLAGS "-w" + ) -target_include_directories(${RPI_TEST} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}) -target_include_directories(${RPI_TEST} PRIVATE gdbus) -# Link libraries to the target -target_link_libraries(${RPI_TEST} ${NAMESPACE}Core::${NAMESPACE}Core ${GLIB_LIBRARIES} ${GIO_LIBRARIES} uuid) + target_compile_options(${PLUGIN_LIBNM_CLI} PRIVATE ${COMMON_COMPILE_OPTIONS}) + target_include_directories(${PLUGIN_LIBNM_CLI} PRIVATE ${COMMON_INCLUDES}) + target_link_libraries(${PLUGIN_LIBNM_CLI} PRIVATE ${COMMON_LIBS} ${LIBNM_LIBRARIES}) -# Include directories -target_include_directories(${RPI_TEST} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + install(TARGETS ${PLUGIN_LIBNM_CLI} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -# Install the executable to the appropriate location -install(TARGETS ${RPI_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +endif() diff --git a/tools/plugincli/NetworkManagerGdbusTest.cpp b/tools/plugincli/NetworkManagerGdbusTest.cpp index d1421204c..d37e411a9 100644 --- a/tools/plugincli/NetworkManagerGdbusTest.cpp +++ b/tools/plugincli/NetworkManagerGdbusTest.cpp @@ -63,7 +63,7 @@ namespace WPEFramework { NMLOG_INFO("calling 'ReportWiFiStateChange' cb"); } - void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const string strength, const Exchange::INetworkManager::WiFiSignalQuality quality) + void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality) { NMLOG_INFO("calling 'ReportWiFiSignalQualityChange' cb"); } @@ -156,11 +156,11 @@ int main() case 2: { std::list ssids; - if (nmClient->getAvailableSSIDs(ssids)) { - printSSIDs(ssids); - } else { - NMLOG_ERROR("Failed to get available SSIDs"); - } + // if (nmClient->getAvailableSSIDs(ssids)) { + // printSSIDs(ssids); + // } else { + // NMLOG_ERROR("Failed to get available SSIDs"); + // } break; } diff --git a/tools/plugincli/NetworkManagerLibnmTest.cpp b/tools/plugincli/NetworkManagerLibnmTest.cpp new file mode 100644 index 000000000..08254a099 --- /dev/null +++ b/tools/plugincli/NetworkManagerLibnmTest.cpp @@ -0,0 +1,391 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ +#include "NetworkManagerLogger.h" +#include "NetworkManagerGnomeEvents.h" +#include "INetworkManager.h" +#include "NetworkManagerGnomeUtils.h" +#include "NetworkManagerImplementation.h" +#include "NetworkManagerGnomeWIFI.h" +#include +#include +#include +#include +#include + +using namespace WPEFramework; +using namespace WPEFramework::Plugin; +using namespace WPEFramework::Exchange; +using namespace std; + +namespace WPEFramework +{ + namespace Plugin + { + + void NetworkManagerImplementation::ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface) + { + NMLOG_INFO("calling 'ReportInterfaceStateChange' cb"); + } + void NetworkManagerImplementation::ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface) + { + NMLOG_INFO("calling 'ReportActiveInterfaceChange' cb"); + } + void NetworkManagerImplementation::ReportIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status) + { + NMLOG_INFO("calling 'ReportIPAddressChange' cb"); + } + void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) + { + NMLOG_INFO("calling 'ReportInternetStatusChange' cb"); + } + void NetworkManagerImplementation::ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults) + { + NMLOG_INFO("calling 'ReportAvailableSSIDs' cb"); + } + void NetworkManagerImplementation::ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state) + { + NMLOG_INFO("calling 'ReportWiFiStateChange' cb"); + } + void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality) + { + NMLOG_INFO("calling 'ReportWiFiSignalQualityChange' cb"); + } + + NetworkManagerImplementation* _instance = nullptr; + } +} + +void displayMenu() +{ + std::cout << "\n--- Network Manager API Test Menu ---" << std::endl; + std::cout << "1. Get Known SSIDs" << std::endl; + std::cout << "2. Get Connected SSID" << std::endl; + std::cout << "3. Add to Known SSIDs" << std::endl; + std::cout << "4. Remove Known SSIDs" << std::endl; + std::cout << "5. Start WiFi Scan" << std::endl; + std::cout << "6. WiFi Connect" << std::endl; + std::cout << "7. WiFi Disconnect" << std::endl; + std::cout << "8. Get WiFi State" << std::endl; + std::cout << "9. start WPS" << std::endl; + std::cout << "10. stop WPS" << std::endl; + std::cout << "11. Get WiFi Signal Strength" << std::endl; + std::cout << "12. GetAvailableInterface" << std::endl; + std::cout << "13. GetPrimaryInterface" << std::endl; + std::cout << "14. SetPrimaryInterface" << std::endl; + std::cout << "15. SetInterfaceState" << std::endl; + std::cout << "16. GetInterfaceState" << std::endl; + std::cout << "17. GetIPSettings" << std::endl; + std::cout << "18. SetIPSettings" << std::endl; + std::cout << "0. Exit" << std::endl; + std::cout << "-------------------------------------" << std::endl; +} + +WPEFramework::Exchange::INetworkManager::WIFISecurityMode getSecurityType() +{ + int securityChoice; + std::cout << "Select Security Type:" << std::endl; + std::cout << "1. WIFI_SECURITY_NONE" << std::endl; + std::cout << "2. WIFI_SECURITY_WPA_PSK" << std::endl; + std::cout << "3. WIFI_SECURITY_SAE" << std::endl; + std::cout << "4. WIFI_SECURITY_EAP" << std::endl; + std::cin >> securityChoice; + + switch (securityChoice) { + case 4: + return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_EAP; + case 3: + return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_SAE; + case 2: + return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_WPA_PSK; + case 1: + return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_NONE; + default: + std::cout << "Invalid choice. Defaulting to open." << std::endl; + return WPEFramework::Exchange::INetworkManager::WIFI_SECURITY_NONE; + } +} + +void printSSIDs(const std::list& ssids) +{ + if (ssids.empty()) { + std::cout << "No SSIDs found" << std::endl; + } else { + std::cout << "SSIDs:" << std::endl; + for (const auto& ssid : ssids) { + std::cout << "- " << ssid << std::endl; + } + } +} + +int main() +{ + int choice = -1; + NMLOG_INFO("Starting NetworkManager libnm cli tool"); + NetworkManagerLogger::SetLevel(NetworkManagerLogger::DEBUG_LEVEL); + GnomeNetworkManagerEvents* nmEvent = GnomeNetworkManagerEvents::getInstance(); + wifiManager *wifiMgr = wifiManager::getInstance(); + nmEvent->startNetworkMangerEventMonitor(); + if (wifiMgr == nullptr) { + NMLOG_ERROR("Failed to create wifiManager instance"); + return -1; + } + NMLOG_INFO("wifiManager instance created successfully"); + while (choice != 0) + { + displayMenu(); + std::cout << "Enter your choice: \n"; + std::cin >> choice; + switch (choice) + { + case 0: + break; + case 1: { + std::list ssids; + if (wifiMgr->getKnownSSIDs(ssids)) { + printSSIDs(ssids); + } else { + NMLOG_ERROR("Failed to get available SSIDs"); + } + break; + } + case 2: { + Exchange::INetworkManager::WiFiSSIDInfo ssidinfo; + if (wifiMgr->wifiConnectedSSIDInfo(ssidinfo)) + NMLOG_INFO("Connected SSID: %s", ssidinfo.ssid.c_str()); + else + NMLOG_ERROR("Failed to get connected SSID"); + break; + } + case 3: { + std::string ssid, passphrase; + std::cout << "Enter SSID to add : "; + std::cin.ignore(); + std::getline(std::cin, ssid); + std::cout << "Enter passphrase: "; + std::getline(std::cin, passphrase); + WPEFramework::Exchange::INetworkManager::WIFISecurityMode securityType = getSecurityType(); + Exchange::INetworkManager::WiFiConnectTo ssidinfo = { + .ssid = ssid, + .passphrase = passphrase, + .security = securityType, + .persist = true, + }; + if (wifiMgr->addToKnownSSIDs(ssidinfo)) { + NMLOG_INFO("SSID added to known list successfully"); + } else { + NMLOG_ERROR("Failed to add SSID to known list"); + } + break; + } + case 4: { + std::string ssid; + std::cout << "Enter know ssid to remove ? (leave blank for all): "; + std::cin.ignore(); + std::getline(std::cin, ssid); + if (wifiMgr->removeKnownSSID(ssid)) { + NMLOG_INFO("SSID removed successfully"); + } else { + NMLOG_ERROR("Failed to remove SSID"); + } + break; + } + case 5: + { + std::string ssid; + std::cout << "Enter SSID to scan (leave blank for all): "; + + if (std::cin.peek() == '\n') { + std::cin.ignore(); + } + + std::getline(std::cin, ssid); + + nmEvent->setwifiScanOptions(true); // If this triggers scan customization + + NMLOG_INFO("Sending WiFi scan request%s", ssid.empty() ? " (all SSIDs)" : (" for SSID: " + ssid).c_str()); + + if (wifiMgr->wifiScanRequest(ssid)) { + NMLOG_INFO("WiFi scan request sent successfully."); + } else { + NMLOG_ERROR("Failed to send WiFi scan request."); + } + break; + } + case 6: + { + std::string ssid, passphrase; + bool persist; + + std::cout << "Enter SSID to connect: "; + std::cin.ignore(); + std::getline(std::cin, ssid); + + std::cout << "Enter passphrase: "; + std::getline(std::cin, passphrase); + + WPEFramework::Exchange::INetworkManager::WIFISecurityMode securityType = getSecurityType(); + + std::cout << "Persist SSID info? (1 for yes, 0 for no): "; + std::cin >> persist; + + Exchange::INetworkManager::WiFiConnectTo ssidinfo = { + .ssid = ssid, + .passphrase = passphrase, + .security = securityType, + .persist = persist + }; + + if (wifiMgr->wifiConnect(ssidinfo)) { + NMLOG_INFO("Connected to WiFi successfully"); + } else { + NMLOG_ERROR("Failed to connect to WiFi"); + } + break; + } + case 7: { + if (wifiMgr->wifiDisconnect()) { + NMLOG_INFO("Disconnected from WiFi successfully"); + } else { + NMLOG_ERROR("Failed to disconnect from WiFi"); + } + break; + } + case 8: { + Exchange::INetworkManager::WiFiState state; + if (wifiMgr->getWifiState(state)) { + NMLOG_INFO("WiFi State: %d", state); // Assuming state is an enum or int + } else { + NMLOG_ERROR("Failed to get WiFi state"); + } + break; + } + case 9: { + if (wifiMgr->startWPS()) { + NMLOG_INFO("WPS started successfully"); + } else { + NMLOG_ERROR("Failed to start WPS"); + } + break; + } + case 10: { + if (wifiMgr->stopWPS()) { + NMLOG_INFO("WPS started successfully"); + } else { + NMLOG_ERROR("Failed to start WPS"); + } + break; + } + case 11: { + std::string interface; + std::string input; + bool enable; + std::cout << "Enter interface name to change the state: "; + std::cin.ignore(); + std::getline(std::cin, interface); + std::cout << "Enable Interface(input true/false): "; + std::getline(std::cin, input); + enable = (input == "true")? true: false; + + if(wifiMgr->setInterfaceState(interface, enable)){ + NMLOG_INFO("setInterfaceState successful"); + } + else + { + NMLOG_ERROR("Failed to set Interface State"); + } + break; + } + case 12: { + std::string interface; + std::string ipVersion; + std::string input; + bool autoConfig; + std::string ipAddress; + uint32_t prefix = 0; + std::string gateway; + std::string primarydns; + std::string secondarydns; + Exchange::INetworkManager::IPAddress address; + std::cout << "Enter interface: "; + std::cin.ignore(); + std::getline(std::cin, interface); + + std::cout << "Enter IP version: (IPv4/IPv6)"; + std::getline(std::cin, ipVersion); + + std::cout << "Enter auto configuration setting(input true/false): "; + std::getline(std::cin, input); + autoConfig = (input == "true")? true: false; + + if(!autoConfig) + { + std::cout << "Enter IP address: "; + std::getline(std::cin, ipAddress); + + // For prefix, use std::cin because it's a uint32_t + std::cout << "Enter prefix length: "; + std::cin >> prefix; + std::cin.ignore(std::numeric_limits::max(), '\n'); // Ignore leftover newline + + std::cout << "Enter gateway: "; + std::getline(std::cin, gateway); + + std::cout << "Enter primary DNS: "; + std::getline(std::cin, primarydns); + + std::cout << "Enter secondary DNS: "; + std::getline(std::cin, secondarydns); + } + address.ipversion = ipVersion; + address.autoconfig = autoConfig; + address.ipaddress = ipAddress; + address.prefix = prefix; + address.gateway = gateway; + address.primarydns = primarydns; + address.secondarydns = secondarydns; + if(wifiMgr->setIpSettings(interface, address)){ + NMLOG_INFO("setIPSettings successful"); + } + else + { + NMLOG_ERROR("Failed to set IP settings"); + } + break; + } + case 13: { + std::string interface; + std::cout << "Enter interface name to set to: "; + std::cin.ignore(); + std::getline(std::cin, interface); + if (wifiMgr->setPrimaryInterface(interface)) { + NMLOG_INFO("setPrimaryInterface successful"); + } else { + NMLOG_ERROR("Failed to setPrimaryInterface"); + } + break; + } + default: + std::cout << "Invalid choice. Please try again." << std::endl; + break; + } + } + NMLOG_INFO("cliTool completed successfully"); + nmEvent->stopNetworkMangerEventMonitor(); + return 0; +} From 93dfecc8993f87d67074cf24e1c72e5572329df4 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 24 Apr 2025 18:07:15 +0530 Subject: [PATCH 125/271] RDKEMW-3728: WIFI Connection Failure when the SSID security type is WPA2 - WPA3 Personal (#143) * RDKEMW-3728: WIFI Connection Failure when the SSID security type is WPA2 - WPA3 Personal * plugin cli build enabled in workflow --- .github/workflows/gnome_unit_test.yml | 2 ++ plugin/gnome/NetworkManagerGnomeUtils.cpp | 10 ++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index 05edeca5c..64ba786a7 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -73,6 +73,7 @@ jobs: -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" -DCMAKE_CXX_FLAGS=" -fprofile-arcs -ftest-coverage " -DENABLE_GNOME_NETWORKMANAGER=ON + -DENABLE_PLUGIN_CLI=ON && cmake --build build/GnomeLibnmNetworkmanager --target install -j8 @@ -87,6 +88,7 @@ jobs: -DCMAKE_CXX_FLAGS=" -fprofile-arcs -ftest-coverage " -DENABLE_GNOME_NETWORKMANAGER=ON -DENABLE_GNOME_GDBUS=ON + -DENABLE_PLUGIN_CLI=ON && cmake --build build/GnomeGdbusNetworkmanager --target install -j8 diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index 3bfd3ce69..a6b2bdb46 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -49,14 +49,16 @@ namespace WPEFramework else NMLOG_INFO("ap [%s] security str %s", ssid.c_str(), nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); - if ((flags != NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) + if ((flags != NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) // Open network security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE; - else if (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE) + else if((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) && (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE)) // WPA2/WPA3 Transition + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + else if (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE) // Pure WPA3 (SAE only): WPA3-Personal security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE; - else if (wpaFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X || rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + else if (wpaFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X || rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) // WPA2/WPA3 Enterprise: EAP present in either WPA or RSN security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP; else - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; // WPA2-PSK return security; } From 184f9b4219c39ed9508c236b496e8b5786d29a00 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Thu, 24 Apr 2025 11:31:28 -0400 Subject: [PATCH 126/271] Print the Incoming WIFIConnect request details (#144) - Print the Incoming WIFIConnect request details - org.rdk.wifi.connect() must be allowed to be called with empty param Signed-off-by: kamirt573_comcast --- legacy/LegacyWiFiManagerAPIs.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/legacy/LegacyWiFiManagerAPIs.cpp b/legacy/LegacyWiFiManagerAPIs.cpp index 6d9734196..9a583b67f 100644 --- a/legacy/LegacyWiFiManagerAPIs.cpp +++ b/legacy/LegacyWiFiManagerAPIs.cpp @@ -377,12 +377,17 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::WiFiConnectTo ssid{}; - NMLOG_INFO("Entry to %s\n", __FUNCTION__); + JsonObject inParam = parameters; + + if (inParam.HasLabel("passphrase")) + inParam["passphrase"] = "*******"; + + string jsonStr; + inParam.ToString(jsonStr); + NMLOG_INFO("params=%s", jsonStr.c_str() ); if (parameters.HasLabel("ssid")) ssid.ssid = parameters["ssid"].String(); - else - returnJson(rc); if (parameters.HasLabel("passphrase")) ssid.passphrase = parameters["passphrase"].String(); @@ -565,7 +570,14 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; Exchange::INetworkManager::WiFiConnectTo ssid{}; - NMLOG_INFO("Entry to %s\n", __FUNCTION__); + JsonObject inParam = parameters; + + if (inParam.HasLabel("passphrase")) + inParam["passphrase"] = "*******"; + + string jsonStr; + inParam.ToString(jsonStr); + NMLOG_INFO("params=%s", jsonStr.c_str() ); if (parameters.HasLabel("ssid") && parameters.HasLabel("passphrase")) { From a5b1f0769ea80ee7a345c8f3db1b1d4f8d16658d Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Thu, 24 Apr 2025 11:41:03 -0400 Subject: [PATCH 127/271] Release of v0.15.0 Release of v0.15.0 --- CHANGELOG.md | 8 ++++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d3807692..5d551eb2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,14 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.15.0] - 2025-04-24 +### Fixed +- Implemented a CLI tool to test the plugin independently +- Implemented Retry logic to register with IARM upon failure for RDK Backend +- Fixed the memory leak that was observed in Gnome backend when connecting to SSID +- Fixed the events published upon WPS successful connects and failures. +- Fixed the WiFiConnect call with empty param from the legacy plugin + ## [0.14.0] - 2025-04-18 ### Added - Process Monitoring for the out-of-process plugin added diff --git a/CMakeLists.txt b/CMakeLists.txt index c650d6a57..7e8364bbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 14) +set(VERSION_MINOR 15) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index e7a8d8933..1344cc837 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.14.0" + "version": "0.15.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 76fe5ccf0..cab21893c 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.14.0** +**Version: 0.15.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.14.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.15.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 9d9ad60d29c580e637cbc94bab47b7051e85edfc Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Mon, 28 Apr 2025 08:37:08 -0400 Subject: [PATCH 128/271] DELIA-67975 : Handle the response for PING request (#145) Reason for change: Handle the response for PING request Test Procedure: verify jsonrpc response for ping request Risks: Low Signed-off-by: kamirt573_comcast --- legacy/LegacyNetworkAPIs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/legacy/LegacyNetworkAPIs.cpp b/legacy/LegacyNetworkAPIs.cpp index ff9b37f65..2da5345e6 100644 --- a/legacy/LegacyNetworkAPIs.cpp +++ b/legacy/LegacyNetworkAPIs.cpp @@ -676,7 +676,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { response = reply; response["target"] = endpoint; } - returnJson(rc); + return rc; } uint32_t Network::doTrace(const JsonObject& parameters, JsonObject& response) @@ -711,7 +711,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { response["target"] = endpoint; } } - returnJson(rc); + return rc; } uint32_t Network::getPublicIP(const JsonObject& parameters, JsonObject& response) From 46100039bc7d92a05cc53dd6cdb56c0da7382668 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Wed, 30 Apr 2025 07:19:14 +0530 Subject: [PATCH 129/271] RDKEMW-3715 : Failed to connect with WPS when network switch between WPS To WPS (#146) * RDKEMW-3715 Failed to connect with WPS when network switch between WPS to WPS Signed-off-by: rafi --- plugin/NetworkManagerSecretAgent.cpp | 8 ++-- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 58 +++++++++--------------- 2 files changed, 25 insertions(+), 41 deletions(-) diff --git a/plugin/NetworkManagerSecretAgent.cpp b/plugin/NetworkManagerSecretAgent.cpp index e8ab57ed5..dad4a1c20 100644 --- a/plugin/NetworkManagerSecretAgent.cpp +++ b/plugin/NetworkManagerSecretAgent.cpp @@ -99,13 +99,14 @@ namespace WPEFramework flags = g_variant_get_uint32(flagVar); if(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE) flagStr += ", wps_pbc_active"; - if(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION) + if(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION) { flagStr += ", allow_interaction"; - if(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED) { - flagStr += ", user_requested"; /* wait for 10 sec mean time in the background networkmanager will do wps operation */ SecretAgent::wait(10); // 10 sec } + if(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED) + flagStr += ", user_requested"; + NMLOG_INFO("SecretAgent GetSecrets Flags = %u %s", flags, flagStr.c_str()); } @@ -123,7 +124,6 @@ namespace WPEFramework else if (g_strcmp0(method_name, "CancelGetSecrets") == 0) { NMLOG_DEBUG("CancelGetSecrets method called"); - SecretAgent::stopWait(); g_dbus_method_invocation_return_value(invocation, NULL); } else if (g_strcmp0(method_name, "SaveSecrets") == 0) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 602b9425f..bda276cd6 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -761,8 +761,10 @@ namespace WPEFramework GError *error = NULL; NMLOG_WARNING(" '%s' connection existing but properties mismatch; deleting...", ssidInfo.ssid.c_str()); nm_remote_connection_delete (NM_REMOTE_CONNECTION(connection), NULL, &error); - if (error) + if (error) { NMLOG_ERROR("deleting connection failed %s", error->message); + g_error_free(error); + } else connection = NULL; } @@ -1196,6 +1198,7 @@ namespace WPEFramework GMainContext *wpsContext = NULL; const char *wpsApPath = NULL; GMainLoop *loop = NULL; + NMClient* client = NULL; Exchange::INetworkManager::WiFiConnectTo wifiConnectInfo{}; Exchange::INetworkManager::WiFiSSIDInfo wpsApInfo{}; @@ -1229,7 +1232,7 @@ namespace WPEFramework g_main_context_push_thread_default(wpsContext); - NMClient* client = nm_client_new(NULL, &error); + client = nm_client_new(NULL, &error); if (!client) { if(error != NULL) { @@ -1238,9 +1241,6 @@ namespace WPEFramework } else NMLOG_ERROR("NetworkManager cleint create failed"); - - g_main_context_pop_thread_default(wpsContext); - g_main_context_unref(wpsContext); break; } @@ -1248,12 +1248,6 @@ namespace WPEFramework if(wifidevice == NULL) { NMLOG_ERROR("Failed to get device list."); - g_main_context_pop_thread_default(wpsContext); - g_main_context_unref(wpsContext); - if(client != NULL) { - g_object_unref(client); - client = NULL; - } break; } @@ -1293,12 +1287,6 @@ namespace WPEFramework if(ApList == NULL) { NMLOG_ERROR("Aplist Error !"); - g_main_context_pop_thread_default(wpsContext); - g_main_context_unref(wpsContext); - if(client != NULL) { - g_object_unref(client); - client = NULL; - } break; } @@ -1327,8 +1315,10 @@ namespace WPEFramework NMLOG_INFO("stopping the ongoing Wi-Fi connection"); // some other ssid connected or connecting; wps need a disconnected wifi state nm_device_disconnect(wifidevice, NULL, &error); - if (error) + if (error) { NMLOG_ERROR("disconnect connection failed %s", error->message); + g_error_free(error); + } sleep(3); // wait for 3 sec to complete disconnect process } } @@ -1336,12 +1326,6 @@ namespace WPEFramework if(wpsComplete) { - g_main_context_pop_thread_default(wpsContext); - g_main_context_unref(wpsContext); - if(client != NULL) { - g_object_unref(client); - client = NULL; - } break; } @@ -1355,25 +1339,13 @@ namespace WPEFramework if(!connectionBuilder(wifiConnectInfo, connection, true)) { NMLOG_ERROR("wps connection builder failed"); - g_main_context_pop_thread_default(wpsContext); - g_main_context_unref(wpsContext); - if(client != NULL) { - g_object_unref(client); - client = NULL; - } - return; + break; } loop = g_main_loop_new(wpsContext, FALSE); if(loop == NULL) { NMLOG_ERROR("g_main_loop_new failed"); - g_main_context_pop_thread_default(wpsContext); - g_main_context_unref(wpsContext); - if(client != NULL) { - g_object_unref(client); - client = NULL; - } break; } @@ -1411,6 +1383,7 @@ namespace WPEFramework g_main_context_pop_thread_default(wpsContext); g_main_context_unref(wpsContext); + wpsContext = NULL; if(client != NULL) { g_object_unref(client); client = NULL; @@ -1433,6 +1406,17 @@ namespace WPEFramework _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED); } + if(wpsContext != NULL) + { + g_main_context_pop_thread_default(wpsContext); + g_main_context_unref(wpsContext); + } + + if(client != NULL) { + g_object_unref(client); + client = NULL; + } + // wps success ! wifi connect event will be send by wifi event monitor m_secretAgent.UnregisterAgent(); NMLOG_INFO("WPS process thread exist"); From 410b5d5411f7e6deb2fde0a5d3e9f0bcb12d8408 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Thu, 1 May 2025 22:09:39 -0400 Subject: [PATCH 130/271] Release of v0.16.0 Release of v0.16.0 --- CHANGELOG.md | 10 ++++++++-- CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d551eb2c..a282fe180 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.16.0] - 2025-05-01 +### Fixed +- Fixed the deregistration of Security Agent upon one successful WPS Connect. +- JSONRPC response for Ping in the legacy plugin is addressed + ## [0.15.0] - 2025-04-24 ### Fixed - Implemented a CLI tool to test the plugin independently @@ -43,7 +48,7 @@ All notable changes to this RDK Service will be documented in this file. - The file and folder structure of NetworkManager repo is re-organized - Implemented a separate library for out-of-process plugin - Implemented GDbus based APIs for all the NetworkManager APIs -- Implmented a Router Discovery tool +- Implemented a Router Discovery tool - Changed the approach to identify Open SSIDs - Added INFO logging for the discovered SSIDs and the security methods discovered. - Fixed Invalid Timeout in Connectivity Monitoring @@ -71,7 +76,7 @@ All notable changes to this RDK Service will be documented in this file. ### Added - Enhanced Internet Connectivity Monitoring - Redefined the security modes -- Removed explict API to start/stop connectivity monitoring +- Removed explicit API to start/stop connectivity monitoring - Added retriveSSID method for migration ready - Implemented initial code for gdbus based methods to communicate with NetworkManager - Fixed Coverity Issues @@ -154,3 +159,4 @@ All notable changes to this RDK Service will be documented in this file. ## [0.1.0] - 2024-03-28 ### Added - Added NetworkManager plugin. A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device. + diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e8364bbb..a24b6e292 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 15) +set(VERSION_MINOR 16) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 1344cc837..4bea9596c 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.15.0" + "version": "0.16.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index cab21893c..e904e3c2f 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.15.0** +**Version: 0.16.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.15.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.16.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From d62d880ad0f101cf58b80cf16ac7f8cb898e1a1f Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 1 May 2025 22:58:57 -0400 Subject: [PATCH 131/271] RDKEMW-3086 - Memory leak is observed with Network Manager plugin (#147) Reason for change: The Scanned SSIDs are associated with nmclient instance and that is not released fully is what causing the process to increase RSS memory. Test Procedure: Verify with Ethernet or WiFi Connected and check the process RSS Risks: Medium --- plugin/gnome/NetworkManagerGnomeEvents.cpp | 1 - plugin/gnome/NetworkManagerGnomeProxy.cpp | 1 - plugin/gnome/NetworkManagerGnomeWIFI.cpp | 97 ++++++++++++++++++++-- plugin/gnome/NetworkManagerGnomeWIFI.h | 10 ++- 4 files changed, 98 insertions(+), 11 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 413a0aadd..298ac8cb1 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include "Module.h" #include "NetworkManagerGnomeEvents.h" #include "NetworkManagerLogger.h" diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 76e7eff3f..489a68484 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -20,7 +20,6 @@ #include "NetworkManagerGnomeWIFI.h" #include "NetworkManagerGnomeEvents.h" #include "NetworkManagerGnomeUtils.h" -#include #include #include diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index bda276cd6..b0ed759f3 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -49,11 +49,6 @@ namespace WPEFramework bool wifiManager::createClientNewConnection() { GError *error = NULL; - if(m_client != nullptr) - { - g_object_unref(m_client); - m_client = nullptr; - } m_client = nm_client_new(NULL, &error); if (!m_client || !m_loop) { @@ -64,6 +59,22 @@ namespace WPEFramework return true; } + void wifiManager::deleteClientConnection() + { + if(m_client != NULL) { + GMainContext *context = g_main_context_ref(nm_client_get_main_context(m_client)); + GObject *contextBusyWatcher = nm_client_get_context_busy_watcher(m_client); + g_object_add_weak_pointer(contextBusyWatcher,(gpointer *) &contextBusyWatcher); + g_clear_object(&m_client); + while (contextBusyWatcher) + { + g_main_context_iteration(context, TRUE); + } + g_main_context_unref(context); + m_client = NULL; + } + } + bool wifiManager::quit(NMDevice *wifiNMDevice) { if(!g_main_loop_is_running(m_loop)) { @@ -150,7 +161,6 @@ namespace WPEFramework default: break; } - return wifiDevice; } @@ -258,6 +268,7 @@ namespace WPEFramework NMDevice *wifiDevice = getWifiDevice(); if(wifiDevice == NULL) { NMLOG_FATAL("NMDeviceWifi * NULL !"); + deleteClientConnection(); return false; } NMDeviceState deviceState = nm_device_get_state(wifiDevice); @@ -287,6 +298,7 @@ namespace WPEFramework } NMLOG_INFO("wifi state (%d) mapped state (%d) ", (int)deviceState, (int)state); + deleteClientConnection(); return true; } @@ -298,6 +310,7 @@ namespace WPEFramework NMDevice* wifiDevice = getWifiDevice(); if(wifiDevice == NULL) { NMLOG_FATAL("NMDeviceWifi * NULL !"); + deleteClientConnection(); return false; } @@ -307,15 +320,18 @@ namespace WPEFramework NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(NM_DEVICE_WIFI(wifiDevice)); if(activeAP == NULL) { NMLOG_ERROR("NMAccessPoint = NULL !"); + deleteClientConnection(); return false; } NMLOG_DEBUG("active access point found !"); getApInfo(activeAP, ssidinfo, false); + deleteClientConnection(); return true; } else NMLOG_WARNING("no active access point!; wifi device state: (%d)", deviceState); + deleteClientConnection(); return true; } @@ -351,6 +367,7 @@ namespace WPEFramework NMDevice *wifiNMDevice = getWifiDevice(); if(wifiNMDevice == NULL) { NMLOG_WARNING("wifi state is unmanaged !"); + deleteClientConnection(); return true; } @@ -359,11 +376,13 @@ namespace WPEFramework if (deviceState <= NM_DEVICE_STATE_DISCONNECTED || deviceState == NM_DEVICE_STATE_FAILED || deviceState == NM_DEVICE_STATE_DEACTIVATING) { NMLOG_WARNING("wifi already disconnected !"); + deleteClientConnection(); return true; } nm_device_disconnect_async(wifiNMDevice, NULL, disconnectCb, this); wait(m_loop); + deleteClientConnection(); return m_isSuccess; } @@ -616,6 +635,7 @@ namespace WPEFramework NMDevice *m_wifidevice = getWifiDevice(); if(m_wifidevice == NULL) { NMLOG_WARNING("wifi state is unmanaged !"); + deleteClientConnection(); return false; } @@ -624,6 +644,7 @@ namespace WPEFramework if(knownssid.empty()) { NMLOG_WARNING("ssid not specified !"); + deleteClientConnection(); return false; } @@ -631,6 +652,7 @@ namespace WPEFramework if(wifiConnections == NULL) { NMLOG_WARNING("No wifi connection found !"); + deleteClientConnection(); return false; } @@ -648,6 +670,7 @@ namespace WPEFramework if (m_connection == NULL) { NMLOG_ERROR("m_connection == NULL smothing went worng"); + deleteClientConnection(); return false; } break; @@ -667,6 +690,7 @@ namespace WPEFramework NMLOG_ERROR("'%s' connection not found !", knownssid.c_str()); } + deleteClientConnection(); return m_isSuccess; } @@ -688,7 +712,10 @@ namespace WPEFramework m_wifidevice = getWifiDevice(); if(m_wifidevice == NULL) + { + deleteClientConnection(); return false; + } if(getConnectedSSID(m_wifidevice, activeSSID)) { @@ -696,6 +723,7 @@ namespace WPEFramework { NMLOG_INFO("'%s' already connected !", activeSSID.c_str()); _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + deleteClientConnection(); return true; } else @@ -706,6 +734,7 @@ namespace WPEFramework if(ApList == NULL) { NMLOG_ERROR("Aplist Error !"); + deleteClientConnection(); return false; } @@ -718,8 +747,10 @@ namespace WPEFramework if(addToKnownSSIDs(ssidInfo)) { NMLOG_DEBUG("Adding to known ssid '%s' ", ssidInfo.ssid.c_str()); + deleteClientConnection(); return activateKnownWifiConnection(ssidInfo.ssid); } + deleteClientConnection(); return false; } @@ -746,6 +777,7 @@ namespace WPEFramework if (m_connection == NULL) { NMLOG_ERROR("m_connection == NULL smothing went worng"); + deleteClientConnection(); return false; } break; @@ -777,6 +809,7 @@ namespace WPEFramework { if(!connectionBuilder(ssidInfo, m_connection)) { NMLOG_ERROR("connection builder failed"); + deleteClientConnection(); return false; } GVariant *connSettings = nm_connection_to_dbus(m_connection, NM_CONNECTION_SERIALIZE_ALL); @@ -798,6 +831,7 @@ namespace WPEFramework NMLOG_ERROR("connection builder failed"); if(m_connection) g_object_unref(m_connection); + deleteClientConnection(); return false; } m_createNewConnection = true; @@ -807,6 +841,7 @@ namespace WPEFramework } wait(m_loop); + deleteClientConnection(); return m_isSuccess; } @@ -869,12 +904,16 @@ namespace WPEFramework NMDevice *device = getWifiDevice(); if(device == NULL) + { + deleteClientConnection(); return false; + } const GPtrArray *availableConnections = nm_device_get_available_connections(device); if(availableConnections == NULL) { NMLOG_ERROR("No available connections found !"); + deleteClientConnection(); return false; } @@ -893,6 +932,7 @@ namespace WPEFramework if(!connectionBuilder(ssidinfo, m_connection)) { NMLOG_ERROR("connection builder failed"); + deleteClientConnection(); return false; } NMLOG_DEBUG("update exsisting connection '%s' ", ssidinfo.ssid.c_str()); @@ -912,6 +952,7 @@ namespace WPEFramework if(!connectionBuilder(ssidinfo, m_connection)) { NMLOG_ERROR("connection builder failed"); + deleteClientConnection(); return false; } m_createNewConnection = true; @@ -923,6 +964,7 @@ namespace WPEFramework addToKnownSSIDsCb, this); } wait(m_loop); + deleteClientConnection(); return m_isSuccess; } @@ -943,6 +985,7 @@ namespace WPEFramework if(allconnections == NULL) { NMLOG_ERROR("nm connections list null "); + deleteClientConnection(); return false; } for (guint i = 0; i < allconnections->len; i++) @@ -987,6 +1030,7 @@ namespace WPEFramework NMLOG_WARNING("No wifi connection profiles found !!"); } + deleteClientConnection(); return true; } @@ -1001,6 +1045,7 @@ namespace WPEFramework if(connections == nullptr) { NMLOG_ERROR("nm connections list null "); + deleteClientConnection(); return false; } for (guint i = 0; i < connections->len; i++) @@ -1035,9 +1080,11 @@ namespace WPEFramework if (!ssids.empty()) { NMLOG_INFO("known wifi connections are %s", ssidPrint.c_str()); + deleteClientConnection(); return true; } + deleteClientConnection(); return false; } @@ -1069,6 +1116,7 @@ namespace WPEFramework NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getWifiDevice()); if(wifiDevice == NULL) { NMLOG_FATAL("NMDeviceWifi * NULL !"); + deleteClientConnection(); return false; } m_isSuccess = false; @@ -1085,11 +1133,13 @@ namespace WPEFramework g_variant_builder_add(&builder, "{sv}", "ssids", g_variant_builder_end(&array_builder)); options = g_variant_builder_end(&builder); nm_device_wifi_request_scan_options_async(wifiDevice, options, NULL, wifiScanCb, this); + g_variant_unref(options); // Unreference the GVariant after passing it to the async function } else { nm_device_wifi_request_scan_async(wifiDevice, NULL, wifiScanCb, this); } wait(m_loop); + deleteClientConnection(); return m_isSuccess; } @@ -1101,20 +1151,24 @@ namespace WPEFramework NMDeviceWifi *wifiDevice = NM_DEVICE_WIFI(getWifiDevice()); if (wifiDevice == NULL) { NMLOG_ERROR("Invalid Wi-Fi device."); + deleteClientConnection(); return false; } gint64 last_scan_time = nm_device_wifi_get_last_scan(wifiDevice); if (last_scan_time <= 0) { NMLOG_INFO("No scan has been performed yet"); + deleteClientConnection(); return false; } gint64 current_time_in_msec = nm_utils_get_timestamp_msec(); gint64 time_difference_in_seconds = (current_time_in_msec - last_scan_time) / 1000; if (time_difference_in_seconds <= timelimitInSec) { + deleteClientConnection(); return true; } + deleteClientConnection(); return false; } @@ -1483,6 +1537,7 @@ namespace WPEFramework GPtrArray *devices = const_cast(nm_client_get_devices(m_client)); if (devices == nullptr) { NMLOG_ERROR("Failed to get device list."); + deleteClientConnection(); return m_isSuccess; } @@ -1500,18 +1555,27 @@ namespace WPEFramework } if (device == nullptr) + { + deleteClientConnection(); return false; + } NMDeviceState deviceState = nm_device_get_state(device); if (enabled) { NMLOG_DEBUG("Enabling interface..."); if (deviceState >= NM_DEVICE_STATE_DISCONNECTED) // already enabled + { + deleteClientConnection(); return true; + } } else { NMLOG_DEBUG("Disabling interface..."); if (deviceState <= NM_DEVICE_STATE_UNMANAGED) // already disabled + { + deleteClientConnection(); return true; + } else if (deviceState > NM_DEVICE_STATE_DISCONNECTED) { nm_device_disconnect_async(device, nullptr, disconnectCb, this); @@ -1526,6 +1590,7 @@ namespace WPEFramework nm_client_dbus_set_property( m_client, objectPath, NM_DBUS_INTERFACE_DEVICE,"Managed", value, -1, nullptr, deviceManagedCb, this); wait(m_loop); + deleteClientConnection(); return m_isSuccess; } @@ -1584,18 +1649,25 @@ namespace WPEFramework device = nm_client_get_device_by_iface(m_client, interface.c_str()); if(device == NULL) + { + deleteClientConnection(); return false; + } if(interface == nmUtils::ethIface()) { NMSettingConnection *settings = NULL; if(device == NULL) + { + deleteClientConnection(); return false; + } const GPtrArray *connections = nm_device_get_available_connections(device); if (connections == NULL || connections->len == 0) { NMLOG_WARNING("no connections availble to edit "); + deleteClientConnection(); return true; } @@ -1614,6 +1686,7 @@ namespace WPEFramework remoteConn = NM_REMOTE_CONNECTION(connection); } else { NMLOG_ERROR("The connection is not a remote connection."); + deleteClientConnection(); return false; /* connection and remoteconnection should match */ } @@ -1629,11 +1702,13 @@ namespace WPEFramework if(activeConnection == NULL) { NMLOG_WARNING("no active connection for wifi"); + deleteClientConnection(); return false; } remoteConn = nm_active_connection_get_connection(activeConnection); if(remoteConn == NULL) { NMLOG_WARNING("no remote connection for wifi"); + deleteClientConnection(); return false; } connection = NM_CONNECTION(remoteConn); @@ -1642,6 +1717,7 @@ namespace WPEFramework if(connection == nullptr) { NMLOG_WARNING("not a single connection availble for %s", interface.c_str()); + deleteClientConnection(); return true; } @@ -1654,6 +1730,7 @@ namespace WPEFramework if(checkAutoConnectEnabledInIPv4Conn(connection)) // already auto connect true connection { NMLOG_INFO("Setting IPv4 auto connect enabled"); + deleteClientConnection(); return true; // no need to modify } sIp4 = (NMSettingIP4Config *)nm_setting_ip4_config_new(); @@ -1708,6 +1785,7 @@ namespace WPEFramework } else { NMLOG_ERROR("Failed to commit changes to the remote connection (unknown error)."); } + deleteClientConnection(); return false; } @@ -1718,12 +1796,14 @@ namespace WPEFramework if (!nm_client_deactivate_connection(m_client, activeConnection, NULL, &deactivate_error)) { NMLOG_ERROR("Failed to deactivate connection: %s", deactivate_error->message); g_clear_error(&deactivate_error); + deleteClientConnection(); return false; } } nm_client_activate_connection_async(m_client, connection, device, specObject, NULL, onActivateComplete, this); wait(m_loop); + deleteClientConnection(); return m_isSuccess; } @@ -1737,6 +1817,7 @@ namespace WPEFramework if (!createClientNewConnection()) return false; if(interface.empty() || (wifiname != interface && ethname != interface)) { NMLOG_FATAL("interface is not valied %s", interface.c_str()!=nullptr? interface.c_str():"empty"); + deleteClientConnection(); return false; } otherInterface = (interface == wifiname)?ethname:wifiname; @@ -1744,6 +1825,7 @@ namespace WPEFramework const GPtrArray* activeConnections = nm_client_get_active_connections(m_client); if (!activeConnections) { NMLOG_ERROR("Failed to retrieve active connections"); + deleteClientConnection(); return false; } for (guint i = 0; i < activeConnections->len; i++) @@ -1781,6 +1863,7 @@ namespace WPEFramework } else { NMLOG_ERROR("Failed to commit changes to the remote connection (unknown error)."); } + deleteClientConnection(); return false; } if (activeConnection != NULL) @@ -1792,6 +1875,7 @@ namespace WPEFramework { NMLOG_ERROR("Failed to deactivate connection: %s", deactivate_error->message); g_clear_error(&deactivate_error); + deleteClientConnection(); return false; } } @@ -1800,6 +1884,7 @@ namespace WPEFramework } } wait(m_loop); + deleteClientConnection(); return rc; } } // namespace Plugin diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 0e95dfef0..cdaad248e 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -72,10 +72,13 @@ namespace WPEFramework wifiManager(); ~wifiManager() { NMLOG_INFO("~wifiManager"); - g_main_context_pop_thread_default(m_nmContext); + if (m_nmContext) { + g_main_context_pop_thread_default(m_nmContext); + g_main_context_unref(m_nmContext); + m_nmContext = NULL; + } if(m_client != NULL) { - g_object_unref(m_client); - m_client = NULL; + deleteClientConnection(); } if(m_loop != NULL) { g_main_loop_unref(m_loop); @@ -88,6 +91,7 @@ namespace WPEFramework void operator=(wifiManager const&) = delete; bool createClientNewConnection(); + void deleteClientConnection(); public: NMClient *m_client; From c6ec56a8ea32794f4f7b4bca87a6de0c66672703 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 2 May 2025 16:37:59 -0400 Subject: [PATCH 132/271] Release of v0.17.0 Release of v0.17.0 --- CHANGELOG.md | 4 ++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a282fe180..41498a3c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.17.0] - 2025-05-02 +### Fixed +- Fixed the memory leak in Gnome-libnm port of the plugin. + ## [0.16.0] - 2025-05-01 ### Fixed - Fixed the deregistration of Security Agent upon one successful WPS Connect. diff --git a/CMakeLists.txt b/CMakeLists.txt index a24b6e292..d7da03d95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 16) +set(VERSION_MINOR 17) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 4bea9596c..192732d3e 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.16.0" + "version": "0.17.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index e904e3c2f..5c1ef22d3 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.16.0** +**Version: 0.17.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.16.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.17.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 6e9ed7f992d63d77fcad940ec329d21ce871fef4 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 9 May 2025 20:20:54 +0530 Subject: [PATCH 133/271] RDKEMW-4215 [Network] onDefaultInterfaceChange Event is posted empty (#149) Reason for change: fix for onDefaultInterfaceChange event is posted empty Test Procedure: Verify interface state change events Priority:P1 --- plugin/rdk/NetworkManagerRDKProxy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 7693f404c..41b9882f2 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -541,9 +541,9 @@ namespace WPEFramework oldInterface = e->oldInterface; newInterface = e->newInterface; NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_DEFAULT_INTERFACE %s :: %s..", oldInterface.c_str(), newInterface.c_str()); - if(oldInterface != "eth0" || oldInterface != "wlan0") + if(oldInterface != "eth0" && oldInterface != "wlan0") oldInterface = ""; /* assigning "null" if the interface is not eth0 or wlan0 */ - if(newInterface != "eth0" || newInterface != "wlan0") + if(newInterface != "eth0" && newInterface != "wlan0") newInterface = ""; /* assigning "null" if the interface is not eth0 or wlan0 */ ::_instance->ReportActiveInterfaceChange(oldInterface, newInterface); From 74aba9edd4822b75b828cb401bc596a0f845aff2 Mon Sep 17 00:00:00 2001 From: kamirt573_comcast Date: Wed, 14 May 2025 20:05:56 +0000 Subject: [PATCH 134/271] RDKEMW-4375 : The interval between the ECHO requests is reduced (#155) Signed-off-by: kamirt573_comcast RDKEMW-4375 : The interval between the ECHO requests is reduced Reason for change: The interval between the ECHO requests is reduced Test Procedure: run curl command with `time` in the front to check pre and post. Also verify the deepsleep to wake up time Risks: Medium Signed-off-by: kamirt573_comcast --- legacy/LegacyNetworkAPIs.cpp | 4 +++- plugin/NetworkManagerImplementation.cpp | 4 ++-- plugin/NetworkManagerJsonRpc.cpp | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/legacy/LegacyNetworkAPIs.cpp b/legacy/LegacyNetworkAPIs.cpp index 2da5345e6..6cb2725b0 100644 --- a/legacy/LegacyNetworkAPIs.cpp +++ b/legacy/LegacyNetworkAPIs.cpp @@ -646,7 +646,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { string guid{}; string ipversion{"IPv4"}; uint32_t noOfRequest = 3; - uint16_t timeOutInSeconds = 5; + uint16_t timeOutInSeconds = 3; endpoint = parameters["endpoint"].String(); @@ -676,6 +676,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { response = reply; response["target"] = endpoint; } + LOG_OUTPARAM(); return rc; } @@ -711,6 +712,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { response["target"] = endpoint; } } + LOG_OUTPARAM(); return rc; } diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 342a9b249..2921fbfa4 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -367,11 +367,11 @@ namespace WPEFramework string tempResult = ""; if(0 == strcasecmp("IPv6", ipversion.c_str())) { - snprintf(cmd, sizeof(cmd), "ping6 -c %d -W %d '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); + snprintf(cmd, sizeof(cmd), "ping6 -c %d -W %d -i 0.2 '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); } else { - snprintf(cmd, sizeof(cmd), "ping -c %d -W %d '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); + snprintf(cmd, sizeof(cmd), "ping -c %d -W %d -i 0.2 '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); } NMLOG_DEBUG ("The Command is %s", cmd); diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index 801aa41db..aed59cc7c 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -565,13 +565,12 @@ namespace WPEFramework string result{}; string endpoint{}; uint32_t rc = Core::ERROR_GENERAL; - LOG_INPARAM(); if (parameters.HasLabel("endpoint")) { string guid{}; string ipversion{"IPv4"}; uint32_t noOfRequest = 3; - uint16_t timeOutInSeconds = 5; + uint16_t timeOutInSeconds = 3; endpoint = parameters["endpoint"].String(); @@ -599,6 +598,7 @@ namespace WPEFramework reply.FromString(result); response = reply; } + LOG_OUTPARAM(); return rc; } From f7344c0481df8e9e083f1653893274a932ab51a3 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Wed, 21 May 2025 15:35:45 -0400 Subject: [PATCH 135/271] Release of v0.18.0 Release of v0.18.0 --- CHANGELOG.md | 5 +++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41498a3c5..ba92637d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.18.0] - 2025-05-21 +### Fixed +- Fixed onActiveInterfaceChange event data. +- Implemented an improvement to the Ping method to have lesser interval between echo requests + ## [0.17.0] - 2025-05-02 ### Fixed - Fixed the memory leak in Gnome-libnm port of the plugin. diff --git a/CMakeLists.txt b/CMakeLists.txt index d7da03d95..15261a477 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 17) +set(VERSION_MINOR 18) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 192732d3e..aee056fd8 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.17.0" + "version": "0.18.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 5c1ef22d3..2544c93e0 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.17.0** +**Version: 0.18.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.17.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.18.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 85f26a66143f05f6b9899b0e0ea27be3acdabfc0 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 23 May 2025 01:18:24 +0530 Subject: [PATCH 136/271] RDKEMW-4175 : WiFi Power Switch toggling On/Off support (#154) Reason for change: for following issues - RDKEMW-3859 SetInterfaceState is not working as expected for the wlan0 interface. - RDKEMW-4063 [RDKE][Gnome]WiFi is connected on bootup even if WiFi option was disabled before reboot - RDKEMW-4106 [RDKEMW][FOXTEL]Device does not automatically reconnect to WiFi SSID after toggling WiFi OFF and ON - RDKEMW-4175 WiFi doesn't connect back automatically to previously connected SSID after toggling WiFi On/Off Switch Test Procedure: Verify wifi disable option in RDKE device --- plugin/CMakeLists.txt | 7 ++ plugin/gnome/NetworkManagerGnomeEvents.cpp | 8 ++ plugin/gnome/NetworkManagerGnomeProxy.cpp | 19 ++- plugin/gnome/NetworkManagerGnomeUtils.cpp | 41 ++++++ plugin/gnome/NetworkManagerGnomeUtils.h | 4 + plugin/gnome/NetworkManagerGnomeWIFI.cpp | 117 +++++++++++++----- plugin/gnome/NetworkManagerGnomeWIFI.h | 2 +- plugin/gnome/scripts/nm_interface_handler.sh | 63 ++++++++++ .../gnome-networkmanager-migration.conf | 2 + 9 files changed, 227 insertions(+), 36 deletions(-) create mode 100644 plugin/gnome/scripts/nm_interface_handler.sh create mode 100644 plugin/gnome/systemd/gnome-networkmanager-migration.conf diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index aad6155ec..7aec66ec6 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -133,5 +133,12 @@ endif (USE_RDK_LOGGER) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) install(TARGETS ${MODULE_IMPL_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) +if(ENABLE_GNOME_NETWORKMANAGER) +install(PROGRAMS gnome/scripts/nm_interface_handler.sh + DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/rdk) +install(FILES gnome/systemd/gnome-networkmanager-migration.conf + DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/systemd/system/wpeframework-networkmanager.service.d) +endif(ENABLE_GNOME_NETWORKMANAGER) + #Generate Plugin configuration file write_config() diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 298ac8cb1..078a21189 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -432,6 +432,14 @@ namespace WPEFramework std::string ifname = nm_device_get_iface(device); if((ifname == nmUtils::ethIface()) || (ifname == nmUtils::wlanIface())) { + NMDeviceState devState = nm_device_get_state(device); + // NM_DEVICE_STATE_UNAVAILABLE can occur for an Ethernet interface when it is disconnected (e.g., no cable connected). + bool isDeviceEnabled = devState >= NM_DEVICE_STATE_UNAVAILABLE && devState <= NM_DEVICE_STATE_ACTIVATED; + if(!isDeviceEnabled) + { + NMLOG_WARNING("device %s is not enabled, So no event monitor", ifname.c_str()); + continue; + } deviceStateChangeCb(device, nullptr, nullptr); //posting event if interface already connected g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(deviceStateChangeCb), nmEvents); NMIPConfig *ipv4Config = nm_device_get_ip4_config(device); diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 489a68484..31248e9fe 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -96,7 +96,6 @@ namespace WPEFramework nmEvent = GnomeNetworkManagerEvents::getInstance(); nmEvent->startNetworkMangerEventMonitor(); wifi = wifiManager::getInstance(); - return; } uint32_t NetworkManagerImplementation::GetAvailableInterfaces (Exchange::INetworkManager::IInterfaceDetailsIterator*& interfacesItr/* @out */) @@ -254,6 +253,22 @@ namespace WPEFramework } NMLOG_INFO("interface %s state: %s", interface.c_str(), enabled ? "enabled" : "disabled"); + if(enabled) + { + sleep(1); // wait for 1 sec to change the device state + if(interface == nmUtils::wlanIface() && _instance != NULL) + { + NMLOG_INFO("Activating connection '%s' ...", _instance->m_lastConnectedSSID.c_str()); + wifi->activateKnownConnection(nmUtils::wlanIface(), _instance->m_lastConnectedSSID); + } + else if(interface == nmUtils::ethIface()) + { + NMLOG_INFO("Activating connection 'Wired connection 1' ..."); + // default wired connection name is 'Wired connection 1' + wifi->activateKnownConnection(nmUtils::ethIface(), "Wired connection 1"); + } + } + return Core::ERROR_NONE; } @@ -644,7 +659,7 @@ namespace WPEFramework if(ssid.ssid.empty() && _instance != NULL) { NMLOG_WARNING("ssid is empty activating last connectd ssid !"); - if(wifi->activateKnownWifiConnection(_instance->m_lastConnectedSSID)) + if(wifi->activateKnownConnection(nmUtils::wlanIface(), _instance->m_lastConnectedSSID)) rc = Core::ERROR_NONE; } else if(ssid.ssid.size() < 32) diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index a6b2bdb46..51aca0a2a 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -281,5 +281,46 @@ namespace WPEFramework return exitCode == 0; } + + void nmUtils::setMarkerFile(const char* filename, bool unmark) + { + char fqn[64]; + snprintf(fqn, sizeof(fqn), "%s", filename); + if (unmark) + { + if (remove(fqn) != 0) { + NMLOG_ERROR("Failed to remove marker file"); + } + } + else + { + FILE *fp = fopen(fqn, "w"); + if (fp != NULL) { + fclose(fp); + } else { + NMLOG_ERROR("Failed to open marker file %s", fqn); + } + } + } + + bool nmUtils::isInterfaceEnabled(const std::string& interface) + { + std::string markerFile; + if (interface == nmUtils::ethIface()) { + markerFile = EthernetDisableMarker; + } + else if (interface == nmUtils::wlanIface()) { + markerFile = WiFiDisableMarker; + } + else { + NMLOG_ERROR("Invalid interface name: %s", interface.c_str()); + return false; + } + + bool isAllowed = (access(markerFile.c_str(), F_OK) != 0); + NMLOG_DEBUG("isInterfaceEnabled %s: %s", interface.c_str(), isAllowed ? "true" : "false"); + return isAllowed; + } + } // Plugin } // WPEFramework diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index ec12d3cb1..35688d461 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -29,6 +29,8 @@ namespace WPEFramework { namespace Plugin { + constexpr const char* EthernetDisableMarker = "/opt/persistent/ethernet.interface.disable"; + constexpr const char* WiFiDisableMarker = "/opt/persistent/wifi.interface.disable"; class nmUtils { @@ -42,6 +44,8 @@ namespace WPEFramework static std::string wifiFrequencyFromAp(guint32 apFreq); static std::string getSecurityModeString(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); static bool setNetworkManagerlogLevelToTrace(); + static void setMarkerFile(const char* filename, bool unmark = false); + static bool isInterfaceEnabled(const std::string& interface); }; } } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index b0ed759f3..22cf19b3d 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -623,53 +623,55 @@ namespace WPEFramework return true; } - bool wifiManager::activateKnownWifiConnection(std::string knownssid) + bool wifiManager::activateKnownConnection(std::string iface, std::string knowConnectionID) { - const GPtrArray *wifiConnections = NULL; - NMConnection *m_connection = NULL; + const GPtrArray *devConnections = NULL; + NMConnection *knownConnection = NULL; + NMConnection *firstConnection = NULL; const char* specificObjPath = "/"; if(!createClientNewConnection()) return false; - NMDevice *m_wifidevice = getWifiDevice(); - if(m_wifidevice == NULL) { - NMLOG_WARNING("wifi state is unmanaged !"); + NMDevice *nmDevice = nm_client_get_device_by_iface(m_client, iface.c_str());; + if(nmDevice == NULL) { + NMLOG_WARNING("nm_client_get_device_by_iface failed !"); deleteClientConnection(); return false; } - nm_device_set_autoconnect(m_wifidevice, true); // set autoconnect true - - if(knownssid.empty()) - { - NMLOG_WARNING("ssid not specified !"); - deleteClientConnection(); - return false; - } + nm_device_set_autoconnect(nmDevice, true); // set autoconnect true - wifiConnections = nm_device_get_available_connections(m_wifidevice); - if(wifiConnections == NULL) + devConnections = nm_device_get_available_connections(nmDevice); + if(devConnections == NULL) { - NMLOG_WARNING("No wifi connection found !"); + NMLOG_WARNING("No connections specific dev found !"); deleteClientConnection(); return false; } - for (guint i = 0; i < wifiConnections->len; i++) + for (guint i = 0; i < devConnections->len; i++) { - NMConnection *connection = static_cast(g_ptr_array_index(wifiConnections, i)); + NMConnection *connection = static_cast(g_ptr_array_index(devConnections, i)); if(connection == NULL) continue; const char *connId = nm_connection_get_id(NM_CONNECTION(connection)); - if (connId != NULL && strcmp(connId, knownssid.c_str()) == 0) + if(connId != NULL) { + NMLOG_DEBUG("wifi conn : %s", connId); + if(firstConnection == NULL) + firstConnection = connection; + } + else + NMLOG_WARNING("wifi connection id is NULL"); + + if (connId != NULL && strcmp(connId, knowConnectionID.c_str()) == 0) { - m_connection = g_object_ref(connection); - NMLOG_DEBUG("connection '%s' exists !", knownssid.c_str()); - if (m_connection == NULL) + knownConnection = g_object_ref(connection); + NMLOG_DEBUG("connection '%s' exists !", knowConnectionID.c_str()); + if (knownConnection == NULL) { - NMLOG_ERROR("m_connection == NULL smothing went worng"); + NMLOG_ERROR("knownConnection == NULL smothing went worng"); deleteClientConnection(); return false; } @@ -677,17 +679,25 @@ namespace WPEFramework } } + // if no connection found then try activate first connection form connection list + if(knownConnection == NULL && firstConnection != NULL) + { + NMLOG_INFO("No known connection found, using first wifi connection"); + knownConnection = g_object_ref(firstConnection); + knowConnectionID = nm_connection_get_id(NM_CONNECTION(knownConnection)); + } + m_isSuccess = false; - if (m_connection != NULL && NM_IS_REMOTE_CONNECTION(m_connection)) + if (knownConnection != NULL && NM_IS_REMOTE_CONNECTION(knownConnection)) { - NMLOG_INFO("activating known wifi '%s' connection", knownssid.c_str()); + NMLOG_INFO("activating known wifi '%s' connection", knowConnectionID.c_str()); m_createNewConnection = false; // no need to create new connection - nm_client_activate_connection_async(m_client, NM_CONNECTION(m_connection), m_wifidevice, specificObjPath, NULL, wifiConnectCb, this); + nm_client_activate_connection_async(m_client, NM_CONNECTION(knownConnection), nmDevice, specificObjPath, NULL, wifiConnectCb, this); wait(m_loop); } else { - NMLOG_ERROR("'%s' connection not found !", knownssid.c_str()); + NMLOG_ERROR("'%s' connection not found !", knowConnectionID.c_str()); } deleteClientConnection(); @@ -748,7 +758,7 @@ namespace WPEFramework { NMLOG_DEBUG("Adding to known ssid '%s' ", ssidInfo.ssid.c_str()); deleteClientConnection(); - return activateKnownWifiConnection(ssidInfo.ssid); + return activateKnownConnection(nmUtils::wlanIface(), ssidInfo.ssid); } deleteClientConnection(); return false; @@ -1564,26 +1574,57 @@ namespace WPEFramework if (enabled) { NMLOG_DEBUG("Enabling interface..."); - if (deviceState >= NM_DEVICE_STATE_DISCONNECTED) // already enabled + if (deviceState >= NM_DEVICE_STATE_UNAVAILABLE) // already enabled { deleteClientConnection(); return true; } } else { NMLOG_DEBUG("Disabling interface..."); - if (deviceState <= NM_DEVICE_STATE_UNMANAGED) // already disabled + if (deviceState < NM_DEVICE_STATE_UNAVAILABLE) // already disabled { deleteClientConnection(); return true; } - else if (deviceState > NM_DEVICE_STATE_DISCONNECTED) { + NMLOG_DEBUG("Disconnecting device..."); + // Disconnect the device before setting it to unmanaged. + // This ensures that NetworkManager cleanly removes any IP addresses, routes, + // and DNS configuration associated with the interface. Setting an interface + // to unmanaged without disconnecting first may leave residual configuration + // that can cause networking issues. nm_device_disconnect_async(device, nullptr, disconnectCb, this); wait(m_loop); - sleep(1); // to remove the connection + // Wait until device is truly disconnected + int retry = 24; // 12 seconds + NMDeviceState oldDevState = NM_DEVICE_STATE_UNKNOWN; + while (retry-- > 0) { + /* Force glib event processing to update state + * This below line will create an uncertain time wait. We are taking a fixed time interval of 12 seconds. + */ + // while (g_main_context_iteration(NULL, FALSE)); + + deviceState = nm_device_get_state(device); + if(oldDevState != deviceState) + { + oldDevState = deviceState; + NMLOG_WARNING("Device state: %d", deviceState); + } + + if (deviceState <= NM_DEVICE_STATE_DISCONNECTED) + break; + + g_usleep(500 * 1000); // 500ms (much faster response) + } } } + if(deviceState > NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_WARNING("Device not fully disconnected (state: %d), setting to unmanaged state", deviceState); + } + // Set the "Managed" property to enable/disable the device + m_isSuccess = false; const char *objectPath = nm_object_get_path(NM_OBJECT(device)); GVariant *value = g_variant_new_boolean(enabled); @@ -1591,6 +1632,16 @@ namespace WPEFramework value, -1, nullptr, deviceManagedCb, this); wait(m_loop); deleteClientConnection(); + + if(m_isSuccess) + { + // set persistent marker file for specific interface + if(interface == nmUtils::ethIface()) + nmUtils::setMarkerFile(EthernetDisableMarker, enabled); + else // wifi + nmUtils::setMarkerFile(WiFiDisableMarker, enabled); + } + return m_isSuccess; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index cdaad248e..d661ea75d 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -50,7 +50,7 @@ namespace WPEFramework bool getWifiState(Exchange::INetworkManager::WiFiState& state); bool wifiDisconnect(); - bool activateKnownWifiConnection(std::string knownssid); + bool activateKnownConnection(std::string iface, std::string knowConnectionID=""); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); bool wifiConnect(Exchange::INetworkManager::WiFiConnectTo ssidInfo); bool wifiScanRequest(std::string ssidReq = ""); diff --git a/plugin/gnome/scripts/nm_interface_handler.sh b/plugin/gnome/scripts/nm_interface_handler.sh new file mode 100644 index 000000000..12ce1514a --- /dev/null +++ b/plugin/gnome/scripts/nm_interface_handler.sh @@ -0,0 +1,63 @@ +#!/bin/sh +############################################################################## +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2025 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################## + +# nm_interface_handler.sh +# +# This script manages Ethernet and Wi-Fi interfaces based on marker files. +# If specific marker files exist, it marks eth0 or wlan0 as unmanaged +# in NetworkManager, preventing automatic configuration. +# +# Invocation: +# Called automatically during system startup as part of the thunder-startup-services +# WPEFramework NetworkManager plugin service using ExecStartPre in: +# wpeframework-networkmanager.service + +. /etc/device.properties + +# Ethernet +NSM_ETH_MARKER="/opt/persistent/ethernet_disallowed" +NM_ETH_MARKER="/opt/persistent/ethernet.interface.disable" +ETH_INTERFACE="$ETHERNET_INTERFACE" + +# Wi-Fi +NSM_WIFI_MARKER="/opt/persistent/wifi_disallowed" +NM_WIFI_MARKER="/opt/persistent/wifi.interface.disable" +WIFI_INTERFACE="$WIFI_INTERFACE" + +# Rename legacy netsrvmger markers to networkmanager markers if they exist +if [ -f "$NSM_ETH_MARKER" ]; then + mv "$NSM_ETH_MARKER" "$NM_ETH_MARKER" +fi + +if [ -f "$NSM_WIFI_MARKER" ]; then + mv "$NSM_WIFI_MARKER" "$NM_WIFI_MARKER" +fi + +# If networkmanager Ethernet marker exists, make eth0 unmanaged +if [ -f "$NM_ETH_MARKER" ]; then + nmcli device disconnect "$ETH_INTERFACE" + nmcli dev set "$ETH_INTERFACE" managed no +fi + +# If networkmanager Wi-Fi marker exists, make wlan0 unmanaged +if [ -f "$NM_WIFI_MARKER" ]; then + nmcli device disconnect "$WIFI_INTERFACE" + nmcli dev set "$WIFI_INTERFACE" managed no +fi diff --git a/plugin/gnome/systemd/gnome-networkmanager-migration.conf b/plugin/gnome/systemd/gnome-networkmanager-migration.conf new file mode 100644 index 000000000..7aa5fcad0 --- /dev/null +++ b/plugin/gnome/systemd/gnome-networkmanager-migration.conf @@ -0,0 +1,2 @@ +[Service] +ExecStartPre=/bin/sh -c '/lib/rdk/nm_interface_handler.sh' From 82b9f575a42a19caae2390ac122f2950b85c0f67 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 29 May 2025 15:05:08 -0400 Subject: [PATCH 137/271] RDKEMW-4100 - [RDKEMW][FOXTEL] [XioneUK] Process crashed = NetworkManager seen on after reboot (#161) Reason for change: Added try catch to detect whether crash is happening in monitorThreadFunction function Test Procedure: Check for the logs monitorThreadFunction Risks: Medium Priority: P2 --- plugin/NetworkManagerImplementation.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 2921fbfa4..bea50cb78 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -720,7 +720,12 @@ namespace WPEFramework } m_isRunning = true; m_stopThread = false; - m_monitorThread = std::thread(&NetworkManagerImplementation::monitorThreadFunction, this, interval); + try { + m_monitorThread = std::thread(&NetworkManagerImplementation::monitorThreadFunction, this, interval); + NMLOG_INFO("monitorThreadFunction thread creation successful"); + } catch (const std::exception& err) { + NMLOG_INFO("monitorThreadFunction thread creation failed: %s\n", err.what()); + } } void NetworkManagerImplementation::stopWiFiSignalQualityMonitor() From 2a0a4e32be46f1228f9722e97c63e8f25cc349ce Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Thu, 29 May 2025 15:43:36 -0400 Subject: [PATCH 138/271] Release of 0.19.0 (#162) Signed-off-by: Karunakaran A --- CHANGELOG.md | 5 +++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba92637d2..f1a08900a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.19.0] - 2025-05-29 +### Fixed +- Fixed Persistence related to interface enable/disable status +- Added addtional logs to understand WIFISignal monitoring thread + ## [0.18.0] - 2025-05-21 ### Fixed - Fixed onActiveInterfaceChange event data. diff --git a/CMakeLists.txt b/CMakeLists.txt index 15261a477..344afd4cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 18) +set(VERSION_MINOR 19) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index aee056fd8..6511685fe 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.18.0" + "version": "0.19.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 2544c93e0..6ec614422 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.18.0** +**Version: 0.19.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.18.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.19.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From f83364d88ab8b7948c36d7c668b3350a7f0ad264 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 9 Jun 2025 13:53:15 -0400 Subject: [PATCH 139/271] RDKEMW-5110 - Updating the workflow of Network Manager plugin (#167) Reason for change: Removed release and feature branches. Added support and topic branches. Test Procedure: Check the .yml is getting executed for new added branches Risks: Medium Priority: P2 --- .github/workflows/gnome_unit_test.yml | 4 ++-- .github/workflows/rdk_unit_test.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index 64ba786a7..69d4d063a 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -2,9 +2,9 @@ name: gnome_unit_test on: push: - branches: [ main, develop, 'release/**', 'hotfix/**', 'feature/**'] + branches: [ main, develop, 'support/**', 'hotfix/**', 'topic/**'] pull_request: - branches: [ main, develop, 'release/**', 'hotfix/**', 'feature/**'] + branches: [ main, develop, 'support/**', 'hotfix/**', 'topic/**'] env: THUNDER_REF: "R4.4.1" diff --git a/.github/workflows/rdk_unit_test.yml b/.github/workflows/rdk_unit_test.yml index 6c23ab3c1..2a6a1d20e 100644 --- a/.github/workflows/rdk_unit_test.yml +++ b/.github/workflows/rdk_unit_test.yml @@ -2,9 +2,9 @@ name: rdk_unit_test on: push: - branches: [ main, develop, 'release/**', 'hotfix/**', 'feature/**'] + branches: [ main, develop, 'support/**', 'hotfix/**', 'topic/**'] pull_request: - branches: [ main, develop, 'release/**', 'hotfix/**', 'feature/**'] + branches: [ main, develop, 'support/**', 'hotfix/**', 'topic/**'] env: THUNDER_REF: "R4.4.1" From bdc9a6822c83ff776f79040d4677d4910daca532 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 10 Jun 2025 16:25:14 -0400 Subject: [PATCH 140/271] RDKEMW-4954 - NetworkManager plugin documentation change (#170) Reason for change: Modified the documentation for GetSupportedSecurityModes Test Procedure: NA Risks: Medium Priority: P2 --- definition/NetworkManager.json | 4 ++-- docs/NetworkManagerPlugin.md | 12 ++++++------ plugin/NetworkManagerImplementation.cpp | 4 ++-- plugin/NetworkManagerImplementation.h | 2 +- plugin/NetworkManagerJsonRpc.cpp | 3 ++- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 6511685fe..7771a02e8 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -1265,7 +1265,7 @@ "result": { "type": "object", "properties": { - "security_modes": { + "security": { "summary": "The supported security modes and its associated integer value.", "type": "object", "properties": { @@ -1302,7 +1302,7 @@ } }, "required": [ - "security_modes", + "security", "success" ] } diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 6ec614422..7282d2773 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -1620,11 +1620,11 @@ This method takes no parameters. | Name | Type | Description | | :-------- | :-------- | :-------- | | result | object | | -| result.security_modes | object | The supported security modes and its associated integer value | -| result.security_modes.NONE | integer | Security mode for open network | -| result.security_modes.WPA_PSK | integer | Supports security mode WPA,WPA-PSK,WPA2-PSK, WPA3-Personal-Transition | -| result.security_modes.SAE | integer | Supports security mode WPA3-Personal | -| result.security_modes.EAP | integer | Supports security mode WPA enterpise | +| result.security | object | The supported security modes and its associated integer value | +| result.security.NONE | integer | Security mode for open network | +| result.security.WPA_PSK | integer | Supports security mode WPA,WPA-PSK,WPA2-PSK, WPA3-Personal-Transition | +| result.security.SAE | integer | Supports security mode WPA3-Personal | +| result.security.EAP | integer | Supports security mode WPA enterpise | | result.success | boolean | Whether the request succeeded | ### Example @@ -1646,7 +1646,7 @@ This method takes no parameters. "jsonrpc": "2.0", "id": 42, "result": { - "security_modes": { + "security": { "NONE": 0, "WPA_PSK": 1, "SAE": 2, diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index bea50cb78..073a4fc5a 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -573,7 +573,7 @@ namespace WPEFramework // WiFi Specific Methods /* @brief Initiate a WIFI Scan; This is Async method and returns the scan results as Event */ - uint32_t NetworkManagerImplementation::GetSupportedSecurityModes(ISecurityModeIterator*& securityModes /* @out */) const + uint32_t NetworkManagerImplementation::GetSupportedSecurityModes(ISecurityModeIterator*& security /* @out */) const { LOG_ENTRY_FUNCTION(); std::vector modeInfo { @@ -584,7 +584,7 @@ namespace WPEFramework }; using Implementation = RPC::IteratorType; - securityModes = Core::Service::Create(modeInfo); + security = Core::Service::Create(modeInfo); return Core::ERROR_NONE; } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 930c6f76a..f222f774f 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -243,7 +243,7 @@ namespace WPEFramework /* @brief Request for trace get the response in as event. The GUID used in the request will be returned in the event. */ uint32_t Trace (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const string guid /* @in */, string& response /* @out */) override; - uint32_t GetSupportedSecurityModes(ISecurityModeIterator*& securityModes /* @out */) const override; + uint32_t GetSupportedSecurityModes(ISecurityModeIterator*& security /* @out */) const override; /* @brief Set the network manager plugin log level */ uint32_t SetLogLevel(const Logging& level /* @in */) override; diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index aed59cc7c..e2a1a9d90 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -953,8 +953,9 @@ namespace WPEFramework Exchange::INetworkManager::WIFISecurityModeInfo _resultItem_{}; while (securityModes->Next(_resultItem_) == true) { - response.Set(_resultItem_.securityName.c_str(), JsonValue(_resultItem_.security)); + modes.Set(_resultItem_.securityName.c_str(), JsonValue(_resultItem_.security)); } + response["security"] = modes; securityModes->Release(); } } From 857da161d720526c280750f905f9898a2dd135a9 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 13 Jun 2025 20:24:26 +0530 Subject: [PATCH 141/271] RDKEMW-4095 : Losing WiFi Signal Monitor Thread context when Toggling WiFi - Leading to exception (#171) Reason for change: Losing WiFi Signal Monitor Thread context when Toggling WiFi - Leading to exception Test Procedure: Network Reset Risks: Low --- plugin/NetworkManagerImplementation.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 073a4fc5a..6cf90765e 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -719,12 +719,17 @@ namespace WPEFramework return; } m_isRunning = true; - m_stopThread = false; try { + if (m_monitorThread.joinable()) { + m_stopThread = true; + NMLOG_INFO("joinable monitorThreadFunction is active !"); + m_monitorThread.join(); + } + m_stopThread = false; m_monitorThread = std::thread(&NetworkManagerImplementation::monitorThreadFunction, this, interval); NMLOG_INFO("monitorThreadFunction thread creation successful"); } catch (const std::exception& err) { - NMLOG_INFO("monitorThreadFunction thread creation failed: %s\n", err.what()); + NMLOG_INFO("monitorThreadFunction thread creation failed: %s", err.what()); } } From 6fd360b458f131a8d9f351762546c74c2c50f4b2 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 13 Jun 2025 11:40:13 -0400 Subject: [PATCH 142/271] RDKTV-37227 - retrieveSSID API should return the Security Mode based on getsupportedsecuritymodes (#173) Reason for change: Changes the retieveSSID security mode return value as per legacy getsupportedsecuritymodes Test Procedure: retrieveSSID curl Risks: Medium Priority: P1 Signed-off-by: Gururaaja ESR --- legacy/LegacyWiFiManagerAPIs.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/legacy/LegacyWiFiManagerAPIs.cpp b/legacy/LegacyWiFiManagerAPIs.cpp index 9a583b67f..fcae4efb8 100644 --- a/legacy/LegacyWiFiManagerAPIs.cpp +++ b/legacy/LegacyWiFiManagerAPIs.cpp @@ -790,11 +790,11 @@ namespace WPEFramework response["ssid"] = ssid; //As enterprise data is not persisted, WPA_EAP mode is not considered here if(security == "NONE") - response["securityMode"] = JsonValue(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE); + response["securityMode"] = JsonValue(NET_WIFI_SECURITY_NONE); else if(security == "SAE") - response["securityMode"] = JsonValue(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE); + response["securityMode"] = JsonValue(NET_WIFI_SECURITY_WPA3_SAE); else - response["securityMode"] = JsonValue(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK); + response["securityMode"] = JsonValue(NET_WIFI_SECURITY_WPA2_PSK_AES); /* WPA3_PSK_AES has backward compatibility for PSK. So WPA-PSK is considered as default */ response["passphrase"] = passphrase; response["success"] = true; From 4b48814417e7ab4faa46251cd771562daa6434d9 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 13 Jun 2025 13:27:15 -0400 Subject: [PATCH 143/271] RDKEMW-5174 - SSID Name with length 32 is not connecting (#172) * RDKEMW-5174 - SSID Name with length 32 is not connecting Reason for change: The allowed ssid length is 32. Updated to handle it Test Procedure: NA Risks: Medium Priority: P0 --- plugin/gnome/NetworkManagerGnomeProxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 31248e9fe..443eecfd5 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -662,7 +662,7 @@ namespace WPEFramework if(wifi->activateKnownConnection(nmUtils::wlanIface(), _instance->m_lastConnectedSSID)) rc = Core::ERROR_NONE; } - else if(ssid.ssid.size() < 32) + else if(ssid.ssid.size() <= 32) { if(wifi->wifiConnect(ssid)) rc = Core::ERROR_NONE; From da20a2ff3513c6c0714bcf497547b8dc74f55606 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 13 Jun 2025 13:28:10 -0400 Subject: [PATCH 144/271] DELIA-68256 - Reset Manual IP is not working (#169) * DELIA-68256 - Reset Manual IP is not working Reason for change: Checked for proper ipversion in the input curl request and it is not valid return as bad request. This will address the issue of Network Reset performed for AutoConfig IP when the device is already setup with manual IP, it is not accepting the mode change. Test Procedure: Check setIPSettings curl command Risks: Medium Priority: P2 --- legacy/LegacyNetworkAPIs.cpp | 12 +++++++++++- plugin/gnome/NetworkManagerGnomeProxy.cpp | 4 ++++ plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp | 4 ++++ plugin/rdk/NetworkManagerRDKProxy.cpp | 4 ++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/legacy/LegacyNetworkAPIs.cpp b/legacy/LegacyNetworkAPIs.cpp index 6cb2725b0..4d4d3eb2a 100644 --- a/legacy/LegacyNetworkAPIs.cpp +++ b/legacy/LegacyNetworkAPIs.cpp @@ -458,11 +458,21 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { return Core::ERROR_BAD_REQUEST; } + if (parameters.HasLabel("ipversion")) + { + address.ipversion = parameters["ipversion"].String(); + if (("IPv4" != address.ipversion) && ("IPv6" != address.ipversion)) + { + return Core::ERROR_BAD_REQUEST; + } + } + else + return Core::ERROR_BAD_REQUEST; + address.autoconfig = parameters["autoconfig"].Boolean(); if (!address.autoconfig) { address.ipaddress = parameters["ipaddr"].String(); - address.ipversion = parameters["ipversion"].String(); address.gateway = parameters["gateway"].String(); address.primarydns = parameters["primarydns"].String(); address.secondarydns = parameters["secondarydns"].String(); diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 443eecfd5..cb63b642c 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -561,6 +561,10 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::SetIPSettings(const string& interface /* @in */, const IPAddress& address /* @in */) { uint32_t rc = Core::ERROR_GENERAL; + if (("IPv4" != address.ipversion) && ("IPv6" != address.ipversion)) + { + return Core::ERROR_BAD_REQUEST; + } if(wifi->setIpSettings(interface, address)) rc = Core::ERROR_NONE; return rc; diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp index 9e34eb0f5..ccd9f0ab0 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp @@ -165,6 +165,10 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::SetIPSettings(const string& interface /* @in */, const IPAddress& address /* @in */) { uint32_t rc = Core::ERROR_GENERAL; + if (("IPv4" != address.ipversion) && ("IPv6" != address.ipversion)) + { + return Core::ERROR_BAD_REQUEST; + } if(_nmGdbusClient->setIPSettings(interface, address)) rc = Core::ERROR_NONE; else diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 41b9882f2..b2a67e9d7 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -1091,6 +1091,10 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { uint32_t NetworkManagerImplementation::SetIPSettings(const string& interface /* @in */, const IPAddress& address /* @in */) { uint32_t rc = Core::ERROR_NONE; + if (("IPv4" != address.ipversion) && ("IPv6" != address.ipversion)) + { + return Core::ERROR_BAD_REQUEST; + } if ("IPv4" == address.ipversion) { IARM_BUS_NetSrvMgr_Iface_Settings_t iarmData = {0}; From 2fdfac8e71b91a550aec8102901a6b51eb82d473 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 16 Jun 2025 15:34:46 -0400 Subject: [PATCH 145/271] RDKTV-36415 - Device is taking 3-5min to connect the internet after waking from DS (#150) Reason for change: - changed the initial monitoring logic to post the internet status change event even when we have single successful connect. - changed the IPv4 and IPv6 thread start only when there is corresponding IPv4 and IPv6 are available. - Removed the m_notify in the switchToInitialCheck().As it is leads to a unnecessary event posting Test Procedure: As mentioned in the jira ticket RDKTV-36415 Risks: Medium Priority: P0 Signed-off-by: Gururaaja ESR --- plugin/NetworkManagerConnectivity.cpp | 38 ++++++++++++----- plugin/NetworkManagerImplementation.cpp | 8 +++- plugin/rdk/NetworkManagerRDKProxy.cpp | 54 ++++++++++++++++++------- 3 files changed, 74 insertions(+), 26 deletions(-) diff --git a/plugin/NetworkManagerConnectivity.cpp b/plugin/NetworkManagerConnectivity.cpp index 3540d8b45..aa2a5f04f 100644 --- a/plugin/NetworkManagerConnectivity.cpp +++ b/plugin/NetworkManagerConnectivity.cpp @@ -387,7 +387,11 @@ namespace WPEFramework } } else { - NMLOG_ERROR("%s, curl error = %d (%s)", endpntConf, msg->data.result, curl_easy_strerror(msg->data.result)); + NMLOG_ERROR("INTERNET_CONNECTIVITY_MONITORING_CURL_ERROR : For endpoint = <%s> on (%s) got curl error = %d (%s)", + endpntConf, + (IP_ADDRESS_V4 == ipversion) ? "IPv4" : "IPv6", + msg->data.result, + curl_easy_strerror(msg->data.result)); curlErrorCode = static_cast(msg->data.result); } http_responses.push_back(response_code); @@ -583,7 +587,6 @@ namespace WPEFramework bool ConnectivityMonitor::switchToInitialCheck() { m_switchToInitial = true; - m_notify = true; // m_notify internet state because some network state change may happen m_cmCv.notify_one(); if(_instance != nullptr) { NMLOG_INFO("switching to initial check - eth %s - wlan %s", @@ -618,10 +621,22 @@ namespace WPEFramework m_Ipv4InternetState = INTERNET_UNKNOWN; m_Ipv6InternetState = INTERNET_UNKNOWN; m_notify = true; + std::thread ipv4thread; + std::thread ipv6thread; while (m_cmRunning) { + if (nullptr == _instance) + { + NMLOG_DEBUG("Must be right from the constructor; because the _instance is NULL"); + timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; + m_InternetState = INTERNET_NOT_AVAILABLE; + m_Ipv4InternetState = INTERNET_NOT_AVAILABLE; + m_Ipv6InternetState = INTERNET_NOT_AVAILABLE; + currentInternetState = INTERNET_NOT_AVAILABLE; + InitialRetryCount = 0; + } // Check if no interfaces are connected - if (_instance != nullptr && !_instance->m_ethConnected && !_instance->m_wlanConnected) { + else if (_instance != nullptr && !_instance->m_ethConnected && !_instance->m_wlanConnected) { NMLOG_DEBUG("no interface connected, no ccm check"); timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; m_InternetState = INTERNET_NOT_AVAILABLE; @@ -634,7 +649,7 @@ namespace WPEFramework } else if (m_switchToInitial) { - NMLOG_INFO("Initial cm check - retry count %d - %s", InitialRetryCount, getInternetStateString(currentInternetState)); + NMLOG_INFO("Initial connectivity check - index:%d current state:%s", InitialRetryCount, getInternetStateString(currentInternetState)); timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; // Lambda functions to check connectivity for IPv4 and IPv6 @@ -654,13 +669,14 @@ namespace WPEFramework m_captiveURI = testInternet.getCaptivePortal(); }; - // Start threads for IPv4 and IPv6 checks - std::thread ipv4thread(curlCheckThrdIpv4); - std::thread ipv6thread(curlCheckThrdIpv6); + ipv4thread = std::thread (curlCheckThrdIpv4); + ipv6thread = std::thread (curlCheckThrdIpv6); // Wait for both threads to finish - ipv4thread.join(); - ipv6thread.join(); + if (ipv4thread.joinable()) + ipv4thread.join(); + if (ipv6thread.joinable()) + ipv6thread.join(); // Determine the current internet state based on the results if (m_Ipv4InternetState == INTERNET_NOT_AVAILABLE && m_Ipv6InternetState == INTERNET_NOT_AVAILABLE) { @@ -693,6 +709,7 @@ namespace WPEFramework NMLOG_DEBUG("initial connectivity state change %s", getInternetStateString(m_InternetState)); m_InternetState = currentInternetState; InitialRetryCount = 1; // reset retry count to get continuous 3 same state + m_notify = true; } InitialRetryCount++; } @@ -701,8 +718,9 @@ namespace WPEFramework m_switchToInitial = false; m_notify = true; InitialRetryCount = 0; - IdealRetryCount = 0; + NMLOG_INFO("Let us monitor internet connectivity on %s address further.", (IP_ADDRESS_V4 == m_ipversion) ? "IPv4" : "IPv6"); } + IdealRetryCount = 0; } // Ideal case monitoring else { diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 6cf90765e..5807beea0 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -602,8 +602,12 @@ namespace WPEFramework } /* Only the Ethernet connection status is changing here. The WiFi status is updated in the WiFi state callback. */ - if(Exchange::INetworkManager::INTERFACE_LINK_UP == state && interface == "eth0") - m_ethConnected = true; + if(Exchange::INetworkManager::INTERFACE_LINK_UP == state) + { + connectivityMonitor.switchToInitialCheck(); + if(interface == "eth0") + m_ethConnected = true; + } _notificationLock.Lock(); NMLOG_INFO("Posting onInterfaceChange %s - %u", interface.c_str(), (unsigned)state); diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index b2a67e9d7..f48c1c6de 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -674,7 +674,19 @@ namespace WPEFramework { // check the connection state and post event Exchange::INetworkManager::IInterfaceDetailsIterator* _interfaces{}; + Exchange::INetworkManager::IInterfaceDetailsIterator* _tmpInterfaces{}; uint32_t rc = GetAvailableInterfaces(_interfaces); + _tmpInterfaces = _interfaces; + size_t interfaceCount = 0; + Exchange::INetworkManager::InterfaceDetails tmpIface{}; + + while (_tmpInterfaces->Next(tmpIface)) + { + if(tmpIface.enabled && tmpIface.connected) + { + interfaceCount++; + } + } if (Core::ERROR_NONE == rc) { @@ -683,23 +695,37 @@ namespace WPEFramework Exchange::INetworkManager::InterfaceDetails iface{}; while (_interfaces->Next(iface) == true) { - Core::JSON::EnumType type{iface.type}; - if(iface.enabled) + if((interfaceCount == 2 && "eth0" == iface.name) || interfaceCount == 1) { - NMLOG_INFO("'%s' interface is enabled", iface.name.c_str()); - // ReportInterfaceStateChange(Exchange::INetworkManager::INTERFACE_ADDED, iface.name); - if(iface.connected) + Core::JSON::EnumType type{iface.type}; + if(iface.enabled) { - NMLOG_INFO("'%s' interface is connected", iface.name.c_str()); - ReportActiveInterfaceChange(iface.name, iface.name); - std::string ipversion = {}; - Exchange::INetworkManager::IPAddress addr; - rc = GetIPSettings(iface.name, ipversion, addr); - if (Core::ERROR_NONE == rc) + NMLOG_INFO("'%s' interface is enabled", iface.name.c_str()); + // ReportInterfaceStateChange(Exchange::INetworkManager::INTERFACE_ADDED, iface.name); + if(iface.connected) { - if(!addr.ipaddress.empty()) { - NMLOG_INFO("'%s' interface have ip '%s'", iface.name.c_str(), addr.ipaddress.c_str()); - ReportIPAddressChange(iface.name, addr.ipversion, addr.ipaddress, Exchange::INetworkManager::IP_ACQUIRED); + NMLOG_INFO("'%s' interface is connected", iface.name.c_str()); + if(m_defaultInterface != iface.name) + ReportActiveInterfaceChange(m_defaultInterface, iface.name); + Exchange::INetworkManager::IPAddress addrv4; + Exchange::INetworkManager::IPAddress addrv6; + std::string ipversion = "IPv4"; + rc = GetIPSettings(iface.name, ipversion, addrv4); + if (Core::ERROR_NONE == rc) + { + if(!addrv4.ipaddress.empty()) { + NMLOG_INFO("'%s' interface have ip '%s'", iface.name.c_str(), addrv4.ipaddress.c_str()); + ReportIPAddressChange(iface.name, addrv4.ipversion, addrv4.ipaddress, Exchange::INetworkManager::IP_ACQUIRED); + } + } + ipversion = "IPv6"; + rc = GetIPSettings(iface.name, ipversion, addrv6); + if (Core::ERROR_NONE == rc) + { + if(!addrv6.ipaddress.empty()) { + NMLOG_INFO("'%s' interface have ip '%s'", iface.name.c_str(), addrv6.ipaddress.c_str()); + ReportIPAddressChange(iface.name, addrv6.ipversion, addrv6.ipaddress, Exchange::INetworkManager::IP_ACQUIRED); + } } } } From 61c98ecdd8ef94682afc0ea258eb5553d3955716 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 20 Jun 2025 09:48:02 -0400 Subject: [PATCH 146/271] RDKEMW-2444 - nm_event_thrd crash (#177) Reason for change: The crash is happening because of thread is not joined, when wifi is disconnected while the monitorThreadFunction() is running(which sets the m_isRunning to false) and stopWiFiSignalQualityMonitor() is called. So the next time when the thread creation is initiate it leads to a crash. Removed m_isRunning set to false at the end of monitorThreadFunction(), so that the stopWiFiSignalQualityMonitor() will join the thread in the above mentioned scenario Test Procedure: Toggle the wifi switch in the UI and check whether nm_event_thrd crash is observed or not Risks: Medium Priority: P1 --- plugin/NetworkManagerConnectivity.cpp | 6 +- plugin/NetworkManagerImplementation.cpp | 77 ++++++++++------------- plugin/NetworkManagerImplementation.h | 3 +- plugin/gnome/NetworkManagerGnomeProxy.cpp | 8 +-- plugin/rdk/NetworkManagerRDKProxy.cpp | 4 +- 5 files changed, 43 insertions(+), 55 deletions(-) diff --git a/plugin/NetworkManagerConnectivity.cpp b/plugin/NetworkManagerConnectivity.cpp index aa2a5f04f..5a3ffa3c2 100644 --- a/plugin/NetworkManagerConnectivity.cpp +++ b/plugin/NetworkManagerConnectivity.cpp @@ -564,7 +564,7 @@ namespace WPEFramework if(_instance != nullptr) { NMLOG_INFO("connectivity monitor started - eth %s - wlan %s", - _instance->m_ethConnected? "up":"down", _instance->m_wlanConnected? "up":"down"); + _instance->m_ethConnected.load()? "up":"down", _instance->m_wlanConnected.load()? "up":"down"); } NMLOG_INFO("connectivity monitor is started"); @@ -590,7 +590,7 @@ namespace WPEFramework m_cmCv.notify_one(); if(_instance != nullptr) { NMLOG_INFO("switching to initial check - eth %s - wlan %s", - _instance->m_ethConnected? "up":"down", _instance->m_wlanConnected? "up":"down"); + _instance->m_ethConnected.load()? "up":"down", _instance->m_wlanConnected.load()? "up":"down"); } return true; } @@ -636,7 +636,7 @@ namespace WPEFramework InitialRetryCount = 0; } // Check if no interfaces are connected - else if (_instance != nullptr && !_instance->m_ethConnected && !_instance->m_wlanConnected) { + else if (_instance != nullptr && !_instance->m_ethConnected.load() && !_instance->m_wlanConnected.load()) { NMLOG_DEBUG("no interface connected, no ccm check"); timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; m_InternetState = INTERNET_NOT_AVAILABLE; diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 5807beea0..f7df9e692 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -44,8 +44,8 @@ namespace WPEFramework m_stunCacheTimeout = 0; m_defaultInterface = ""; m_publicIP = ""; - m_ethConnected = false; - m_wlanConnected = false; + m_ethConnected.store(false); + m_wlanConnected.store(false); /* Set NetworkManager Out-Process name to be NWMgrPlugin */ Core::ProcessInfo().Name("NWMgrPlugin"); @@ -63,11 +63,12 @@ namespace WPEFramework { m_registrationThread.join(); } + /* Stop WiFi Signal Monitoring */ stopWiFiSignalQualityMonitor(); { std::unique_lock lock(m_processMonMutex); - m_processMonThreadStop = true; + m_processMonThreadStop.store(true); m_processMonCondVar.notify_one(); } @@ -315,7 +316,7 @@ namespace WPEFramework bool isIPv6 = (ipversion == "IPv6"); // Either Interface must be connected to get the public IP - if (!(m_ethConnected | m_wlanConnected)) + if (!(m_ethConnected.load() || m_wlanConnected.load())) { NMLOG_WARNING("No interface Connected"); return Core::ERROR_GENERAL; @@ -595,9 +596,9 @@ namespace WPEFramework if(Exchange::INetworkManager::INTERFACE_LINK_DOWN == state || Exchange::INetworkManager::INTERFACE_REMOVED == state) { if(interface == "eth0") - m_ethConnected = false; + m_ethConnected.store(false); else if(interface == "wlan0") - m_wlanConnected = false; + m_wlanConnected.store(false); connectivityMonitor.switchToInitialCheck(); } @@ -606,7 +607,7 @@ namespace WPEFramework { connectivityMonitor.switchToInitialCheck(); if(interface == "eth0") - m_ethConnected = true; + m_ethConnected.store(true); } _notificationLock.Lock(); @@ -623,9 +624,9 @@ namespace WPEFramework NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); if(currentActiveinterface == "eth0") - m_ethConnected = true; + m_ethConnected.store(true); else if (currentActiveinterface == "wlan0") - m_wlanConnected = true; + m_wlanConnected.store(true); // FIXME : This could be the place to define `m_defaultInterface` to incoming `currentActiveinterface`. // m_defaultInterface = currentActiveinterface; @@ -643,12 +644,12 @@ namespace WPEFramework // Switch the connectivity monitor to initial check // if ipaddress is aquired means there should be interface connected if(interface == "eth0") - m_ethConnected = true; + m_ethConnected.store(true); else if(interface == "wlan0") - m_wlanConnected = true; + m_wlanConnected.store(true); // FIXME : Availability of ip address for a given interface does not mean that its the default interface. This hardcoding will work for RDKProxy but not for Gnome. - if (m_ethConnected && m_wlanConnected) + if (m_ethConnected.load() && m_wlanConnected.load()) m_defaultInterface = "eth0"; else m_defaultInterface = interface; @@ -718,18 +719,12 @@ namespace WPEFramework void NetworkManagerImplementation::startWiFiSignalQualityMonitor(int interval) { - if (m_isRunning) { + if (m_isRunning.load()) { NMLOG_INFO("WiFiSignalQualityMonitor Thread is already running."); return; } - m_isRunning = true; try { - if (m_monitorThread.joinable()) { - m_stopThread = true; - NMLOG_INFO("joinable monitorThreadFunction is active !"); - m_monitorThread.join(); - } - m_stopThread = false; + m_isRunning.store(true); m_monitorThread = std::thread(&NetworkManagerImplementation::monitorThreadFunction, this, interval); NMLOG_INFO("monitorThreadFunction thread creation successful"); } catch (const std::exception& err) { @@ -739,18 +734,19 @@ namespace WPEFramework void NetworkManagerImplementation::stopWiFiSignalQualityMonitor() { - if (!m_isRunning) { + if (!m_isRunning.load()) return; // No thread to stop - } + { - std::unique_lock lock(m_condVariableMutex); - m_stopThread = true; - m_condVariable.notify_one(); + std::lock_guard lock(m_condVariableMutex); + m_stopThread.store(true); } + m_condVariable.notify_one(); + if (m_monitorThread.joinable()) { m_monitorThread.join(); } - m_isRunning = false; + m_isRunning.store(false); } /* The below implementation of GetWiFiSignalQuality is a temporary mitigation. Need to be revisited */ @@ -912,11 +908,11 @@ namespace WPEFramework std::unique_lock lock(m_processMonMutex); // Wait for the specified interval or until notified to stop - if (m_processMonCondVar.wait_for(lock, std::chrono::seconds(interval), [this](){ return m_processMonThreadStop == true; })) + if (m_processMonCondVar.wait_for(lock, std::chrono::seconds(interval), [this](){ return m_processMonThreadStop.load(); })) { NMLOG_INFO("Received stop signal"); } - } while (!m_processMonThreadStop); + } while (!m_processMonThreadStop.load()); return; } @@ -925,7 +921,8 @@ namespace WPEFramework { static Exchange::INetworkManager::WiFiSignalQuality oldSignalQuality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; NMLOG_INFO("WiFiSignalQualityMonitor thread started ! (%d)", interval); - while (!m_stopThread) { + while (true) + { std::string ssid{}; std::string strength{}; std::string noise{}; @@ -943,18 +940,18 @@ namespace WPEFramework if (newSignalQuality == Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED) { NMLOG_WARNING("WiFiSignalQualityChanged to disconnect - WiFiSignalQualityMonitor exiting"); - m_stopThread = true; // Signal thread to stop break; // Exit the loop } std::unique_lock lock(m_condVariableMutex); // Wait for the specified interval or until notified to stop - if (m_condVariable.wait_for(lock, std::chrono::seconds(interval), [this](){ return m_stopThread == true; })) + if (m_condVariable.wait_for(lock, std::chrono::seconds(interval), [this](){ return m_stopThread.load(); })) { NMLOG_INFO("WiFiSignalQualityMonitor received stop signal or timed out"); + break; } } - m_isRunning = false; + m_stopThread.store(false); } void NetworkManagerImplementation::ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state) @@ -962,21 +959,13 @@ namespace WPEFramework /* start signal strength monitor when wifi connected */ if(INetworkManager::WiFiState::WIFI_STATE_CONNECTED == state) { - m_wlanConnected = true; - if (!m_monitoringStarted) - { - startWiFiSignalQualityMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC); - m_monitoringStarted = true; - } + m_wlanConnected.store(true); + startWiFiSignalQualityMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC); } else { - if (m_monitoringStarted) - { - stopWiFiSignalQualityMonitor(); - m_monitoringStarted = false; - } - m_wlanConnected = false; /* Any other state is considered as WiFi not connected. */ + stopWiFiSignalQualityMonitor(); + m_wlanConnected.store(false); /* Any other state is considered as WiFi not connected. */ } _notificationLock.Lock(); diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index f222f774f..7f85b2157 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -294,9 +294,8 @@ namespace WPEFramework std::atomic m_processMonThreadStop{false}; std::condition_variable m_processMonCondVar; - std::atomic m_stopThread{false}; std::atomic m_isRunning{false}; - bool m_monitoringStarted = false; + std::atomic m_stopThread{false}; std::mutex m_condVariableMutex; std::condition_variable m_condVariable; diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index cb63b642c..404ee3089 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -139,12 +139,12 @@ namespace WPEFramework if(ifaceStr == wifiname) { interface.type = INTERFACE_TYPE_WIFI; interface.name = wifiname; - m_wlanConnected = interface.connected; + m_wlanConnected.store(interface.connected); } if(ifaceStr == ethname) { interface.type = INTERFACE_TYPE_ETHERNET; interface.name = ethname; - m_ethConnected = interface.connected; + m_ethConnected.store(interface.connected); } interfaceList.push_back(interface); @@ -203,9 +203,9 @@ namespace WPEFramework { NMLOG_ERROR("nm_connection_get_interface_name is failed"); /* Temporary mitigation for nm_connection_get_interface_name failure */ - if(m_wlanConnected) + if(m_wlanConnected.load()) ifacePtr = wifiname.c_str(); - if(m_ethConnected) + if(m_ethConnected.load()) ifacePtr = ethname.c_str(); } diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index f48c1c6de..33bab9c34 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -847,11 +847,11 @@ namespace WPEFramework tmp.connected = ((list.interfaces[i].flags & IFF_RUNNING) != 0); if ("eth0" == interfaceName) { tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_ETHERNET; - m_ethConnected = tmp.connected; + m_ethConnected.store(tmp.connected); } else if ("wlan0" == interfaceName) { tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_WIFI; - m_wlanConnected = tmp.connected; + m_wlanConnected.store(tmp.connected); } interfaceList.push_back(tmp); From 17cc46d26716aecf30a3dcad3a577f39dc95d000 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 20 Jun 2025 10:06:23 -0400 Subject: [PATCH 147/271] Release of 0.20.0 Release of 0.20.0 --- CHANGELOG.md | 9 +++++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1a08900a..cba04b21e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,15 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.20.0] - 2025-06-20 +### Fixed +- Fixed the bug in Resetting of Manual IPv4 +- Fixed the SSID Name Length Check +- Added Connectivity Improvement +- Fixed the WiFi Signal Monitor thread exception +- Fixed documentation of GetSupportedSecurityModes +- Fixed the WiFi Migration settings + ## [0.19.0] - 2025-05-29 ### Fixed - Fixed Persistence related to interface enable/disable status diff --git a/CMakeLists.txt b/CMakeLists.txt index 344afd4cb..aa16eea82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 19) +set(VERSION_MINOR 20) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 7771a02e8..6a2cd97da 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.19.0" + "version": "0.20.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 7282d2773..e420634de 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.19.0** +**Version: 0.20.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.19.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.20.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 1f05094947d0765963cbbb41b7ee1f7a63983c68 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 27 Jun 2025 02:50:01 +0530 Subject: [PATCH 148/271] RDKEMW-5154, RDKEMW-5265 Wi-Fi Reconnection Fails After Re-Enabling (#178) --- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 32 ++++++++++++++++-------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 22cf19b3d..011e977f0 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -642,10 +642,10 @@ namespace WPEFramework nm_device_set_autoconnect(nmDevice, true); // set autoconnect true - devConnections = nm_device_get_available_connections(nmDevice); - if(devConnections == NULL) + devConnections = nm_client_get_connections(m_client); + if(devConnections == NULL || devConnections->len == 0) { - NMLOG_WARNING("No connections specific dev found !"); + NMLOG_ERROR("No connections found !"); deleteClientConnection(); return false; } @@ -657,13 +657,26 @@ namespace WPEFramework continue; const char *connId = nm_connection_get_id(NM_CONNECTION(connection)); - if(connId != NULL) { - NMLOG_DEBUG("wifi conn : %s", connId); + if (connId == NULL) { + NMLOG_WARNING("connection id is NULL"); + continue; + } + + const char *connTyp = nm_connection_get_connection_type(NM_CONNECTION(connection)); + if (connTyp == NULL) { + NMLOG_WARNING("connection type is NULL"); + continue; + } + + std::string connTypStr = connTyp; + NMLOG_DEBUG("connection id: %s, type: %s", connId != NULL ? connId : "NULL", connTypStr.c_str()); + if(connTypStr == "802-11-wireless") { + NMLOG_INFO("wifi conn found : %s", connId); + // if no known ssid given then use first wifi connection from list + // it usefule when bootup there will be no known ssid if(firstConnection == NULL) firstConnection = connection; } - else - NMLOG_WARNING("wifi connection id is NULL"); if (connId != NULL && strcmp(connId, knowConnectionID.c_str()) == 0) { @@ -1566,6 +1579,7 @@ namespace WPEFramework if (device == nullptr) { + NMLOG_ERROR("Device not found: %s", interface.c_str()); deleteClientConnection(); return false; } @@ -1603,7 +1617,7 @@ namespace WPEFramework * This below line will create an uncertain time wait. We are taking a fixed time interval of 12 seconds. */ // while (g_main_context_iteration(NULL, FALSE)); - + g_usleep(500 * 1000); // give some time to NM to process the request deviceState = nm_device_get_state(device); if(oldDevState != deviceState) { @@ -1613,8 +1627,6 @@ namespace WPEFramework if (deviceState <= NM_DEVICE_STATE_DISCONNECTED) break; - - g_usleep(500 * 1000); // 500ms (much faster response) } } } From 3963673b1f505a97e1ebd85e508140dbee3e3a4b Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 1 Jul 2025 16:27:27 -0400 Subject: [PATCH 149/271] RDKEMW-4229 - Fixing the gdbus issues (#151) Fixed the issues in the networkmanager - gdbus proxy implementation --- .../gnome/gdbus/NetworkManagerGdbusClient.cpp | 82 ++++++++++++++++--- .../gnome/gdbus/NetworkManagerGdbusClient.h | 4 +- .../gnome/gdbus/NetworkManagerGdbusProxy.cpp | 14 +++- 3 files changed, 85 insertions(+), 15 deletions(-) diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp index de74f3f12..233611d81 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp @@ -27,13 +27,12 @@ #include "NetworkManagerLogger.h" #include "NetworkManagerGdbusClient.h" #include "NetworkManagerGdbusUtils.h" -#include "NetworkManagerImplementation.h" namespace WPEFramework { namespace Plugin { - + extern NetworkManagerImplementation* _instance; NetworkManagerClient::NetworkManagerClient() { NMLOG_INFO("NetworkManagerClient"); } @@ -541,11 +540,25 @@ namespace WPEFramework return true; } + bool NetworkManagerClient::getDefaultInterface(std::string& interface) + { + deviceInfo devInfo{}; + std::string wifiname = GnomeUtils::getWifiIfname(), ethname = GnomeUtils::getEthIfname(); + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, ethname.c_str(), devInfo)) + return false; + if(devInfo.state > NM_DEVICE_STATE_DISCONNECTED && devInfo.state < NM_DEVICE_STATE_DEACTIVATING) + interface = ethname; + else + interface = wifiname; // default is wifi + return true; + } + bool NetworkManagerClient::getPrimaryInterface(std::string& interface) { GError* error = nullptr; std::string primaryConnectionPath; GDBusProxy *nmProxy = nullptr; + nmProxy = m_dbus.getNetworkManagerPropertyProxy("/org/freedesktop/NetworkManager"); if(nmProxy == nullptr) return false; @@ -753,7 +766,7 @@ namespace WPEFramework return true; } - bool NetworkManagerClient::getIPSettings(const std::string& interface, const std::string& ipversion, Exchange::INetworkManager::IPAddress& result) + bool NetworkManagerClient::getIPSettings(std::string& interface, const std::string& ipversion, Exchange::INetworkManager::IPAddress& result) { std::string devicePath; std::string addressStr; @@ -772,12 +785,54 @@ namespace WPEFramework const gchar *IPv6Method = nullptr; deviceInfo devInfo{}; GError *error = nullptr; + + std::string wifiname = GnomeUtils::getWifiIfname(), ethname = GnomeUtils::getEthIfname(); + + if(interface.empty()) + { + if(Core::ERROR_NONE != _instance->GetPrimaryInterface(interface)) + { + NMLOG_WARNING("default interface get failed"); + return true; + } + if(interface.empty()) + { + NMLOG_DEBUG("default interface return empty default is wlan0"); + interface = wifiname; + } + } + else if(wifiname != interface && ethname != interface) + { + NMLOG_ERROR("interface: %s; not valied", interface.c_str()); + return false; + } + + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, interface.c_str(), devInfo)) + { + return false; + } + + if(devInfo.state <= NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_WARNING("Device state is not a valid state: (%d)", devInfo.state); + return false; + } + else if (devInfo.state > NM_DEVICE_STATE_DISCONNECTED && devInfo.state < NM_DEVICE_STATE_IP_CHECK) + { + result.autoconfig = true; + if(ipversion.empty()) + result.ipversion = "IPv4"; + else + result.ipversion = ipversion; + return true; + } + if(!GnomeUtils::getDeviceByIpIface(m_dbus, interface.c_str(), devicePath)) return false; GDBusProxy *deviceProxy = m_dbus.getNetworkManagerDeviceProxy(devicePath.c_str()); if(deviceProxy == nullptr) return false; - if (g_strcmp0(ipversion.c_str(), "IPv4") == 0) + if(ipversion.empty() || (g_strcmp0(ipversion.c_str(), "IPv4") == 0)) { GVariant *ip4Property = g_dbus_proxy_get_cached_property(deviceProxy, "Ip4Config"); if (ip4Property != nullptr) @@ -895,6 +950,7 @@ namespace WPEFramework if (dhcpServerIp) { NMLOG_DEBUG("DHCP server IP address: %s", dhcpServerIp); } else { + dhcpServerIp = nullptr; NMLOG_DEBUG("Failed to find DHCP server IP address"); } if (dnsAddresses) { @@ -920,8 +976,9 @@ namespace WPEFramework g_object_unref(dhcpv4Proxy); } } + result.ipversion = "IPv4"; } - else if (g_strcmp0(ipversion.c_str(), "IPv6") == 0) + if((addressStr.empty() && !(g_strcmp0(ipversion.c_str(), "IPv4") == 0)) || g_strcmp0(ipversion.c_str(), "IPV6") == 0) { GVariant *ip6Property = g_dbus_proxy_get_cached_property(deviceProxy, "Ip6Config"); if (ip6Property != nullptr) { @@ -997,6 +1054,7 @@ namespace WPEFramework } else { + gatewayIp = nullptr; NMLOG_ERROR("Failed to get Gateway property for IPv6"); g_object_unref(ipv6Proxy); } @@ -1059,6 +1117,7 @@ namespace WPEFramework NMLOG_ERROR("Failed to parse DNS addresses"); } } else { + dnsList = nullptr; std::cerr << "Failed to find DNS addresses" << std::endl; } } @@ -1068,6 +1127,13 @@ namespace WPEFramework g_object_unref(dhcpv6Proxy); } } + result.ipversion = "IPv6"; + } + if(addressStr.empty()) + { + result.autoconfig = true; + if(ipversion.empty()) + result.ipversion = "IPv4"; } std::string connectionPath; if (!GnomeUtils::getSettingsConnectionPath(m_dbus, connectionPath, interface)) @@ -1076,13 +1142,10 @@ namespace WPEFramework return false; } - if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, interface.c_str(), devInfo)) - return false; GDBusProxy *settingsProxy = m_dbus.getNetworkManagerSettingsConnectionProxy(connectionPath.c_str()); if (settingsProxy == nullptr) { - NMLOG_ERROR("Error creating connection settings proxy: %s",error->message); - g_error_free(error); + NMLOG_ERROR("Error creating connection settings proxy"); return false; } @@ -1129,7 +1192,6 @@ namespace WPEFramework } } - result.ipversion = ipversion; result.autoconfig = true; if(g_strcmp0(ipversion.c_str(), "IPv4") == 0) result.autoconfig = (g_strcmp0(IPv4Method, "auto") == 0); diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusClient.h b/plugin/gnome/gdbus/NetworkManagerGdbusClient.h index 9a727b923..4b3d9afbe 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusClient.h +++ b/plugin/gnome/gdbus/NetworkManagerGdbusClient.h @@ -26,6 +26,7 @@ #include "NetworkManagerLogger.h" #include "NetworkManagerGdbusMgr.h" #include "NetworkManagerSecretAgent.h" +#include "NetworkManagerImplementation.h" #include "INetworkManager.h" #define GDBUS_WPS_RETRY_WAIT_IN_MS 10 // 10 sec @@ -53,8 +54,9 @@ namespace WPEFramework bool setInterfaceState(const std::string& interface, bool enable); bool setIPSettings(const std::string& interface, const Exchange::INetworkManager::IPAddress& address); bool getPrimaryInterface(std::string& interface); + bool getDefaultInterface(std::string& interface); bool getInterfaceState(const std::string& interface, bool& isEnabled); - bool getIPSettings(const std::string& interface, const std::string& ipversion, Exchange::INetworkManager::IPAddress& result); + bool getIPSettings(std::string& interface, const std::string& ipversion, Exchange::INetworkManager::IPAddress& result); bool getKnownSSIDs(std::list& ssids); bool getConnectedSSID(Exchange::INetworkManager::WiFiSSIDInfo& ssidinfo); bool addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo); diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp index ccd9f0ab0..e22381c5b 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp @@ -113,12 +113,18 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::GetPrimaryInterface (string& interface /* @out */) { - uint32_t rc = Core::ERROR_GENERAL; if(_nmGdbusClient->getPrimaryInterface(interface)) - rc = Core::ERROR_NONE; + return Core::ERROR_NONE; else - NMLOG_ERROR("GetPrimaryInterface failed"); - return rc; + { + if(_nmGdbusClient->getDefaultInterface(interface)) + { + _instance->m_defaultInterface = interface; + return Core::ERROR_NONE; + } + else + return Core::ERROR_GENERAL; + } } uint32_t NetworkManagerImplementation::SetPrimaryInterface (const string& interface/* @in */) From e093a42a09cee53493d10b98c45743ab5fa7ae3c Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 2 Jul 2025 12:12:09 -0400 Subject: [PATCH 150/271] RDKEMW-5720 - Removal of SetPrimaryInterface and other cleanup (#182) * RDKEMW-4918 - Removal of SetPrimaryInterface and other cleanup Reason for change: Removed SetPrimaryInterface support and inherited Iconfiguration to configure the plugin. Also removed activation of networkmanager plugin from legacy plugin Test Procedure: NA Risks: Medium Priority: P1 --- .github/workflows/gnome_unit_test.yml | 10 ++++ .github/workflows/rdk_unit_test.yml | 10 ++++ definition/NetworkManager.json | 33 +----------- docs/NetworkManagerPlugin.md | 53 +------------------ interface/INetworkManager.h | 2 - legacy/LegacyNetworkAPIs.cpp | 50 +---------------- legacy/LegacyNetworkAPIs.h | 1 - legacy/LegacyWiFiManagerAPIs.cpp | 28 ---------- legacy/LegacyWiFiManagerAPIs.h | 1 - plugin/NetworkManager.cpp | 20 ++++--- plugin/NetworkManager.h | 2 +- plugin/NetworkManagerImplementation.h | 6 +-- plugin/NetworkManagerJsonRpc.cpp | 22 -------- plugin/gnome/NetworkManagerGnomeProxy.cpp | 9 ---- .../gnome/gdbus/NetworkManagerGdbusProxy.cpp | 9 ---- plugin/rdk/NetworkManagerRDKProxy.cpp | 32 ----------- tests/unittest/test_NetworkManager.cpp | 7 --- tools/plugincli/NetworkManagerGdbusTest.cpp | 34 ++++-------- 18 files changed, 52 insertions(+), 277 deletions(-) diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gnome_unit_test.yml index 69d4d063a..a14a07a9d 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gnome_unit_test.yml @@ -35,6 +35,7 @@ jobs: run: | git clone https://github.com/rdkcentral/ThunderTools ThunderTools --branch ${{ env.THUNDER_REF }} git clone https://github.com/rdkcentral/Thunder Thunder --branch ${{ env.THUNDER_REF }} + git clone https://github.com/rdkcentral/ThunderInterfaces ThunderInterfaces --branch ${{ env.THUNDER_REF }} - name: Build ThunderTools run: > @@ -58,6 +59,15 @@ jobs: && cmake --build build/Thunder --target install -j8 + - name: ThunderInterfaces + run: > + cmake + -S "${{github.workspace}}/ThunderInterfaces" -B build/ThunderInterfaces + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + && + cmake --build build/ThunderInterfaces --target install -j8 + - name: Checkout networkmanager uses: actions/checkout@v3 with: diff --git a/.github/workflows/rdk_unit_test.yml b/.github/workflows/rdk_unit_test.yml index 2a6a1d20e..f42f39862 100644 --- a/.github/workflows/rdk_unit_test.yml +++ b/.github/workflows/rdk_unit_test.yml @@ -35,6 +35,7 @@ jobs: run: | git clone https://github.com/rdkcentral/ThunderTools ThunderTools --branch ${{ env.THUNDER_REF }} git clone https://github.com/rdkcentral/Thunder Thunder --branch ${{ env.THUNDER_REF }} + git clone https://github.com/rdkcentral/ThunderInterfaces ThunderInterfaces --branch ${{ env.THUNDER_REF }} - name: Checkout networkmanager uses: actions/checkout@v3 @@ -68,6 +69,15 @@ jobs: && cmake --build build/Thunder --target install -j8 + - name: ThunderInterfaces + run: > + cmake + -S "${{github.workspace}}/ThunderInterfaces" -B build/ThunderInterfaces + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + && + cmake --build build/ThunderInterfaces --target install -j8 + - name: Generate IARM headers run: | touch install/usr/lib/libIARMBus.so diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 6a2cd97da..518bb8e16 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -276,37 +276,6 @@ ] } }, - "SetPrimaryInterface":{ - "summary": "Sets the primary/default interface for the device. This call fails if the interface is not enabled.", - "events":{ - "onActiveInterfaceChange" : "Triggered when device’s default interface changed.", - "onInterfaceStateChange" : "Triggered when interface’s state changed", - "onAddressChange" : "Triggered when the device connects to router.", - "onInternetStatusChange" : "Triggered when each IP address is lost or acquired." - }, - "params": { - "type":"object", - "properties": { - "interface": { - "$ref": "#/definitions/interface" - } - }, - "required": [ - "interface" - ] - }, - "result": { - "type": "object", - "properties": { - "success": { - "$ref": "#/definitions/success" - } - }, - "required": [ - "success" - ] - } - }, "SetInterfaceState":{ "summary": "Enable or disable the specified interface", "events":{ @@ -1393,7 +1362,7 @@ } }, "onActiveInterfaceChange":{ - "summary": "Triggered when the primary/active interface changes, regardless if it's from a system operation or through the `SetPrimaryInterface` method.", + "summary": "Triggered when the primary/active interface changes", "params": { "type": "object", "properties": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index e420634de..c2b50ad83 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -76,7 +76,6 @@ NetworkManager interface methods: | [GetLogLevel](#method.GetLogLevel) | Get Log level that is currently used | | [GetAvailableInterfaces](#method.GetAvailableInterfaces) | Get device supported list of available interface including their state | | [GetPrimaryInterface](#method.GetPrimaryInterface) | Gets the primary/default network interface for the device | -| [SetPrimaryInterface](#method.SetPrimaryInterface) | Sets the primary/default interface for the device | | [SetInterfaceState](#method.SetInterfaceState) | Enable or disable the specified interface | | [GetInterfaceState](#method.GetInterfaceState) | Gets the current Status of the specified interface | | [GetIPSettings](#method.GetIPSettings) | Gets the IP setting for the given interface | @@ -294,54 +293,6 @@ This method takes no parameters. } ``` - -## *SetPrimaryInterface [method](#head.Methods)* - -Sets the primary/default interface for the device. This call fails if the interface is not enabled. - -Also see: [onActiveInterfaceChange](#event.onActiveInterfaceChange), [onInterfaceStateChange](#event.onInterfaceStateChange), [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) - -### Parameters - -| Name | Type | Description | -| :-------- | :-------- | :-------- | -| params | object | | -| params.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | - -### Result - -| Name | Type | Description | -| :-------- | :-------- | :-------- | -| result | object | | -| result.success | boolean | Whether the request succeeded | - -### Example - -#### Request - -```json -{ - "jsonrpc": "2.0", - "id": 42, - "method": "org.rdk.NetworkManager.1.SetPrimaryInterface", - "params": { - "interface": "wlan0" - } -} -``` - -#### Response - -```json -{ - "jsonrpc": "2.0", - "id": 42, - "result": { - "success": true - } -} -``` - ## *SetInterfaceState [method](#head.Methods)* @@ -1729,7 +1680,7 @@ NetworkManager interface events: | :-------- | :-------- | | [onInterfaceStateChange](#event.onInterfaceStateChange) | Triggered when an interface state is changed | | [onAddressChange](#event.onAddressChange) | Triggered when an IP Address is assigned or lost | -| [onActiveInterfaceChange](#event.onActiveInterfaceChange) | Triggered when the primary/active interface changes, regardless if it's from a system operation or through the `SetPrimaryInterface` method | +| [onActiveInterfaceChange](#event.onActiveInterfaceChange) | Triggered when the primary/active interface changes | | [onInternetStatusChange](#event.onInternetStatusChange) | Triggered when internet connection state changed | | [onAvailableSSIDs](#event.onAvailableSSIDs) | Triggered when scan completes or when scan cancelled | | [onWiFiStateChange](#event.onWiFiStateChange) | Triggered when WIFI connection state get changed | @@ -1803,7 +1754,7 @@ Triggered when an IP Address is assigned or lost. ## *onActiveInterfaceChange [event](#head.Notifications)* -Triggered when the primary/active interface changes, regardless if it's from a system operation or through the `SetPrimaryInterface` method. +Triggered when the primary/active interface changes. ### Parameters diff --git a/interface/INetworkManager.h b/interface/INetworkManager.h index 0064587ce..65c982a27 100644 --- a/interface/INetworkManager.h +++ b/interface/INetworkManager.h @@ -198,8 +198,6 @@ namespace WPEFramework /* @brief Get the Primary Interface used for external world communication */ virtual uint32_t GetPrimaryInterface (string& interface /* @out */) = 0; - /* @brief Set the Primary Interface used for external world communication */ - virtual uint32_t SetPrimaryInterface (const string& interface/* @in */) = 0; /* @brief Enable/Disable the given interface */ virtual uint32_t SetInterfaceState (const string& interface /* @in */, const bool enabled /* @in */) = 0; diff --git a/legacy/LegacyNetworkAPIs.cpp b/legacy/LegacyNetworkAPIs.cpp index 4d4d3eb2a..bc0a669ed 100644 --- a/legacy/LegacyNetworkAPIs.cpp +++ b/legacy/LegacyNetworkAPIs.cpp @@ -92,28 +92,6 @@ namespace WPEFramework _gNWInstance = nullptr; } - void Network::activatePrimaryPlugin() - { - uint32_t result = Core::ERROR_ASYNC_FAILED; - string callsign(NETWORK_MANAGER_CALLSIGN); - Core::Event event(false, true); - Core::IWorkerPool::Instance().Submit(Core::ProxyType(Core::ProxyType::Create([&]() { - auto interface = m_service->QueryInterfaceByCallsign(callsign); - if (interface == nullptr) { - result = Core::ERROR_UNAVAILABLE; - NMLOG_WARNING("no IShell for %s", callsign.c_str()); - } else { - NMLOG_INFO("Activating %s", callsign.c_str()); - result = interface->Activate(PluginHost::IShell::reason::REQUESTED); - interface->Release(); - } - event.SetEvent(); - }))); - event.Lock(); - - return; - } - const string Network::Initialize(PluginHost::IShell* service ) { m_service = service; @@ -152,28 +130,21 @@ namespace WPEFramework NMLOG_INFO("Dependency Plugin '%s' Ready", callsign.c_str()); break; } - else - { - NMLOG_INFO("Lets attempt to activate the Plugin '%s', retry %d", callsign.c_str(), retry+1); - activatePrimaryPlugin(); - } usleep(500*1000); } while(retry++ < 5); - if(PluginHost::IShell::state::ACTIVATED == state) { Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); m_networkmanager = make_shared >(_T(NETWORK_MANAGER_CALLSIGN), _T("org.rdk.Network"), query); + subscribeToEvents(); } else message = _T("dependency Plugin 'NetworkManager' not Ready"); - interface->Release(); } else message = _T("Failed to get IShell for 'NetworkManager'"); - return message; } @@ -411,24 +382,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { uint32_t Network::setDefaultInterface(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); - uint32_t rc = Core::ERROR_GENERAL; - string givenInterface = parameters["interface"].String(); - const string interface = getInterfaceTypeToName(givenInterface); - - if ("wlan0" != interface && "eth0" != interface) - { - rc = Core::ERROR_BAD_REQUEST; - return rc; - } - - auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); - if (_nwmgr) - { - rc = _nwmgr->SetPrimaryInterface(interface); - _nwmgr->Release(); - } - else - rc = Core::ERROR_UNAVAILABLE; + uint32_t rc = Core::ERROR_NONE; returnJson(rc); } diff --git a/legacy/LegacyNetworkAPIs.h b/legacy/LegacyNetworkAPIs.h index 72b82ddb5..e8b5764ed 100644 --- a/legacy/LegacyNetworkAPIs.h +++ b/legacy/LegacyNetworkAPIs.h @@ -50,7 +50,6 @@ namespace WPEFramework { void registerLegacyMethods(void); void unregisterLegacyMethods(void); void subscribeToEvents(void); - void activatePrimaryPlugin(); uint32_t internalGetIPSettings(const JsonObject& parameters, JsonObject& response); string getInterfaceNameToType(const string & interface); string getInterfaceTypeToName(const string & interface); diff --git a/legacy/LegacyWiFiManagerAPIs.cpp b/legacy/LegacyWiFiManagerAPIs.cpp index fcae4efb8..463707e35 100644 --- a/legacy/LegacyWiFiManagerAPIs.cpp +++ b/legacy/LegacyWiFiManagerAPIs.cpp @@ -126,28 +126,6 @@ namespace WPEFramework _gWiFiInstance = nullptr; } - void WiFiManager::activatePrimaryPlugin() - { - uint32_t result = Core::ERROR_ASYNC_FAILED; - string callsign(NETWORK_MANAGER_CALLSIGN); - Core::Event event(false, true); - Core::IWorkerPool::Instance().Submit(Core::ProxyType(Core::ProxyType::Create([&]() { - auto interface = m_service->QueryInterfaceByCallsign(callsign); - if (interface == nullptr) { - result = Core::ERROR_UNAVAILABLE; - NMLOG_WARNING("no IShell for %s", callsign.c_str()); - } else { - NMLOG_INFO("Activating %s", callsign.c_str()); - result = interface->Activate(PluginHost::IShell::reason::REQUESTED); - interface->Release(); - } - event.SetEvent(); - }))); - event.Lock(); - - return; - } - const string WiFiManager::Initialize(PluginHost::IShell* service ) { m_service = service; @@ -189,14 +167,8 @@ namespace WPEFramework NMLOG_INFO("Dependency Plugin '%s' Ready", callsign.c_str()); break; } - else - { - NMLOG_INFO("Lets attempt to activate the Plugin '%s', retry %d", callsign.c_str(), retry+1); - activatePrimaryPlugin(); - } usleep(500*1000); } while(retry++ < 5); - if(PluginHost::IShell::state::ACTIVATED == state) { Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); diff --git a/legacy/LegacyWiFiManagerAPIs.h b/legacy/LegacyWiFiManagerAPIs.h index c6c594e9d..90d817ca0 100644 --- a/legacy/LegacyWiFiManagerAPIs.h +++ b/legacy/LegacyWiFiManagerAPIs.h @@ -87,7 +87,6 @@ namespace WPEFramework { void subscribeToEvents(void); static std::string getInterfaceMapping(const std::string &interface); static bool ErrorCodeMapping(const uint32_t ipvalue , uint32_t &opvalue); - void activatePrimaryPlugin(); private: PluginHost::IShell* m_service; diff --git a/plugin/NetworkManager.cpp b/plugin/NetworkManager.cpp index 18e636750..250b3e06b 100644 --- a/plugin/NetworkManager.cpp +++ b/plugin/NetworkManager.cpp @@ -84,12 +84,6 @@ namespace WPEFramework // Still running inside the main WPEFramework process - the child process will have now been spawned and registered if necessary if (_networkManager != nullptr) { - SYSLOG(Logging::Startup, (_T("Configuring NetworkManager"))); - if (_networkManager->Configure(service) != Core::ERROR_NONE) - { - SYSLOG(Logging::Shutdown, (_T("NetworkManager failed to configure"))); - message = _T("NetworkManager failed to configure"); - } // Set the plugin log level Exchange::INetworkManager::Logging _loglevel; @@ -100,6 +94,20 @@ namespace WPEFramework SYSLOG(Logging::Startup, (_T("Registering Notification to NetworkManager"))); _networkManager->Register(&_notification); + SYSLOG(Logging::Startup, (_T("Configuring NetworkManager"))); + Exchange::IConfiguration* config = _networkManager->QueryInterface(); + if (config != nullptr) { + if(config->Configure(service) != Core::ERROR_NONE) + { + SYSLOG(Logging::Shutdown, (_T("NetworkManager failed to configure"))); + message = _T("NetworkManager failed to configure"); + } + else + { + SYSLOG(Logging::Startup, (_T("Configuring successful"))); + } + config->Release(); + } // Register all custom JSON-RPC methods SYSLOG(Logging::Startup, (_T("Registering JSONRPC Methods"))); RegisterAllMethods(); diff --git a/plugin/NetworkManager.h b/plugin/NetworkManager.h index 1d768bfee..98007e8c7 100644 --- a/plugin/NetworkManager.h +++ b/plugin/NetworkManager.h @@ -22,6 +22,7 @@ #include "Module.h" #include "INetworkManager.h" +#include #include "NetworkManagerLogger.h" #include @@ -236,7 +237,6 @@ namespace WPEFramework uint32_t GetLogLevel (const JsonObject& parameters, JsonObject& response); uint32_t GetAvailableInterfaces (const JsonObject& parameters, JsonObject& response); uint32_t GetPrimaryInterface (const JsonObject& parameters, JsonObject& response); - uint32_t SetPrimaryInterface (const JsonObject& parameters, JsonObject& response); uint32_t GetInterfaceState(const JsonObject& parameters, JsonObject& response); uint32_t SetInterfaceState(const JsonObject& parameters, JsonObject& response); uint32_t GetIPSettings(const JsonObject& parameters, JsonObject& response); diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 7f85b2157..d6077e8d4 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -30,6 +30,7 @@ using namespace std; #include "INetworkManager.h" +#include #include "NetworkManagerLogger.h" #include "NetworkManagerConnectivity.h" #include "NetworkManagerStunClient.h" @@ -49,7 +50,7 @@ namespace WPEFramework { namespace Plugin { - class NetworkManagerImplementation : public Exchange::INetworkManager + class NetworkManagerImplementation : public Exchange::INetworkManager, public Exchange::IConfiguration { enum NetworkEvents { @@ -177,6 +178,7 @@ namespace WPEFramework BEGIN_INTERFACE_MAP(NetworkManagerImplementation) INTERFACE_ENTRY(Exchange::INetworkManager) + INTERFACE_ENTRY(Exchange::IConfiguration) END_INTERFACE_MAP // Handle Notification registration/removal @@ -190,8 +192,6 @@ namespace WPEFramework /* @brief Get the active Interface used for external world communication */ uint32_t GetPrimaryInterface (string& interface /* @out */) override; - /* @brief Set the active Interface used for external world communication */ - uint32_t SetPrimaryInterface (const string& interface/* @in */) override; /* @brief Enable/Disable the given interface */ uint32_t SetInterfaceState(const string& interface/* @in */, const bool isEnabled/* @in */) override; diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index e2a1a9d90..07a4fc301 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -56,7 +56,6 @@ namespace WPEFramework Register("SetLogLevel", &NetworkManager::SetLogLevel, this); Register("GetAvailableInterfaces", &NetworkManager::GetAvailableInterfaces, this); Register("GetPrimaryInterface", &NetworkManager::GetPrimaryInterface, this); - Register("SetPrimaryInterface", &NetworkManager::SetPrimaryInterface, this); Register("SetInterfaceState", &NetworkManager::SetInterfaceState, this); Register("GetInterfaceState", &NetworkManager::GetInterfaceState, this); Register("GetIPSettings", &NetworkManager::GetIPSettings, this); @@ -93,7 +92,6 @@ namespace WPEFramework Unregister("SetLogLevel"); Unregister("GetAvailableInterfaces"); Unregister("GetPrimaryInterface"); - Unregister("SetPrimaryInterface"); Unregister("SetInterfaceState"); Unregister("GetInterfaceState"); Unregister("GetIPSettings"); @@ -212,26 +210,6 @@ namespace WPEFramework returnJson(rc); } - uint32_t NetworkManager::SetPrimaryInterface (const JsonObject& parameters, JsonObject& response) - { - LOG_INPARAM(); - uint32_t rc = Core::ERROR_GENERAL; - string interface = parameters["interface"].String(); - - if ("wlan0" != interface && "eth0" != interface) - { - rc = Core::ERROR_BAD_REQUEST; - return rc; - } - - if (_networkManager) - rc = _networkManager->SetPrimaryInterface(interface); - else - rc = Core::ERROR_UNAVAILABLE; - - returnJson(rc); - } - uint32_t NetworkManager::SetInterfaceState(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 404ee3089..1cc5b761d 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -222,15 +222,6 @@ namespace WPEFramework return rc; } - /* @brief Set the active Interface used for external world communication */ - uint32_t NetworkManagerImplementation::SetPrimaryInterface (const string& interface/* @in */) - { - uint32_t rc = Core::ERROR_GENERAL; - if(wifi->setPrimaryInterface(interface)) - rc = Core::ERROR_NONE; - return rc; - } - uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) { diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp index e22381c5b..ce2930596 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp @@ -127,15 +127,6 @@ namespace WPEFramework } } - uint32_t NetworkManagerImplementation::SetPrimaryInterface (const string& interface/* @in */) - { - uint32_t rc = Core::ERROR_GENERAL; - if(_nmGdbusClient->setPrimaryInterface(interface)) - rc = Core::ERROR_NONE; - else - NMLOG_ERROR("SetPrimaryInterface failed"); - return rc; - } uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) { uint32_t rc = Core::ERROR_GENERAL; diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 33bab9c34..737f5fb56 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -889,38 +889,6 @@ namespace WPEFramework return rc; } - /* @brief Set the active Interface used for external world communication */ - uint32_t NetworkManagerImplementation::SetPrimaryInterface (const string& interface/* @in */) - { - LOG_ENTRY_FUNCTION(); - uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - IARM_BUS_NetSrvMgr_Iface_EventData_t iarmData = { 0 }; - iarmData.persist = true; - - /* Netsrvmgr returns eth0 & wlan0 as primary interface but when we want to set., we must set ETHERNET or WIFI*/ - //TODO: Fix netsrvmgr to accept eth0 & wlan0 - if ("wlan0" == interface) - strncpy(iarmData.setInterface, "WIFI", INTERFACE_SIZE); - else if ("eth0" == interface) - strncpy(iarmData.setInterface, "ETHERNET", INTERFACE_SIZE); - else - { - rc = Core::ERROR_BAD_REQUEST; - return rc; - } - - if (IARM_RESULT_SUCCESS == IARM_Bus_Call (IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_setDefaultInterface, (void *)&iarmData, sizeof(iarmData))) - { - NMLOG_INFO ("Call to %s for %s success", IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_setDefaultInterface); - rc = Core::ERROR_NONE; - } - else - { - NMLOG_ERROR ("Call to %s for %s failed", IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_setDefaultInterface); - } - return rc; - } - uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enable /* @in */) { LOG_ENTRY_FUNCTION(); diff --git a/tests/unittest/test_NetworkManager.cpp b/tests/unittest/test_NetworkManager.cpp index 09fdf0edd..1ecf60b43 100644 --- a/tests/unittest/test_NetworkManager.cpp +++ b/tests/unittest/test_NetworkManager.cpp @@ -74,7 +74,6 @@ TEST_F(NetworkManagerTest, TestFunShouldExist) EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetLogLevel"))); EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetAvailableInterfaces"))); EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetPrimaryInterface"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetPrimaryInterface"))); EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetInterfaceState"))); EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetInterfaceState"))); EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetIPSettings"))); @@ -115,12 +114,6 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface) EXPECT_EQ(response, string("")); } -TEST_F(NetworkManagerTest, SetPrimaryInterface) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("SetPrimaryInterface"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - TEST_F(NetworkManagerTest, GetInterfaceState) { EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetInterfaceState"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); diff --git a/tools/plugincli/NetworkManagerGdbusTest.cpp b/tools/plugincli/NetworkManagerGdbusTest.cpp index d37e411a9..ce972237f 100644 --- a/tools/plugincli/NetworkManagerGdbusTest.cpp +++ b/tools/plugincli/NetworkManagerGdbusTest.cpp @@ -86,12 +86,11 @@ void displayMenu() std::cout << "9. Get WiFi State" << std::endl; std::cout << "10. Get WiFi Signal Strength" << std::endl; std::cout << "11. GetAvailableInterface" << std::endl; - std::cout << "12. SetPrimaryInterface" << std::endl; - std::cout << "13. SetInterfaceState" << std::endl; - std::cout << "14. SetIPSettings" << std::endl; - std::cout << "15. GetPrimaryInterface" << std::endl; - std::cout << "16. GetInterfaceState" << std::endl; - std::cout << "17. GetIPSettings" << std::endl; + std::cout << "12. SetInterfaceState" << std::endl; + std::cout << "13. SetIPSettings" << std::endl; + std::cout << "14. GetPrimaryInterface" << std::endl; + std::cout << "15. GetInterfaceState" << std::endl; + std::cout << "16. GetIPSettings" << std::endl; std::cout << "0. Exit" << std::endl; std::cout << "-------------------------------------" << std::endl; } @@ -296,21 +295,6 @@ int main() break; } case 12: { - std::string interface; - std::cout << "Enter interface name to set as primary: "; - std::cin.ignore(); - std::getline(std::cin, interface); - - if(nmClient->setPrimaryInterface(interface)){ - NMLOG_INFO("setPrimaryInterface successful"); - } - else - { - NMLOG_ERROR("Failed to set Primary Interface"); - } - break; - } - case 13: { std::string interface; std::string input; bool enable; @@ -330,7 +314,7 @@ int main() } break; } - case 14: { + case 13: { std::string interface; std::string ipVersion; std::string input; @@ -387,7 +371,7 @@ int main() } break; } - case 15: { + case 14: { std::string interface; if(nmClient->getPrimaryInterface(interface)){ @@ -399,7 +383,7 @@ int main() } break; } - case 16: { + case 15: { std::string interface; bool isEnabled; std::cout << "Enter interface: "; @@ -414,7 +398,7 @@ int main() } break; } - case 17: { + case 16: { std::string interface; std::string ipVersion; Exchange::INetworkManager::IPAddress result; From 48f7020490d118b5495fd418f5c7fe2a6ab0d3be Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 3 Jul 2025 17:00:04 -0400 Subject: [PATCH 151/271] RDKTV-37469, RDKTV-37468 - Increase in offline toaster markers (#184) Reason for change: The issue is because of the logic failure is in accessing the InterfaceList Iterator returned by the Thunder IIteratorType. Addressed the same by resetting the list with Reset() call. Also moved the interface count while loop inside the return code and NULL pointer check Test Procedure: Deep sleep to wake up scenario Priority:P1 Risks: Medium Signed-off-by: Gururaaja E S R --- plugin/rdk/NetworkManagerRDKProxy.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 737f5fb56..26726feeb 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -674,25 +674,22 @@ namespace WPEFramework { // check the connection state and post event Exchange::INetworkManager::IInterfaceDetailsIterator* _interfaces{}; - Exchange::INetworkManager::IInterfaceDetailsIterator* _tmpInterfaces{}; uint32_t rc = GetAvailableInterfaces(_interfaces); - _tmpInterfaces = _interfaces; size_t interfaceCount = 0; - Exchange::INetworkManager::InterfaceDetails tmpIface{}; - - while (_tmpInterfaces->Next(tmpIface)) - { - if(tmpIface.enabled && tmpIface.connected) - { - interfaceCount++; - } - } + Exchange::INetworkManager::InterfaceDetails iface{}; if (Core::ERROR_NONE == rc) { if (_interfaces != nullptr) { - Exchange::INetworkManager::InterfaceDetails iface{}; + while (_interfaces->Next(iface)) + { + if(iface.enabled && iface.connected) + { + interfaceCount++; + } + } + _interfaces->Reset(0); while (_interfaces->Next(iface) == true) { if((interfaceCount == 2 && "eth0" == iface.name) || interfaceCount == 1) From 140c23504df45e8c5a6ffd4331341ab8d1a1bcd5 Mon Sep 17 00:00:00 2001 From: Arun P Madhavan <54109113+arun-madhavan-013@users.noreply.github.com> Date: Mon, 7 Jul 2025 16:00:16 -0400 Subject: [PATCH 152/271] RDKEMW-2939: add param validation (#185) * RDKEMW-2939: add param validation Reason for Change: ping succeeds with invalid ipversion - {"jsonrpc":"2.0","id":42,"method":"org.rdk.NetworkManager.1.Ping","params":{"endpoint":"142.250.192.78","ipversion":"invalid"}} * RDKEMW-2939: param validation for SetStunEndPoint Reason for Change: invalid param produces SUCCESS ``` {"jsonrpc":"2.0","id":42,"method":"org.rdk.NetworkManager.1.SetStunEndpoint"} {"jsonrpc":"2.0","id":42,"method":"org.rdk.NetworkManager.1.SetStunEndpoint","params":{"port":0}} ``` * Clean the temporary file --- plugin/NetworkManagerImplementation.cpp | 37 ++++++++++++++++++++----- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index f7df9e692..6e2859ec0 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -213,6 +213,19 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::SetStunEndpoint (string const endpoint /* @in */, const uint32_t port /* @in */, const uint32_t bindTimeout /* @in */, const uint32_t cacheTimeout /* @in */) { LOG_ENTRY_FUNCTION(); + + // If no parameters are provided, return error + if (endpoint.empty() && port == 0 && bindTimeout == 0 && cacheTimeout == 0) { + NMLOG_WARNING("No parameters provided to update STUN Endpoint"); + return Core::ERROR_BAD_REQUEST; + } + + // If port is provided but is 0, reject as invalid + if (port == 0 && !endpoint.empty()) { + NMLOG_WARNING("Invalid STUN port: 0"); + return Core::ERROR_BAD_REQUEST; + } + if (!endpoint.empty()) m_stunEndpoint = endpoint; @@ -260,7 +273,7 @@ namespace WPEFramework return Core::ERROR_NONE; } - /* @brief Get Internet Connectivty Status */ + /* @brief Get Internet Connectivty Status */ uint32_t NetworkManagerImplementation::IsConnectedToInternet(string &ipversion /* @inout */, string &interface /* @inout */, InternetStatus &result /* @out */) { LOG_ENTRY_FUNCTION(); @@ -300,7 +313,7 @@ namespace WPEFramework return Core::ERROR_NONE; } - /* @brief Get Authentication URL if the device is behind Captive Portal */ + /* @brief Get Authentication URL if the device is behind Captive Portal */ uint32_t NetworkManagerImplementation::GetCaptivePortalURI(string &uri /* @out */) const { LOG_ENTRY_FUNCTION(); @@ -363,18 +376,23 @@ namespace WPEFramework /* @brief Request for ping and get the response in as event. The GUID used in the request will be returned in the event. */ uint32_t NetworkManagerImplementation::Ping (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const uint16_t timeOutInSeconds /* @in */, const string guid /* @in */, string& response /* @out */) - { + { char cmd[100] = ""; string tempResult = ""; + if (endpoint.empty() || (ipversion != "IPv4" && ipversion != "IPv6")) + { + NMLOG_WARNING("Invalid arguments: endpoint=%s, ipversion=%s", endpoint.c_str(), ipversion.c_str()); + return Core::ERROR_BAD_REQUEST; + } if(0 == strcasecmp("IPv6", ipversion.c_str())) - { + { snprintf(cmd, sizeof(cmd), "ping6 -c %d -W %d -i 0.2 '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); } else - { + { snprintf(cmd, sizeof(cmd), "ping -c %d -W %d -i 0.2 '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); } - + NMLOG_DEBUG ("The Command is %s", cmd); string commandToExecute(cmd); executeExternally(NETMGR_PING, commandToExecute, tempResult); @@ -392,6 +410,11 @@ namespace WPEFramework { char cmd[256] = ""; string tempResult = ""; + if (endpoint.empty() || (ipversion != "IPv4" && ipversion != "IPv6")) + { + NMLOG_WARNING("Invalid arguments: endpoint=%s, ipversion=%s", endpoint.c_str(), ipversion.c_str()); + return Core::ERROR_BAD_REQUEST; + } if(0 == strcasecmp("IPv6", ipversion.c_str())) { snprintf(cmd, 256, "traceroute6 -w 3 -m 6 -q %d %s 64 2>&1", noOfRequest, endpoint.c_str()); @@ -423,7 +446,7 @@ namespace WPEFramework pipe = popen(commandToExecute.c_str(), "r"); if (pipe == NULL) - { + { NMLOG_INFO ("%s: failed to open file '%s' for read mode with result: %s", __FUNCTION__, commandToExecute.c_str(), strerror(errno)); return; } From 7e29691911922bc2e411f64e818da515248e8969 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Tue, 8 Jul 2025 23:55:13 +0530 Subject: [PATCH 153/271] RDKEMW-5550 Multiple IP address change events with IPv6/IPV4 after network link up (#181) * RDKEMW-5550 Bring Multiple IP address change events with IPv6/IPV4 after network link up Issue Fix --- plugin/rdk/NetworkManagerRDKProxy.cpp | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 26726feeb..fd9fc2cee 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -19,6 +19,7 @@ #include "NetworkManagerImplementation.h" #include "NetworkManagerConnectivity.h" #include "libIBus.h" +#include using namespace WPEFramework; using namespace WPEFramework::Plugin; @@ -467,6 +468,35 @@ namespace WPEFramework return 0; /* WIFI_SECURITY_NONE */ } + static bool alreadySentRecently(std::string &interface) + { + // Use std::chrono::steady_clock for measuring elapsed time. + // steady_clock is monotonic and not affected by system time changes (e.g., NTP synchronization), + // ensuring timing is reliable even if the system clock is adjusted. + static std::chrono::steady_clock::time_point eth_last_time = std::chrono::steady_clock::time_point{}; + static std::chrono::steady_clock::time_point wlan_last_time = std::chrono::steady_clock::time_point{}; + auto now = std::chrono::steady_clock::now(); + + if (interface == "eth0") + { + if (eth_last_time != std::chrono::steady_clock::time_point{} && + std::chrono::duration_cast(now - eth_last_time).count() < 500) { // 500 milliseconds threshold + return true; + } + eth_last_time = now; + } + else if (interface == "wlan0") + { + if (wlan_last_time != std::chrono::steady_clock::time_point{} && + std::chrono::duration_cast(now - wlan_last_time).count() < 500) { // 500 milliseconds threshold + return true; + } + wlan_last_time = now; + } + + return false; + } + void NetworkManagerInternalEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) { LOG_ENTRY_FUNCTION(); @@ -523,6 +553,11 @@ namespace WPEFramework if(interface == "eth0" || interface == "wlan0") { string ipversion("IPv4"); Exchange::INetworkManager::IPStatus status = Exchange::INetworkManager::IP_LOST; + if(!e->is_ipv6 && alreadySentRecently(interface)) + { + NMLOG_INFO("Already sent recently, skipping IP address change event for %s", interface.c_str()); + break; + } if (e->is_ipv6) ipversion = "IPv6"; From 2c50c78583bb8efbc0b1396952fc9f10af0f930a Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Tue, 8 Jul 2025 14:31:44 -0400 Subject: [PATCH 154/271] Release of 0.21.0 Release of 0.21.0 --- CHANGELOG.md | 7 +++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cba04b21e..3ee312e68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,13 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.21.0] - 2025-07-08 +### Fixed +- Fixed WiFi On/Off toggling failure +- Fixed the bug in IPAddress availability check upon wake-up +- Removed the SetPrimartInterface method +- Added input param validation for Ping and Stun methods + ## [0.20.0] - 2025-06-20 ### Fixed - Fixed the bug in Resetting of Manual IPv4 diff --git a/CMakeLists.txt b/CMakeLists.txt index aa16eea82..7b2475a2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 20) +set(VERSION_MINOR 21) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 518bb8e16..4fac73cc5 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.20.0" + "version": "0.21.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index c2b50ad83..79b313db9 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.20.0** +**Version: 0.21.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.20.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.21.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 59fe0dae9fb092499629052b84f5a3af132572c2 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 14 Jul 2025 09:37:47 -0400 Subject: [PATCH 155/271] RDKEMW-6063 - OnWiFiStateChanged Event is not posted appropriately wlan0 LINK_UP (#187) Reason for change: Posting the WIFI connected event when we receive the state as NM_DEVICE_STATE_IP_CONFIG from gnome networkmanager so that we can avoid the delay in postin the events onWiFiStateChanged Test Procedure: Network reset with UI Priority:P1 Risks: Medium --- plugin/gnome/NetworkManagerGnomeEvents.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 078a21189..2ba50ff3b 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -147,6 +147,7 @@ namespace WPEFramework case NM_DEVICE_STATE_IP_CONFIG: wifiState = "NM_DEVICE_STATE_IP_CONFIG"; GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_UP, nmUtils::wlanIface()); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTED); break; case NM_DEVICE_STATE_IP_CHECK: wifiState = "NM_DEVICE_STATE_IP_CHECK"; From bb3298fcdc4266ab8a6bb448efdef40d75b4af45 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 14 Jul 2025 09:41:17 -0400 Subject: [PATCH 156/271] RDKTV-37660 - TVOffline marker seen after waking up due to Roam event (#188) Reason for change: The issue is happening because of the race condition happening between the 2 threads(connectivityMonitorFunction and the main thread in which switchToInitialCheck executes). Because of the race condition, switchToInitialCheck() was triggered before the m_wlanConnected was set to true. So the execution goes inside [else if (_instance != nullptr && !_instance->m_ethConnected && !_instance->m_wlanConnected)] and no event is actually posted as InitialRetryCount was already set to 1. Made changes to ReportInterfaceStateChange() to set m_wlanConnected to true when the interface is UP and then switchToInitialCheck() is triggered. Test Procedure: Deep sleep to wake up scenario Priority:P1 Risks: Medium Signed-off-by: Gururaaja E S R --- plugin/NetworkManagerImplementation.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 6e2859ec0..93e1de46a 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -628,9 +628,11 @@ namespace WPEFramework /* Only the Ethernet connection status is changing here. The WiFi status is updated in the WiFi state callback. */ if(Exchange::INetworkManager::INTERFACE_LINK_UP == state) { - connectivityMonitor.switchToInitialCheck(); if(interface == "eth0") m_ethConnected.store(true); + else if(interface == "wlan0") + m_wlanConnected = true; + connectivityMonitor.switchToInitialCheck(); } _notificationLock.Lock(); From 8d2f75d9368b97e11de3066a679c5dbed47b1523 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Mon, 14 Jul 2025 10:28:36 -0400 Subject: [PATCH 157/271] Release of 0.22.0 Release of 0.22.0 --- CHANGELOG.md | 5 +++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ee312e68..81279c2be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.22.0] - 2025-07-14 +### Fixed +- Fixed trigger point for the connectivity monitoring +- Posting onWiFiStateChange Event when link-up for wifi event is received. + ## [0.21.0] - 2025-07-08 ### Fixed - Fixed WiFi On/Off toggling failure diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b2475a2e..d05577c5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 21) +set(VERSION_MINOR 22) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 4fac73cc5..de469b887 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.21.0" + "version": "0.22.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 79b313db9..fd7a1b44c 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.21.0** +**Version: 0.22.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.21.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.22.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 11f570e3c384a49f8d7a18abca26a30a0421988a Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 15 Jul 2025 09:45:18 -0400 Subject: [PATCH 158/271] RDKEMW-6097 - Removal of log GetIPSettings : ipversion error IPv4/IPv6 (#189) Reason for change - Removal of unnecessary log to avoid log flooding --- plugin/gnome/NetworkManagerGnomeProxy.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 1cc5b761d..bb18d9a62 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -537,8 +537,6 @@ namespace WPEFramework } } } - else - NMLOG_WARNING("ipversion error IPv4/IPv6"); if(result.ipaddress.empty()) { result.autoconfig = true; From 7a3c7c6aa403ac46644b5db6cca4545685a300d3 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 24 Jul 2025 21:10:59 +0530 Subject: [PATCH 159/271] RDKEMW-6189, RDKEMW-6300: Fix RemoveKnownSSID response and address memory leak in NetworkManager (#197) * RDKEMW-6300 fix for memory leak in NetworkManager * updated the log line --- plugin/NetworkManagerSecretAgent.cpp | 10 +- plugin/gnome/NetworkManagerGnomeProxy.cpp | 6 +- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 131 +++++++++++++----- .../gnome/gdbus/NetworkManagerGdbusEvent.cpp | 6 + 4 files changed, 111 insertions(+), 42 deletions(-) diff --git a/plugin/NetworkManagerSecretAgent.cpp b/plugin/NetworkManagerSecretAgent.cpp index dad4a1c20..aa6436465 100644 --- a/plugin/NetworkManagerSecretAgent.cpp +++ b/plugin/NetworkManagerSecretAgent.cpp @@ -233,10 +233,14 @@ namespace WPEFramework &error); if (!agentRegID) { - NMLOG_ERROR("Failed to register object: %s", error->message); - g_error_free(error); + NMLOG_ERROR("Failed to register object:"); + if (error != NULL) + { + NMLOG_ERROR("Error : %s", error->message); + g_error_free(error); + } g_dbus_node_info_unref(node_info); - return ; + return; } NMLOG_INFO("Object registered with ID: %u", agentRegID); diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index bb18d9a62..0a48feb38 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -80,8 +80,10 @@ namespace WPEFramework // initialize the NMClient object client = nm_client_new(NULL, &error); if (client == NULL) { - NMLOG_FATAL("Error initializing NMClient: %s", error->message); - g_error_free(error); + if (error) { + NMLOG_FATAL("Error initializing NMClient: %s", error->message); + g_error_free(error); + } return; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 011e977f0..49454ba87 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -52,8 +52,10 @@ namespace WPEFramework m_client = nm_client_new(NULL, &error); if (!m_client || !m_loop) { - NMLOG_ERROR("Could not connect to NetworkManager: %s.", error->message); - g_error_free(error); + if (error) { + NMLOG_ERROR("Could not connect to NetworkManager: %s.", error->message); + g_error_free(error); + } return false; } return true; @@ -337,23 +339,28 @@ namespace WPEFramework static void disconnectCb(GObject *object, GAsyncResult *result, gpointer user_data) { - NMDevice *device = NM_DEVICE(object); - GError *error = NULL; - wifiManager *_wifiManager = (static_cast(user_data)); + NMDevice *device = NM_DEVICE(object); + GError *error = NULL; + wifiManager *_wifiManager = static_cast(user_data); NMLOG_DEBUG("Disconnecting... "); _wifiManager->m_isSuccess = true; - if (!nm_device_disconnect_finish(device, result, &error)) { - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - NMLOG_ERROR("Device '%s' (%s) disconnecting failed: %s", - nm_device_get_iface(device), - nm_object_get_path(NM_OBJECT(device)), - error->message); - g_error_free(error); - _wifiManager->quit(device); - _wifiManager->m_isSuccess = false; + if (!nm_device_disconnect_finish(device, result, &error)) + { + NMLOG_ERROR("device '%s' disconnect failed !", nm_device_get_iface(device)); + if(error != NULL) + { + if(g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + { + NMLOG_ERROR("something went wrong no matching gerror found !"); + } + else + { + NMLOG_ERROR("Device path '%s': %s", nm_object_get_path(NM_OBJECT(device)), error->message); + } + g_error_free(error); + } + _wifiManager->m_isSuccess = false; } _wifiManager->quit(device); } @@ -566,8 +573,12 @@ namespace WPEFramework NULL, &error)) { - NMLOG_ERROR("ca certificate add failed: %s", error->message); - g_error_free(error); + NMLOG_ERROR("ca certificate add failed"); + if(error != NULL) + { + NMLOG_ERROR("Error message %s", error->message); + g_error_free(error); + } return false; } @@ -577,8 +588,12 @@ namespace WPEFramework NULL, &error)) { - NMLOG_ERROR("client certificate add failed: %s", error->message); - g_error_free(error); + NMLOG_ERROR("client certificate add failed"); + if(error != NULL) + { + NMLOG_ERROR("Error message %s", error->message); + g_error_free(error); + } return false; } @@ -589,8 +604,12 @@ namespace WPEFramework NULL, &error)) { - NMLOG_ERROR("client private key add failed: %s", error->message); - g_error_free(error); + NMLOG_ERROR("client private key failed"); + if(error != NULL) + { + NMLOG_ERROR("Error message %s", error->message); + g_error_free(error); + } return false; } @@ -713,6 +732,9 @@ namespace WPEFramework NMLOG_ERROR("'%s' connection not found !", knowConnectionID.c_str()); } + if(knownConnection != NULL) + g_object_unref(knownConnection); + deleteClientConnection(); return m_isSuccess; } @@ -878,8 +900,10 @@ namespace WPEFramework ret = nm_remote_connection_update2_finish(remote_con, res, &error); if (!ret) { - NMLOG_ERROR("Error: %s.", error->message); - g_error_free(error); + if(error) { + NMLOG_ERROR("Error: %s.", error->message); + g_error_free(error); + } _wifiManager->m_isSuccess = false; NMLOG_ERROR("AddToKnownSSIDs failed"); } @@ -995,6 +1019,7 @@ namespace WPEFramework { NMConnection *m_connection = NULL; bool ssidSpecified = false; + bool connectionFound = false; if(!createClientNewConnection()) return false; @@ -1039,13 +1064,27 @@ namespace WPEFramework nm_remote_connection_delete(NM_REMOTE_CONNECTION(connection), NULL, &error); if(error) { NMLOG_ERROR("deleting connection failed %s", error->message); + g_error_free(error); + if(m_connection) + { + g_object_unref(m_connection); + m_connection = NULL; + } + break; // error break the loop and return false } else NMLOG_INFO("delete '%s' connection ...", connId); + connectionFound = true; + } + + if(m_connection) + { + g_object_unref(m_connection); + m_connection = NULL; } } - if(!m_connection) + if(!connectionFound) { if(ssidSpecified) NMLOG_WARNING("'%s' no such connection profile", ssid.c_str()); @@ -1054,7 +1093,9 @@ namespace WPEFramework } deleteClientConnection(); - return true; + // ssid is specified and connection is not found return false + // all other case return true, even if no wificonnection is found + return((ssidSpecified && !connectionFound)? false : true); } bool wifiManager::getKnownSSIDs(std::list& ssids) @@ -1201,8 +1242,10 @@ namespace WPEFramework GMainLoop *loop = static_cast(user_data); nm_client_add_and_activate_connection_finish(NM_CLIENT(client), result, &error); - if (error) + if (error) { NMLOG_ERROR("Failed to add/activate new connection: %s", error->message); + g_error_free(error); + } else NMLOG_INFO("WPS connection added/activated successfully"); g_main_loop_quit(loop); @@ -1236,6 +1279,7 @@ namespace WPEFramework nm_remote_connection_delete (NM_REMOTE_CONNECTION(connection), NULL, &error); if(error) { NMLOG_ERROR("deleting connection failed %s", error->message); + g_error_free(error); return false; } } @@ -1526,16 +1570,25 @@ namespace WPEFramework wifiManager *_wifiManager = static_cast(user_data); GError *error = nullptr; - if (!nm_client_dbus_set_property_finish(NM_CLIENT(object), result, &error)) { - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + if (!nm_client_dbus_set_property_finish(NM_CLIENT(object), result, &error)) + { + NMLOG_ERROR("Failed to set Managed property"); + if (error != nullptr) + { + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + { + NMLOG_ERROR("something went wrong no matching gerror found !"); + } + else + { + NMLOG_ERROR("Failed Error msg: %s", error->message); + } g_error_free(error); - return; + _wifiManager->m_isSuccess = false; } - - NMLOG_ERROR("Failed to set Managed property: %s", error->message); - g_error_free(error); - _wifiManager->m_isSuccess = false; - } else { + } + else + { NMLOG_DEBUG("Successfully set Managed property."); _wifiManager->m_isSuccess = true; } @@ -1664,8 +1717,12 @@ namespace WPEFramework NMLOG_DEBUG("activate connection completeing..."); // Check if the operation was successful if (!nm_client_activate_connection_finish(NM_CLIENT(source_object), res, &error)) { - NMLOG_DEBUG("Activating connection failed: %s", error->message); - g_error_free(error); + NMLOG_ERROR("Activating connection failed"); + if(error != NULL) + { + NMLOG_ERROR("Activating connection failed: %s", error->message); + g_error_free(error); + } _wifiManager->m_isSuccess = false; } else { NMLOG_DEBUG("Activating connection successful"); diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp index a7b920a72..c451b8f25 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp @@ -48,6 +48,7 @@ namespace WPEFramework GVariant *ifaceVariant = g_dbus_proxy_get_cached_property(deviceProxy, "Interface"); if (ifaceVariant == NULL) { NMLOG_WARNING("Interface property get error"); + g_object_unref(deviceProxy); return ifname; } @@ -750,7 +751,12 @@ namespace WPEFramework g_variant_get(result, "(ao)", &iter); if(iter == NULL) + { + NMLOG_ERROR("GetAllAccessPoints GVariantIter returned NULL"); + g_variant_unref(result); + g_object_unref(wProxy); return; + } while (g_variant_iter_loop(iter, "o", &apPath)) { Exchange::INetworkManager::WiFiSSIDInfo wifiInfo; // NMLOG_DEBUG("Access Point Path: %s", apPath); From 4948b8ad261734c8d2ef26d5248d8e1131627347 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Sun, 27 Jul 2025 00:30:16 +0530 Subject: [PATCH 160/271] RDKEMW-5756 : NetworkManager Plugin - L1/L2 Test coverage - RDK Backend (#199) * RDKEMW-5756 NetworkManager Plugin - Improve L1/L2 Test coverage - NetSrvMgr Backend * more Test case added * popen mock add * getWifiSiganalStrength gtest added * setipsettings * test * update the wraps mock --- ..._unit_test.yml => gdbus_proxy_L1_test.yml} | 74 +- .github/workflows/libnm_proxy_L1_test.yml | 123 ++ ...unit_test.yml => rdk_proxy_L1_L2_test.yml} | 89 +- CMakeLists.txt | 3 +- plugin/NetworkManagerImplementation.cpp | 5 + plugin/rdk/NetworkManagerRDKProxy.cpp | 345 +--- plugin/rdk/NetworkManagerRDKProxy.h | 364 ++++ tests/l1Test/CMakeLists.txt | 97 + .../l1_test_connectivity.cpp} | 2 +- tests/l1Test/l1_test_routediscovery.cpp | 100 ++ .../l1_test_stunclient.cpp} | 0 tests/l2Test/CMakeLists.txt | 85 + tests/l2Test/l2_test_rdkproxy.cpp | 1556 +++++++++++++++++ tests/l2Test/l2_test_rdkproxyEvent.cpp | 698 ++++++++ tests/l2Test/l2_test_rdkproxyImpl.cpp | 263 +++ tests/mocks/ConnectivityMockServer.h | 224 +++ tests/mocks/Iarm.cpp | 4 + tests/mocks/IarmBusMock.h | 6 +- tests/mocks/Wraps.cpp | 162 ++ tests/mocks/Wraps.h | 55 + tests/mocks/WrapsMock.h | 36 + tests/mocks/secure_wrappermock.h | 37 + tests/mocks/thunder/COMLinkMock.h | 9 +- tests/mocks/thunder/Communicator.cpp | 30 + tests/mocks/thunder/Communicator.h | 286 +++ tests/mocks/thunder/CommunicatorMock.h | 53 + tests/mocks/thunder/DispatcherMock.h | 46 +- tests/mocks/thunder/FactoriesImplementation.h | 3 +- tests/mocks/thunder/Module.cpp | 2 +- tests/mocks/thunder/Module.h | 4 +- tests/mocks/thunder/ServiceMock.h | 41 +- tests/mocks/thunder/SystemInfo.h | 3 +- tests/mocks/thunder/ThunderPortability.h | 3 +- .../mocks/thunder/WorkerPoolImplementation.h | 3 +- tests/mocks/thunder/mockauthservices.h | 87 + 35 files changed, 4428 insertions(+), 470 deletions(-) rename .github/workflows/{gnome_unit_test.yml => gdbus_proxy_L1_test.yml} (65%) create mode 100644 .github/workflows/libnm_proxy_L1_test.yml rename .github/workflows/{rdk_unit_test.yml => rdk_proxy_L1_L2_test.yml} (68%) create mode 100644 plugin/rdk/NetworkManagerRDKProxy.h create mode 100644 tests/l1Test/CMakeLists.txt rename tests/{unittest/test_NetworkManagerConnectivity.cpp => l1Test/l1_test_connectivity.cpp} (97%) create mode 100644 tests/l1Test/l1_test_routediscovery.cpp rename tests/{unittest/test_NetworkManagerStunClient.cpp => l1Test/l1_test_stunclient.cpp} (100%) create mode 100644 tests/l2Test/CMakeLists.txt create mode 100644 tests/l2Test/l2_test_rdkproxy.cpp create mode 100644 tests/l2Test/l2_test_rdkproxyEvent.cpp create mode 100644 tests/l2Test/l2_test_rdkproxyImpl.cpp create mode 100644 tests/mocks/ConnectivityMockServer.h create mode 100644 tests/mocks/Wraps.cpp create mode 100644 tests/mocks/Wraps.h create mode 100644 tests/mocks/WrapsMock.h create mode 100644 tests/mocks/secure_wrappermock.h create mode 100755 tests/mocks/thunder/Communicator.cpp create mode 100755 tests/mocks/thunder/Communicator.h create mode 100755 tests/mocks/thunder/CommunicatorMock.h mode change 100644 => 100755 tests/mocks/thunder/ThunderPortability.h create mode 100644 tests/mocks/thunder/mockauthservices.h diff --git a/.github/workflows/gnome_unit_test.yml b/.github/workflows/gdbus_proxy_L1_test.yml similarity index 65% rename from .github/workflows/gnome_unit_test.yml rename to .github/workflows/gdbus_proxy_L1_test.yml index a14a07a9d..7d605b4ba 100644 --- a/.github/workflows/gnome_unit_test.yml +++ b/.github/workflows/gdbus_proxy_L1_test.yml @@ -1,4 +1,4 @@ -name: gnome_unit_test +name: gdbus_proxy_l1_tests on: push: @@ -7,14 +7,39 @@ on: branches: [ main, develop, 'support/**', 'hotfix/**', 'topic/**'] env: - THUNDER_REF: "R4.4.1" + THUNDER_REF: "R4.4.3" jobs: - unit-tests: + L1-tests: name: Build and run unit tests runs-on: ubuntu-22.04 - + steps: + # Set up Thunder cache + - name: Set up Thunder cache + id: cache + uses: actions/cache@v3 + with: + path: | + build/Thunder + build/ThunderInterfaces + build/ThunderTools + install + !install/etc/WPEFramework/plugins + !install/usr/bin/gdbusproxy_l1_test + !install/usr/include/gmock + !install/usr/include/gtest + !install/usr/lib/libgmockd.a + !install/usr/lib/libgmock_maind.a + !install/usr/lib/libgtestd.a + !install/usr/lib/libgtest_maind.a + !install/usr/lib/cmake/GTest + !install/usr/lib/pkgconfig/gmock.pc + !install/usr/lib/pkgconfig/gmock_main.pc + !install/usr/lib/pkgconfig/gtest.pc + !install/usr/lib/pkgconfig/gtest_main.pc + !install/usr/lib/wpeframework/plugins + key: thunder-${{ env.THUNDER_REF }}-gdbus - name: Install packages run: | sudo apt update @@ -30,14 +55,26 @@ jobs: uses: jwlawson/actions-setup-cmake@v1.13 with: cmake-version: '3.16.x' - - name: Checkout thunder repositories + if: steps.cache.outputs.cache-hit != 'true' run: | git clone https://github.com/rdkcentral/ThunderTools ThunderTools --branch ${{ env.THUNDER_REF }} git clone https://github.com/rdkcentral/Thunder Thunder --branch ${{ env.THUNDER_REF }} git clone https://github.com/rdkcentral/ThunderInterfaces ThunderInterfaces --branch ${{ env.THUNDER_REF }} - + + - name: Checkout networkmanager + uses: actions/checkout@v3 + with: + path: networkmanager + + - name: Apply Thunder Patches + if: steps.cache.outputs.cache-hit != 'true' + run: | + cd ${{github.workspace}}/Thunder + git apply ${{github.workspace}}/networkmanager/tests/patches/thunder/Remove-SmartLinkType.patch + - name: Build ThunderTools + if: steps.cache.outputs.cache-hit != 'true' run: > cmake -S "${{github.workspace}}/ThunderTools" -B build/ThunderTools @@ -48,6 +85,7 @@ jobs: cmake --build build/ThunderTools --target install -j8 - name: Build Thunder + if: steps.cache.outputs.cache-hit != 'true' run: > cmake -S "${{github.workspace}}/Thunder" -B build/Thunder @@ -60,6 +98,7 @@ jobs: cmake --build build/Thunder --target install -j8 - name: ThunderInterfaces + if: steps.cache.outputs.cache-hit != 'true' run: > cmake -S "${{github.workspace}}/ThunderInterfaces" -B build/ThunderInterfaces @@ -68,30 +107,11 @@ jobs: && cmake --build build/ThunderInterfaces --target install -j8 - - name: Checkout networkmanager - uses: actions/checkout@v3 - with: - path: networkmanager - - - name: Build networkmanager with Gnome libnm Proxy - run: > - cmake - -S "${{github.workspace}}/networkmanager" - -B build/GnomeLibnmNetworkmanager - -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" - -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" - -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" - -DCMAKE_CXX_FLAGS=" -fprofile-arcs -ftest-coverage " - -DENABLE_GNOME_NETWORKMANAGER=ON - -DENABLE_PLUGIN_CLI=ON - && - cmake --build build/GnomeLibnmNetworkmanager --target install -j8 - - name: Build networkmanager with Gnome GDBUS Proxy run: > cmake -S "${{github.workspace}}/networkmanager" - -B build/GnomeGdbusNetworkmanager + -B build/networkmanager_gdbus -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" @@ -100,6 +120,6 @@ jobs: -DENABLE_GNOME_GDBUS=ON -DENABLE_PLUGIN_CLI=ON && - cmake --build build/GnomeGdbusNetworkmanager --target install -j8 + cmake --build build/networkmanager_gdbus --target install -j8 diff --git a/.github/workflows/libnm_proxy_L1_test.yml b/.github/workflows/libnm_proxy_L1_test.yml new file mode 100644 index 000000000..ba22e3cc4 --- /dev/null +++ b/.github/workflows/libnm_proxy_L1_test.yml @@ -0,0 +1,123 @@ +name: libnm_proxy_l1_tests + +on: + push: + branches: [ main, develop, 'support/**', 'hotfix/**', 'topic/**'] + pull_request: + branches: [ main, develop, 'support/**', 'hotfix/**', 'topic/**'] + +env: + THUNDER_REF: "R4.4.3" + +jobs: + L1-tests: + name: Build and run unit tests + runs-on: ubuntu-22.04 + + steps: + # Set up Thunder cache + - name: Set up Thunder cache + id: cache + uses: actions/cache@v3 + with: + path: | + build/Thunder + build/ThunderInterfaces + build/ThunderTools + install + !install/etc/WPEFramework/plugins + !install/usr/bin/libnmproxy_l1_test + !install/usr/include/gmock + !install/usr/include/gtest + !install/usr/lib/libgmockd.a + !install/usr/lib/libgmock_maind.a + !install/usr/lib/libgtestd.a + !install/usr/lib/libgtest_maind.a + !install/usr/lib/cmake/GTest + !install/usr/lib/pkgconfig/gmock.pc + !install/usr/lib/pkgconfig/gmock_main.pc + !install/usr/lib/pkgconfig/gtest.pc + !install/usr/lib/pkgconfig/gtest_main.pc + !install/usr/lib/wpeframework/plugins + key: thunder-${{ env.THUNDER_REF }}-libnm + - name: Install packages + run: | + sudo apt update + sudo apt-get install -y pkg-config libglib2.0-dev libnm-dev libcurl4-openssl-dev lcov ninja-build + + - name: Configure Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + - run: pip install jsonref + + - name: Configure CMake + uses: jwlawson/actions-setup-cmake@v1.13 + with: + cmake-version: '3.16.x' + - name: Checkout thunder repositories + if: steps.cache.outputs.cache-hit != 'true' + run: | + git clone https://github.com/rdkcentral/ThunderTools ThunderTools --branch ${{ env.THUNDER_REF }} + git clone https://github.com/rdkcentral/Thunder Thunder --branch ${{ env.THUNDER_REF }} + git clone https://github.com/rdkcentral/ThunderInterfaces ThunderInterfaces --branch ${{ env.THUNDER_REF }} + + - name: Checkout networkmanager + uses: actions/checkout@v3 + with: + path: networkmanager + + - name: Apply Thunder Patches + if: steps.cache.outputs.cache-hit != 'true' + run: | + cd ${{github.workspace}}/Thunder + git apply ${{github.workspace}}/networkmanager/tests/patches/thunder/Remove-SmartLinkType.patch + + - name: Build ThunderTools + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake + -S "${{github.workspace}}/ThunderTools" -B build/ThunderTools + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DGENERIC_CMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + && + cmake --build build/ThunderTools --target install -j8 + + - name: Build Thunder + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake + -S "${{github.workspace}}/Thunder" -B build/Thunder + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DBUILD_TYPE=Debug + -DBINDING=127.0.0.1 + -DPORT=9998 + && + cmake --build build/Thunder --target install -j8 + + - name: ThunderInterfaces + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake + -S "${{github.workspace}}/ThunderInterfaces" -B build/ThunderInterfaces + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + && + cmake --build build/ThunderInterfaces --target install -j8 + + - name: Build networkmanager with Gnome libnm Proxy + run: > + cmake + -S "${{github.workspace}}/networkmanager" + -B build/networkmanager_libnm + -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DCMAKE_CXX_FLAGS=" -fprofile-arcs -ftest-coverage " + -DENABLE_GNOME_NETWORKMANAGER=ON + -DENABLE_PLUGIN_CLI=ON + && + cmake --build build/networkmanager_libnm --target install -j8 + diff --git a/.github/workflows/rdk_unit_test.yml b/.github/workflows/rdk_proxy_L1_L2_test.yml similarity index 68% rename from .github/workflows/rdk_unit_test.yml rename to .github/workflows/rdk_proxy_L1_L2_test.yml index f42f39862..26d97e8c4 100644 --- a/.github/workflows/rdk_unit_test.yml +++ b/.github/workflows/rdk_proxy_L1_L2_test.yml @@ -1,4 +1,4 @@ -name: rdk_unit_test +name: rdk_proxy_l1_l2_tests on: push: @@ -7,14 +7,39 @@ on: branches: [ main, develop, 'support/**', 'hotfix/**', 'topic/**'] env: - THUNDER_REF: "R4.4.1" + THUNDER_REF: "R4.4.3" jobs: - unit-tests: + L1-tests: name: Build and run unit tests runs-on: ubuntu-22.04 steps: + # Set up Thunder cache + - name: Set up Thunder cache + id: cache + uses: actions/cache@v3 + with: + path: | + build/Thunder + build/ThunderInterfaces + build/ThunderTools + install + !install/etc/WPEFramework/plugins + !install/usr/bin/rdkproxy_l1_test + !install/usr/include/gmock + !install/usr/include/gtest + !install/usr/lib/libgmockd.a + !install/usr/lib/libgmock_maind.a + !install/usr/lib/libgtestd.a + !install/usr/lib/libgtest_maind.a + !install/usr/lib/cmake/GTest + !install/usr/lib/pkgconfig/gmock.pc + !install/usr/lib/pkgconfig/gmock_main.pc + !install/usr/lib/pkgconfig/gtest.pc + !install/usr/lib/pkgconfig/gtest_main.pc + !install/usr/lib/wpeframework/plugins + key: thunder-${{ env.THUNDER_REF }}-rdk - name: Install packages run: | sudo apt update @@ -30,24 +55,26 @@ jobs: uses: jwlawson/actions-setup-cmake@v1.13 with: cmake-version: '3.16.x' - - name: Checkout thunder repositories + if: steps.cache.outputs.cache-hit != 'true' run: | git clone https://github.com/rdkcentral/ThunderTools ThunderTools --branch ${{ env.THUNDER_REF }} git clone https://github.com/rdkcentral/Thunder Thunder --branch ${{ env.THUNDER_REF }} git clone https://github.com/rdkcentral/ThunderInterfaces ThunderInterfaces --branch ${{ env.THUNDER_REF }} - + - name: Checkout networkmanager uses: actions/checkout@v3 with: path: networkmanager - + - name: Apply Thunder Patches + if: steps.cache.outputs.cache-hit != 'true' run: | cd ${{github.workspace}}/Thunder git apply ${{github.workspace}}/networkmanager/tests/patches/thunder/Remove-SmartLinkType.patch - name: Build ThunderTools + if: steps.cache.outputs.cache-hit != 'true' run: > cmake -S "${{github.workspace}}/ThunderTools" -B build/ThunderTools @@ -58,6 +85,7 @@ jobs: cmake --build build/ThunderTools --target install -j8 - name: Build Thunder + if: steps.cache.outputs.cache-hit != 'true' run: > cmake -S "${{github.workspace}}/Thunder" -B build/Thunder @@ -70,6 +98,7 @@ jobs: cmake --build build/Thunder --target install -j8 - name: ThunderInterfaces + if: steps.cache.outputs.cache-hit != 'true' run: > cmake -S "${{github.workspace}}/ThunderInterfaces" -B build/ThunderInterfaces @@ -92,7 +121,7 @@ jobs: run: > cmake -S "${{github.workspace}}/networkmanager" - -B build/RDKNetworkmanager + -B build/networkmanager_rdk -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" @@ -100,45 +129,31 @@ jobs: -I ${{github.workspace}}/networkmanager/tests/headers -I ${{github.workspace}}/networkmanager/tests/headers/rdk/iarmbus --include ${{github.workspace}}/networkmanager/tests/mocks/Iarm.h + --include ${{github.workspace}}/networkmanager/tests/mocks/secure_wrappermock.h + -Wall --coverage " -DENABLE_UNIT_TESTING=ON -DENABLE_ROUTER_DISCOVERY_TOOL=ON && - cmake --build build/RDKNetworkmanager --target install -j8 - - - name: Run unit tests for common class - run: > - PATH=${{github.workspace}}/install/usr/bin:${PATH} - LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} - common_class_tests - - - name: Run unit tests for rdk proxy - run: > - PATH=${{github.workspace}}/install/usr/bin:${PATH} - LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} - rdkproxy_tests - - - name: Run unit tests for Legacy_WiFi + cmake --build build/networkmanager_rdk --target install -j8 + + - name: Run l1 tests run: > PATH=${{github.workspace}}/install/usr/bin:${PATH} LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} - legacywifi_tests - - - name: Run unit tests for Legacy_Network + upnpcli_l1_test --gtest_color=yes --gtest_output="xml:/tmp/gtest_log/upnpcli_l1_test.xml" + class_l1_test --gtest_color=yes --gtest_output="xml:/tmp/gtest_log/class_l1_test.xml" + + - name: Run l2 rdk proxy tests run: > PATH=${{github.workspace}}/install/usr/bin:${PATH} LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} - legacynetwork_tests + rdkproxy_l2_test --gtest_color=yes --gtest_output="xml:/tmp/gtest_log/rdkproxy_l2_test.xml" - - name: Run unit tests for routerDiscovery - run: > - PATH=${{github.workspace}}/install/usr/bin:${PATH} - routerDiscovery_tests - - name: Generate coverage run: | - lcov -c -o coverage.info -d build/RDKNetworkmanager - lcov -r coverage.info '/usr/include/*' '*/build/RDKNetworkmanager/*' \ + lcov -c -o coverage.info -d build/networkmanager_rdk + lcov -r coverage.info '/usr/include/*' '*/build/networkmanager_rdk/*' \ '*/install/usr/include/*' '*/tests/*' 'googlemock/*' 'googletest/*' \ -o filtered_coverage.info - name: Generate the html report @@ -148,7 +163,7 @@ jobs: - name: Upload the coverage report to Pull request using actions uses: actions/upload-artifact@v4 with: - name: coverage-report - path: /tmp/coverage_report - - + name: coverage-report + path: | + /tmp/coverage_report + /tmp/gtest_log diff --git a/CMakeLists.txt b/CMakeLists.txt index d05577c5f..efcea13f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ endif (ENABLE_LEGACY_PLUGINS) add_subdirectory(tools) if(ENABLE_UNIT_TESTING) - add_subdirectory(tests/unittest) + add_subdirectory(tests/l1Test) + add_subdirectory(tests/l2Test) endif(ENABLE_UNIT_TESTING) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 93e1de46a..521e8719a 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -351,6 +351,7 @@ namespace WPEFramework } else { + NMLOG_ERROR("stun bind failed for endpoint %s:%d", m_stunEndpoint.c_str(), m_stunPort); return Core::ERROR_GENERAL; } } @@ -797,10 +798,12 @@ namespace WPEFramework while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) { std::istringstream mystream(buff); if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) + { if (key == "bssid") { bssid = value; break; } + } } pclose(fp); @@ -816,6 +819,7 @@ namespace WPEFramework { std::istringstream mystream(buff); if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) + { if (key == "level") { strength = value; } @@ -830,6 +834,7 @@ namespace WPEFramework } if (!strength.empty() && !noise.empty() && !ssid.empty() && !snr.empty()) break; + } } pclose(fp); diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index fd9fc2cee..dc03b3cc4 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -18,6 +18,7 @@ **/ #include "NetworkManagerImplementation.h" #include "NetworkManagerConnectivity.h" +#include "NetworkManagerRDKProxy.h" #include "libIBus.h" #include @@ -28,349 +29,6 @@ using namespace std; namespace WPEC = WPEFramework::Core; namespace WPEJ = WPEFramework::Core::JSON; -#define IARM_BUS_NM_SRV_MGR_NAME "NET_SRV_MGR" - -#define MAX_IP_ADDRESS_LEN 46 -#define NETSRVMGR_INTERFACES_MAX 16 -#define MAX_ENDPOINTS 5 -#define MAX_ENDPOINT_SIZE 512 -#define MAX_URI_LEN 512 -#define MAX_HOST_NAME_LEN 128 -#define DEFAULT_PING_PACKETS 15 -#define CIDR_NETMASK_IP_LEN 32 -#define INTERFACE_SIZE 10 -#define INTERFACE_LIST 50 -#define MAX_IP_FAMILY_SIZE 10 - - -#define BUFF_LENGTH_64 65 -#define BUFF_LENGTH_256 257 -#define BUFF_MAX 1025 -#define BUFF_MAC 18 -#define BUFF_MIN 17 -#define BUFF_LENGTH_4 4 -#define SSID_SIZE 33 -#define BSSID_BUFF 20 -#define BUFF_LENGTH_24 24 -#define PASSPHRASE_BUFF 385 -#define MAX_SSIDLIST_BUF (48*1024) -#define MAX_FILE_PATH_LEN 4096 - -typedef enum _NetworkManager_EventId_t { - IARM_BUS_NETWORK_MANAGER_EVENT_SET_INTERFACE_ENABLED=50, - IARM_BUS_NETWORK_MANAGER_EVENT_SET_INTERFACE_CONTROL_PERSISTENCE, - IARM_BUS_NETWORK_MANAGER_EVENT_WIFI_INTERFACE_STATE, - IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS, - IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, - IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, - IARM_BUS_NETWORK_MANAGER_EVENT_DEFAULT_INTERFACE, - IARM_BUS_NETWORK_MANAGER_EVENT_INTERNET_CONNECTION_CHANGED, - IARM_BUS_NETWORK_MANAGER_MAX, -} IARM_Bus_NetworkManager_EventId_t; - -typedef enum _IARM_Bus_NMgr_WiFi_EventId_t { - IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged = 1, - IARM_BUS_WIFI_MGR_EVENT_onError, - IARM_BUS_WIFI_MGR_EVENT_onSSIDsChanged, - IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, - IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDsIncr, - IARM_BUS_WIFI_MGR_EVENT_onWIFILNFStateChanged, - IARM_BUS_WIFI_MGR_EVENT_MAX, /*!< Maximum event id*/ -} IARM_Bus_NMgr_WiFi_EventId_t; - - -typedef struct { - char name[16]; - char mac[20]; - unsigned int flags; -} NetSrvMgr_Interface_t; - -typedef struct { - unsigned char size; - NetSrvMgr_Interface_t interfaces[NETSRVMGR_INTERFACES_MAX]; -} IARM_BUS_NetSrvMgr_InterfaceList_t; - -typedef enum _NetworkManager_GetIPSettings_ErrorCode_t -{ - NETWORK_IPADDRESS_ACQUIRED, - NETWORK_IPADDRESS_NOTFOUND, - NETWORK_NO_ROUTE_INTERFACE, - NETWORK_NO_DEFAULT_ROUTE, - NETWORK_DNS_NOT_CONFIGURED, - NETWORK_INVALID_IPADDRESS, -} NetworkManager_GetIPSettings_ErrorCode_t; - -typedef struct { - char interface[16]; - char ipversion[16]; - bool autoconfig; - char ipaddress[MAX_IP_ADDRESS_LEN]; - char netmask[MAX_IP_ADDRESS_LEN]; - char gateway[MAX_IP_ADDRESS_LEN]; - char dhcpserver[MAX_IP_ADDRESS_LEN]; - char primarydns[MAX_IP_ADDRESS_LEN]; - char secondarydns[MAX_IP_ADDRESS_LEN]; - bool isSupported; - NetworkManager_GetIPSettings_ErrorCode_t errCode; -} IARM_BUS_NetSrvMgr_Iface_Settings_t; - -typedef struct { - char interface[16]; - char gateway[MAX_IP_ADDRESS_LEN]; -} IARM_BUS_NetSrvMgr_DefaultRoute_t; - -typedef struct { - char interface[16]; - bool status; -} IARM_BUS_NetSrvMgr_Iface_EventInterfaceStatus_t; - -typedef IARM_BUS_NetSrvMgr_Iface_EventInterfaceStatus_t IARM_BUS_NetSrvMgr_Iface_EventInterfaceEnabledStatus_t; -typedef IARM_BUS_NetSrvMgr_Iface_EventInterfaceStatus_t IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t; - -typedef struct { - char interface[16]; - char ip_address[MAX_IP_ADDRESS_LEN]; - bool is_ipv6; - bool acquired; -} IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t; - -typedef struct { - char oldInterface[16]; - char newInterface[16]; -} IARM_BUS_NetSrvMgr_Iface_EventDefaultInterface_t; - -typedef struct -{ - char server[MAX_HOST_NAME_LEN]; - uint16_t port; - bool ipv6; - char interface[16]; - uint16_t bind_timeout; - uint16_t cache_timeout; - bool sync; - char public_ip[MAX_IP_ADDRESS_LEN]; -} IARM_BUS_NetSrvMgr_Iface_StunRequest_t; - -typedef struct -{ - bool disableConnectivityTest; -} IARM_BUS_NetSrvMgr_configurePNI_t; - - - -/*! Supported values are NONE - 0, WPA - 1, WEP - 2*/ -typedef enum _SsidSecurity -{ - NET_WIFI_SECURITY_NONE = 0, - NET_WIFI_SECURITY_WEP_64, - NET_WIFI_SECURITY_WEP_128, - NET_WIFI_SECURITY_WPA_PSK_TKIP, - NET_WIFI_SECURITY_WPA_PSK_AES, - NET_WIFI_SECURITY_WPA2_PSK_TKIP, - NET_WIFI_SECURITY_WPA2_PSK_AES, - NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP, - NET_WIFI_SECURITY_WPA_ENTERPRISE_AES, - NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP, - NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES, - NET_WIFI_SECURITY_WPA_WPA2_PSK, - NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE, - NET_WIFI_SECURITY_WPA3_PSK_AES, - NET_WIFI_SECURITY_WPA3_SAE, - NET_WIFI_SECURITY_NOT_SUPPORTED = 99, -} SsidSecurity; - - -/*! Event states associated with WiFi connection */ -typedef enum _WiFiStatusCode_t { - WIFI_UNINSTALLED, /**< The device was in an installed state, and was uninstalled */ - WIFI_DISABLED, /**< The device is installed (or was just installed) and has not yet been enabled */ - WIFI_DISCONNECTED, /**< The device is not connected to a network */ - WIFI_PAIRING, /**< The device is not connected to a network, but not yet connecting to a network */ - WIFI_CONNECTING, /**< The device is attempting to connect to a network */ - WIFI_CONNECTED, /**< The device is successfully connected to a network */ - WIFI_FAILED /**< The device has encountered an unrecoverable error with the wifi adapter */ -} WiFiStatusCode_t; - -/*! Error code: A recoverable, unexpected error occurred, - * as defined by one of the following values */ -typedef enum _WiFiErrorCode_t { - WIFI_SSID_CHANGED, /**< The SSID of the network changed */ - WIFI_CONNECTION_LOST, /**< The connection to the network was lost */ - WIFI_CONNECTION_FAILED, /**< The connection failed for an unknown reason */ - WIFI_CONNECTION_INTERRUPTED, /**< The connection was interrupted */ - WIFI_INVALID_CREDENTIALS, /**< The connection failed due to invalid credentials */ - WIFI_NO_SSID, /**< The SSID does not exist */ - WIFI_UNKNOWN, /**< Any other error */ - WIFI_AUTH_FAILED /**< The connection failed due to auth failure */ -} WiFiErrorCode_t; - -typedef enum _WiFiLNFState_t { - LNF_SSID_CONNECTED, /**< Connected to the LNF network */ - LNF_SSID_CONNECT_FAILED, /**< failed connect to the LNF network */ - LNF_ENDPOINT_BACKOFF_TIME, /**< lnf in last requested backoff time */ - LNF_ENDPOINT_CONNECTED, /**< lnf connected to end point and get the LFAT */ - LNF_RECEIVED_PRIVATE_SSID_INFO, /**< lnf process Got private cridential*/ - LNF_SWITCHING_TO_PRIVATE, /**< lnf connected to private*/ - LNF_SSID_DISCONNECTED, /**< disconnected form lnf ssid */ - LNF_ERROR /**< common lnf error replay from lnf library */ -} WiFiLNFState_t; - -typedef struct _IARM_Bus_WiFiSrvMgr_WPS_Parameters_t -{ - bool pbc; - char pin[9]; - bool status; -} IARM_Bus_WiFiSrvMgr_WPS_Parameters_t; - - -/*! LNF states */ -typedef enum _WiFiLNFStatusCode_t { - LNF_UNITIALIZED, /**< Network manager hasn't started the LNF process */ - LNF_IN_PROGRESS, /**< Network manager has started LNF, and waiting for operation to complete */ - CONNECTED_LNF, /**< Connected to the LNF network */ - CONNECTED_PRIVATE, /** Connected to a network that is not LNF */ - DISCONNECTED_NO_LNF_GATEWAY_DETECTED, /**< unable to connect to LNF network */ - DISCONNECTED_GET_LFAT_FAILED, /**< client wasn't able to acquire an LFAT */ - DISCONNECTED_CANT_CONNECT_TO_PRIVATE // client could obtain LFAT, but couldn't connect to private network */ - /**< The device has encountered an unrecoverable error with the wifi adapter */ -} WiFiLNFStatusCode_t; - - -typedef struct _setWiFiAdapter -{ - bool enable; -} setWiFiAdapter; - -typedef struct _WiFiConnection -{ - char ssid[SSID_SIZE]; - char bssid[BSSID_BUFF]; - char security[BUFF_LENGTH_64]; - char passphrase[PASSPHRASE_BUFF]; - SsidSecurity security_mode; - char security_WEPKey[PASSPHRASE_BUFF]; - char security_PSK[PASSPHRASE_BUFF]; - char eapIdentity[BUFF_LENGTH_256]; - char carootcert[MAX_FILE_PATH_LEN]; - char clientcert[MAX_FILE_PATH_LEN]; - char privatekey[MAX_FILE_PATH_LEN]; - bool persistSSIDInfo; -} WiFiConnection; - -typedef struct _WiFiConnectedSSIDInfo -{ - char ssid[SSID_SIZE]; /**< The name of connected SSID. */ - char bssid[BSSID_BUFF]; /**< The the Basic Service Set ID (mac address). */ - char band[BUFF_MIN]; /**< The frequency band at which the client is conneted to. */ - int securityMode; /**< Current WiFi Security Mode used for connection. */ - int frequency; /**< The Frequency wt which the client is connected to. */ - float rate; /**< The Physical data rate in Mbps */ - float noise; /**< The average noise strength in dBm. */ - float signalStrength; /**< The RSSI value in dBm. */ - -} WiFiConnectedSSIDInfo_t; - -typedef struct _WiFiPairedSSIDInfo -{ - char ssid[SSID_SIZE]; /**< The name of connected SSID. */ - char bssid[BSSID_BUFF]; /**< The the Basic Service Set ID (mac address). */ - char security[BUFF_LENGTH_64]; /**< security of AP */ - SsidSecurity secMode; -} WiFiPairedSSIDInfo_t; - - -typedef enum _WiFiConnectionTypeCode_t { - WIFI_CON_UNKNOWN, - WIFI_CON_WPS, - WIFI_CON_MANUAL, - WIFI_CON_LNF, - WIFI_CON_PRIVATE, - WIFI_CON_MAX, -} WiFiConnectionTypeCode_t; - - -typedef struct _IARM_Bus_WiFiSrvMgr_Param_t { - union { - WiFiLNFStatusCode_t wifiLNFStatus; - WiFiStatusCode_t wifiStatus; - setWiFiAdapter setwifiadapter; - WiFiConnection connect; - WiFiConnection saveSSID; - WiFiConnection clearSSID; - WiFiConnectedSSIDInfo_t getConnectedSSID; - WiFiPairedSSIDInfo_t getPairedSSIDInfo; - WiFiConnectionTypeCode_t connectionType; - struct getPairedSSID { - char ssid[SSID_SIZE]; - } getPairedSSID; - bool isPaired; - } data; - bool status; -} IARM_Bus_WiFiSrvMgr_Param_t; - -typedef struct _IARM_BUS_NetSrvMgr_Iface_EventData_t { - union { - char activeIface[INTERFACE_SIZE]; - char allNetworkInterfaces[INTERFACE_LIST]; - char setInterface[INTERFACE_SIZE]; - char activeIfaceIpaddr[MAX_IP_ADDRESS_LEN]; - }; - char interfaceCount; - bool isInterfaceEnabled; - bool persist; - char ipfamily[MAX_IP_FAMILY_SIZE]; -} IARM_BUS_NetSrvMgr_Iface_EventData_t; - -typedef struct _IARM_BUS_WiFiSrvMgr_EventData_t { - union { - struct _WIFI_STATECHANGE_DATA { - WiFiStatusCode_t state; - } wifiStateChange; - struct _WIFI_ERROR { - WiFiErrorCode_t code; - } wifiError; - struct _WIFI_SSID_LIST { - char ssid_list[MAX_SSIDLIST_BUF]; - bool more_data; - } wifiSSIDList; - struct _WIFI_LNF_STATE { - WiFiLNFState_t state; - float backOffTime; - }wifilnfState; - } data; -} IARM_BUS_WiFiSrvMgr_EventData_t; - -typedef struct _wifiSsidData_t { - char jdata[MAX_SSIDLIST_BUF]; /**< Buffer containing the serialized data. */ - size_t jdataLen; /**< Length of the data buffer. */ -} wifiSsidData_t; - -typedef struct _IARM_Bus_WiFiSrvMgr_SsidList_Param_t { - wifiSsidData_t curSsids; - bool status; -} IARM_Bus_WiFiSrvMgr_SsidList_Param_t; - - -#define IARM_BUS_NETSRVMGR_API_getInterfaceList "getInterfaceList" -#define IARM_BUS_NETSRVMGR_API_getDefaultInterface "getDefaultInterface" -#define IARM_BUS_NETSRVMGR_API_setDefaultInterface "setDefaultInterface" -#define IARM_BUS_NETSRVMGR_API_isInterfaceEnabled "isInterfaceEnabled" -#define IARM_BUS_NETSRVMGR_API_setInterfaceEnabled "setInterfaceEnabled" -#define IARM_BUS_NETSRVMGR_API_setIPSettings "setIPSettings" -#define IARM_BUS_NETSRVMGR_API_getIPSettings "getIPSettings" -#define IARM_BUS_NETSRVMGR_API_isAvailable "isAvailable" -#define IARM_BUS_WIFI_MGR_API_getAvailableSSIDsAsync "getAvailableSSIDsAsync" /**< Retrieve array of strings representing SSIDs */ -#define IARM_BUS_WIFI_MGR_API_getAvailableSSIDsAsyncIncr "getAvailableSSIDsAsyncIncr" /**< Retrieve array of strings representing SSIDs in an incremental way */ -#define IARM_BUS_WIFI_MGR_API_stopProgressiveWifiScanning "stopProgressiveWifiScanning" /**< Stop any in-progress wifi progressive scanning thread */ -#define IARM_BUS_WIFI_MGR_API_initiateWPSPairing2 "initiateWPSPairing2" /**< Initiate connection via WPS via either Push Button or PIN */ -#define IARM_BUS_WIFI_MGR_API_cancelWPSPairing "cancelWPSPairing" /**< Cancel in-progress WPS */ -#define IARM_BUS_WIFI_MGR_API_getConnectedSSID "getConnectedSSID" /**< Return properties of the currently connected SSID */ -#define IARM_BUS_WIFI_MGR_API_saveSSID "saveSSID" /**< Save SSID and passphrase */ -#define IARM_BUS_WIFI_MGR_API_clearSSID "clearSSID" /**< Clear given SSID */ -#define IARM_BUS_WIFI_MGR_API_connect "connect" /**< Connect with given or saved SSID and passphrase */ -#define IARM_BUS_WIFI_MGR_API_disconnectSSID "disconnectSSID" /**< Disconnect from current SSID */ -#define IARM_BUS_WIFI_MGR_API_getCurrentState "getCurrentState" /**< Retrieve current state */ - namespace WPEFramework { namespace Plugin @@ -1584,7 +1242,6 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - IARM_Result_t retVal = IARM_RESULT_SUCCESS; IARM_Bus_WiFiSrvMgr_Param_t param; memset(¶m, 0, sizeof(param)); diff --git a/plugin/rdk/NetworkManagerRDKProxy.h b/plugin/rdk/NetworkManagerRDKProxy.h new file mode 100644 index 000000000..96e9a3963 --- /dev/null +++ b/plugin/rdk/NetworkManagerRDKProxy.h @@ -0,0 +1,364 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +#define IARM_BUS_NM_SRV_MGR_NAME "NET_SRV_MGR" + +#define MAX_IP_ADDRESS_LEN 46 +#define NETSRVMGR_INTERFACES_MAX 16 +#define MAX_ENDPOINTS 5 +#define MAX_ENDPOINT_SIZE 512 +#define MAX_URI_LEN 512 +#define MAX_HOST_NAME_LEN 128 +#define DEFAULT_PING_PACKETS 15 +#define CIDR_NETMASK_IP_LEN 32 +#define INTERFACE_SIZE 10 +#define INTERFACE_LIST 50 +#define MAX_IP_FAMILY_SIZE 10 + + +#define BUFF_LENGTH_64 65 +#define BUFF_LENGTH_256 257 +#define BUFF_MAX 1025 +#define BUFF_MAC 18 +#define BUFF_MIN 17 +#define BUFF_LENGTH_4 4 +#define SSID_SIZE 33 +#define BSSID_BUFF 20 +#define BUFF_LENGTH_24 24 +#define PASSPHRASE_BUFF 385 +#define MAX_SSIDLIST_BUF (48*1024) +#define MAX_FILE_PATH_LEN 4096 + +typedef enum _NetworkManager_EventId_t { + IARM_BUS_NETWORK_MANAGER_EVENT_SET_INTERFACE_ENABLED=50, + IARM_BUS_NETWORK_MANAGER_EVENT_SET_INTERFACE_CONTROL_PERSISTENCE, + IARM_BUS_NETWORK_MANAGER_EVENT_WIFI_INTERFACE_STATE, + IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS, + IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, + IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, + IARM_BUS_NETWORK_MANAGER_EVENT_DEFAULT_INTERFACE, + IARM_BUS_NETWORK_MANAGER_EVENT_INTERNET_CONNECTION_CHANGED, + IARM_BUS_NETWORK_MANAGER_MAX, +} IARM_Bus_NetworkManager_EventId_t; + +typedef enum _IARM_Bus_NMgr_WiFi_EventId_t { + IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged = 1, + IARM_BUS_WIFI_MGR_EVENT_onError, + IARM_BUS_WIFI_MGR_EVENT_onSSIDsChanged, + IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, + IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDsIncr, + IARM_BUS_WIFI_MGR_EVENT_onWIFILNFStateChanged, + IARM_BUS_WIFI_MGR_EVENT_MAX, /*!< Maximum event id*/ +} IARM_Bus_NMgr_WiFi_EventId_t; + + +typedef struct { + char name[16]; + char mac[20]; + unsigned int flags; +} NetSrvMgr_Interface_t; + +typedef struct { + unsigned char size; + NetSrvMgr_Interface_t interfaces[NETSRVMGR_INTERFACES_MAX]; +} IARM_BUS_NetSrvMgr_InterfaceList_t; + +typedef enum _NetworkManager_GetIPSettings_ErrorCode_t +{ + NETWORK_IPADDRESS_ACQUIRED, + NETWORK_IPADDRESS_NOTFOUND, + NETWORK_NO_ROUTE_INTERFACE, + NETWORK_NO_DEFAULT_ROUTE, + NETWORK_DNS_NOT_CONFIGURED, + NETWORK_INVALID_IPADDRESS, +} NetworkManager_GetIPSettings_ErrorCode_t; + +typedef struct { + char interface[16]; + char ipversion[16]; + bool autoconfig; + char ipaddress[MAX_IP_ADDRESS_LEN]; + char netmask[MAX_IP_ADDRESS_LEN]; + char gateway[MAX_IP_ADDRESS_LEN]; + char dhcpserver[MAX_IP_ADDRESS_LEN]; + char primarydns[MAX_IP_ADDRESS_LEN]; + char secondarydns[MAX_IP_ADDRESS_LEN]; + bool isSupported; + NetworkManager_GetIPSettings_ErrorCode_t errCode; +} IARM_BUS_NetSrvMgr_Iface_Settings_t; + +typedef struct { + char interface[16]; + char gateway[MAX_IP_ADDRESS_LEN]; +} IARM_BUS_NetSrvMgr_DefaultRoute_t; + +typedef struct { + char interface[16]; + bool status; +} IARM_BUS_NetSrvMgr_Iface_EventInterfaceStatus_t; + +typedef IARM_BUS_NetSrvMgr_Iface_EventInterfaceStatus_t IARM_BUS_NetSrvMgr_Iface_EventInterfaceEnabledStatus_t; +typedef IARM_BUS_NetSrvMgr_Iface_EventInterfaceStatus_t IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t; + +typedef struct { + char interface[16]; + char ip_address[MAX_IP_ADDRESS_LEN]; + bool is_ipv6; + bool acquired; +} IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t; + +typedef struct { + char oldInterface[16]; + char newInterface[16]; +} IARM_BUS_NetSrvMgr_Iface_EventDefaultInterface_t; + +typedef struct +{ + char server[MAX_HOST_NAME_LEN]; + uint16_t port; + bool ipv6; + char interface[16]; + uint16_t bind_timeout; + uint16_t cache_timeout; + bool sync; + char public_ip[MAX_IP_ADDRESS_LEN]; +} IARM_BUS_NetSrvMgr_Iface_StunRequest_t; + +typedef struct +{ + bool disableConnectivityTest; +} IARM_BUS_NetSrvMgr_configurePNI_t; + + + +/*! Supported values are NONE - 0, WPA - 1, WEP - 2*/ +typedef enum _SsidSecurity +{ + NET_WIFI_SECURITY_NONE = 0, + NET_WIFI_SECURITY_WEP_64, + NET_WIFI_SECURITY_WEP_128, + NET_WIFI_SECURITY_WPA_PSK_TKIP, + NET_WIFI_SECURITY_WPA_PSK_AES, + NET_WIFI_SECURITY_WPA2_PSK_TKIP, + NET_WIFI_SECURITY_WPA2_PSK_AES, + NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP, + NET_WIFI_SECURITY_WPA_ENTERPRISE_AES, + NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP, + NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES, + NET_WIFI_SECURITY_WPA_WPA2_PSK, + NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE, + NET_WIFI_SECURITY_WPA3_PSK_AES, + NET_WIFI_SECURITY_WPA3_SAE, + NET_WIFI_SECURITY_NOT_SUPPORTED = 99, +} SsidSecurity; + + +/*! Event states associated with WiFi connection */ +typedef enum _WiFiStatusCode_t { + WIFI_UNINSTALLED, /**< The device was in an installed state, and was uninstalled */ + WIFI_DISABLED, /**< The device is installed (or was just installed) and has not yet been enabled */ + WIFI_DISCONNECTED, /**< The device is not connected to a network */ + WIFI_PAIRING, /**< The device is not connected to a network, but not yet connecting to a network */ + WIFI_CONNECTING, /**< The device is attempting to connect to a network */ + WIFI_CONNECTED, /**< The device is successfully connected to a network */ + WIFI_FAILED /**< The device has encountered an unrecoverable error with the wifi adapter */ +} WiFiStatusCode_t; + +/*! Error code: A recoverable, unexpected error occurred, + * as defined by one of the following values */ +typedef enum _WiFiErrorCode_t { + WIFI_SSID_CHANGED, /**< The SSID of the network changed */ + WIFI_CONNECTION_LOST, /**< The connection to the network was lost */ + WIFI_CONNECTION_FAILED, /**< The connection failed for an unknown reason */ + WIFI_CONNECTION_INTERRUPTED, /**< The connection was interrupted */ + WIFI_INVALID_CREDENTIALS, /**< The connection failed due to invalid credentials */ + WIFI_NO_SSID, /**< The SSID does not exist */ + WIFI_UNKNOWN, /**< Any other error */ + WIFI_AUTH_FAILED /**< The connection failed due to auth failure */ +} WiFiErrorCode_t; + +typedef enum _WiFiLNFState_t { + LNF_SSID_CONNECTED, /**< Connected to the LNF network */ + LNF_SSID_CONNECT_FAILED, /**< failed connect to the LNF network */ + LNF_ENDPOINT_BACKOFF_TIME, /**< lnf in last requested backoff time */ + LNF_ENDPOINT_CONNECTED, /**< lnf connected to end point and get the LFAT */ + LNF_RECEIVED_PRIVATE_SSID_INFO, /**< lnf process Got private cridential*/ + LNF_SWITCHING_TO_PRIVATE, /**< lnf connected to private*/ + LNF_SSID_DISCONNECTED, /**< disconnected form lnf ssid */ + LNF_ERROR /**< common lnf error replay from lnf library */ +} WiFiLNFState_t; + +typedef struct _IARM_Bus_WiFiSrvMgr_WPS_Parameters_t +{ + bool pbc; + char pin[9]; + bool status; +} IARM_Bus_WiFiSrvMgr_WPS_Parameters_t; + + +/*! LNF states */ +typedef enum _WiFiLNFStatusCode_t { + LNF_UNITIALIZED, /**< Network manager hasn't started the LNF process */ + LNF_IN_PROGRESS, /**< Network manager has started LNF, and waiting for operation to complete */ + CONNECTED_LNF, /**< Connected to the LNF network */ + CONNECTED_PRIVATE, /** Connected to a network that is not LNF */ + DISCONNECTED_NO_LNF_GATEWAY_DETECTED, /**< unable to connect to LNF network */ + DISCONNECTED_GET_LFAT_FAILED, /**< client wasn't able to acquire an LFAT */ + DISCONNECTED_CANT_CONNECT_TO_PRIVATE // client could obtain LFAT, but couldn't connect to private network */ + /**< The device has encountered an unrecoverable error with the wifi adapter */ +} WiFiLNFStatusCode_t; + + +typedef struct _setWiFiAdapter +{ + bool enable; +} setWiFiAdapter; + +typedef struct _WiFiConnection +{ + char ssid[SSID_SIZE]; + char bssid[BSSID_BUFF]; + char security[BUFF_LENGTH_64]; + char passphrase[PASSPHRASE_BUFF]; + SsidSecurity security_mode; + char security_WEPKey[PASSPHRASE_BUFF]; + char security_PSK[PASSPHRASE_BUFF]; + char eapIdentity[BUFF_LENGTH_256]; + char carootcert[MAX_FILE_PATH_LEN]; + char clientcert[MAX_FILE_PATH_LEN]; + char privatekey[MAX_FILE_PATH_LEN]; + bool persistSSIDInfo; +} WiFiConnection; + +typedef struct _WiFiConnectedSSIDInfo +{ + char ssid[SSID_SIZE]; /**< The name of connected SSID. */ + char bssid[BSSID_BUFF]; /**< The the Basic Service Set ID (mac address). */ + char band[BUFF_MIN]; /**< The frequency band at which the client is conneted to. */ + int securityMode; /**< Current WiFi Security Mode used for connection. */ + int frequency; /**< The Frequency wt which the client is connected to. */ + float rate; /**< The Physical data rate in Mbps */ + float noise; /**< The average noise strength in dBm. */ + float signalStrength; /**< The RSSI value in dBm. */ + +} WiFiConnectedSSIDInfo_t; + +typedef struct _WiFiPairedSSIDInfo +{ + char ssid[SSID_SIZE]; /**< The name of connected SSID. */ + char bssid[BSSID_BUFF]; /**< The the Basic Service Set ID (mac address). */ + char security[BUFF_LENGTH_64]; /**< security of AP */ + SsidSecurity secMode; +} WiFiPairedSSIDInfo_t; + + +typedef enum _WiFiConnectionTypeCode_t { + WIFI_CON_UNKNOWN, + WIFI_CON_WPS, + WIFI_CON_MANUAL, + WIFI_CON_LNF, + WIFI_CON_PRIVATE, + WIFI_CON_MAX, +} WiFiConnectionTypeCode_t; + + +typedef struct _IARM_Bus_WiFiSrvMgr_Param_t { + union { + WiFiLNFStatusCode_t wifiLNFStatus; + WiFiStatusCode_t wifiStatus; + setWiFiAdapter setwifiadapter; + WiFiConnection connect; + WiFiConnection saveSSID; + WiFiConnection clearSSID; + WiFiConnectedSSIDInfo_t getConnectedSSID; + WiFiPairedSSIDInfo_t getPairedSSIDInfo; + WiFiConnectionTypeCode_t connectionType; + struct getPairedSSID { + char ssid[SSID_SIZE]; + } getPairedSSID; + bool isPaired; + } data; + bool status; +} IARM_Bus_WiFiSrvMgr_Param_t; + +typedef struct _IARM_BUS_NetSrvMgr_Iface_EventData_t { + union { + char activeIface[INTERFACE_SIZE]; + char allNetworkInterfaces[INTERFACE_LIST]; + char setInterface[INTERFACE_SIZE]; + char activeIfaceIpaddr[MAX_IP_ADDRESS_LEN]; + }; + char interfaceCount; + bool isInterfaceEnabled; + bool persist; + char ipfamily[MAX_IP_FAMILY_SIZE]; +} IARM_BUS_NetSrvMgr_Iface_EventData_t; + +typedef struct _IARM_BUS_WiFiSrvMgr_EventData_t { + union { + struct _WIFI_STATECHANGE_DATA { + WiFiStatusCode_t state; + } wifiStateChange; + struct _WIFI_ERROR { + WiFiErrorCode_t code; + } wifiError; + struct _WIFI_SSID_LIST { + char ssid_list[MAX_SSIDLIST_BUF]; + bool more_data; + } wifiSSIDList; + struct _WIFI_LNF_STATE { + WiFiLNFState_t state; + float backOffTime; + }wifilnfState; + } data; +} IARM_BUS_WiFiSrvMgr_EventData_t; + +typedef struct _wifiSsidData_t { + char jdata[MAX_SSIDLIST_BUF]; /**< Buffer containing the serialized data. */ + size_t jdataLen; /**< Length of the data buffer. */ +} wifiSsidData_t; + +typedef struct _IARM_Bus_WiFiSrvMgr_SsidList_Param_t { + wifiSsidData_t curSsids; + bool status; +} IARM_Bus_WiFiSrvMgr_SsidList_Param_t; + + +#define IARM_BUS_NETSRVMGR_API_getInterfaceList "getInterfaceList" +#define IARM_BUS_NETSRVMGR_API_getDefaultInterface "getDefaultInterface" +#define IARM_BUS_NETSRVMGR_API_setDefaultInterface "setDefaultInterface" +#define IARM_BUS_NETSRVMGR_API_isInterfaceEnabled "isInterfaceEnabled" +#define IARM_BUS_NETSRVMGR_API_setInterfaceEnabled "setInterfaceEnabled" +#define IARM_BUS_NETSRVMGR_API_setIPSettings "setIPSettings" +#define IARM_BUS_NETSRVMGR_API_getIPSettings "getIPSettings" +#define IARM_BUS_NETSRVMGR_API_isAvailable "isAvailable" +#define IARM_BUS_WIFI_MGR_API_getAvailableSSIDsAsync "getAvailableSSIDsAsync" /**< Retrieve array of strings representing SSIDs */ +#define IARM_BUS_WIFI_MGR_API_getAvailableSSIDsAsyncIncr "getAvailableSSIDsAsyncIncr" /**< Retrieve array of strings representing SSIDs in an incremental way */ +#define IARM_BUS_WIFI_MGR_API_stopProgressiveWifiScanning "stopProgressiveWifiScanning" /**< Stop any in-progress wifi progressive scanning thread */ +#define IARM_BUS_WIFI_MGR_API_initiateWPSPairing2 "initiateWPSPairing2" /**< Initiate connection via WPS via either Push Button or PIN */ +#define IARM_BUS_WIFI_MGR_API_cancelWPSPairing "cancelWPSPairing" /**< Cancel in-progress WPS */ +#define IARM_BUS_WIFI_MGR_API_getConnectedSSID "getConnectedSSID" /**< Return properties of the currently connected SSID */ +#define IARM_BUS_WIFI_MGR_API_saveSSID "saveSSID" /**< Save SSID and passphrase */ +#define IARM_BUS_WIFI_MGR_API_clearSSID "clearSSID" /**< Clear given SSID */ +#define IARM_BUS_WIFI_MGR_API_connect "connect" /**< Connect with given or saved SSID and passphrase */ +#define IARM_BUS_WIFI_MGR_API_disconnectSSID "disconnectSSID" /**< Disconnect from current SSID */ +#define IARM_BUS_WIFI_MGR_API_getCurrentState "getCurrentState" /**< Retrieve current state */ + diff --git a/tests/l1Test/CMakeLists.txt b/tests/l1Test/CMakeLists.txt new file mode 100644 index 000000000..b552a49bb --- /dev/null +++ b/tests/l1Test/CMakeLists.txt @@ -0,0 +1,97 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2024 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# +message ("building l1 test") + +find_package(CURL) +find_package(PkgConfig REQUIRED) +find_package(${NAMESPACE}Core REQUIRED) +find_package(${NAMESPACE}Plugins REQUIRED) + +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip +) + +FetchContent_MakeAvailable(googletest) + +include_directories(${PROJECT_SOURCE_DIR}/interface) +include_directories(${PROJECT_SOURCE_DIR}/plugin/rdk) +include_directories(${PROJECT_SOURCE_DIR}/plugin) + +set(NM_ROUTER_DISCOVERY_L1_TEST "upnpcli_l1_test") + +add_executable(${NM_ROUTER_DISCOVERY_L1_TEST} + ${CMAKE_SOURCE_DIR}/tests/l1Test/l1_test_routediscovery.cpp + ${CMAKE_SOURCE_DIR}/tools/upnp/UpnpDiscoveryManager.cpp +) + +target_link_libraries(${NM_ROUTER_DISCOVERY_L1_TEST} PRIVATE + gmock_main + ${GLIB_LIBRARIES} + ${LIBSOUP_LIBRARIES} + ${GUPNP_LIBRARIES} + ${GSSDP_LIBRARIES} +) + +set_target_properties(${NM_ROUTER_DISCOVERY_L1_TEST} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) + +target_include_directories(${NM_ROUTER_DISCOVERY_L1_TEST} PRIVATE + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include + ${PROJECT_SOURCE_DIR}/tools/upnp + ${GUPNP_INCLUDE_DIRS} + ${GLIB_INCLUDE_DIRS} + ${LIBSOUP_INCLUDE_DIRS} + ${GSSDP_INCLUDE_DIRS} +) + +install(TARGETS ${NM_ROUTER_DISCOVERY_L1_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) + +set(NM_CLASS_L1_TEST "class_l1_test") + +add_executable(${NM_CLASS_L1_TEST} + ${CMAKE_SOURCE_DIR}/tests/l1Test/l1_test_stunclient.cpp + ${CMAKE_SOURCE_DIR}/tests/l1Test/l1_test_connectivity.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp +) + +target_link_libraries(${NM_CLASS_L1_TEST} PRIVATE + gmock_main + ${CURL_LIBRARIES} + ${NAMESPACE}Core::${NAMESPACE}Core +) + +set_target_properties(${NM_CLASS_L1_TEST} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) + +target_include_directories(${NM_CLASS_L1_TEST} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include +) + +install(TARGETS ${NM_CLASS_L1_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/unittest/test_NetworkManagerConnectivity.cpp b/tests/l1Test/l1_test_connectivity.cpp similarity index 97% rename from tests/unittest/test_NetworkManagerConnectivity.cpp rename to tests/l1Test/l1_test_connectivity.cpp index a1b5d7b01..b34408be7 100644 --- a/tests/unittest/test_NetworkManagerConnectivity.cpp +++ b/tests/l1Test/l1_test_connectivity.cpp @@ -63,5 +63,5 @@ TEST_F(ConnectivityMonitorTest, SetEndpoints_InvalidShortEndpoints) { TEST_F(ConnectivityMonitorTest, SetEndpoints_DuplicateEndpoints) { std::vector endpoints = {"https://github.com", "https://github.com"}; cm.setConnectivityMonitorEndpoints(endpoints); - EXPECT_EQ(cm.getConnectivityMonitorEndpoints().size(), 2); + EXPECT_EQ((int)cm.getConnectivityMonitorEndpoints().size(), 2); } diff --git a/tests/l1Test/l1_test_routediscovery.cpp b/tests/l1Test/l1_test_routediscovery.cpp new file mode 100644 index 000000000..49b817165 --- /dev/null +++ b/tests/l1Test/l1_test_routediscovery.cpp @@ -0,0 +1,100 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2025 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include +#include +#include +#include + +using ::testing::_; +using ::testing::Return; +using ::testing::Mock; + +class UpnpDiscoveryManagerTest : public ::testing::Test { +protected: + UpnpDiscoveryManager upnpDiscover; + GMainLoop* mainLoop; + void SetUp() override { + mainLoop = g_main_loop_new(nullptr, FALSE); + } +}; + +std::string getInterfaceWithDefaultRoute() { + std::string command = "ip -4 route show | grep default | awk '{print $5}'"; + std::array buffer; + std::string result; + + std::unique_ptr pipe(popen(command.c_str(), "r"), pclose); + if (!pipe) { + throw std::runtime_error("popen() failed!"); + } + + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + result += buffer.data(); + } + + // Remove trailing newline character + if (!result.empty() && result.back() == '\n') { + result.pop_back(); + } + return result; +} + +TEST_F(UpnpDiscoveryManagerTest, FindGatewayDeviceTest) +{ + // Invalid interface name + EXPECT_EQ(false, upnpDiscover.findGatewayDevice("123")); + + // Get router details on actual interface + std::string interfaceName = getInterfaceWithDefaultRoute(); + if (!interfaceName.empty()) { + std::cout << "Interface with default route: " << interfaceName << std::endl; + } else { + std::cout << "No default route interface found." << std::endl; + } + + // Valid interface name + EXPECT_EQ(true, upnpDiscover.findGatewayDevice(interfaceName)); +} + +TEST_F(UpnpDiscoveryManagerTest, routerDiscovery) +{ + auto threadHandler = [&]() { + std::this_thread::sleep_for(std::chrono::seconds(10)); + std::cout << "Thread finished sleeping." << std::endl; + if (this->mainLoop) + { + g_main_loop_quit(this->mainLoop); + g_main_loop_unref(this->mainLoop); + } + }; + // Get router details on actual interface + std::string interfaceName = getInterfaceWithDefaultRoute(); + if (!interfaceName.empty()) { + std::cout << "Interface with default route: " << interfaceName << std::endl; + } else { + std::cout << "No default route interface found." << std::endl; + } + mainLoop = g_main_loop_new(NULL, FALSE); + std::thread workerThread(threadHandler); + // Get the router details, mostly will timeout in corporate network + EXPECT_EQ(true, upnpDiscover.findGatewayDevice(interfaceName)); + g_main_loop_run(mainLoop); + workerThread.join(); +} diff --git a/tests/unittest/test_NetworkManagerStunClient.cpp b/tests/l1Test/l1_test_stunclient.cpp similarity index 100% rename from tests/unittest/test_NetworkManagerStunClient.cpp rename to tests/l1Test/l1_test_stunclient.cpp diff --git a/tests/l2Test/CMakeLists.txt b/tests/l2Test/CMakeLists.txt new file mode 100644 index 000000000..9ded43a5b --- /dev/null +++ b/tests/l2Test/CMakeLists.txt @@ -0,0 +1,85 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2024 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# +message ("building l2 test") + +set(NM_RDK_PROXY_L2_TEST "rdkproxy_l2_test") + +find_package(CURL) +find_package(PkgConfig REQUIRED) +find_package(${NAMESPACE}Core REQUIRED) +find_package(${NAMESPACE}Plugins REQUIRED) + +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip +) + +FetchContent_MakeAvailable(googletest) + +add_executable(${NM_RDK_PROXY_L2_TEST} + ${CMAKE_SOURCE_DIR}/tests/l2Test/l2_test_rdkproxy.cpp + ${CMAKE_SOURCE_DIR}/tests/l2Test/l2_test_rdkproxyEvent.cpp + ${CMAKE_SOURCE_DIR}/tests/l2Test/l2_test_rdkproxyImpl.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/Wraps.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerJsonRpc.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerImplementation.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp + ${CMAKE_SOURCE_DIR}/plugin/rdk/NetworkManagerRDKProxy.cpp + ${PROXY_STUB_SOURCES} +) + +set_target_properties(${NM_RDK_PROXY_L2_TEST} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) + +target_compile_options(${NM_RDK_PROXY_L2_TEST} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) + +include_directories(${PROJECT_SOURCE_DIR}/interface) +include_directories(${PROJECT_SOURCE_DIR}/plugin/rdk) +include_directories(${PROJECT_SOURCE_DIR}/plugin) +include_directories(${PROJECT_SOURCE_DIR}/tests/mocks) +include_directories(${PROJECT_SOURCE_DIR}/tests/mocks/thunder) +include_directories(${PROJECT_SOURCE_DIR}/../install/usr/include/rdk/iarmbus/) +include_directories(${PROJECT_SOURCE_DIR}/tools/upnp/) + +target_include_directories(${NM_RDK_PROXY_L2_TEST} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include +) + +target_link_options(${NM_RDK_PROXY_L2_TEST} PRIVATE -Wl,-wrap,system -Wl,-wrap,popen -Wl,-wrap,syslog -Wl,-wrap,pclose -Wl,-wrap,getmntent -Wl,-wrap,setmntent -Wl,-wrap,v_secure_popen -Wl,-wrap,v_secure_pclose -Wl,-wrap,v_secure_system) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") + +target_link_libraries(${NM_RDK_PROXY_L2_TEST} PRIVATE + gmock_main + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ${CURL_LIBRARIES} +) + +install(TARGETS ${NM_RDK_PROXY_L2_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/l2Test/l2_test_rdkproxy.cpp b/tests/l2Test/l2_test_rdkproxy.cpp new file mode 100644 index 000000000..163728534 --- /dev/null +++ b/tests/l2Test/l2_test_rdkproxy.cpp @@ -0,0 +1,1556 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ +#include +#include +#include +#include +#include + +#include "FactoriesImplementation.h" +#include "IarmBusMock.h" +#include "WrapsMock.h" +#include "ServiceMock.h" +#include "ThunderPortability.h" +#include "COMLinkMock.h" +#include "IarmBusMock.h" +#include "WorkerPoolImplementation.h" +#include "NetworkManagerImplementation.h" +#include "NetworkManagerRDKProxy.h" +#include "NetworkManagerLogger.h" +#include "NetworkManager.h" + +using namespace WPEFramework; +using ::testing::NiceMock; + +class NetworkManagerTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + DECL_CORE_JSONRPC_CONX connection; + Core::JSONRPC::Message message; + string response; + + // Mock classes + IarmBusImplMock *p_iarmBusImplMock = nullptr; + WrapsImplMock *p_wrapsImplMock = nullptr; + Core::ProxyType NetworkManagerImpl; + + NiceMock comLinkMock; + NiceMock service; + PLUGINHOST_DISPATCHER* dispatcher; + Core::ProxyType workerPool; + NiceMock factoriesImplementation; + + NetworkManagerTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , INIT_CONX(1, 0) + , workerPool(Core::ProxyType::Create(2, Core::Thread::DefaultStackSize(), 16)) + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + p_wrapsImplMock = new NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Invoke( + [this]() { + return &comLinkMock; + })); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return( + "{" + " \"locator\":\"libWPEFrameworkNetworkManager.so\"," + " \"classname\":\"NetworkManager\"," + " \"callsign\":\"org.rdk.NetworkManager\"," + " \"startuporder\":55," + " \"autostart\":false," + " \"configuration\":{" + " \"root\":{" + " \"outofprocess\":true," + " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" + " }," + " \"connectivity\":{" + " \"endpoint_1\":\"http://clients3.google.com/generate_204\"," + " \"interval\":60" + " }," + " \"stun\":{" + " \"endpoint\":\"stun.l.google.com\"," + " \"port\":19302," + " \"interval\":30" + " }," + " \"loglevel\":3" + " }" + "}" + )); + + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const RPC::Object& object, const uint32_t waitTime, uint32_t& connectionId) { + NetworkManagerImpl = Core::ProxyType::Create(); + return &NetworkManagerImpl; + })); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Init(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME))) + .WillByDefault(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + PluginHost::IFactories::Assign(&factoriesImplementation); + + Core::IWorkerPool::Assign(&(*workerPool)); + workerPool->Run(); + + dispatcher = static_cast( + plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); + dispatcher->Activate(&service); + response = plugin->Initialize(&service); + EXPECT_EQ(string(""), response); + NetworkManagerLogger::SetLevel(static_cast(NetworkManagerLogger::INFO_LEVEL)); // Set log level to DEBUG_LEVEL + } + + virtual void SetUp() override + { + // remove any previous connectivity endpoints file + } + + virtual ~NetworkManagerTest() override + { + plugin->Deinitialize(&service); + + dispatcher->Deactivate(); + dispatcher->Release(); + + Core::IWorkerPool::Assign(nullptr); + workerPool.Release(); + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + } +}; + +TEST_F(NetworkManagerTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("SetLogLevel"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetLogLevel"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetAvailableInterfaces"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetPrimaryInterface"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetInterfaceState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("SetInterfaceState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetIPSettings"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("SetIPSettings"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetStunEndpoint"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("SetStunEndpoint"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetConnectivityTestEndpoints"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("SetConnectivityTestEndpoints"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("IsConnectedToInternet"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetCaptivePortalURI"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetPublicIP"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("Ping"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("Trace"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("StartWiFiScan"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("StopWiFiScan"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetKnownSSIDs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("AddToKnownSSIDs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("RemoveKnownSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("WiFiConnect"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("WiFiDisconnect"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetConnectedSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("StartWPS"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("StopWPS"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetWifiState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetWiFiSignalQuality"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetSupportedSecurityModes"))); +} + +TEST_F(NetworkManagerTest, LogLevel) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetLogLevel"), _T("{\"level\":1}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetLogLevel"), _T(""), response)); + EXPECT_EQ(response, _T("{\"level\":1,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetLogLevel"), _T("{\"level\":2}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetLogLevel"), _T(""), response)); + EXPECT_EQ(response, _T("{\"level\":2,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetLogLevel"), _T("{\"level\":3}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetLogLevel"), _T(""), response)); + EXPECT_EQ(response, _T("{\"level\":3,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetLogLevel"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetLogLevel"), _T(""), response)); + EXPECT_EQ(response, _T("{\"level\":3,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetLogLevel"), _T("{\"level\":4}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetLogLevel"), _T(""), response)); + EXPECT_EQ(response, _T("{\"level\":4,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetLogLevel"), _T("{\"levelInvalid\":4}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, GetAvailableInterfaces) +{ + IARM_BUS_NetSrvMgr_InterfaceList_t mockList = {}; + mockList.size = 2; + // eth0 + strcpy(mockList.interfaces[0].name, "eth0"); + strcpy(mockList.interfaces[0].mac, "AA:AA:AA:AA:AA:AA"); + mockList.interfaces[0].flags = IFF_UP | IFF_RUNNING; // enabled and connected + // wlan0 + strcpy(mockList.interfaces[1].name, "wlan0"); + strcpy(mockList.interfaces[1].mac, "BB:BB:BB:BB:BB:BB"); + mockList.interfaces[1].flags = IFF_UP; // enabled, not connected + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_getInterfaceList), + ::testing::NotNull(), sizeof(mockList))) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockList](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockList, sizeof(mockList)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T(""), response)); + std::string expectedResponse = + _T("{\"interfaces\":[") + _T("{\"type\":\"ETHERNET\",\"name\":\"eth0\",\"mac\":\"AA:AA:AA:AA:AA:AA\",\"enabled\":true,\"connected\":true},") + _T("{\"type\":\"WIFI\",\"name\":\"wlan0\",\"mac\":\"BB:BB:BB:BB:BB:BB\",\"enabled\":true,\"connected\":false}") + _T("],\"success\":true}"); + EXPECT_EQ(response, expectedResponse); +} + +TEST_F(NetworkManagerTest, GetAvailableInterfaces_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_getInterfaceList), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, GetPrimaryInterface) +{ + IARM_BUS_NetSrvMgr_DefaultRoute_t mockDefaultRoute = {}; + strcpy(mockDefaultRoute.interface, "eth0"); + strcpy(mockDefaultRoute.gateway, "192.168.1.1"); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_getDefaultInterface), + ::testing::NotNull(), sizeof(mockDefaultRoute))) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockDefaultRoute](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockDefaultRoute, sizeof(mockDefaultRoute)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); + EXPECT_EQ(response, _T("{\"interface\":\"eth0\",\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetPrimaryInterface_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_getDefaultInterface), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetInterfaceState) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_setInterfaceEnabled), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([](const char*, const char*, void* arg, size_t) { + IARM_BUS_NetSrvMgr_Iface_EventData_t* ifaceData = + static_cast(arg); + // Verify the parameters + EXPECT_TRUE(ifaceData->isInterfaceEnabled); + EXPECT_TRUE(ifaceData->persist); + EXPECT_STREQ(ifaceData->setInterface, "WIFI"); // RDKProxy converts wlan0 to WIFI + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"), + _T("{\"interface\":\"wlan0\",\"enabled\":true}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_setInterfaceEnabled), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([](const char*, const char*, void* arg, size_t) { + IARM_BUS_NetSrvMgr_Iface_EventData_t* ifaceData = + static_cast(arg); + // Verify the parameters + EXPECT_TRUE(ifaceData->isInterfaceEnabled); + EXPECT_TRUE(ifaceData->persist); + EXPECT_STREQ(ifaceData->setInterface, "ETHERNET"); // RDKProxy converts eth0 to ETHERNET + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"), + _T("{\"interface\":\"eth0\",\"enabled\":true}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, SetInterfaceState_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_setInterfaceEnabled), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"), + _T("{\"interface\":\"wlan0\",\"enabled\":true}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, GetInterfaceState_wifi) +{ + IARM_BUS_NetSrvMgr_Iface_EventData_t mockIfaceData = {}; + strcpy(mockIfaceData.setInterface, "WIFI"); // Interface is converted to WIFI for wlan0 + mockIfaceData.isInterfaceEnabled = true; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_isInterfaceEnabled), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockIfaceData](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockIfaceData, sizeof(mockIfaceData)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), + _T("{\"interface\":\"wlan0\"}"), response)); + EXPECT_EQ(response, _T("{\"enabled\":true,\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetInterfaceState_eth0) +{ + IARM_BUS_NetSrvMgr_Iface_EventData_t mockIfaceData = {}; + strcpy(mockIfaceData.setInterface, "ETHERNET"); // Interface is converted to ETHERNET for eth0 + mockIfaceData.isInterfaceEnabled = true; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_isInterfaceEnabled), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockIfaceData](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockIfaceData, sizeof(mockIfaceData)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), + _T("{\"interface\":\"eth0\"}"), response)); + EXPECT_EQ(response, _T("{\"enabled\":true,\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetIPSettings) +{ + IARM_BUS_NetSrvMgr_Iface_Settings_t mockSettings = {}; + strcpy(mockSettings.interface, "eth0"); + strcpy(mockSettings.ipversion, "IPv4"); + mockSettings.autoconfig = true; + strcpy(mockSettings.ipaddress, "192.168.1.100"); + strcpy(mockSettings.netmask, "255.255.255.0"); + strcpy(mockSettings.gateway, "192.168.1.1"); + strcpy(mockSettings.primarydns, "8.8.8.8"); + strcpy(mockSettings.secondarydns, "8.8.4.4"); + mockSettings.isSupported = true; + mockSettings.errCode = NETWORK_IPADDRESS_ACQUIRED; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_getIPSettings), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockSettings](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockSettings, sizeof(mockSettings)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), + _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\"}"), response)); + + // The response should include all IP settings in JSON format + std::string expectedResponse = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"ula\":\"\",\"dhcpserver\":\"\",\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\",\"success\":true}"); + EXPECT_EQ(response, expectedResponse); +} + +TEST_F(NetworkManagerTest, GetIPSettings_IPv6) +{ + IARM_BUS_NetSrvMgr_Iface_Settings_t mockSettings = {}; + strcpy(mockSettings.interface, "eth0"); + strcpy(mockSettings.ipversion, "IPv6"); + mockSettings.autoconfig = true; + strcpy(mockSettings.ipaddress, "2001:db8::1"); + strcpy(mockSettings.netmask, "64"); + strcpy(mockSettings.gateway, "2001:db8::fe"); + strcpy(mockSettings.primarydns, "2001:4860:4860::8888"); + strcpy(mockSettings.secondarydns, "2001:4860:4860::8844"); + mockSettings.isSupported = true; + mockSettings.errCode = NETWORK_IPADDRESS_ACQUIRED; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_getIPSettings), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockSettings](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockSettings, sizeof(mockSettings)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), + _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv6\"}"), response)); + + // The response should include all IP settings in JSON format + std::string expectedResponse = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv6\",\"autoconfig\":true,\"ipaddress\":\"2001:db8::1\",\"prefix\":64,\"ula\":\"\",\"dhcpserver\":\"\",\"gateway\":\"2001:db8::fe\",\"primarydns\":\"2001:4860:4860::8888\",\"secondarydns\":\"2001:4860:4860::8844\",\"success\":true}"); + EXPECT_EQ(response, expectedResponse); +} + +TEST_F(NetworkManagerTest, GetIPSettings_NoInterfaceNoIpVersion) { + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_StaticIPv4) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_setIPSettings), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([](const char*, const char*, void* arg, size_t) { + IARM_BUS_NetSrvMgr_Iface_Settings_t* settings = + static_cast(arg); + + // Verify the parameters + EXPECT_STREQ(settings->interface, "ETHERNET"); + EXPECT_STREQ(settings->ipversion, "IPv4"); + EXPECT_EQ(settings->autoconfig, false); + EXPECT_STREQ(settings->ipaddress, "192.168.1.100"); + EXPECT_STREQ(settings->netmask, "255.255.255.0"); + EXPECT_STREQ(settings->gateway, "192.168.1.1"); + EXPECT_STREQ(settings->primarydns, "8.8.8.8"); + EXPECT_STREQ(settings->secondarydns, "8.8.4.4"); + + return IARM_RESULT_SUCCESS; + }) + )); + + // Test setting static IP configuration + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\"}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_DHCP) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_setIPSettings), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([](const char*, const char*, void* arg, size_t) { + IARM_BUS_NetSrvMgr_Iface_Settings_t* settings = + static_cast(arg); + + // Verify the parameters + EXPECT_STREQ(settings->interface, "ETHERNET"); + EXPECT_STREQ(settings->ipversion, "IPv4"); + EXPECT_EQ(settings->autoconfig, true); + + return IARM_RESULT_SUCCESS; + }) + )); + + // Test setting DHCP configuration + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_WiFi) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_setIPSettings), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([](const char*, const char*, void* arg, size_t) { + IARM_BUS_NetSrvMgr_Iface_Settings_t* settings = + static_cast(arg); + + // Verify the parameters for WiFi interface + EXPECT_STREQ(settings->interface, "WIFI"); + EXPECT_STREQ(settings->ipversion, "IPv4"); + EXPECT_EQ(settings->autoconfig, false); + EXPECT_STREQ(settings->ipaddress, "192.168.1.100"); + EXPECT_STREQ(settings->netmask, "255.255.255.0"); + EXPECT_STREQ(settings->gateway, "192.168.1.1"); + + return IARM_RESULT_SUCCESS; + }) + )); + + std::string request = _T("{\"interface\":\"wlan0\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\"}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_InvalidInterface) +{ + // Test with an invalid interface name + std::string request = _T("{\"interface\":\"invalid0\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\"}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_InvalidIPVersion) +{ + // Test with an invalid IP version + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv5\",\"autoconfig\":false,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\"}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_IPv6NotSupported) +{ + // Test with IPv6, which is marked as not supported in the implementation + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv6\",\"autoconfig\":false,\"ipaddress\":\"2001:db8::1\",\"prefix\":64,\"gateway\":\"2001:db8::1:1\"}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_InvalidPrefix) +{ + // Test with an invalid prefix value (greater than 32 for IPv4) + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddress\":\"192.168.1.100\",\"prefix\":33,\"gateway\":\"192.168.1.1\"}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_InvalidIPFormat) +{ + // Test with an invalid IP address format + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddress\":\"192.168.1\",\"prefix\":24,\"gateway\":\"192.168.1.1\"}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_SameIPAndGateway) +{ + // Test when IP and gateway are the same (should fail validation) + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddress\":\"192.168.1.1\",\"prefix\":24,\"gateway\":\"192.168.1.1\"}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_DifferentBroadcastDomain) +{ + // Test when IP and gateway are not in the same broadcast domain + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.2.1\"}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_IPEqualsBroadcast) +{ + // Test when IP equals broadcast address + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddress\":\"192.168.1.255\",\"prefix\":24,\"gateway\":\"192.168.1.1\"}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_GatewayEqualsBroadcast) +{ + // Test when gateway equals broadcast address + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.255\"}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_APICallFailed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_setIPSettings), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\"}"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, StartWiFiScan_Success) +{ + IARM_Bus_WiFiSrvMgr_SsidList_Param_t mockParam = {}; + mockParam.status = true; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_getAvailableSSIDsAsync), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockParam](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockParam, sizeof(mockParam)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), + _T("{\"frequency\":\"2.4GHz\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, StartWiFiScan_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_getAvailableSSIDsAsync), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), + _T("{\"frequency\":\"2.4GHz\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, StopWiFiScan_Success) +{ + IARM_Bus_WiFiSrvMgr_Param_t mockParam = {}; + mockParam.status = true; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_stopProgressiveWifiScanning), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockParam](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockParam, sizeof(mockParam)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StopWiFiScan"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, StopWiFiScan_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_stopProgressiveWifiScanning), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StopWiFiScan"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, GetKnownSSIDs_Success) +{ + IARM_Bus_WiFiSrvMgr_Param_t mockParam = {}; + mockParam.status = true; + strncpy(mockParam.data.getConnectedSSID.ssid, "TestNetwork", SSID_SIZE - 1); + mockParam.data.getConnectedSSID.securityMode = NET_WIFI_SECURITY_WPA_WPA2_PSK; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_getConnectedSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockParam](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockParam, sizeof(mockParam)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetKnownSSIDs"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ssids\":[\"TestNetwork\"],\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetKnownSSIDs_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_getConnectedSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetKnownSSIDs"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, AddToKnownSSIDs_Success) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_saveSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([](const char*, const char*, void* arg, size_t) { + IARM_Bus_WiFiSrvMgr_Param_t* param = static_cast(arg); + + // Verify the parameters + EXPECT_STREQ(param->data.connect.ssid, "TestNetwork"); + EXPECT_STREQ(param->data.connect.passphrase, "TestPassword"); + EXPECT_EQ(param->data.connect.security_mode, NET_WIFI_SECURITY_WPA2_PSK_AES); + param->status = true; + + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("AddToKnownSSIDs"), + _T("{\"ssid\":\"TestNetwork\",\"passphrase\":\"TestPassword\",\"security\":1}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, AddToKnownSSIDs_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_saveSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("AddToKnownSSIDs"), + _T("{\"ssid\":\"TestNetwork\",\"passphrase\":\"TestPassword\",\"security\":1}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, RemoveKnownSSID_Success) +{ + IARM_Bus_WiFiSrvMgr_Param_t mockParam = {}; + mockParam.status = true; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_clearSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockParam](const char*, const char*, void* arg, size_t) { + IARM_Bus_WiFiSrvMgr_Param_t* param = static_cast(arg); + param->status = true; + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("RemoveKnownSSID"), + _T("{\"ssid\":\"TestNetwork\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, RemoveKnownSSID_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_clearSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("RemoveKnownSSID"), + _T("{\"ssid\":\"TestNetwork\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, WiFiConnect_Success) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_connect), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([](const char*, const char*, void* arg, size_t) { + IARM_Bus_WiFiSrvMgr_Param_t* param = static_cast(arg); + + // Verify the parameters + EXPECT_STREQ(param->data.connect.ssid, "TestNetwork"); + EXPECT_STREQ(param->data.connect.passphrase, "TestPassword"); + EXPECT_EQ(param->data.connect.security_mode, NET_WIFI_SECURITY_WPA2_PSK_AES); + param->status = true; + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), + _T("{\"ssid\":\"TestNetwork\",\"passphrase\":\"TestPassword\",\"security\":1}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, WiFiConnectEAP_Success) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_connect), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([](const char*, const char*, void* arg, size_t) { + IARM_Bus_WiFiSrvMgr_Param_t* param = static_cast(arg); + + // Verify the parameters + EXPECT_STREQ(param->data.connect.ssid, "TestNetwork"); + EXPECT_STREQ(param->data.connect.passphrase, "TestPassword"); + EXPECT_STREQ(param->data.connect.clientcert, "test_client_cert"); + EXPECT_STREQ(param->data.connect.privatekey, "test_private_key"); + EXPECT_EQ(param->data.connect.security_mode, NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE); + EXPECT_TRUE(param->data.connect.persistSSIDInfo); + param->status = true; + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), + _T("{\"ssid\":\"TestNetwork\",\"passphrase\":\"TestPassword\",\"security\":3,\"ca_cert\":\"test_ca_cert\",\"client_cert\":\"test_client_cert\",\"private_key\":\"test_private_key\",\"private_key_passwd\":\"test_private_key_passwd\",\"eap\":\"test_eap\",\"eap_identity\":\"test_eap_identity\",\"eap_password\":\"test_eap_password\",\"eap_phase1\":\"test_eap_phase1\",\"eap_phase2\":\"test_eap_phase2\",\"persist\":true}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, WiFiConnect_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_connect), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), + _T("{\"ssid\":\"TestNetwork\",\"passphrase\":\"TestPassword\",\"security\":1}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, WiFiDisconnect_Success) +{ + IARM_Bus_WiFiSrvMgr_Param_t mockParam = {}; + mockParam.status = true; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_disconnectSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockParam](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockParam, sizeof(mockParam)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiDisconnect"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, WiFiDisconnect_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_disconnectSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiDisconnect"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, GetConnectedSSID_Success) +{ + IARM_Bus_WiFiSrvMgr_Param_t mockParam = {}; + mockParam.status = true; + strncpy(mockParam.data.getConnectedSSID.ssid, "TestNetwork", SSID_SIZE - 1); + mockParam.data.getConnectedSSID.securityMode = NET_WIFI_SECURITY_WPA2_PSK_AES; + mockParam.data.getConnectedSSID.signalStrength = -30.00; // Example signal strength + mockParam.data.getConnectedSSID.frequency = 2412; // Example frequency in MHz + mockParam.data.getConnectedSSID.rate = 0; // Example rate + mockParam.data.getConnectedSSID.noise = 6; // Example noise level + strncpy(mockParam.data.getConnectedSSID.bssid, "AB:CD:EF:GH:IJ:KL", BSSID_BUFF - 1); // Example BSSID + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_getConnectedSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockParam](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockParam, sizeof(mockParam)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":\"-30\",\"frequency\":\"2.412\",\"rate\":\"0\",\"noise\":\"0\",\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetConnectedSSID_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_getConnectedSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, StartWPS_Success) +{ + IARM_Bus_WiFiSrvMgr_WPS_Parameters_t mockWpsParams = {}; + mockWpsParams.pbc = true; + mockWpsParams.status = true; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_initiateWPSPairing2), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockWpsParams](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockWpsParams, sizeof(mockWpsParams)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWPS"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, StartWPS_WIFI_WPS_PIN_Success) +{ + IARM_Bus_WiFiSrvMgr_WPS_Parameters_t mockWpsParams = {}; + mockWpsParams.pbc = true; + mockWpsParams.status = true; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_initiateWPSPairing2), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockWpsParams](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockWpsParams, sizeof(mockWpsParams)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWPS"), _T("{\"method\":\"PIN\", \"pin\":\"12345678\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, StartWPS_WIFI_WPS_SERIALIZED_PIN_Success) +{ + IARM_Bus_WiFiSrvMgr_WPS_Parameters_t mockWpsParams = {}; + mockWpsParams.pbc = true; + mockWpsParams.status = true; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_initiateWPSPairing2), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockWpsParams](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockWpsParams, sizeof(mockWpsParams)); + return IARM_RESULT_SUCCESS; + }) + )); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWPS"), _T("{\"method\":\"SERIALIZED_PIN\", \"pin\":\"12345678\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, StartWPS_Failed) +{ + IARM_Bus_WiFiSrvMgr_WPS_Parameters_t mockWpsParams = {}; + mockWpsParams.pbc = true; + mockWpsParams.status = false; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_initiateWPSPairing2), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockWpsParams](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockWpsParams, sizeof(mockWpsParams)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWPS"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, StopWPS_Success) +{ + IARM_Bus_WiFiSrvMgr_Param_t param; + memset(¶m, 0, sizeof(param)); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_cancelWPSPairing), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([¶m](const char*, const char*, void* arg, size_t) { + memcpy(arg, ¶m, sizeof(param)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StopWPS"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, StopWPS_Failed) +{ + IARM_Bus_WiFiSrvMgr_Param_t param; + memset(¶m, 0, sizeof(param)); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_cancelWPSPairing), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StopWPS"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, GetWifiState) +{ + IARM_Bus_WiFiSrvMgr_Param_t param; + param.data.wifiStatus = WIFI_CONNECTED; + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_getCurrentState), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([¶m](const char*, const char*, void* arg, size_t) { + memcpy(arg, ¶m, sizeof(param)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWifiState"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"state\":5,\"status\":\"WIFI_STATE_CONNECTED\",\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetWifiState_Failed) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_getCurrentState), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWifiState"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, GetPublicIP_Failed) +{ + // Mock STUN client behavior for a successful public IP lookup + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPublicIP"), _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPublicIP"), _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv6\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, GetStunEndpoint) +{ + // The default values from the configuration in NetworkManagerTest constructor + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetStunEndpoint"), _T("{}"), response)); + std::string expectedResponse = _T("{\"endpoint\":\"stun.l.google.com\",\"port\":19302,\"timeout\":30,\"cacheLifetime\":0,\"success\":true}"); + EXPECT_EQ(response, expectedResponse); +} + +TEST_F(NetworkManagerTest, SetStunEndpoint_Success) +{ + std::string request = _T("{\"endpoint\":\"stun.example.com\",\"port\":3478,\"timeout\":60,\"cacheLifetime\":300}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetStunEndpoint"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + // Verify the settings were applied by getting them + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetStunEndpoint"), _T("{}"), response)); + std::string expectedResponse = _T("{\"endpoint\":\"stun.example.com\",\"port\":3478,\"timeout\":60,\"cacheLifetime\":300,\"success\":true}"); + EXPECT_EQ(response, expectedResponse); +} + +TEST_F(NetworkManagerTest, SetStunEndpoint_InvalidParams) +{ + // Test with empty request + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetStunEndpoint"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, ConfigLineEmpty) +{ + // Mock the service to return an empty configuration line + EXPECT_CALL(service, ConfigLine()) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Return(_T(""))); + + // Initialize the plugin with the mocked service + plugin->Initialize(&service); +} + +TEST_F(NetworkManagerTest, ComLinkEmpty) +{ + // Mock the service to return an empty configuration line + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const RPC::Object& object, const uint32_t waitTime, uint32_t& connectionId) { + return nullptr; + })); + + // Initialize the plugin with the mocked service + plugin->Initialize(&service); +} + +TEST_F(NetworkManagerTest, platformInit) +{ + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Init(::testing::StrEq("netsrvmgr-thunder"))) + .Times(2) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)) + .WillOnce(::testing::Return(IARM_RESULT_SUCCESS)); + + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Connect()) + .Times(2) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)) + .WillOnce(::testing::Return(IARM_RESULT_SUCCESS)); + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call_with_IPCTimeout(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_NETSRVMGR_API_isAvailable), + ::testing::NotNull(), ::testing::_, ::testing::_)) + .Times(3) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)) + .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)) + .WillOnce(::testing::Return(IARM_RESULT_SUCCESS)); + + plugin->Initialize(&service); +} + +TEST_F(NetworkManagerTest, GetConnectivityTestEndpoints) +{ + std::string request = _T("{\"endpoints\":[\"https://example.com/connectivity\",\"https://example.org/check\"]}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetConnectivityTestEndpoints"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Allow server to start + // The default values from the configuration in NetworkManagerTest constructor + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectivityTestEndpoints"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"endpoints\":[\"https:\\/\\/example.com\\/connectivity\",\"https:\\/\\/example.org\\/check\"],\"success\":true}")); +} + +TEST_F(NetworkManagerTest, SetConnectivityTestEndpoints_Success) +{ + std::string request = _T("{\"endpoints\":[\"https://example.com/connectivity\",\"https://example.org/check\"]}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetConnectivityTestEndpoints"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Allow server to start + // Verify the settings were applied by getting them + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectivityTestEndpoints"), _T("{}"), response)); + std::string expectedResponse = _T("{\"endpoints\":[\"https:\\/\\/example.com\\/connectivity\",\"https:\\/\\/example.org\\/check\"],\"success\":true}"); + EXPECT_EQ(response, expectedResponse); +} + +TEST_F(NetworkManagerTest, SetConnectivityTestEndpoints_Empty) +{ + // Test with empty endpoints array + std::string request = _T("{\"endpoints\":[]}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetConnectivityTestEndpoints"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, m_ipv4AddressCache) +{ + Exchange::INetworkManager::IPAddress address{}; + address.ipversion = "IPv4"; + address.autoconfig = true; + address.dhcpserver = "192.168.1.1"; + address.ula = ""; + address.ipaddress = "192.168.1.100"; + address.prefix = 24; + address.gateway = "192.168.1.1"; + address.primarydns = "8.8.8.8"; + address.secondarydns = "8.8.4.4"; + plugin->m_ipv4AddressCache = address; +} + +TEST_F(NetworkManagerTest, m_ipv6AddressCache) +{ + Exchange::INetworkManager::IPAddress address{}; + address.ipversion = "IPv6"; + address.autoconfig = true; + address.dhcpserver = ""; + address.ula = "fd00:1234:5678::1"; + address.ipaddress = "2001:db8::1"; + address.prefix = 64; + address.gateway = "2001:db8::fffe"; + address.primarydns = "2001:4860:4860::8888"; + address.secondarydns = "2001:4860:4860::8844"; + plugin->m_ipv6AddressCache = address; +} + +TEST_F(NetworkManagerTest, GetWiFiSignalQualityWpa_cliFailed) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli status")); + return nullptr; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, GetWiFiSignalQualityDisconnected2) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli status")); + // Create a temporary file with the mock output + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("Selected interface 'wlan0'\n" + "wpa_state=DISCONNECTED\n" + "p2p_device_address=d4:52:ee:d9:0a:39\n" + "address=d4:52:ee:d9:0a:39\n" + "uuid=feb4fcc9-04c3-5be3-a3f9-03fed1d0604c\n", tempFile); + rewind(tempFile); + } + return tempFile; + })) + .WillOnce(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli bss ")); + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("driver error", tempFile); + rewind(tempFile); + } + return tempFile; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ssid\":\"\",\"quality\":\"Disconnected\",\"snr\":\"0\",\"strength\":\"0\",\"noise\":\"0\",\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnected) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli status")); + // Create a temporary file with the mock output + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("Selected interface 'wlan0'\n" + "bssid=aa:bb:cc:dd:ee:ff\n" + "freq=2462\n" + "ssid=dummySSID\n", tempFile); + rewind(tempFile); + } + return tempFile; + })) + .WillOnce(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli bss aa:bb:cc:dd:ee:ff")); + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("Selected interface 'wlan0'\n" + "ssid=dummySSID\n" + "noise=-114\n" + "level=-49\n" + "snr=65\n", tempFile); + rewind(tempFile); + } + return tempFile; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Excellent\",\"snr\":\"65\",\"strength\":\"-49\",\"noise\":\"-114\",\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedGood) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli status")); + // Create a temporary file with the mock output + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("Selected interface 'wlan0'\n" + "bssid=aa:bb:cc:dd:ee:ff\n" + "freq=5462\n" + "ssid=dummySSID\n", tempFile); + rewind(tempFile); + } + return tempFile; + })) + .WillOnce(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli bss aa:bb:cc:dd:ee:ff")); + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("Selected interface 'wlan0'\n" + "ssid=dummySSID\n" + "noise=-114\n" + "level=-90\n" + "snr=33\n", tempFile); + rewind(tempFile); + } + return tempFile; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Good\",\"snr\":\"33\",\"strength\":\"-90\",\"noise\":\"-114\",\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedLowBad) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli status")); + // Create a temporary file with the mock output + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("Selected interface 'wlan0'\n" + "bssid=aa:bb:cc:dd:ee:ff\n" + "freq=5462\n" + "ssid=dummySSID\n", tempFile); + rewind(tempFile); + } + return tempFile; + })) + .WillOnce(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli bss aa:bb:cc:dd:ee:ff")); + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("Selected interface 'wlan0'\n" + "ssid=dummySSID\n" + "noise=-114\n" + "level=-120\n" + "snr=33\n", tempFile); + rewind(tempFile); + } + return tempFile; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Good\",\"snr\":\"33\",\"strength\":\"-120\",\"noise\":\"-114\",\"success\":true}")); +} + +TEST_F(NetworkManagerTest, Trace_Success_ipv4) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillOnce([](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("traceroute -w 3 -m 6 -q 1 8.8.8.8 52 2>&1")); + EXPECT_EQ(type, "r"); + // Create a temporary file with the mock output + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("traceroute to 8.8.8.8 (8.8.8.8), 6 hops max, 52 byte packets\n" + "1 gateway (10.46.5.1) 0.448 ms\n" + "2 10.46.0.240 (10.46.0.240) 3.117 ms\n" + "3 *\n" + "4 *\n" + "5 *\n" + "6 *\n", tempFile); + rewind(tempFile); + } + return tempFile; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("Trace"), + _T("{\"endpoint\":\"8.8.8.8\",\"ipversion\":\"IPv4\",\"packets\":1}"), response)); + + // We expect the response to contain success and results fields + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"results\":") != std::string::npos); + EXPECT_TRUE(response.find("\"endpoint\":\"8.8.8.8\"") != std::string::npos); + EXPECT_TRUE(response.find("6 hops max, 52 byte packets") != std::string::npos); +} + +TEST_F(NetworkManagerTest, Trace_Failed_ipv6) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillOnce([](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("traceroute6 -w 3 -m 6 -q 1 8.8.8.8 64 2>&1")); + EXPECT_EQ(type, "r"); + // Create a temporary file with the mock output + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("traceroute6: bad address '8.8.8.8'", tempFile); + rewind(tempFile); + } + return tempFile; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("Trace"), + _T("{\"endpoint\":\"8.8.8.8\",\"ipversion\":\"IPv6\",\"packets\":1}"), response)); + + EXPECT_EQ(response, _T("{\"results\":\"[\\\"traceroute6: bad address '8.8.8.8' \\\"]\",\"endpoint\":\"8.8.8.8\",\"success\":true}")); +} + +TEST_F(NetworkManagerTest, Trace_Success_ipv6) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillOnce([](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("traceroute6 -w 3 -m 6 -q 1 2001:4860:4860::8888 64 2>&1")); + EXPECT_EQ(type, "r"); + // Create a temporary file with the mock output + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("traceroute to 2001:4860:4860::8888 (2001:4860:4860::8888), 6 hops max, 64 byte packets\n" + "1 2401:4900:9092:d613::d4 (2401:4900:9092:d613::d4) 14.503 ms !N\n", tempFile); + rewind(tempFile); + } + return tempFile; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("Trace"), + _T("{\"endpoint\":\"2001:4860:4860::8888\",\"ipversion\":\"IPv6\",\"packets\":1}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("6 hops max, 64 byte packets") != std::string::npos); + EXPECT_TRUE(response.find("\"endpoint\":\"2001:4860:4860::8888\"") != std::string::npos); +} + +TEST_F(NetworkManagerTest, Ping_Success_ipv4) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillOnce([](const char* command, const char* type) -> FILE* { + std::string cmdStr = command; + EXPECT_TRUE(cmdStr.find("ping") != std::string::npos); + EXPECT_TRUE(cmdStr.find("8.8.8.8") != std::string::npos); + EXPECT_EQ(type, "r"); + // Create a temporary file with the mock output + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("PING 8.8.8.8 (8.8.8.8): 56 data bytes\n" + "64 bytes from 8.8.8.8: seq=0 ttl=119 time=23.363 ms\n" + "64 bytes from 8.8.8.8: seq=1 ttl=119 time=23.440 ms\n" + "64 bytes from 8.8.8.8: seq=2 ttl=119 time=23.384 ms\n" + "\n" + "--- 8.8.8.8 ping statistics ---\n" + "3 packets transmitted, 3 packets received, 0% packet loss\n" + "round-trip min/avg/max/mdev = 23.363/23.395/23.440/0.179 ms\n", tempFile); + rewind(tempFile); + } + return tempFile; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("Ping"), + _T("{\"endpoint\":\"8.8.8.8\",\"ipversion\":\"IPv4\",\"packets\":5,\"timeout\":2}"), response)); + + EXPECT_EQ(response, _T("{\"endpoint\":\"8.8.8.8\",\"success\":true,\"tripStdDev\":\"0.179 ms\",\"tripMax\":\"23.440\",\"tripAvg\":\"23.395\",\"tripMin\":\" 23.363\",\"packetLoss\":\" 0\",\"packetsReceived\":3,\"packetsTransmitted\":3}")); +} + +TEST_F(NetworkManagerTest, Ping_Failed_ipv4) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillOnce([](const char* command, const char* type) -> FILE* { + std::string cmdStr = command; + EXPECT_TRUE(cmdStr.find("ping") != std::string::npos); + EXPECT_TRUE(cmdStr.find("192.0.0.1") != std::string::npos); + EXPECT_EQ(type, "r"); + // Create a temporary file with the mock output + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("PING 192.0.0.1 (192.0.0.1): 56 data bytes\n" + "\n" + "--- 192.0.0.1 ping statistics ---\n" + "3 packets transmitted, 0 packets received, 100% packet loss\n", tempFile); + rewind(tempFile); + } + return tempFile; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("Ping"), + _T("{\"endpoint\":\"192.0.0.1\",\"ipversion\":\"IPv4\",\"packets\":5,\"timeout\":2}"), response)); + + EXPECT_EQ(response, _T("{\"endpoint\":\"192.0.0.1\",\"success\":true,\"packetLoss\":\" 100\",\"packetsReceived\":0,\"packetsTransmitted\":3}")); +} + +TEST_F(NetworkManagerTest, Ping_success_ipv6) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillOnce([](const char* command, const char* type) -> FILE* { + std::string cmdStr = command; + EXPECT_TRUE(cmdStr.find("ping6") != std::string::npos); + EXPECT_TRUE(cmdStr.find("2404:6800:4007:80b::200e") != std::string::npos); + EXPECT_EQ(type, "r"); + // Create a temporary file with the mock output + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("PING 2404:6800:4007:80b::200e (2404:6800:4007:80b::200e): 56 data bytes\n" + "64 bytes from 2404:6800:4007:80b::200e: seq=0 ttl=117 time=39.546 ms\n" + "64 bytes from 2404:6800:4007:80b::200e: seq=0 ttl=117 time=46.505 ms (DUP!)\n" + "64 bytes from 2404:6800:4007:80b::200e: seq=1 ttl=117 time=35.637 ms\n" + "64 bytes from 2404:6800:4007:80b::200e: seq=2 ttl=117 time=44.998 ms\n" + "\n" + "--- 2404:6800:4007:80b::200e ping statistics ---\n" + "3 packets transmitted, 3 packets received, 1 duplicates, 0% packet loss\n" + "round-trip min/avg/max/mdev = 35.637/41.671/46.505/4.345 ms\n", tempFile); + rewind(tempFile); + } + return tempFile; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("Ping"), + _T("{\"endpoint\":\"2404:6800:4007:80b::200e\",\"ipversion\":\"IPv6\",\"packets\":5,\"timeout\":2}"), response)); + + EXPECT_EQ(response, _T("{\"endpoint\":\"2404:6800:4007:80b::200e\",\"success\":true,\"tripStdDev\":\"4.345 ms\",\"tripMax\":\"46.505\",\"tripAvg\":\"41.671\",\"tripMin\":\" 35.637\",\"packetLoss\":\" 1 duplicates\",\"packetsReceived\":3,\"packetsTransmitted\":3}")); +} + +TEST_F(NetworkManagerTest, Ping_Failed_ipv6) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .WillOnce([](const char* command, const char* type) -> FILE* { + std::string cmdStr = command; + EXPECT_TRUE(cmdStr.find("ping6") != std::string::npos); + EXPECT_TRUE(cmdStr.find("2404:6800:4007:80b::200e") != std::string::npos); + EXPECT_EQ(type, "r"); + return NULL; + }); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("Ping"), + _T("{\"endpoint\":\"2404:6800:4007:80b::200e\",\"ipversion\":\"IPv6\",\"packets\":5,\"timeout\":2}"), response)); + + EXPECT_EQ(response, _T("{\"endpoint\":\"2404:6800:4007:80b::200e\"}")); +} diff --git a/tests/l2Test/l2_test_rdkproxyEvent.cpp b/tests/l2Test/l2_test_rdkproxyEvent.cpp new file mode 100644 index 000000000..02fe37454 --- /dev/null +++ b/tests/l2Test/l2_test_rdkproxyEvent.cpp @@ -0,0 +1,698 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ +#include +#include +#include +#include +#include + +#include "FactoriesImplementation.h" +#include "IarmBusMock.h" +#include "WrapsMock.h" +#include "ServiceMock.h" +#include "ThunderPortability.h" +#include "COMLinkMock.h" +#include "IarmBusMock.h" +#include "WorkerPoolImplementation.h" +#include "NetworkManagerImplementation.h" +#include "NetworkManagerRDKProxy.h" +#include "NetworkManagerLogger.h" +#include "NetworkManager.h" +#include "ConnectivityMockServer.h" + +using namespace WPEFramework; +using ::testing::NiceMock; + +class NetworkManagerEventTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + DECL_CORE_JSONRPC_CONX connection; + Core::JSONRPC::Message message; + string response; + + // Mock classes + IarmBusImplMock *p_iarmBusImplMock = nullptr; + WrapsImplMock *p_wrapsImplMock = nullptr; + IARM_EventHandler_t _nmEventHandler{}; + Core::ProxyType NetworkManagerImpl; + + NiceMock comLinkMock; + NiceMock service; + PLUGINHOST_DISPATCHER* dispatcher; + Core::ProxyType workerPool; + NiceMock factoriesImplementation; + + + NetworkManagerEventTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , INIT_CONX(1, 0) + , workerPool(Core::ProxyType::Create(2, Core::Thread::DefaultStackSize(), 16)) + { + p_iarmBusImplMock = new NiceMock ; + IarmBus::setImpl(p_iarmBusImplMock); + p_wrapsImplMock = new NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Invoke( + [this]() { + return &comLinkMock; + })); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return( + "{" + " \"locator\":\"libWPEFrameworkNetworkManager.so\"," + " \"classname\":\"NetworkManager\"," + " \"callsign\":\"org.rdk.NetworkManager\"," + " \"startuporder\":55," + " \"autostart\":false," + " \"configuration\":{" + " \"root\":{" + " \"outofprocess\":true," + " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" + " }," + " \"connectivity\":{" + " \"endpoint_1\":\"http://localhost:8080/generate_204\"," + " \"interval\":60" + " }," + " \"stun\":{" + " \"endpoint\":\"stun.l.google.com\"," + " \"port\":19302," + " \"interval\":30" + " }" + " }" + "}" + )); + + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const RPC::Object& object, const uint32_t waitTime, uint32_t& connectionId) { + NetworkManagerImpl = Core::ProxyType::Create(); + return &NetworkManagerImpl; + })); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Init(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME))) + .WillByDefault(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS)) { + _nmEventHandler = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS)) { + _nmEventHandler = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS)) { + _nmEventHandler = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_NETWORK_MANAGER_EVENT_DEFAULT_INTERFACE)) { + _nmEventHandler = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs)) { + _nmEventHandler = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged)) { + _nmEventHandler = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_WIFI_MGR_EVENT_onError)) { + _nmEventHandler = handler; + } + return IARM_RESULT_SUCCESS; + })); + + PluginHost::IFactories::Assign(&factoriesImplementation); + + Core::IWorkerPool::Assign(&(*workerPool)); + workerPool->Run(); + + dispatcher = static_cast( + plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); + dispatcher->Activate(&service); + response = plugin->Initialize(&service); + EXPECT_EQ(string(""), response); + NetworkManagerLogger::SetLevel(static_cast(NetworkManagerLogger::DEBUG_LEVEL)); // Set log level to DEBUG_LEVEL + } + + virtual void SetUp() override + { + + } + + virtual ~NetworkManagerEventTest() override + { + plugin->Deinitialize(&service); + + dispatcher->Deactivate(); + dispatcher->Release(); + + Core::IWorkerPool::Assign(nullptr); + workerPool.Release(); + + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) + { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + } +}; + +TEST_F(NetworkManagerEventTest, iarmEventHandlerErrorChack) +{ + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t eventData = { .interface = "wlan0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS, &eventData, 0); + + eventData = { .interface = "eth0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERNET_CONNECTION_CHANGED, &eventData, sizeof(eventData)); +} + +TEST_F(NetworkManagerEventTest, onInterfaceStateChange) +{ + Core::Event onInterfaceStateChange(false, true); + EVENT_SUBSCRIBE(2, _T("onInterfaceStateChange"), _T("org.rdk.NetworkManager"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.NetworkManager.onInterfaceStateChange\",\"params\":{\"state\":0,\"status\":\"INTERFACE_ADDED\",\"interface\":\"wlan0\"}}"))); + onInterfaceStateChange.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.NetworkManager.onInterfaceStateChange\",\"params\":{\"state\":0,\"status\":\"INTERFACE_ADDED\",\"interface\":\"eth0\"}}"))); + onInterfaceStateChange.SetEvent(); + return Core::ERROR_NONE; + })); + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t eventData = { .interface = "wlan0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS, &eventData, sizeof(eventData)); + + eventData = { .interface = "eth0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS, &eventData, sizeof(eventData)); + + EXPECT_EQ(Core::ERROR_NONE, onInterfaceStateChange.Lock()); + + EVENT_UNSUBSCRIBE(2, _T("onInterfaceStateChange"), _T("org.rdk.NetworkManager"), message); +} + +TEST_F(NetworkManagerEventTest, onActiveInterfaceChange) +{ + Core::Event onActiveInterfaceChange(false, true); + EVENT_SUBSCRIBE(2, _T("onActiveInterfaceChange"), _T("org.rdk.NetworkManager"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_TRUE(text.find("\"method\":\"org.rdk.NetworkManager.onActiveInterfaceChange\"") != std::string::npos); + EXPECT_TRUE(text.find("\"prevActiveInterface\":\"eth0\"") != std::string::npos); + EXPECT_TRUE(text.find("\"currentActiveInterface\":\"wlan0\"") != std::string::npos); + onActiveInterfaceChange.SetEvent(); + return Core::ERROR_NONE; + })); + + IARM_BUS_NetSrvMgr_Iface_EventDefaultInterface_t eventData; + strcpy(eventData.oldInterface, "eth0"); + strcpy(eventData.newInterface, "wlan0"); + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_DEFAULT_INTERFACE, &eventData, sizeof(eventData)); + + EXPECT_EQ(Core::ERROR_NONE, onActiveInterfaceChange.Lock()); + EVENT_UNSUBSCRIBE(2, _T("onActiveInterfaceChange"), _T("org.rdk.NetworkManager"), message); +} + +TEST_F(NetworkManagerEventTest, onWiFiStateChange) +{ + Core::Event onWiFiStateChange(false, true); + EVENT_SUBSCRIBE(2, _T("onWiFiStateChange"), _T("org.rdk.NetworkManager"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_TRUE(text.find("\"method\":\"org.rdk.NetworkManager.onWiFiStateChange\"") != std::string::npos); + EXPECT_TRUE(text.find("\"state\":5") != std::string::npos); // WIFI_STATE_CONNECTED = 4 + EXPECT_TRUE(text.find("\"status\":\"WIFI_STATE_CONNECTED\"") != std::string::npos); + onWiFiStateChange.SetEvent(); + return Core::ERROR_NONE; + })); + + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli status")); + // Create a temporary file with the mock output + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("Selected interface 'wlan0'\n" + "bssid=aa:bb:cc:dd:ee:ff\n" + "freq=5462\n" + "ssid=dummySSID\n", tempFile); + rewind(tempFile); + } + return tempFile; + })) + .WillOnce(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli bss aa:bb:cc:dd:ee:ff")); + FILE* tempFile = tmpfile(); + if (tempFile) { + fputs("Selected interface 'wlan0'\n" + "ssid=dummySSID\n" + "noise=-114\n" + "level=-90\n" + "snr=33\n", tempFile); + rewind(tempFile); + } + return tempFile; + })); + + // Create and populate event data for WiFi state change + IARM_BUS_WiFiSrvMgr_EventData_t eventData; + eventData.data.wifiStateChange.state = WIFI_CONNECTED; + + // Trigger the event handler + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged, &eventData, sizeof(eventData)); + EXPECT_EQ(Core::ERROR_NONE, onWiFiStateChange.Lock()); + EVENT_UNSUBSCRIBE(2, _T("onWiFiStateChange"), _T("org.rdk.NetworkManager"), message); +} + +TEST_F(NetworkManagerEventTest, onWiFiErrorStateChange) +{ + Core::Event onWiFiStateChange(false, true); + EVENT_SUBSCRIBE(2, _T("onWiFiStateChange"), _T("org.rdk.NetworkManager"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_TRUE(text.find("\"method\":\"org.rdk.NetworkManager.onWiFiStateChange\"") != std::string::npos); + EXPECT_TRUE(text.find("\"state\":8") != std::string::npos); // WIFI_STATE_CONNECTION_LOST = 8 + EXPECT_TRUE(text.find("\"status\":\"WIFI_STATE_CONNECTION_LOST\"") != std::string::npos); + onWiFiStateChange.SetEvent(); + return Core::ERROR_NONE; + })); + + // Create and populate event data for WiFi error + IARM_BUS_WiFiSrvMgr_EventData_t eventData; + eventData.data.wifiError.code = WIFI_CONNECTION_LOST; + + // Trigger the event handler + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onError, &eventData, sizeof(eventData)); + + EXPECT_EQ(Core::ERROR_NONE, onWiFiStateChange.Lock()); + + EVENT_UNSUBSCRIBE(2, _T("onWiFiStateChange"), _T("org.rdk.NetworkManager"), message); +} + +TEST_F(NetworkManagerEventTest, onAvailableSSIDsEvent) +{ + Core::Event onAvailableSSIDs(false, true); + EVENT_SUBSCRIBE(2, _T("onAvailableSSIDs"), _T("org.rdk.NetworkManager"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_TRUE(text.find("\"method\":\"org.rdk.NetworkManager.onAvailableSSIDs\"") != std::string::npos); + EXPECT_TRUE(text.find("\"ssids\"") != std::string::npos); + onAvailableSSIDs.SetEvent(); + return Core::ERROR_NONE; + })); + + // Create a simple JSON string with SSID list + const char* jsonData = R"({ + "getAvailableSSIDs": [ + { + "ssid": "HomeWiFi", + "security": 0, + "signalStrength": -65, + "frequency": 2.4 + }, + { + "ssid": "OfficeNetwork", + "security": 4, + "signalStrength": -72, + "frequency": 5.0 + } + ] + })"; + + // Create and populate event data for WiFi SSIDs + IARM_BUS_WiFiSrvMgr_EventData_t eventData; + strncpy(eventData.data.wifiSSIDList.ssid_list, jsonData, sizeof(eventData.data.wifiSSIDList.ssid_list)); + + // Trigger the event handler + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs, &eventData, sizeof(eventData)); + + EXPECT_EQ(Core::ERROR_NONE, onAvailableSSIDs.Lock()); + + EVENT_UNSUBSCRIBE(2, _T("onAvailableSSIDs"), _T("org.rdk.NetworkManager"), message); +} + + +TEST_F(NetworkManagerEventTest, ConnectivityMonitorEvents) +{ + Core::Event onAddressChange(false, true); + EVENT_SUBSCRIBE(2, _T("onIPAddressChange"), _T("org.rdk.NetworkManager"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_TRUE(text.find("\"method\":\"org.rdk.NetworkManager.onIPAddressChange\"") != std::string::npos); + EXPECT_TRUE(text.find("\"interface\":\"eth0\"") != std::string::npos); + EXPECT_TRUE(text.find("\"ipversion\":\"IPv4\"") != std::string::npos); + EXPECT_TRUE(text.find("\"ipaddress\":\"192.168.1.100\"") != std::string::npos); + EXPECT_TRUE(text.find("\"status\":\"LOST\"") != std::string::npos); + onAddressChange.SetEvent(); + return Core::ERROR_NONE; + })); + + // Create and populate event data for IP address change + IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t eventData{.interface = "eth0", + .ip_address = "192.168.1.100", + .is_ipv6 = false, + .acquired = false}; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, &eventData, sizeof(eventData)); + EXPECT_EQ(Core::ERROR_NONE, onAddressChange.Lock()); + EVENT_UNSUBSCRIBE(2, _T("onIPAddressChange"), _T("org.rdk.NetworkManager"), message); +} + +TEST_F(NetworkManagerEventTest, onInterfaceStateChange2) +{ + Core::Event onInterfaceStateChange(false, true); + EVENT_SUBSCRIBE(2, _T("onInterfaceStateChange"), _T("org.rdk.NetworkManager"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.NetworkManager.onInterfaceStateChange\",\"params\":{\"state\":1,\"status\":\"INTERFACE_LINK_UP\",\"interface\":\"wlan0\"}}"))); + onInterfaceStateChange.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"org.rdk.NetworkManager.onInterfaceStateChange\",\"params\":{\"state\":2,\"status\":\"INTERFACE_LINK_DOWN\",\"interface\":\"eth0\"}}"))); + onInterfaceStateChange.SetEvent(); + return Core::ERROR_NONE; + })); + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t eventData = { .interface = "wlan0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &eventData, sizeof(eventData)); + + eventData = { .interface = "eth0", .status = false }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &eventData, sizeof(eventData)); + + EXPECT_EQ(Core::ERROR_NONE, onInterfaceStateChange.Lock()); + + EVENT_UNSUBSCRIBE(2, _T("onInterfaceStateChange"), _T("org.rdk.NetworkManager"), message); + +} + +TEST_F(NetworkManagerEventTest, onInternetStatusChange_CaptivePortal) +{ + Core::Event onInternetStatusChange(false, true); + EVENT_SUBSCRIBE(2, _T("onInternetStatusChange"), _T("org.rdk.NetworkManager"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_TRUE(text.find("\"method\":\"org.rdk.NetworkManager.onInternetStatusChange\"") != std::string::npos); + onInternetStatusChange.SetEvent(); + return Core::ERROR_NONE; + })); + + SimpleHttpServer server(8080); + server.setHttpResponseCode(302); // Found (Redirect) + server.setHttpMessage("http://captive.portal/login"); + server.start(); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Allow server to start + + std::string request = _T("{\"endpoints\":[\"http://localhost:8080/generate_204\"]}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetConnectivityTestEndpoints"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "wlan0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t ipEventData{.interface = "wlan0", + .ip_address = "fe80::1889:1e36:52a:a82f%26", + .is_ipv6 = true, + .acquired = true}; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, &ipEventData, sizeof(ipEventData)); + + EXPECT_EQ(Core::ERROR_NONE, onInternetStatusChange.Lock()); + EVENT_UNSUBSCRIBE(2, _T("onInternetStatusChange"), _T("org.rdk.NetworkManager"), message); + + // Test with both IPv4 and IPv6 + // EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("IsConnectedToInternet"), _T("{}"), response)); + // EXPECT_EQ(response, _T("{\"ipversion\":\"IPv4\",\"interface\":\"wlan0\",\"connected\":false,\"state\":0,\"status\":\"NO_INTERNET\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetCaptivePortalURI"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"uri\":\"\",\"success\":true}")); + server.stop(); +} + +TEST_F(NetworkManagerEventTest, onInternetStatusChange_LimitedInternet) +{ + Core::Event onInternetStatusChange(false, true); + EVENT_SUBSCRIBE(2, _T("onInternetStatusChange"), _T("org.rdk.NetworkManager"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_TRUE(text.find("\"method\":\"org.rdk.NetworkManager.onInternetStatusChange\"") != std::string::npos); + onInternetStatusChange.SetEvent(); + return Core::ERROR_NONE; + })); + + SimpleHttpServer server(8080); + server.setHttpResponseCode(200); // OK + server.setHttpMessage(""); + server.start(); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Allow server to start + + std::string request = _T("{\"endpoints\":[\"http://localhost:8080/generate_204\"]}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetConnectivityTestEndpoints"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "eth0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t ipEventData{.interface = "eth0", + .ip_address = "192.168.148.1", + .is_ipv6 = false, + .acquired = true}; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, &ipEventData, sizeof(ipEventData)); + + EXPECT_EQ(Core::ERROR_NONE, onInternetStatusChange.Lock()); + EVENT_UNSUBSCRIBE(2, _T("onInternetStatusChange"), _T("org.rdk.NetworkManager"), message); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Allow server to start + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("IsConnectedToInternet"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ipversion\":\"IPv4\",\"interface\":\"eth0\",\"connected\":false,\"state\":1,\"status\":\"LIMITED_INTERNET\",\"success\":true}")); + server.stop(); +} + +TEST_F(NetworkManagerEventTest, onInternetStatusChange_FULLY_CONNECTED) +{ + Core::Event onInternetStatusChange(false, true); + EVENT_SUBSCRIBE(2, _T("onInternetStatusChange"), _T("org.rdk.NetworkManager"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_TRUE(text.find("\"method\":\"org.rdk.NetworkManager.onInternetStatusChange\"") != std::string::npos); + onInternetStatusChange.SetEvent(); + return Core::ERROR_NONE; + })); + + SimpleHttpServer server(8080); + server.setHttpResponseCode(204); // No Content + server.setHttpMessage(""); + server.start(); + + std::string request = _T("{\"endpoints\":[\"http://localhost:8080/generate_204\"]}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetConnectivityTestEndpoints"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Allow server to start + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "eth0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t ipEventData{.interface = "eth0", + .ip_address = "192.168.148.1", + .is_ipv6 = false, + .acquired = true}; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, &ipEventData, sizeof(ipEventData)); + + EXPECT_EQ(Core::ERROR_NONE, onInternetStatusChange.Lock()); + EVENT_UNSUBSCRIBE(2, _T("onInternetStatusChange"), _T("org.rdk.NetworkManager"), message); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Allow server to start + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("IsConnectedToInternet"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ipversion\":\"IPv4\",\"interface\":\"eth0\",\"connected\":true,\"state\":3,\"status\":\"FULLY_CONNECTED\",\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetCaptivePortalURI"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"uri\":\"\",\"success\":true}")); + + server.stop(); +} + +TEST_F(NetworkManagerEventTest, GetPublicIP_SuccessWithEvent) +{ + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "wlan0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t ipEventData{.interface = "wlan0", + .ip_address = "fe80::1889:1e36:52a:a82f%26", + .is_ipv6 = true, + .acquired = true}; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, &ipEventData, sizeof(ipEventData)); + + // Test with both IPv4 and IPv6 + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPublicIP"), _T("{}"), response)); + EXPECT_TRUE(response.find("\"ipaddress\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ipversion\"") != std::string::npos); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); +} + +TEST_F(NetworkManagerEventTest, GetSupportedSecurityModes) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetSupportedSecurityModes"), _T(""), response)); + EXPECT_EQ(response, _T("{\"security\":{\"NONE\":0,\"WPA_PSK\":1,\"SAE\":2,\"EAP\":3},\"success\":true}")); +} + +TEST_F(NetworkManagerEventTest, IsConnectedToInternet_Failed) +{ + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Allow server to start + std::string request = _T("{\"endpoints\":[\"http://localhost:8077/generate_204\"]}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetConnectivityTestEndpoints"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Allow server to start + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "wlan0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t ipEventData{.interface = "wlan0", + .ip_address = "fe80::1889:1e36:52a:a82f%26", + .is_ipv6 = true, + .acquired = true}; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, &ipEventData, sizeof(ipEventData)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("IsConnectedToInternet"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ipversion\":\"IPv4\",\"interface\":\"wlan0\",\"connected\":false,\"state\":0,\"status\":\"NO_INTERNET\",\"success\":true}")); + + // Test with IPv4 only + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("IsConnectedToInternet"), _T("{\"ipversion\":\"IPv6\"}"), response)); + EXPECT_EQ(response, _T("{\"ipversion\":\"IPv6\",\"interface\":\"wlan0\",\"connected\":false,\"state\":0,\"status\":\"NO_INTERNET\",\"success\":true}")); + + // Test with specific interface + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("IsConnectedToInternet"), _T("{\"interface\":\"eth0\"}"), response)); + EXPECT_EQ(response, _T("{\"ipversion\":\"IPv4\",\"interface\":\"eth0\",\"connected\":false,\"state\":0,\"status\":\"NO_INTERNET\",\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("IsConnectedToInternet"), _T("{\"interface\":\"wlan0\"}"), response)); + EXPECT_EQ(response, _T("{\"ipversion\":\"IPv4\",\"interface\":\"wlan0\",\"connected\":false,\"state\":0,\"status\":\"NO_INTERNET\",\"success\":true}")); + +} +/* This test case takes more time because of connectivity monitor existing logic */ +TEST_F(NetworkManagerEventTest, FULLY_CONNECTED_wait) +{ + Core::Event onInternetStatusChange(false, true); + EVENT_SUBSCRIBE(2, _T("onInternetStatusChange"), _T("org.rdk.NetworkManager"), message); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillRepeatedly(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_TRUE(text.find("\"method\":\"org.rdk.NetworkManager.onInternetStatusChange\"") != std::string::npos); + onInternetStatusChange.SetEvent(); + return Core::ERROR_NONE; + })); + + SimpleHttpServer server(8080); + server.setHttpResponseCode(204); // No Content + server.setHttpMessage(""); + server.start(); + + std::string request = _T("{\"endpoints\":[\"http://localhost:8080/generate_204\"]}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetConnectivityTestEndpoints"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Allow server to start + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "eth0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceIPAddress_t ipEventData{.interface = "eth0", + .ip_address = "192.168.148.1", + .is_ipv6 = false, + .acquired = true}; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, &ipEventData, sizeof(ipEventData)); + std::this_thread::sleep_for(std::chrono::milliseconds(15000)); // Allow server to start + server.setTimeout(15000); // Set timeout to 15 seconds + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + server.stop(); + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventDataLost = { .interface = "eth0", .status = false }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventDataLost, sizeof(ifaceEventDataLost)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + EXPECT_EQ(Core::ERROR_NONE, onInternetStatusChange.Lock()); + EVENT_UNSUBSCRIBE(2, _T("onInternetStatusChange"), _T("org.rdk.NetworkManager"), message); +} diff --git a/tests/l2Test/l2_test_rdkproxyImpl.cpp b/tests/l2Test/l2_test_rdkproxyImpl.cpp new file mode 100644 index 000000000..ebae2073f --- /dev/null +++ b/tests/l2Test/l2_test_rdkproxyImpl.cpp @@ -0,0 +1,263 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include "FactoriesImplementation.h" +#include "ThunderPortability.h" + +#include +#include +#include "NetworkManagerImplementation.h" +#include "NetworkManager.h" +#include "IarmBusMock.h" +#include "ServiceMock.h" +#include "Module.h" + +#include +#include "ThunderPortability.h" +#include "INetworkManager.h" + +using namespace std; +using namespace WPEFramework; +using namespace WPEFramework::Plugin; +using IStringIterator = RPC::IIteratorType; +using ::testing::NiceMock; + +class NetworkManagerImplTest : public ::testing::Test { +protected: + static Core::ProxyType NetworkManagerImplementation; + static Exchange::INetworkManager* interface; + static IarmBusImplMock* p_iarmBusImplMock; + + static void SetUpTestSuite() { + // Create the mock implementation for IARM Bus + p_iarmBusImplMock = new NiceMock; + IarmBus::setImpl(p_iarmBusImplMock); + + // Create the NetworkManagerImplementation instance + NetworkManagerImplementation = Core::ProxyType::Create(); + interface = static_cast(NetworkManagerImplementation->QueryInterface(Exchange::INetworkManager::ID)); + ASSERT_TRUE(interface != nullptr); + } + + static void TearDownTestSuite() { + // Release the interface and clean up resources + interface->Release(); + IarmBus::setImpl(nullptr); + if (p_iarmBusImplMock != nullptr) { + delete p_iarmBusImplMock; + p_iarmBusImplMock = nullptr; + } + } + + virtual void SetUp() override { + ASSERT_TRUE(interface != nullptr); + } + + virtual void TearDown() override { + ASSERT_TRUE(interface != nullptr); + } +}; + +// Static member initialization +Core::ProxyType NetworkManagerImplTest::NetworkManagerImplementation; +Exchange::INetworkManager* NetworkManagerImplTest::interface = nullptr; +IarmBusImplMock* NetworkManagerImplTest::p_iarmBusImplMock = nullptr; + +TEST_F(NetworkManagerImplTest, SetLogLevel) { + // Test setting log level to FATAL + Exchange::INetworkManager::Logging logLevel = Exchange::INetworkManager::LOG_LEVEL_FATAL; + uint32_t result = interface->SetLogLevel(logLevel); + EXPECT_EQ(result, Core::ERROR_NONE); + + // Test setting log level to ERROR + logLevel = Exchange::INetworkManager::LOG_LEVEL_ERROR; + result = interface->SetLogLevel(logLevel); + EXPECT_EQ(result, Core::ERROR_NONE); + + // Test setting log level to WARNING + logLevel = Exchange::INetworkManager::LOG_LEVEL_WARNING; + result = interface->SetLogLevel(logLevel); + EXPECT_EQ(result, Core::ERROR_NONE); + + // Test setting log level to INFO + logLevel = Exchange::INetworkManager::LOG_LEVEL_INFO; + result = interface->SetLogLevel(logLevel); + EXPECT_EQ(result, Core::ERROR_NONE); + + // Test setting log level to DEBUG + logLevel = Exchange::INetworkManager::LOG_LEVEL_DEBUG; + result = interface->SetLogLevel(logLevel); + EXPECT_EQ(result, Core::ERROR_NONE); +} + +TEST_F(NetworkManagerImplTest, GetLogLevel) { + // Test getting log level after setting it to FATAL + Exchange::INetworkManager::Logging logLevel = Exchange::INetworkManager::LOG_LEVEL_FATAL; + interface->SetLogLevel(logLevel); + Exchange::INetworkManager::Logging retrievedLogLevel; + uint32_t result = interface->GetLogLevel(retrievedLogLevel); + EXPECT_EQ(result, Core::ERROR_NONE); + EXPECT_EQ(retrievedLogLevel, Exchange::INetworkManager::LOG_LEVEL_FATAL); + + // Test getting log level after setting it to ERROR + logLevel = Exchange::INetworkManager::LOG_LEVEL_ERROR; + interface->SetLogLevel(logLevel); + result = interface->GetLogLevel(retrievedLogLevel); + EXPECT_EQ(result, Core::ERROR_NONE); + EXPECT_EQ(retrievedLogLevel, Exchange::INetworkManager::LOG_LEVEL_ERROR); + + // Test getting log level after setting it to WARNING + logLevel = Exchange::INetworkManager::LOG_LEVEL_WARNING; + interface->SetLogLevel(logLevel); + result = interface->GetLogLevel(retrievedLogLevel); + EXPECT_EQ(result, Core::ERROR_NONE); + EXPECT_EQ(retrievedLogLevel, Exchange::INetworkManager::LOG_LEVEL_WARNING); + + // Test getting log level after setting it to INFO + logLevel = Exchange::INetworkManager::LOG_LEVEL_INFO; + interface->SetLogLevel(logLevel); + result = interface->GetLogLevel(retrievedLogLevel); + EXPECT_EQ(result, Core::ERROR_NONE); + EXPECT_EQ(retrievedLogLevel, Exchange::INetworkManager::LOG_LEVEL_INFO); + + // Test getting log level after setting it to DEBUG + logLevel = Exchange::INetworkManager::LOG_LEVEL_DEBUG; + interface->SetLogLevel(logLevel); + result = interface->GetLogLevel(retrievedLogLevel); + EXPECT_EQ(result, Core::ERROR_NONE); + EXPECT_EQ(retrievedLogLevel, Exchange::INetworkManager::LOG_LEVEL_DEBUG); +} + +TEST_F(NetworkManagerImplTest, LogMessageTruncation) { + // Generate a log message longer than the maximum allowed size + std::string longMessage(1025, 'A'); // Create a string with 1025 'A' characters + NetworkManagerLogger::logPrint(NetworkManagerLogger::DEBUG_LEVEL, __FILE__, __func__, __LINE__, "%s", longMessage.c_str()); + + // Since the log message is truncated, the last three characters should be "..." + // This test ensures that the truncation logic is executed + EXPECT_TRUE(true); // Placeholder assertion to ensure the test runs +} + +TEST_F(NetworkManagerImplTest, GetConnectivityTestEndpoints) +{ + // Set up mock endpoints in the ConnectivityMonitor + std::vector mockEndpoints = {"http://clients3.google.com/generate_204", "http://example.com"}; + NetworkManagerImplementation->connectivityMonitor.setConnectivityMonitorEndpoints(mockEndpoints); + + // Call GetConnectivityTestEndpoints + RPC::IIteratorType* endpoints = nullptr; + uint32_t result = interface->GetConnectivityTestEndpoints(endpoints); + + // Verify the result + EXPECT_EQ(result, Core::ERROR_NONE); + ASSERT_NE(endpoints, nullptr); + + // Verify the endpoints returned + std::vector retrievedEndpoints; + std::string endpoint; + while (endpoints->Next(endpoint)) { + retrievedEndpoints.push_back(endpoint); + } + EXPECT_EQ(retrievedEndpoints, mockEndpoints); + + // Clean up + endpoints->Release(); + // remove any previous connectivity endpoints file +} + +TEST_F(NetworkManagerImplTest, SetConnectivityTestEndpoints_EmptyEndpoints) { + // Prepare empty endpoints + std::vector emptyEndpoints; + RPC::IIteratorType* endpoints = Core::Service::Create(emptyEndpoints); + + // Call SetConnectivityTestEndpoints + uint32_t result = interface->SetConnectivityTestEndpoints(endpoints); + + // Verify the result + EXPECT_EQ(result, Core::ERROR_NONE); + + // Verify the endpoints were not set + std::vector retrievedEndpoints = NetworkManagerImplementation->connectivityMonitor.getConnectivityMonitorEndpoints(); + printf("Retrieved Endpoints Size: %zu %s\n", retrievedEndpoints.size(), retrievedEndpoints[0].c_str()); + EXPECT_TRUE(retrievedEndpoints.empty() != true && retrievedEndpoints[0] == "http://clients3.google.com/generate_204"); // default endpoint should remain + + // Clean up + endpoints->Release(); +} + +TEST_F(NetworkManagerImplTest, SetConnectivityTestEndpoints_ValidEndpoints) { + // Prepare valid endpoints + std::vector validEndpoints = {"http://clients3.google.com/generate_204", "http://example.com"}; + RPC::IIteratorType* endpoints = Core::Service::Create(validEndpoints); + + // Call SetConnectivityTestEndpoints + uint32_t result = interface->SetConnectivityTestEndpoints(endpoints); + + // Verify the result + EXPECT_EQ(result, Core::ERROR_NONE); + + // Verify the endpoints were set correctly + std::vector retrievedEndpoints = NetworkManagerImplementation->connectivityMonitor.getConnectivityMonitorEndpoints(); + EXPECT_EQ(retrievedEndpoints, validEndpoints); + + // Clean up + endpoints->Release(); + // remove any previous connectivity endpoints file +} + +TEST_F(NetworkManagerImplTest, SetConnectivityTestEndpoints_InvalidEndpoints) { + // Prepare invalid endpoints (too short to be valid URLs) + std::vector invalidEndpoints = {"1234567", "1234567890"}; // "1234567" is not a valid URL less than 7, "12345678" is too short + RPC::IIteratorType* endpoints = Core::Service::Create(invalidEndpoints); + + // Call SetConnectivityTestEndpoints + uint32_t result = interface->SetConnectivityTestEndpoints(endpoints); + + // Verify the result + EXPECT_EQ(result, Core::ERROR_NONE); + + // Verify the endpoints were not set + std::vector retrievedEndpoints = NetworkManagerImplementation->connectivityMonitor.getConnectivityMonitorEndpoints(); + EXPECT_TRUE(retrievedEndpoints.size() == 1 && retrievedEndpoints[0] == "1234567890"); + + // Clean up + endpoints->Release(); +} + +TEST_F(NetworkManagerImplTest, SetConnectivityTestEndpoints_TooManyEndpoints) { + + std::vector tooManyEndpoints; + for (int i = 0; i < 12; ++i) { + tooManyEndpoints.push_back("http://example.com/endpoint" + std::to_string(i)); + } + RPC::IIteratorType* endpoints = Core::Service::Create(tooManyEndpoints); + + // Call SetConnectivityTestEndpoints + uint32_t result = interface->SetConnectivityTestEndpoints(endpoints); + + // Verify the result + EXPECT_EQ(result, Core::ERROR_NONE); + + std::vector retrievedEndpoints = NetworkManagerImplementation->connectivityMonitor.getConnectivityMonitorEndpoints(); + EXPECT_EQ((int)retrievedEndpoints.size(), 12); + + // Clean up + endpoints->Release(); +} + diff --git a/tests/mocks/ConnectivityMockServer.h b/tests/mocks/ConnectivityMockServer.h new file mode 100644 index 000000000..1e5570176 --- /dev/null +++ b/tests/mocks/ConnectivityMockServer.h @@ -0,0 +1,224 @@ +#include +#include +#include +#include +#include +#include +#include + +class SimpleHttpServer { +public: + SimpleHttpServer(unsigned short port = 8080) + : m_port(port), m_running(false), m_httpResponseCode(204), m_httpMessage(""), m_timeoutMs(0) {} + + ~SimpleHttpServer() { + stop(); + } + + void setHttpResponseCode(int code) { + m_httpResponseCode = code; + } + + void setHttpMessage(const std::string& message) { + m_httpMessage = message; + } + + void setTimeout(unsigned int timeoutMs) { + m_timeoutMs = timeoutMs; + } + + void start() { + m_running = true; + m_serverThread = std::thread([this]() { run(); }); + } + + void stop() { + m_running = false; + if (m_serverThread.joinable()) { + m_serverThread.join(); + } + } + +private: + void run() { + int server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd == -1) { + std::cerr << "Failed to create socket" << std::endl; + return; + } + + // Set SO_REUSEADDR to allow immediate reuse of the port + int opt = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { + std::cerr << "Failed to set socket options" << std::endl; + close(server_fd); + return; + } + + sockaddr_in server_addr{}; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(m_port); + + if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { + std::cerr << "Failed to bind socket" << std::endl; + close(server_fd); + return; + } + + if (listen(server_fd, 5) < 0) { + std::cerr << "Failed to listen on socket" << std::endl; + close(server_fd); + return; + } + + std::cout << "Server running on http://localhost:" << m_port << "/generate_204" << std::endl; + + while (m_running) { + sockaddr_in client_addr{}; + socklen_t client_len = sizeof(client_addr); + int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len); + if (client_fd < 0) { + std::cerr << "Failed to accept connection" << std::endl; + continue; + } + + handleRequest(client_fd); + close(client_fd); + } + + close(server_fd); + } + + void handleRequest(int client_fd) { + // If timeout is set, simulate a timeout by sleeping + if (m_timeoutMs > 0) { + // Break timeout into 100ms chunks so we can check for stop conditions + const unsigned int chunkSize = 100; // 100ms chunks + unsigned int remaining = m_timeoutMs; + + while (m_running && remaining > 0) { + // Sleep for chunkSize or remaining time, whichever is smaller + unsigned int sleepTime = std::min(chunkSize, remaining); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); + remaining -= sleepTime; + + // If stop() was called during the sleep, exit immediately + if (!m_running) { + break; + } + } + + // Return without sending a response to simulate timeout + return; + } + + char buffer[1024] = {0}; + ssize_t bytesRead = read(client_fd, buffer, sizeof(buffer)); + if (bytesRead < 0) { + std::cerr << "Error reading from client socket: " << strerror(errno) << std::endl; + return; + } + + std::string response; + + switch (m_httpResponseCode) { + case 204: // No Content + response = "HTTP/1.1 204 No Content\r\n"; + response += "Content-Length: 0\r\n"; + response += "Date: " + getCurrentDate() + "\r\n"; + response += "\r\n"; + break; + + case 302: // Found (Redirect) + response = "HTTP/1.1 302 Found\r\n"; + response += "Content-Length: " + std::to_string(m_httpMessage.size()) + "\r\n"; + response += "Location: " + m_httpMessage + "\r\n"; + response += "Date: " + getCurrentDate() + "\r\n"; + response += "\r\n"; + response += m_httpMessage; // Add the URI as the body + break; + + case 200: // OK + response = "HTTP/1.1 200 OK\r\n"; + response += "Content-Length: 0\r\n"; + response += "Date: " + getCurrentDate() + "\r\n"; + response += "\r\n"; + response += m_httpMessage; + break; + + case 404: // Not Found + response = "HTTP/1.1 404 Not Found\r\n"; + response += "Content-Length: 0\r\n"; + response += "Date: " + getCurrentDate() + "\r\n"; + response += "\r\n"; + break; + + case 511: // Authentication Required (Redirect as 302) + response = "HTTP/1.1 302 Found\r\n"; + response += "Content-Length: " + std::to_string(m_httpMessage.size()) + "\r\n"; + response += "Location: " + m_httpMessage + "\r\n"; + response += "Date: " + getCurrentDate() + "\r\n"; + response += "\r\n"; + response += m_httpMessage; // Add the URI as the body + break; + + default: // Default case for unsupported codes + response = "HTTP/1.1 500 Internal Server Error\r\n"; + response += "Content-Length: 0\r\n"; + response += "Date: " + getCurrentDate() + "\r\n"; + response += "\r\n"; + break; + } + + send(client_fd, response.c_str(), response.size(), 0); + } + + std::string getCurrentDate() { + std::time_t now = std::time(nullptr); + char buf[100]; + std::strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", std::gmtime(&now)); + return std::string(buf); + } + + unsigned short m_port; + std::thread m_serverThread; + bool m_running; + int m_httpResponseCode; + std::string m_httpMessage; + unsigned int m_timeoutMs; +}; + +// int main() { +// SimpleHttpServer server(8080); + +// // Test all possible response codes +// std::vector> testCases = { +// {204, ""}, // No Content +// {302, "http://example.com/redirect"}, // Found (Redirect) +// {200, "OK"}, // OK +// {404, ""}, // Not Found +// {511, "http://captive.portal/login"} // Authentication Required (Redirect as 302) +// }; + +// for (const auto& testCase : testCases) { +// server.setHttpResponseCode(testCase.first); +// server.setHttpMessage(testCase.second); + +// std::cout << "Testing HTTP response code: " << testCase.first << std::endl; +// server.start(); + +// std::this_thread::sleep_for(std::chrono::seconds(5)); // Wait for 5 seconds to test +// server.stop(); +// std::this_thread::sleep_for(std::chrono::seconds(1)); +// } + +// // Test timeout functionality +// std::cout << "Testing timeout functionality..." << std::endl; +// server.setTimeout(5000); // Set a 5000ms timeout +// server.start(); +// std::this_thread::sleep_for(std::chrono::seconds(10)); // Wait longer than the timeout +// server.stop(); + +// return 0; +// } \ No newline at end of file diff --git a/tests/mocks/Iarm.cpp b/tests/mocks/Iarm.cpp index a4a7babdc..63aa73353 100644 --- a/tests/mocks/Iarm.cpp +++ b/tests/mocks/Iarm.cpp @@ -20,7 +20,11 @@ #include "Iarm.h" #include +#ifdef ENABLE_TEST_LOG #define TEST_LOG(x, ...) fprintf(stderr, "\033[1;32m[%s:%d](%s)" x "\n\033[0m", __FILE__, __LINE__, __FUNCTION__, getpid(), gettid(), ##__VA_ARGS__); fflush(stderr); +#else +#define TEST_LOG(x, ...) +#endif IarmBusImpl* IarmBus::impl = nullptr; diff --git a/tests/mocks/IarmBusMock.h b/tests/mocks/IarmBusMock.h index ad18629a2..5f344412c 100644 --- a/tests/mocks/IarmBusMock.h +++ b/tests/mocks/IarmBusMock.h @@ -21,8 +21,11 @@ #include #include "libIBus.h" +#ifdef ENABLE_TEST_LOG #define TEST_LOG(x, ...) fprintf(stderr, "\033[1;32m[%s:%d](%s)" x "\n\033[0m", __FILE__, __LINE__, __FUNCTION__, getpid(), gettid(), ##__VA_ARGS__); fflush(stderr); - +#else +#define TEST_LOG(x, ...) +#endif class IarmBusImplMock : public IarmBusImpl { public: IarmBusImplMock() @@ -46,7 +49,6 @@ class IarmBusImplMock : public IarmBusImpl { ON_CALL(*this, IARM_Bus_Connect()) .WillByDefault(::testing::Invoke( []() { - TEST_LOG("Mock IARM_Bus_Connect called"); return IARM_RESULT_SUCCESS; })); ON_CALL(*this, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) diff --git a/tests/mocks/Wraps.cpp b/tests/mocks/Wraps.cpp new file mode 100644 index 000000000..2ff5b4815 --- /dev/null +++ b/tests/mocks/Wraps.cpp @@ -0,0 +1,162 @@ +#include +#include +#include "Wraps.h" +#include +#include + +extern "C" int __wrap_system(const char* command) +{ + return Wraps::getInstance().system(command); +} + +extern "C" FILE* __wrap_popen(const char* command, const char* type) +{ + return Wraps::getInstance().popen(command, type); +} + +extern "C" int __wrap_pclose(FILE* pipe) +{ + return Wraps::getInstance().pclose(pipe); +} + +//This function will be called for syslog() in the code (added -Wl,-wrap,syslog) +extern "C" void __wrap_syslog(int pri, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Wraps::getInstance().syslog(pri, fmt, args); + vsyslog(pri, fmt, args); + va_end(args); +} + +extern "C" FILE* __wrap_setmntent(const char* command, const char* type) +{ + return Wraps::getInstance().setmntent(command, type); +} + +extern "C" struct mntent* __wrap_getmntent(FILE* pipe) +{ + return Wraps::getInstance().getmntent(pipe); +} + +extern "C" FILE * __wrap_v_secure_popen(const char *direction, const char *command, ...) +{ + va_list args; + FILE *retFp = nullptr; + va_start(args, command); + retFp = Wraps::getInstance().v_secure_popen(direction, command, args); + va_end(args); + return retFp; +} + + +extern "C" int __wrap_v_secure_pclose(FILE *file) +{ + return Wraps::getInstance().v_secure_pclose(file); +} + + +extern "C" int __wrap_v_secure_system(const char *command, ...) +{ + int ret; + va_list args; + va_start(args,command); + ret = Wraps::getInstance().v_secure_system(command, args); + va_end(args); + return ret; +} + +extern "C" ssize_t __wrap_readlink(const char *pathname, char *buf, size_t bufsiz) +{ + return Wraps::getInstance().readlink(pathname, buf, bufsiz); +} + +extern "C" time_t __wrap_time(time_t *arg) +{ + return Wraps::getInstance().time(arg); +} + +WrapsImpl* Wraps::impl = nullptr; + +Wraps::Wraps() {} + +void Wraps::setImpl(WrapsImpl* newImpl) +{ + // Handles both resetting 'impl' to nullptr and assigning a new value to 'impl' + EXPECT_TRUE ((nullptr == impl) || (nullptr == newImpl)); + impl = newImpl; +} + +Wraps& Wraps::getInstance() +{ + static Wraps instance; + return instance; +} + +int Wraps::system(const char* command) +{ + EXPECT_NE(impl, nullptr); + return impl->system(command); +} + +FILE* Wraps::popen(const char* command, const char* type) +{ + EXPECT_NE(impl, nullptr); + return impl->popen(command, type); +} + +int Wraps::pclose(FILE* pipe) +{ + EXPECT_NE(impl, nullptr); + return impl->pclose(pipe); +} + +void Wraps::syslog(int pri, const char* fmt, va_list args) +{ + EXPECT_NE(impl, nullptr); + impl->syslog(pri, fmt, args); +} + +FILE* Wraps::setmntent(const char* command, const char* type) +{ + EXPECT_NE(impl, nullptr); + return impl->setmntent(command,type); +} + +struct mntent* Wraps::getmntent(FILE* pipe) +{ + EXPECT_NE(impl, nullptr); + return impl->getmntent(pipe); +} + +FILE * Wraps::v_secure_popen(const char *direction, const char *command, va_list args) +{ + EXPECT_NE(impl, nullptr); + return impl->v_secure_popen(direction, command, args); +} + +int Wraps::v_secure_pclose(FILE *file) +{ + EXPECT_NE(impl, nullptr); + return impl->v_secure_pclose(file); +} + +int Wraps::v_secure_system(const char *command, va_list args) +{ + EXPECT_NE(impl, nullptr); + return impl->v_secure_system(command,args); +} + + +ssize_t Wraps::readlink(const char *pathname, char *buf, size_t bufsiz) +{ + EXPECT_NE(impl, nullptr); + return impl->readlink(pathname,buf,bufsiz); +} + +time_t Wraps::time(time_t* arg) +{ + EXPECT_NE(impl, nullptr); + return impl->time(arg); +} + diff --git a/tests/mocks/Wraps.h b/tests/mocks/Wraps.h new file mode 100644 index 000000000..ff34a0fda --- /dev/null +++ b/tests/mocks/Wraps.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include "secure_wrappermock.h" + +class WrapsImpl { +public: + virtual ~WrapsImpl() = default; + + virtual int system(const char* command) = 0; + virtual FILE* popen(const char* command, const char* type) = 0; + virtual int pclose(FILE *pipe) = 0; + virtual void syslog(int pri, const char* fmt, va_list args) = 0; + virtual FILE* setmntent(const char* command, const char* type) = 0; + virtual struct mntent* getmntent(FILE *pipe) = 0; + virtual FILE *v_secure_popen(const char *direction, const char *command, va_list args) = 0; + virtual int v_secure_pclose(FILE *) = 0; + virtual int v_secure_system(const char *command, va_list args) =0; + virtual ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) = 0; + virtual time_t time(time_t* arg) = 0; +}; + +class Wraps { +protected: + static WrapsImpl* impl; + +public: + Wraps(); + Wraps(const Wraps &obj) = delete; + static void setImpl(WrapsImpl* newImpl); + static Wraps& getInstance(); + + static int system(const char* command); + + static FILE* popen(const char* command, const char* type); + + static int pclose(FILE* pipe); + + static void syslog(int pri, const char* fmt, va_list args); + + static FILE* setmntent(const char* command, const char* type); + + static struct mntent* getmntent(FILE* pipe); + + static FILE *v_secure_popen(const char *direction, const char *command, va_list args); + + static int v_secure_pclose(FILE *file); + + static int v_secure_system(const char *command, va_list args); + + ssize_t readlink(const char *pathname, char *buf, size_t bufsiz); + + static time_t time(time_t* arg); +}; diff --git a/tests/mocks/WrapsMock.h b/tests/mocks/WrapsMock.h new file mode 100644 index 000000000..b6f99728e --- /dev/null +++ b/tests/mocks/WrapsMock.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +#include "Wraps.h" + +extern "C" FILE* __real_setmntent(const char* command, const char* type); + +class WrapsImplMock : public WrapsImpl { +public: + WrapsImplMock():WrapsImpl() + { + /*Setting up Default behavior for setmntent: + * We are mocking setmntent in this file below with __wrap_setmntent, + * and the actual setmntent will be called via this interface */ + ON_CALL(*this, setmntent(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + return __real_setmntent(command, type); + })); + } + virtual ~WrapsImplMock() = default; + + MOCK_METHOD(int, system, (const char* command), (override)); + MOCK_METHOD(FILE*, popen, (const char* command, const char* type), (override)); + MOCK_METHOD(int, pclose, (FILE* pipe), (override)); + MOCK_METHOD(void, syslog, (int pri, const char* fmt, va_list args), (override)); + MOCK_METHOD(FILE*, setmntent, (const char* command, const char* type), (override)); + MOCK_METHOD(struct mntent*, getmntent, (FILE* pipe), (override)); + MOCK_METHOD(FILE*, v_secure_popen, (const char *direction, const char *command, va_list args), (override)); + MOCK_METHOD(int, v_secure_pclose, (FILE *file), (override)); + MOCK_METHOD(int, v_secure_system,(const char *command, va_list args), (override)); + MOCK_METHOD(ssize_t, readlink, (const char *pathname, char *buf, size_t bufsiz), (override)); + MOCK_METHOD(time_t, time, (time_t* arg), (override)); +}; \ No newline at end of file diff --git a/tests/mocks/secure_wrappermock.h b/tests/mocks/secure_wrappermock.h new file mode 100644 index 000000000..37dd7a2e4 --- /dev/null +++ b/tests/mocks/secure_wrappermock.h @@ -0,0 +1,37 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once +#include +#include + +# ifdef __cplusplus +extern "C" { +# endif + + +FILE *v_secure_popen(const char *direction, const char *command, ...); + +int v_secure_pclose(FILE *); + +int v_secure_system(const char *command, ...); + +# ifdef __cplusplus +} +# endif diff --git a/tests/mocks/thunder/COMLinkMock.h b/tests/mocks/thunder/COMLinkMock.h index 28557ca0d..4b69f988a 100644 --- a/tests/mocks/thunder/COMLinkMock.h +++ b/tests/mocks/thunder/COMLinkMock.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2023 RDK Management +* Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,10 +28,11 @@ class COMLinkMock : public WPEFramework::PluginHost::IShell::ICOMLink { virtual ~COMLinkMock() = default; MOCK_METHOD(void, Register, (WPEFramework::RPC::IRemoteConnection::INotification*), (override)); - MOCK_METHOD(void, Unregister, (WPEFramework::RPC::IRemoteConnection::INotification*), (override)); + MOCK_METHOD(void, Unregister, (const WPEFramework::RPC::IRemoteConnection::INotification*), (override)); + MOCK_METHOD(void, Register, (INotification*), (override)); + MOCK_METHOD(void, Unregister, (INotification*), (override)); MOCK_METHOD(WPEFramework::RPC::IRemoteConnection*, RemoteConnection, (const uint32_t), (override)); - MOCK_METHOD(void*, Instantiate, (const WPEFramework::RPC::Object&, const uint32_t, uint32_t&, const string&, const string&), (override)); + MOCK_METHOD(void*, Instantiate, (const WPEFramework::RPC::Object&, const uint32_t, uint32_t&), (override)); }; #endif //RDKSERVICES_TESTS_MOCKS_COMLINKMOCK_H_ - diff --git a/tests/mocks/thunder/Communicator.cpp b/tests/mocks/thunder/Communicator.cpp new file mode 100755 index 000000000..2bb1bceb8 --- /dev/null +++ b/tests/mocks/thunder/Communicator.cpp @@ -0,0 +1,30 @@ +/* +* If not stated otherwise in this file or this component's LICENSE file the +* following copyright and licenses apply: +* +* Copyright 2025 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "Communicator.h" +#include + +ICommunicatorClient* WPEFramework::RPC::CommunicatorClient::impl = nullptr; + +void WPEFramework::RPC::CommunicatorClient::setImpl(ICommunicatorClient* newImpl) +{ + // Handles both resetting 'impl' to nullptr and assigning a new value to 'impl' + EXPECT_TRUE ((nullptr == impl) || (nullptr == newImpl)); + impl = newImpl; +} diff --git a/tests/mocks/thunder/Communicator.h b/tests/mocks/thunder/Communicator.h new file mode 100755 index 000000000..5d0524b84 --- /dev/null +++ b/tests/mocks/thunder/Communicator.h @@ -0,0 +1,286 @@ +/* +* If not stated otherwise in this file or this component's LICENSE file the +* following copyright and licenses apply: +* +* Copyright 2025 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __COM_PROCESSLAUNCH_H +#define __COM_PROCESSLAUNCH_H + +#include +#include "Proxy.h" +#include "NodeId.h" +#include "IPCConnector.h" + +using std::string; +const uint32_t CommunicationTimeOut = 3000; + +class ICommunicatorClient { +public: + virtual ~ICommunicatorClient() = default; + virtual uint32_t Open(const uint32_t waitTime) = 0; + virtual void* Open(const std::string& className, const uint32_t version, const uint32_t waitTime) = 0; + virtual void* Acquire(const uint32_t waitTime, const std::string& className, const uint32_t versionId) = 0; + virtual uint32_t Offer(void* offer, const uint32_t version, const uint32_t waitTime) = 0; + virtual uint32_t Revoke(void* offer, const uint32_t version, const uint32_t waitTime) = 0; + virtual uint32_t Close(const uint32_t waitTime) = 0; + virtual void* Acquire(const std::string& className, const uint32_t interfaceId, const uint32_t versionId) = 0; +}; + +namespace WPEFramework { +namespace RPC { + class Object { + public: + enum class HostType { + LOCAL, + DISTRIBUTED, + CONTAINER + }; + + Object() + : _locator() + , _className() + , _callsign() + , _interface(~0) + , _version(~0) + , _user() + , _group() + , _threads() + , _priority() + , _type(HostType::LOCAL) + , _systemRootPath() + , _remoteAddress() + , _configuration() + { + } + Object(const Object& copy) + : _locator(copy._locator) + , _className(copy._className) + , _callsign(copy._callsign) + , _interface(copy._interface) + , _version(copy._version) + , _user(copy._user) + , _group(copy._group) + , _threads(copy._threads) + , _priority(copy._priority) + , _type(copy._type) + , _systemRootPath(copy._systemRootPath) + , _remoteAddress(copy._remoteAddress) + , _configuration(copy._configuration) + { + } + Object(const string& locator, + const string& className, + const string& callsign, + const uint32_t interface, + const uint32_t version, + const string& user, + const string& group, + const uint8_t threads, + const int8_t priority, + const HostType type, + const string& systemRootPath, + const string& remoteAddress, + const string& configuration) + : _locator(locator) + , _className(className) + , _callsign(callsign) + , _interface(interface) + , _version(version) + , _user(user) + , _group(group) + , _threads(threads) + , _priority(priority) + , _type(type) + , _systemRootPath(systemRootPath) + , _remoteAddress(remoteAddress) + , _configuration(configuration) + { + } + ~Object() + { + } + + Object& operator=(const Object& RHS) + { + _locator = RHS._locator; + _className = RHS._className; + _callsign = RHS._callsign; + _interface = RHS._interface; + _version = RHS._version; + _user = RHS._user; + _group = RHS._group; + _threads = RHS._threads; + _priority = RHS._priority; + _systemRootPath = RHS._systemRootPath; + _type = RHS._type; + _remoteAddress = RHS._remoteAddress; + _configuration = RHS._configuration; + + return (*this); + } + + public: + inline const string& Locator() const + { + return (_locator); + } + inline const string& ClassName() const + { + return (_className); + } + inline const string& Callsign() const + { + return (_callsign); + } + inline uint32_t Interface() const + { + return (_interface); + } + inline uint32_t Version() const + { + return (_version); + } + inline const string& User() const + { + return (_user); + } + inline const string& Group() const + { + return (_group); + } + inline uint8_t Threads() const + { + return (_threads); + } + inline int8_t Priority() const + { + return (_priority); + } + inline HostType Type() const + { + return (_type); + } + inline const string& SystemRootPath() const + { + return (_systemRootPath); + } + inline const Core::NodeId RemoteAddress() const + { + return (Core::NodeId(_remoteAddress.c_str())); + } + inline const string& Configuration() const + { + return (_configuration); + } + + private: + string _locator; + string _className; + string _callsign; + uint32_t _interface; + uint32_t _version; + string _user; + string _group; + uint8_t _threads; + int8_t _priority; + HostType _type; + string _systemRootPath; + string _remoteAddress; + string _configuration; + }; + + class CommunicatorClient{ + protected: + static ICommunicatorClient* impl; + + public: + class Source { + bool IsOpen() const + { + return true; + } + }; + CommunicatorClient() = delete; + CommunicatorClient(CommunicatorClient&&) = delete; + CommunicatorClient(const CommunicatorClient&) = delete; + CommunicatorClient& operator=(CommunicatorClient&&) = delete; + CommunicatorClient& operator=(const CommunicatorClient&) = delete; + + static void setImpl(ICommunicatorClient* newImpl); + + CommunicatorClient(const Core::NodeId& remoteNode) { + //Mock CommunicatorClient constructor. + } + + CommunicatorClient(const Core::NodeId& remoteNode, const Core::ProxyType& handler) { + //Mock CommunicatorClient constructor. + } + + ~CommunicatorClient() { + } + + public: + inline uint32_t ConnectionId() const { + return _connectionId; + } + + // Open a communication channel with this process, no need for an initial exchange + uint32_t Open(const uint32_t waitTime) + { + return impl->Open(waitTime); + } + template + INTERFACE* Open(const std::string& className, const uint32_t version = static_cast(~0), const uint32_t waitTime = CommunicationTimeOut) + { + return static_cast(impl->Open(className, version, waitTime)); + } + template + INTERFACE* Acquire(const uint32_t waitTime, const std::string& className, const uint32_t versionId) + { + return static_cast(impl->Acquire(waitTime, className, versionId)); + } + template + uint32_t Offer(INTERFACE* offer, const uint32_t version = static_cast(~0), const uint32_t waitTime = CommunicationTimeOut) + { + return static_cast(impl->Offer(static_cast(offer), version, CommunicationTimeOut)); + } + template + uint32_t Revoke(INTERFACE* offer, const uint32_t version = static_cast(~0), const uint32_t waitTime = CommunicationTimeOut) + { + return static_cast(impl->Revoke(static_cast(offer), version, CommunicationTimeOut)); + } + uint32_t Close(const uint32_t waitTime) + { + if (impl) + return impl->Close(waitTime); + return Core::ERROR_GENERAL; + } + virtual void* Acquire(const std::string& className, const uint32_t interfaceId, const uint32_t versionId) + { + return impl->Acquire(className, interfaceId, versionId); + } + protected: + void StateChange() { + //Mock CommunicatorClient StateChange is calling. + } + private: + uint32_t _connectionId; + }; +} +} +#endif // __COM_PROCESSLAUNCH_H + diff --git a/tests/mocks/thunder/CommunicatorMock.h b/tests/mocks/thunder/CommunicatorMock.h new file mode 100755 index 000000000..60bfdcefa --- /dev/null +++ b/tests/mocks/thunder/CommunicatorMock.h @@ -0,0 +1,53 @@ +/* +* If not stated otherwise in this file or this component's LICENSE file the +* following copyright and licenses apply: +* +* Copyright 2025 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#pragma once + +#include +#include "Communicator.h" + +#if 0 +class CommunicatorClientMock : public ICommunicatorClient +{ +public: + virtual ~CommunicatorClientMock() = default; + + MOCK_METHOD(uint32_t, Open, (const uint32_t waitTime), (override)); + MOCK_METHOD(INTERFACE*, Open, (const std::string& className, const uint32_t version, const uint32_t waitTime), (override)); + MOCK_METHOD(INTERFACE*, Acquire, (const uint32_t waitTime, const std::string& className, const uint32_t versionId), (override)); + MOCK_METHOD(uint32_t, Offer, (INTERFACE* offer, const uint32_t version, const uint32_t waitTime), (override)); + MOCK_METHOD(uint32_t, Revoke, (INTERFACE* offer, const uint32_t version, const uint32_t waitTime), (override)); + MOCK_METHOD(uint32_t, Close, (const uint32_t waitTime), (override)); +}; +#else +class CommunicatorClientMock : public ICommunicatorClient { +public: + virtual ~CommunicatorClientMock() = default; + MOCK_METHOD(void, AddRef, (), (const)); + MOCK_METHOD(uint32_t, Release, (), (const)); + MOCK_METHOD(uint32_t, Open, (const uint32_t waitTime), (override)); + MOCK_METHOD(void*, Open, (const std::string& className, const uint32_t version, const uint32_t waitTime), (override)); + MOCK_METHOD(void*, Acquire, (const uint32_t waitTime, const std::string& className, const uint32_t versionId), (override)); + MOCK_METHOD(uint32_t, Offer, (void* offer, const uint32_t version, const uint32_t waitTime), (override)); + MOCK_METHOD(uint32_t, Revoke, (void* offer, const uint32_t version, const uint32_t waitTime), (override)); + MOCK_METHOD(uint32_t, Close, (const uint32_t waitTime), (override)); + MOCK_METHOD(void*, Acquire, (const std::string& className, const uint32_t interfaceId, const uint32_t versionId), (override)); +}; + +#endif diff --git a/tests/mocks/thunder/DispatcherMock.h b/tests/mocks/thunder/DispatcherMock.h index 5229c6783..7a643f79c 100644 --- a/tests/mocks/thunder/DispatcherMock.h +++ b/tests/mocks/thunder/DispatcherMock.h @@ -1,21 +1,21 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2023 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #ifndef DISPATCHERMOCK_H #define DISPATCHERMOCK_H @@ -24,7 +24,7 @@ #include "Module.h" - class DispatcherMock: public WPEFramework::PluginHost::IDispatcher{ + class DispatcherMock: public WPEFramework::PluginHost::ILocalDispatcher{ public: virtual ~DispatcherMock() = default; MOCK_METHOD(void, AddRef, (), (const, override)); @@ -32,8 +32,12 @@ MOCK_METHOD(void*, QueryInterface, (const uint32_t interfaceNummer), (override)); MOCK_METHOD(void, Activate, (WPEFramework::PluginHost::IShell* service)); MOCK_METHOD(void, Deactivate, ()); - MOCK_METHOD(WPEFramework::Core::ProxyType, Invoke, (const string&, uint32_t, const WPEFramework::Core::JSONRPC::Message&), (override)); + MOCK_METHOD(void, Dropped, (const uint32_t)); + MOCK_METHOD(uint32_t, Invoke, (const uint32_t channelId, const uint32_t id, const string& token, const string& method, const string& parameters, string& response), (override)); + MOCK_METHOD(WPEFramework::Core::hresult, Invoke, (WPEFramework::PluginHost::IDispatcher::ICallback* callback, const uint32_t channelId, const uint32_t id, const string& token, const string& method, const string& parameters /* @restrict:(4M-1) */, string& response /* @restrict:(4M-1) @out */), (override)); + MOCK_METHOD(WPEFramework::Core::hresult, Revoke, (WPEFramework::PluginHost::IDispatcher::ICallback* callback), (override)); + MOCK_METHOD(WPEFramework::Core::hresult, Validate, (const string& token, const string& method, const string& paramaters /* @restrict:(4M-1) */), (const, override)); + MOCK_METHOD(WPEFramework::PluginHost::ILocalDispatcher*, Local, (), (override)); }; #endif //DISPATCHERMOCK_H - diff --git a/tests/mocks/thunder/FactoriesImplementation.h b/tests/mocks/thunder/FactoriesImplementation.h index e1f381b8d..2fe178f85 100644 --- a/tests/mocks/thunder/FactoriesImplementation.h +++ b/tests/mocks/thunder/FactoriesImplementation.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2023 RDK Management +* Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -64,4 +64,3 @@ class FactoriesImplementation : public WPEFramework::PluginHost::IFactories { WPEFramework::Core::ProxyPoolType _fileBodyFactory; WPEFramework::Core::ProxyPoolType _jsonRPCFactory; }; - diff --git a/tests/mocks/thunder/Module.cpp b/tests/mocks/thunder/Module.cpp index ab461e818..cd6d4d14e 100644 --- a/tests/mocks/thunder/Module.cpp +++ b/tests/mocks/thunder/Module.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2023 RDK Management +* Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tests/mocks/thunder/Module.h b/tests/mocks/thunder/Module.h index 4c34d4669..e113be84f 100644 --- a/tests/mocks/thunder/Module.h +++ b/tests/mocks/thunder/Module.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2023 RDK Management +* Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ #pragma once #ifndef MODULE_NAME -#define MODULE_NAME tests +#define MODULE_NAME networkmanager_tests #endif #include diff --git a/tests/mocks/thunder/ServiceMock.h b/tests/mocks/thunder/ServiceMock.h index e14547d55..537395005 100644 --- a/tests/mocks/thunder/ServiceMock.h +++ b/tests/mocks/thunder/ServiceMock.h @@ -1,21 +1,21 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2023 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #ifndef SERVICEMOCK_H #define SERVICEMOCK_H @@ -23,12 +23,11 @@ #include #include "Module.h" - class ServiceMock : public WPEFramework::PluginHost::IShell { public: virtual ~ServiceMock() = default; - MOCK_METHOD(void, AddRef, (), (const, override)); + MOCK_METHOD(uint32_t, AddRef, (), (const, override)); MOCK_METHOD(uint32_t, Release, (), (const, override)); MOCK_METHOD(string, Versions, (), (const, override)); MOCK_METHOD(string, Locator, (), (const, override)); @@ -52,7 +51,6 @@ class ServiceMock : public WPEFramework::PluginHost::IShell { MOCK_METHOD(WPEFramework::Core::hresult, Startup, (const startup value), (override)); MOCK_METHOD(WPEFramework::Core::hresult, Resumed, (const bool value), (override)); MOCK_METHOD(WPEFramework::Core::hresult, Metadata, (string& info), (const, override)); - MOCK_METHOD(bool, Resumed, (), (const, override)); MOCK_METHOD(bool, IsSupported, (const uint8_t), (const, override)); MOCK_METHOD(void, EnableWebServer, (const string&, const string&), (override)); @@ -76,4 +74,3 @@ class ServiceMock : public WPEFramework::PluginHost::IShell { }; #endif //SERVICEMOCK_H - diff --git a/tests/mocks/thunder/SystemInfo.h b/tests/mocks/thunder/SystemInfo.h index 12ee47ec8..c20266274 100644 --- a/tests/mocks/thunder/SystemInfo.h +++ b/tests/mocks/thunder/SystemInfo.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2023 RDK Management +* Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -81,4 +81,3 @@ class SystemInfo : public WPEFramework::PluginHost::ISubSystem { std::map _subsystems; uint32_t _flags; }; - diff --git a/tests/mocks/thunder/ThunderPortability.h b/tests/mocks/thunder/ThunderPortability.h old mode 100644 new mode 100755 index 48f2407d5..62310708a --- a/tests/mocks/thunder/ThunderPortability.h +++ b/tests/mocks/thunder/ThunderPortability.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2023 RDK Management +* Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,4 +29,3 @@ #define INIT_CONX(__X__, __Y__) connection(__X__, __Y__, "") #define PLUGINHOST_DISPATCHER PluginHost::ILocalDispatcher #define PLUGINHOST_DISPATCHER_ID PluginHost::ILocalDispatcher::ID - diff --git a/tests/mocks/thunder/WorkerPoolImplementation.h b/tests/mocks/thunder/WorkerPoolImplementation.h index 2a0f924e9..bb7466150 100644 --- a/tests/mocks/thunder/WorkerPoolImplementation.h +++ b/tests/mocks/thunder/WorkerPoolImplementation.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE * file the following copyright and licenses apply: * -* Copyright 2023 RDK Management +* Copyright 2024 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,4 +61,3 @@ class WorkerPoolImplementation : public WPEFramework::Core::WorkerPool { private: Dispatcher _dispatcher; }; - diff --git a/tests/mocks/thunder/mockauthservices.h b/tests/mocks/thunder/mockauthservices.h new file mode 100644 index 000000000..9a696ff5d --- /dev/null +++ b/tests/mocks/thunder/mockauthservices.h @@ -0,0 +1,87 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCKAUTHSERVICES_H +#define MOCKAUTHSERVICES_H + +#include + +#include "Module.h" + +class MockAuthService : public WPEFramework::Exchange::IAuthService { +public: + virtual ~MockAuthService() = default; + MOCK_METHOD(uint32_t, GetActivationStatus, (ActivationStatusResult&), (override)); + MOCK_METHOD(uint32_t, SetActivationStatus, (const std::string&, SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, ClearAuthToken, (SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, ClearSessionToken, (SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, ClearServiceAccessToken, (SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, ClearLostAndFoundAccessToken, (SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, ClearServiceAccountId, (SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, ClearCustomProperties, (SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, GetCustomProperties, (std::string&, bool&), (override)); + MOCK_METHOD(uint32_t, SetCustomProperties, (const std::string&, bool&), (override)); + MOCK_METHOD(uint32_t, GetAlternateIds, (std::string&, std::string&, bool&), (override)); + MOCK_METHOD(uint32_t, SetAlternateIds, (const std::string&, std::string&, bool&), (override)); + MOCK_METHOD(uint32_t, GetTransitionData, (std::string&, std::string&, bool&), (override)); + MOCK_METHOD(void, AddRef, (), (const, override)); + MOCK_METHOD(uint32_t, Release, (), (const, override)); + MOCK_METHOD(void*, QueryInterface, (uint32_t), (override)); + MOCK_METHOD(uint32_t, Register, (IAuthService::INotification*), (override)); + MOCK_METHOD(uint32_t, Unregister, (IAuthService::INotification*), (override)); + MOCK_METHOD(uint32_t, Configure, (), (override)); + MOCK_METHOD(uint32_t, GetInfo, (GetInfoResult&), (override)); + MOCK_METHOD(uint32_t, GetDeviceInfo, (GetDeviceInfoResult&), (override)); + MOCK_METHOD(uint32_t, GetDeviceId, (GetDeviceIdResult&), (override)); + MOCK_METHOD(uint32_t, SetDeviceId, (const std::string&, SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, SetPartnerId, (const std::string&, SetPartnerIdResult&), (override)); + MOCK_METHOD(uint32_t, GetAuthToken, (const bool, const bool, GetAuthTokenResult&), (override)); + MOCK_METHOD(uint32_t, GetSessionToken, (GetSessionTokenResult&), (override)); + MOCK_METHOD(uint32_t, SetSessionToken, (const int32_t&, const std::string&, uint32_t, const std::string&, const std::string&, SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, GetServiceAccessToken, (GetServiceAccessTokenResult&), (override)); + MOCK_METHOD(uint32_t, SetServiceAccessToken, (const int32_t&, const std::string&, uint32_t, SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, GetServiceAccountId, (GetServiceAccountIdResult&), (override)); + MOCK_METHOD(uint32_t, SetServiceAccountId, (const std::string&, SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, SetAuthIdToken, (const std::string&, SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, Ready, (const std::string&, SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, GetBootstrapProperty, (const std::string&, GetBootstrapPropResult&), (override)); + MOCK_METHOD(uint32_t, ActivationStarted, (SuccessResult&), (override)); + MOCK_METHOD(uint32_t, ActivationComplete, (SuccessResult&), (override)); + MOCK_METHOD(uint32_t, GetLostAndFoundAccessToken, (std::string&, std::string&, bool&), (override)); + MOCK_METHOD(uint32_t, SetLostAndFoundAccessToken, (const std::string&, SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, GetXDeviceId, (GetXDeviceIdResult&), (override)); + MOCK_METHOD(uint32_t, SetXDeviceId, (const std::string&, SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, GetExperience, (GetExpResult&), (override)); + MOCK_METHOD(uint32_t, SetExperience, (const std::string&, SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, GetXifaId, (GetxifaIdResult&), (override)); + MOCK_METHOD(uint32_t, SetXifaId, (const std::string&, SuccessMsgResult&), (override)); + MOCK_METHOD(uint32_t, GetAdvtOptOut, (AdvtOptOutResult&), (override)); + MOCK_METHOD(uint32_t, SetAdvtOptOut, (const bool&, SuccessMsgResult&), (override)); +}; + +class MockIAuthenticate : public WPEFramework::PluginHost::IAuthenticate { +public: + MOCK_METHOD(void*, QueryInterfaceByCallsign, (const uint32_t, const string&)); + MOCK_METHOD(uint32_t, CreateToken, (uint16_t, const uint8_t*, std::string&)); + MOCK_METHOD(uint32_t, Release, (), (const, override)); + MOCK_METHOD(void*, QueryInterface, (uint32_t), (override)); + MOCK_METHOD(void, AddRef, (), (const, override)); + MOCK_METHOD(WPEFramework::PluginHost::ISecurity*, Officer, (const std::string& token), (override)); +}; +#endif From 52d80d4bcdb05551098cc4b188ee03a25e0e0a37 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 30 Jul 2025 16:56:16 -0400 Subject: [PATCH 161/271] RDKEMW-5763 - NetworkManager Legacy Plugins - Improve L1/L2 Test coverage (#201) * RDKEMW-5763 - NetworkManager Legacy Plugins - Improve L1/L2 Test coverage Reason for change: Added L2 test cases for legacy network and wifi plugin Test Procedure: Check the unit test yml is executing properly or not for legacy plugin Risks: Medium Priority: P1 Signed-off-by: Gururaaja ESR --- .github/workflows/gdbus_proxy_L1_test.yml | 2 +- .github/workflows/legacy_L1_L2_test.yml | 171 ++++ .github/workflows/libnm_proxy_L1_test.yml | 2 +- .github/workflows/rdk_proxy_L1_L2_test.yml | 2 +- legacy/LegacyWiFiManagerAPIs.cpp | 2 +- tests/l2Test/CMakeLists.txt | 58 +- .../l2_test_LegacyPlugin_NetworkAPIs.cpp | 941 ++++++++++++++++++ .../l2_test_LegacyPlugin_WiFiManagerAPIs.cpp | 898 +++++++++++++++++ tests/mocks/INetworkManagerMock.h | 60 ++ tests/mocks/LegacyNetworkMock.h | 65 ++ tests/mocks/LegacyWiFiManagerMock.h | 54 + tests/mocks/thunder/CommunicatorMock.h | 2 +- tests/mocks/thunder/DispatcherMock.h | 2 +- tests/mocks/thunder/IStringIteratorMock.h | 39 + tests/mocks/thunder/InterfaceIteratorMock.h | 38 + tests/mocks/thunder/mockauthservices.h | 53 +- .../thunder/Remove-SmartLinkType.patch | 21 - tests/patches/thunder/SubscribeStub.patch | 21 + 18 files changed, 2351 insertions(+), 80 deletions(-) create mode 100644 .github/workflows/legacy_L1_L2_test.yml create mode 100644 tests/l2Test/l2_test_LegacyPlugin_NetworkAPIs.cpp create mode 100644 tests/l2Test/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp create mode 100644 tests/mocks/INetworkManagerMock.h create mode 100644 tests/mocks/LegacyNetworkMock.h create mode 100644 tests/mocks/LegacyWiFiManagerMock.h create mode 100644 tests/mocks/thunder/IStringIteratorMock.h create mode 100644 tests/mocks/thunder/InterfaceIteratorMock.h delete mode 100644 tests/patches/thunder/Remove-SmartLinkType.patch create mode 100644 tests/patches/thunder/SubscribeStub.patch diff --git a/.github/workflows/gdbus_proxy_L1_test.yml b/.github/workflows/gdbus_proxy_L1_test.yml index 7d605b4ba..242ca6bda 100644 --- a/.github/workflows/gdbus_proxy_L1_test.yml +++ b/.github/workflows/gdbus_proxy_L1_test.yml @@ -71,7 +71,7 @@ jobs: if: steps.cache.outputs.cache-hit != 'true' run: | cd ${{github.workspace}}/Thunder - git apply ${{github.workspace}}/networkmanager/tests/patches/thunder/Remove-SmartLinkType.patch + git apply ${{github.workspace}}/networkmanager/tests/patches/thunder/SubscribeStub.patch - name: Build ThunderTools if: steps.cache.outputs.cache-hit != 'true' diff --git a/.github/workflows/legacy_L1_L2_test.yml b/.github/workflows/legacy_L1_L2_test.yml new file mode 100644 index 000000000..a735bfdf3 --- /dev/null +++ b/.github/workflows/legacy_L1_L2_test.yml @@ -0,0 +1,171 @@ +name: legacy_l1_l2_tests + +on: + push: + branches: [ main, develop, 'support/**', 'hotfix/**', 'topic/**'] + pull_request: + branches: [ main, develop, 'support/**', 'hotfix/**', 'topic/**'] + +env: + THUNDER_REF: "R4.4.3" + +jobs: + L1-tests: + permissions: + contents: read + pull-requests: write + name: Build and run unit tests + runs-on: ubuntu-22.04 + + steps: + # Set up Thunder cache + - name: Set up Thunder cache + id: cache + uses: actions/cache@v3 + with: + path: | + !build/Thunder + build/ThunderInterfaces + build/ThunderTools + install + !install/etc/WPEFramework/plugins + !install/usr/bin/rdkproxy_l1_test + !install/usr/include/gmock + !install/usr/include/gtest + !install/usr/lib/libgmockd.a + !install/usr/lib/libgmock_maind.a + !install/usr/lib/libgtestd.a + !install/usr/lib/libgtest_maind.a + !install/usr/lib/cmake/GTest + !install/usr/lib/pkgconfig/gmock.pc + !install/usr/lib/pkgconfig/gmock_main.pc + !install/usr/lib/pkgconfig/gtest.pc + !install/usr/lib/pkgconfig/gtest_main.pc + !install/usr/lib/wpeframework/plugins + key: thunder-${{ env.THUNDER_REF }}-rdk + - name: Install packages + run: | + sudo apt update + sudo apt-get install -y pkg-config libglib2.0-dev libnm-dev libcurl4-openssl-dev lcov ninja-build libgupnp-1.2-1 libgupnp-1.2-dev libgssdp-1.2-0 libsoup2.4-1 + + - name: Configure Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + - run: pip install jsonref + + - name: Configure CMake + uses: jwlawson/actions-setup-cmake@v1.13 + with: + cmake-version: '3.16.x' + - name: Checkout thunder repositories + if: steps.cache.outputs.cache-hit != 'true' + run: | + git clone https://github.com/rdkcentral/ThunderTools ThunderTools --branch ${{ env.THUNDER_REF }} + git clone https://github.com/rdkcentral/Thunder Thunder --branch ${{ env.THUNDER_REF }} + git clone https://github.com/rdkcentral/ThunderInterfaces ThunderInterfaces --branch ${{ env.THUNDER_REF }} + + - name: Checkout networkmanager + uses: actions/checkout@v3 + with: + path: networkmanager + + - name: Apply Thunder Patches + if: steps.cache.outputs.cache-hit != 'true' + run: | + cd ${{github.workspace}}/Thunder + git apply ${{github.workspace}}/networkmanager/tests/patches/thunder/SubscribeStub.patch + + - name: Build ThunderTools + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake + -S "${{github.workspace}}/ThunderTools" -B build/ThunderTools + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DGENERIC_CMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + && + cmake --build build/ThunderTools --target install -j8 + + - name: Build Thunder + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake + -S "${{github.workspace}}/Thunder" -B build/Thunder + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DBUILD_TYPE=Debug + -DBINDING=127.0.0.1 + -DPORT=9998 + && + cmake --build build/Thunder --target install -j8 + + - name: ThunderInterfaces + if: steps.cache.outputs.cache-hit != 'true' + run: > + cmake + -S "${{github.workspace}}/ThunderInterfaces" -B build/ThunderInterfaces + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + && + cmake --build build/ThunderInterfaces --target install -j8 + + - name: Generate IARM headers + run: | + touch install/usr/lib/libIARMBus.so + mkdir -p install/usr/include/rdk/iarmbus + touch install/usr/include/rdk/iarmbus/libIARM.h + cd "${{github.workspace}}/networkmanager/tests/" + mkdir -p headers/rdk/iarmbus + cd headers + touch rdk/iarmbus/libIARM.h rdk/iarmbus/libIBus.h + + - name: Build networkmanager with RDK Proxy + run: > + cmake + -S "${{github.workspace}}/networkmanager" + -B build/networkmanager_rdk + -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" + -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" + -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" + -DCMAKE_CXX_FLAGS=" + -I ${{github.workspace}}/networkmanager/tests/headers + -I ${{github.workspace}}/networkmanager/tests/headers/rdk/iarmbus + --include ${{github.workspace}}/networkmanager/tests/mocks/Iarm.h + --include ${{github.workspace}}/networkmanager/tests/mocks/secure_wrappermock.h + -Wall --coverage + " + -DENABLE_UNIT_TESTING=ON + -DENABLE_ROUTER_DISCOVERY_TOOL=ON + && + cmake --build build/networkmanager_rdk --target install -j8 + + - name: Run unit tests for Legacy_Network + run: > + PATH=${{github.workspace}}/install/usr/bin:${PATH} + LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} + legacynetwork_tests + + - name: Run unit tests for Legacy_WiFi + run: > + PATH=${{github.workspace}}/install/usr/bin:${PATH} + LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} + legacywifi_tests + + - name: Generate coverage + run: | + lcov -c -o coverage.info -d build/networkmanager_rdk + lcov -r coverage.info '/usr/include/*' '*/build/networkmanager_rdk/*' \ + '*/install/usr/include/*' '*/tests/*' 'googlemock/*' 'googletest/*' \ + -o filtered_coverage.info + - name: Generate the html report + run: | + genhtml filtered_coverage.info --output-directory /tmp/coverage_report + + - name: Upload the coverage report to Pull request using actions + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: | + /tmp/coverage_report + /tmp/gtest_log diff --git a/.github/workflows/libnm_proxy_L1_test.yml b/.github/workflows/libnm_proxy_L1_test.yml index ba22e3cc4..d92b5f586 100644 --- a/.github/workflows/libnm_proxy_L1_test.yml +++ b/.github/workflows/libnm_proxy_L1_test.yml @@ -71,7 +71,7 @@ jobs: if: steps.cache.outputs.cache-hit != 'true' run: | cd ${{github.workspace}}/Thunder - git apply ${{github.workspace}}/networkmanager/tests/patches/thunder/Remove-SmartLinkType.patch + git apply ${{github.workspace}}/networkmanager/tests/patches/thunder/SubscribeStub.patch - name: Build ThunderTools if: steps.cache.outputs.cache-hit != 'true' diff --git a/.github/workflows/rdk_proxy_L1_L2_test.yml b/.github/workflows/rdk_proxy_L1_L2_test.yml index 26d97e8c4..9124e4b66 100644 --- a/.github/workflows/rdk_proxy_L1_L2_test.yml +++ b/.github/workflows/rdk_proxy_L1_L2_test.yml @@ -71,7 +71,7 @@ jobs: if: steps.cache.outputs.cache-hit != 'true' run: | cd ${{github.workspace}}/Thunder - git apply ${{github.workspace}}/networkmanager/tests/patches/thunder/Remove-SmartLinkType.patch + git apply ${{github.workspace}}/networkmanager/tests/patches/thunder/SubscribeStub.patch - name: Build ThunderTools if: steps.cache.outputs.cache-hit != 'true' diff --git a/legacy/LegacyWiFiManagerAPIs.cpp b/legacy/LegacyWiFiManagerAPIs.cpp index 463707e35..dc032dc85 100644 --- a/legacy/LegacyWiFiManagerAPIs.cpp +++ b/legacy/LegacyWiFiManagerAPIs.cpp @@ -496,7 +496,7 @@ namespace WPEFramework uint32_t WiFiManager::getSupportedSecurityModes(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); - uint32_t rc = Core::ERROR_GENERAL; + uint32_t rc = Core::ERROR_NONE; JsonObject security_modes; security_modes["NET_WIFI_SECURITY_NONE"] = (int)NET_WIFI_SECURITY_NONE; security_modes["NET_WIFI_SECURITY_WEP_64"] = (int)NET_WIFI_SECURITY_WEP_64; diff --git a/tests/l2Test/CMakeLists.txt b/tests/l2Test/CMakeLists.txt index 9ded43a5b..84bf8b97a 100644 --- a/tests/l2Test/CMakeLists.txt +++ b/tests/l2Test/CMakeLists.txt @@ -19,6 +19,8 @@ message ("building l2 test") set(NM_RDK_PROXY_L2_TEST "rdkproxy_l2_test") +set(NM_LEGACY_WIFI_UT "legacywifi_tests") +set(NM_LEGACY_NETWORK_UT "legacynetwork_tests") find_package(CURL) find_package(PkgConfig REQUIRED) @@ -50,16 +52,42 @@ add_executable(${NM_RDK_PROXY_L2_TEST} ${PROXY_STUB_SOURCES} ) +add_executable(${NM_LEGACY_WIFI_UT} + ${CMAKE_SOURCE_DIR}/tests/l2Test/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/legacy/LegacyWiFiManagerAPIs.cpp +) + +add_executable(${NM_LEGACY_NETWORK_UT} + ${CMAKE_SOURCE_DIR}/tests/l2Test/l2_test_LegacyPlugin_NetworkAPIs.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/legacy/LegacyNetworkAPIs.cpp +) + set_target_properties(${NM_RDK_PROXY_L2_TEST} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES ) +set_target_properties(${NM_LEGACY_WIFI_UT} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) +set_target_properties(${NM_LEGACY_NETWORK_UT} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) + target_compile_options(${NM_RDK_PROXY_L2_TEST} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) +target_compile_options(${NM_LEGACY_WIFI_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) +target_compile_options(${NM_LEGACY_NETWORK_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) include_directories(${PROJECT_SOURCE_DIR}/interface) include_directories(${PROJECT_SOURCE_DIR}/plugin/rdk) include_directories(${PROJECT_SOURCE_DIR}/plugin) +include_directories(${PROJECT_SOURCE_DIR}/legacy) include_directories(${PROJECT_SOURCE_DIR}/tests/mocks) include_directories(${PROJECT_SOURCE_DIR}/tests/mocks/thunder) include_directories(${PROJECT_SOURCE_DIR}/../install/usr/include/rdk/iarmbus/) @@ -67,7 +95,19 @@ include_directories(${PROJECT_SOURCE_DIR}/tools/upnp/) target_include_directories(${NM_RDK_PROXY_L2_TEST} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} - ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include +) + +target_include_directories(${NM_LEGACY_WIFI_UT} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include +) + +target_include_directories(${NM_LEGACY_NETWORK_UT} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}/../googlemock/include ) @@ -81,5 +121,21 @@ target_link_libraries(${NM_RDK_PROXY_L2_TEST} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${CURL_LIBRARIES} ) +target_link_libraries(${NM_LEGACY_WIFI_UT} PRIVATE + gmock_main + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ${NAMESPACE}Core::${NAMESPACE}Core + ${CURL_LIBRARIES} +) +target_link_libraries(${NM_LEGACY_NETWORK_UT} PRIVATE + gmock_main + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ${NAMESPACE}Core::${NAMESPACE}Core + ${CURL_LIBRARIES} +) install(TARGETS ${NM_RDK_PROXY_L2_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS ${NM_LEGACY_WIFI_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS ${NM_LEGACY_NETWORK_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/l2Test/l2_test_LegacyPlugin_NetworkAPIs.cpp b/tests/l2Test/l2_test_LegacyPlugin_NetworkAPIs.cpp new file mode 100644 index 000000000..162315833 --- /dev/null +++ b/tests/l2Test/l2_test_LegacyPlugin_NetworkAPIs.cpp @@ -0,0 +1,941 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include +#include +#include +#include +#include "ServiceMock.h" +#include "FactoriesImplementation.h" +#include "NetworkManagerLogger.h" +#include "LegacyNetworkAPIs.h" +#include "ThunderPortability.h" +#include "INetworkManager.h" +#include "INetworkManagerMock.h" +#include "LegacyNetworkMock.h" +#include "IStringIteratorMock.h" +#include "mockauthservices.h" +#include "InterfaceIteratorMock.h" + +using namespace std; +using namespace WPEFramework; +using namespace WPEFramework::Plugin; +using IStringIterator = RPC::IIteratorType; +using ::testing::NiceMock; + +class NetworkTest : public ::testing::Test{ +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Handler& handlerV2; + DECL_CORE_JSONRPC_CONX connection; + Core::JSONRPC::Message message; + string response; + ServiceMock *m_service; + bool m_subsIfaceStateChange; + bool m_subsActIfaceChange; + bool m_subsIPAddrChange; + bool m_subsInternetChange; + + NetworkTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , handlerV2(*(plugin->GetHandler(2))) + , INIT_CONX(1, 0) + , m_subsIfaceStateChange(true) + , m_subsActIfaceChange(true) + , m_subsIPAddrChange(true) + , m_subsInternetChange(true) + { + ServiceMock* service = new ServiceMock(); + WPEFramework::PluginHost::IAuthenticate* mock_security_agent = new MockIAuthenticate(); + ServiceMock* mockShell = new ServiceMock(); + + EXPECT_CALL(*service, AddRef()).Times(1); + EXPECT_CALL(*service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("SecurityAgent"))); + return static_cast(mock_security_agent); + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + m_subsIfaceStateChange = true; + m_subsActIfaceChange = true; + m_subsIPAddrChange = true; + m_subsInternetChange = true; + return static_cast(mockShell); + })); + m_service = service; + EXPECT_CALL(*mockShell, State()) + .WillOnce(::testing::Return(PluginHost::IShell::state::UNAVAILABLE)) + .WillOnce(::testing::Return(PluginHost::IShell::state::UNAVAILABLE)) + .WillRepeatedly(::testing::Return(PluginHost::IShell::state::ACTIVATED)); + EXPECT_EQ(string{}, plugin->Initialize(service)); + delete mockShell; + delete mock_security_agent; + } + virtual ~NetworkTest() override + { + plugin->Deinitialize(m_service); + m_service->Release(); + delete m_service; + } +}; + +TEST_F(NetworkTest, getInterfaces) +{ + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + NiceMock mockIterator; + Exchange::INetworkManager::InterfaceDetails entry1; + entry1.type = Exchange::INetworkManager::InterfaceType::INTERFACE_TYPE_ETHERNET; + entry1.mac = "00:11:22:33:44:55"; + entry1.enabled = true; + entry1.connected = false; + + Exchange::INetworkManager::InterfaceDetails entry2; + entry2.type = Exchange::INetworkManager::InterfaceType::INTERFACE_TYPE_WIFI; + entry2.mac = "66:77:88:99:AA:BB"; + entry2.enabled = false; + entry2.connected = true; + + // Set up Next() to return two entries, then false + EXPECT_CALL(mockIterator, Next(testing::_)) + .WillOnce(testing::DoAll(testing::SetArgReferee<0>(entry1), testing::Return(true))) + .WillOnce(testing::DoAll(testing::SetArgReferee<0>(entry2), testing::Return(true))) + .WillOnce(testing::Return(false)); + EXPECT_CALL(mockIterator, Release()).Times(1); + NiceMock service; + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + EXPECT_CALL(*mockNetworkManager, GetAvailableInterfaces(::testing::_)) + .WillOnce(testing::DoAll( + ::testing::Invoke([&mockIterator](WPEFramework::Exchange::INetworkManager::IInterfaceDetailsIterator*& iterator) -> uint32_t { + iterator = &mockIterator; + return 0; + }))); + EXPECT_CALL(*mockNetworkManager, Release()).Times(1); + JsonObject parameters, JsonResponse; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInterfaces"), _T("{}"), response)); + std::string expectedResponse = "{\"interfaces\":[{\"interface\":\"ETHERNET\",\"macAddress\":\"00:11:22:33:44:55\",\"enabled\":true,\"connected\":false},{\"interface\":\"WIFI\",\"macAddress\":\"66:77:88:99:AA:BB\",\"enabled\":false,\"connected\":true}],\"success\":true}"; + EXPECT_EQ(response, expectedResponse); + delete mockNetworkManager; +} + +TEST_F(NetworkTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getStbIp"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getInterfaces"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setStunEndPoint"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isInterfaceEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setInterfaceEnabled"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getDefaultInterface"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getIPSettings"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isConnectedToInternet"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPublicIP"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSTBIPFamily"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setConnectivityTestEndpoints"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getCaptivePortalURI"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startConnectivityMonitoring"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopConnectivityMonitoring"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setDefaultInterface"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setIPSettings"))); + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getIPSettings"))); +} + +TEST_F(NetworkTest, setStunEndpoint) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + string endpoint = "stun.example.com"; + uint32_t port = 3478; + uint32_t bindTimeout = 10; + uint32_t cacheTimeout = 30; + + JsonObject parameters; + parameters["server"] = endpoint; + parameters["port"] = port; + parameters["timeout"] = bindTimeout; + parameters["cache_timeout"] = cacheTimeout; + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + EXPECT_CALL(*mockNetworkManager, SetStunEndpoint(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([&](string const endpoint, const uint32_t port, const uint32_t timeout, const uint32_t cacheLifetime ) -> uint32_t { + return 0; + })); + EXPECT_CALL(*mockNetworkManager, Release()).Times(1); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setStunEndPoint"), _T("{}"), response)); + EXPECT_EQ(response, "{\"success\":true}"); + delete mockNetworkManager; +} + +TEST_F(NetworkTest, setInterfaceEnabled){ + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + string interface = "ETHERNET"; + bool enabled = true; + + JsonObject jsonParameters; + jsonParameters["interface"] = interface; + jsonParameters["enabled"] = enabled; + string parameters; + jsonParameters.ToString(parameters); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + EXPECT_CALL(*mockNetworkManager, SetInterfaceState(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(Core::ERROR_NONE)); + + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setInterfaceEnabled"), _T(parameters), response)); + EXPECT_EQ(response, "{\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, getDefaultInterface) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + string interface = "eth0"; + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + EXPECT_CALL(*mockNetworkManager, GetPrimaryInterface(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](string& interface) -> uint32_t { + interface = "eth0"; + return Core::ERROR_NONE; + })); + + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getDefaultInterface"), _T("{}"), response)); + EXPECT_EQ(response, "{\"interface\":\"ETHERNET\",\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, setDefaultInterface) { + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setDefaultInterface"), _T("{}"), response)); + EXPECT_EQ(response, "{\"success\":true}"); +} + +TEST_F(NetworkTest, setIPSettings) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + JsonObject jsonParameters; + jsonParameters["interface"] = "WIFI"; + jsonParameters["ipversion"] = "IPv4"; + jsonParameters["autoconfig"] = false; + jsonParameters["ipaddr"] = "192.168.1.100"; + jsonParameters["gateway"] = "192.168.1.1"; + jsonParameters["primarydns"] = "8.8.8.8"; + jsonParameters["secondarydns"] = "8.8.4.4"; + jsonParameters["netmask"] = "255.255.255.0"; + + string parameters; + jsonParameters.ToString(parameters); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + EXPECT_CALL(*mockNetworkManager, SetIPSettings(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Return(Core::ERROR_NONE)); + + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setIPSettings"), _T(parameters), response)); + EXPECT_EQ(response, "{\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, getIPSettings) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + JsonObject jsonParameters; + jsonParameters["interface"] = "WIFI"; + jsonParameters["ipversion"] = "IPv4"; + string parameters; + string response; + jsonParameters.ToString(parameters); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + WPEFramework::Exchange::INetworkManager::IPAddress address{}; + EXPECT_CALL(*mockNetworkManager, GetIPSettings(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](string& , const string&, WPEFramework::Exchange::INetworkManager::IPAddress& address) -> uint32_t { + address.primarydns = "75.75.75.76"; + address.secondarydns = "75.75.76.76"; + address.dhcpserver = "192.168.0.1"; + address.gateway = "192.168.0.1"; + address.ipaddress = "192.168.0.11"; + address.ipversion = "IPv4"; + address.prefix = 24; + return Core::ERROR_NONE; + })); + + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getIPSettings"), _T(parameters), response)); + EXPECT_EQ(response, "{\"primarydns\":\"75.75.75.76\",\"gateway\":\"192.168.0.1\",\"secondarydns\":\"75.75.76.76\",\"dhcpserver\":\"192.168.0.1\",\"netmask\":\"255.255.255.0\",\"ipaddr\":\"192.168.0.11\",\"autoconfig\":false,\"ipversion\":\"IPv4\",\"interface\":\"WIFI\",\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, getIPSettingsIPv6) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + JsonObject jsonParameters; + jsonParameters["interface"] = "WIFI"; + jsonParameters["ipversion"] = "IPv6"; + string parameters; + string response; + jsonParameters.ToString(parameters); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + WPEFramework::Exchange::INetworkManager::IPAddress address{}; + EXPECT_CALL(*mockNetworkManager, GetIPSettings(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](string& , const string&, WPEFramework::Exchange::INetworkManager::IPAddress& address) -> uint32_t { + address.ipaddress = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; + address.ipversion = "IPv6"; + address.prefix = 64; + address.primarydns = "2001:4860:4860::8888"; + address.gateway = "fe80::1"; + address.secondarydns = "2001:4860:4860::8844"; + address.dhcpserver = "fe80::2"; + return Core::ERROR_NONE; + })); + + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getIPSettings"), _T(parameters), response)); + EXPECT_EQ(response, "{\"primarydns\":\"2001:4860:4860::8888\",\"gateway\":\"fe80::1\",\"secondarydns\":\"2001:4860:4860::8844\",\"dhcpserver\":\"fe80::2\",\"netmask\":64,\"ipaddr\":\"2001:0db8:85a3:0000:0000:8a2e:0370:7334\",\"autoconfig\":false,\"ipversion\":\"IPv6\",\"interface\":\"WIFI\",\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, getIPSettingsErrorEmptyString) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + JsonObject jsonParameters; + jsonParameters["interface"] = "WIFI"; + jsonParameters["ipversion"] = "IPv4"; + string parameters; + string response; + jsonParameters.ToString(parameters); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + WPEFramework::Exchange::INetworkManager::IPAddress address{}; + EXPECT_CALL(*mockNetworkManager, GetIPSettings(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](string& , const string&, WPEFramework::Exchange::INetworkManager::IPAddress& address) -> uint32_t { + address.ipaddress = ""; + address.ipversion = "IPv4"; + address.prefix = 34; + return Core::ERROR_NONE; + })); + + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getIPSettings"), _T(parameters), response)); + EXPECT_EQ(response, "{\"success\":false}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, getIPSettings2) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + JsonObject jsonParameters; + jsonParameters["interface"] = "WIFI"; + jsonParameters["ipversion"] = "IPv4"; + string parameters; + string response; + jsonParameters.ToString(parameters); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + WPEFramework::Exchange::INetworkManager::IPAddress address{}; + EXPECT_CALL(*mockNetworkManager, GetIPSettings(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](string& , const string&, WPEFramework::Exchange::INetworkManager::IPAddress& address) -> uint32_t { + address.primarydns = "75.75.75.76"; + address.secondarydns = "75.75.76.76"; + address.dhcpserver = "192.168.0.1"; + address.gateway = "192.168.0.1"; + address.ipaddress = "192.168.0.11"; + address.ipversion = "IPv4"; + address.prefix = 24; + return Core::ERROR_NONE; + })); + + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getIPSettings"), _T(parameters), response)); + string expectedResponse = "{\"interface\":\"WIFI\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddr\":\"192.168.0.11\",\"netmask\":\"255.255.255.0\",\"dhcpserver\":\"192.168.0.1\",\"gateway\":\"192.168.0.1\",\"primarydns\":\"75.75.75.76\",\"secondarydns\":\"75.75.76.76\",\"success\":true}"; + EXPECT_EQ(response, expectedResponse); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, isConnectedToInternet) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + JsonObject jsonParameters; + jsonParameters["ipversion"] = "IPv4"; + string parameters; + string response; + jsonParameters.ToString(parameters); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + EXPECT_CALL(*mockNetworkManager, IsConnectedToInternet(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](string& , string&, WPEFramework::Exchange::INetworkManager::InternetStatus& result) -> uint32_t + { + result = WPEFramework::Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED; + return Core::ERROR_NONE; + })); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isConnectedToInternet"), _T(parameters), response)); + EXPECT_EQ(response, "{\"ipversion\":\"IPv4\",\"connectedToInternet\":true,\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, getInternetConnectionState) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + JsonObject jsonParameters; + jsonParameters["ipversion"] = "IPv4"; + string parameters; + string response; + jsonParameters.ToString(parameters); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + EXPECT_CALL(*mockNetworkManager, IsConnectedToInternet(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const string&, const string&, Exchange::INetworkManager::InternetStatus& status) { + status = Exchange::INetworkManager::InternetStatus::INTERNET_CAPTIVE_PORTAL; + return Core::ERROR_NONE; + })); + + EXPECT_CALL(*mockNetworkManager, GetCaptivePortalURI(::testing::_)) + .Times(1) + .WillOnce(::testing::DoAll( + ::testing::SaveArg<0>(&response), + ::testing::Return(Core::ERROR_NONE))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getInternetConnectionState"), _T(parameters), response)); + EXPECT_EQ(response, "{\"ipversion\":\"IPv4\",\"state\":2,\"URI\":\"\",\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, doPing) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + std::string traceResult = "{" + "\"success\": true," + "\"tripStdDev\": \"0.741 ms\"," + "\"tripAvg\": \"16.702\"," + "\"tripMin\": \"15.747\"," + "\"tripMax\": \"17.564\"," + "\"packetLoss\": \"0\"," + "\"endpoint\": \"8.8.8.8\"," + "\"packetsReceived\": 5," + "\"packetsTransmitted\": 5," + "\"target\": \"8.8.8.8\"" + "}"; + EXPECT_CALL(*mockNetworkManager, Ping(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const string, const string, const uint32_t, const uint16_t, const string, string& result) -> uint32_t + { + result = traceResult; + return Core::ERROR_NONE; + })); + + JsonObject parametersJson; + parametersJson["endpoint"] = "8.8.8.8"; + parametersJson["packets"] = 5; + parametersJson["ipversion"] = "IPv4"; + parametersJson["guid"] = "..."; + string parameters; + parametersJson.ToString(parameters); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ping"), _T(parameters), response)); + string expectedResponse = "{\"packetsTransmitted\":5,\"packetsReceived\":5,\"packetLoss\":\"0\",\"target\":\"8.8.8.8\",\"tripMax\":\"17.564\",\"tripMin\":\"15.747\",\"tripAvg\":\"16.702\",\"tripStdDev\":\"0.741 ms\",\"endpoint\":\"8.8.8.8\",\"success\":true}"; + EXPECT_EQ(response, expectedResponse); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, doTrace) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + std::string traceResult = "{" + "\"results\": \"[\\\"traceroute to 8.8.8.8 (8.8.8.8), 6 hops max, 52 byte packets \\\",\\\"" + "1 gateway (10.46.5.1) 0.448 ms\\\",\\\"" + "2 10.46.0.240 (10.46.0.240) 3.117 ms\\\",\\\"" + "3 *\\\",\\\"" + "4 *\\\",\\\"" + "5 *\\\",\\\"" + "6 *\\\"]\"," + "\"endpoint\": \"8.8.8.8\"," + "\"success\": true" + "}"; + EXPECT_CALL(*mockNetworkManager, Trace(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const string, const string, const uint32_t, const string, string& response1) -> uint32_t + { + response1 = traceResult; + return Core::ERROR_NONE; + })); + + JsonObject parametersJson; + parametersJson["endpoint"] = "8.8.8.8"; + parametersJson["ipversion"] = "IPv4"; + parametersJson["packets"] = 1; + string parametersStr; + parametersJson.ToString(parametersStr); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("trace"), _T(parametersStr), response)); + // We expect the response to contain success and results fields + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"results\":") != std::string::npos); + EXPECT_TRUE(response.find("\"endpoint\":\"8.8.8.8\"") != std::string::npos); + EXPECT_TRUE(response.find("\"target\":\"8.8.8.8\"") != std::string::npos); + EXPECT_TRUE(response.find("6 hops max, 52 byte packets") != std::string::npos); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, getPublicIP) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + EXPECT_CALL(*mockNetworkManager, GetPublicIP(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](string&, string&, string& ipaddress) { + ipaddress = "69.136.49.95"; + return Core::ERROR_NONE; + })); + + + JsonObject parametersJson; + parametersJson["ipv6"] = true; + parametersJson["iface"] = "WIFI"; + string parametersStr; + parametersJson.ToString(parametersStr); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPublicIP"), _T(parametersStr), response)); + EXPECT_EQ(response, "{\"public_ip\":\"69.136.49.95\",\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, isInterfaceEnabled) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + EXPECT_CALL(*mockNetworkManager, GetInterfaceState(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::DoAll( + ::testing::Return(Core::ERROR_NONE))); + + JsonObject parametersJson; + parametersJson["interface"] = "WIFI"; + string parametersStr; + parametersJson.ToString(parametersStr); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isInterfaceEnabled"), _T(parametersStr), response)); + EXPECT_EQ(response, "{\"enabled\":false,\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, isInterfaceEnabledErrorInvalidInterface) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + + JsonObject parametersJson; + parametersJson["interface"] = "INVALID"; + string parametersStr; + parametersJson.ToString(parametersStr); + + EXPECT_EQ(Core::ERROR_BAD_REQUEST, handler.Invoke(connection, _T("isInterfaceEnabled"), _T(parametersStr), response)); + EXPECT_EQ(response, string{}); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, setConnectivityTestEndpoints) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + EXPECT_CALL(*mockNetworkManager, SetConnectivityTestEndpoints(::testing::_)) + .Times(1) + .WillOnce(::testing::Return(Core::ERROR_NONE)); + + JsonArray array; + array.Add("http://example.com"); + array.Add("http://example2.com"); + array.Add("http://example3.com"); + + JsonObject parametersJson; + parametersJson["endpoints"] = array; + string parametersStr; + parametersJson.ToString(parametersStr); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setConnectivityTestEndpoints"), _T(parametersStr), response)); + EXPECT_EQ(response, "{\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, setConnectivityTestEndpointsErrorInvalidType) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + + JsonArray array; + array.Add("http://example.com"); + array.Add(1234); + array.Add("http://example3.com"); + + JsonObject parametersJson; + parametersJson["endpoints"] = array; + string parametersStr; + parametersJson.ToString(parametersStr); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setConnectivityTestEndpoints"), _T(parametersStr), response)); + EXPECT_EQ(response, "{\"success\":false}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, setConnectivityTestEndpointsErrorEmptyArray) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + + JsonArray array; + + JsonObject parametersJson; + string parametersStr; + parametersJson.ToString(parametersStr); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setConnectivityTestEndpoints"), _T(parametersStr), response)); + EXPECT_EQ(response, "{\"success\":false}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, startConnectivityMonitoring) { + string parameters; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startConnectivityMonitoring"), _T(parameters), response)); + EXPECT_EQ(response, "{\"success\":true}"); +} + +TEST_F(NetworkTest, getCaptivePortalURI) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + string parameters; + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + EXPECT_CALL(*mockNetworkManager, GetCaptivePortalURI(::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](string& uri) { + uri = "http://10.0.0.1/captiveportal.jst"; + return Core::ERROR_NONE; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCaptivePortalURI"), _T(parameters), response)); + EXPECT_EQ(response, "{\"uri\":\"http:\\/\\/10.0.0.1\\/captiveportal.jst\",\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, stopConnectivityMonitoring) { + string parameters; + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopConnectivityMonitoring"), _T(parameters), response)); + EXPECT_EQ(response, "{\"success\":true}"); +} + +TEST_F(NetworkTest, getStbIp) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + JsonObject jsonParameters; + jsonParameters["interface"] = "WIFI"; + jsonParameters["ipversion"] = "IPv4"; + string parameters; + string response; + jsonParameters.ToString(parameters); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + EXPECT_CALL(*mockNetworkManager, GetIPSettings(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](string& , const string&, WPEFramework::Exchange::INetworkManager::IPAddress& address) -> uint32_t { + address.ipaddress = "192.168.0.1"; + address.ipversion = "IPv4"; + address.prefix = 24; + return Core::ERROR_NONE; + })); + + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStbIp"), _T(parameters), response)); + EXPECT_EQ(response, "{\"ip\":\"192.168.0.1\",\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, getSTBIPFamily) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + JsonObject jsonParameters; + jsonParameters["interface"] = "WIFI"; + jsonParameters["ipversion"] = "IPv4"; + string parameters; + string response; + jsonParameters.ToString(parameters); + + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + EXPECT_CALL(*mockNetworkManager, GetIPSettings(::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](string& , const string&, WPEFramework::Exchange::INetworkManager::IPAddress& address) -> uint32_t { + address.ipaddress = "192.168.0.1"; + address.ipversion = "IPv4"; + address.prefix = 24; + return Core::ERROR_NONE; + })); + + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSTBIPFamily"), _T({}), response)); + EXPECT_EQ(response, "{\"ip\":\"192.168.0.1\",\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(NetworkTest, ReportonInterfaceStateChangeAdded) { + StubNetwork network; + JsonObject parameters; + parameters["status"] = "INTERFACE_ADDED"; + parameters["interface"] = "ETHERNET"; + network.onInterfaceStateChange(parameters); +} + +TEST_F(NetworkTest, ReportonInterfaceStateChangeRemoved) { + StubNetwork network; + JsonObject parameters; + parameters["status"] = "INTERFACE_REMOVED"; + parameters["interface"] = "eth0"; + network.onInterfaceStateChange(parameters); +} + +TEST_F(NetworkTest, ReportonInterfaceStateChangeLinkUp) { + StubNetwork network; + JsonObject parameters; + parameters["status"] = "INTERFACE_LINK_UP"; + parameters["interface"] = "wlan0"; + network.onInterfaceStateChange(parameters); +} + +TEST_F(NetworkTest, ReportonInterfaceStateChangeLinkDown) { + StubNetwork network; + JsonObject parameters; + parameters["status"] = "INTERFACE_LINK_DOWN"; + parameters["interface"] = "eth0"; + network.onInterfaceStateChange(parameters); +} + +TEST_F(NetworkTest, ReportonActiveInterfaceChange) { + StubNetwork network; + JsonObject parameters; + parameters["prevActiveInterface"] = "eth0"; + parameters["currentActiveInterface"] = "wlan0"; + network.onActiveInterfaceChange(parameters); +} + +TEST_F(NetworkTest, ReportonIPAddressChange_IPv4) { + StubNetwork network; + JsonObject parameters; + parameters["interface"] = "eth0"; + parameters["ipversion"] = "IPv4"; + parameters["ipaddress"] = "192.168.1.100"; + network.onIPAddressChange(parameters); +} + +TEST_F(NetworkTest, ReportonIPAddressChange_IPv6) { + StubNetwork network; + JsonObject parameters; + parameters["interface"] = "wlan0"; + parameters["ipversion"] = "IPv6"; + parameters["ipaddress"] = "fe80::1"; + + network.onIPAddressChange(parameters); +} + +TEST_F(NetworkTest, ReportonInternetStatusChange) { + StubNetwork network; + JsonObject parameters; + parameters["state"] = "CONNECTED"; + parameters["status"] = "OK"; + network.onInternetStatusChange(parameters); +} + +TEST_F(NetworkTest, Information) { + StubNetwork network; + network.Information(); +} diff --git a/tests/l2Test/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp b/tests/l2Test/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp new file mode 100644 index 000000000..aa2c8a563 --- /dev/null +++ b/tests/l2Test/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp @@ -0,0 +1,898 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include +#include +#include +#include "ServiceMock.h" +#include "FactoriesImplementation.h" +#include "NetworkManagerLogger.h" +#include "LegacyWiFiManagerAPIs.h" +#include "ThunderPortability.h" +#include "INetworkManagerMock.h" +#include "LegacyWiFiManagerMock.h" +#include "IStringIteratorMock.h" +#include "mockauthservices.h" + +using namespace std; +using namespace WPEFramework; +using namespace WPEFramework::Plugin; +using ::testing::NiceMock; + +#define WPA_SUPPLICANT_CONF "/opt/secure/wifi/wpa_supplicant.conf/wpa_supplicant.conf" + +Plugin::WiFiManager* _gWiFiInstance = nullptr; +class WiFiManagerTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + Core::JSONRPC::Handler& handlerV2; + DECL_CORE_JSONRPC_CONX connection; + ServiceMock *m_service; + Core::JSONRPC::Message message; + string response; + + WiFiManagerTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , handlerV2(*(plugin->GetHandler(2))) + , INIT_CONX(1, 0) + { + ServiceMock* service = new ServiceMock(); + WPEFramework::PluginHost::IAuthenticate* mock_security_agent = new MockIAuthenticate(); + ServiceMock* mockShell = new ServiceMock(); + + EXPECT_CALL(*service, AddRef()).Times(1); + EXPECT_CALL(*service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(2) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("SecurityAgent"))); + return static_cast(mock_security_agent); + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockShell); + })); + m_service = service; + EXPECT_CALL(*mockShell, State()) + .WillOnce(::testing::Return(PluginHost::IShell::state::UNAVAILABLE)) + .WillOnce(::testing::Return(PluginHost::IShell::state::UNAVAILABLE)) + .WillRepeatedly(::testing::Return(PluginHost::IShell::state::ACTIVATED)); + EXPECT_EQ(string{}, plugin->Initialize(service)); + delete mockShell; + delete mock_security_agent; + } + + virtual ~WiFiManagerTest() override + { + plugin->Deinitialize(m_service); + m_service->Release(); + delete m_service; + } +}; + +TEST_F(WiFiManagerTest, TestedAPIsShouldExist) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startScan"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopScan"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("connect"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("disconnect"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("initiateWPSPairing"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("cancelWPSPairing"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("saveSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("clearSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPairedSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPairedSSIDInfo"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isPaired"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getCurrentState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getConnectedSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("retrieveSSID"))); +} + +TEST_F(WiFiManagerTest, cancelWPSPairing) +{ + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + EXPECT_CALL(*mockNetworkManager, StopWPS()) + .WillOnce(::testing::Return(Core::ERROR_NONE)); + + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("cancelWPSPairing"), _T("{}"), response)); + EXPECT_EQ(response, "{\"result\":\"\",\"success\":true}"); + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, clearSSID) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + EXPECT_CALL(*mockNetworkManager, RemoveKnownSSID(::testing::_)) + .WillOnce(::testing::Return(Core::ERROR_NONE)); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("clearSSID"), _T("{}"), response)); + EXPECT_EQ(response, "{\"result\":0,\"success\":true}"); + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, connect) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + EXPECT_CALL(*mockNetworkManager, WiFiConnect(::testing::_)) + .WillOnce(::testing::Return(Core::ERROR_NONE)); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Create a sample parameters object + JsonObject jsonParameters; + jsonParameters["ssid"] = "my-ssid"; + jsonParameters["passphrase"] = "my-passphrase"; + jsonParameters["securityMode"] = 1; // Assuming 1 is the value for WPA2 + + string parameters; + jsonParameters.ToString(parameters); + // Call the connect method + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("connect"), parameters, response)); + EXPECT_EQ(response, "{\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, getConnectedSSID) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; + ssidInfo.ssid = "my-ssid"; + ssidInfo.bssid = "00:11:22:33:44:55"; + ssidInfo.rate = "100"; + ssidInfo.noise = "-50"; + ssidInfo.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + ssidInfo.strength = "50"; + ssidInfo.frequency = "2.4"; + EXPECT_CALL(*mockNetworkManager, GetConnectedSSID(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>(ssidInfo), + ::testing::Return(Core::ERROR_NONE))); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Call the getConnectedSSID method + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getConnectedSSID"), _T("{}"), response)); + + std::string expectedResponse = "{\"ssid\":\"my-ssid\",\"bssid\":\"00:11:22:33:44:55\",\"rate\":\"100\",\"noise\":\"-50\",\"security\":6,\"signalStrength\":\"50\",\"frequency\":\"2.4\",\"success\":true}"; + EXPECT_EQ(response, expectedResponse); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, getConnectedSSIDSAE) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; + ssidInfo.ssid = "my-ssid"; + ssidInfo.bssid = "00:11:22:33:44:55"; + ssidInfo.rate = "100"; + ssidInfo.noise = "-50"; + ssidInfo.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE; + ssidInfo.strength = "50"; + ssidInfo.frequency = "2.4"; + EXPECT_CALL(*mockNetworkManager, GetConnectedSSID(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>(ssidInfo), + ::testing::Return(Core::ERROR_NONE))); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Call the getConnectedSSID method + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getConnectedSSID"), _T("{}"), response)); + + std::string expectedResponse = "{\"ssid\":\"my-ssid\",\"bssid\":\"00:11:22:33:44:55\",\"rate\":\"100\",\"noise\":\"-50\",\"security\":14,\"signalStrength\":\"50\",\"frequency\":\"2.4\",\"success\":true}"; + EXPECT_EQ(response, expectedResponse); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, getConnectedSSIDEAP) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; + ssidInfo.ssid = "my-ssid"; + ssidInfo.bssid = "00:11:22:33:44:55"; + ssidInfo.rate = "100"; + ssidInfo.noise = "-50"; + ssidInfo.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP; + ssidInfo.strength = "50"; + ssidInfo.frequency = "2.4"; + EXPECT_CALL(*mockNetworkManager, GetConnectedSSID(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>(ssidInfo), + ::testing::Return(Core::ERROR_NONE))); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Call the getConnectedSSID method + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getConnectedSSID"), _T("{}"), response)); + + std::string expectedResponse = "{\"ssid\":\"my-ssid\",\"bssid\":\"00:11:22:33:44:55\",\"rate\":\"100\",\"noise\":\"-50\",\"security\":12,\"signalStrength\":\"50\",\"frequency\":\"2.4\",\"success\":true}"; + EXPECT_EQ(response, expectedResponse); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, getCurrentState) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + Exchange::INetworkManager::WiFiState state = Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTED; + EXPECT_CALL(*mockNetworkManager, GetWifiState(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>(state), + ::testing::Return(Core::ERROR_NONE))); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Call the getCurrentState method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCurrentState"), _T("{}"), response)); + + std::string expectedResponse = "{\"state\":5,\"success\":true}"; + // Verify the response + EXPECT_EQ(response, expectedResponse); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, getCurrentStateFailed1) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + Exchange::INetworkManager::WiFiState state = Exchange::INetworkManager::WiFiState::WIFI_STATE_ERROR; + EXPECT_CALL(*mockNetworkManager, GetWifiState(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>(state), + ::testing::Return(Core::ERROR_NONE))); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Call the getCurrentState method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCurrentState"), _T("{}"), response)); + + std::string expectedResponse = "{\"state\":6,\"success\":true}"; + // Verify the response + EXPECT_EQ(response, expectedResponse); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, getCurrentStateFailed2) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + Exchange::INetworkManager::WiFiState state = Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTION_INTERRUPTED; + EXPECT_CALL(*mockNetworkManager, GetWifiState(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>(state), + ::testing::Return(Core::ERROR_NONE))); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Call the getCurrentState method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCurrentState"), _T("{}"), response)); + + std::string expectedResponse = "{\"state\":2,\"success\":true}"; + // Verify the response + EXPECT_EQ(response, expectedResponse); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, getCurrentStateDisconnected) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + Exchange::INetworkManager::WiFiState state = Exchange::INetworkManager::WiFiState::WIFI_STATE_DISCONNECTED; + EXPECT_CALL(*mockNetworkManager, GetWifiState(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>(state), + ::testing::Return(Core::ERROR_NONE))); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Call the getCurrentState method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCurrentState"), _T("{}"), response)); + + std::string expectedResponse = "{\"state\":2,\"success\":true}"; + // Verify the response + EXPECT_EQ(response, expectedResponse); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, getCurrentStateConnected) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + Exchange::INetworkManager::WiFiState state = Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTED; + EXPECT_CALL(*mockNetworkManager, GetWifiState(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>(state), + ::testing::Return(Core::ERROR_NONE))); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Call the getCurrentState method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getCurrentState"), _T("{}"), response)); + + std::string expectedResponse = "{\"state\":5,\"success\":true}"; + // Verify the response + EXPECT_EQ(response, expectedResponse); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, getPairedSSIDInfo) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; + ssidInfo.ssid = "my-ssid"; + ssidInfo.bssid = "00:11:22:33:44:55"; + EXPECT_CALL(*mockNetworkManager, GetConnectedSSID(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>(ssidInfo), + ::testing::Return(Core::ERROR_NONE))); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Call the getPairedSSIDInfo method + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPairedSSIDInfo"), _T("{}"), response)); + + // Verify the response + EXPECT_EQ(response, "{\"ssid\":\"my-ssid\",\"bssid\":\"00:11:22:33:44:55\",\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, getSupportedSecurityModes) { + // Call the getSupportedSecurityModes method + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSupportedSecurityModes"), _T("{}"), response)); + + // Verify the response + std::string expectedResponse = "{\"security_modes\":{\"NET_WIFI_SECURITY_NONE\":0,\"NET_WIFI_SECURITY_WEP_64\":1,\"NET_WIFI_SECURITY_WEP_128\":2,\"NET_WIFI_SECURITY_WPA_PSK_TKIP\":3,\"NET_WIFI_SECURITY_WPA_PSK_AES\":4,\"NET_WIFI_SECURITY_WPA2_PSK_TKIP\":5,\"NET_WIFI_SECURITY_WPA2_PSK_AES\":6,\"NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP\":7,\"NET_WIFI_SECURITY_WPA_ENTERPRISE_AES\":8,\"NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP\":9,\"NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES\":10,\"NET_WIFI_SECURITY_WPA_WPA2_PSK\":11,\"NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE\":12,\"NET_WIFI_SECURITY_WPA3_PSK_AES\":13,\"NET_WIFI_SECURITY_WPA3_SAE\":14,\"NET_WIFI_SECURITY_NOT_SUPPORTED\":99},\"success\":true}"; + EXPECT_EQ(response, expectedResponse); + +} + +TEST_F(WiFiManagerTest, saveSSID) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + Exchange::INetworkManager::WiFiConnectTo ssid{}; + ssid.ssid = "my-ssid"; + ssid.passphrase = "my-passphrase"; + ssid.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + EXPECT_CALL(*mockNetworkManager, AddToKnownSSIDs(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Return(Core::ERROR_NONE))); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Create a sample parameters object + JsonObject jsonParameters; + jsonParameters["ssid"] = "my-ssid"; + jsonParameters["passphrase"] = "my-passphrase"; + jsonParameters["security"] = 1; // Assuming 1 is the value for WPA2 + + string parameters; + jsonParameters.ToString(parameters); + // Call the saveSSID method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("saveSSID"), parameters, response)); + + // Verify the response + EXPECT_EQ(response, "{\"result\":0,\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, disconnect) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + EXPECT_CALL(*mockNetworkManager, WiFiDisconnect()) + .WillOnce(::testing::Return(Core::ERROR_NONE)); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Call the disconnect method + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("disconnect"), _T("{}"), response)); + + // Verify the response + EXPECT_EQ(response, "{\"result\":0,\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, initiateWPSPairing) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + EXPECT_CALL(*mockNetworkManager, StartWPS(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(Core::ERROR_NONE)); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Create a sample parameters object + JsonObject jsonParameters; + jsonParameters["method"] = static_cast(Exchange::INetworkManager::WiFiWPS::WIFI_WPS_PIN); + jsonParameters["pin"] = "my-pin"; + + string parameters; + jsonParameters.ToString(parameters); + // Call the initiateWPSPairing method + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("initiateWPSPairing"), parameters, response)); + + // Verify the response + EXPECT_EQ(response, "{\"result\":0,\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, startScan) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + EXPECT_CALL(*mockNetworkManager, StartWiFiScan(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(Core::ERROR_NONE)); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Create a sample parameters object + JsonObject jsonParameters; + jsonParameters["frequency"] = "2.4GHz"; + jsonParameters["ssid"] = "test"; + + // Call the startScan method + std::string parameters; + jsonParameters.ToString(parameters); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startScan"), parameters, response)); + + // Verify the response + EXPECT_EQ(response, "{\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, stopScan) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + EXPECT_CALL(*mockNetworkManager, StopWiFiScan()) + .WillOnce(::testing::Return(Core::ERROR_NONE)); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Call the stopScan method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopScan"), _T("{}"), response)); + + // Verify the response + EXPECT_EQ(response, "{\"success\":true}"); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, stopScan_Error) { + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + EXPECT_CALL(*mockNetworkManager, StopWiFiScan()) + .WillOnce(::testing::Return(Core::ERROR_GENERAL)); + EXPECT_CALL(*mockNetworkManager, Release()) + .Times(1); + + // Call the stopScan method + std::string response; + EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopScan"), _T("{}"), response)); + + // Verify the response + EXPECT_EQ(response, string{}); + + delete mockNetworkManager; +} + +TEST_F(WiFiManagerTest, onWiFiStateChange1) { + StubWiFi wifi; + JsonObject parameters; + parameters["state"] = static_cast(Exchange::INetworkManager::WIFI_STATE_SSID_CHANGED); + wifi.onWiFiStateChange(parameters); +} + +TEST_F(WiFiManagerTest, onWiFiStateChange2) { + StubWiFi wifi; + JsonObject parameters; + parameters["state"] = static_cast(Exchange::INetworkManager::WIFI_STATE_CONNECTION_LOST); + wifi.onWiFiStateChange(parameters); +} + +TEST_F(WiFiManagerTest, onWiFiStateChange3) { + StubWiFi wifi; + JsonObject parameters; + parameters["state"] = static_cast(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED); + wifi.onWiFiStateChange(parameters); +} + +TEST_F(WiFiManagerTest, onWiFiStateChange4) { + StubWiFi wifi; + JsonObject parameters; + parameters["state"] = static_cast(Exchange::INetworkManager::WIFI_STATE_CONNECTION_INTERRUPTED); + wifi.onWiFiStateChange(parameters); +} + +TEST_F(WiFiManagerTest, onWiFiStateChange5) { + StubWiFi wifi; + JsonObject parameters; + parameters["state"] = static_cast(Exchange::INetworkManager::WIFI_STATE_INVALID_CREDENTIALS); + wifi.onWiFiStateChange(parameters); +} + +TEST_F(WiFiManagerTest, onWiFiStateChange6) { + StubWiFi wifi; + JsonObject parameters; + parameters["state"] = static_cast(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + wifi.onWiFiStateChange(parameters); +} + +TEST_F(WiFiManagerTest, onWiFiStateChange7) { + StubWiFi wifi; + JsonObject parameters; + parameters["state"] = static_cast(Exchange::INetworkManager::WIFI_STATE_ERROR); + wifi.onWiFiStateChange(parameters); +} + +TEST_F(WiFiManagerTest, onWiFiStateChange8) { + StubWiFi wifi; + JsonObject parameters; + parameters["state"] = static_cast(Exchange::INetworkManager::WIFI_STATE_AUTHENTICATION_FAILED); + wifi.onWiFiStateChange(parameters); +} + +TEST_F(WiFiManagerTest, onAvailableSSIDs) { + StubWiFi wifi; + JsonObject parameters; + JsonArray ssids; + JsonObject ssid1; + ssid1["ssid"] = "test"; + ssid1["security"] = 2; + ssid1["signalStrength"] = "-27.000"; + ssid1["frequency"] = "2.4"; + ssids.Add(ssid1); + parameters["ssids"] = ssids; + + wifi.onAvailableSSIDs(parameters); +} + +TEST_F(WiFiManagerTest, onWiFiSignalQualityChange) { + StubWiFi wifi; + JsonObject parameters; + parameters["signalStrength"] = "27.00"; + parameters["strength"] = "Excellent"; + + wifi.onWiFiSignalQualityChange(parameters); +} + +TEST_F(WiFiManagerTest, Information) { + StubWiFi wifi; + wifi.Information(); +} + +TEST_F(WiFiManagerTest, getPairedSSID) { + // Create a mock network manager object + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + + // Set up the mock network manager to return a mock string iterator + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + // Set up the mock string iterator to return a string + MockStringIterator* mockStringIterator = new MockStringIterator(); + EXPECT_CALL(*mockNetworkManager, GetKnownSSIDs(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>(mockStringIterator), + ::testing::Return(Core::ERROR_NONE))); + EXPECT_CALL(*mockStringIterator, Next(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>("my-ssid"), + ::testing::Return(true))); + + // Call the getPairedSSID method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getPairedSSID"), _T("{}"), response)); + + // Verify the response + EXPECT_EQ(response, "{\"ssid\":\"my-ssid\",\"success\":true}"); + + // Clean up + delete mockNetworkManager; + delete mockStringIterator; +} + +TEST_F(WiFiManagerTest, isPaired) { + // Create a mock network manager object + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + + // Set up the mock network manager to return a mock string iterator + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + // Set up the mock string iterator to return a string + MockStringIterator* mockStringIterator = new MockStringIterator(); + EXPECT_CALL(*mockNetworkManager, GetKnownSSIDs(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>(mockStringIterator), + ::testing::Return(Core::ERROR_NONE))); + EXPECT_CALL(*mockStringIterator, Next(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::SetArgReferee<0>("my-ssid"), + ::testing::Return(true))); + + // Call the getPairedSSID method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isPaired"), _T("{}"), response)); + + // Verify the response + EXPECT_EQ(response, "{\"result\":1,\"success\":true}"); + + // Clean up + delete mockNetworkManager; + delete mockStringIterator; +} + +TEST_F(WiFiManagerTest, isPairedNoSSID) { + // Create a mock network manager object + MockINetworkManager* mockNetworkManager = new MockINetworkManager(); + + // Set up the mock network manager to return a mock string iterator + EXPECT_CALL(*m_service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const string& name) -> void* { + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + return static_cast(mockNetworkManager); + })); + + // Set up the mock string iterator to return a string + EXPECT_CALL(*mockNetworkManager, GetKnownSSIDs(::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Return(Core::ERROR_NONE))); + + // Call the getPairedSSID method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("isPaired"), _T("{}"), response)); + + // Verify the response + EXPECT_EQ(response, "{\"result\":0,\"success\":true}"); + + // Clean up + delete mockNetworkManager; +} + +// Create a sample configuration file +std::string configFileContent = "ssid=\"my-ssid\"\n" +"key_mgmt=PSK\n" +"psk=\"my-passphrase\"\n"; + +void wpaSupplicantConfCreate(std::string configFileContent) +{ + std::string filePath = "/opt/secure/wifi/wpa_supplicant.conf"; + // Create the parent directories if they don't exist + size_t pos = filePath.find_last_of('/'); + if (pos != std::string::npos) { + std::string dirPath = filePath.substr(0, pos); + std::string cmd = "mkdir -p " + dirPath; + FILE* pipe = popen(cmd.c_str(), "w"); + if (!pipe) { + // Handle error + } + pclose(pipe); + } + std::ofstream configFileOut(filePath, std::ios_base::out | std::ios_base::app); + // Check if the file is open + if (configFileOut.is_open()) { + // File is open, write to it + configFileOut << configFileContent; + configFileOut.close(); + + // Print the content of the file + std::ifstream configFileRead(filePath); + if (configFileRead.is_open()) { + std::cout << configFileRead.rdbuf(); + configFileRead.close(); + } else { + std::cerr << "Unable to open file for reading." << std::endl; + } + } else { + std::cerr << "Unable to open file for writing." << std::endl; + } +} + +TEST_F(WiFiManagerTest, retrieveSSIDWPAPSK) { + std::string configFileContent = "ssid=\"my-ssid\"\n" + "key_mgmt=PSK\n" + "psk=\"my-passphrase\"\n"; + + wpaSupplicantConfCreate(configFileContent); + // Call the retrieveSSID method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("retrieveSSID"), _T("{}"), response)); + + // Verify the response + EXPECT_EQ(response, "{\"ssid\":\"my-ssid\",\"securityMode\":6,\"passphrase\":\"my-passphrase\",\"success\":true}"); + + // Remove the configuration file + std::remove("/opt/secure/wifi/wpa_supplicant.conf"); +} + +TEST_F(WiFiManagerTest, retrieveSSIDSecurityNone) { + std::string configFileContent = "ssid=\"my-ssid\"\n" + "key_mgmt=NONE\n" + "psk=\"my-passphrase\"\n"; + + wpaSupplicantConfCreate(configFileContent); + // Call the retrieveSSID method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("retrieveSSID"), _T("{}"), response)); + + // Verify the response + EXPECT_EQ(response, "{\"ssid\":\"my-ssid\",\"securityMode\":0,\"passphrase\":\"my-passphrase\",\"success\":true}"); + + // Remove the configuration file + std::remove("/opt/secure/wifi/wpa_supplicant.conf"); +} + +TEST_F(WiFiManagerTest, retrieveSSIDSecuritySAE) { + std::string configFileContent = "ssid=\"my-ssid\"\n" + "key_mgmt=SAE\n" + "psk=\"my-passphrase\"\n"; + + wpaSupplicantConfCreate(configFileContent); + // Call the retrieveSSID method + std::string response; + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("retrieveSSID"), _T("{}"), response)); + + // Verify the response + EXPECT_EQ(response, "{\"ssid\":\"my-ssid\",\"securityMode\":14,\"passphrase\":\"my-passphrase\",\"success\":true}"); + + // Remove the configuration file + std::remove("/opt/secure/wifi/wpa_supplicant.conf"); +} diff --git a/tests/mocks/INetworkManagerMock.h b/tests/mocks/INetworkManagerMock.h new file mode 100644 index 000000000..7aad39b35 --- /dev/null +++ b/tests/mocks/INetworkManagerMock.h @@ -0,0 +1,60 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "Module.h" + +class MockINetworkManager : public WPEFramework::Exchange::INetworkManager { +public: + MOCK_METHOD(uint32_t, GetAvailableInterfaces, (WPEFramework::Exchange::INetworkManager::IInterfaceDetailsIterator*& interfaces), (override)); + MOCK_METHOD(uint32_t, GetPrimaryInterface, (string& interface), (override)); MOCK_METHOD(uint32_t, SetInterfaceState, (const string& interface, const bool enabled), (override)); + MOCK_METHOD(uint32_t, GetInterfaceState, (const string& interface, bool& enabled), (override)); + MOCK_METHOD(uint32_t, GetIPSettings, (string& interface, const string& ipversion, IPAddress& address), (override)); + MOCK_METHOD(uint32_t, SetIPSettings, (const string& interface, const IPAddress& address), (override)); + MOCK_METHOD(uint32_t, GetStunEndpoint, (string& endpoint, uint32_t& port, uint32_t& timeout, uint32_t& cacheLifetime), (const)); + MOCK_METHOD(uint32_t, SetStunEndpoint, (string const endpoint, const uint32_t port, const uint32_t timeout, const uint32_t cacheLifetime), (override)); + MOCK_METHOD(uint32_t, GetConnectivityTestEndpoints, (IStringIterator*& endpoints), (const)); + MOCK_METHOD(uint32_t, SetConnectivityTestEndpoints, (IStringIterator* const endpoints), (override)); + MOCK_METHOD(uint32_t, IsConnectedToInternet, (string& ipversion, string& interface, WPEFramework::Exchange::INetworkManager::InternetStatus& status), (override)); + MOCK_METHOD(uint32_t, GetCaptivePortalURI, (string& uri), (const)); + MOCK_METHOD(uint32_t, GetPublicIP, (string& interface, string& ipversion, string& ipaddress), (override)); + MOCK_METHOD(uint32_t, Ping, (const string ipversion, const string endpoint, const uint32_t count, const uint16_t timeout, const string guid, string& response), (override)); + MOCK_METHOD(uint32_t, Trace, (const string ipversion, const string endpoint, const uint32_t nqueries, const string guid, string& response), (override)); + MOCK_METHOD(uint32_t, StartWiFiScan, (const string& frequency, IStringIterator* const ssids), (override)); + MOCK_METHOD(uint32_t, StopWiFiScan, (), (override)); + MOCK_METHOD(uint32_t, GetKnownSSIDs, (IStringIterator*& ssids), (override)); + MOCK_METHOD(uint32_t, AddToKnownSSIDs, (const WiFiConnectTo& ssid), (override)); + MOCK_METHOD(uint32_t, RemoveKnownSSID, (const string& ssid), (override)); + MOCK_METHOD(uint32_t, WiFiConnect, (const WiFiConnectTo& ssid), (override)); + MOCK_METHOD(uint32_t, WiFiDisconnect, (), (override)); + MOCK_METHOD(uint32_t, GetConnectedSSID, (WiFiSSIDInfo& ssidInfo), (override)); + MOCK_METHOD(uint32_t, StartWPS, (const WiFiWPS& method, const string& pin), (override)); + MOCK_METHOD(uint32_t, StopWPS, (), (override)); + MOCK_METHOD(uint32_t, GetWifiState, (WPEFramework::Exchange::INetworkManager::WiFiState& state), (override)); + MOCK_METHOD(uint32_t, GetWiFiSignalQuality, (string& ssid, string& strength, string& noise, string& snr, WPEFramework::Exchange::INetworkManager::WiFiSignalQuality& quality), (override)); + MOCK_METHOD(uint32_t, GetSupportedSecurityModes, (ISecurityModeIterator*& modes), (const)); + MOCK_METHOD(uint32_t, SetLogLevel, (const Logging& level), (override)); + MOCK_METHOD(uint32_t, GetLogLevel, (Logging& level), (override)); + MOCK_METHOD(uint32_t, Configure, (WPEFramework::PluginHost::IShell* service), (override)); + MOCK_METHOD(uint32_t, Register, (WPEFramework::Exchange::INetworkManager::INotification* notification), (override)); + MOCK_METHOD(uint32_t, Unregister, (WPEFramework::Exchange::INetworkManager::INotification* notification), (override)); + MOCK_METHOD(uint32_t, AddRef, (), (const, override)); + MOCK_METHOD(uint32_t, Release, (), (const, override)); + MOCK_METHOD(void*, QueryInterface, (uint32_t), (override)); +}; diff --git a/tests/mocks/LegacyNetworkMock.h b/tests/mocks/LegacyNetworkMock.h new file mode 100644 index 000000000..084690c8b --- /dev/null +++ b/tests/mocks/LegacyNetworkMock.h @@ -0,0 +1,65 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCKNETWORK_H +#define MOCKNETWORK_H + +#include +#include "Module.h" + +class StubNetwork : public WPEFramework::Plugin::Network { +public: + void onInterfaceStateChange(const JsonObject& parameters) { + WPEFramework::Plugin::Network::ReportonInterfaceStateChange(parameters); // Call the method on this object + } + + void onActiveInterfaceChange(const JsonObject& parameters) { + EXPECT_EQ(parameters["prevActiveInterface"].String(), "eth0"); + EXPECT_EQ(parameters["currentActiveInterface"].String(), "wlan0"); + WPEFramework::Plugin::Network::ReportonActiveInterfaceChange(parameters); + } + + void onIPAddressChange(const JsonObject& parameters) { + WPEFramework::Plugin::Network::ReportonIPAddressChange(parameters); + } + + void onInternetStatusChange(const JsonObject& parameters) { + EXPECT_EQ(parameters["state"].String(), "CONNECTED"); + EXPECT_EQ(parameters["status"].String(), "OK"); + WPEFramework::Plugin::Network::ReportonInternetStatusChange(parameters); + } + + string Information() const + { + WPEFramework::Plugin::Network::Information(); + return(string()); + } + + MOCK_METHOD(uint32_t, AddRef, (), (const, override)); + MOCK_METHOD(uint32_t, Release, (), (const, override)); + MOCK_METHOD(void*, QueryInterface, (uint32_t), (override)); + MOCK_METHOD(const std::string, Initialize, (WPEFramework::PluginHost::IShell*), (override)); + MOCK_METHOD(void, Deinitialize, (WPEFramework::PluginHost::IShell*), (override)); + MOCK_METHOD(void, ReportonInterfaceStateChange, (const JsonObject&), ()); + MOCK_METHOD(void, ReportonActiveInterfaceChange, (const JsonObject&), ()); + MOCK_METHOD(void, ReportonIPAddressChange, (const JsonObject&), ()); + MOCK_METHOD(void, ReportonInternetStatusChange, (const JsonObject&), ()); + MOCK_METHOD(void, subscribeToEvents, (), ()); +}; +#endif diff --git a/tests/mocks/LegacyWiFiManagerMock.h b/tests/mocks/LegacyWiFiManagerMock.h new file mode 100644 index 000000000..5a44022a5 --- /dev/null +++ b/tests/mocks/LegacyWiFiManagerMock.h @@ -0,0 +1,54 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCKWIFIMANAGER_H +#define MOCKWIFIMANAGER_H + +#include +#include "Module.h" + +class StubWiFi : public WPEFramework::Plugin::WiFiManager { +public: + void onWiFiStateChange(const JsonObject& parameters) { + WPEFramework::Plugin::WiFiManager::onWiFiStateChange(parameters); // Call the method on this object + } + + void onAvailableSSIDs(const JsonObject& parameters) { + WPEFramework::Plugin::WiFiManager::onAvailableSSIDs(parameters); // Call the method on this object + } + + void onWiFiSignalQualityChange(const JsonObject& parameters) { + WPEFramework::Plugin::WiFiManager::onWiFiSignalQualityChange(parameters); // Call the method on this object + } + + string Information() const + { + WPEFramework::Plugin::WiFiManager::Information(); + return(string()); + } + + MOCK_METHOD(uint32_t, AddRef, (), (const, override)); + MOCK_METHOD(uint32_t, Release, (), (const, override)); + MOCK_METHOD(void*, QueryInterface, (uint32_t), (override)); + MOCK_METHOD(const std::string, Initialize, (WPEFramework::PluginHost::IShell*), (override)); + MOCK_METHOD(void, Deinitialize, (WPEFramework::PluginHost::IShell*), (override)); + MOCK_METHOD(void, subscribeToEvents, (), ()); + MOCK_METHOD(uint32_t, cancelWPSPairing, (const JsonObject& parameters, JsonObject& response), ()); +}; +#endif diff --git a/tests/mocks/thunder/CommunicatorMock.h b/tests/mocks/thunder/CommunicatorMock.h index 60bfdcefa..b689de20e 100755 --- a/tests/mocks/thunder/CommunicatorMock.h +++ b/tests/mocks/thunder/CommunicatorMock.h @@ -39,7 +39,7 @@ class CommunicatorClientMock : public ICommunicatorClient class CommunicatorClientMock : public ICommunicatorClient { public: virtual ~CommunicatorClientMock() = default; - MOCK_METHOD(void, AddRef, (), (const)); + MOCK_METHOD(uint32_t, AddRef, (), (const)); MOCK_METHOD(uint32_t, Release, (), (const)); MOCK_METHOD(uint32_t, Open, (const uint32_t waitTime), (override)); MOCK_METHOD(void*, Open, (const std::string& className, const uint32_t version, const uint32_t waitTime), (override)); diff --git a/tests/mocks/thunder/DispatcherMock.h b/tests/mocks/thunder/DispatcherMock.h index 7a643f79c..6ae2b7f52 100644 --- a/tests/mocks/thunder/DispatcherMock.h +++ b/tests/mocks/thunder/DispatcherMock.h @@ -27,7 +27,7 @@ class DispatcherMock: public WPEFramework::PluginHost::ILocalDispatcher{ public: virtual ~DispatcherMock() = default; - MOCK_METHOD(void, AddRef, (), (const, override)); + MOCK_METHOD(uint32_t, AddRef, (), (const, override)); MOCK_METHOD(uint32_t, Release, (), (const, override)); MOCK_METHOD(void*, QueryInterface, (const uint32_t interfaceNummer), (override)); MOCK_METHOD(void, Activate, (WPEFramework::PluginHost::IShell* service)); diff --git a/tests/mocks/thunder/IStringIteratorMock.h b/tests/mocks/thunder/IStringIteratorMock.h new file mode 100644 index 000000000..0477dbf27 --- /dev/null +++ b/tests/mocks/thunder/IStringIteratorMock.h @@ -0,0 +1,39 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCKSTRINGITERATOR_H +#define MOCKSTRINGITERATOR_H + +#include +#include "Module.h" + +template +class MockStringIterator : public WPEFramework::RPC::IStringIterator{ +public: + MOCK_METHOD(bool, Next, (ELEMENT&), (override)); + MOCK_METHOD(bool, Previous, (ELEMENT&), (override)); + MOCK_METHOD(void, Reset, (uint32_t), (override)); + MOCK_METHOD(bool, IsValid, (), (const)); + MOCK_METHOD(uint32_t, Count, (), (const)); + MOCK_METHOD(ELEMENT, Current, (), (const)); + MOCK_METHOD(uint32_t, AddRef, (), (const)); + MOCK_METHOD(uint32_t, Release, (), (const)); + MOCK_METHOD(void*, QueryInterface, (uint32_t), (override)); +}; +#endif diff --git a/tests/mocks/thunder/InterfaceIteratorMock.h b/tests/mocks/thunder/InterfaceIteratorMock.h new file mode 100644 index 000000000..42aff4e61 --- /dev/null +++ b/tests/mocks/thunder/InterfaceIteratorMock.h @@ -0,0 +1,38 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCKINTERFACEITERATOR_H +#define MOCKINTERFACEITERATOR_H + +#include +#include "Module.h" + +class MockIInterfaceDetailsIterator : public WPEFramework::Exchange::INetworkManager::IInterfaceDetailsIterator { +public: + MOCK_METHOD(bool, Next, (WPEFramework::Exchange::INetworkManager::InterfaceDetails&), (override)); + MOCK_METHOD(bool, Previous, (WPEFramework::Exchange::INetworkManager::InterfaceDetails&), (override)); + MOCK_METHOD(void, Reset, (const uint32_t position), (override)); + MOCK_METHOD(bool, IsValid, (), (const, override)); + MOCK_METHOD(uint32_t, Count, (), (const, override)); + MOCK_METHOD(WPEFramework::Exchange::INetworkManager::InterfaceDetails, Current, (), (const, override)); + MOCK_METHOD(uint32_t, AddRef, (), (const, override)); + MOCK_METHOD(uint32_t, Release, (), (const, override)); + MOCK_METHOD(void*, QueryInterface, (uint32_t), (override)); +}; +#endif diff --git a/tests/mocks/thunder/mockauthservices.h b/tests/mocks/thunder/mockauthservices.h index 9a696ff5d..35e522a94 100644 --- a/tests/mocks/thunder/mockauthservices.h +++ b/tests/mocks/thunder/mockauthservices.h @@ -24,64 +24,13 @@ #include "Module.h" -class MockAuthService : public WPEFramework::Exchange::IAuthService { -public: - virtual ~MockAuthService() = default; - MOCK_METHOD(uint32_t, GetActivationStatus, (ActivationStatusResult&), (override)); - MOCK_METHOD(uint32_t, SetActivationStatus, (const std::string&, SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, ClearAuthToken, (SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, ClearSessionToken, (SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, ClearServiceAccessToken, (SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, ClearLostAndFoundAccessToken, (SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, ClearServiceAccountId, (SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, ClearCustomProperties, (SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, GetCustomProperties, (std::string&, bool&), (override)); - MOCK_METHOD(uint32_t, SetCustomProperties, (const std::string&, bool&), (override)); - MOCK_METHOD(uint32_t, GetAlternateIds, (std::string&, std::string&, bool&), (override)); - MOCK_METHOD(uint32_t, SetAlternateIds, (const std::string&, std::string&, bool&), (override)); - MOCK_METHOD(uint32_t, GetTransitionData, (std::string&, std::string&, bool&), (override)); - MOCK_METHOD(void, AddRef, (), (const, override)); - MOCK_METHOD(uint32_t, Release, (), (const, override)); - MOCK_METHOD(void*, QueryInterface, (uint32_t), (override)); - MOCK_METHOD(uint32_t, Register, (IAuthService::INotification*), (override)); - MOCK_METHOD(uint32_t, Unregister, (IAuthService::INotification*), (override)); - MOCK_METHOD(uint32_t, Configure, (), (override)); - MOCK_METHOD(uint32_t, GetInfo, (GetInfoResult&), (override)); - MOCK_METHOD(uint32_t, GetDeviceInfo, (GetDeviceInfoResult&), (override)); - MOCK_METHOD(uint32_t, GetDeviceId, (GetDeviceIdResult&), (override)); - MOCK_METHOD(uint32_t, SetDeviceId, (const std::string&, SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, SetPartnerId, (const std::string&, SetPartnerIdResult&), (override)); - MOCK_METHOD(uint32_t, GetAuthToken, (const bool, const bool, GetAuthTokenResult&), (override)); - MOCK_METHOD(uint32_t, GetSessionToken, (GetSessionTokenResult&), (override)); - MOCK_METHOD(uint32_t, SetSessionToken, (const int32_t&, const std::string&, uint32_t, const std::string&, const std::string&, SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, GetServiceAccessToken, (GetServiceAccessTokenResult&), (override)); - MOCK_METHOD(uint32_t, SetServiceAccessToken, (const int32_t&, const std::string&, uint32_t, SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, GetServiceAccountId, (GetServiceAccountIdResult&), (override)); - MOCK_METHOD(uint32_t, SetServiceAccountId, (const std::string&, SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, SetAuthIdToken, (const std::string&, SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, Ready, (const std::string&, SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, GetBootstrapProperty, (const std::string&, GetBootstrapPropResult&), (override)); - MOCK_METHOD(uint32_t, ActivationStarted, (SuccessResult&), (override)); - MOCK_METHOD(uint32_t, ActivationComplete, (SuccessResult&), (override)); - MOCK_METHOD(uint32_t, GetLostAndFoundAccessToken, (std::string&, std::string&, bool&), (override)); - MOCK_METHOD(uint32_t, SetLostAndFoundAccessToken, (const std::string&, SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, GetXDeviceId, (GetXDeviceIdResult&), (override)); - MOCK_METHOD(uint32_t, SetXDeviceId, (const std::string&, SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, GetExperience, (GetExpResult&), (override)); - MOCK_METHOD(uint32_t, SetExperience, (const std::string&, SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, GetXifaId, (GetxifaIdResult&), (override)); - MOCK_METHOD(uint32_t, SetXifaId, (const std::string&, SuccessMsgResult&), (override)); - MOCK_METHOD(uint32_t, GetAdvtOptOut, (AdvtOptOutResult&), (override)); - MOCK_METHOD(uint32_t, SetAdvtOptOut, (const bool&, SuccessMsgResult&), (override)); -}; - class MockIAuthenticate : public WPEFramework::PluginHost::IAuthenticate { public: MOCK_METHOD(void*, QueryInterfaceByCallsign, (const uint32_t, const string&)); MOCK_METHOD(uint32_t, CreateToken, (uint16_t, const uint8_t*, std::string&)); MOCK_METHOD(uint32_t, Release, (), (const, override)); MOCK_METHOD(void*, QueryInterface, (uint32_t), (override)); - MOCK_METHOD(void, AddRef, (), (const, override)); + MOCK_METHOD(uint32_t, AddRef, (), (const, override)); MOCK_METHOD(WPEFramework::PluginHost::ISecurity*, Officer, (const std::string& token), (override)); }; #endif diff --git a/tests/patches/thunder/Remove-SmartLinkType.patch b/tests/patches/thunder/Remove-SmartLinkType.patch deleted file mode 100644 index ecf958589..000000000 --- a/tests/patches/thunder/Remove-SmartLinkType.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/Source/websocket/JSONRPCLink.h b/Source/websocket/JSONRPCLink.h -index 9652d7ec..aad19ab1 100644 ---- a/Source/websocket/JSONRPCLink.h -+++ b/Source/websocket/JSONRPCLink.h -@@ -1235,16 +1235,6 @@ namespace WPEFramework { - } - - public: -- template -- uint32_t Subscribe(const uint32_t waitTime, const string& eventName, const METHOD& method) -- { -- return Subscribe(waitTime, eventName, method); -- } -- template -- uint32_t Subscribe(const uint32_t waitTime, const string& eventName, const METHOD& method, REALOBJECT* objectPtr) -- { -- return Subscribe(waitTime, eventName, method, objectPtr); -- } - bool IsActivated() - { - return (_state == ACTIVATED); diff --git a/tests/patches/thunder/SubscribeStub.patch b/tests/patches/thunder/SubscribeStub.patch new file mode 100644 index 000000000..91d16a775 --- /dev/null +++ b/tests/patches/thunder/SubscribeStub.patch @@ -0,0 +1,21 @@ +diff --git a/Source/websocket/JSONRPCLink.h b/Source/websocket/JSONRPCLink.h +--- a/Source/websocket/JSONRPCLink.h 2025-07-21 11:11:43.178011151 -0400 ++++ b/Source/websocket/JSONRPCLink.h 2025-07-21 11:13:11.330611722 -0400 +@@ -1238,12 +1238,15 @@ namespace WPEFramework { + template + uint32_t Subscribe(const uint32_t waitTime, const string& eventName, const METHOD& method) + { +- return Subscribe(waitTime, eventName, method); ++ const string parameters("{ \"event\": \"" + eventName + "\"}"); ++ if (eventName.empty() == false) ++ method(parameters); ++ return 0; + } + template + uint32_t Subscribe(const uint32_t waitTime, const string& eventName, const METHOD& method, REALOBJECT* objectPtr) + { +- return Subscribe(waitTime, eventName, method, objectPtr); ++ return 0; + } + bool IsActivated() + { From 562ece896f27a6a93b309b1663e8316b82b401e4 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Wed, 30 Jul 2025 16:59:24 -0400 Subject: [PATCH 162/271] Release of 0.23.0 Release of 0.23.0 --- CHANGELOG.md | 6 ++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81279c2be..522fd606b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.23.0] - 2025-07-30 +### Added +- Added L1/L2 workflow for LegacyNetwork, LegacyWiFi and NetworkManager Plugins +- Fixed RemoveKnownSSID method to handle the invalid inputs +- Fixed the logging in GetIPSettings + ## [0.22.0] - 2025-07-14 ### Fixed - Fixed trigger point for the connectivity monitoring diff --git a/CMakeLists.txt b/CMakeLists.txt index efcea13f3..6c6558d17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 22) +set(VERSION_MINOR 23) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index de469b887..2dd3eddbb 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.22.0" + "version": "0.23.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index fd7a1b44c..8f30d4236 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.22.0** +**Version: 0.23.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.22.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.23.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 1246ed2332422b725d92176d34b6366fc61de810 Mon Sep 17 00:00:00 2001 From: jincysam87 <167995204+jincysam87@users.noreply.github.com> Date: Fri, 8 Aug 2025 16:32:48 -0400 Subject: [PATCH 163/271] RDK-58636: Pass private key password to wpa-supplicant (#202) * RDK-58636: Pass private key password to wpa-supplicant Reason for change: Pass the private key password to supplicant for EAP authentication Test Procedure: Test LNF EAP authentication Risks: None Signed-off-by: jincysaramma_sam@comcast.com --- plugin/rdk/NetworkManagerRDKProxy.cpp | 4 ++++ plugin/rdk/NetworkManagerRDKProxy.h | 1 + 2 files changed, 5 insertions(+) diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index dc03b3cc4..e85ae4f98 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -1043,6 +1043,10 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { ssid.client_cert.copy(param.data.connect.clientcert, sizeof(param.data.connect.clientcert) - 1); if(!ssid.private_key.empty()) ssid.private_key.copy(param.data.connect.privatekey, sizeof(param.data.connect.privatekey) - 1); + if(!ssid.private_key_passwd.empty()) + { + ssid.private_key_passwd.copy(param.data.connect.privatekeypasswd, sizeof(param.data.connect.privatekeypasswd) - 1); + } param.data.connect.persistSSIDInfo = ssid.persist; } diff --git a/plugin/rdk/NetworkManagerRDKProxy.h b/plugin/rdk/NetworkManagerRDKProxy.h index 96e9a3963..4a678d0b3 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.h +++ b/plugin/rdk/NetworkManagerRDKProxy.h @@ -245,6 +245,7 @@ typedef struct _WiFiConnection char carootcert[MAX_FILE_PATH_LEN]; char clientcert[MAX_FILE_PATH_LEN]; char privatekey[MAX_FILE_PATH_LEN]; + char privatekeypasswd[PASSPHRASE_BUFF]; bool persistSSIDInfo; } WiFiConnection; From 825ec18a898f2b386cd1ca373541992ee5607e14 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Mon, 11 Aug 2025 16:47:39 -0400 Subject: [PATCH 164/271] Release of 0.24.0 Release of 0.24.0 --- CHANGELOG.md | 4 ++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 522fd606b..2807f47d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.24.0] - 2025-08-11 +### Added +- Use incoming EAP-PrivateKey Password to connect to WiFi when given + ## [0.23.0] - 2025-07-30 ### Added - Added L1/L2 workflow for LegacyNetwork, LegacyWiFi and NetworkManager Plugins diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c6558d17..fa8b7af93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 23) +set(VERSION_MINOR 24) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 2dd3eddbb..fbde9789f 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.23.0" + "version": "0.24.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 8f30d4236..931378052 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.23.0** +**Version: 0.24.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.23.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.24.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 0fb49f88767e5f0068a3da07eb0593f98be2ab68 Mon Sep 17 00:00:00 2001 From: Muhammed Rafi c Date: Thu, 14 Aug 2025 11:27:19 +0530 Subject: [PATCH 165/271] RDKEMW-6225 Add SetHostName method in NetworkManager RDKEMW-6225 Add SetHostName method in NetworkManager Reason for change: implemented DHCP hostname configuration support Risks: Medium Priority: P1 Signed-off-by: cmuhammedrafi --- definition/NetworkManager.json | 28 +++- docs/NetworkManagerPlugin.md | 47 ++++++ interface/INetworkManager.h | 2 + plugin/NetworkManager.h | 1 + plugin/NetworkManagerImplementation.h | 3 + plugin/NetworkManagerJsonRpc.cpp | 25 +++ plugin/gnome/NetworkManagerGnomeProxy.cpp | 190 +++++++++++++++++++++- plugin/gnome/NetworkManagerGnomeUtils.cpp | 73 ++++++++- plugin/gnome/NetworkManagerGnomeUtils.h | 6 +- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 17 +- plugin/rdk/NetworkManagerRDKProxy.cpp | 7 + tests/mocks/INetworkManagerMock.h | 1 + 12 files changed, 392 insertions(+), 8 deletions(-) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index fbde9789f..b43c4c811 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -1299,9 +1299,35 @@ "success" ] } + }, + "SetHostname": { + "summary": "To configure a custom DHCP hostname instead of the default (which is typically the device name).", + "params": { + "type": "object", + "properties": { + "hostname": { + "summary": "The hostname to be set for the device (maximum 32 characters)", + "type": "string", + "example": "RDK-Device" + } + }, + "required": [ + "hostname" + ] + }, + "result": { + "type": "object", + "properties": { + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] + } } }, - "events": { "onInterfaceStateChange":{ "summary": "Triggered when an interface state is changed. The possible states are \n* 'INTERFACE_ADDED' \n* 'INTERFACE_LINK_UP' \n* 'INTERFACE_LINK_DOWN' \n* 'INTERFACE_ACQUIRING_IP' \n* 'INTERFACE_REMOVED' \n* 'INTERFACE_DISABLED' \n", diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 931378052..4dcf7807a 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -102,6 +102,7 @@ NetworkManager interface methods: | [GetWiFiSignalQuality](#method.GetWiFiSignalQuality) | Get WiFi signal quality of currently connected SSID | | [GetSupportedSecurityModes](#method.GetSupportedSecurityModes) | Returns the Wifi security modes that the device supports | | [GetWifiState](#method.GetWifiState) | Returns the current Wifi State | +| [SetHostname](#method.SetHostname) | To configure a custom DHCP hostname instead of the default (which is typically the device name). | ## *SetLogLevel [method](#head.Methods)* @@ -1667,6 +1668,52 @@ This method takes no parameters. } ``` + +## *SetHostname [method](#head.Methods)* + +To configure a custom DHCP hostname instead of the default (which is typically the device name), note that the change will only take effect after a device reboot, creating a new Wi-Fi connection, reactivation of existing NetworkManager connection, or renewal of the DHCP lease. + +### Parameters + +| Name | Type | Description | +| :-------- | :-------- | :-------- | +| params | object | | +| params.hostname | string | The hostname to be set for the device (maximum 32 characters) | + +### Result + +| Name | Type | Description | +| :-------- | :-------- | :-------- | +| result | object | | +| result.success | boolean | Whether the request succeeded | + +### Example + +#### Request + +```json +{ + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.SetHostname", + "params": { + "hostname": "RDK-Device" + } +} +``` + +#### Response + +```json +{ + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } +} +``` + # Notifications diff --git a/interface/INetworkManager.h b/interface/INetworkManager.h index 65c982a27..edf369ffd 100644 --- a/interface/INetworkManager.h +++ b/interface/INetworkManager.h @@ -233,6 +233,8 @@ namespace WPEFramework /* @brief Request for trace get the response in as event. The GUID used in the request will be returned in the event. */ virtual uint32_t Trace (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t nqueries /* @in */, const string guid /* @in */, string& response /* @out */) = 0; + /* @brief Set the dhcp hostname */ + virtual uint32_t SetHostname(const string& hostname /* @in */) = 0; // WiFi Specific Methods /* @brief Initiate a WIFI Scan; This is Async method and returns the scan results as Event */ diff --git a/plugin/NetworkManager.h b/plugin/NetworkManager.h index 98007e8c7..1abce8d08 100644 --- a/plugin/NetworkManager.h +++ b/plugin/NetworkManager.h @@ -250,6 +250,7 @@ namespace WPEFramework uint32_t GetPublicIP(const JsonObject& parameters, JsonObject& response); uint32_t Ping(const JsonObject& parameters, JsonObject& response); uint32_t Trace(const JsonObject& parameters, JsonObject& response); + uint32_t SetHostname (const JsonObject& parameters, JsonObject& response); uint32_t StartWiFiScan(const JsonObject& parameters, JsonObject& response); uint32_t StopWiFiScan(const JsonObject& parameters, JsonObject& response); uint32_t GetKnownSSIDs(const JsonObject& parameters, JsonObject& response); diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index d6077e8d4..aff37e446 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -245,6 +245,9 @@ namespace WPEFramework uint32_t GetSupportedSecurityModes(ISecurityModeIterator*& security /* @out */) const override; + /* @brief Set the dhcp hostname */ + uint32_t SetHostname(const string& hostname /* @in */) override; + /* @brief Set the network manager plugin log level */ uint32_t SetLogLevel(const Logging& level /* @in */) override; uint32_t GetLogLevel(Logging& level /* @out */) override; diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index 07a4fc301..5ac09c56e 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -69,6 +69,7 @@ namespace WPEFramework Register("GetPublicIP", &NetworkManager::GetPublicIP, this); Register("Ping", &NetworkManager::Ping, this); Register("Trace", &NetworkManager::Trace, this); + Register("SetHostname", &NetworkManager::SetHostname, this); Register("StartWiFiScan", &NetworkManager::StartWiFiScan, this); Register("StopWiFiScan", &NetworkManager::StopWiFiScan, this); Register("GetKnownSSIDs", &NetworkManager::GetKnownSSIDs, this); @@ -105,6 +106,7 @@ namespace WPEFramework Unregister("GetPublicIP"); Unregister("Ping"); Unregister("Trace"); + Unregister("SetHostname"); Unregister("StartWiFiScan"); Unregister("StopWiFiScan"); Unregister("GetKnownSSIDs"); @@ -608,6 +610,29 @@ namespace WPEFramework returnJson(rc); } + uint32_t NetworkManager::SetHostname (const JsonObject& parameters, JsonObject& response) + { + LOG_INPARAM(); + uint32_t rc = Core::ERROR_GENERAL; + string hostname{}; + + if (parameters.HasLabel("hostname") && !parameters["hostname"].String().empty()) + { + hostname = parameters["hostname"].String(); + if (_networkManager) + rc = _networkManager->SetHostname(hostname); + else + rc = Core::ERROR_UNAVAILABLE; + } + else + { + NMLOG_ERROR("Invalid hostname length: %zu", hostname.length()); + rc = Core::ERROR_BAD_REQUEST; + } + + returnJson(rc); + } + uint32_t NetworkManager::StartWiFiScan(const JsonObject& parameters, JsonObject& response) { LOG_INPARAM(); diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 0a48feb38..1431fdc2f 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -64,6 +64,191 @@ namespace WPEFramework return deviceState; } + static bool setHostname(NMConnection *connection, const std::string& hostname) + { + GError *error = NULL; + NMSettingIPConfig *sIPv4 = NULL; + NMSettingIPConfig *sIPv6 = NULL; + bool needChange = false; + + if(connection == NULL) { + NMLOG_ERROR("Connection is NULL"); + return false; + } + + sIPv4 = nm_connection_get_setting_ip4_config(connection); + if (sIPv4) { + const char* existingHostname = nm_setting_ip_config_get_dhcp_hostname(sIPv4); + gboolean sendHostname = nm_setting_ip_config_get_dhcp_send_hostname(sIPv4); + + if (!sendHostname || !existingHostname || hostname != existingHostname) { + needChange = true; + } + } + else + needChange = true; + + sIPv6 = nm_connection_get_setting_ip6_config(connection); + if (sIPv6) { + const char* existingHostname = nm_setting_ip_config_get_dhcp_hostname(sIPv6); + gboolean sendHostname = nm_setting_ip_config_get_dhcp_send_hostname(sIPv6); + + if (!sendHostname || !existingHostname || hostname != existingHostname) { + needChange = true; + } + } + else + needChange = true; + + if (!needChange) { + NMLOG_DEBUG("Hostname already set to '%s', no changes needed", hostname.c_str()); + return true; + } + + NMLOG_DEBUG("Setting hostname to '%s' for connection '%s'", hostname.c_str(), nm_connection_get_id(connection)); + + if (!sIPv4) { + sIPv4 = NM_SETTING_IP_CONFIG(nm_setting_ip4_config_new()); + nm_connection_add_setting(connection, NM_SETTING(sIPv4)); + } + g_object_set(sIPv4, + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), + NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, + NULL); + + if (!sIPv6) { + sIPv6 = NM_SETTING_IP_CONFIG(nm_setting_ip6_config_new()); + nm_connection_add_setting(connection, NM_SETTING(sIPv6)); + } + g_object_set(sIPv6, + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), + NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, + NULL); + + nm_remote_connection_commit_changes(NM_REMOTE_CONNECTION(connection), TRUE, NULL, &error); + if(error) { + NMLOG_ERROR("Failed to commit changes: %s", error->message); + g_error_free(error); + return false; + } + + return true; + } + + static bool modifyDefaultConnConfig(NMClient *client) + { + GError *error = NULL; + const GPtrArray *connections = NULL; + NMConnection *connection = NULL; + std::string hostname{}; + + if (client == nullptr) { + NMLOG_ERROR("NMClient is NULL"); + return false; + } + + // read persistent hostname if exist + if(!nmUtils::readPersistentHostname(hostname)) + { + hostname = nmUtils::deviceHostname(); // default hostname as device name + } + + connections = nm_client_get_connections(client); + if (connections == NULL || connections->len == 0) { + NMLOG_ERROR("Could not get nm connections"); + return false; + } + + for (uint32_t i = 0; i < connections->len; i++) + { + connection = NM_CONNECTION(connections->pdata[i]); + if(connection == NULL) + { + NMLOG_ERROR("Connection at index %d is NULL", i); + continue; + } + + const char *iface = nm_connection_get_interface_name(connection); + if(!iface) + { + NMLOG_WARNING("Failed to get connection interface name !"); + continue; + } + + std::string interface = iface; + if(interface != nmUtils::ethIface() && interface != nmUtils::wlanIface()) { + NMLOG_DEBUG("Skipping non-ethernet/wifi connection type: %s", interface.c_str()); + continue; + } + + if(!setHostname(connection, hostname)) { + NMLOG_WARNING("Failed to set hostname for connection at index %d", i); + } + } + + return true; + } + + /* @brief Set the dhcp hostname */ + uint32_t NetworkManagerImplementation::SetHostname(const string& hostname /* @in */) + { + const GPtrArray *connections = NULL; + NMConnection *connection = NULL; + + if (client == nullptr) { + NMLOG_ERROR("NMClient is NULL"); + return Core::ERROR_GENERAL; + } + + if(hostname.length() < 1 || hostname.length() > 32) + { + NMLOG_ERROR("Invalid hostname length: %zu", hostname.length()); + return Core::ERROR_BAD_REQUEST; + } + + connections = nm_client_get_connections(client); + if (connections == NULL || connections->len == 0) + { + NMLOG_ERROR("Could not get nm connections"); + return Core::ERROR_GENERAL; + } + + NMLOG_INFO("Setting DHCP hostname to %s", hostname.c_str()); + + for (uint32_t i = 0; i < connections->len; i++) + { + connection = NM_CONNECTION(connections->pdata[i]); + if(connection != NULL) + { + const char *iface = nm_connection_get_interface_name(connection); + if(!iface) + { + NMLOG_WARNING("Failed to get connection interface name !"); + continue; + } + + std::string interface = iface; + if(interface != nmUtils::ethIface() && interface != nmUtils::wlanIface()) { + NMLOG_DEBUG("Skipping non-ethernet/wifi connection type: %s", interface.c_str()); + continue; + } + + if(!setHostname(connection, hostname)) + { + NMLOG_ERROR("Failed to set hostname for connection at index %d", i); + return Core::ERROR_GENERAL; + } + } + else + NMLOG_ERROR("Connection at index %d is NULL", i); + } + + // Write the hostname to persistent storage + nmUtils::writePersistentHostname(hostname); + + return Core::ERROR_NONE; + } + void NetworkManagerImplementation::platform_logging(const NetworkManagerLogger::LogLevel& level) { /* set networkmanager daemon log level based on current plugin log level */ @@ -76,7 +261,7 @@ namespace WPEFramework { ::_instance = this; GError *error = NULL; - + // initialize the NMClient object client = nm_client_new(NULL, &error); if (client == NULL) { @@ -87,7 +272,8 @@ namespace WPEFramework return; } - nmUtils::getInterfacesName(); // get interface name form '/etc/device.proprties' + nmUtils::getDeviceProperties(); // get interface name form '/etc/device.proprties' + modifyDefaultConnConfig(client); NMDeviceState ethState = ifaceState(client, nmUtils::ethIface()); if(ethState > NM_DEVICE_STATE_DISCONNECTED && ethState < NM_DEVICE_STATE_DEACTIVATING) m_defaultInterface = nmUtils::ethIface(); diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index 51aca0a2a..3910b6c3a 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -37,9 +37,11 @@ namespace WPEFramework { static std::string m_ethifname = "eth0"; static std::string m_wlanifname = "wlan0"; + static std::string m_deviceHostname = "rdk-device"; // Device name can be empty if not set in /etc/device.properties const char* nmUtils::wlanIface() {return m_wlanifname.c_str();} const char* nmUtils::ethIface() {return m_ethifname.c_str();} + const char* nmUtils::deviceHostname() {return m_deviceHostname.c_str();} uint8_t nmUtils::wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags, bool doPrint) { @@ -205,11 +207,12 @@ namespace WPEFramework return upperStr1 == upperStr2; } - bool nmUtils::getInterfacesName() + bool nmUtils::getDeviceProperties() { std::string line; std::string wifiIfname; std::string ethIfname; // cached interface name + std::string deviceHostname; std::ifstream file("/etc/device.properties"); if (!file.is_open()) { @@ -243,12 +246,24 @@ namespace WPEFramework wifiIfname = "wlan0_missing"; // means device doesnot have wifi interface } } + + if (line.find("DEVICE_NAME=") != std::string::npos) { + deviceHostname = line.substr(line.find('=') + 1); + deviceHostname.erase(deviceHostname.find_last_not_of("\r\n\t") + 1); + deviceHostname.erase(0, deviceHostname.find_first_not_of("\r\n\t")); + if(deviceHostname.empty()) + { + NMLOG_WARNING("DEVICE_NAME is empty in /etc/device.properties"); + deviceHostname = ""; // set empty device name + } + } } file.close(); m_wlanifname = wifiIfname; m_ethifname = ethIfname; - NMLOG_INFO("/etc/device.properties eth: %s, wlan: %s", m_ethifname.c_str(), m_wlanifname.c_str()); + m_deviceHostname = deviceHostname; + NMLOG_INFO("/etc/device.properties eth: %s, wlan: %s, device name: %s", m_ethifname.c_str(), m_wlanifname.c_str(), m_deviceHostname.c_str()); return true; } @@ -303,6 +318,8 @@ namespace WPEFramework } } + + bool nmUtils::isInterfaceEnabled(const std::string& interface) { std::string markerFile; @@ -322,5 +339,57 @@ namespace WPEFramework return isAllowed; } + bool nmUtils::writePersistentHostname(const std::string& hostname) + { + if (hostname.empty()) { + NMLOG_ERROR("Cannot write empty hostname to persistent storage"); + return false; + } + + std::ofstream file(HostnameFile); + if (!file.is_open()) { + NMLOG_ERROR("Failed to open %s for writing", HostnameFile); + return false; + } + + file << hostname; + bool success = !file.fail(); + file.close(); + + if (success) + NMLOG_DEBUG("Successfully wrote hostname '%s' to %s",hostname.c_str(), HostnameFile); + else + NMLOG_ERROR("Error writing hostname to %s", HostnameFile); + + return success; + } + + bool nmUtils::readPersistentHostname(std::string& hostname) + { + std::ifstream file(HostnameFile); + if (!file.is_open()) { + NMLOG_DEBUG("Could not open %s - file may not exist yet", HostnameFile); + hostname = ""; + return false; + } + + std::string line; + if (std::getline(file, line)) { + // Remove any whitespace, newlines, etc. + line.erase(line.find_last_not_of("\r\n\t") + 1); + line.erase(0, line.find_first_not_of("\r\n\t")); + hostname = line; + file.close(); + + NMLOG_INFO("Read persistent hostname: '%s'", hostname.c_str()); + return true; + } + + NMLOG_WARNING("Persistent hostname file exists but is empty"); + hostname = ""; + file.close(); + return false; + } + } // Plugin } // WPEFramework diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index 35688d461..aab7daf0a 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -31,13 +31,15 @@ namespace WPEFramework { constexpr const char* EthernetDisableMarker = "/opt/persistent/ethernet.interface.disable"; constexpr const char* WiFiDisableMarker = "/opt/persistent/wifi.interface.disable"; + constexpr const char* HostnameFile = "/opt/persistent/nm.plugin.hostname"; class nmUtils { public: - static bool getInterfacesName(); + static bool getDeviceProperties(); static const char* wlanIface(); static const char* ethIface(); + static const char* deviceHostname(); static const char* convertPercentageToSignalStrengtStr(int percentage); static bool caseInsensitiveCompare(const std::string& str1, const std::string& str2); static uint8_t wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags, bool doPrint = true); @@ -46,6 +48,8 @@ namespace WPEFramework static bool setNetworkManagerlogLevelToTrace(); static void setMarkerFile(const char* filename, bool unmark = false); static bool isInterfaceEnabled(const std::string& interface); + static bool writePersistentHostname(const std::string& hostname); + static bool readPersistentHostname(std::string& hostname); }; } } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 49454ba87..7d5725565 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -630,14 +630,27 @@ namespace WPEFramework } } - /* Build up the 'ipv4' Setting */ + std::string hostname; + if(!nmUtils::readPersistentHostname(hostname)) + { + hostname = nmUtils::deviceHostname(); + NMLOG_DEBUG("no persistent hostname found taking device name as hostname !"); + } + + NMLOG_INFO("dhcp hostname: %s", hostname.c_str()); + + /* Build up the 'IPv4' Setting */ NMSettingIP4Config *sIpv4Conf = (NMSettingIP4Config *) nm_setting_ip4_config_new(); g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); // autoconf = true + g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); + g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); // hostname send enabled nm_connection_add_setting(m_connection, NM_SETTING(sIpv4Conf)); - /* Build up the 'ipv6' Setting */ + /* Build up the 'IPv6' Setting */ NMSettingIP6Config *sIpv6Conf = (NMSettingIP6Config *) nm_setting_ip6_config_new(); g_object_set(G_OBJECT(sIpv6Conf), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); // autoconf = true + g_object_set(G_OBJECT(sIpv6Conf), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); + g_object_set(G_OBJECT(sIpv6Conf), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); // hostname send enabled nm_connection_add_setting(m_connection, NM_SETTING(sIpv6Conf)); return true; } diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index e85ae4f98..543d014ed 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -433,6 +433,13 @@ namespace WPEFramework return; } + /* @brief Set the dhcp hostname */ + uint32_t NetworkManagerImplementation::SetHostname(const string& hostname /* @in */) + { + // TODO: Implement setting the DHCP hostname for netsrvmgr + return Core::ERROR_NONE; + } + void NetworkManagerImplementation::platform_init() { LOG_ENTRY_FUNCTION(); diff --git a/tests/mocks/INetworkManagerMock.h b/tests/mocks/INetworkManagerMock.h index 7aad39b35..eb3596277 100644 --- a/tests/mocks/INetworkManagerMock.h +++ b/tests/mocks/INetworkManagerMock.h @@ -50,6 +50,7 @@ class MockINetworkManager : public WPEFramework::Exchange::INetworkManager { MOCK_METHOD(uint32_t, GetWiFiSignalQuality, (string& ssid, string& strength, string& noise, string& snr, WPEFramework::Exchange::INetworkManager::WiFiSignalQuality& quality), (override)); MOCK_METHOD(uint32_t, GetSupportedSecurityModes, (ISecurityModeIterator*& modes), (const)); MOCK_METHOD(uint32_t, SetLogLevel, (const Logging& level), (override)); + MOCK_METHOD(uint32_t, SetHostname, (const string& hostname), (override)); MOCK_METHOD(uint32_t, GetLogLevel, (Logging& level), (override)); MOCK_METHOD(uint32_t, Configure, (WPEFramework::PluginHost::IShell* service), (override)); MOCK_METHOD(uint32_t, Register, (WPEFramework::Exchange::INetworkManager::INotification* notification), (override)); From 6a6ea3c59d81b926dbb1f2126a6c44e57144b2e2 Mon Sep 17 00:00:00 2001 From: jincysam87 <167995204+jincysam87@users.noreply.github.com> Date: Tue, 19 Aug 2025 22:44:39 -0400 Subject: [PATCH 166/271] RDKEMW-7242 : observing routerDiscovery service in failed state (#207) * Update getRouterInfo-NMdispatcher.sh * Update getRouterInfo-nlmon.sh * Update readyToGetRouterInfo.sh * Update getRouterInfo-nlmon.sh --- .../upnp/scripts/getRouterInfo-NMdispatcher.sh | 18 ++++++++++++------ tools/upnp/scripts/getRouterInfo-nlmon.sh | 10 ++++++---- tools/upnp/scripts/readyToGetRouterInfo.sh | 2 +- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/tools/upnp/scripts/getRouterInfo-NMdispatcher.sh b/tools/upnp/scripts/getRouterInfo-NMdispatcher.sh index 11872b793..316c3bc29 100755 --- a/tools/upnp/scripts/getRouterInfo-NMdispatcher.sh +++ b/tools/upnp/scripts/getRouterInfo-NMdispatcher.sh @@ -20,9 +20,15 @@ . /etc/device.properties ifc=$1 -pid=`pidof routerDiscovery` -if [ -n "$pid" ]; then - kill -9 $pid -fi -echo "Starting routerDiscovery on $ifc" >> /opt/logs/routerInfo.log -systemctl start routerDiscovery@$ifc +mode=$2 +#Perform routerDiscovery only in case of v4 IP acquisition +if [ "$mode" == "dhcp4-change" ]; then + # Find the PID of the routerDiscovery process that is running specifically on this interface. + pid=$(pgrep -f "routerDiscovery $ifc") + if [ -n "$pid" ]; then + echo "$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ") Found existing routerDiscovery ($pid) for $ifc, Killing it." >> /opt/logs/routerInfo.log + kill -15 "$pid" + fi + echo "$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ") Starting routerDiscovery on $ifc" >> /opt/logs/routerInfo.log + systemctl start routerDiscovery@$ifc +fi diff --git a/tools/upnp/scripts/getRouterInfo-nlmon.sh b/tools/upnp/scripts/getRouterInfo-nlmon.sh index 2d9345199..672c1e8c3 100755 --- a/tools/upnp/scripts/getRouterInfo-nlmon.sh +++ b/tools/upnp/scripts/getRouterInfo-nlmon.sh @@ -25,14 +25,16 @@ ifc=$3 flags=$5 file="/tmp/.routerdiscover" if [[ "$ifc" == "$WIFI_INTERFACE" || "$ifc" == "$ETHERNET_INTERFACE" ]]; then - if [ "$cmd" == "add" ] && [ "$flags" = "global" ]; then + if [ "$cmd" == "add" ] && [ "$flags" == "global" ] && [ "$mode" == "ipv4" ]; then if [ ! -f $file ]; then touch /tmp/.routerdiscover - pid=`pidof routerDiscovery` + # Find the PID of the routerDiscovery process that is running specifically on this interface. + pid=$(pgrep -f "routerDiscovery $ifc") if [ -n "$pid" ]; then - kill -9 $pid + echo "$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ") Found existing routerDiscovery ($pid) for $ifc, Killing it." >> /opt/logs/routerInfo.log + kill -15 $pid fi - echo "Starting routerDiscovery on $ifc" >> /opt/logs/routerInfo.log + echo "$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ") Starting routerDiscovery on $ifc" >> /opt/logs/routerInfo.log systemctl start routerDiscovery@$ifc fi fi diff --git a/tools/upnp/scripts/readyToGetRouterInfo.sh b/tools/upnp/scripts/readyToGetRouterInfo.sh index b7ce58b94..ceb0efd9c 100755 --- a/tools/upnp/scripts/readyToGetRouterInfo.sh +++ b/tools/upnp/scripts/readyToGetRouterInfo.sh @@ -23,7 +23,7 @@ ifc=$1 file="/tmp/.routerdiscover" if [[ "$ifc" == "$WIFI_INTERFACE" || "$ifc" == "$ETHERNET_INTERFACE" ]]; then if [ -f "$file" ]; then - echo "Ready to read router details" >> /opt/logs/routerInfo.log + echo "$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ") Ready to read router details" >> /opt/logs/routerInfo.log rm "$file" fi fi From a9d25c84d9854f2c5c2cc0f740e336454087063d Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Mon, 25 Aug 2025 23:58:05 +0530 Subject: [PATCH 167/271] RDKEMW-7458 ConnectivityMonitor Thread crashed during Reboot (#210) Reason for change: fix for connectivity monitor crash Test Procedure: reboot test and verify the crash Signed-off-by: Muhammed Rafi c --- plugin/NetworkManagerImplementation.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 521e8719a..706022613 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -32,6 +32,7 @@ namespace WPEFramework { namespace Plugin { + extern NetworkManagerImplementation* _instance; SERVICE_REGISTRATION(NetworkManagerImplementation, NETWORKMANAGER_MAJOR_VERSION, NETWORKMANAGER_MINOR_VERSION, NETWORKMANAGER_PATCH_VERSION); NetworkManagerImplementation::NetworkManagerImplementation() @@ -59,6 +60,8 @@ namespace WPEFramework NetworkManagerImplementation::~NetworkManagerImplementation() { NMLOG_INFO("NetworkManager Out-Of-Process Shutdown/Cleanup"); + connectivityMonitor.stopConnectivityMonitor(); + _instance = nullptr; if(m_registrationThread.joinable()) { m_registrationThread.join(); From 8d487fb8aca9042be3ddd2e70f081dd3321fd8c4 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Tue, 26 Aug 2025 00:55:44 +0530 Subject: [PATCH 168/271] RDKEMW-7459 : Clamp Network-Plugin Noise Value to Range [0 dBm to -96dBm] (#211) RDKEMW-7459 : Clamp Network-Plugin Noise Value to Range [0 dBm to -96dBm] Signed-off-by: Muhammed Rafi c --------- Signed-off-by: Muhammed Rafi c Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- plugin/NetworkManagerImplementation.cpp | 13 ++-- plugin/NetworkManagerImplementation.h | 10 ++- plugin/rdk/NetworkManagerRDKProxy.cpp | 15 ++++- tests/l2Test/l2_test_rdkproxy.cpp | 87 +++++++++++++++++++++++-- 4 files changed, 111 insertions(+), 14 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 706022613..e61dcf8c9 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -852,11 +852,16 @@ namespace WPEFramework readNoise = std::stoi(noise); readSnr = std::stoi(snr); - /* Check the Noise is within range */ - if(!(readNoise < 0 && readNoise >= DEFAULT_NOISE)) + /* Check the Noise is within range between 0 and -96 dbm*/ + if((readNoise >= 0) || (readNoise < DEFAULT_NOISE)) { - NMLOG_WARNING("Received Noise (%d) from wifi driver is not valid", readNoise); - noise = "0"; + NMLOG_DEBUG("Received Noise (%d) from wifi driver is not valid; so clamping it", readNoise); + if (readNoise >= 0) { + noise = std::to_string(0); + } + else if (readNoise < DEFAULT_NOISE) { + noise = std::to_string(DEFAULT_NOISE); + } } /* mapping rssi value when the SNR value is not proper */ diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index aff37e446..9cf0d8b5e 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -35,7 +35,15 @@ using namespace std; #include "NetworkManagerConnectivity.h" #include "NetworkManagerStunClient.h" -#define DEFAULT_NOISE -180 +/* + * Receiver thermal noise + BW factor + assumed noise figure (NF) (dB) + * for a 20MHz channel, + * = -174dBm/Hz + 10*log10(20MHz) + 5 + * = -174 + 73 + 5 = -96dBm + * Even if the channel width increases, the noise value will be increases by 3 dBm; (ie -93 dBm). + * So the minimum noise value cannot go beyond -96 dBm. + */ +#define DEFAULT_NOISE -96 #define MAX_SNR_VALUE 180 #define DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC 60 diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 543d014ed..8130966b7 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -1113,10 +1113,19 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { ssidInfo.security = (WIFISecurityMode)mapToNewSecurityMode(connectedSsid.securityMode); ssidInfo.strength = to_string((int)connectedSsid.signalStrength); ssidInfo.rate = to_string((int)connectedSsid.rate); - if(connectedSsid.noise <= 0 && connectedSsid.noise >= DEFAULT_NOISE) - ssidInfo.noise = to_string((int)connectedSsid.noise); + + if(((int) connectedSsid.noise >= 0) || ((int) connectedSsid.noise < DEFAULT_NOISE)) + { + NMLOG_DEBUG ("Received Noise (%f) from wifi driver is not valid; so clamping it", connectedSsid.noise); + if (connectedSsid.noise >= 0) { + ssidInfo.noise = std::to_string(0); + } + else if (connectedSsid.noise < DEFAULT_NOISE) { + ssidInfo.noise = std::to_string(DEFAULT_NOISE); + } + } else - ssidInfo.noise = to_string(0); + ssidInfo.noise = std::to_string((int)connectedSsid.noise); std::string freqStr = to_string((double)connectedSsid.frequency/1000); ssidInfo.frequency = freqStr.substr(0, 5); diff --git a/tests/l2Test/l2_test_rdkproxy.cpp b/tests/l2Test/l2_test_rdkproxy.cpp index 163728534..d97eac192 100644 --- a/tests/l2Test/l2_test_rdkproxy.cpp +++ b/tests/l2Test/l2_test_rdkproxy.cpp @@ -920,6 +920,81 @@ TEST_F(NetworkManagerTest, GetConnectedSSID_Success) EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":\"-30\",\"frequency\":\"2.412\",\"rate\":\"0\",\"noise\":\"0\",\"success\":true}")); } +TEST_F(NetworkManagerTest, GetConnectedSSID_Success_noise_9999) +{ + IARM_Bus_WiFiSrvMgr_Param_t mockParam = {}; + mockParam.status = true; + strncpy(mockParam.data.getConnectedSSID.ssid, "TestNetwork", SSID_SIZE - 1); + mockParam.data.getConnectedSSID.securityMode = NET_WIFI_SECURITY_WPA2_PSK_AES; + mockParam.data.getConnectedSSID.signalStrength = -30.00; // Example signal strength + mockParam.data.getConnectedSSID.frequency = 2412; // Example frequency in MHz + mockParam.data.getConnectedSSID.rate = 0; // Example rate + mockParam.data.getConnectedSSID.noise = 9999; // Example noise level + strncpy(mockParam.data.getConnectedSSID.bssid, "AB:CD:EF:GH:IJ:KL", BSSID_BUFF - 1); // Example BSSID + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_getConnectedSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockParam](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockParam, sizeof(mockParam)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":\"-30\",\"frequency\":\"2.412\",\"rate\":\"0\",\"noise\":\"0\",\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetConnectedSSID_Success_noise_100) +{ + IARM_Bus_WiFiSrvMgr_Param_t mockParam = {}; + mockParam.status = true; + strncpy(mockParam.data.getConnectedSSID.ssid, "TestNetwork", SSID_SIZE - 1); + mockParam.data.getConnectedSSID.securityMode = NET_WIFI_SECURITY_WPA2_PSK_AES; + mockParam.data.getConnectedSSID.signalStrength = -30.00; // Example signal strength + mockParam.data.getConnectedSSID.frequency = 2412; // Example frequency in MHz + mockParam.data.getConnectedSSID.rate = 0; // Example rate + mockParam.data.getConnectedSSID.noise = -100; // Example noise level + strncpy(mockParam.data.getConnectedSSID.bssid, "AB:CD:EF:GH:IJ:KL", BSSID_BUFF - 1); // Example BSSID + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_getConnectedSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockParam](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockParam, sizeof(mockParam)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":\"-30\",\"frequency\":\"2.412\",\"rate\":\"0\",\"noise\":\"-96\",\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetConnectedSSID_Success_noise_50) +{ + IARM_Bus_WiFiSrvMgr_Param_t mockParam = {}; + mockParam.status = true; + strncpy(mockParam.data.getConnectedSSID.ssid, "TestNetwork", SSID_SIZE - 1); + mockParam.data.getConnectedSSID.securityMode = NET_WIFI_SECURITY_WPA2_PSK_AES; + mockParam.data.getConnectedSSID.signalStrength = -30.00; // Example signal strength + mockParam.data.getConnectedSSID.frequency = 2412; // Example frequency in MHz + mockParam.data.getConnectedSSID.rate = 0; // Example rate + mockParam.data.getConnectedSSID.noise = -50; // Example noise level + strncpy(mockParam.data.getConnectedSSID.bssid, "AB:CD:EF:GH:IJ:KL", BSSID_BUFF - 1); // Example BSSID + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), + ::testing::StrEq(IARM_BUS_WIFI_MGR_API_getConnectedSSID), + ::testing::NotNull(), ::testing::_)) + .WillOnce(::testing::DoAll( + ::testing::Invoke([&mockParam](const char*, const char*, void* arg, size_t) { + memcpy(arg, &mockParam, sizeof(mockParam)); + return IARM_RESULT_SUCCESS; + }) + )); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":\"-30\",\"frequency\":\"2.412\",\"rate\":\"0\",\"noise\":\"-50\",\"success\":true}")); +} + TEST_F(NetworkManagerTest, GetConnectedSSID_Failed) { EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), @@ -1290,7 +1365,7 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnected) if (tempFile) { fputs("Selected interface 'wlan0'\n" "ssid=dummySSID\n" - "noise=-114\n" + "noise=-117\n" "level=-49\n" "snr=65\n", tempFile); rewind(tempFile); @@ -1299,7 +1374,7 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnected) })); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Excellent\",\"snr\":\"65\",\"strength\":\"-49\",\"noise\":\"-114\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Excellent\",\"snr\":\"65\",\"strength\":\"-49\",\"noise\":\"-96\",\"success\":true}")); } TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedGood) @@ -1327,7 +1402,7 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedGood) if (tempFile) { fputs("Selected interface 'wlan0'\n" "ssid=dummySSID\n" - "noise=-114\n" + "noise=-30\n" "level=-90\n" "snr=33\n", tempFile); rewind(tempFile); @@ -1336,7 +1411,7 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedGood) })); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Good\",\"snr\":\"33\",\"strength\":\"-90\",\"noise\":\"-114\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Good\",\"snr\":\"33\",\"strength\":\"-90\",\"noise\":\"-30\",\"success\":true}")); } TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedLowBad) @@ -1364,7 +1439,7 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedLowBad) if (tempFile) { fputs("Selected interface 'wlan0'\n" "ssid=dummySSID\n" - "noise=-114\n" + "noise=9999\n" "level=-120\n" "snr=33\n", tempFile); rewind(tempFile); @@ -1373,7 +1448,7 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedLowBad) })); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Good\",\"snr\":\"33\",\"strength\":\"-120\",\"noise\":\"-114\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Good\",\"snr\":\"33\",\"strength\":\"-120\",\"noise\":\"0\",\"success\":true}")); } TEST_F(NetworkManagerTest, Trace_Success_ipv4) From 0c754c56817f32f135d912e5f3a34b9d5bc1f280 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Wed, 27 Aug 2025 19:37:57 +0530 Subject: [PATCH 169/271] RDKEMW-6135 : Implement L1/L2 for Legacy NetworkManager libnm Implementation (#209) * Implement L1/L2 for Legacy NetworkManager libnm Implementation * l2 test folder reorg * wifi api test added * setIPsettings, AddToknownSSID, GetKnownssid api test added --- .github/workflows/legacy_L1_L2_test.yml | 4 +- .github/workflows/libnm_proxy_L1_test.yml | 30 + .github/workflows/rdk_proxy_L1_L2_test.yml | 1 + plugin/gnome/NetworkManagerGnomeProxy.cpp | 6 +- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 37 +- tests/l1Test/CMakeLists.txt | 72 +- tests/l2Test/CMakeLists.txt | 121 +- tests/l2Test/legacy/CMakeLists.txt | 89 + .../l2_test_LegacyPlugin_NetworkAPIs.cpp | 0 .../l2_test_LegacyPlugin_WiFiManagerAPIs.cpp | 0 tests/l2Test/libnm/CMakeLists.txt | 166 ++ tests/l2Test/libnm/l2_test_libnmproxy.cpp | 1532 ++++++++++++++ tests/l2Test/libnm/l2_test_libnmproxyInit.cpp | 171 ++ tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp | 1822 +++++++++++++++++ tests/l2Test/rdk/CMakeLists.txt | 77 + tests/l2Test/{ => rdk}/l2_test_rdkproxy.cpp | 0 .../{ => rdk}/l2_test_rdkproxyEvent.cpp | 0 .../l2Test/{ => rdk}/l2_test_rdkproxyImpl.cpp | 0 tests/mocks/GLibWraps.cpp | 30 + tests/mocks/GLibWraps.h | 25 + tests/mocks/GLibWrapsMock.h | 22 + tests/mocks/LibnmWraps.cpp | 641 ++++++ tests/mocks/LibnmWraps.h | 256 +++ tests/mocks/LibnmWrapsMock.h | 526 +++++ tests/unittest/CMakeLists.txt | 200 -- .../test_LegacyPlugin_NetworkAPIs.cpp | 98 - .../test_LegacyPlugin_WiFiManagerAPIs.cpp | 159 -- tests/unittest/test_NetworkManager.cpp | 197 -- tests/unittest/test_UpnpDiscoveryManager.cpp | 100 - .../test_WiFiSignalStrengthMonitor.cpp | 69 - 30 files changed, 5453 insertions(+), 998 deletions(-) create mode 100644 tests/l2Test/legacy/CMakeLists.txt rename tests/l2Test/{ => legacy}/l2_test_LegacyPlugin_NetworkAPIs.cpp (100%) rename tests/l2Test/{ => legacy}/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp (100%) create mode 100644 tests/l2Test/libnm/CMakeLists.txt create mode 100644 tests/l2Test/libnm/l2_test_libnmproxy.cpp create mode 100644 tests/l2Test/libnm/l2_test_libnmproxyInit.cpp create mode 100644 tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp create mode 100644 tests/l2Test/rdk/CMakeLists.txt rename tests/l2Test/{ => rdk}/l2_test_rdkproxy.cpp (100%) rename tests/l2Test/{ => rdk}/l2_test_rdkproxyEvent.cpp (100%) rename tests/l2Test/{ => rdk}/l2_test_rdkproxyImpl.cpp (100%) create mode 100644 tests/mocks/GLibWraps.cpp create mode 100644 tests/mocks/GLibWraps.h create mode 100644 tests/mocks/GLibWrapsMock.h create mode 100644 tests/mocks/LibnmWraps.cpp create mode 100644 tests/mocks/LibnmWraps.h create mode 100644 tests/mocks/LibnmWrapsMock.h delete mode 100644 tests/unittest/CMakeLists.txt delete mode 100644 tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp delete mode 100644 tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp delete mode 100644 tests/unittest/test_NetworkManager.cpp delete mode 100644 tests/unittest/test_UpnpDiscoveryManager.cpp delete mode 100644 tests/unittest/test_WiFiSignalStrengthMonitor.cpp diff --git a/.github/workflows/legacy_L1_L2_test.yml b/.github/workflows/legacy_L1_L2_test.yml index a735bfdf3..b3645cce6 100644 --- a/.github/workflows/legacy_L1_L2_test.yml +++ b/.github/workflows/legacy_L1_L2_test.yml @@ -42,7 +42,7 @@ jobs: !install/usr/lib/pkgconfig/gtest.pc !install/usr/lib/pkgconfig/gtest_main.pc !install/usr/lib/wpeframework/plugins - key: thunder-${{ env.THUNDER_REF }}-rdk + key: thunder-${{ env.THUNDER_REF }}-legacy - name: Install packages run: | sudo apt update @@ -136,7 +136,7 @@ jobs: -Wall --coverage " -DENABLE_UNIT_TESTING=ON - -DENABLE_ROUTER_DISCOVERY_TOOL=ON + -DENABLE_ROUTER_DISCOVERY_TOOL=OFF && cmake --build build/networkmanager_rdk --target install -j8 diff --git a/.github/workflows/libnm_proxy_L1_test.yml b/.github/workflows/libnm_proxy_L1_test.yml index d92b5f586..ed40fc22e 100644 --- a/.github/workflows/libnm_proxy_L1_test.yml +++ b/.github/workflows/libnm_proxy_L1_test.yml @@ -107,6 +107,12 @@ jobs: && cmake --build build/ThunderInterfaces --target install -j8 + - name: Generate dependency files + run: | + sudo bash -c 'echo "ETHERNET_INTERFACE=eth0 + WIFI_INTERFACE=wlan0 + DEVICE_NAME=rdk_test_device " > /etc/device.properties' + - name: Build networkmanager with Gnome libnm Proxy run: > cmake @@ -117,7 +123,31 @@ jobs: -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" -DCMAKE_CXX_FLAGS=" -fprofile-arcs -ftest-coverage " -DENABLE_GNOME_NETWORKMANAGER=ON + -DENABLE_LEGACY_PLUGINS=OFF + -DENABLE_UNIT_TESTING=ON -DENABLE_PLUGIN_CLI=ON && cmake --build build/networkmanager_libnm --target install -j8 + - name: Run l2 libnm proxy tests + run: > + PATH=${{github.workspace}}/install/usr/bin:${PATH} + LD_LIBRARY_PATH=${{github.workspace}}/install/usr/lib:${{github.workspace}}/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} + libnm_proxy_l2_test --gtest_color=yes --gtest_output="xml:/tmp/gtest_log/libnm_proxy_l2_test.xml" + + - name: Generate coverage + run: | + lcov -c -o coverage.info -d build/networkmanager_libnm/ + lcov -e coverage.info '*/networkmanager/plugin/gnome/*' -o filtered_coverage.info + + - name: Generate the html report + run: | + genhtml filtered_coverage.info --output-directory /tmp/coverage_report + + - name: Upload the coverage report to Pull request using actions + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: | + /tmp/coverage_report + /tmp/gtest_log diff --git a/.github/workflows/rdk_proxy_L1_L2_test.yml b/.github/workflows/rdk_proxy_L1_L2_test.yml index 9124e4b66..4fb464fe0 100644 --- a/.github/workflows/rdk_proxy_L1_L2_test.yml +++ b/.github/workflows/rdk_proxy_L1_L2_test.yml @@ -134,6 +134,7 @@ jobs: " -DENABLE_UNIT_TESTING=ON -DENABLE_ROUTER_DISCOVERY_TOOL=ON + -DENABLE_LEGACY_PLUGINS=OFF && cmake --build build/networkmanager_rdk --target install -j8 diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 1431fdc2f..0c4e986f1 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -391,10 +391,10 @@ namespace WPEFramework { NMLOG_ERROR("nm_connection_get_interface_name is failed"); /* Temporary mitigation for nm_connection_get_interface_name failure */ - if(m_wlanConnected.load()) - ifacePtr = wifiname.c_str(); if(m_ethConnected.load()) ifacePtr = ethname.c_str(); + else // default always wifi + ifacePtr = wifiname.c_str(); } interface = ifacePtr; @@ -772,7 +772,7 @@ namespace WPEFramework } nmEvent->setwifiScanOptions(true); - if(wifi->wifiScanRequest(m_filterfrequency)) + if(wifi->wifiScanRequest(m_filterSsidslist.size() == 1 ? m_filterSsidslist[0] : "")) rc = Core::ERROR_NONE; return rc; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 7d5725565..1884502ea 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -269,9 +269,10 @@ namespace WPEFramework NMDevice *wifiDevice = getWifiDevice(); if(wifiDevice == NULL) { - NMLOG_FATAL("NMDeviceWifi * NULL !"); + NMLOG_WARNING("wifi state disabled !"); + state = Exchange::INetworkManager::WiFiState::WIFI_STATE_DISABLED; deleteClientConnection(); - return false; + return true; } NMDeviceState deviceState = nm_device_get_state(wifiDevice); // Todo check NMDeviceStateReason for more information @@ -970,24 +971,22 @@ namespace WPEFramework } const GPtrArray *availableConnections = nm_device_get_available_connections(device); - if(availableConnections == NULL) - { - NMLOG_ERROR("No available connections found !"); - deleteClientConnection(); - return false; - } - - for (guint i = 0; i < availableConnections->len; i++) + if(availableConnections != NULL) { - NMConnection *connection = static_cast(g_ptr_array_index(availableConnections, i)); - const char *connId = nm_connection_get_id(NM_CONNECTION(connection)); - if (connId != NULL && strcmp(connId, ssidinfo.ssid.c_str()) == 0) + for (guint i = 0; i < availableConnections->len; i++) { - m_connection = g_object_ref(connection); + NMConnection *connection = static_cast(g_ptr_array_index(availableConnections, i)); + const char *connId = nm_connection_get_id(NM_CONNECTION(connection)); + if (connId != NULL && strcmp(connId, ssidinfo.ssid.c_str()) == 0) + { + m_connection = g_object_ref(connection); + } } } + else + NMLOG_WARNING("No known available connections found !"); - if (NM_IS_REMOTE_CONNECTION(m_connection)) + if (m_connection && NM_IS_REMOTE_CONNECTION(m_connection)) { if(!connectionBuilder(ssidinfo, m_connection)) { @@ -1197,7 +1196,7 @@ namespace WPEFramework return false; } m_isSuccess = false; - if(!ssidReq.empty() && ssidReq != "null") + if(!ssidReq.empty()) { NMLOG_INFO("staring wifi scanning .. %s", ssidReq.c_str()); GVariantBuilder builder, array_builder; @@ -1790,12 +1789,6 @@ namespace WPEFramework if(interface == nmUtils::ethIface()) { NMSettingConnection *settings = NULL; - if(device == NULL) - { - deleteClientConnection(); - return false; - } - const GPtrArray *connections = nm_device_get_available_connections(device); if (connections == NULL || connections->len == 0) { diff --git a/tests/l1Test/CMakeLists.txt b/tests/l1Test/CMakeLists.txt index b552a49bb..dfae9937d 100644 --- a/tests/l1Test/CMakeLists.txt +++ b/tests/l1Test/CMakeLists.txt @@ -23,49 +23,43 @@ find_package(PkgConfig REQUIRED) find_package(${NAMESPACE}Core REQUIRED) find_package(${NAMESPACE}Plugins REQUIRED) -include(FetchContent) -FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip -) - -FetchContent_MakeAvailable(googletest) - include_directories(${PROJECT_SOURCE_DIR}/interface) include_directories(${PROJECT_SOURCE_DIR}/plugin/rdk) include_directories(${PROJECT_SOURCE_DIR}/plugin) -set(NM_ROUTER_DISCOVERY_L1_TEST "upnpcli_l1_test") - -add_executable(${NM_ROUTER_DISCOVERY_L1_TEST} - ${CMAKE_SOURCE_DIR}/tests/l1Test/l1_test_routediscovery.cpp - ${CMAKE_SOURCE_DIR}/tools/upnp/UpnpDiscoveryManager.cpp -) - -target_link_libraries(${NM_ROUTER_DISCOVERY_L1_TEST} PRIVATE - gmock_main - ${GLIB_LIBRARIES} - ${LIBSOUP_LIBRARIES} - ${GUPNP_LIBRARIES} - ${GSSDP_LIBRARIES} -) - -set_target_properties(${NM_ROUTER_DISCOVERY_L1_TEST} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES -) - -target_include_directories(${NM_ROUTER_DISCOVERY_L1_TEST} PRIVATE - ${gtest_SOURCE_DIR}/include - ${gtest_SOURCE_DIR}/../googlemock/include - ${PROJECT_SOURCE_DIR}/tools/upnp - ${GUPNP_INCLUDE_DIRS} - ${GLIB_INCLUDE_DIRS} - ${LIBSOUP_INCLUDE_DIRS} - ${GSSDP_INCLUDE_DIRS} -) - -install(TARGETS ${NM_ROUTER_DISCOVERY_L1_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +if(ENABLE_ROUTER_DISCOVERY_TOOL) + set(NM_ROUTER_DISCOVERY_L1_TEST "upnpcli_l1_test") + + add_executable(${NM_ROUTER_DISCOVERY_L1_TEST} + ${CMAKE_SOURCE_DIR}/tests/l1Test/l1_test_routediscovery.cpp + ${CMAKE_SOURCE_DIR}/tools/upnp/UpnpDiscoveryManager.cpp + ) + + target_link_libraries(${NM_ROUTER_DISCOVERY_L1_TEST} PRIVATE + gmock_main + ${GLIB_LIBRARIES} + ${LIBSOUP_LIBRARIES} + ${GUPNP_LIBRARIES} + ${GSSDP_LIBRARIES} + ) + + set_target_properties(${NM_ROUTER_DISCOVERY_L1_TEST} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES + ) + + target_include_directories(${NM_ROUTER_DISCOVERY_L1_TEST} PRIVATE + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include + ${PROJECT_SOURCE_DIR}/tools/upnp + ${GUPNP_INCLUDE_DIRS} + ${GLIB_INCLUDE_DIRS} + ${LIBSOUP_INCLUDE_DIRS} + ${GSSDP_INCLUDE_DIRS} + ) + + install(TARGETS ${NM_ROUTER_DISCOVERY_L1_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +endif() set(NM_CLASS_L1_TEST "class_l1_test") diff --git a/tests/l2Test/CMakeLists.txt b/tests/l2Test/CMakeLists.txt index 84bf8b97a..f9cfa9488 100644 --- a/tests/l2Test/CMakeLists.txt +++ b/tests/l2Test/CMakeLists.txt @@ -2,7 +2,7 @@ # If not stated otherwise in this file or this component's LICENSE file the # following copyright and licenses apply: # -# Copyright 2024 RDK Management +# Copyright 2023 RDK Management # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,13 +16,11 @@ # See the License for the specific language governing permissions and # limitations under the License. ############################################################################# -message ("building l2 test") - -set(NM_RDK_PROXY_L2_TEST "rdkproxy_l2_test") -set(NM_LEGACY_WIFI_UT "legacywifi_tests") -set(NM_LEGACY_NETWORK_UT "legacynetwork_tests") +cmake_minimum_required(VERSION 3.3) +message ("building Networkmanager plugin l2 tests") find_package(CURL) +find_package(WPEFramework) find_package(PkgConfig REQUIRED) find_package(${NAMESPACE}Core REQUIRED) find_package(${NAMESPACE}Plugins REQUIRED) @@ -35,107 +33,12 @@ FetchContent_Declare( FetchContent_MakeAvailable(googletest) -add_executable(${NM_RDK_PROXY_L2_TEST} - ${CMAKE_SOURCE_DIR}/tests/l2Test/l2_test_rdkproxy.cpp - ${CMAKE_SOURCE_DIR}/tests/l2Test/l2_test_rdkproxyEvent.cpp - ${CMAKE_SOURCE_DIR}/tests/l2Test/l2_test_rdkproxyImpl.cpp - ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp - ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp - ${CMAKE_SOURCE_DIR}/tests/mocks/Wraps.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerJsonRpc.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerImplementation.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp - ${CMAKE_SOURCE_DIR}/plugin/rdk/NetworkManagerRDKProxy.cpp - ${PROXY_STUB_SOURCES} -) - -add_executable(${NM_LEGACY_WIFI_UT} - ${CMAKE_SOURCE_DIR}/tests/l2Test/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp - ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp - ${CMAKE_SOURCE_DIR}/legacy/LegacyWiFiManagerAPIs.cpp -) - -add_executable(${NM_LEGACY_NETWORK_UT} - ${CMAKE_SOURCE_DIR}/tests/l2Test/l2_test_LegacyPlugin_NetworkAPIs.cpp - ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp - ${CMAKE_SOURCE_DIR}/legacy/LegacyNetworkAPIs.cpp -) - -set_target_properties(${NM_RDK_PROXY_L2_TEST} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES -) - -set_target_properties(${NM_LEGACY_WIFI_UT} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES -) -set_target_properties(${NM_LEGACY_NETWORK_UT} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES -) - -target_compile_options(${NM_RDK_PROXY_L2_TEST} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) -target_compile_options(${NM_LEGACY_WIFI_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) -target_compile_options(${NM_LEGACY_NETWORK_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) - -include_directories(${PROJECT_SOURCE_DIR}/interface) -include_directories(${PROJECT_SOURCE_DIR}/plugin/rdk) -include_directories(${PROJECT_SOURCE_DIR}/plugin) -include_directories(${PROJECT_SOURCE_DIR}/legacy) -include_directories(${PROJECT_SOURCE_DIR}/tests/mocks) -include_directories(${PROJECT_SOURCE_DIR}/tests/mocks/thunder) -include_directories(${PROJECT_SOURCE_DIR}/../install/usr/include/rdk/iarmbus/) -include_directories(${PROJECT_SOURCE_DIR}/tools/upnp/) - -target_include_directories(${NM_RDK_PROXY_L2_TEST} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${gtest_SOURCE_DIR}/include - ${gtest_SOURCE_DIR}/../googlemock/include -) - -target_include_directories(${NM_LEGACY_WIFI_UT} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${gtest_SOURCE_DIR}/include - ${gtest_SOURCE_DIR}/../googlemock/include -) - -target_include_directories(${NM_LEGACY_NETWORK_UT} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${gtest_SOURCE_DIR}/include - ${gtest_SOURCE_DIR}/../googlemock/include -) - -target_link_options(${NM_RDK_PROXY_L2_TEST} PRIVATE -Wl,-wrap,system -Wl,-wrap,popen -Wl,-wrap,syslog -Wl,-wrap,pclose -Wl,-wrap,getmntent -Wl,-wrap,setmntent -Wl,-wrap,v_secure_popen -Wl,-wrap,v_secure_pclose -Wl,-wrap,v_secure_system) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") - -target_link_libraries(${NM_RDK_PROXY_L2_TEST} PRIVATE - gmock_main - ${NAMESPACE}Core::${NAMESPACE}Core - ${NAMESPACE}Plugins::${NAMESPACE}Plugins - ${CURL_LIBRARIES} -) -target_link_libraries(${NM_LEGACY_WIFI_UT} PRIVATE - gmock_main - ${NAMESPACE}Core::${NAMESPACE}Core - ${NAMESPACE}Plugins::${NAMESPACE}Plugins - ${NAMESPACE}Core::${NAMESPACE}Core - ${CURL_LIBRARIES} -) -target_link_libraries(${NM_LEGACY_NETWORK_UT} PRIVATE - gmock_main - ${NAMESPACE}Core::${NAMESPACE}Core - ${NAMESPACE}Plugins::${NAMESPACE}Plugins - ${NAMESPACE}Core::${NAMESPACE}Core - ${CURL_LIBRARIES} -) +if(ENABLE_LEGACY_PLUGINS) + add_subdirectory(legacy) +endif() -install(TARGETS ${NM_RDK_PROXY_L2_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -install(TARGETS ${NM_LEGACY_WIFI_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -install(TARGETS ${NM_LEGACY_NETWORK_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +if(ENABLE_GNOME_NETWORKMANAGER) + add_subdirectory(libnm) +else() + add_subdirectory(rdk) +endif() diff --git a/tests/l2Test/legacy/CMakeLists.txt b/tests/l2Test/legacy/CMakeLists.txt new file mode 100644 index 000000000..5106f18ed --- /dev/null +++ b/tests/l2Test/legacy/CMakeLists.txt @@ -0,0 +1,89 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2024 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# +message ("building l2 legacy plugin test") + +set(NM_LEGACY_WIFI_UT "legacywifi_tests") +set(NM_LEGACY_NETWORK_UT "legacynetwork_tests") + +find_package(PkgConfig REQUIRED) +find_package(${NAMESPACE}Core REQUIRED) +find_package(${NAMESPACE}Plugins REQUIRED) + +add_executable(${NM_LEGACY_WIFI_UT} + ${CMAKE_SOURCE_DIR}/tests/l2Test/legacy/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/legacy/LegacyWiFiManagerAPIs.cpp +) + +add_executable(${NM_LEGACY_NETWORK_UT} + ${CMAKE_SOURCE_DIR}/tests/l2Test/legacy/l2_test_LegacyPlugin_NetworkAPIs.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/legacy/LegacyNetworkAPIs.cpp +) + +set_target_properties(${NM_LEGACY_WIFI_UT} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) +set_target_properties(${NM_LEGACY_NETWORK_UT} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) + +target_compile_options(${NM_LEGACY_WIFI_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) +target_compile_options(${NM_LEGACY_NETWORK_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) + +include_directories(${PROJECT_SOURCE_DIR}/interface) +include_directories(${PROJECT_SOURCE_DIR}/plugin) +include_directories(${PROJECT_SOURCE_DIR}/legacy) +include_directories(${PROJECT_SOURCE_DIR}/tests/mocks) +include_directories(${PROJECT_SOURCE_DIR}/tests/mocks/thunder) + +target_include_directories(${NM_LEGACY_WIFI_UT} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include +) + +target_include_directories(${NM_LEGACY_NETWORK_UT} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include +) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") + +target_link_libraries(${NM_LEGACY_WIFI_UT} PRIVATE + gmock_main + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ${NAMESPACE}Core::${NAMESPACE}Core +) + +target_link_libraries(${NM_LEGACY_NETWORK_UT} PRIVATE + gmock_main + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ${NAMESPACE}Core::${NAMESPACE}Core +) + +install(TARGETS ${NM_LEGACY_WIFI_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS ${NM_LEGACY_NETWORK_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/l2Test/l2_test_LegacyPlugin_NetworkAPIs.cpp b/tests/l2Test/legacy/l2_test_LegacyPlugin_NetworkAPIs.cpp similarity index 100% rename from tests/l2Test/l2_test_LegacyPlugin_NetworkAPIs.cpp rename to tests/l2Test/legacy/l2_test_LegacyPlugin_NetworkAPIs.cpp diff --git a/tests/l2Test/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp b/tests/l2Test/legacy/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp similarity index 100% rename from tests/l2Test/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp rename to tests/l2Test/legacy/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp diff --git a/tests/l2Test/libnm/CMakeLists.txt b/tests/l2Test/libnm/CMakeLists.txt new file mode 100644 index 000000000..c7356c56c --- /dev/null +++ b/tests/l2Test/libnm/CMakeLists.txt @@ -0,0 +1,166 @@ +############################################################################# +# Copyright 2024 RDK Management +# Licensed under the Apache License, Version 2.0 +############################################################################# +message ("building libnm test") + +set(NM_LIBNM_PROXY_L2_TEST "libnm_proxy_l2_test") + +find_package(CURL) +find_package(PkgConfig REQUIRED) +find_package(${NAMESPACE}Core REQUIRED) +find_package(${NAMESPACE}Plugins REQUIRED) +pkg_check_modules(GLIB REQUIRED glib-2.0) +pkg_check_modules(LIBNM REQUIRED libnm) +pkg_check_modules(GIO REQUIRED gio-2.0) + +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip +) +FetchContent_MakeAvailable(googletest) + +message("networkmanager building with libnm") +add_executable(${NM_LIBNM_PROXY_L2_TEST} + ${CMAKE_SOURCE_DIR}/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp + ${CMAKE_SOURCE_DIR}/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp + ${CMAKE_SOURCE_DIR}/tests/l2Test/libnm/l2_test_libnmproxy.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/Wraps.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/LibnmWraps.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/GLibWraps.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerJsonRpc.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerImplementation.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp + ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeProxy.cpp + ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeWIFI.cpp + ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeEvents.cpp + ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeUtils.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerSecretAgent.cpp + ${PROXY_STUB_SOURCES} +) + +set_target_properties(${NM_LIBNM_PROXY_L2_TEST} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) + +target_compile_options(${NM_LIBNM_PROXY_L2_TEST} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) + +# Add a definition to handle the NM_DEVICE macro in test +target_compile_definitions(${NM_LIBNM_PROXY_L2_TEST} PRIVATE + NM_DEVICE_CAST_WORKAROUND=1 +) + +include_directories(${PROJECT_SOURCE_DIR}/interface) +include_directories(${PROJECT_SOURCE_DIR}/plugin) +include_directories(${PROJECT_SOURCE_DIR}/legacy) +include_directories(${PROJECT_SOURCE_DIR}/tests/mocks) +include_directories(${PROJECT_SOURCE_DIR}/tests/mocks/thunder) + +target_include_directories(${NM_LIBNM_PROXY_L2_TEST} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${GLIB_INCLUDE_DIRS} + ${LIBNM_INCLUDE_DIRS} + ${GIO_INCLUDE_DIRS} + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include +) + +target_link_options(${NM_LIBNM_PROXY_L2_TEST} PRIVATE + -g + -Wall + -Wl,-wrap,system + -Wl,-wrap,popen + -Wl,-wrap,syslog + -Wl,-wrap,pclose + -Wl,-wrap,getmntent + -Wl,-wrap,setmntent + -Wl,-wrap,v_secure_popen + -Wl,-wrap,v_secure_pclose + -Wl,-wrap,v_secure_system + -Wl,-wrap,nm_device_get_iface + -Wl,-wrap,nm_client_get_primary_connection + -Wl,-wrap,nm_active_connection_get_connection + -Wl,-wrap,nm_connection_get_interface_name + -Wl,-wrap,nm_client_get_device_by_iface + -Wl,-wrap,nm_device_get_state + -Wl,-wrap,nm_client_get_devices + -Wl,-wrap,nm_client_new + -Wl,-wrap,nm_device_get_hw_address + -Wl,-wrap,nm_client_get_active_connections + -Wl,-wrap,nm_connection_get_setting_connection + -Wl,-wrap,nm_setting_connection_get_interface_name + -Wl,-wrap,nm_active_connection_get_ip4_config + -Wl,-wrap,nm_active_connection_get_ip6_config + -Wl,-wrap,nm_active_connection_get_dhcp4_config + -Wl,-wrap,nm_active_connection_get_dhcp6_config + -Wl,-wrap,nm_connection_get_setting_ip4_config + -Wl,-wrap,nm_connection_get_setting_ip6_config + -Wl,-wrap,nm_setting_ip_config_get_method + -Wl,-wrap,nm_ip_config_get_addresses + -Wl,-wrap,nm_ip_address_get_address + -Wl,-wrap,nm_ip_address_get_prefix + -Wl,-wrap,nm_ip_config_get_gateway + -Wl,-wrap,nm_ip_config_get_nameservers + -Wl,-wrap,nm_dhcp_config_get_one_option + -Wl,-wrap,nm_device_disconnect_async + -Wl,-wrap,nm_device_disconnect_finish + -Wl,-wrap,g_main_loop_is_running + -Wl,-wrap,nm_access_point_get_flags + -Wl,-wrap,nm_access_point_get_wpa_flags + -Wl,-wrap,nm_access_point_get_rsn_flags + -Wl,-wrap,nm_access_point_get_ssid + -Wl,-wrap,nm_access_point_get_bssid + -Wl,-wrap,nm_access_point_get_frequency + -Wl,-wrap,nm_access_point_get_mode + -Wl,-wrap,nm_access_point_get_max_bitrate + -Wl,-wrap,nm_access_point_get_strength + -Wl,-wrap,nm_device_wifi_get_active_access_point + -Wl,-wrap,nm_device_wifi_request_scan_async + -Wl,-wrap,nm_device_wifi_request_scan_options_async + -Wl,-wrap,nm_device_wifi_request_scan_finish + -Wl,-wrap,nm_client_activate_connection_async + -Wl,-wrap,nm_connection_get_connection_type + -Wl,-wrap,nm_connection_get_id + -Wl,-wrap,nm_client_get_connections + -Wl,-wrap,nm_device_set_autoconnect + -Wl,-wrap,nm_device_wifi_get_last_scan + -Wl,-wrap,nm_client_activate_connection_finish + -Wl,-wrap,nm_client_add_and_activate_connection_async + -Wl,-wrap,nm_remote_connection_update2_finish + -Wl,-wrap,nm_client_add_connection2 + -Wl,-wrap,nm_client_add_connection2_finish + -Wl,-wrap,nm_client_add_and_activate_connection_finish + -Wl,-wrap,nm_device_wifi_get_access_points + -Wl,-wrap,nm_device_get_available_connections + -Wl,-wrap,nm_object_get_path + -Wl,-wrap,nm_client_dbus_set_property + -Wl,-wrap,nm_client_dbus_set_property_finish + -Wl,-wrap,nm_device_get_active_connection + -Wl,-wrap,nm_remote_connection_commit_changes + -Wl,-wrap,nm_setting_ip_config_get_dhcp_hostname + -Wl,-wrap,nm_setting_ip_config_get_dhcp_send_hostname + -Wl,-wrap,nm_connection_add_setting + -Wl,-wrap,nm_setting_wireless_get_ssid + -Wl,-wrap,nm_connection_get_setting_wireless + -Wl,-wrap,nm_remote_connection_delete +) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") + +target_link_libraries(${NM_LIBNM_PROXY_L2_TEST} PRIVATE + gmock_main + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ${CURL_LIBRARIES} + ${GLIB_LIBRARIES} + ${LIBNM_LIBRARIES} + ${GIO_LIBRARIES} +) + +install(TARGETS ${NM_LIBNM_PROXY_L2_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/l2Test/libnm/l2_test_libnmproxy.cpp b/tests/l2Test/libnm/l2_test_libnmproxy.cpp new file mode 100644 index 000000000..b67cfc949 --- /dev/null +++ b/tests/l2Test/libnm/l2_test_libnmproxy.cpp @@ -0,0 +1,1532 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ +#include +#include +#include +#include +#include +#include +#include + +#include "FactoriesImplementation.h" +#include "WrapsMock.h" +#include "LibnmWrapsMock.h" +#include "GLibWrapsMock.h" +#include "ServiceMock.h" +#include "ThunderPortability.h" +#include "COMLinkMock.h" +#include "WorkerPoolImplementation.h" +#include "NetworkManagerImplementation.h" +#include "NetworkManagerLogger.h" +#include "NetworkManager.h" +#include + +using namespace WPEFramework; +using ::testing::NiceMock; + +class NetworkManagerTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + DECL_CORE_JSONRPC_CONX connection; + Core::JSONRPC::Message message; + string response; + NMClient* gNmClient = NULL; + + WrapsImplMock *p_wrapsImplMock = nullptr; + GLibWrapsImplMock *p_gLibWrapsImplMock = nullptr; + LibnmWrapsImplMock *p_libnmWrapsImplMock = nullptr; + Core::ProxyType NetworkManagerImpl; + + NiceMock comLinkMock; + NiceMock service; + PLUGINHOST_DISPATCHER* dispatcher; + Core::ProxyType workerPool; + NiceMock factoriesImplementation; + + NetworkManagerTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , INIT_CONX(1, 0) + , workerPool(Core::ProxyType::Create(2, Core::Thread::DefaultStackSize(), 16)) + { + + p_libnmWrapsImplMock = new NiceMock ; + LibnmWraps::setImpl(p_libnmWrapsImplMock); + + p_gLibWrapsImplMock = new NiceMock ; + GLibWraps::setImpl(p_gLibWrapsImplMock); + + p_wrapsImplMock = new NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Invoke( + [this]() { + return &comLinkMock; + })); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return( + "{" + " \"locator\":\"libWPEFrameworkNetworkManager.so\"," + " \"classname\":\"NetworkManager\"," + " \"callsign\":\"org.rdk.NetworkManager\"," + " \"startuporder\":55," + " \"autostart\":false," + " \"configuration\":{" + " \"root\":{" + " \"outofprocess\":true," + " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" + " }," + " \"connectivity\":{" + " \"endpoint_1\":\"http://clients3.google.com/generate_204\"," + " \"interval\":60" + " }," + " \"stun\":{" + " \"endpoint\":\"stun.l.google.com\"," + " \"port\":19302," + " \"interval\":30" + " }," + " \"loglevel\":4" + " }" + "}" + )); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const RPC::Object& object, const uint32_t waitTime, uint32_t& connectionId) { + NetworkManagerImpl = Core::ProxyType::Create(); + return &NetworkManagerImpl; + })); + + PluginHost::IFactories::Assign(&factoriesImplementation); + + Core::IWorkerPool::Assign(&(*workerPool)); + workerPool->Run(); + + + dispatcher = static_cast( + plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); + dispatcher->Activate(&service); + response = plugin->Initialize(&service); + EXPECT_EQ(string(""), response); + NetworkManagerLogger::SetLevel(static_cast(NetworkManagerLogger::DEBUG_LEVEL)); + } + + virtual void SetUp() override + { + struct stat buffer; + if (stat("/etc/device.properties", &buffer) != 0) { + std::ofstream file("/etc/device.properties"); + if (file.is_open()) { + file << "ETHERNET_INTERFACE=eth0\nWIFI_INTERFACE=wlan0\n"; + file.close(); + } + else { + std::cerr << "Failed to create /etc/device.properties file." << std::endl; + } + } + } + + virtual ~NetworkManagerTest() override + { + plugin->Deinitialize(&service); + dispatcher->Deactivate(); + dispatcher->Release(); + + Core::IWorkerPool::Assign(nullptr); + workerPool.Release(); + + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + + LibnmWraps::setImpl(nullptr); + if (p_libnmWrapsImplMock != nullptr) + { + delete p_libnmWrapsImplMock; + p_libnmWrapsImplMock = nullptr; + } + + GLibWraps::setImpl(nullptr); + if (p_gLibWrapsImplMock != nullptr) + { + delete p_gLibWrapsImplMock; + p_gLibWrapsImplMock = nullptr; + } + } +}; + +TEST_F(NetworkManagerTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("SetLogLevel"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetLogLevel"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetAvailableInterfaces"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetPrimaryInterface"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetInterfaceState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("SetInterfaceState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetIPSettings"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("SetIPSettings"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("StartWiFiScan"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("StopWiFiScan"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetKnownSSIDs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("AddToKnownSSIDs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("RemoveKnownSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("WiFiConnect"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("WiFiDisconnect"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetConnectedSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("StartWPS"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("StopWPS"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetWifiState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetWiFiSignalQuality"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetSupportedSecurityModes"))); +} + +TEST_F(NetworkManagerTest, SetLogLevel) +{ + EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) + .Times(1) + .WillOnce(::testing::Invoke( + [&](const char* command, const char* type) -> FILE* { + EXPECT_THAT(string(command), ::testing::MatchesRegex("nmcli general logging level TRACE domains ALL")); + // Create a temporary file with the mock output + FILE* tempFile = tmpfile(); + return tempFile; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetLogLevel"), _T("{\"level\":4}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, SetHostName_null) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetHostname"), _T("{\"hostname\":\"\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetHostName_ClientCon_Null) +{ + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetHostname"), _T("{\"hostname\":\"test_host\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetHostName_iface_null) +{ + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(::testing::_)) + .WillOnce(::testing::Return(nullptr)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetHostname"), _T("{\"hostname\":\"test_host\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + //g_object_unref(conn); + g_ptr_array_free(dummyConns, TRUE); +} + +TEST_F(NetworkManagerTest, SetHostName_iface_unknown) +{ + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(::testing::_)) + .WillOnce(::testing::Return("unknown")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetHostname"), _T("{\"hostname\":\"test_host\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + g_object_unref(conn); + g_ptr_array_free(dummyConns, TRUE); +} + +TEST_F(NetworkManagerTest, SetHostName_iface_wlan0_alradyset) +{ + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_ip4_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_ip6_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100174))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_ip_config_get_dhcp_hostname(::testing::_)) + .WillOnce(::testing::Return("test_host")) + .WillOnce(::testing::Return("test_host")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_ip_config_get_dhcp_send_hostname(::testing::_)) + .WillOnce(::testing::Return(TRUE)) + .WillOnce(::testing::Return(TRUE)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetHostname"), _T("{\"hostname\":\"test_host\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + g_object_unref(conn); + g_ptr_array_free(dummyConns, TRUE); +} + +TEST_F(NetworkManagerTest, SetHostName_iface_wlan0) +{ + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_ip4_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_ip6_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return("test_wlan")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_commit_changes(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [](NMRemoteConnection *connection, gboolean save_to_disk, GCancellable *cancellable, GError **error) -> gboolean { + return TRUE; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetHostname"), _T("{\"hostname\":\"test_host\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + g_object_unref(conn); + g_ptr_array_free(dummyConns, TRUE); +} + +TEST_F(NetworkManagerTest, GetPrimaryInterface_eth0) +{ + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); + EXPECT_EQ(response, _T("{\"interface\":\"eth0\",\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetPrimaryInterface_wlan0) +{ + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNAVAILABLE)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); + EXPECT_EQ(response, _T("{\"interface\":\"wlan0\",\"success\":true}")); +} + +TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_null_eth0) +{ + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) + .WillOnce(::testing::Return(dummyActiveConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); + EXPECT_EQ(response, _T("{\"interface\":\"eth0\",\"success\":true}")); + g_object_unref(dummyActiveConn); +} + +TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_null_wlan0) +{ + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNAVAILABLE)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) + .WillOnce(::testing::Return(dummyActiveConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); + EXPECT_EQ(response, _T("{\"interface\":\"wlan0\",\"success\":true}")); + g_object_unref(dummyActiveConn); +} + +TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_wlan0) +{ + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) + .WillOnce(::testing::Return(dummyActiveConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) + .WillOnce(::testing::Return(dummyRemoteConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) + .WillOnce(::testing::Return("wlan0")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); + EXPECT_EQ(response, _T("{\"interface\":\"wlan0\",\"success\":true}")); + g_object_unref(dummyActiveConn); + g_object_unref(dummyRemoteConn); +} + +TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_eth0) +{ + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) + .WillOnce(::testing::Return(dummyActiveConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) + .WillOnce(::testing::Return(dummyRemoteConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) + .WillOnce(::testing::Return("eth0")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); + EXPECT_EQ(response, _T("{\"interface\":\"eth0\",\"success\":true}")); + g_object_unref(dummyActiveConn); + g_object_unref(dummyRemoteConn); +} + +TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_unknown) +{ + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) + .WillOnce(::testing::Return(dummyActiveConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) + .WillOnce(::testing::Return(dummyRemoteConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) + .WillOnce(::testing::Return("unknown")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + g_object_unref(dummyActiveConn); + g_object_unref(dummyRemoteConn); +} + +TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_iface_null) +{ + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) + .WillOnce(::testing::Return(dummyActiveConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) + .WillOnce(::testing::Return(dummyRemoteConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) + .WillOnce(::testing::Return(nullptr)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); + EXPECT_EQ(response, _T("{\"interface\":\"wlan0\",\"success\":true}")); + g_object_unref(dummyActiveConn); + g_object_unref(dummyRemoteConn); +} + +TEST_F(NetworkManagerTest, GetInterfaceState_Failed) +{ + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(nullptr)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), _T("{\"interface\":\"wlan0\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, GetInterfaceState_WifiEth) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")) + .WillOnce(::testing::Return("eth0")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); // disabled + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), _T("{\"interface\":\"wlan0\"}"), response)); + EXPECT_EQ(response, _T("{\"enabled\":true,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), _T("{\"interface\":\"eth0\"}"), response)); + EXPECT_EQ(response, _T("{\"enabled\":false,\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerTest, GetInterfaceState_WifiEthNotFound) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan1")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), _T("{\"interface\":\"wlan0\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerTest, GetInterfaceState_unknown) +{ + Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); + Exchange::INetworkManager* interface = static_cast(NetworkManagerImpl2->QueryInterface(Exchange::INetworkManager::ID)); + ASSERT_TRUE(interface != nullptr); + + bool isEnabled; + std::string ifaceName = "wlan1"; + uint32_t result = interface->GetInterfaceState(ifaceName, isEnabled); + EXPECT_EQ(result, Core::ERROR_GENERAL); + EXPECT_EQ(isEnabled, false); +} + +TEST_F(NetworkManagerTest, GetAvailableInterfaces_DevicesNull) +{ + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillOnce(::testing::Return(nullptr)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T(""), response)); + EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); +} + +TEST_F(NetworkManagerTest, GetAvailableInterfaces_Enabled) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *ethDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); + NMDevice* wifiDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, wifiDevice); + g_ptr_array_add(fakeDevices, ethDevice); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillOnce(::testing::Return(fakeDevices)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(ethDevice)) + .WillOnce(::testing::Return("eth0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(wifiDevice)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_hw_address(ethDevice)) + .WillOnce(::testing::Return("00:11:22:33:44:55")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_hw_address(wifiDevice)) + .WillOnce(::testing::Return("66:77:88:99:AA:BB")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(ethDevice)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(wifiDevice)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNAVAILABLE)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T(""), response)); + EXPECT_TRUE(response.find("wlan0") != std::string::npos); + EXPECT_TRUE(response.find("eth0") != std::string::npos); + + std::string expectedResponse = + _T("{\"interfaces\":[") + _T("{\"type\":\"WIFI\",\"name\":\"wlan0\",\"mac\":\"66:77:88:99:AA:BB\",\"enabled\":true,\"connected\":false},") + _T("{\"type\":\"ETHERNET\",\"name\":\"eth0\",\"mac\":\"00:11:22:33:44:55\",\"enabled\":true,\"connected\":true}") + _T("],\"success\":true}"); + EXPECT_EQ(response, expectedResponse); + + g_object_unref(ethDevice); + g_object_unref(wifiDevice); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerTest, GetAvailableInterfaces_disabled) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *ethDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); + NMDevice* wifiDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, wifiDevice); + g_ptr_array_add(fakeDevices, ethDevice); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillOnce(::testing::Return(fakeDevices)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(ethDevice)) + .WillOnce(::testing::Return("eth0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(wifiDevice)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_hw_address(ethDevice)) + .WillOnce(::testing::Return("00:11:22:33:44:55")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_hw_address(wifiDevice)) + .WillOnce(::testing::Return("66:77:88:99:AA:BB")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(ethDevice)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(wifiDevice)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T(""), response)); + EXPECT_TRUE(response.find("wlan0") != std::string::npos); + EXPECT_TRUE(response.find("eth0") != std::string::npos); + + std::string expectedResponse = + _T("{\"interfaces\":[") + _T("{\"type\":\"WIFI\",\"name\":\"wlan0\",\"mac\":\"66:77:88:99:AA:BB\",\"enabled\":false,\"connected\":false},") + _T("{\"type\":\"ETHERNET\",\"name\":\"eth0\",\"mac\":\"00:11:22:33:44:55\",\"enabled\":false,\"connected\":false}") + _T("],\"success\":true}"); + EXPECT_EQ(response, expectedResponse); + + g_object_unref(ethDevice); + g_object_unref(wifiDevice); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerTest, GetIPSettings_unknown_iface) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth1\"}"), response)); + EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); +} + +TEST_F(NetworkManagerTest, GetIPSettings_invalidDevice) +{ + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); + EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); +} + +TEST_F(NetworkManagerTest, GetIPSettings_invalid_state) +{ + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); + EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); +} + +TEST_F(NetworkManagerTest, GetIPSettings_interface_Empty) +{ + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100172))) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNAVAILABLE)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"\"}"), response)); + EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); +} + +TEST_F(NetworkManagerTest, GetIPSettings_GetPrimary_failed) +{ + // EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + // .WillOnce(::testing::Return(reinterpret_cast(0x100172))) + // .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + // EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) + // .WillOnce(::testing::Return(NM_DEVICE_STATE_UNAVAILABLE)); + + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) + .WillOnce(::testing::Return(dummyActiveConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) + .WillOnce(::testing::Return(dummyRemoteConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) + .WillOnce(::testing::Return("unknown")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"\"}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + + g_object_unref(dummyActiveConn); + g_object_unref(dummyRemoteConn); +} + +TEST_F(NetworkManagerTest, GetIPSettings_Invalid_ActiveConnection) +{ + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); + EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); +} + +TEST_F(NetworkManagerTest, GetIPSettings_Invalid_Connection) +{ + GPtrArray* dummyActiveConn = g_ptr_array_new(); + NMActiveConnection *nullConnection = static_cast(NULL); + NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + g_ptr_array_add(dummyActiveConn, nullConnection); + g_ptr_array_add(dummyActiveConn, ethActiveConn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); + EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); + + g_object_unref(ethActiveConn); + g_ptr_array_free(dummyActiveConn, TRUE); +} + +TEST_F(NetworkManagerTest, GetIPSettings_valid_ConnectionSettingsEmpty) +{ + GPtrArray* dummyActiveConn = g_ptr_array_new(); + NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection* retConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyActiveConn, ethActiveConn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) + .WillOnce(::testing::Return(retConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); + EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); + + g_object_unref(ethActiveConn); + g_ptr_array_free(dummyActiveConn, TRUE); +} + +TEST_F(NetworkManagerTest, GetIPSettings_ipv4_config) +{ + GPtrArray* dummyActiveConn = g_ptr_array_new(); + NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection* retConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyActiveConn, ethActiveConn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_ip4_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_connection_get_interface_name(::testing::_)) + .WillOnce(::testing::Return("eth0")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) + .WillOnce(::testing::Return(retConn)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); + std::string expectedResponse = + _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"success\":true}"); + EXPECT_EQ(response, expectedResponse); + + g_object_unref(ethActiveConn); + g_ptr_array_free(dummyActiveConn, TRUE); +} + +TEST_F(NetworkManagerTest, GetIPSettings_ipv4_configAutoConftrue) +{ + GPtrArray* dummyActiveConn = g_ptr_array_new(); + NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection* retConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyActiveConn, ethActiveConn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_ip4_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_connection_get_interface_name(::testing::_)) + .WillOnce(::testing::Return("eth0")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_ip_config_get_method(::testing::_)) + .WillOnce(::testing::Return("auto")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_ip4_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) + .WillOnce(::testing::Return(retConn)) + .WillOnce(::testing::Return(reinterpret_cast(retConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); + std::string expectedResponse = + _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"success\":true}"); + EXPECT_EQ(response, expectedResponse); + + g_object_unref(ethActiveConn); + g_ptr_array_free(dummyActiveConn, TRUE); +} + +TEST_F(NetworkManagerTest, GetIPSettings_ipv4_configAutoConfNull) +{ + GPtrArray* dummyActiveConn = g_ptr_array_new(); + NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection* retConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyActiveConn, ethActiveConn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_ip4_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_connection_get_interface_name(::testing::_)) + .WillOnce(::testing::Return("eth0")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_ip_config_get_method(::testing::_)) + .WillOnce(::testing::Return("not auto")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_ip4_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) + .WillOnce(::testing::Return(retConn)) + .WillOnce(::testing::Return(reinterpret_cast(retConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); + std::string expectedResponse = + _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"success\":true}"); + EXPECT_EQ(response, expectedResponse); + + g_object_unref(ethActiveConn); + g_ptr_array_free(dummyActiveConn, TRUE); +} + +TEST_F(NetworkManagerTest, GetIPSettings_ipv4_config_valid) +{ + NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection* retConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + NMIPAddress* ipv4Addr = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + + GPtrArray* dummyActiveConn = g_ptr_array_new(); + GPtrArray* ipvAddr = g_ptr_array_new(); + g_ptr_array_add(dummyActiveConn, ethActiveConn); + g_ptr_array_add(ipvAddr, ipv4Addr); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_dhcp_config_get_one_option(::testing::_, ::testing::_)) + .WillOnce(::testing::Return("192.168.1.11")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_dhcp4_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100170))); + + const char* fakeDnsServers[] = {"8.8.8.8", "8.8.4.4", nullptr}; + EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_nameservers(::testing::_)) + .WillOnce(::testing::Return(fakeDnsServers)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_gateway(::testing::_)) + .WillOnce(::testing::Return("192.168.1.0")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_address_get_address(::testing::_)) + .WillOnce(::testing::Return("192.168.1.2")) + .WillOnce(::testing::Return("192.168.1.2")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_addresses(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(ipvAddr))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_ip4_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100171))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_connection_get_interface_name(::testing::_)) + .WillOnce(::testing::Return("eth0")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) + .WillOnce(::testing::Return(retConn)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); + + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"secondarydns\":\"8.8.4.4\"") != std::string::npos); + EXPECT_TRUE(response.find("\"primarydns\":\"8.8.8.8\"") != std::string::npos); + EXPECT_TRUE(response.find("\"interface\":\"eth0\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\":\"192.168.1.2\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ula\":\"\"") != std::string::npos); + EXPECT_TRUE(response.find("\"dhcpserver\":\"192.168.1.11\"") != std::string::npos); + EXPECT_TRUE(response.find("\"gateway\":\"192.168.1.0\"") != std::string::npos); + + g_object_unref(ethActiveConn); + g_object_unref(retConn); + g_object_unref(ipv4Addr); + g_ptr_array_free(dummyActiveConn, TRUE); + g_ptr_array_free(ipvAddr, TRUE); +} + +TEST_F(NetworkManagerTest, GetIPSettings_ipv6_config_valid) +{ + NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection* retConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + NMIPAddress* ipv6Addr = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + + GPtrArray* dummyActiveConn = g_ptr_array_new(); + GPtrArray* ipvAddr = g_ptr_array_new(); + g_ptr_array_add(dummyActiveConn, ethActiveConn); + g_ptr_array_add(ipvAddr, ipv6Addr); + g_ptr_array_add(ipvAddr, reinterpret_cast(0x100176)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_dhcp_config_get_one_option(::testing::_, ::testing::_)) + .WillOnce(::testing::Return("2001:db8::1")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_dhcp6_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100170))); + + const char* fakeDnsServers[] = {"2001:4860:4860::8888", "2001:4860:4860::8844", nullptr}; + EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_nameservers(::testing::_)) + .WillOnce(::testing::Return(fakeDnsServers)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_gateway(::testing::_)) + .WillOnce(::testing::Return("2001:4860:4860::1")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_address_get_prefix(::testing::_)) + .WillOnce(::testing::Return(64)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_address_get_address(::testing::_)) + .WillOnce(::testing::Return("2001:db8:1:2:3:4:5:6")) + .WillOnce(::testing::Return("fe80::1234:5678:abcd:ef01")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_addresses(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(ipvAddr))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_ip6_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100171))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_connection_get_interface_name(::testing::_)) + .WillOnce(::testing::Return("eth0")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) + .WillOnce(::testing::Return(retConn)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv6\"}"), response)); + + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"ipversion\":\"IPv6\"") != std::string::npos); + EXPECT_TRUE(response.find("\"secondarydns\":\"2001:4860:4860::8844\"") != std::string::npos); + EXPECT_TRUE(response.find("\"primarydns\":\"2001:4860:4860::8888\"") != std::string::npos); + EXPECT_TRUE(response.find("\"interface\":\"eth0\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\":\"2001:db8:1:2:3:4:5:6\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ula\":\"fe80::1234:5678:abcd:ef01\"") != std::string::npos); + EXPECT_TRUE(response.find("\"prefix\":64") != std::string::npos); + EXPECT_TRUE(response.find("\"dhcpserver\":\"2001:db8::1\"") != std::string::npos); + EXPECT_TRUE(response.find("\"gateway\":\"2001:4860:4860::1\"") != std::string::npos); + + g_object_unref(ethActiveConn); + g_object_unref(retConn); + g_object_unref(ipv6Addr); + g_ptr_array_free(dummyActiveConn, TRUE); + g_ptr_array_free(ipvAddr, TRUE); +} + +TEST_F(NetworkManagerTest, SetInterfaceState_deviceFailed_wlan0) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"), _T("{\"interface\":\"eth0\",\"enabled\":true}"), response)); + EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerTest, SetInterfaceState_wlan0_already_diconnected) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"), _T("{\"interface\":\"wlan0\",\"enabled\":false}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerTest, SetInterfaceState_wlan0_activated) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_disconnect_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_disconnect_async(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDevice *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(device); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_object_get_path(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_dbus_set_property_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GAsyncResult *result, GError **error) -> gboolean { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_FAILED, "WiFi scanning failed: %s", "Network interface is busy or unavailable"); + return FALSE; + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_dbus_set_property(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, const char *object_path, const char *interface_name, const char *property_name, GVariant *value, int timeout_msec, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(client); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"), _T("{\"interface\":\"wlan0\",\"enabled\":false}"), response)); + EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerTest, SetInterfaceState_wlan0_deactivated_ErroCode) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_disconnect_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_disconnect_async(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDevice *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(device); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_object_get_path(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_dbus_set_property_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GAsyncResult *result, GError **error) -> gboolean { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_CANCELLED, "WiFi scanning failed: %s", "Network interface is busy or unavailable"); + return FALSE; + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_dbus_set_property(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, const char *object_path, const char *interface_name, const char *property_name, GVariant *value, int timeout_msec, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(client); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"), _T("{\"interface\":\"wlan0\",\"enabled\":false}"), response)); + EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerTest, SetInterfaceState_wlan0_deactivated_success) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_disconnect_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_disconnect_async(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDevice *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(device); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_object_get_path(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_dbus_set_property_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GAsyncResult *result, GError **error) -> gboolean { + return TRUE; + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_dbus_set_property(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, const char *object_path, const char *interface_name, const char *property_name, GVariant *value, int timeout_msec, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(client); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"), _T("{\"interface\":\"wlan0\",\"enabled\":false}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerTest, SetInterfaceState_wlan0_enable_success) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_object_get_path(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_dbus_set_property_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GAsyncResult *result, GError **error) -> gboolean { + return TRUE; + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_dbus_set_property(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, const char *object_path, const char *interface_name, const char *property_name, GVariant *value, int timeout_msec, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(client); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) + .WillRepeatedly(::testing::Return(static_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"), _T("{\"interface\":\"wlan0\",\"enabled\":true}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerTest, SetInterfaceState_eth0_enable_success) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("eth0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_object_get_path(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_dbus_set_property_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GAsyncResult *result, GError **error) -> gboolean { + return TRUE; + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_dbus_set_property(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, const char *object_path, const char *interface_name, const char *property_name, GVariant *value, int timeout_msec, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(client); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) + .WillRepeatedly(::testing::Return(static_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"), _T("{\"interface\":\"eth0\",\"enabled\":true}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + + +TEST_F(NetworkManagerTest, SetIPSettings_interface_empty) +{ + // Test setting static IP configuration + std::string request = _T("{\"interface\":\"\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\"}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_device_NULL) +{ + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + // Test setting static IP configuration + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\"}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_Connection_NULL) +{ + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x778392))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\"}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_settingsNull) +{ + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x778392))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\"}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_Connection) +{ + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x778392))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x778394))); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_connection_get_interface_name(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\"}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_Connection_eth0) +{ + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x778392))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x778394))); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_connection_get_interface_name(::testing::_)) + .WillOnce(::testing::Return("eth0")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_ip4_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_ip_config_get_method(::testing::_)) + .WillOnce(::testing::Return("auto")); + + std::string request = _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\"}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerTest, SetIPSettings_static_wlan0_activeNull) +{ + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_active_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + std::string request = _T("{\"interface\":\"wlan0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\"}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(dummyActiveConn); +} + +TEST_F(NetworkManagerTest, SetIPSettings_static_wlan0_active_remoteNull) +{ + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_active_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + std::string request = _T("{\"interface\":\"wlan0\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\"}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(dummyActiveConn); +} + +TEST_F(NetworkManagerTest, SetIPSettings_static_wlan0_autoConfTrue) +{ + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_active_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyRemoteConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_ip4_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_ip_config_get_method(::testing::_)) + .WillOnce(::testing::Return("auto")); + + std::string request = _T("{\"interface\":\"wlan0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\"}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(dummyActiveConn); + g_object_unref(dummyRemoteConn); +} + +TEST_F(NetworkManagerTest, SetIPSettings_static_wlan0_autoConffalse) +{ + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_active_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyRemoteConn))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_ip4_config(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_commit_changes(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke( + [](NMRemoteConnection *connection, gboolean save_to_disk, GCancellable *cancellable, GError **error) -> gboolean { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_FAILED, "connection delete failed"); + return false; + })); + + std::string request = _T("{\"interface\":\"wlan0\",\"ipversion\":\"IPv4\",\"autoconfig\":false,\"ipaddress\":\"192.168.1.100\",\"prefix\":24,\"gateway\":\"192.168.1.1\",\"primarydns\":\"8.8.8.8\",\"secondarydns\":\"8.8.4.4\"}"); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetIPSettings"), request, response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(dummyActiveConn); + g_object_unref(dummyRemoteConn); +} \ No newline at end of file diff --git a/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp b/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp new file mode 100644 index 000000000..f7a3666bb --- /dev/null +++ b/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp @@ -0,0 +1,171 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ +#include +#include +#include +#include +#include +#include +#include + +#include "FactoriesImplementation.h" +#include "LibnmWrapsMock.h" +#include "ServiceMock.h" +#include "ThunderPortability.h" +#include "COMLinkMock.h" +#include "WorkerPoolImplementation.h" +#include "NetworkManagerImplementation.h" +#include "NetworkManagerLogger.h" +#include "NetworkManager.h" +#include + +using namespace WPEFramework; +using ::testing::NiceMock; + +class NetworkManagerInitTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + DECL_CORE_JSONRPC_CONX connection; + Core::JSONRPC::Message message; + string response; + + LibnmWrapsImplMock *p_libnmWrapsImplMock = nullptr; + Core::ProxyType NetworkManagerImpl; + + NiceMock comLinkMock; + NiceMock service; + PLUGINHOST_DISPATCHER* dispatcher; + Core::ProxyType workerPool; + NiceMock factoriesImplementation; + + NetworkManagerInitTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , INIT_CONX(1, 0) + , workerPool(Core::ProxyType::Create(2, Core::Thread::DefaultStackSize(), 16)) + { + + p_libnmWrapsImplMock = new NiceMock ; + LibnmWraps::setImpl(p_libnmWrapsImplMock); + + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Invoke( + [this]() { + return &comLinkMock; + })); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return( + "{" + " \"locator\":\"libWPEFrameworkNetworkManager.so\"," + " \"classname\":\"NetworkManager\"," + " \"callsign\":\"org.rdk.NetworkManager\"," + " \"startuporder\":55," + " \"autostart\":false," + " \"configuration\":{" + " \"root\":{" + " \"outofprocess\":true," + " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" + " }," + " \"connectivity\":{" + " \"endpoint_1\":\"http://clients3.google.com/generate_204\"," + " \"interval\":60" + " }," + " \"stun\":{" + " \"endpoint\":\"stun.l.google.com\"," + " \"port\":19302," + " \"interval\":30" + " }," + " \"loglevel\":4" + " }" + "}" + )); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_new(::testing::_, ::testing::_)) + .WillRepeatedly(::testing::Return(nullptr)); + + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const RPC::Object& object, const uint32_t waitTime, uint32_t& connectionId) { + NetworkManagerImpl = Core::ProxyType::Create(); + return &NetworkManagerImpl; + })); + + PluginHost::IFactories::Assign(&factoriesImplementation); + + Core::IWorkerPool::Assign(&(*workerPool)); + workerPool->Run(); + + dispatcher = static_cast( + plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); + dispatcher->Activate(&service); + response = plugin->Initialize(&service); + EXPECT_EQ(string(""), response); + NetworkManagerLogger::SetLevel(static_cast(NetworkManagerLogger::DEBUG_LEVEL)); // Set log level to DEBUG_LEVEL + } + + virtual void SetUp() override + { + } + + virtual ~NetworkManagerInitTest() override + { + plugin->Deinitialize(&service); + + dispatcher->Deactivate(); + dispatcher->Release(); + + Core::IWorkerPool::Assign(nullptr); + workerPool.Release(); + + LibnmWraps::setImpl(nullptr); + if (p_libnmWrapsImplMock != nullptr) + { + delete p_libnmWrapsImplMock; + p_libnmWrapsImplMock = nullptr; + } + } +}; + +TEST_F(NetworkManagerInitTest, platformInit) +{ + NetworkManagerLogger::SetLevel(static_cast(NetworkManagerLogger::DEBUG_LEVEL)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T(""), response)); + EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), _T("{\"interface\":\"wlan0\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"wlan0\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetHostname"), _T("{\"hostname\":\"test-host\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetLogLevel"), _T(""), response)); + EXPECT_EQ(response, _T("{\"level\":4,\"success\":true}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetSupportedSecurityModes"), _T(""), response)); + EXPECT_EQ(response, _T("{\"security\":{\"NONE\":0,\"WPA_PSK\":1,\"SAE\":2,\"EAP\":3},\"success\":true}")); +} \ No newline at end of file diff --git a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp new file mode 100644 index 000000000..6c7dd65fc --- /dev/null +++ b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp @@ -0,0 +1,1822 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "FactoriesImplementation.h" +#include "WrapsMock.h" +#include "LibnmWrapsMock.h" +#include "GLibWrapsMock.h" +#include "ServiceMock.h" +#include "ThunderPortability.h" +#include "COMLinkMock.h" +#include "WorkerPoolImplementation.h" +#include "NetworkManagerImplementation.h" +#include "NetworkManagerLogger.h" +#include "NetworkManager.h" +#include + +using namespace WPEFramework; +using ::testing::NiceMock; + +class NetworkManagerWifiTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + DECL_CORE_JSONRPC_CONX connection; + Core::JSONRPC::Message message; + string response; + NMClient* gNmClient = NULL; + + WrapsImplMock *p_wrapsImplMock = nullptr; + LibnmWrapsImplMock *p_libnmWrapsImplMock = nullptr; + GLibWrapsImplMock *p_gLibWrapsImplMock = nullptr; + Core::ProxyType NetworkManagerImpl; + + NiceMock comLinkMock; + NiceMock service; + PLUGINHOST_DISPATCHER* dispatcher; + Core::ProxyType workerPool; + NiceMock factoriesImplementation; + + NetworkManagerWifiTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , INIT_CONX(1, 0) + , workerPool(Core::ProxyType::Create(2, Core::Thread::DefaultStackSize(), 16)) + { + + p_libnmWrapsImplMock = new NiceMock ; + LibnmWraps::setImpl(p_libnmWrapsImplMock); + + p_gLibWrapsImplMock = new NiceMock ; + GLibWraps::setImpl(p_gLibWrapsImplMock); + + p_wrapsImplMock = new NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Invoke( + [this]() { + return &comLinkMock; + })); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return( + "{" + " \"locator\":\"libWPEFrameworkNetworkManager.so\"," + " \"classname\":\"NetworkManager\"," + " \"callsign\":\"org.rdk.NetworkManager\"," + " \"startuporder\":55," + " \"autostart\":false," + " \"configuration\":{" + " \"root\":{" + " \"outofprocess\":true," + " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" + " }," + " \"connectivity\":{" + " \"endpoint_1\":\"http://clients3.google.com/generate_204\"," + " \"interval\":60" + " }," + " \"stun\":{" + " \"endpoint\":\"stun.l.google.com\"," + " \"port\":19302," + " \"interval\":30" + " }," + " \"loglevel\":4" + " }" + "}" + )); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const RPC::Object& object, const uint32_t waitTime, uint32_t& connectionId) { + NetworkManagerImpl = Core::ProxyType::Create(); + return &NetworkManagerImpl; + })); + + PluginHost::IFactories::Assign(&factoriesImplementation); + + Core::IWorkerPool::Assign(&(*workerPool)); + workerPool->Run(); + + dispatcher = static_cast( + plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); + dispatcher->Activate(&service); + response = plugin->Initialize(&service); + EXPECT_EQ(string(""), response); + NetworkManagerLogger::SetLevel(static_cast(NetworkManagerLogger::DEBUG_LEVEL)); + usleep(1000); // wait for the plugin to initialize + } + + virtual void SetUp() override + { + struct stat buffer; + if (stat("/etc/device.properties", &buffer) != 0) { + std::ofstream file("/etc/device.properties"); + if (file.is_open()) { + file << "ETHERNET_INTERFACE=eth0\nWIFI_INTERFACE=wlan0\n"; + file.close(); + } + else { + std::cerr << "Failed to create /etc/device.properties file." << std::endl; + } + } + } + + virtual ~NetworkManagerWifiTest() override + { + plugin->Deinitialize(&service); + dispatcher->Deactivate(); + dispatcher->Release(); + + Core::IWorkerPool::Assign(nullptr); + workerPool.Release(); + + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + + LibnmWraps::setImpl(nullptr); + if (p_libnmWrapsImplMock != nullptr) + { + delete p_libnmWrapsImplMock; + p_libnmWrapsImplMock = nullptr; + } + + GLibWraps::setImpl(nullptr); + if (p_gLibWrapsImplMock != nullptr) + { + delete p_gLibWrapsImplMock; + p_gLibWrapsImplMock = nullptr; + } + } +}; + +TEST_F(NetworkManagerWifiTest, RegisteredMethods) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("SetLogLevel"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetLogLevel"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetAvailableInterfaces"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetPrimaryInterface"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetInterfaceState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("SetInterfaceState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetIPSettings"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("SetIPSettings"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("StartWiFiScan"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("StopWiFiScan"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetKnownSSIDs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("AddToKnownSSIDs"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("RemoveKnownSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("WiFiConnect"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("WiFiDisconnect"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetConnectedSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("StartWPS"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("StopWPS"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetWifiState"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetWiFiSignalQuality"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetSupportedSecurityModes"))); +} + +TEST_F(NetworkManagerWifiTest, get_wifi_device_devices_null) +{ + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiDisconnect"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerWifiTest, WiFiAlreadyDisconnected) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiDisconnect"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiAlreadyConnected_failed) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillOnce(::testing::Return(true)) + .WillOnce(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_disconnect_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDevice *device, GAsyncResult *result, GError **error) -> gboolean { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_CANCELLED, "WiFi scanning failed: %s", "Network interface is busy or unavailable"); + return FALSE; + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_disconnect_async(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDevice *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(device); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiDisconnect"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiAlreadyConnected_failed_errorCode) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillOnce(::testing::Return(true)) + .WillOnce(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_object_get_path(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("NULL"))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_disconnect_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDevice *device, GAsyncResult *result, GError **error) -> gboolean { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_CLOSED, "WiFi scanning failed: %s", "Network interface is busy or unavailable"); + return FALSE; + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_disconnect_async(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDevice *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(device); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiDisconnect"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiAlreadyConnected_success) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillOnce(::testing::Return(true)) + .WillOnce(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_disconnect_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_disconnect_async(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDevice *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(device); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiDisconnect"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetConnectedSSID_deviceError) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetConnectedSSID_ApNotConnected) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T(""), response)); + EXPECT_EQ(response, _T("{\"ssid\":\"\",\"bssid\":\"\",\"security\":0,\"strength\":\"\",\"frequency\":\"\",\"rate\":\"\",\"noise\":\"\",\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetConnectedSSID_ApNotNull) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_IP_CHECK)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetConnectedSSID_Connected_psk) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_IP_CHECK)); + + // Create a fake SSID GBytes object + const char* ssid_str = "TestWiFiNetwork"; + GBytes* fake_ssid = g_bytes_new_static(ssid_str, strlen(ssid_str)); + + // Setup the Access Point mock calls + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x833332))); + + // AP property mocks + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) + .WillOnce(::testing::Return(fake_ssid)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) + .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) + .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) + .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T(""), response)); + + // Update expected response to match the mock data + EXPECT_EQ(response, _T("{\"ssid\":\"TestWiFiNetwork\",\"bssid\":\"AA:BB:CC:DD:EE:FF\",\"security\":2,\"strength\":\"-39\",\"frequency\":\"2.462\",\"rate\":\"54000\",\"noise\":\"0\",\"success\":true}")); + + // Free the GBytes object + g_bytes_unref(fake_ssid); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetConnectedSSID_Connected_EAP) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_IP_CHECK)); + + // Create a fake SSID GBytes object + const char* ssid_str = "TestWiFiNetwork"; + GBytes* fake_ssid = g_bytes_new_static(ssid_str, strlen(ssid_str)); + + // Setup the Access Point mock calls + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x833332))); + + // AP property mocks + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_802_1X))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_802_1X))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) + .WillOnce(::testing::Return(fake_ssid)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) + .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) + .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) + .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T(""), response)); + + // Update expected response to match the mock data + EXPECT_EQ(response, _T("{\"ssid\":\"TestWiFiNetwork\",\"bssid\":\"AA:BB:CC:DD:EE:FF\",\"security\":3,\"strength\":\"-39\",\"frequency\":\"2.462\",\"rate\":\"54000\",\"noise\":\"0\",\"success\":true}")); + + // Free the GBytes object + g_bytes_unref(fake_ssid); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetConnectedSSID_Connected_ssidNull) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_IP_CHECK)); + + // Create a fake SSID GBytes object + const char* ssid_str = ""; + GBytes* fake_ssid = g_bytes_new_static(ssid_str, 0); + + // Setup the Access Point mock calls + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x833332))); + + // AP property mocks + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_NONE))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_NONE))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) + .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) + .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) + .WillOnce(::testing::Return(static_cast(20))); // 20% signal strength + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T(""), response)); + + // Update expected response to match the mock data + EXPECT_EQ(response, _T("{\"ssid\":\"\",\"bssid\":\"AA:BB:CC:DD:EE:FF\",\"security\":1,\"strength\":\"-78\",\"frequency\":\"2.462\",\"rate\":\"54000\",\"noise\":\"0\",\"success\":true}")); + + // Free the GBytes object + g_bytes_unref(fake_ssid); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetWifiState_Disconnect) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWifiState"), _T(""), response)); + EXPECT_EQ(response, _T("{\"state\":2,\"status\":\"WIFI_STATE_DISCONNECTED\",\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetWifiState_Connected) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWifiState"), _T(""), response)); + EXPECT_EQ(response, _T("{\"state\":5,\"status\":\"WIFI_STATE_CONNECTED\",\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetWifiState_Pairing) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_PREPARE)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_CONFIG)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWifiState"), _T(""), response)); + EXPECT_EQ(response, _T("{\"state\":3,\"status\":\"WIFI_STATE_PAIRING\",\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetWifiState_unknown) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_NEED_AUTH)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNKNOWN)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWifiState"), _T(""), response)); + EXPECT_EQ(response, _T("{\"state\":1,\"status\":\"WIFI_STATE_DISABLED\",\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetWifiState_Connecting) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_NEED_AUTH)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_IP_CONFIG)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWifiState"), _T(""), response)); + EXPECT_EQ(response, _T("{\"state\":4,\"status\":\"WIFI_STATE_CONNECTING\",\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetWifiState_Disabled) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWifiState"), _T(""), response)); + EXPECT_EQ(response, _T("{\"state\":1,\"status\":\"WIFI_STATE_DISABLED\",\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, StartWiFiScan_Failed) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, StartWiFiScan_with_SSIDList) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), _T("{\"ssid\":[\"Testssid_1\", \"Testssid_2\"]}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, StartWiFiScan_with_Frequency) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), _T("{\"frequency\":\"5\", \"ssids\":[\"Testssid_1\", \"Testssid_2\"]}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, StartWiFiScan_with_failed_with_error) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillOnce(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_request_scan_async(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDeviceWifi *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(device); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_request_scan_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDeviceWifi *device, GAsyncResult *result, GError **error) -> gboolean { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_FAILED, "WiFi scanning failed: %s", "Network interface is busy or unavailable"); + return FALSE; + })); + + // Execute the test + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + // Cleanup + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, StartWiFiScan_success) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); // Device must be active for scanning + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillOnce(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_request_scan_async(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDeviceWifi *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(device); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_request_scan_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDeviceWifi *device, GAsyncResult *result, GError **error) -> gboolean { + return true; + })); + + // Execute the test + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + // Cleanup + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, StartWiFiScan_with_option_success) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); // Device must be active for scanning + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillOnce(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_request_scan_options_async(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDeviceWifi *device, GVariant *options, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(device); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + } + )); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_request_scan_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMDeviceWifi *device, GAsyncResult *result, GError **error) -> gboolean { + return true; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), _T("{\"ssids\":[\"Testssid_1\"]}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiConnect_long_ssid) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA32\",\"passphrase\": \"123454321\",\"security\":1, \"persist\":false }"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed_device_null) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) + .WillRepeatedly(::testing::Return(static_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed_noconnection) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) + .WillRepeatedly(::testing::Return(deviceDummy)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_set_autoconnect(::testing::_,::testing::_)) + .WillOnce(::testing::Return()); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed_noconnection_null) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) + .WillRepeatedly(::testing::Return(deviceDummy)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_set_autoconnect(::testing::_,::testing::_)) + .WillOnce(::testing::Return()); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + // g_object_unref(conn); + g_ptr_array_free(dummyConns, TRUE); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed_noconnection_id) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn1 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn1); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) + .WillRepeatedly(::testing::Return(deviceDummy)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_set_autoconnect(::testing::_,::testing::_)) + .WillOnce(::testing::Return()); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + // g_object_unref(conn); + g_ptr_array_free(dummyConns, TRUE); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed_noconnection_type_null) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn1 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn1); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) + .WillRepeatedly(::testing::Return(deviceDummy)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_set_autoconnect(::testing::_,::testing::_)) + .WillOnce(::testing::Return()); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return("TestConnection")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + // g_object_unref(conn); + g_ptr_array_free(dummyConns, TRUE); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn1 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn1); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) + .WillRepeatedly(::testing::Return(deviceDummy)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_set_autoconnect(::testing::_,::testing::_)) + .WillOnce(::testing::Return()); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return("TestConnection")) + .WillOnce(::testing::Return("TestConnection")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_connection_type(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("802-11-wireless"))); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_activate_connection_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GAsyncResult *result, GError **error) -> NMActiveConnection* { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_FAILED, "connection activation failed %s", "Network interface is busy or unavailable"); + return reinterpret_cast(NULL); + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_activate_connection_async(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient* client, NMConnection* connection, NMDevice* device, const char* specific_object, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(client); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_object_unref(conn1); + g_ptr_array_free(dummyConns, TRUE); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_success) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn1 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn1); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) + .WillRepeatedly(::testing::Return(deviceDummy)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_set_autoconnect(::testing::_,::testing::_)) + .WillOnce(::testing::Return()); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return("TestConnection")) + .WillOnce(::testing::Return("TestConnection")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_connection_type(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("802-11-wireless"))); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_activate_connection_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(dummyActiveConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_activate_connection_async(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient* client, NMConnection* connection, NMDevice* device, const char* specific_object, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(client); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(deviceDummy); + g_object_unref(conn1); + g_ptr_array_free(dummyConns, TRUE); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiConnect_with_same_ssid) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) + .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); + + // Setup the Access Point mock calls + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x333223))); + + const char* ssid_str = "TestWiFiNetwork"; + GBytes* fake_ssid = g_bytes_new_static(ssid_str, strlen(ssid_str)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) + .WillOnce(::testing::Return(fake_ssid)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork\",\"passphrase\": \"123454321\",\"security\":1, \"persist\":false}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_bytes_unref(fake_ssid); + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiConnect_with_Ap_list_null) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) + .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); + + // Setup the Access Point mock calls + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x333223))); + + const char* ssid_str = "TestWiFiNetwork_1"; + GBytes* fake_ssid = g_bytes_new_static(ssid_str, strlen(ssid_str)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) + .WillOnce(::testing::Return(fake_ssid)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_access_points(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + // GPtrArray* fakeAccessPoints = g_ptr_array_new(); + // g_ptr_array_add(fakeAccessPoints, reinterpret_cast(NULL)); + + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork_0\",\"passphrase\": \"123454321\",\"security\":1, \"persist\":false}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_bytes_unref(fake_ssid); + g_object_unref(deviceDummy); + //g_ptr_array_free(fakeAccessPoints, TRUE); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiConnect_with_no_access_point) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) + .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x333223))); + + const char* ssid_str = "TestWiFiNetwork_1"; + GBytes* fake_ssid1 = g_bytes_new_static(ssid_str, strlen(ssid_str)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) + .WillRepeatedly(::testing::Return(fake_ssid1)); + + GPtrArray* fakeAccessPoints = g_ptr_array_new(); + g_ptr_array_add(fakeAccessPoints, reinterpret_cast(NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_access_points(::testing::_)) + .WillOnce(::testing::Return(fakeAccessPoints)); + + // // TODO MOck addToKnownSSIDs call + // EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + // .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork_2\",\"passphrase\": \"123454321\",\"security\":1, \"persist\":false}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_bytes_unref(fake_ssid1); + g_object_unref(deviceDummy); + g_ptr_array_free(fakeAccessPoints, TRUE); + g_ptr_array_free(fakeDevices, TRUE); +} +/* +TEST_F(NetworkManagerWifiTest, WiFiConnect_with_different_ssid) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) + .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x333223))); + + const char* ssid_str = "TestWiFiNetwork_1"; + GBytes* fake_ssid1 = g_bytes_new_static(ssid_str, strlen(ssid_str)); + const char* ssid_str2 = "TestWiFiNetwork_2"; + GBytes* fake_ssid2 = g_bytes_new_static(ssid_str2, strlen(ssid_str2)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) + .WillOnce(::testing::Return(fake_ssid1)) + .WillOnce(::testing::Return(fake_ssid2)); + + GPtrArray* fakeAccessPoints = g_ptr_array_new(); + g_ptr_array_add(fakeAccessPoints, reinterpret_cast(NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_access_points(::testing::_)) + .WillOnce(::testing::Return(fakeAccessPoints)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork_2\",\"passphrase\": \"123454321\",\"security\":1, \"persist\":false}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_bytes_unref(fake_ssid1); + g_bytes_unref(fake_ssid2); + g_object_unref(deviceDummy); + g_ptr_array_free(fakeAccessPoints, TRUE); + g_ptr_array_free(fakeDevices, TRUE); +} +*/ +TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_deviceFailed) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("AddToKnownSSIDs"), _T("{ \"ssid\":\"test\",\"passphrase\": \"123454321\",\"security\":1, \"persist\":false }"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_SmallPssword) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("AddToKnownSSIDs"), _T("{ \"ssid\":\"test\",\"passphrase\": \"12345\",\"security\":1, \"persist\":false }"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_sae_failed) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_add_connection2_finish(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GAsyncResult *result, GVariant **out_result, GError **error) -> NMRemoteConnection* { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_FAILED, "add connection activation failed %s", "Network interface is busy or unavailable"); + return reinterpret_cast(NULL); + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_add_connection2(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, GVariant *args, gboolean ignore_out_result, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(client); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("AddToKnownSSIDs"), _T("{ \"ssid\":\"test\",\"passphrase\": \"5454543343\",\"security\":2, \"persist\":false }"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_sae_success) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_add_connection2_finish(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GAsyncResult *result, GVariant **out_result, GError **error) -> NMRemoteConnection* { + return reinterpret_cast(0x22222); + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_add_connection2(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, GVariant *args, gboolean ignore_out_result, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(client); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("AddToKnownSSIDs"), + _T("{" + " \"ssid\":\"test\"," + "\"passphrase\": \"5454543343\"," + "\"security\":2," + " \"persist\":false" + " }"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_eap_success) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_add_connection2_finish(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GAsyncResult *result, GVariant **out_result, GError **error) -> NMRemoteConnection* { + return reinterpret_cast(0x22222); + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_add_connection2(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, GVariant *args, gboolean ignore_out_result, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(client); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("AddToKnownSSIDs"), + _T("{" + " \"ssid\":\"TestNetwork\"," + "\"passphrase\":\"TestPassword\"," + "\"security\":3," + "\"ca_cert\":\"test_ca_cert\"," + "\"client_cert\":\"test_client_cert\"," + "\"private_key\":\"test_private_key\"," + "\"private_key_passwd\":\"test_private_key_passwd\"," + "\"eap\":\"test_eap\"," + "\"eap_identity\":\"test_eap_identity\"," + "\"eap_password\":\"test_eap_password\"," + "\"eap_phase1\":\"test_eap_phase1\"," + "\"eap_phase2\":\"test_eap_phase2\"," + "\"persist\":true" + " }"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetKnownSSIDs_connectionFailed) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillRepeatedly(::testing::Return(nullptr)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetKnownSSIDs"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, GetKnownSSIDs_success) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn1 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn1); + NMSettingWireless* settingWireless = reinterpret_cast(g_object_new(NM_TYPE_SETTING_WIRELESS, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_wireless(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(settingWireless))) + .WillOnce(::testing::Return(reinterpret_cast(settingWireless))); + + const char* ssid_str = "TestWiFiNetwork"; + GBytes* fake_ssid = g_bytes_new_static(ssid_str, strlen(ssid_str)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_wireless_get_ssid(::testing::_)) + .WillOnce(::testing::Return(fake_ssid)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetKnownSSIDs"), _T(""), response)); + EXPECT_EQ(response, _T("{\"ssids\":[\"TestWiFiNetwork\"],\"success\":true}")); + + g_object_unref(deviceDummy); + g_object_unref(settingWireless); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, RemoveKnownSSIDs) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillRepeatedly(::testing::Return(nullptr)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("RemoveKnownSSID"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, RemoveKnownSSIDs_success_false) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn1 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn1); + NMSettingWireless* settingWireless = reinterpret_cast(g_object_new(NM_TYPE_SETTING_WIRELESS, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_wireless(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(settingWireless))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("Test_wifi"))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_delete(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMRemoteConnection *connection, GCancellable *cancellable, GError **error) -> gboolean { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_FAILED, "connection delete failed"); + return FALSE; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("RemoveKnownSSID"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, RemoveKnownSSIDs_success_true) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn1 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn1); + NMSettingWireless* settingWireless = reinterpret_cast(g_object_new(NM_TYPE_SETTING_WIRELESS, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_wireless(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(settingWireless))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("Test_wifi"))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_delete(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMRemoteConnection *connection, GCancellable *cancellable, GError **error) -> gboolean { + return TRUE; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("RemoveKnownSSID"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, RemoveKnownSSIDs_conn_id_null) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn1 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn1); + NMSettingWireless* settingWireless = reinterpret_cast(g_object_new(NM_TYPE_SETTING_WIRELESS, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_wireless(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(settingWireless))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("RemoveKnownSSID"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, RemoveKnownSSIDs_success_ssid_specified_not_found) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn1 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn1); + NMSettingWireless* settingWireless = reinterpret_cast(g_object_new(NM_TYPE_SETTING_WIRELESS, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_wireless(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(settingWireless))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("Test_wifi"))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("RemoveKnownSSID"), + _T("{\"ssid\":\"TestNetwork\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, RemoveKnownSSIDs_success_ssid_specified_found) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn1 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn1); + NMSettingWireless* settingWireless = reinterpret_cast(g_object_new(NM_TYPE_SETTING_WIRELESS, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_wireless(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(settingWireless))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("TestNetwork"))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_delete(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMRemoteConnection *connection, GCancellable *cancellable, GError **error) -> gboolean { + return TRUE; + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("RemoveKnownSSID"), + _T("{\"ssid\":\"TestNetwork\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, StopWPS) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StopWPS"), + _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); +} + +TEST_F(NetworkManagerWifiTest, StartWPS) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWPS"), + _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWPS"), + _T(""), response)); +} diff --git a/tests/l2Test/rdk/CMakeLists.txt b/tests/l2Test/rdk/CMakeLists.txt new file mode 100644 index 000000000..bcc895956 --- /dev/null +++ b/tests/l2Test/rdk/CMakeLists.txt @@ -0,0 +1,77 @@ +############################################################################# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2024 RDK Management +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################# +message ("building rdk proxy l2 test") +set(NM_RDK_PROXY_L2_TEST "rdkproxy_l2_test") + +find_package(CURL) +find_package(PkgConfig REQUIRED) +find_package(${NAMESPACE}Core REQUIRED) +find_package(${NAMESPACE}Plugins REQUIRED) + +add_executable(${NM_RDK_PROXY_L2_TEST} + ${CMAKE_SOURCE_DIR}/tests/l2Test/rdk/l2_test_rdkproxy.cpp + ${CMAKE_SOURCE_DIR}/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp + ${CMAKE_SOURCE_DIR}/tests/l2Test/rdk/l2_test_rdkproxyImpl.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/Wraps.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerJsonRpc.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerImplementation.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp + ${CMAKE_SOURCE_DIR}/plugin/rdk/NetworkManagerRDKProxy.cpp + ${PROXY_STUB_SOURCES} +) + +set_target_properties(${NM_RDK_PROXY_L2_TEST} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES +) + +target_compile_options(${NM_RDK_PROXY_L2_TEST} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) + +include_directories(${PROJECT_SOURCE_DIR}/interface) +include_directories(${PROJECT_SOURCE_DIR}/plugin/rdk) +include_directories(${PROJECT_SOURCE_DIR}/plugin) +include_directories(${PROJECT_SOURCE_DIR}/legacy) +include_directories(${PROJECT_SOURCE_DIR}/tests/mocks) +include_directories(${PROJECT_SOURCE_DIR}/tests/mocks/thunder) +include_directories(${PROJECT_SOURCE_DIR}/../install/usr/include/rdk/iarmbus/) +include_directories(${PROJECT_SOURCE_DIR}/tools/upnp/) + +target_include_directories(${NM_RDK_PROXY_L2_TEST} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${gtest_SOURCE_DIR}/include + ${gtest_SOURCE_DIR}/../googlemock/include +) + +target_link_options(${NM_RDK_PROXY_L2_TEST} PRIVATE -Wl,-wrap,system -Wl,-wrap,popen -Wl,-wrap,syslog -Wl,-wrap,pclose -Wl,-wrap,getmntent -Wl,-wrap,setmntent -Wl,-wrap,v_secure_popen -Wl,-wrap,v_secure_pclose -Wl,-wrap,v_secure_system) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") + +target_link_libraries(${NM_RDK_PROXY_L2_TEST} PRIVATE + gmock_main + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}Plugins::${NAMESPACE}Plugins + ${CURL_LIBRARIES} +) + +install(TARGETS ${NM_RDK_PROXY_L2_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/l2Test/l2_test_rdkproxy.cpp b/tests/l2Test/rdk/l2_test_rdkproxy.cpp similarity index 100% rename from tests/l2Test/l2_test_rdkproxy.cpp rename to tests/l2Test/rdk/l2_test_rdkproxy.cpp diff --git a/tests/l2Test/l2_test_rdkproxyEvent.cpp b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp similarity index 100% rename from tests/l2Test/l2_test_rdkproxyEvent.cpp rename to tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp diff --git a/tests/l2Test/l2_test_rdkproxyImpl.cpp b/tests/l2Test/rdk/l2_test_rdkproxyImpl.cpp similarity index 100% rename from tests/l2Test/l2_test_rdkproxyImpl.cpp rename to tests/l2Test/rdk/l2_test_rdkproxyImpl.cpp diff --git a/tests/mocks/GLibWraps.cpp b/tests/mocks/GLibWraps.cpp new file mode 100644 index 000000000..ba6a2f15f --- /dev/null +++ b/tests/mocks/GLibWraps.cpp @@ -0,0 +1,30 @@ +#include "GLibWraps.h" +#include + +// // Define the real function to ensure it exists for the wrapper to call +// extern "C" gboolean __real_g_main_loop_is_running(GMainLoop* loop) { +// // Default implementation if the real function can't be called +// return FALSE; +// } + +extern "C" gboolean __wrap_g_main_loop_is_running(GMainLoop* loop) { + return GLibWraps::getInstance().g_main_loop_is_running(loop); +} + +GLibWrapsImpl* GLibWraps::impl = nullptr; +GLibWraps::GLibWraps() {} + +void GLibWraps::setImpl(GLibWrapsImpl* newImpl) { + EXPECT_TRUE((nullptr == impl) || (nullptr == newImpl)); + impl = newImpl; +} + +GLibWraps& GLibWraps::getInstance() { + static GLibWraps instance; + return instance; +} + +gboolean GLibWraps::g_main_loop_is_running(GMainLoop* loop) { + EXPECT_NE(impl, nullptr); + return impl->g_main_loop_is_running(loop); +} diff --git a/tests/mocks/GLibWraps.h b/tests/mocks/GLibWraps.h new file mode 100644 index 000000000..a7d42ad3f --- /dev/null +++ b/tests/mocks/GLibWraps.h @@ -0,0 +1,25 @@ +#pragma once + +#include +// #include +#include + +class GLibWrapsImpl { +public: + virtual ~GLibWrapsImpl() = default; + + virtual gboolean g_main_loop_is_running(GMainLoop* loop) = 0; +}; + +class GLibWraps { +protected: + static GLibWrapsImpl* impl; + +public: + GLibWraps(); + GLibWraps(const GLibWraps &obj) = delete; + static void setImpl(GLibWrapsImpl* newImpl); + static GLibWraps& getInstance(); + + static gboolean g_main_loop_is_running(GMainLoop* loop); +}; diff --git a/tests/mocks/GLibWrapsMock.h b/tests/mocks/GLibWrapsMock.h new file mode 100644 index 000000000..3e413b54d --- /dev/null +++ b/tests/mocks/GLibWrapsMock.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include "GLibWraps.h" + +extern "C" gboolean __real_g_main_loop_is_running(GMainLoop* loop); + +class GLibWrapsImplMock : public GLibWrapsImpl { +public: + GLibWrapsImplMock() : GLibWrapsImpl() { + ON_CALL(*this, g_main_loop_is_running(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](GMainLoop* loop) -> gboolean { + return __real_g_main_loop_is_running(loop); + })); + } + + virtual ~GLibWrapsImplMock() = default; + + // Mock methods + MOCK_METHOD(gboolean, g_main_loop_is_running, (GMainLoop* loop), (override)); +}; diff --git a/tests/mocks/LibnmWraps.cpp b/tests/mocks/LibnmWraps.cpp new file mode 100644 index 000000000..afd36f734 --- /dev/null +++ b/tests/mocks/LibnmWraps.cpp @@ -0,0 +1,641 @@ +#include "LibnmWraps.h" +#include +#include + +extern "C" gint64 __wrap_nm_device_wifi_get_last_scan(NMDeviceWifi *device) { + return LibnmWraps::getInstance().nm_device_wifi_get_last_scan(device); +} + +extern "C" void __wrap_nm_device_set_autoconnect(NMDevice *device, gboolean autoconnect) { + LibnmWraps::getInstance().nm_device_set_autoconnect(device, autoconnect); +} +extern "C" const GPtrArray* __wrap_nm_client_get_connections(NMClient *client) { + return LibnmWraps::getInstance().nm_client_get_connections(client); +} +extern "C" const char* __wrap_nm_connection_get_id(NMConnection *connection) { + return LibnmWraps::getInstance().nm_connection_get_id(connection); +} +extern "C" const char* __wrap_nm_connection_get_connection_type(NMConnection *connection) { + return LibnmWraps::getInstance().nm_connection_get_connection_type(connection); +} + +extern "C" void __wrap_nm_client_activate_connection_async(NMClient *client, NMConnection *connection, NMDevice *device, const char *specific_object, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + LibnmWraps::getInstance().nm_client_activate_connection_async(client, connection, device, specific_object, cancellable, callback, user_data); +} + +extern "C" NMActiveConnection* __wrap_nm_client_activate_connection_finish(NMClient *client, GAsyncResult *result, GError **error) { + return LibnmWraps::getInstance().nm_client_activate_connection_finish(client, result, error); +} + +extern "C" void __wrap_nm_client_add_and_activate_connection_async(NMClient *client, NMConnection *partial, NMDevice *device, const char *specific_object, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + LibnmWraps::getInstance().nm_client_add_and_activate_connection_async(client, partial, device, specific_object, cancellable, callback, user_data); +} + +extern "C" NMActiveConnection* __wrap_nm_client_add_and_activate_connection_finish(NMClient *client, GAsyncResult *result, GError **error) { + return LibnmWraps::getInstance().nm_client_add_and_activate_connection_finish(client, result, error); +} + +extern "C" GVariant* __wrap_nm_remote_connection_update2_finish(NMRemoteConnection *connection, GAsyncResult *result, GError **error) { + return LibnmWraps::getInstance().nm_remote_connection_update2_finish(connection, result, error); +} + +extern "C" void __wrap_nm_client_add_connection2(NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, GVariant *args, gboolean ignore_out_result, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + LibnmWraps::getInstance().nm_client_add_connection2(client, settings, flags, args, ignore_out_result, cancellable, callback, user_data); +} + +extern "C" NMRemoteConnection* __wrap_nm_client_add_connection2_finish(NMClient *client, GAsyncResult *result, GVariant **out_result, GError **error) { + return LibnmWraps::getInstance().nm_client_add_connection2_finish(client, result, out_result, error); +} + +extern "C" const char* __wrap_nm_device_get_hw_address(NMDevice* device) { + return LibnmWraps::getInstance().nm_device_get_hw_address(device); +} + +extern "C" NMClient* __wrap_nm_client_new(GCancellable* cancellable, GError** error) { + return LibnmWraps::getInstance().nm_client_new(cancellable, error); +} + +extern "C" const char* __wrap_nm_device_get_iface(NMDevice* device) { + return LibnmWraps::getInstance().nm_device_get_iface(device); +} + +extern "C" NMActiveConnection* __wrap_nm_client_get_primary_connection(NMClient *client) { + return LibnmWraps::getInstance().nm_client_get_primary_connection(client); +} + +extern "C" NMActiveConnection* __wrap_nm_device_get_active_connection(NMDevice *device) { + return LibnmWraps::getInstance().nm_device_get_active_connection(device); +} + +extern "C" NMRemoteConnection* __wrap_nm_active_connection_get_connection(NMActiveConnection *connection) { + return LibnmWraps::getInstance().nm_active_connection_get_connection(connection); +} + +extern "C" const char* __wrap_nm_connection_get_interface_name(NMRemoteConnection *connection) { + return LibnmWraps::getInstance().nm_connection_get_interface_name(connection); +} + +extern "C" NMDevice* __wrap_nm_client_get_device_by_iface(NMClient *client, const char *iface) { + return LibnmWraps::getInstance().nm_client_get_device_by_iface(client, iface); +} + +extern "C" NMDeviceState __wrap_nm_device_get_state(NMDevice *device) { + return LibnmWraps::getInstance().nm_device_get_state(device); +} + +extern "C" void __wrap_nm_device_disconnect_async(NMDevice *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + LibnmWraps::getInstance().nm_device_disconnect_async(device, cancellable, callback, user_data); +} + +extern "C" gboolean __wrap_nm_device_disconnect_finish(NMDevice *device, GAsyncResult *result, GError **error) { + return LibnmWraps::getInstance().nm_device_disconnect_finish(device, result, error); +} + +extern "C" const GPtrArray* __wrap_nm_client_get_devices(NMClient* client) { + return LibnmWraps::getInstance().nm_client_get_devices(client); +} + +extern "C" const GPtrArray* __wrap_nm_client_get_active_connections(NMClient* client) { + return LibnmWraps::getInstance().nm_client_get_active_connections(client); +} + +extern "C" NMSettingIPConfig* __wrap_nm_connection_get_setting_ip4_config(NMConnection* connection) { + return LibnmWraps::getInstance().nm_connection_get_setting_ip4_config(connection); +} + +extern "C" NMSettingIPConfig* __wrap_nm_connection_get_setting_ip6_config(NMConnection* connection) { + return LibnmWraps::getInstance().nm_connection_get_setting_ip6_config(connection); +} + +extern "C" const char* __wrap_nm_setting_ip_config_get_method(NMSettingIPConfig* setting) { + return LibnmWraps::getInstance().nm_setting_ip_config_get_method(setting); +} + +extern "C" NMSettingConnection* __wrap_nm_connection_get_setting_connection(NMConnection* connection) { + return LibnmWraps::getInstance().nm_connection_get_setting_connection(connection); +} + +extern "C" const char* __wrap_nm_setting_connection_get_interface_name(NMSettingConnection* setting) { + return LibnmWraps::getInstance().nm_setting_connection_get_interface_name(setting); +} + +extern "C" NMIPConfig* __wrap_nm_active_connection_get_ip4_config(NMActiveConnection* connection) { + return LibnmWraps::getInstance().nm_active_connection_get_ip4_config(connection); +} + +extern "C" NMIPConfig* __wrap_nm_active_connection_get_ip6_config(NMActiveConnection* connection) { + return LibnmWraps::getInstance().nm_active_connection_get_ip6_config(connection); +} + +extern "C" GPtrArray* __wrap_nm_ip_config_get_addresses(NMIPConfig* config) { + return LibnmWraps::getInstance().nm_ip_config_get_addresses(config); +} + +extern "C" const char* __wrap_nm_ip_address_get_address(NMIPAddress* address) { + return LibnmWraps::getInstance().nm_ip_address_get_address(address); +} + +extern "C" guint __wrap_nm_ip_address_get_prefix(NMIPAddress* address) { + return LibnmWraps::getInstance().nm_ip_address_get_prefix(address); +} + +extern "C" const char* __wrap_nm_ip_config_get_gateway(NMIPConfig* config) { + return LibnmWraps::getInstance().nm_ip_config_get_gateway(config); +} + +extern "C" const char* const* __wrap_nm_ip_config_get_nameservers(NMIPConfig* config) { + return LibnmWraps::getInstance().nm_ip_config_get_nameservers(config); +} + +extern "C" NMDhcpConfig* __wrap_nm_active_connection_get_dhcp4_config(NMActiveConnection* connection) { + return LibnmWraps::getInstance().nm_active_connection_get_dhcp4_config(connection); +} + +extern "C" NMDhcpConfig* __wrap_nm_active_connection_get_dhcp6_config(NMActiveConnection* connection) { + return LibnmWraps::getInstance().nm_active_connection_get_dhcp6_config(connection); +} + +extern "C" const char* __wrap_nm_dhcp_config_get_one_option(NMDhcpConfig* config, const char* option) { + return LibnmWraps::getInstance().nm_dhcp_config_get_one_option(config, option); +} + +// Access Point API wrappers +extern "C" NM80211ApFlags __wrap_nm_access_point_get_flags(NMAccessPoint *ap) { + return LibnmWraps::getInstance().nm_access_point_get_flags(ap); +} + +extern "C" NM80211ApSecurityFlags __wrap_nm_access_point_get_wpa_flags(NMAccessPoint *ap) { + return LibnmWraps::getInstance().nm_access_point_get_wpa_flags(ap); +} + +extern "C" NM80211ApSecurityFlags __wrap_nm_access_point_get_rsn_flags(NMAccessPoint *ap) { + return LibnmWraps::getInstance().nm_access_point_get_rsn_flags(ap); +} + +extern "C" GBytes* __wrap_nm_access_point_get_ssid(NMAccessPoint *ap) { + return LibnmWraps::getInstance().nm_access_point_get_ssid(ap); +} + +extern "C" const char* __wrap_nm_access_point_get_bssid(NMAccessPoint *ap) { + return LibnmWraps::getInstance().nm_access_point_get_bssid(ap); +} + +extern "C" guint32 __wrap_nm_access_point_get_frequency(NMAccessPoint *ap) { + return LibnmWraps::getInstance().nm_access_point_get_frequency(ap); +} + +extern "C" NM80211Mode __wrap_nm_access_point_get_mode(NMAccessPoint *ap) { + return LibnmWraps::getInstance().nm_access_point_get_mode(ap); +} + +extern "C" guint32 __wrap_nm_access_point_get_max_bitrate(NMAccessPoint *ap) { + return LibnmWraps::getInstance().nm_access_point_get_max_bitrate(ap); +} + +extern "C" guint8 __wrap_nm_access_point_get_strength(NMAccessPoint *ap) { + return LibnmWraps::getInstance().nm_access_point_get_strength(ap); +} + +extern "C" NMAccessPoint* __wrap_nm_device_wifi_get_active_access_point(NMDeviceWifi *device) { + return LibnmWraps::getInstance().nm_device_wifi_get_active_access_point(device); +} + +extern "C" const GPtrArray* __wrap_nm_device_wifi_get_access_points(NMDeviceWifi *device) { + return LibnmWraps::getInstance().nm_device_wifi_get_access_points(device); +} + +extern "C" const GPtrArray* __wrap_nm_device_get_available_connections(NMDevice *device) { + return LibnmWraps::getInstance().nm_device_get_available_connections(device); +} + +extern "C" const char* __wrap_nm_object_get_path(NMObject *object) { + return LibnmWraps::getInstance().nm_object_get_path(object); +} + +extern "C" void __wrap_nm_client_dbus_set_property(NMClient *client, + const char *object_path, + const char *interface_name, + const char *property_name, + GVariant *value, + int timeout_msec, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { + LibnmWraps::getInstance().nm_client_dbus_set_property(client, object_path, interface_name, property_name, value, timeout_msec, cancellable, callback, user_data); +} + +extern "C" gboolean __wrap_nm_client_dbus_set_property_finish(NMClient *client, + GAsyncResult *result, + GError **error) { + return LibnmWraps::getInstance().nm_client_dbus_set_property_finish(client, result, error); +} + +// New wrapper functions for commit changes and DHCP hostname +extern "C" gboolean __wrap_nm_remote_connection_commit_changes(NMRemoteConnection *connection, + gboolean save_to_disk, + GCancellable *cancellable, + GError **error) { + return LibnmWraps::getInstance().nm_remote_connection_commit_changes(connection, save_to_disk, cancellable, error); +} + +extern "C" const char* __wrap_nm_setting_ip_config_get_dhcp_hostname(NMSettingIPConfig *setting) { + return LibnmWraps::getInstance().nm_setting_ip_config_get_dhcp_hostname(setting); +} + +extern "C" gboolean __wrap_nm_setting_ip_config_get_dhcp_send_hostname(NMSettingIPConfig *setting) { + return LibnmWraps::getInstance().nm_setting_ip_config_get_dhcp_send_hostname(setting); +} + +extern "C" void __wrap_nm_connection_add_setting(NMConnection *connection, NMSetting *setting) { + LibnmWraps::getInstance().nm_connection_add_setting(connection, setting); +} + +extern "C" NMSettingWireless* __wrap_nm_connection_get_setting_wireless(NMConnection *connection) { + return LibnmWraps::getInstance().nm_connection_get_setting_wireless(connection); +} + +extern "C" GBytes* __wrap_nm_setting_wireless_get_ssid(NMSettingWireless *setting) { + return LibnmWraps::getInstance().nm_setting_wireless_get_ssid(setting); +} + +extern "C" gboolean __wrap_nm_remote_connection_delete(NMRemoteConnection *connection, GCancellable *cancellable, GError **error) { + return LibnmWraps::getInstance().nm_remote_connection_delete(connection, cancellable, error); +} + +// WiFi Scan API wrappers +extern "C" void __wrap_nm_device_wifi_request_scan_async(NMDeviceWifi *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { + LibnmWraps::getInstance().nm_device_wifi_request_scan_async(device, cancellable, callback, user_data); +} + +extern "C" void __wrap_nm_device_wifi_request_scan_options_async(NMDeviceWifi *device, + GVariant *options, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { + LibnmWraps::getInstance().nm_device_wifi_request_scan_options_async(device, options, cancellable, callback, user_data); +} + +extern "C" gboolean __wrap_nm_device_wifi_request_scan_finish(NMDeviceWifi *device, + GAsyncResult *result, + GError **error) { + return LibnmWraps::getInstance().nm_device_wifi_request_scan_finish(device, result, error); +} + +LibnmWrapsImpl* LibnmWraps::impl = nullptr; +LibnmWraps::LibnmWraps() {} + +void LibnmWraps::setImpl(LibnmWrapsImpl* newImpl) { + EXPECT_TRUE((nullptr == impl) || (nullptr == newImpl)); + impl = newImpl; +} + +LibnmWraps& LibnmWraps::getInstance() { + static LibnmWraps instance; + return instance; +} + +const char* LibnmWraps::nm_device_get_iface(NMDevice* device) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_get_iface(device); +} + +NMActiveConnection* LibnmWraps::nm_client_get_primary_connection(NMClient *client) { + EXPECT_NE(impl, nullptr); + return impl->nm_client_get_primary_connection(client); +} + +NMActiveConnection* LibnmWraps::nm_device_get_active_connection(NMDevice *device) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_get_active_connection(device); +} + +NMRemoteConnection* LibnmWraps::nm_active_connection_get_connection(NMActiveConnection *connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_active_connection_get_connection(connection); +} + +const char* LibnmWraps::nm_connection_get_interface_name(NMRemoteConnection *connection) { // Changed to NMRemoteConnection* + EXPECT_NE(impl, nullptr); + return impl->nm_connection_get_interface_name(connection); +} + +NMDevice* LibnmWraps::nm_client_get_device_by_iface(NMClient *client, const char *iface) { + EXPECT_NE(impl, nullptr); + return impl->nm_client_get_device_by_iface(client, iface); +} + +NMDeviceState LibnmWraps::nm_device_get_state(NMDevice *device) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_get_state(device); +} + +void LibnmWraps::nm_device_disconnect_async(NMDevice *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + EXPECT_NE(impl, nullptr); + impl->nm_device_disconnect_async(device, cancellable, callback, user_data); +} + +gboolean LibnmWraps::nm_device_disconnect_finish(NMDevice *device, GAsyncResult *result, GError **error) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_disconnect_finish(device, result, error); +} + +const GPtrArray* LibnmWraps::nm_client_get_devices(NMClient* client) { + EXPECT_NE(impl, nullptr); + return impl->nm_client_get_devices(client); +} + +const GPtrArray* LibnmWraps::nm_client_get_active_connections(NMClient* client) { + EXPECT_NE(impl, nullptr); + return impl->nm_client_get_active_connections(client); +} + +NMClient* LibnmWraps::nm_client_new(GCancellable* cancellable, GError** error) { + EXPECT_NE(impl, nullptr); + return impl->nm_client_new(cancellable, error); +} + +const char* LibnmWraps::nm_device_get_hw_address(NMDevice* device) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_get_hw_address(device); +} + +NMSettingIPConfig* LibnmWraps::nm_connection_get_setting_ip4_config(NMConnection* connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_connection_get_setting_ip4_config(connection); +} + +NMSettingIPConfig* LibnmWraps::nm_connection_get_setting_ip6_config(NMConnection* connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_connection_get_setting_ip6_config(connection); +} + +const char* LibnmWraps::nm_setting_ip_config_get_method(NMSettingIPConfig* setting) { + EXPECT_NE(impl, nullptr); + return impl->nm_setting_ip_config_get_method(setting); +} + +NMSettingConnection* LibnmWraps::nm_connection_get_setting_connection(NMConnection* connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_connection_get_setting_connection(connection); +} + +const char* LibnmWraps::nm_setting_connection_get_interface_name(NMSettingConnection* setting) { + EXPECT_NE(impl, nullptr); + return impl->nm_setting_connection_get_interface_name(setting); +} + +NMIPConfig* LibnmWraps::nm_active_connection_get_ip4_config(NMActiveConnection* connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_active_connection_get_ip4_config(connection); +} + +NMIPConfig* LibnmWraps::nm_active_connection_get_ip6_config(NMActiveConnection* connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_active_connection_get_ip6_config(connection); +} + +GPtrArray* LibnmWraps::nm_ip_config_get_addresses(NMIPConfig* config) { + EXPECT_NE(impl, nullptr); + return impl->nm_ip_config_get_addresses(config); +} + +const char* LibnmWraps::nm_ip_address_get_address(NMIPAddress* address) { + EXPECT_NE(impl, nullptr); + return impl->nm_ip_address_get_address(address); +} + +guint LibnmWraps::nm_ip_address_get_prefix(NMIPAddress* address) { + EXPECT_NE(impl, nullptr); + return impl->nm_ip_address_get_prefix(address); +} + +const char* LibnmWraps::nm_ip_config_get_gateway(NMIPConfig* config) { + EXPECT_NE(impl, nullptr); + return impl->nm_ip_config_get_gateway(config); +} + +const char* const* LibnmWraps::nm_ip_config_get_nameservers(NMIPConfig* config) { + EXPECT_NE(impl, nullptr); + return impl->nm_ip_config_get_nameservers(config); +} + +NMDhcpConfig* LibnmWraps::nm_active_connection_get_dhcp4_config(NMActiveConnection* connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_active_connection_get_dhcp4_config(connection); +} + +NMDhcpConfig* LibnmWraps::nm_active_connection_get_dhcp6_config(NMActiveConnection* connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_active_connection_get_dhcp6_config(connection); +} + +const char* LibnmWraps::nm_dhcp_config_get_one_option(NMDhcpConfig* config, const char* option) { + EXPECT_NE(impl, nullptr); + return impl->nm_dhcp_config_get_one_option(config, option); +} + +// Access Point API implementation +NM80211ApFlags LibnmWraps::nm_access_point_get_flags(NMAccessPoint *ap) { + EXPECT_NE(impl, nullptr); + return impl->nm_access_point_get_flags(ap); +} + +NM80211ApSecurityFlags LibnmWraps::nm_access_point_get_wpa_flags(NMAccessPoint *ap) { + EXPECT_NE(impl, nullptr); + return impl->nm_access_point_get_wpa_flags(ap); +} + +NM80211ApSecurityFlags LibnmWraps::nm_access_point_get_rsn_flags(NMAccessPoint *ap) { + EXPECT_NE(impl, nullptr); + return impl->nm_access_point_get_rsn_flags(ap); +} + +GBytes* LibnmWraps::nm_access_point_get_ssid(NMAccessPoint *ap) { + EXPECT_NE(impl, nullptr); + return impl->nm_access_point_get_ssid(ap); +} + +const char* LibnmWraps::nm_access_point_get_bssid(NMAccessPoint *ap) { + EXPECT_NE(impl, nullptr); + return impl->nm_access_point_get_bssid(ap); +} + +guint32 LibnmWraps::nm_access_point_get_frequency(NMAccessPoint *ap) { + EXPECT_NE(impl, nullptr); + return impl->nm_access_point_get_frequency(ap); +} + +NM80211Mode LibnmWraps::nm_access_point_get_mode(NMAccessPoint *ap) { + EXPECT_NE(impl, nullptr); + return impl->nm_access_point_get_mode(ap); +} + +guint32 LibnmWraps::nm_access_point_get_max_bitrate(NMAccessPoint *ap) { + EXPECT_NE(impl, nullptr); + return impl->nm_access_point_get_max_bitrate(ap); +} + +guint8 LibnmWraps::nm_access_point_get_strength(NMAccessPoint *ap) { + EXPECT_NE(impl, nullptr); + return impl->nm_access_point_get_strength(ap); +} + +NMAccessPoint* LibnmWraps::nm_device_wifi_get_active_access_point(NMDeviceWifi *device) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_wifi_get_active_access_point(device); +} + +const GPtrArray* LibnmWraps::nm_device_wifi_get_access_points(NMDeviceWifi *device) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_wifi_get_access_points(device); +} + +const GPtrArray* LibnmWraps::nm_device_get_available_connections(NMDevice *device) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_get_available_connections(device); +} + +const char* LibnmWraps::nm_object_get_path(NMObject *object) { + EXPECT_NE(impl, nullptr); + return impl->nm_object_get_path(object); +} + +void LibnmWraps::nm_client_dbus_set_property(NMClient *client, + const char *object_path, + const char *interface_name, + const char *property_name, + GVariant *value, + int timeout_msec, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { + EXPECT_NE(impl, nullptr); + impl->nm_client_dbus_set_property(client, object_path, interface_name, property_name, value, timeout_msec, cancellable, callback, user_data); +} + +gboolean LibnmWraps::nm_client_dbus_set_property_finish(NMClient *client, + GAsyncResult *result, + GError **error) { + EXPECT_NE(impl, nullptr); + return impl->nm_client_dbus_set_property_finish(client, result, error); +} + +// WiFi Scan API implementation +void LibnmWraps::nm_device_wifi_request_scan_async(NMDeviceWifi *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { + EXPECT_NE(impl, nullptr); + impl->nm_device_wifi_request_scan_async(device, cancellable, callback, user_data); +} + +void LibnmWraps::nm_device_wifi_request_scan_options_async(NMDeviceWifi *device, + GVariant *options, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { + EXPECT_NE(impl, nullptr); + impl->nm_device_wifi_request_scan_options_async(device, options, cancellable, callback, user_data); +} + +gboolean LibnmWraps::nm_device_wifi_request_scan_finish(NMDeviceWifi *device, + GAsyncResult *result, + GError **error) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_wifi_request_scan_finish(device, result, error); +} + +gint64 LibnmWraps::nm_device_wifi_get_last_scan(NMDeviceWifi *device) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_wifi_get_last_scan(device); +} +void LibnmWraps::nm_device_set_autoconnect(NMDevice *device, gboolean autoconnect) { + EXPECT_NE(impl, nullptr); + impl->nm_device_set_autoconnect(device, autoconnect); +} +const GPtrArray* LibnmWraps::nm_client_get_connections(NMClient *client) { + EXPECT_NE(impl, nullptr); + return impl->nm_client_get_connections(client); +} +const char* LibnmWraps::nm_connection_get_id(NMConnection *connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_connection_get_id(connection); +} +const char* LibnmWraps::nm_connection_get_connection_type(NMConnection *connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_connection_get_connection_type(connection); +} + +void LibnmWraps::nm_client_activate_connection_async(NMClient *client, NMConnection *connection, NMDevice *device, const char *specific_object, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + EXPECT_NE(impl, nullptr); + impl->nm_client_activate_connection_async(client, connection, device, specific_object, cancellable, callback, user_data); +} + +NMActiveConnection* LibnmWraps::nm_client_activate_connection_finish(NMClient *client, GAsyncResult *result, GError **error) { + EXPECT_NE(impl, nullptr); + return impl->nm_client_activate_connection_finish(client, result, error); +} + +void LibnmWraps::nm_client_add_and_activate_connection_async(NMClient *client, NMConnection *partial, NMDevice *device, const char *specific_object, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + EXPECT_NE(impl, nullptr); + impl->nm_client_add_and_activate_connection_async(client, partial, device, specific_object, cancellable, callback, user_data); +} + +NMActiveConnection* LibnmWraps::nm_client_add_and_activate_connection_finish(NMClient *client, GAsyncResult *result, GError **error) { + EXPECT_NE(impl, nullptr); + return impl->nm_client_add_and_activate_connection_finish(client, result, error); +} + +GVariant* LibnmWraps::nm_remote_connection_update2_finish(NMRemoteConnection *connection, GAsyncResult *result, GError **error) { + EXPECT_NE(impl, nullptr); + return impl->nm_remote_connection_update2_finish(connection, result, error); +} + +void LibnmWraps::nm_client_add_connection2(NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, GVariant *args, gboolean ignore_out_result, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + EXPECT_NE(impl, nullptr); + impl->nm_client_add_connection2(client, settings, flags, args, ignore_out_result, cancellable, callback, user_data); +} + +NMRemoteConnection* LibnmWraps::nm_client_add_connection2_finish(NMClient *client, GAsyncResult *result, GVariant **out_result, GError **error) { + EXPECT_NE(impl, nullptr); + return impl->nm_client_add_connection2_finish(client, result, out_result, error); +} + +// New commit and DHCP hostname implementation +gboolean LibnmWraps::nm_remote_connection_commit_changes(NMRemoteConnection *connection, gboolean save_to_disk, GCancellable *cancellable, GError **error) { + EXPECT_NE(impl, nullptr); + return impl->nm_remote_connection_commit_changes(connection, save_to_disk, cancellable, error); +} + +const char* LibnmWraps::nm_setting_ip_config_get_dhcp_hostname(NMSettingIPConfig *setting) { + EXPECT_NE(impl, nullptr); + return impl->nm_setting_ip_config_get_dhcp_hostname(setting); +} + +gboolean LibnmWraps::nm_setting_ip_config_get_dhcp_send_hostname(NMSettingIPConfig *setting) { + EXPECT_NE(impl, nullptr); + return impl->nm_setting_ip_config_get_dhcp_send_hostname(setting); +} + +void LibnmWraps::nm_connection_add_setting(NMConnection *connection, NMSetting *setting) { + EXPECT_NE(impl, nullptr); + impl->nm_connection_add_setting(connection, setting); +} + +NMSettingWireless* LibnmWraps::nm_connection_get_setting_wireless(NMConnection *connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_connection_get_setting_wireless(connection); +} + +GBytes* LibnmWraps::nm_setting_wireless_get_ssid(NMSettingWireless *setting) { + EXPECT_NE(impl, nullptr); + return impl->nm_setting_wireless_get_ssid(setting); +} + +gboolean LibnmWraps::nm_remote_connection_delete(NMRemoteConnection *connection, GCancellable *cancellable, GError **error) { + EXPECT_NE(impl, nullptr); + return impl->nm_remote_connection_delete(connection, cancellable, error); +} diff --git a/tests/mocks/LibnmWraps.h b/tests/mocks/LibnmWraps.h new file mode 100644 index 000000000..8fb5a6dfd --- /dev/null +++ b/tests/mocks/LibnmWraps.h @@ -0,0 +1,256 @@ +#pragma once + +#include +#include +#include +#include + +class LibnmWrapsImpl { +public: + virtual ~LibnmWrapsImpl() = default; + + // New APIs + virtual gint64 nm_device_wifi_get_last_scan(NMDeviceWifi *device) = 0; + virtual void nm_device_set_autoconnect(NMDevice *device, gboolean autoconnect) = 0; + virtual const GPtrArray* nm_client_get_connections(NMClient *client) = 0; + virtual const char* nm_connection_get_id(NMConnection *connection) = 0; + virtual const char* nm_connection_get_connection_type(NMConnection *connection) = 0; + virtual const char* nm_device_get_iface(NMDevice* device) = 0; + virtual NMDevice* nm_client_get_device_by_iface(NMClient *client, const char *iface) = 0; + virtual NMDeviceState nm_device_get_state(NMDevice *device) = 0; + virtual void nm_device_disconnect_async(NMDevice *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) = 0; + virtual gboolean nm_device_disconnect_finish(NMDevice *device, GAsyncResult *result, GError **error) = 0; + virtual NMActiveConnection* nm_client_get_primary_connection(NMClient *client) = 0; + virtual NMActiveConnection* nm_device_get_active_connection(NMDevice *device) = 0; + virtual NMRemoteConnection* nm_active_connection_get_connection(NMActiveConnection *connection) = 0; + virtual const char* nm_connection_get_interface_name(NMRemoteConnection *connection) = 0; + virtual NMClient* nm_client_new(GCancellable* cancellable, GError** error) = 0; + virtual const GPtrArray* nm_client_get_devices(NMClient* client) = 0; + virtual const char* nm_device_get_hw_address(NMDevice* device) = 0; + virtual const GPtrArray* nm_client_get_active_connections(NMClient* client) = 0; + virtual NMSettingIPConfig* nm_connection_get_setting_ip4_config(NMConnection* connection) = 0; + virtual NMSettingIPConfig* nm_connection_get_setting_ip6_config(NMConnection* connection) = 0; + virtual const char* nm_setting_ip_config_get_method(NMSettingIPConfig* setting) = 0; + virtual NMSettingConnection* nm_connection_get_setting_connection(NMConnection* connection) = 0; + virtual const char* nm_setting_connection_get_interface_name(NMSettingConnection* setting) = 0; + virtual NMIPConfig* nm_active_connection_get_ip4_config(NMActiveConnection* connection) = 0; + virtual NMIPConfig* nm_active_connection_get_ip6_config(NMActiveConnection* connection) = 0; + virtual GPtrArray* nm_ip_config_get_addresses(NMIPConfig* config) = 0; + virtual const char* nm_ip_address_get_address(NMIPAddress* address) = 0; + virtual guint nm_ip_address_get_prefix(NMIPAddress* address) = 0; + virtual const char* nm_ip_config_get_gateway(NMIPConfig* config) = 0; + virtual const char* const* nm_ip_config_get_nameservers(NMIPConfig* config) = 0; + virtual NMDhcpConfig* nm_active_connection_get_dhcp4_config(NMActiveConnection* connection) = 0; + virtual NMDhcpConfig* nm_active_connection_get_dhcp6_config(NMActiveConnection* connection) = 0; + virtual const char* nm_dhcp_config_get_one_option(NMDhcpConfig* config, const char* option) = 0; + + // Access Point APIs + virtual NM80211ApFlags nm_access_point_get_flags(NMAccessPoint *ap) = 0; + virtual NM80211ApSecurityFlags nm_access_point_get_wpa_flags(NMAccessPoint *ap) = 0; + virtual NM80211ApSecurityFlags nm_access_point_get_rsn_flags(NMAccessPoint *ap) = 0; + virtual GBytes* nm_access_point_get_ssid(NMAccessPoint *ap) = 0; + virtual const char* nm_access_point_get_bssid(NMAccessPoint *ap) = 0; + virtual guint32 nm_access_point_get_frequency(NMAccessPoint *ap) = 0; + virtual NM80211Mode nm_access_point_get_mode(NMAccessPoint *ap) = 0; + virtual guint32 nm_access_point_get_max_bitrate(NMAccessPoint *ap) = 0; + virtual guint8 nm_access_point_get_strength(NMAccessPoint *ap) = 0; + virtual NMAccessPoint* nm_device_wifi_get_active_access_point(NMDeviceWifi *device) = 0; + virtual const GPtrArray* nm_device_wifi_get_access_points(NMDeviceWifi *device) = 0; + virtual const GPtrArray* nm_device_get_available_connections(NMDevice* device) = 0; + + // WiFi Scan APIs + virtual void nm_device_wifi_request_scan_async(NMDeviceWifi *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) = 0; + virtual void nm_device_wifi_request_scan_options_async(NMDeviceWifi *device, + GVariant *options, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) = 0; + virtual gboolean nm_device_wifi_request_scan_finish(NMDeviceWifi *device, + GAsyncResult *result, + GError **error) = 0; + virtual void nm_client_activate_connection_async(NMClient *client, NMConnection *connection, NMDevice *device, + const char *specific_object, GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer user_data) = 0; + virtual NMActiveConnection *nm_client_activate_connection_finish(NMClient *client, GAsyncResult *result, GError **error) = 0; + virtual void nm_client_add_and_activate_connection_async(NMClient *client, + NMConnection *partial, + NMDevice *device, + const char *specific_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) = 0; + virtual NMActiveConnection *nm_client_add_and_activate_connection_finish(NMClient *client, + GAsyncResult *result, + GError **error) = 0; + virtual GVariant *nm_remote_connection_update2_finish(NMRemoteConnection *connection, + GAsyncResult *result, + GError **error) = 0; + virtual void nm_client_add_connection2(NMClient *client, + GVariant *settings, + NMSettingsAddConnection2Flags flags, + GVariant *args, + gboolean ignore_out_result, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) = 0; + virtual NMRemoteConnection *nm_client_add_connection2_finish(NMClient *client, + GAsyncResult *result, + GVariant **out_result, + GError **error) = 0; + virtual const char *nm_object_get_path(NMObject *object) = 0; + virtual void nm_client_dbus_set_property(NMClient *client, + const char *object_path, + const char *interface_name, + const char *property_name, + GVariant *value, + int timeout_msec, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) = 0; + virtual gboolean nm_client_dbus_set_property_finish(NMClient *client, + GAsyncResult *result, + GError **error) = 0; + + // New commit and DHCP hostname functions + virtual gboolean nm_remote_connection_commit_changes(NMRemoteConnection *connection, + gboolean save_to_disk, + GCancellable *cancellable, + GError **error) = 0; + virtual const char *nm_setting_ip_config_get_dhcp_hostname(NMSettingIPConfig *setting) = 0; + virtual gboolean nm_setting_ip_config_get_dhcp_send_hostname(NMSettingIPConfig *setting) = 0; + virtual void nm_connection_add_setting(NMConnection *connection, NMSetting *setting) = 0; + virtual NMSettingWireless *nm_connection_get_setting_wireless(NMConnection *connection) = 0; + virtual GBytes *nm_setting_wireless_get_ssid(NMSettingWireless *setting) = 0; + virtual gboolean nm_remote_connection_delete(NMRemoteConnection *connection, GCancellable *cancellable, GError **error) = 0; +}; + +class LibnmWraps { +protected: + static LibnmWrapsImpl* impl; + +public: + LibnmWraps(); + LibnmWraps(const LibnmWraps &obj) = delete; + static void setImpl(LibnmWrapsImpl* newImpl); + static LibnmWraps& getInstance(); + + // New APIs + static gint64 nm_device_wifi_get_last_scan(NMDeviceWifi *device); + static void nm_device_set_autoconnect(NMDevice *device, gboolean autoconnect); + static const GPtrArray* nm_client_get_connections(NMClient *client); + static const char* nm_connection_get_id(NMConnection *connection); + static const char* nm_connection_get_connection_type(NMConnection *connection); + static void nm_client_activate_connection_async(NMClient *client, NMConnection *connection, NMDevice *device, const char *specific_object, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); + static NMActiveConnection *nm_client_activate_connection_finish(NMClient *client, GAsyncResult *result, GError **error); + static void nm_client_add_and_activate_connection_async(NMClient *client, + NMConnection *partial, + NMDevice *device, + const char *specific_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + static NMActiveConnection *nm_client_add_and_activate_connection_finish(NMClient *client, + GAsyncResult *result, + GError **error); + static GVariant *nm_remote_connection_update2_finish(NMRemoteConnection *connection, + GAsyncResult *result, + GError **error); + static void nm_client_add_connection2(NMClient *client, + GVariant *settings, + NMSettingsAddConnection2Flags flags, + GVariant *args, + gboolean ignore_out_result, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + static NMRemoteConnection *nm_client_add_connection2_finish(NMClient *client, + GAsyncResult *result, + GVariant **out_result, + GError **error); + + // Access Point APIs + static const char* nm_device_get_iface(NMDevice* device); + static NMDevice* nm_client_get_device_by_iface(NMClient *client, const char *iface); + static NMDeviceState nm_device_get_state(NMDevice *device); + static void nm_device_disconnect_async(NMDevice *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); + static gboolean nm_device_disconnect_finish(NMDevice *device, GAsyncResult *result, GError **error); + static NMActiveConnection* nm_client_get_primary_connection(NMClient *client); + static NMActiveConnection* nm_device_get_active_connection(NMDevice *device); + static NMRemoteConnection* nm_active_connection_get_connection(NMActiveConnection *connection); + static const char* nm_connection_get_interface_name(NMRemoteConnection *connection); + static NMClient* nm_client_new(GCancellable* cancellable, GError** error); + static const GPtrArray* nm_client_get_devices(NMClient* client); + static const char* nm_device_get_hw_address(NMDevice* device); + static const GPtrArray* nm_client_get_active_connections(NMClient* client); + static NMSettingIPConfig* nm_connection_get_setting_ip4_config(NMConnection* connection); + static NMSettingIPConfig* nm_connection_get_setting_ip6_config(NMConnection* connection); + static const char* nm_setting_ip_config_get_method(NMSettingIPConfig* setting); + static NMSettingConnection* nm_connection_get_setting_connection(NMConnection* connection); + static const char* nm_setting_connection_get_interface_name(NMSettingConnection* setting); + static NMIPConfig* nm_active_connection_get_ip4_config(NMActiveConnection* connection); + static NMIPConfig* nm_active_connection_get_ip6_config(NMActiveConnection* connection); + static GPtrArray* nm_ip_config_get_addresses(NMIPConfig* config); + static const char* nm_ip_address_get_address(NMIPAddress* address); + static guint nm_ip_address_get_prefix(NMIPAddress* address); + static const char* nm_ip_config_get_gateway(NMIPConfig* config); + static const char* const* nm_ip_config_get_nameservers(NMIPConfig* config); + static NMDhcpConfig* nm_active_connection_get_dhcp4_config(NMActiveConnection* connection); + static NMDhcpConfig* nm_active_connection_get_dhcp6_config(NMActiveConnection* connection); + static const char* nm_dhcp_config_get_one_option(NMDhcpConfig* config, const char* option); + + // Access Point APIs + static NM80211ApFlags nm_access_point_get_flags(NMAccessPoint *ap); + static NM80211ApSecurityFlags nm_access_point_get_wpa_flags(NMAccessPoint *ap); + static NM80211ApSecurityFlags nm_access_point_get_rsn_flags(NMAccessPoint *ap); + static GBytes* nm_access_point_get_ssid(NMAccessPoint *ap); + static const char* nm_access_point_get_bssid(NMAccessPoint *ap); + static guint32 nm_access_point_get_frequency(NMAccessPoint *ap); + static NM80211Mode nm_access_point_get_mode(NMAccessPoint *ap); + static guint32 nm_access_point_get_max_bitrate(NMAccessPoint *ap); + static guint8 nm_access_point_get_strength(NMAccessPoint *ap); + static NMAccessPoint* nm_device_wifi_get_active_access_point(NMDeviceWifi *device); + static const GPtrArray* nm_device_wifi_get_access_points(NMDeviceWifi *device); + static const GPtrArray* nm_device_get_available_connections(NMDevice* device); + + // WiFi Scan APIs + static void nm_device_wifi_request_scan_async(NMDeviceWifi *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + static void nm_device_wifi_request_scan_options_async(NMDeviceWifi *device, + GVariant *options, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + static gboolean nm_device_wifi_request_scan_finish(NMDeviceWifi *device, + GAsyncResult *result, + GError **error); + static const char *nm_object_get_path(NMObject *object); + static void nm_client_dbus_set_property(NMClient *client, + const char *object_path, + const char *interface_name, + const char *property_name, + GVariant *value, + int timeout_msec, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + static gboolean nm_client_dbus_set_property_finish(NMClient *client, + GAsyncResult *result, + GError **error); + + // New commit and DHCP hostname functions + static gboolean nm_remote_connection_commit_changes(NMRemoteConnection *connection, + gboolean save_to_disk, + GCancellable *cancellable, + GError **error); + static const char *nm_setting_ip_config_get_dhcp_hostname(NMSettingIPConfig *setting); + static gboolean nm_setting_ip_config_get_dhcp_send_hostname(NMSettingIPConfig *setting); + static void nm_connection_add_setting(NMConnection *connection, NMSetting *setting); + static NMSettingWireless *nm_connection_get_setting_wireless(NMConnection *connection); + static GBytes *nm_setting_wireless_get_ssid(NMSettingWireless *setting); + static gboolean nm_remote_connection_delete(NMRemoteConnection *connection, GCancellable *cancellable, GError **error); +}; diff --git a/tests/mocks/LibnmWrapsMock.h b/tests/mocks/LibnmWrapsMock.h new file mode 100644 index 000000000..462c76a59 --- /dev/null +++ b/tests/mocks/LibnmWrapsMock.h @@ -0,0 +1,526 @@ +#pragma once + +#include +#include +#include "LibnmWraps.h" +#include + +extern "C" const char* __real_nm_device_get_iface(NMDevice* device); +extern "C" gboolean __real_nm_remote_connection_delete(NMRemoteConnection *connection, GCancellable *cancellable, GError **error); +extern "C" NMActiveConnection* __real_nm_client_get_primary_connection(NMClient *client); +extern "C" NMActiveConnection* __real_nm_device_get_active_connection(NMDevice *device); +extern "C" NMRemoteConnection* __real_nm_active_connection_get_connection(NMActiveConnection *connection); +extern "C" const char* __real_nm_connection_get_interface_name(NMRemoteConnection *connection); +extern "C" NMDevice* __real_nm_client_get_device_by_iface(NMClient *client, const char *iface); +extern "C" NMDeviceState __real_nm_device_get_state(NMDevice *device); +extern "C" void __real_nm_device_disconnect_async(NMDevice *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); +extern "C" gboolean __real_nm_device_disconnect_finish(NMDevice *device, GAsyncResult *result, GError **error); +extern "C" const GPtrArray* __real_nm_client_get_devices(NMClient* client); +extern "C" NMClient* __real_nm_client_new(GCancellable* cancellable, GError** error); +extern "C" const char* __real_nm_device_get_hw_address(NMDevice* device); +extern "C" const GPtrArray* __real_nm_client_get_active_connections(NMClient* client); +extern "C" NMSettingIPConfig* __real_nm_connection_get_setting_ip4_config(NMConnection* connection); +extern "C" NMSettingIPConfig* __real_nm_connection_get_setting_ip6_config(NMConnection* connection); +extern "C" const char* __real_nm_setting_ip_config_get_method(NMSettingIPConfig* setting); +extern "C" NMSettingConnection* __real_nm_connection_get_setting_connection(NMConnection* connection); +extern "C" const char* __real_nm_setting_connection_get_interface_name(NMSettingConnection* setting); +extern "C" NMIPConfig* __real_nm_active_connection_get_ip4_config(NMActiveConnection* connection); +extern "C" NMIPConfig* __real_nm_active_connection_get_ip6_config(NMActiveConnection* connection); +extern "C" GPtrArray* __real_nm_ip_config_get_addresses(NMIPConfig* config); +extern "C" const char* __real_nm_ip_address_get_address(NMIPAddress* address); +extern "C" guint __real_nm_ip_address_get_prefix(NMIPAddress* address); +extern "C" const char* __real_nm_ip_config_get_gateway(NMIPConfig* config); +extern "C" const char* const* __real_nm_ip_config_get_nameservers(NMIPConfig* config); +extern "C" NMDhcpConfig* __real_nm_active_connection_get_dhcp4_config(NMActiveConnection* connection); +extern "C" NMDhcpConfig* __real_nm_active_connection_get_dhcp6_config(NMActiveConnection* connection); +extern "C" const char* __real_nm_dhcp_config_get_one_option(NMDhcpConfig* config, const char* option); + +// Access Point API real functions +extern "C" NM80211ApFlags __real_nm_access_point_get_flags(NMAccessPoint *ap); +extern "C" NM80211ApSecurityFlags __real_nm_access_point_get_wpa_flags(NMAccessPoint *ap); +extern "C" NM80211ApSecurityFlags __real_nm_access_point_get_rsn_flags(NMAccessPoint *ap); +extern "C" GBytes* __real_nm_access_point_get_ssid(NMAccessPoint *ap); +extern "C" const char* __real_nm_access_point_get_bssid(NMAccessPoint *ap); +extern "C" guint32 __real_nm_access_point_get_frequency(NMAccessPoint *ap); +extern "C" NM80211Mode __real_nm_access_point_get_mode(NMAccessPoint *ap); +extern "C" guint32 __real_nm_access_point_get_max_bitrate(NMAccessPoint *ap); +extern "C" guint8 __real_nm_access_point_get_strength(NMAccessPoint *ap); +extern "C" NMAccessPoint* __real_nm_device_wifi_get_active_access_point(NMDeviceWifi *device); + +// WiFi Scan API real functions +extern "C" void __real_nm_device_wifi_request_scan_async(NMDeviceWifi *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +extern "C" void __real_nm_device_wifi_request_scan_options_async(NMDeviceWifi *device, + GVariant *options, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +extern "C" gboolean __real_nm_device_wifi_request_scan_finish(NMDeviceWifi *device, + GAsyncResult *result, + GError **error); +extern "C" const GPtrArray *__real_nm_device_wifi_get_access_points(NMDeviceWifi *device); +extern "C" const GPtrArray *__real_nm_device_get_available_connections(NMDevice *device); + + +// New API real functions +extern "C" gint64 __real_nm_device_wifi_get_last_scan(NMDeviceWifi *device); +extern "C" void __real_nm_device_set_autoconnect(NMDevice *device, gboolean autoconnect); +extern "C" const GPtrArray* __real_nm_client_get_connections(NMClient *client); +extern "C" const char* __real_nm_connection_get_id(NMConnection *connection); +extern "C" const char* __real_nm_connection_get_connection_type(NMConnection *connection); +extern "C" void __real_nm_client_activate_connection_async(NMClient *client, + NMConnection *connection, + NMDevice *device, + const char *specific_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +extern "C" NMActiveConnection* __real_nm_client_activate_connection_finish(NMClient *client, GAsyncResult *result, GError **error); +extern "C" void __real_nm_client_add_and_activate_connection_async(NMClient *client, + NMConnection *partial, + NMDevice *device, + const char *specific_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +extern "C" NMActiveConnection* __real_nm_client_add_and_activate_connection_finish(NMClient *client, + GAsyncResult *result, + GError **error); +extern "C" GVariant* __real_nm_remote_connection_update2_finish(NMRemoteConnection *connection, + GAsyncResult *result, + GError **error); +extern "C" void __real_nm_client_add_connection2(NMClient *client, + GVariant *settings, + NMSettingsAddConnection2Flags flags, + GVariant *args, + gboolean ignore_out_result, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +extern "C" NMRemoteConnection* __real_nm_client_add_connection2_finish(NMClient *client, + GAsyncResult *result, + GVariant **out_result, + GError **error); +extern "C" const char* __real_nm_object_get_path(NMObject *object); +extern "C" void __real_nm_client_dbus_set_property(NMClient *client, + const char *object_path, + const char *interface_name, + const char *property_name, + GVariant *value, + int timeout_msec, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +extern "C" gboolean __real_nm_client_dbus_set_property_finish(NMClient *client, + GAsyncResult *result, + GError **error); + +// New real functions for commit changes and DHCP hostname +extern "C" gboolean __real_nm_remote_connection_commit_changes(NMRemoteConnection *connection, + gboolean save_to_disk, + GCancellable *cancellable, + GError **error); +extern "C" const char* __real_nm_setting_ip_config_get_dhcp_hostname(NMSettingIPConfig *setting); +extern "C" gboolean __real_nm_setting_ip_config_get_dhcp_send_hostname(NMSettingIPConfig *setting); +extern "C" void __real_nm_connection_add_setting(NMConnection *connection, NMSetting *setting); +extern "C" NMSettingWireless *__real_nm_connection_get_setting_wireless(NMConnection *connection); +extern "C" GBytes *__real_nm_setting_wireless_get_ssid(NMSettingWireless *setting); + + +class LibnmWrapsImplMock : public LibnmWrapsImpl { +public: + LibnmWrapsImplMock() : LibnmWrapsImpl() { + + ON_CALL(*this, nm_device_wifi_get_last_scan(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDeviceWifi* device) -> gint64 { + return __real_nm_device_wifi_get_last_scan(device); + })); + ON_CALL(*this, nm_device_set_autoconnect(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDevice* device, gboolean autoconnect) { + __real_nm_device_set_autoconnect(device, autoconnect); + })); + ON_CALL(*this, nm_client_get_connections(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client) -> const GPtrArray* { + return __real_nm_client_get_connections(client); + })); + ON_CALL(*this, nm_connection_get_id(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMConnection* connection) -> const char* { + return __real_nm_connection_get_id(connection); + })); + ON_CALL(*this, nm_connection_get_connection_type(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMConnection* connection) -> const char* { + return __real_nm_connection_get_connection_type(connection); + })); + ON_CALL(*this, nm_client_activate_connection_async(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client, NMConnection* connection, NMDevice* device, const char* specific_object, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data) { + __real_nm_client_activate_connection_async(client, connection, device, specific_object, cancellable, callback, user_data); + })); + ON_CALL(*this, nm_client_activate_connection_finish(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client, GAsyncResult* result, GError** error) -> NMActiveConnection* { + return __real_nm_client_activate_connection_finish(client, result, error); + })); + ON_CALL(*this, nm_client_add_and_activate_connection_async(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client, NMConnection* partial, NMDevice* device, const char* specific_object, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data) { + __real_nm_client_add_and_activate_connection_async(client, partial, device, specific_object, cancellable, callback, user_data); + })); + ON_CALL(*this, nm_client_add_and_activate_connection_finish(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client, GAsyncResult* result, GError** error) -> NMActiveConnection* { + return __real_nm_client_add_and_activate_connection_finish(client, result, error); + })); + ON_CALL(*this, nm_remote_connection_update2_finish(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMRemoteConnection* connection, GAsyncResult* result, GError** error) -> GVariant* { + return __real_nm_remote_connection_update2_finish(connection, result, error); + })); + ON_CALL(*this, nm_client_add_connection2(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client, GVariant* settings, NMSettingsAddConnection2Flags flags, GVariant* args, gboolean ignore_out_result, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data) { + __real_nm_client_add_connection2(client, settings, flags, args, ignore_out_result, cancellable, callback, user_data); + })); + ON_CALL(*this, nm_client_add_connection2_finish(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client, GAsyncResult* result, GVariant** out_result, GError** error) -> NMRemoteConnection* { + return __real_nm_client_add_connection2_finish(client, result, out_result, error); + })); + + ON_CALL(*this, nm_device_get_iface(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDevice* device) -> const char* { + return __real_nm_device_get_iface(device); + })); + ON_CALL(*this, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client, const char* iface) -> NMDevice* { + return __real_nm_client_get_device_by_iface(client, iface); + })); + ON_CALL(*this, nm_device_get_state(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDevice* device) -> NMDeviceState { + return __real_nm_device_get_state(device); + })); + ON_CALL(*this, nm_device_disconnect_async(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDevice* device, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data) { + return __real_nm_device_disconnect_async(device, cancellable, callback, user_data); + })); + + ON_CALL(*this, nm_device_disconnect_finish(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDevice* device, GAsyncResult* result, GError** error) -> gboolean { + return __real_nm_device_disconnect_finish(device, result, error); + })); + ON_CALL(*this, nm_client_get_primary_connection(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client) -> NMActiveConnection* { + return __real_nm_client_get_primary_connection(client); + })); + ON_CALL(*this, nm_device_get_active_connection(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDevice* device) -> NMActiveConnection* { + return __real_nm_device_get_active_connection(device); + })); + ON_CALL(*this, nm_active_connection_get_connection(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMActiveConnection* connection) -> NMRemoteConnection* { + return __real_nm_active_connection_get_connection(connection); + })); + ON_CALL(*this, nm_connection_get_interface_name(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMRemoteConnection* connection) -> const char* { + return __real_nm_connection_get_interface_name(connection); + })); + ON_CALL(*this, nm_client_get_devices(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client) -> const GPtrArray* { + return __real_nm_client_get_devices(client); + })); + ON_CALL(*this, nm_client_new(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](GCancellable* cancellable, GError** error) -> NMClient* { + return __real_nm_client_new(cancellable, error); + })); + ON_CALL(*this, nm_device_get_hw_address(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDevice* device) -> const char* { + return __real_nm_device_get_hw_address(device); + })); + ON_CALL(*this, nm_client_get_active_connections(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client) -> const GPtrArray* { + return __real_nm_client_get_active_connections(client); + })); + ON_CALL(*this, nm_connection_get_setting_ip4_config(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMConnection* connection) -> NMSettingIPConfig* { + return __real_nm_connection_get_setting_ip4_config(connection); + })); + ON_CALL(*this, nm_connection_get_setting_ip6_config(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMConnection* connection) -> NMSettingIPConfig* { + return __real_nm_connection_get_setting_ip6_config(connection); + })); + ON_CALL(*this, nm_setting_ip_config_get_method(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMSettingIPConfig* setting) -> const char* { + return __real_nm_setting_ip_config_get_method(setting); + })); + ON_CALL(*this, nm_connection_get_setting_connection(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMConnection* connection) -> NMSettingConnection* { + return __real_nm_connection_get_setting_connection(connection); + })); + ON_CALL(*this, nm_setting_connection_get_interface_name(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMSettingConnection* setting) -> const char* { + return __real_nm_setting_connection_get_interface_name(setting); + })); + ON_CALL(*this, nm_active_connection_get_ip4_config(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMActiveConnection* connection) -> NMIPConfig* { + return __real_nm_active_connection_get_ip4_config(connection); + })); + ON_CALL(*this, nm_active_connection_get_ip6_config(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMActiveConnection* connection) -> NMIPConfig* { + return __real_nm_active_connection_get_ip6_config(connection); + })); + ON_CALL(*this, nm_ip_config_get_addresses(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMIPConfig* config) -> GPtrArray* { + return __real_nm_ip_config_get_addresses(config); + })); + ON_CALL(*this, nm_ip_address_get_address(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMIPAddress* address) -> const char* { + return __real_nm_ip_address_get_address(address); + })); + ON_CALL(*this, nm_ip_address_get_prefix(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMIPAddress* address) -> guint { + return __real_nm_ip_address_get_prefix(address); + })); + ON_CALL(*this, nm_ip_config_get_gateway(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMIPConfig* config) -> const char* { + return __real_nm_ip_config_get_gateway(config); + })); + ON_CALL(*this, nm_ip_config_get_nameservers(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMIPConfig* config) -> const char* const* { + return __real_nm_ip_config_get_nameservers(config); + })); + ON_CALL(*this, nm_active_connection_get_dhcp4_config(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMActiveConnection* connection) -> NMDhcpConfig* { + return __real_nm_active_connection_get_dhcp4_config(connection); + })); + ON_CALL(*this, nm_active_connection_get_dhcp6_config(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMActiveConnection* connection) -> NMDhcpConfig* { + return __real_nm_active_connection_get_dhcp6_config(connection); + })); + ON_CALL(*this, nm_dhcp_config_get_one_option(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDhcpConfig* config, const char* option) -> const char* { + return __real_nm_dhcp_config_get_one_option(config, option); + })); + + // Access Point API ON_CALL setups + ON_CALL(*this, nm_access_point_get_flags(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMAccessPoint* ap) -> NM80211ApFlags { + return __real_nm_access_point_get_flags(ap); + })); + + ON_CALL(*this, nm_access_point_get_wpa_flags(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMAccessPoint* ap) -> NM80211ApSecurityFlags { + return __real_nm_access_point_get_wpa_flags(ap); + })); + + ON_CALL(*this, nm_access_point_get_rsn_flags(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMAccessPoint* ap) -> NM80211ApSecurityFlags { + return __real_nm_access_point_get_rsn_flags(ap); + })); + + ON_CALL(*this, nm_access_point_get_ssid(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMAccessPoint* ap) -> GBytes* { + return __real_nm_access_point_get_ssid(ap); + })); + + ON_CALL(*this, nm_access_point_get_bssid(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMAccessPoint* ap) -> const char* { + return __real_nm_access_point_get_bssid(ap); + })); + + ON_CALL(*this, nm_access_point_get_frequency(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMAccessPoint* ap) -> guint32 { + return __real_nm_access_point_get_frequency(ap); + })); + + ON_CALL(*this, nm_access_point_get_mode(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMAccessPoint* ap) -> NM80211Mode { + return __real_nm_access_point_get_mode(ap); + })); + + ON_CALL(*this, nm_access_point_get_max_bitrate(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMAccessPoint* ap) -> guint32 { + return __real_nm_access_point_get_max_bitrate(ap); + })); + + ON_CALL(*this, nm_access_point_get_strength(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMAccessPoint* ap) -> guint8 { + return __real_nm_access_point_get_strength(ap); + })); + + ON_CALL(*this, nm_device_wifi_get_active_access_point(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDeviceWifi* device) -> NMAccessPoint* { + return __real_nm_device_wifi_get_active_access_point(device); + })); + + // WiFi Scan API ON_CALL setups + ON_CALL(*this, nm_device_wifi_request_scan_async(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDeviceWifi *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + __real_nm_device_wifi_request_scan_async(device, cancellable, callback, user_data); + })); + + ON_CALL(*this, nm_device_wifi_request_scan_options_async(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDeviceWifi *device, GVariant *options, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + __real_nm_device_wifi_request_scan_options_async(device, options, cancellable, callback, user_data); + })); + + ON_CALL(*this, nm_device_wifi_request_scan_finish(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDeviceWifi *device, GAsyncResult *result, GError **error) -> gboolean { + return __real_nm_device_wifi_request_scan_finish(device, result, error); + })); + ON_CALL(*this, nm_device_wifi_get_access_points(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDeviceWifi *device) -> const GPtrArray* { + return __real_nm_device_wifi_get_access_points(device); + })); + ON_CALL(*this, nm_device_get_available_connections(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDevice *device) -> const GPtrArray* { + return __real_nm_device_get_available_connections(device); + })); + ON_CALL(*this, nm_object_get_path(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMObject *object) -> const char* { + return __real_nm_object_get_path(object); + })); + ON_CALL(*this, nm_client_dbus_set_property(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient *client, const char *object_path, const char *interface_name, const char *property_name, GVariant *value, int timeout_msec, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + __real_nm_client_dbus_set_property(client, object_path, interface_name, property_name, value, timeout_msec, cancellable, callback, user_data); + })); + ON_CALL(*this, nm_client_dbus_set_property_finish(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient *client, GAsyncResult *result, GError **error) -> gboolean { + return __real_nm_client_dbus_set_property_finish(client, result, error); + })); + ON_CALL(*this, nm_remote_connection_delete(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMRemoteConnection *connection, GCancellable *cancellable, GError **error) -> gboolean { + return __real_nm_remote_connection_delete(connection, cancellable, error); + })); + } +// NMActiveConnection *nm_device_get_active_connection(NMDevice *device); + virtual ~LibnmWrapsImplMock() = default; + + // Mock methods + MOCK_METHOD(const char*, nm_device_get_iface, (NMDevice* device), (override)); + MOCK_METHOD(NMDevice*, nm_client_get_device_by_iface, (NMClient *client, const char *iface), (override)); + MOCK_METHOD(NMDeviceState, nm_device_get_state, (NMDevice *device), (override)); + MOCK_METHOD(void, nm_device_disconnect_async, (NMDevice *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); + MOCK_METHOD(gboolean, nm_device_disconnect_finish, (NMDevice *device, GAsyncResult *result, GError **error), (override)); + MOCK_METHOD(NMActiveConnection*, nm_client_get_primary_connection, (NMClient *client), (override)); + MOCK_METHOD(NMActiveConnection*, nm_device_get_active_connection, (NMDevice *device), (override)); + MOCK_METHOD(NMRemoteConnection*, nm_active_connection_get_connection, (NMActiveConnection *connection), (override)); + MOCK_METHOD(const char*, nm_connection_get_interface_name, (NMRemoteConnection *connection), (override)); + MOCK_METHOD(NMClient*, nm_client_new, (GCancellable* cancellable, GError** error), (override)); + MOCK_METHOD(const GPtrArray*, nm_client_get_devices, (NMClient* client), (override)); + MOCK_METHOD(const char*, nm_device_get_hw_address, (NMDevice* device), (override)); + MOCK_METHOD(const char*, nm_setting_connection_get_interface_name, (NMSettingConnection* settings), (override)); + MOCK_METHOD(const GPtrArray*, nm_client_get_active_connections, (NMClient* client), (override)); + MOCK_METHOD(NMSettingIPConfig*, nm_connection_get_setting_ip4_config, (NMConnection* connection), (override)); + MOCK_METHOD(NMSettingIPConfig*, nm_connection_get_setting_ip6_config, (NMConnection* connection), (override)); + MOCK_METHOD(const char*, nm_setting_ip_config_get_method, (NMSettingIPConfig* setting), (override)); + MOCK_METHOD(NMSettingConnection*, nm_connection_get_setting_connection, (NMConnection* connection), (override)); + MOCK_METHOD(NMIPConfig*, nm_active_connection_get_ip4_config, (NMActiveConnection* connection), (override)); + MOCK_METHOD(NMIPConfig*, nm_active_connection_get_ip6_config, (NMActiveConnection* connection), (override)); + MOCK_METHOD(NMDhcpConfig*, nm_active_connection_get_dhcp6_config, (NMActiveConnection* connection), (override)); + MOCK_METHOD(GPtrArray*, nm_ip_config_get_addresses, (NMIPConfig* config), (override)); + MOCK_METHOD(const char*, nm_ip_address_get_address, (NMIPAddress* address), (override)); + MOCK_METHOD(guint, nm_ip_address_get_prefix, (NMIPAddress* address), (override)); + MOCK_METHOD(const char*, nm_ip_config_get_gateway, (NMIPConfig* config), (override)); + MOCK_METHOD(const char* const*, nm_ip_config_get_nameservers, (NMIPConfig* config), (override)); + MOCK_METHOD(NMDhcpConfig*, nm_active_connection_get_dhcp4_config, (NMActiveConnection* connection), (override)); + MOCK_METHOD(const char*, nm_dhcp_config_get_one_option, (NMDhcpConfig* config, const char* option), (override)); + + // Access Point API mock methods + MOCK_METHOD(NM80211ApFlags, nm_access_point_get_flags, (NMAccessPoint *ap), (override)); + MOCK_METHOD(NM80211ApSecurityFlags, nm_access_point_get_wpa_flags, (NMAccessPoint *ap), (override)); + MOCK_METHOD(NM80211ApSecurityFlags, nm_access_point_get_rsn_flags, (NMAccessPoint *ap), (override)); + MOCK_METHOD(GBytes*, nm_access_point_get_ssid, (NMAccessPoint *ap), (override)); + MOCK_METHOD(const char*, nm_access_point_get_bssid, (NMAccessPoint *ap), (override)); + MOCK_METHOD(guint32, nm_access_point_get_frequency, (NMAccessPoint *ap), (override)); + MOCK_METHOD(NM80211Mode, nm_access_point_get_mode, (NMAccessPoint *ap), (override)); + MOCK_METHOD(guint32, nm_access_point_get_max_bitrate, (NMAccessPoint *ap), (override)); + MOCK_METHOD(guint8, nm_access_point_get_strength, (NMAccessPoint *ap), (override)); + MOCK_METHOD(NMAccessPoint*, nm_device_wifi_get_active_access_point, (NMDeviceWifi *device), (override)); + MOCK_METHOD(const GPtrArray*, nm_device_wifi_get_access_points, (NMDeviceWifi *device), (override)); + MOCK_METHOD(const GPtrArray*, nm_device_get_available_connections, (NMDevice *device), (override)); + MOCK_METHOD(const char*, nm_object_get_path, (NMObject *object), (override)); + MOCK_METHOD(void, nm_client_dbus_set_property, (NMClient *client, const char *object_path, const char *interface_name, const char *property_name, GVariant *value, int timeout_msec, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); + MOCK_METHOD(gboolean, nm_client_dbus_set_property_finish, (NMClient *client, GAsyncResult *result, GError **error), (override)); + + // WiFi Scan API mock methods + MOCK_METHOD(void, nm_device_wifi_request_scan_async, (NMDeviceWifi *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); + MOCK_METHOD(void, nm_device_wifi_request_scan_options_async, (NMDeviceWifi *device, GVariant *options, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); + MOCK_METHOD(gboolean, nm_device_wifi_request_scan_finish, (NMDeviceWifi *device, GAsyncResult *result, GError **error), (override)); + + // New API mock methods + MOCK_METHOD(gint64, nm_device_wifi_get_last_scan, (NMDeviceWifi *device), (override)); + MOCK_METHOD(void, nm_device_set_autoconnect, (NMDevice *device, gboolean autoconnect), (override)); + MOCK_METHOD(const GPtrArray*, nm_client_get_connections, (NMClient *client), (override)); + MOCK_METHOD(const char*, nm_connection_get_id, (NMConnection *connection), (override)); + MOCK_METHOD(const char*, nm_connection_get_connection_type, (NMConnection *connection), (override)); + MOCK_METHOD(void, nm_client_activate_connection_async, (NMClient *client, NMConnection *connection, NMDevice *device, const char *specific_object, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); + MOCK_METHOD(NMActiveConnection*, nm_client_activate_connection_finish, (NMClient *client, GAsyncResult *result, GError **error), (override)); + MOCK_METHOD(void, nm_client_add_and_activate_connection_async, (NMClient *client, NMConnection *partial, NMDevice *device, const char *specific_object, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); + + // New commit and DHCP hostname mock methods + MOCK_METHOD(gboolean, nm_remote_connection_commit_changes, (NMRemoteConnection *connection, gboolean save_to_disk, GCancellable *cancellable, GError **error), (override)); + MOCK_METHOD(const char*, nm_setting_ip_config_get_dhcp_hostname, (NMSettingIPConfig *setting), (override)); + MOCK_METHOD(gboolean, nm_setting_ip_config_get_dhcp_send_hostname, (NMSettingIPConfig *setting), (override)); + MOCK_METHOD(void, nm_connection_add_setting, (NMConnection *connection, NMSetting *setting), (override)); + MOCK_METHOD(NMSettingWireless*, nm_connection_get_setting_wireless, (NMConnection *connection), (override)); + MOCK_METHOD(GBytes*, nm_setting_wireless_get_ssid, (NMSettingWireless *setting), (override)); + MOCK_METHOD(NMActiveConnection*, nm_client_add_and_activate_connection_finish, (NMClient *client, GAsyncResult *result, GError **error), (override)); + MOCK_METHOD(GVariant*, nm_remote_connection_update2_finish, (NMRemoteConnection *connection, GAsyncResult *result, GError **error), (override)); + MOCK_METHOD(void, nm_client_add_connection2, (NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, GVariant *args, gboolean ignore_out_result, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); + MOCK_METHOD(NMRemoteConnection*, nm_client_add_connection2_finish, (NMClient *client, GAsyncResult *result, GVariant **out_result, GError **error), (override)); + MOCK_METHOD(gboolean, nm_remote_connection_delete, (NMRemoteConnection *connection, GCancellable *cancellable, GError **error), (override)); +}; diff --git a/tests/unittest/CMakeLists.txt b/tests/unittest/CMakeLists.txt deleted file mode 100644 index 13855cb15..000000000 --- a/tests/unittest/CMakeLists.txt +++ /dev/null @@ -1,200 +0,0 @@ -############################################################################# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2024 RDK Management -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -############################################################################# -message ("Unittest binary is built here") - -set(NM_CLASS_UT "common_class_tests") -set(NM_RDKPROXY_UT "rdkproxy_tests") -set(NM_LEGACY_WIFI_UT "legacywifi_tests") -set(NM_LEGACY_NETWORK_UT "legacynetwork_tests") -set(NM_ROUTER_DISCOVERY_UT "routerDiscovery_tests") - -find_package(${NAMESPACE}Core REQUIRED) -find_package(${NAMESPACE}Plugins REQUIRED) -find_package(CURL) -find_package(PkgConfig REQUIRED) -#pkg_check_modules(GLIB REQUIRED glib-2.0) -#pkg_check_modules(GIO REQUIRED gio-2.0) -#pkg_check_modules(LIBNM REQUIRED libnm) - -include(FetchContent) -FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip -) - -FetchContent_MakeAvailable(googletest) - -add_executable(${NM_CLASS_UT} - ${CMAKE_SOURCE_DIR}/tests/unittest/test_NetworkManagerConnectivity.cpp - ${CMAKE_SOURCE_DIR}/tests/unittest/test_NetworkManagerStunClient.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp -) - -add_executable(${NM_RDKPROXY_UT} - ${CMAKE_SOURCE_DIR}/tests/unittest/test_NetworkManager.cpp - ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp - ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerJsonRpc.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerImplementation.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp - ${CMAKE_SOURCE_DIR}/plugin/rdk/NetworkManagerRDKProxy.cpp - ${PROXY_STUB_SOURCES} -) - -add_executable(${NM_LEGACY_WIFI_UT} - ${CMAKE_SOURCE_DIR}/tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp - ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp - ${CMAKE_SOURCE_DIR}/legacy/LegacyWiFiManagerAPIs.cpp -) - -add_executable(${NM_LEGACY_NETWORK_UT} - ${CMAKE_SOURCE_DIR}/tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp - ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp - ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp - ${CMAKE_SOURCE_DIR}/legacy/LegacyNetworkAPIs.cpp -) - -add_executable(${NM_ROUTER_DISCOVERY_UT} - ${CMAKE_SOURCE_DIR}/tests/unittest/test_UpnpDiscoveryManager.cpp - ${CMAKE_SOURCE_DIR}/tools/upnp/UpnpDiscoveryManager.cpp -) - -set_target_properties(${NM_CLASS_UT} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES -) - -set_target_properties(${NM_RDKPROXY_UT} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES -) - -set_target_properties(${NM_LEGACY_WIFI_UT} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES -) -set_target_properties(${NM_LEGACY_NETWORK_UT} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES -) - -set_target_properties(${NM_ROUTER_DISCOVERY_UT} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES -) - -target_compile_options(${NM_CLASS_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) -target_compile_options(${NM_RDKPROXY_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) -target_compile_options(${NM_LEGACY_WIFI_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) -target_compile_options(${NM_LEGACY_NETWORK_UT} PRIVATE -Wall -include ${CMAKE_SOURCE_DIR}/interface/INetworkManager.h) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") - -include_directories(${PROJECT_SOURCE_DIR}/interface) -include_directories(${PROJECT_SOURCE_DIR}/plugin) -include_directories(${PROJECT_SOURCE_DIR}/legacy) -include_directories(${PROJECT_SOURCE_DIR}/tests/mocks) -include_directories(${PROJECT_SOURCE_DIR}/tests/mocks/thunder) - -target_include_directories(${NM_CLASS_UT} PRIVATE - ${GLIB_INCLUDE_DIRS} - ${LIBNM_INCLUDE_DIRS} - ${GIO_INCLUDE_DIRS} - ${PROJECT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${gtest_SOURCE_DIR}/include - ${gtest_SOURCE_DIR}/../googlemock/include -) - -target_include_directories(${NM_RDKPROXY_UT} PRIVATE - ${CURL_INCLUDE_DIRS} - ${IARMBUS_INCLUDE_DIRS} - ${PROJECT_SOURCE_DIR} - ${gtest_SOURCE_DIR}/include - ${gtest_SOURCE_DIR}/../googlemock/include - ${CMAKE_CURRENT_SOURCE_DIR}/install/usr/include/rdk/iarmbus -) -target_include_directories(${NM_LEGACY_WIFI_UT} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${gtest_SOURCE_DIR}/include - ${gtest_SOURCE_DIR}/../googlemock/include -) - -target_include_directories(${NM_LEGACY_NETWORK_UT} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${gtest_SOURCE_DIR}/include - ${gtest_SOURCE_DIR}/../googlemock/include -) -target_include_directories(${NM_ROUTER_DISCOVERY_UT} PRIVATE - ${PROJECT_SOURCE_DIR}/tools/upnp - ${GUPNP_INCLUDE_DIRS} - ${GLIB_INCLUDE_DIRS} - ${LIBSOUP_INCLUDE_DIRS} - ${GSSDP_INCLUDE_DIRS} -) - -target_link_libraries(${NM_CLASS_UT} PRIVATE - gmock_main - ${NAMESPACE}Core::${NAMESPACE}Core - ${GLIB_LIBRARIES} - ${GIO_LIBRARIES} - ${LIBNM_LIBRARIES} - ${CURL_LIBRARIES} -) - -target_link_libraries(${NM_RDKPROXY_UT} PRIVATE - gmock_main - ${NAMESPACE}Core::${NAMESPACE}Core - ${NAMESPACE}Plugins::${NAMESPACE}Plugins - ${CURL_LIBRARIES} - ${IARMBUS_LIBRARIES} -) -target_link_libraries(${NM_LEGACY_WIFI_UT} PRIVATE - gmock_main - ${NAMESPACE}Core::${NAMESPACE}Core - ${NAMESPACE}Plugins::${NAMESPACE}Plugins - ${NAMESPACE}Core::${NAMESPACE}Core - ${CURL_LIBRARIES} -) -target_link_libraries(${NM_LEGACY_NETWORK_UT} PRIVATE - gmock_main - ${NAMESPACE}Core::${NAMESPACE}Core - ${NAMESPACE}Plugins::${NAMESPACE}Plugins - ${NAMESPACE}Core::${NAMESPACE}Core - ${CURL_LIBRARIES} -) -target_link_libraries(${NM_ROUTER_DISCOVERY_UT} PRIVATE - gmock_main - ${GLIB_LIBRARIES} - ${LIBSOUP_LIBRARIES} - ${GUPNP_LIBRARIES} - ${GSSDP_LIBRARIES} -) - -install(TARGETS ${NM_CLASS_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -install(TARGETS ${NM_RDKPROXY_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -install(TARGETS ${NM_LEGACY_WIFI_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -install(TARGETS ${NM_LEGACY_NETWORK_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -install(TARGETS ${NM_ROUTER_DISCOVERY_UT} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp b/tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp deleted file mode 100644 index 88f7fb308..000000000 --- a/tests/unittest/test_LegacyPlugin_NetworkAPIs.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2024 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -#include -#include -#include -#include -#include "ServiceMock.h" -#include "FactoriesImplementation.h" -#include "NetworkManagerLogger.h" -#include "LegacyNetworkAPIs.h" -#include "ThunderPortability.h" - -using namespace std; -using namespace WPEFramework; -using ::testing::NiceMock; - -class NetworkTest : public ::testing::Test { -protected: - Core::ProxyType plugin; - Core::JSONRPC::Handler& handler; - DECL_CORE_JSONRPC_CONX connection; - Core::JSONRPC::Message message; - string response; - ServiceMock services; - - NetworkTest() - : plugin(Core::ProxyType::Create()) - , handler(*(plugin)) - , INIT_CONX(1, 0) - { - - } - virtual ~NetworkTest() override - { - } -}; - -class NetworkInitializedTest : public NetworkTest { -protected: - NiceMock service; - NetworkInitializedTest() - { - EXPECT_EQ(string("Failed to get IShell for 'NetworkManager'"), plugin->Initialize(&service)); - - EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); - return nullptr; - })); - } - - virtual ~NetworkInitializedTest() override - { - plugin->Deinitialize(&service); - } - -}; - - -TEST_F(NetworkTest, RegisteredMethods) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getStbIp"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getInterfaces"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isInterfaceEnabled"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setInterfaceEnabled"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getDefaultInterface"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getIPSettings"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isConnectedToInternet"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPublicIP"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSTBIPFamily"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setConnectivityTestEndpoints"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getCaptivePortalURI"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startConnectivityMonitoring"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopConnectivityMonitoring"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setDefaultInterface"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setIPSettings"))); -} - - diff --git a/tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp b/tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp deleted file mode 100644 index 515c5e76e..000000000 --- a/tests/unittest/test_LegacyPlugin_WiFiManagerAPIs.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2024 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -#include -#include -#include -#include "ServiceMock.h" -#include "FactoriesImplementation.h" -#include "NetworkManagerLogger.h" -#include "LegacyWiFiManagerAPIs.h" -#include "ThunderPortability.h" - -using namespace std; -using namespace WPEFramework; -using namespace WPEFramework::Plugin; -using ::testing::NiceMock; - -class WiFiManagerTest : public ::testing::Test { -protected: - Core::ProxyType plugin; - Core::JSONRPC::Handler& handler; - DECL_CORE_JSONRPC_CONX connection; - Core::JSONRPC::Message message; - string response; - ServiceMock services; - - WiFiManagerTest() - : plugin(Core::ProxyType::Create()) - , handler(*(plugin)) - , INIT_CONX(1, 0) - { - - } - - virtual ~WiFiManagerTest() override - { - } -}; - -class WiFiManagerInitializedTest : public WiFiManagerTest { -protected: - NiceMock service; - WiFiManagerInitializedTest() - { - EXPECT_EQ(string("Failed to get IShell for 'NetworkManager'"), plugin->Initialize(&service)); - - EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); - return nullptr; - })); - } - - virtual ~WiFiManagerInitializedTest() override - { - plugin->Deinitialize(&service); - } - -}; - -TEST_F(WiFiManagerTest, TestedAPIsShouldExist) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startScan"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopScan"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("connect"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("disconnect"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("initiateWPSPairing"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("cancelWPSPairing"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("saveSSID"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("clearSSID"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPairedSSID"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getPairedSSIDInfo"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("isPaired"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getCurrentState"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getConnectedSSID"))); -} - -TEST_F(WiFiManagerInitializedTest, startScan) -{ - EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("startScan"), _T("{}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(WiFiManagerInitializedTest, stopScan) -{ - EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("stopScan"), _T("{}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(WiFiManagerInitializedTest, isPaired) -{ - EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("isPaired"), _T("{}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(WiFiManagerInitializedTest, disconnect) -{ - EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("disconnect"), _T("{}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(WiFiManagerInitializedTest, initiateWPSPairing) -{ - EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("initiateWPSPairing"), _T("{}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(WiFiManagerInitializedTest, cancelWPSPairing) -{ - EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("cancelWPSPairing"), _T("{}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(WiFiManagerInitializedTest, clearSSID) -{ - EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("clearSSID"), _T("{}"), response)); - EXPECT_EQ(response, string("")); -} -TEST_F(WiFiManagerInitializedTest, getPairedSSID) -{ - EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("getPairedSSID"), _T("{}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(WiFiManagerInitializedTest, getPairedSSIDInfo) -{ - EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("getPairedSSIDInfo"), _T("{}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(WiFiManagerInitializedTest, getCurrentState) -{ - EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("getCurrentState"), _T("{}"), response)); - EXPECT_EQ(response, string("")); -} -TEST_F(WiFiManagerInitializedTest, getConnectedSSID) -{ - EXPECT_EQ(Core::ERROR_UNAVAILABLE, handler.Invoke(connection, _T("getConnectedSSID"), _T("{}"), response)); - EXPECT_EQ(response, string("")); -} - diff --git a/tests/unittest/test_NetworkManager.cpp b/tests/unittest/test_NetworkManager.cpp deleted file mode 100644 index 1ecf60b43..000000000 --- a/tests/unittest/test_NetworkManager.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2024 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -#include -#include -#include -#include -#include "NetworkManagerLogger.h" -#include "NetworkManager.h" -#include "ServiceMock.h" -#include "FactoriesImplementation.h" -#include "IarmBusMock.h" -#include "ThunderPortability.h" - -using namespace std; -using namespace WPEFramework; -using namespace WPEFramework::Plugin; -using ::testing::NiceMock; - -class NetworkManagerTestBase : public ::testing::Test { -public: - IarmBusImplMock *p_iarmBusImplMock = nullptr ; - NetworkManagerTestBase() - { - p_iarmBusImplMock = new NiceMock ; - IarmBus::setImpl(p_iarmBusImplMock); - } - - ~NetworkManagerTestBase() { - delete p_iarmBusImplMock; - IarmBus::setImpl(nullptr); - } - -}; - -class NetworkManagerTest : public NetworkManagerTestBase { -protected: - - Core::ProxyType plugin; - Core::JSONRPC::Handler& handler; - DECL_CORE_JSONRPC_CONX connection; - string response; - - Core::JSONRPC::Message message; - - NetworkManagerTest() : plugin(Core::ProxyType::Create()), - handler(*plugin), - INIT_CONX(1, 0) - { - - } - -}; - -TEST_F(NetworkManagerTest, TestFunShouldExist) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetLogLevel"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetLogLevel"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetAvailableInterfaces"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetPrimaryInterface"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetInterfaceState"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetInterfaceState"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetIPSettings"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetIPSettings"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetStunEndpoint"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetStunEndpoint"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetConnectivityTestEndpoints"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("SetConnectivityTestEndpoints"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("IsConnectedToInternet"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetCaptivePortalURI"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("StartConnectivityMonitoring"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("StopConnectivityMonitoring"))); - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Exists(_T("GetPublicIP"))); -} - - -TEST_F(NetworkManagerTest, SetLogLevel) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("SetLogLevel"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, GetLogLevel) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetLogLevel"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, GetAvailableInterfaces) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, GetPrimaryInterface) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetPrimaryInterface"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, GetInterfaceState) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetInterfaceState"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - - -TEST_F(NetworkManagerTest, SetInterfaceState) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("SetInterfaceState"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, GetIPSettings) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetIPSettings"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, SetIPSettings) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("SetIPSettings"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, GetStunEndpoint) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetStunEndpoint"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, SetStunEndpoint) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("SetStunEndpoint"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, GetConnectivityTestEndpoints) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetCOnnectivityTestEndpoints"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, SetConnectivityTestEndpoints) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("SetConnectivityTestEndpoints"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, IsConnectedToInternet) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("IsConnectedToInternet"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, GetCaptivePortalURI) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetCaptivePortalURI"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, StartConnectivityMonitoring) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("StartConnectivityMonitoring"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, StopConnectivityMonitoring) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("StopConnectivityMonitoring"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - -TEST_F(NetworkManagerTest, GetPublicIP) -{ - EXPECT_EQ(Core::ERROR_UNKNOWN_KEY, handler.Invoke(connection, _T("GetPublicIP"), _T("{ \"success\": true, \"error\": \"... \" }"), response)); - EXPECT_EQ(response, string("")); - } - - - diff --git a/tests/unittest/test_UpnpDiscoveryManager.cpp b/tests/unittest/test_UpnpDiscoveryManager.cpp deleted file mode 100644 index 49b817165..000000000 --- a/tests/unittest/test_UpnpDiscoveryManager.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2025 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -#include -#include -#include -#include - -using ::testing::_; -using ::testing::Return; -using ::testing::Mock; - -class UpnpDiscoveryManagerTest : public ::testing::Test { -protected: - UpnpDiscoveryManager upnpDiscover; - GMainLoop* mainLoop; - void SetUp() override { - mainLoop = g_main_loop_new(nullptr, FALSE); - } -}; - -std::string getInterfaceWithDefaultRoute() { - std::string command = "ip -4 route show | grep default | awk '{print $5}'"; - std::array buffer; - std::string result; - - std::unique_ptr pipe(popen(command.c_str(), "r"), pclose); - if (!pipe) { - throw std::runtime_error("popen() failed!"); - } - - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - - // Remove trailing newline character - if (!result.empty() && result.back() == '\n') { - result.pop_back(); - } - return result; -} - -TEST_F(UpnpDiscoveryManagerTest, FindGatewayDeviceTest) -{ - // Invalid interface name - EXPECT_EQ(false, upnpDiscover.findGatewayDevice("123")); - - // Get router details on actual interface - std::string interfaceName = getInterfaceWithDefaultRoute(); - if (!interfaceName.empty()) { - std::cout << "Interface with default route: " << interfaceName << std::endl; - } else { - std::cout << "No default route interface found." << std::endl; - } - - // Valid interface name - EXPECT_EQ(true, upnpDiscover.findGatewayDevice(interfaceName)); -} - -TEST_F(UpnpDiscoveryManagerTest, routerDiscovery) -{ - auto threadHandler = [&]() { - std::this_thread::sleep_for(std::chrono::seconds(10)); - std::cout << "Thread finished sleeping." << std::endl; - if (this->mainLoop) - { - g_main_loop_quit(this->mainLoop); - g_main_loop_unref(this->mainLoop); - } - }; - // Get router details on actual interface - std::string interfaceName = getInterfaceWithDefaultRoute(); - if (!interfaceName.empty()) { - std::cout << "Interface with default route: " << interfaceName << std::endl; - } else { - std::cout << "No default route interface found." << std::endl; - } - mainLoop = g_main_loop_new(NULL, FALSE); - std::thread workerThread(threadHandler); - // Get the router details, mostly will timeout in corporate network - EXPECT_EQ(true, upnpDiscover.findGatewayDevice(interfaceName)); - g_main_loop_run(mainLoop); - workerThread.join(); -} diff --git a/tests/unittest/test_WiFiSignalStrengthMonitor.cpp b/tests/unittest/test_WiFiSignalStrengthMonitor.cpp deleted file mode 100644 index 15d9a6c0d..000000000 --- a/tests/unittest/test_WiFiSignalStrengthMonitor.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2024 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ -#include "NetworkManagerImplementation.h" -#include "NetworkManagerLogger.h" -#include "INetworkManager.h" -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace WPEFramework; -using namespace WPEFramework::Plugin; -namespace WPEFramework -{ - namespace Plugin - { - NetworkManagerImplementation* _instance = nullptr; - void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const string strength, const WiFiSignalQuality quality) - { - return; - } - - void NetworkManagerImplementation::ReportInternetStatusChange(const InternetStatus prevState, const InternetStatus currState) - { - return; - } - } -} - -class WiFiSignalQualityMonitorTest : public ::testing::Test { - protected: - WPEFramework::Plugin::WiFiSignalQualityMonitor monitor; -}; - -TEST_F(WiFiSignalQualityMonitorTest, GetSignalData_Connected) { - std::string ssid = "TestSSID"; - Exchange::INetworkManager::WiFiSignalQuality quality; - std::string strengthOut= "-55"; - monitor.getSignalData(ssid, quality, strengthOut); -} - -TEST_F(WiFiSignalQualityMonitorTest, StartWiFiSignalQualityMonitor) { - monitor.startWiFiSignalQualityMonitor(1); -} - -int main(int argc, char **argv) { - ::testing::InitGoogleMock(&argc, argv); - return RUN_ALL_TESTS(); -} From 66a4f4cadc8ea00276628fe42f8fd96dff723579 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 27 Aug 2025 16:41:05 -0400 Subject: [PATCH 170/271] RDKEMW-5842 - NetworkManager Plugin - Coverity Improvements (#213) * RDKEMW-5842 - NetworkManager Plugin - Coverity Improvements Reason for change: Addressed the networkmanager coverity issue reported in the last received full scan report Test Procedure: Coverity check Risks: Medium Signed-off-by: Gururaaja ESR Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- plugin/NetworkManagerConnectivity.cpp | 1 + plugin/NetworkManagerSecretAgent.cpp | 2 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 5 ++++ plugin/gnome/NetworkManagerGnomeProxy.cpp | 33 +++++++++++++--------- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 12 ++++---- plugin/gnome/NetworkManagerGnomeWIFI.h | 6 ++-- 6 files changed, 36 insertions(+), 23 deletions(-) diff --git a/plugin/NetworkManagerConnectivity.cpp b/plugin/NetworkManagerConnectivity.cpp index 5a3ffa3c2..c26fb287e 100644 --- a/plugin/NetworkManagerConnectivity.cpp +++ b/plugin/NetworkManagerConnectivity.cpp @@ -493,6 +493,7 @@ namespace WPEFramework m_ipversion = IP_ADDRESS_V4; m_Ipv4InternetState = INTERNET_UNKNOWN; m_Ipv6InternetState = INTERNET_UNKNOWN; + m_switchToInitial = true; startConnectivityMonitor(); } diff --git a/plugin/NetworkManagerSecretAgent.cpp b/plugin/NetworkManagerSecretAgent.cpp index aa6436465..c63f977ae 100644 --- a/plugin/NetworkManagerSecretAgent.cpp +++ b/plugin/NetworkManagerSecretAgent.cpp @@ -150,6 +150,7 @@ namespace WPEFramework { GError *error = NULL; isSecretAgentLoopRunning = false; + isSecurityAgentRegistered = false; NMLOG_INFO("SecretAgent Constructor"); GDBusconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); if (!GDBusconn) { @@ -158,7 +159,6 @@ namespace WPEFramework return; } - isSecurityAgentRegistered = false; startSecurityAgent(); } diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 2ba50ff3b..0ea9cdd01 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -207,6 +207,7 @@ namespace WPEFramework break; case NM_DEVICE_STATE_IP_CONFIG: GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP, nmUtils::ethIface()); + break; case NM_DEVICE_STATE_NEED_AUTH: case NM_DEVICE_STATE_SECONDARIES: case NM_DEVICE_STATE_ACTIVATED: @@ -522,6 +523,10 @@ namespace WPEFramework { NMLOG_DEBUG("GnomeNetworkManagerEvents"); GError *error = NULL; + eventThrdID = nullptr; + isEventThrdActive = false; + doScanNotify = false; + nmEvents.client = nm_client_new(NULL, &error); if(!nmEvents.client || error ) { diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 0c4e986f1..b085c2a86 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -315,8 +315,11 @@ namespace WPEFramework if(ifaceStr == wifiname || ifaceStr == ethname) // only wifi and ethenet taking { NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; - Exchange::INetworkManager::InterfaceDetails interface; - interface.mac = nm_device_get_hw_address(device); + Exchange::INetworkManager::InterfaceDetails interface{}; + const char* macAddr = nm_device_get_hw_address(device); + if(macAddr != nullptr) { + interface.mac = macAddr; + } deviceState = nm_device_get_state(device); interface.enabled = (deviceState >= NM_DEVICE_STATE_UNAVAILABLE)? true : false; if(deviceState > NM_DEVICE_STATE_DISCONNECTED && deviceState < NM_DEVICE_STATE_DEACTIVATING) @@ -392,21 +395,23 @@ namespace WPEFramework NMLOG_ERROR("nm_connection_get_interface_name is failed"); /* Temporary mitigation for nm_connection_get_interface_name failure */ if(m_ethConnected.load()) - ifacePtr = ethname.c_str(); + interface = ethname; else // default always wifi - ifacePtr = wifiname.c_str(); - } - - interface = ifacePtr; - m_defaultInterface = interface; - if(interface != wifiname && interface != ethname) - { - NMLOG_ERROR("primary interface is not eth/wlan"); - interface.clear(); + interface = wifiname; + rc = Core::ERROR_NONE; } else - rc = Core::ERROR_NONE; - + { + interface = ifacePtr; + if(interface != wifiname && interface != ethname) + { + NMLOG_ERROR("primary interface is not Ethernet or WiFi"); + interface.clear(); + } + else + rc = Core::ERROR_NONE; + } + m_defaultInterface = interface; return rc; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 1884502ea..4ecb8f900 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -39,7 +39,7 @@ namespace WPEFramework extern NetworkManagerImplementation* _instance; static std::atomic wpsProcessRun = {false}; - wifiManager::wifiManager() : m_client(nullptr), m_loop(nullptr), m_createNewConnection(false) { + wifiManager::wifiManager() : m_client(nullptr), m_loop(nullptr), m_createNewConnection(false), m_objectPath(nullptr), m_wifidevice(nullptr), m_source(nullptr) { NMLOG_INFO("wifiManager"); m_nmContext = g_main_context_new(); g_main_context_push_thread_default(m_nmContext); @@ -753,7 +753,7 @@ namespace WPEFramework return m_isSuccess; } - bool wifiManager::wifiConnect(Exchange::INetworkManager::WiFiConnectTo ssidInfo) + bool wifiManager::wifiConnect(const Exchange::INetworkManager::WiFiConnectTo &ssidInfoParam) { NMAccessPoint *AccessPoint = NULL; const GPtrArray* ApList = NULL; @@ -763,8 +763,9 @@ namespace WPEFramework Exchange::INetworkManager::WiFiSSIDInfo apinfo; std::string activeSSID{}; - NMLOG_DEBUG("wifi connect ssid: %s, security %d persist %d", ssidInfo.ssid.c_str(), ssidInfo.security, ssidInfo.persist); + NMLOG_DEBUG("wifi connect ssid: %s, security %d persist %d", ssidInfoParam.ssid.c_str(), ssidInfoParam.security, ssidInfoParam.persist); + Exchange::INetworkManager::WiFiConnectTo ssidInfo = ssidInfoParam; m_isSuccess = false; if(!createClientNewConnection()) return false; @@ -955,7 +956,7 @@ namespace WPEFramework g_main_loop_quit(_wifiManager->m_loop); } - bool wifiManager::addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo ssidinfo) + bool wifiManager::addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo &ssidinfo) { m_isSuccess = false; NMConnection *m_connection = NULL; @@ -1760,7 +1761,7 @@ namespace WPEFramework return false; } - bool wifiManager::setIpSettings(const string interface, const Exchange::INetworkManager::IPAddress address) + bool wifiManager::setIpSettings(const string interface, const Exchange::INetworkManager::IPAddress &address) { m_isSuccess = false; NMConnection *connection = NULL; @@ -1789,6 +1790,7 @@ namespace WPEFramework if(interface == nmUtils::ethIface()) { NMSettingConnection *settings = NULL; + const GPtrArray *connections = nm_device_get_available_connections(device); if (connections == NULL || connections->len == 0) { diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index d661ea75d..73e374033 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -52,18 +52,18 @@ namespace WPEFramework bool wifiDisconnect(); bool activateKnownConnection(std::string iface, std::string knowConnectionID=""); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); - bool wifiConnect(Exchange::INetworkManager::WiFiConnectTo ssidInfo); + bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo &ssidInfo); bool wifiScanRequest(std::string ssidReq = ""); bool isWifiScannedRecently(int timelimitInSec = 5); // default 5 sec as shotest scanning interval bool getKnownSSIDs(std::list& ssids); - bool addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo ssidinfo); + bool addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo &ssidinfo); bool removeKnownSSID(const string& ssid); bool quit(NMDevice *wifiNMDevice); bool wait(GMainLoop *loop, int timeOutMs = 10000); // default maximium set as 10 sec bool startWPS(); bool stopWPS(); bool setInterfaceState(std::string interface, bool enabled); - bool setIpSettings(const string interface, const Exchange::INetworkManager::IPAddress address); + bool setIpSettings(const string interface, const Exchange::INetworkManager::IPAddress &address); bool setPrimaryInterface(const string interface); private: NMDevice *getWifiDevice(); From 0339085328f79373a38da3324e60693d30aebb36 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:23:22 -0400 Subject: [PATCH 171/271] RDKEMW-7464 - Optimize the Internet Connectivity Monitoring approach (#214) * RDKEMW-7464 - Optimize the Internet Connectivity Monitoring approach Reason for change: Added device model and version details to the user agent of curl request and enabling the continuous monitoring only when the internet state is other fully connected Test Procedure: check the tcpdump Risks: Medium Signed-off-by: Gururaaja ESR Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- plugin/NetworkManagerConnectivity.cpp | 162 +++++++++++++++----------- plugin/NetworkManagerConnectivity.h | 2 + 2 files changed, 97 insertions(+), 67 deletions(-) diff --git a/plugin/NetworkManagerConnectivity.cpp b/plugin/NetworkManagerConnectivity.cpp index c26fb287e..068bfd098 100644 --- a/plugin/NetworkManagerConnectivity.cpp +++ b/plugin/NetworkManagerConnectivity.cpp @@ -237,9 +237,41 @@ namespace WPEFramework } } + static void getDeviceModel(std::string& modelNum, std::string& buildVersion) + { + const std::string filePath = "/etc/device.properties"; + std::ifstream file(filePath); + if (!file.is_open()) { + NMLOG_ERROR("Error opening file: %s", filePath.c_str()); + modelNum = "RDKDevice"; + buildVersion = "1.0"; + return; + } + + std::string line; + const std::string modelKey = "MODEL_NUM="; + const std::string buildKey = "BUILD_VERSION="; + + while (std::getline(file, line)) { + if (line.find(modelKey) == 0) { // line starts with "MODEL_NUM=" + modelNum = line.substr(modelKey.length()); // return value after '=' + } else if (line.find(buildKey) == 0) { // line starts with "BUILD_VERSION=" + buildVersion = line.substr(buildKey.length()); + } + if (!modelNum.empty() && !buildVersion.empty()) { + break; + } + } + if(modelNum.empty()) + modelNum = "RDKDevice"; + if(buildVersion.empty()) + buildVersion = "1.0"; + } + TestConnectivity::TestConnectivity(const std::vector& endpoints, long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion, std::string interface) { + getDeviceModel(m_deviceModel, m_buildVersion); internetSate = INTERNET_UNKNOWN; if(endpoints.size() < 1) { NMLOG_ERROR("Endpoints size error ! curl check not possible"); @@ -289,6 +321,9 @@ namespace WPEFramework std::vector curl_easy_handles; std::vector http_responses; struct curl_slist *chunk = NULL; + std::string userAgent = "RDKCaptiveCheck/1.1"; + userAgent += " " + m_deviceModel + "/" + m_buildVersion; + chunk = curl_slist_append(chunk, "Cache-Control: no-cache, no-store"); chunk = curl_slist_append(chunk, "Connection: close"); for (const auto& endpoint : endpoints) @@ -303,7 +338,8 @@ namespace WPEFramework logmsg += endpoint; /* set our custom set of headers */ curlSetOpt(curl_easy_handle, CURLOPT_HTTPHEADER, chunk); - curlSetOpt(curl_easy_handle, CURLOPT_USERAGENT, "RDKCaptiveCheck/1.0"); + NMLOG_INFO ("INTERNET_CONNECTIVITY_MONITORING_USERAGENT : %s", userAgent.c_str()); + curlSetOpt(curl_easy_handle, CURLOPT_USERAGENT, userAgent.c_str()); if(!headReq) { /* HTTPGET request added insted of HTTPHEAD request fix for DELIA-61526 */ @@ -515,28 +551,13 @@ namespace WPEFramework Exchange::INetworkManager::InternetStatus ConnectivityMonitor::getInternetState(std::string& interface, Exchange::INetworkManager::IPVersion& ipversion, bool ipVersionNotSpecified) { - if(!interface.empty()) /* interface is specified, so doing a fresh curl check not taking cache value */ - { - NMLOG_WARNING("getInternetState specified interface %s", interface.c_str()); - if(ipVersionNotSpecified) - ipversion = m_ipversion; /* ipversion not specified, taking global ip version */ + NMLOG_DEBUG("getInternetState specified interface %s", interface.c_str()); + if(ipVersionNotSpecified) + ipversion = m_ipversion; /* ipversion not specified, taking global ip version */ - TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, - NMCONNECTIVITY_CURL_HEAD_REQUEST, ipversion, interface); - return testInternet.getInternetState(); - } - - if(ipVersionNotSpecified) { - ipversion = m_ipversion; - NMLOG_DEBUG("ipversion %s - %s", ipversion == IP_ADDRESS_V4? "IPv4":"IPv6", getInternetStateString(m_InternetState.load())); - return m_InternetState.load(); - } - else if(ipversion == IP_ADDRESS_V4) - return m_Ipv4InternetState.load(); - else if(ipversion == IP_ADDRESS_V6) - return m_Ipv6InternetState.load(); - else - return INTERNET_UNKNOWN; + TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, + NMCONNECTIVITY_CURL_HEAD_REQUEST, ipversion, interface); + return testInternet.getInternetState(); } std::string ConnectivityMonitor::getCaptivePortalURI() @@ -729,60 +750,67 @@ namespace WPEFramework timeoutInSec = NMCONNECTIVITY_MONITOR_RETRY_INTERVAL; InitialRetryCount = 0; - TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, - NMCONNECTIVITY_CURL_HEAD_REQUEST, m_ipversion); - currentInternetState = testInternet.getInternetState(); + if(m_InternetState != INTERNET_FULLY_CONNECTED) + { + TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, + NMCONNECTIVITY_CURL_HEAD_REQUEST, m_ipversion); + currentInternetState = testInternet.getInternetState(); - if (currentInternetState == INTERNET_CAPTIVE_PORTAL) // if captive portal found copy the URL - m_captiveURI = testInternet.getCaptivePortal(); + if (currentInternetState == INTERNET_CAPTIVE_PORTAL) // if captive portal found copy the URL + m_captiveURI = testInternet.getCaptivePortal(); - if (currentInternetState != m_InternetState) - { - if (currentInternetState == INTERNET_NOT_AVAILABLE && m_InternetState == INTERNET_FULLY_CONNECTED) + if (currentInternetState != m_InternetState) { - DnsResolver dnsResolver(getConnectivityMonitorEndpoints()[0], m_ipversion, testInternet.getCurlError() ); // only first endpoint with specific ipversion - if (dnsResolver()) { - NMLOG_INFO("DNS resolved, success !!!"); - IdealRetryCount = 0; - currentInternetState = INTERNET_FULLY_CONNECTED; - } - else + if (currentInternetState == INTERNET_NOT_AVAILABLE && m_InternetState == INTERNET_FULLY_CONNECTED) { - NMLOG_WARNING("DNS resolve failed !!!"); - timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; // retry in 5 sec - IdealRetryCount++; - if (IdealRetryCount >= NM_CONNECTIVITY_MONITOR_RETRY_COUNT) { + DnsResolver dnsResolver(getConnectivityMonitorEndpoints()[0], m_ipversion, testInternet.getCurlError() ); // only first endpoint with specific ipversion + if (dnsResolver()) { + NMLOG_INFO("DNS resolved, success !!!"); IdealRetryCount = 0; - m_InternetState = INTERNET_NOT_AVAILABLE; - m_Ipv4InternetState = INTERNET_NOT_AVAILABLE; - m_Ipv6InternetState = INTERNET_NOT_AVAILABLE; // reset all states to NO_INTERNET - currentInternetState = INTERNET_NOT_AVAILABLE; - m_switchToInitial = true; // switch to initial check after 3 retries - InitialRetryCount = 1; // reset initial retry count it will not post the event - m_notify = true; - NMLOG_DEBUG("No internet retrying completed notifying !!!"); - } else { - NMLOG_INFO("No internet retrying connection check %d ...", IdealRetryCount); + currentInternetState = INTERNET_FULLY_CONNECTED; } + else + { + NMLOG_WARNING("DNS resolve failed !!!"); + timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; // retry in 5 sec + IdealRetryCount++; + if (IdealRetryCount >= NM_CONNECTIVITY_MONITOR_RETRY_COUNT) { + IdealRetryCount = 0; + m_InternetState = INTERNET_NOT_AVAILABLE; + m_Ipv4InternetState = INTERNET_NOT_AVAILABLE; + m_Ipv6InternetState = INTERNET_NOT_AVAILABLE; // reset all states to NO_INTERNET + currentInternetState = INTERNET_NOT_AVAILABLE; + m_switchToInitial = true; // switch to initial check after 3 retries + InitialRetryCount = 1; // reset initial retry count it will not post the event + m_notify = true; + NMLOG_DEBUG("No internet retrying completed notifying !!!"); + } else { + NMLOG_INFO("No internet retrying connection check %d ...", IdealRetryCount); + } + } + } else { + // a state change happened but it is not fully connected to no internet + // switch to initial check to get the correct state + m_switchToInitial = true; + InitialRetryCount = 0; + IdealRetryCount = 0; + timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; // retry in 5 sec + + if (m_ipversion == IP_ADDRESS_V4) + m_Ipv4InternetState = currentInternetState; + else if (m_ipversion == IP_ADDRESS_V6) + m_Ipv6InternetState = currentInternetState; + else + m_InternetState = currentInternetState; } - } else { - // a state change happened but it is not fully connected to no internet - // switch to initial check to get the correct state - m_switchToInitial = true; - InitialRetryCount = 0; + } else { // ideal case no change in network state IdealRetryCount = 0; - timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; // retry in 5 sec - - if (m_ipversion == IP_ADDRESS_V4) - m_Ipv4InternetState = currentInternetState; - else if (m_ipversion == IP_ADDRESS_V6) - m_Ipv6InternetState = currentInternetState; - else - m_InternetState = currentInternetState; + m_InternetState = currentInternetState; } - } else { // ideal case no change in network state - IdealRetryCount = 0; - m_InternetState = currentInternetState; + } + else + { + /* ToDo: new method "StartInternetMonitoring()" & "StopInternetMonitoring()" methods in a upcoming user story which can be called by EPG to identify LIMITED_INTERNET scenario. */ } } diff --git a/plugin/NetworkManagerConnectivity.h b/plugin/NetworkManagerConnectivity.h index 98f9c3675..210d75044 100644 --- a/plugin/NetworkManagerConnectivity.h +++ b/plugin/NetworkManagerConnectivity.h @@ -109,6 +109,8 @@ namespace WPEFramework long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion, std::string interface); Exchange::INetworkManager::InternetStatus checkInternetStateFromResponseCode(const std::vector& responses); std::string captivePortalURI; + std::string m_deviceModel{}; + std::string m_buildVersion{}; Exchange::INetworkManager::InternetStatus internetSate; int curlErrorCode = 0; template From 8a98488798c500589d03081cb31108b17a3e4657 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 27 Aug 2025 22:22:28 -0400 Subject: [PATCH 172/271] RDKEMW-6581 - Improve NetworkManager Configure Method (#208) * RDKEMW-6581 - Improve NetworkManager Configure Method Reason for change: Improved NetworkManager configure method by removed the Iconfiguration usage and modified the function to make input parameter as string instead of IShell Test Procedure: Check whether the configure is successful for networkmanager plugin Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR --- interface/INetworkManager.h | 2 +- plugin/NetworkManager.cpp | 19 +++++++------------ plugin/NetworkManager.h | 1 - plugin/NetworkManagerImplementation.cpp | 22 ++++++---------------- plugin/NetworkManagerImplementation.h | 6 ++---- tests/mocks/INetworkManagerMock.h | 2 +- 6 files changed, 17 insertions(+), 35 deletions(-) diff --git a/interface/INetworkManager.h b/interface/INetworkManager.h index edf369ffd..23f236779 100644 --- a/interface/INetworkManager.h +++ b/interface/INetworkManager.h @@ -260,7 +260,7 @@ namespace WPEFramework virtual uint32_t GetLogLevel(Logging& level /* @out */) = 0; /* @brief Configure the Network Manager plugin */ - virtual uint32_t Configure(PluginHost::IShell* service /* @in */) = 0; + virtual uint32_t Configure(const string configLine/* @in */) = 0; /* @event */ struct EXTERNAL INotification : virtual public Core::IUnknown diff --git a/plugin/NetworkManager.cpp b/plugin/NetworkManager.cpp index 250b3e06b..1049e5035 100644 --- a/plugin/NetworkManager.cpp +++ b/plugin/NetworkManager.cpp @@ -95,18 +95,13 @@ namespace WPEFramework _networkManager->Register(&_notification); SYSLOG(Logging::Startup, (_T("Configuring NetworkManager"))); - Exchange::IConfiguration* config = _networkManager->QueryInterface(); - if (config != nullptr) { - if(config->Configure(service) != Core::ERROR_NONE) - { - SYSLOG(Logging::Shutdown, (_T("NetworkManager failed to configure"))); - message = _T("NetworkManager failed to configure"); - } - else - { - SYSLOG(Logging::Startup, (_T("Configuring successful"))); - } - config->Release(); + if (_networkManager->Configure(service->ConfigLine()) != Core::ERROR_NONE) + { + SYSLOG(Logging::Shutdown, (_T("NetworkManager failed to configure"))); + } + else + { + SYSLOG(Logging::Startup, (_T("Configuring successful"))); } // Register all custom JSON-RPC methods SYSLOG(Logging::Startup, (_T("Registering JSONRPC Methods"))); diff --git a/plugin/NetworkManager.h b/plugin/NetworkManager.h index 1abce8d08..fe15db0f2 100644 --- a/plugin/NetworkManager.h +++ b/plugin/NetworkManager.h @@ -22,7 +22,6 @@ #include "Module.h" #include "INetworkManager.h" -#include #include "NetworkManagerLogger.h" #include diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index e61dcf8c9..0c3fa1567 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -119,29 +119,19 @@ namespace WPEFramework return Core::ERROR_NONE; } - uint32_t NetworkManagerImplementation::Configure(PluginHost::IShell* service) + uint32_t NetworkManagerImplementation::Configure(const string configLine) { LOG_ENTRY_FUNCTION(); Configuration config; - if (service) + if(configLine.empty()) { - string configLine = service->ConfigLine(); - if(configLine.empty()) - { - NMLOG_FATAL("config line : is empty !"); - return Core::ERROR_GENERAL; - } - else - { - NMLOG_INFO("Loading the incoming configuration : %s", configLine.c_str()); - config.FromString(configLine); - } + NMLOG_FATAL("config line : is empty !"); + return Core::ERROR_GENERAL; } else { - NMLOG_FATAL("Service is NULL!"); - return Core::ERROR_GENERAL; - + NMLOG_INFO("Loading the incoming configuration : %s", configLine.c_str()); + config.FromString(configLine); } NetworkManagerLogger::SetLevel(static_cast (config.loglevel.Value())); diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 9cf0d8b5e..e9eadb9aa 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -30,7 +30,6 @@ using namespace std; #include "INetworkManager.h" -#include #include "NetworkManagerLogger.h" #include "NetworkManagerConnectivity.h" #include "NetworkManagerStunClient.h" @@ -58,7 +57,7 @@ namespace WPEFramework { namespace Plugin { - class NetworkManagerImplementation : public Exchange::INetworkManager, public Exchange::IConfiguration + class NetworkManagerImplementation : public Exchange::INetworkManager { enum NetworkEvents { @@ -186,7 +185,6 @@ namespace WPEFramework BEGIN_INTERFACE_MAP(NetworkManagerImplementation) INTERFACE_ENTRY(Exchange::INetworkManager) - INTERFACE_ENTRY(Exchange::IConfiguration) END_INTERFACE_MAP // Handle Notification registration/removal @@ -261,7 +259,7 @@ namespace WPEFramework uint32_t GetLogLevel(Logging& level /* @out */) override; /* @brief configure network manager plugin */ - uint32_t Configure(PluginHost::IShell* service) override; + uint32_t Configure(const string configLine) override; /* Events */ void ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface); diff --git a/tests/mocks/INetworkManagerMock.h b/tests/mocks/INetworkManagerMock.h index eb3596277..b89926af1 100644 --- a/tests/mocks/INetworkManagerMock.h +++ b/tests/mocks/INetworkManagerMock.h @@ -52,7 +52,7 @@ class MockINetworkManager : public WPEFramework::Exchange::INetworkManager { MOCK_METHOD(uint32_t, SetLogLevel, (const Logging& level), (override)); MOCK_METHOD(uint32_t, SetHostname, (const string& hostname), (override)); MOCK_METHOD(uint32_t, GetLogLevel, (Logging& level), (override)); - MOCK_METHOD(uint32_t, Configure, (WPEFramework::PluginHost::IShell* service), (override)); + MOCK_METHOD(uint32_t, Configure, (const string configLine), (override)); MOCK_METHOD(uint32_t, Register, (WPEFramework::Exchange::INetworkManager::INotification* notification), (override)); MOCK_METHOD(uint32_t, Unregister, (WPEFramework::Exchange::INetworkManager::INotification* notification), (override)); MOCK_METHOD(uint32_t, AddRef, (), (const, override)); From 74dc46659b8f9c6c9fb3a79f8da731b6b5aee27b Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Wed, 27 Aug 2025 22:34:19 -0400 Subject: [PATCH 173/271] Release of 0.25.0 Release of 0.25.0 --- CHANGELOG.md | 11 +++++++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2807f47d6..66f415cb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,17 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [0.25.0] - 2025-08-27 +### Added +- Implemented SetHostname method which can send device's hostname over DHCP explicitly +- Implemented L1/L2 for netsrvmgr (RDK), libnm backends +- Clamped the WIFI Noise value to be within 0 dBm to -96 dBm +- Handled Plugin Termination sequence to stop the monitoring thread before exit +- Handled out-of-process plugin configuration as string +- Fixed Router Discovery to handle dual interface +- Fixed Internet Connectivity Monitoring to not to poll unless requested +- Addressed coverity reported issue + ## [0.24.0] - 2025-08-11 ### Added - Use incoming EAP-PrivateKey Password to connect to WiFi when given diff --git a/CMakeLists.txt b/CMakeLists.txt index fa8b7af93..12e377b83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 0) -set(VERSION_MINOR 24) +set(VERSION_MINOR 25) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index b43c4c811..5b8b438e3 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "development", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.24.0" + "version": "0.25.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 4dcf7807a..4d1d82b9a 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 0.24.0** +**Version: 0.25.0** **Status: :white_circle::white_circle::white_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.24.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.25.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From d5e3455c7b04b2022e9f3b1c2c708a27b84f25ae Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 29 Aug 2025 23:12:07 +0530 Subject: [PATCH 174/271] RDKEMW-6135 : Implement L1/L2 for Legacy NetworkManager libnm Implementation (#216) * connectivty test fix * libnm proxy event code * wifi Event and wifiConnect * more event test added --- plugin/gnome/NetworkManagerGnomeEvents.cpp | 12 +- plugin/gnome/NetworkManagerGnomeEvents.h | 1 + tests/l2Test/libnm/CMakeLists.txt | 13 +- .../l2Test/libnm/l2_test_libnmproxyEvent.cpp | 308 ++++++++++++++++++ tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp | 128 +++++++- tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp | 4 +- tests/mocks/GLibWraps.cpp | 16 +- tests/mocks/GLibWraps.h | 11 +- tests/mocks/GLibWrapsMock.h | 11 + tests/mocks/LibnmWraps.cpp | 54 +++ tests/mocks/LibnmWraps.h | 15 +- tests/mocks/LibnmWrapsMock.h | 62 +++- 12 files changed, 600 insertions(+), 35 deletions(-) create mode 100644 tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 0ea9cdd01..4c17b9f0a 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -71,7 +71,7 @@ namespace WPEFramework } } - static void deviceStateChangeCb(NMDevice *device, GParamSpec *pspec, NMEvents *nmEvents) + void GnomeNetworkManagerEvents::deviceStateChangeCb(NMDevice *device, GParamSpec *pspec, NMEvents *nmEvents) { static bool isEthDisabled = false; static bool isWlanDisabled = false; @@ -340,7 +340,7 @@ namespace WPEFramework /* ip events added only for eth0 and wlan0 */ if(ifname == nmUtils::ethIface() || ifname == nmUtils::wlanIface()) { - g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(deviceStateChangeCb), nmEvents); + g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(GnomeNetworkManagerEvents::deviceStateChangeCb), nmEvents); // TODO call notify::" NM_DEVICE_ACTIVE_CONNECTION if needed NMIPConfig *ipv4Config = nm_device_get_ip4_config(device); NMIPConfig *ipv6Config = nm_device_get_ip6_config(device); @@ -364,11 +364,11 @@ namespace WPEFramework std::string ifname = nm_device_get_iface(device); if(ifname == nmUtils::wlanIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::wlanIface()); - g_signal_handlers_disconnect_by_func(device, (gpointer)deviceStateChangeCb, nmEvents); + g_signal_handlers_disconnect_by_func(device, (gpointer)GnomeNetworkManagerEvents::deviceStateChangeCb, nmEvents); } else if(ifname == nmUtils::ethIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::ethIface()); - g_signal_handlers_disconnect_by_func(device, (gpointer)deviceStateChangeCb, nmEvents); + g_signal_handlers_disconnect_by_func(device, (gpointer)GnomeNetworkManagerEvents::deviceStateChangeCb, nmEvents); } } @@ -442,8 +442,8 @@ namespace WPEFramework NMLOG_WARNING("device %s is not enabled, So no event monitor", ifname.c_str()); continue; } - deviceStateChangeCb(device, nullptr, nullptr); //posting event if interface already connected - g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(deviceStateChangeCb), nmEvents); + GnomeNetworkManagerEvents::deviceStateChangeCb(device, nullptr, nullptr); //posting event if interface already connected + g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(GnomeNetworkManagerEvents::deviceStateChangeCb), nmEvents); NMIPConfig *ipv4Config = nm_device_get_ip4_config(device); NMIPConfig *ipv6Config = nm_device_get_ip6_config(device); if (ipv4Config) { diff --git a/plugin/gnome/NetworkManagerGnomeEvents.h b/plugin/gnome/NetworkManagerGnomeEvents.h index 0c19957c4..64a8aef32 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.h +++ b/plugin/gnome/NetworkManagerGnomeEvents.h @@ -48,6 +48,7 @@ namespace WPEFramework static void onActiveInterfaceChangeCb(std::string newInterface); // ReportActiveInterfaceChange static void onAvailableSSIDsCb(NMDeviceWifi *wifiDevice, GParamSpec *pspec, gpointer userData); // ReportAvailableSSIDs static void onWIFIStateChanged(uint8_t state); // ReportWiFiStateChange + static void deviceStateChangeCb(NMDevice *device, GParamSpec *pspec, NMEvents *nmEvents); public: static GnomeNetworkManagerEvents* getInstance(); diff --git a/tests/l2Test/libnm/CMakeLists.txt b/tests/l2Test/libnm/CMakeLists.txt index c7356c56c..8ec8721a7 100644 --- a/tests/l2Test/libnm/CMakeLists.txt +++ b/tests/l2Test/libnm/CMakeLists.txt @@ -23,6 +23,7 @@ FetchContent_MakeAvailable(googletest) message("networkmanager building with libnm") add_executable(${NM_LIBNM_PROXY_L2_TEST} + ${CMAKE_SOURCE_DIR}/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp ${CMAKE_SOURCE_DIR}/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp ${CMAKE_SOURCE_DIR}/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp ${CMAKE_SOURCE_DIR}/tests/l2Test/libnm/l2_test_libnmproxy.cpp @@ -58,6 +59,7 @@ target_compile_definitions(${NM_LIBNM_PROXY_L2_TEST} PRIVATE include_directories(${PROJECT_SOURCE_DIR}/interface) include_directories(${PROJECT_SOURCE_DIR}/plugin) +include_directories(${PROJECT_SOURCE_DIR}/plugin/gnome) include_directories(${PROJECT_SOURCE_DIR}/legacy) include_directories(${PROJECT_SOURCE_DIR}/tests/mocks) include_directories(${PROJECT_SOURCE_DIR}/tests/mocks/thunder) @@ -71,7 +73,7 @@ target_include_directories(${NM_LIBNM_PROXY_L2_TEST} PRIVATE ${gtest_SOURCE_DIR}/../googlemock/include ) -target_link_options(${NM_LIBNM_PROXY_L2_TEST} PRIVATE +target_link_options(${NM_LIBNM_PROXY_L2_TEST} PUBLIC -g -Wall -Wl,-wrap,system @@ -84,6 +86,12 @@ target_link_options(${NM_LIBNM_PROXY_L2_TEST} PRIVATE -Wl,-wrap,v_secure_pclose -Wl,-wrap,v_secure_system -Wl,-wrap,nm_device_get_iface + -Wl,-wrap,nm_active_connection_get_id + -Wl,-wrap,nm_active_connection_get_connection_type + -Wl,-wrap,nm_device_get_state_reason + -Wl,-wrap,nm_ip_address_get_family + -Wl,-wrap,nm_client_get_state + -Wl,-wrap,nm_client_get_nm_running -Wl,-wrap,nm_client_get_primary_connection -Wl,-wrap,nm_active_connection_get_connection -Wl,-wrap,nm_connection_get_interface_name @@ -111,6 +119,7 @@ target_link_options(${NM_LIBNM_PROXY_L2_TEST} PRIVATE -Wl,-wrap,nm_device_disconnect_async -Wl,-wrap,nm_device_disconnect_finish -Wl,-wrap,g_main_loop_is_running + -Wl,--wrap=g_signal_connect_data -Wl,-wrap,nm_access_point_get_flags -Wl,-wrap,nm_access_point_get_wpa_flags -Wl,-wrap,nm_access_point_get_rsn_flags @@ -155,10 +164,10 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") target_link_libraries(${NM_LIBNM_PROXY_L2_TEST} PRIVATE gmock_main + ${GLIB_LIBRARIES} ${NAMESPACE}Core::${NAMESPACE}Core ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${CURL_LIBRARIES} - ${GLIB_LIBRARIES} ${LIBNM_LIBRARIES} ${GIO_LIBRARIES} ) diff --git a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp new file mode 100644 index 000000000..3fccc439e --- /dev/null +++ b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp @@ -0,0 +1,308 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ +#include +#include +#include +#include +#include +#include +#include + +#include "FactoriesImplementation.h" +#include "WrapsMock.h" +#include "LibnmWrapsMock.h" +#include "GLibWrapsMock.h" +#include "ServiceMock.h" +#include "ThunderPortability.h" +#include "COMLinkMock.h" +#include "WorkerPoolImplementation.h" +#include "NetworkManagerImplementation.h" +#include "NetworkManagerGnomeEvents.h" +#include "NetworkManagerLogger.h" +#include "NetworkManager.h" +#include + +using namespace WPEFramework; +using ::testing::NiceMock; + +class NetworkManagerEventTest : public ::testing::Test { +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + DECL_CORE_JSONRPC_CONX connection; + Core::JSONRPC::Message message; + string response; + + /* every event callback */ + GCallback nmClientRunCb = NULL; + GCallback nmStateChange = NULL; + + WrapsImplMock *p_wrapsImplMock = nullptr; + GLibWrapsImplMock *p_gLibWrapsImplMock = nullptr; + LibnmWrapsImplMock *p_libnmWrapsImplMock = nullptr; + Core::ProxyType NetworkManagerImpl; + + NiceMock comLinkMock; + NiceMock service; + PLUGINHOST_DISPATCHER* dispatcher; + Core::ProxyType workerPool; + NiceMock factoriesImplementation; + + NetworkManagerEventTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , INIT_CONX(1, 0) + , workerPool(Core::ProxyType::Create(2, Core::Thread::DefaultStackSize(), 16)) + { + + p_libnmWrapsImplMock = new NiceMock ; + LibnmWraps::setImpl(p_libnmWrapsImplMock); + + p_gLibWrapsImplMock = new NiceMock ; + GLibWraps::setImpl(p_gLibWrapsImplMock); + + p_wrapsImplMock = new NiceMock ; + Wraps::setImpl(p_wrapsImplMock); + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Invoke( + [this]() { + return &comLinkMock; + })); + + ON_CALL(service, ConfigLine()) + .WillByDefault(::testing::Return( + "{" + " \"locator\":\"libWPEFrameworkNetworkManager.so\"," + " \"classname\":\"NetworkManager\"," + " \"callsign\":\"org.rdk.NetworkManager\"," + " \"startuporder\":55," + "}" + )); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillRepeatedly(::testing::Return(reinterpret_cast(0x100178))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_signal_connect_data(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::Invoke( + [&](gpointer instance, const gchar *detailed_signal, GCallback c_handler, + gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags) -> gulong { + + if(detailed_signal == NULL) + printf("g_signal_connect_data: NULL\n"); + else + printf("g_signal_connect_data - siganal: %s\n", detailed_signal); + return 0; + })); + + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const RPC::Object& object, const uint32_t waitTime, uint32_t& connectionId) { + NetworkManagerImpl = Core::ProxyType::Create(); + return &NetworkManagerImpl; + })); + + PluginHost::IFactories::Assign(&factoriesImplementation); + + Core::IWorkerPool::Assign(&(*workerPool)); + workerPool->Run(); + + dispatcher = static_cast( + plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); + dispatcher->Activate(&service); + EXPECT_EQ(string(""), (response = plugin->Initialize(&service))); + sleep(1); // Allow some time for initialization + } + + virtual void SetUp() override + { + } + + virtual ~NetworkManagerEventTest() override + { + plugin->Deinitialize(&service); + dispatcher->Deactivate(); + dispatcher->Release(); + + Core::IWorkerPool::Assign(nullptr); + workerPool.Release(); + + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + + LibnmWraps::setImpl(nullptr); + if (p_libnmWrapsImplMock != nullptr) + { + delete p_libnmWrapsImplMock; + p_libnmWrapsImplMock = nullptr; + } + + GLibWraps::setImpl(nullptr); + if (p_gLibWrapsImplMock != nullptr) + { + delete p_gLibWrapsImplMock; + p_gLibWrapsImplMock = nullptr; + } + + printf("~NetworkManagerEventTest\n"); + } +}; + +TEST_F(NetworkManagerEventTest, onInterfaceStateChangeCb) +{ + // Testing all interface state change events for Ethernet interface + WPEFramework::Plugin::GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, "eth0"); + WPEFramework::Plugin::GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_UP, "eth0"); + WPEFramework::Plugin::GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_DOWN, "eth0"); + WPEFramework::Plugin::GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP, "eth0"); + WPEFramework::Plugin::GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, "eth0"); + WPEFramework::Plugin::GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_DISABLED, "eth0"); +} + +TEST_F(NetworkManagerEventTest, onAddressChangeCb) +{ + // Test acquiring IPv4 address + WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth0", "192.168.1.100", true, false); + + // Test acquiring IPv6 address + WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth0", "2001:db8::1", true, true); + + // Test acquiring same IPv6 address again (should skip posting) + WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth0", "2001:db8::1", true, true); + + // Test acquiring different IPv6 address + WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth0", "2001:db8::2", true, true); + + // Test losing IPv4 address + WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth0", "", false, false); + + // Test losing IPv6 address + WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth0", "", false, true); + + // Test losing IP on interface with empty cache (should skip posting) + WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth1", "", false, false); + WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth1", "", false, true); +} + +TEST_F(NetworkManagerEventTest, onAvailableSSIDsCb) +{ + NMDeviceWifi *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + + GPtrArray* fakeAccessPoints = g_ptr_array_new(); + g_ptr_array_add(fakeAccessPoints, reinterpret_cast(0x833332)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_access_points(::testing::_)) + .WillOnce(::testing::Return(fakeAccessPoints)); + + // Create a fake SSID GBytes object + const char* ssid_str = "TestWiFiNetwork"; + GBytes* fake_ssid = g_bytes_new_static(ssid_str, strlen(ssid_str)); + + // AP property mocks + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) + .WillOnce(::testing::Return(fake_ssid)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) + .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) + .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength + + WPEFramework::Plugin::GnomeNetworkManagerEvents::onAvailableSSIDsCb(nullptr, nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::onAvailableSSIDsCb(deviceDummy, nullptr, nullptr); + + g_ptr_array_free(fakeAccessPoints, TRUE); +} + +TEST_F(NetworkManagerEventTest, onWIFIStateChanged) +{ + WPEFramework::Plugin::GnomeNetworkManagerEvents::onWIFIStateChanged(1); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNKNOWN)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_PREPARE)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_IP_CONFIG)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("eth0")) + .WillOnce(::testing::Return("eth0")) + .WillOnce(::testing::Return("eth0")) + .WillOnce(::testing::Return("eth0")) + .WillOnce(::testing::Return("eth0")) + .WillOnce(::testing::Return("wlan0")) + .WillOnce(::testing::Return("wlan0")) + .WillOnce(::testing::Return("wlan0")) + .WillOnce(::testing::Return("wlan0")) + .WillOnce(::testing::Return("wlan0")) + .WillOnce(::testing::Return("wlan0")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_SSID_NOT_FOUND)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT)); + + // Test with nullptr and with mock device + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(nullptr, nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); + + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} diff --git a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp index 6c7dd65fc..7c21205cc 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp @@ -1302,8 +1302,7 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_no_access_point) .WillOnce(::testing::Return(fakeAccessPoints)); // // TODO MOck addToKnownSSIDs call - // EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) - // .WillOnce(::testing::Return(reinterpret_cast(NULL))); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork_2\",\"passphrase\": \"123454321\",\"security\":1, \"persist\":false}"), response)); EXPECT_EQ(response, _T("{\"success\":false}")); @@ -1313,13 +1312,15 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_no_access_point) g_ptr_array_free(fakeAccessPoints, TRUE); g_ptr_array_free(fakeDevices, TRUE); } -/* + TEST_F(NetworkManagerWifiTest, WiFiConnect_with_different_ssid) { GPtrArray* fakeDevices = g_ptr_array_new(); NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); g_ptr_array_add(fakeDevices, deviceDummy); + NMAccessPoint *dummyAp = static_cast(g_object_new(NM_TYPE_ACCESS_POINT, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) .WillRepeatedly(::testing::Return(fakeDevices)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) @@ -1333,20 +1334,52 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_different_ssid) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) .WillOnce(::testing::Return(reinterpret_cast(0x333223))); + // AP property mocks + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) + .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) + .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) + .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength + const char* ssid_str = "TestWiFiNetwork_1"; GBytes* fake_ssid1 = g_bytes_new_static(ssid_str, strlen(ssid_str)); const char* ssid_str2 = "TestWiFiNetwork_2"; GBytes* fake_ssid2 = g_bytes_new_static(ssid_str2, strlen(ssid_str2)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) .WillOnce(::testing::Return(fake_ssid1)) + .WillOnce(::testing::Return(fake_ssid2)) .WillOnce(::testing::Return(fake_ssid2)); GPtrArray* fakeAccessPoints = g_ptr_array_new(); - g_ptr_array_add(fakeAccessPoints, reinterpret_cast(NULL)); + g_ptr_array_add(fakeAccessPoints, reinterpret_cast(dummyAp)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_access_points(::testing::_)) .WillOnce(::testing::Return(fakeAccessPoints)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork_2\",\"passphrase\": \"123454321\",\"security\":1, \"persist\":false}"), response)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_object_get_path(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("NULL"))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork_2\",\"passphrase\": \"123454\",\"security\":1, \"persist\":false}"), response)); EXPECT_EQ(response, _T("{\"success\":false}")); g_bytes_unref(fake_ssid1); @@ -1355,7 +1388,90 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_different_ssid) g_ptr_array_free(fakeAccessPoints, TRUE); g_ptr_array_free(fakeDevices, TRUE); } -*/ + +TEST_F(NetworkManagerWifiTest, WiFiConnect_with_different_good_password) +{ + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + NMAccessPoint *dummyAp = static_cast(g_object_new(NM_TYPE_ACCESS_POINT, NULL)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) + .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x333223))); + + // AP property mocks + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) + .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) + .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) + .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength + + const char* ssid_str = "TestWiFiNetwork_1"; + GBytes* fake_ssid1 = g_bytes_new_static(ssid_str, strlen(ssid_str)); + const char* ssid_str2 = "TestWiFiNetwork_2"; + GBytes* fake_ssid2 = g_bytes_new_static(ssid_str2, strlen(ssid_str2)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) + .WillOnce(::testing::Return(fake_ssid1)) + .WillOnce(::testing::Return(fake_ssid2)) + .WillOnce(::testing::Return(fake_ssid2)); + + GPtrArray* fakeAccessPoints = g_ptr_array_new(); + g_ptr_array_add(fakeAccessPoints, reinterpret_cast(dummyAp)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_access_points(::testing::_)) + .WillOnce(::testing::Return(fakeAccessPoints)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_object_get_path(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("NULL"))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork_2\",\"passphrase\": \"123454\",\"security\":1, \"persist\":false}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_bytes_unref(fake_ssid1); + g_bytes_unref(fake_ssid2); + g_object_unref(deviceDummy); + g_ptr_array_free(fakeAccessPoints, TRUE); + g_ptr_array_free(fakeDevices, TRUE); +} + TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_deviceFailed) { GPtrArray* fakeDevices = g_ptr_array_new(); diff --git a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp index 02fe37454..a5eddc3d8 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp @@ -617,6 +617,7 @@ TEST_F(NetworkManagerEventTest, GetSupportedSecurityModes) EXPECT_EQ(response, _T("{\"security\":{\"NONE\":0,\"WPA_PSK\":1,\"SAE\":2,\"EAP\":3},\"success\":true}")); } + TEST_F(NetworkManagerEventTest, IsConnectedToInternet_Failed) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Allow server to start @@ -649,7 +650,7 @@ TEST_F(NetworkManagerEventTest, IsConnectedToInternet_Failed) EXPECT_EQ(response, _T("{\"ipversion\":\"IPv4\",\"interface\":\"wlan0\",\"connected\":false,\"state\":0,\"status\":\"NO_INTERNET\",\"success\":true}")); } -/* This test case takes more time because of connectivity monitor existing logic */ +/* TEST_F(NetworkManagerEventTest, FULLY_CONNECTED_wait) { Core::Event onInternetStatusChange(false, true); @@ -696,3 +697,4 @@ TEST_F(NetworkManagerEventTest, FULLY_CONNECTED_wait) EXPECT_EQ(Core::ERROR_NONE, onInternetStatusChange.Lock()); EVENT_UNSUBSCRIBE(2, _T("onInternetStatusChange"), _T("org.rdk.NetworkManager"), message); } +*/ diff --git a/tests/mocks/GLibWraps.cpp b/tests/mocks/GLibWraps.cpp index ba6a2f15f..0427f8111 100644 --- a/tests/mocks/GLibWraps.cpp +++ b/tests/mocks/GLibWraps.cpp @@ -1,16 +1,16 @@ #include "GLibWraps.h" #include -// // Define the real function to ensure it exists for the wrapper to call -// extern "C" gboolean __real_g_main_loop_is_running(GMainLoop* loop) { -// // Default implementation if the real function can't be called -// return FALSE; -// } extern "C" gboolean __wrap_g_main_loop_is_running(GMainLoop* loop) { return GLibWraps::getInstance().g_main_loop_is_running(loop); } + extern "C" gulong __wrap_g_signal_connect_data(gpointer instance, const gchar *detailed_signal, GCallback c_handler, + gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags){ + return GLibWraps::getInstance().g_signal_connect_data(instance, detailed_signal, c_handler, data, destroy_data, connect_flags); + } + GLibWrapsImpl* GLibWraps::impl = nullptr; GLibWraps::GLibWraps() {} @@ -28,3 +28,9 @@ gboolean GLibWraps::g_main_loop_is_running(GMainLoop* loop) { EXPECT_NE(impl, nullptr); return impl->g_main_loop_is_running(loop); } + +gulong GLibWraps::g_signal_connect_data(gpointer instance, const gchar *detailed_signal, GCallback c_handler, + gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags) { + EXPECT_NE(impl, nullptr); + return impl->g_signal_connect_data(instance, detailed_signal, c_handler, data, destroy_data, connect_flags); +} diff --git a/tests/mocks/GLibWraps.h b/tests/mocks/GLibWraps.h index a7d42ad3f..c2465e47f 100644 --- a/tests/mocks/GLibWraps.h +++ b/tests/mocks/GLibWraps.h @@ -1,7 +1,7 @@ #pragma once #include -// #include +#include #include class GLibWrapsImpl { @@ -9,6 +9,8 @@ class GLibWrapsImpl { virtual ~GLibWrapsImpl() = default; virtual gboolean g_main_loop_is_running(GMainLoop* loop) = 0; + virtual gulong g_signal_connect_data(gpointer instance, const gchar *detailed_signal, GCallback c_handler, + gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags) = 0; }; class GLibWraps { @@ -22,4 +24,11 @@ class GLibWraps { static GLibWraps& getInstance(); static gboolean g_main_loop_is_running(GMainLoop* loop); + static gulong g_signal_connect_data(gpointer instance, const gchar *detailed_signal, GCallback c_handler, + gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags) __attribute__((visibility("default"))); }; + +extern "C" { + gulong __wrap_g_signal_connect_data(gpointer instance, const gchar *detailed_signal, GCallback c_handler, + gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags) __attribute__((visibility("default"))); +} diff --git a/tests/mocks/GLibWrapsMock.h b/tests/mocks/GLibWrapsMock.h index 3e413b54d..872deb773 100644 --- a/tests/mocks/GLibWrapsMock.h +++ b/tests/mocks/GLibWrapsMock.h @@ -4,6 +4,8 @@ #include "GLibWraps.h" extern "C" gboolean __real_g_main_loop_is_running(GMainLoop* loop); +extern "C" gulong __real_g_signal_connect_data(gpointer instance, const gchar *detailed_signal, GCallback c_handler, + gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags); class GLibWrapsImplMock : public GLibWrapsImpl { public: @@ -13,10 +15,19 @@ class GLibWrapsImplMock : public GLibWrapsImpl { [&](GMainLoop* loop) -> gboolean { return __real_g_main_loop_is_running(loop); })); + + ON_CALL(*this, g_signal_connect_data(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](gpointer instance, const gchar *detailed_signal, GCallback c_handler, + gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags) -> gulong { + return __real_g_signal_connect_data(instance, detailed_signal, c_handler, data, destroy_data, connect_flags); + })); } virtual ~GLibWrapsImplMock() = default; // Mock methods MOCK_METHOD(gboolean, g_main_loop_is_running, (GMainLoop* loop), (override)); + MOCK_METHOD(gulong, g_signal_connect_data, (gpointer instance, const gchar *detailed_signal, GCallback c_handler, + gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags), (override)); }; diff --git a/tests/mocks/LibnmWraps.cpp b/tests/mocks/LibnmWraps.cpp index afd36f734..e68ce06cf 100644 --- a/tests/mocks/LibnmWraps.cpp +++ b/tests/mocks/LibnmWraps.cpp @@ -6,6 +6,13 @@ extern "C" gint64 __wrap_nm_device_wifi_get_last_scan(NMDeviceWifi *device) { return LibnmWraps::getInstance().nm_device_wifi_get_last_scan(device); } +extern "C" NMState __wrap_nm_client_get_state(NMClient *client) { + return LibnmWraps::getInstance().nm_client_get_state(client); +} + +extern "C" gboolean __wrap_nm_client_get_nm_running(NMClient *client) { + return LibnmWraps::getInstance().nm_client_get_nm_running(client); +} extern "C" void __wrap_nm_device_set_autoconnect(NMDevice *device, gboolean autoconnect) { LibnmWraps::getInstance().nm_device_set_autoconnect(device, autoconnect); } @@ -284,6 +291,23 @@ extern "C" gboolean __wrap_nm_device_wifi_request_scan_finish(NMDeviceWifi *devi return LibnmWraps::getInstance().nm_device_wifi_request_scan_finish(device, result, error); } + +extern "C" const char* __wrap_nm_active_connection_get_id(NMActiveConnection *connection) { + return LibnmWraps::getInstance().nm_active_connection_get_id(connection); +} + +extern "C" const char* __wrap_nm_active_connection_get_connection_type(NMActiveConnection *connection) { + return LibnmWraps::getInstance().nm_active_connection_get_connection_type(connection); +} + +extern "C" NMDeviceStateReason __wrap_nm_device_get_state_reason(NMDevice *device) { + return LibnmWraps::getInstance().nm_device_get_state_reason(device); +} + +extern "C" int __wrap_nm_ip_address_get_family(NMIPAddress *address) { + return LibnmWraps::getInstance().nm_ip_address_get_family(address); +} + LibnmWrapsImpl* LibnmWraps::impl = nullptr; LibnmWraps::LibnmWraps() {} @@ -639,3 +663,33 @@ gboolean LibnmWraps::nm_remote_connection_delete(NMRemoteConnection *connection, EXPECT_NE(impl, nullptr); return impl->nm_remote_connection_delete(connection, cancellable, error); } + +NMState LibnmWraps::nm_client_get_state(NMClient *client) { + EXPECT_NE(impl, nullptr); + return impl->nm_client_get_state(client); +} + +gboolean LibnmWraps::nm_client_get_nm_running(NMClient *client) { + EXPECT_NE(impl, nullptr); + return impl->nm_client_get_nm_running(client); +} + +const char* LibnmWraps::nm_active_connection_get_id(NMActiveConnection* connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_active_connection_get_id(connection); +} + +const char* LibnmWraps::nm_active_connection_get_connection_type(NMActiveConnection* connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_active_connection_get_connection_type(connection); +} + +NMDeviceStateReason LibnmWraps::nm_device_get_state_reason(NMDevice* device) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_get_state_reason(device); +} + +int LibnmWraps::nm_ip_address_get_family(NMIPAddress* address) { + EXPECT_NE(impl, nullptr); + return impl->nm_ip_address_get_family(address); +} diff --git a/tests/mocks/LibnmWraps.h b/tests/mocks/LibnmWraps.h index 8fb5a6dfd..6a6a392dc 100644 --- a/tests/mocks/LibnmWraps.h +++ b/tests/mocks/LibnmWraps.h @@ -125,6 +125,14 @@ class LibnmWrapsImpl { virtual NMSettingWireless *nm_connection_get_setting_wireless(NMConnection *connection) = 0; virtual GBytes *nm_setting_wireless_get_ssid(NMSettingWireless *setting) = 0; virtual gboolean nm_remote_connection_delete(NMRemoteConnection *connection, GCancellable *cancellable, GError **error) = 0; + virtual NMState nm_client_get_state(NMClient *client) = 0; + virtual gboolean nm_client_get_nm_running(NMClient *client) = 0; + virtual const char* nm_active_connection_get_id(NMActiveConnection *connection) = 0; + virtual const char* nm_active_connection_get_connection_type(NMActiveConnection *connection) = 0; + virtual NMDeviceStateReason nm_device_get_state_reason(NMDevice *device) = 0; + virtual int nm_ip_address_get_family(NMIPAddress *address) = 0; + + }; class LibnmWraps { @@ -137,7 +145,12 @@ class LibnmWraps { static void setImpl(LibnmWrapsImpl* newImpl); static LibnmWraps& getInstance(); - // New APIs + static const char* nm_active_connection_get_id(NMActiveConnection *connection); + static const char* nm_active_connection_get_connection_type(NMActiveConnection *connection); + static NMDeviceStateReason nm_device_get_state_reason(NMDevice *device); + static int nm_ip_address_get_family(NMIPAddress *address); + static NMState nm_client_get_state(NMClient *client); + static gboolean nm_client_get_nm_running(NMClient *client); static gint64 nm_device_wifi_get_last_scan(NMDeviceWifi *device); static void nm_device_set_autoconnect(NMDevice *device, gboolean autoconnect); static const GPtrArray* nm_client_get_connections(NMClient *client); diff --git a/tests/mocks/LibnmWrapsMock.h b/tests/mocks/LibnmWrapsMock.h index 462c76a59..8e766ddac 100644 --- a/tests/mocks/LibnmWrapsMock.h +++ b/tests/mocks/LibnmWrapsMock.h @@ -5,6 +5,10 @@ #include "LibnmWraps.h" #include +extern "C" const char* __real_nm_active_connection_get_id(NMActiveConnection *connection); +extern "C" const char* __real_nm_active_connection_get_connection_type(NMActiveConnection *connection); +extern "C" NMDeviceStateReason __real_nm_device_get_state_reason(NMDevice *device); +extern "C" int __real_nm_ip_address_get_family(NMIPAddress *address); extern "C" const char* __real_nm_device_get_iface(NMDevice* device); extern "C" gboolean __real_nm_remote_connection_delete(NMRemoteConnection *connection, GCancellable *cancellable, GError **error); extern "C" NMActiveConnection* __real_nm_client_get_primary_connection(NMClient *client); @@ -35,7 +39,6 @@ extern "C" NMDhcpConfig* __real_nm_active_connection_get_dhcp4_config(NMActiveCo extern "C" NMDhcpConfig* __real_nm_active_connection_get_dhcp6_config(NMActiveConnection* connection); extern "C" const char* __real_nm_dhcp_config_get_one_option(NMDhcpConfig* config, const char* option); -// Access Point API real functions extern "C" NM80211ApFlags __real_nm_access_point_get_flags(NMAccessPoint *ap); extern "C" NM80211ApSecurityFlags __real_nm_access_point_get_wpa_flags(NMAccessPoint *ap); extern "C" NM80211ApSecurityFlags __real_nm_access_point_get_rsn_flags(NMAccessPoint *ap); @@ -47,7 +50,6 @@ extern "C" guint32 __real_nm_access_point_get_max_bitrate(NMAccessPoint *ap); extern "C" guint8 __real_nm_access_point_get_strength(NMAccessPoint *ap); extern "C" NMAccessPoint* __real_nm_device_wifi_get_active_access_point(NMDeviceWifi *device); -// WiFi Scan API real functions extern "C" void __real_nm_device_wifi_request_scan_async(NMDeviceWifi *device, GCancellable *cancellable, GAsyncReadyCallback callback, @@ -63,8 +65,6 @@ extern "C" gboolean __real_nm_device_wifi_request_scan_finish(NMDeviceWifi *devi extern "C" const GPtrArray *__real_nm_device_wifi_get_access_points(NMDeviceWifi *device); extern "C" const GPtrArray *__real_nm_device_get_available_connections(NMDevice *device); - -// New API real functions extern "C" gint64 __real_nm_device_wifi_get_last_scan(NMDeviceWifi *device); extern "C" void __real_nm_device_set_autoconnect(NMDevice *device, gboolean autoconnect); extern "C" const GPtrArray* __real_nm_client_get_connections(NMClient *client); @@ -117,7 +117,6 @@ extern "C" gboolean __real_nm_client_dbus_set_property_finish(NMClient *client, GAsyncResult *result, GError **error); -// New real functions for commit changes and DHCP hostname extern "C" gboolean __real_nm_remote_connection_commit_changes(NMRemoteConnection *connection, gboolean save_to_disk, GCancellable *cancellable, @@ -127,12 +126,37 @@ extern "C" gboolean __real_nm_setting_ip_config_get_dhcp_send_hostname(NMSetting extern "C" void __real_nm_connection_add_setting(NMConnection *connection, NMSetting *setting); extern "C" NMSettingWireless *__real_nm_connection_get_setting_wireless(NMConnection *connection); extern "C" GBytes *__real_nm_setting_wireless_get_ssid(NMSettingWireless *setting); +extern "C" NMState __real_nm_client_get_state(NMClient *client); +extern "C" gboolean __real_nm_client_get_nm_running(NMClient *client); class LibnmWrapsImplMock : public LibnmWrapsImpl { public: LibnmWrapsImplMock() : LibnmWrapsImpl() { + ON_CALL(*this, nm_active_connection_get_id(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMActiveConnection* connection) -> const char* { + return __real_nm_active_connection_get_id(connection); + })); + + ON_CALL(*this, nm_active_connection_get_connection_type(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMActiveConnection* connection) -> const char* { + return __real_nm_active_connection_get_connection_type(connection); + })); + + ON_CALL(*this, nm_device_get_state_reason(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMDevice* device) -> NMDeviceStateReason { + return __real_nm_device_get_state_reason(device); + })); + + ON_CALL(*this, nm_ip_address_get_family(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMIPAddress* address) -> int { + return __real_nm_ip_address_get_family(address); + })); ON_CALL(*this, nm_device_wifi_get_last_scan(::testing::_)) .WillByDefault(::testing::Invoke( [&](NMDeviceWifi* device) -> gint64 { @@ -445,11 +469,21 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { [&](NMRemoteConnection *connection, GCancellable *cancellable, GError **error) -> gboolean { return __real_nm_remote_connection_delete(connection, cancellable, error); })); + ON_CALL(*this, nm_client_get_state(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client) -> NMState { + return __real_nm_client_get_state(client); + })); + + ON_CALL(*this, nm_client_get_nm_running(::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMClient* client) -> gboolean { + return __real_nm_client_get_nm_running(client); + })); } -// NMActiveConnection *nm_device_get_active_connection(NMDevice *device); + virtual ~LibnmWrapsImplMock() = default; - // Mock methods MOCK_METHOD(const char*, nm_device_get_iface, (NMDevice* device), (override)); MOCK_METHOD(NMDevice*, nm_client_get_device_by_iface, (NMClient *client, const char *iface), (override)); MOCK_METHOD(NMDeviceState, nm_device_get_state, (NMDevice *device), (override)); @@ -479,7 +513,6 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { MOCK_METHOD(NMDhcpConfig*, nm_active_connection_get_dhcp4_config, (NMActiveConnection* connection), (override)); MOCK_METHOD(const char*, nm_dhcp_config_get_one_option, (NMDhcpConfig* config, const char* option), (override)); - // Access Point API mock methods MOCK_METHOD(NM80211ApFlags, nm_access_point_get_flags, (NMAccessPoint *ap), (override)); MOCK_METHOD(NM80211ApSecurityFlags, nm_access_point_get_wpa_flags, (NMAccessPoint *ap), (override)); MOCK_METHOD(NM80211ApSecurityFlags, nm_access_point_get_rsn_flags, (NMAccessPoint *ap), (override)); @@ -496,12 +529,10 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { MOCK_METHOD(void, nm_client_dbus_set_property, (NMClient *client, const char *object_path, const char *interface_name, const char *property_name, GVariant *value, int timeout_msec, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); MOCK_METHOD(gboolean, nm_client_dbus_set_property_finish, (NMClient *client, GAsyncResult *result, GError **error), (override)); - // WiFi Scan API mock methods MOCK_METHOD(void, nm_device_wifi_request_scan_async, (NMDeviceWifi *device, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); MOCK_METHOD(void, nm_device_wifi_request_scan_options_async, (NMDeviceWifi *device, GVariant *options, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); MOCK_METHOD(gboolean, nm_device_wifi_request_scan_finish, (NMDeviceWifi *device, GAsyncResult *result, GError **error), (override)); - - // New API mock methods + MOCK_METHOD(gint64, nm_device_wifi_get_last_scan, (NMDeviceWifi *device), (override)); MOCK_METHOD(void, nm_device_set_autoconnect, (NMDevice *device, gboolean autoconnect), (override)); MOCK_METHOD(const GPtrArray*, nm_client_get_connections, (NMClient *client), (override)); @@ -510,8 +541,7 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { MOCK_METHOD(void, nm_client_activate_connection_async, (NMClient *client, NMConnection *connection, NMDevice *device, const char *specific_object, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); MOCK_METHOD(NMActiveConnection*, nm_client_activate_connection_finish, (NMClient *client, GAsyncResult *result, GError **error), (override)); MOCK_METHOD(void, nm_client_add_and_activate_connection_async, (NMClient *client, NMConnection *partial, NMDevice *device, const char *specific_object, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); - - // New commit and DHCP hostname mock methods + MOCK_METHOD(gboolean, nm_remote_connection_commit_changes, (NMRemoteConnection *connection, gboolean save_to_disk, GCancellable *cancellable, GError **error), (override)); MOCK_METHOD(const char*, nm_setting_ip_config_get_dhcp_hostname, (NMSettingIPConfig *setting), (override)); MOCK_METHOD(gboolean, nm_setting_ip_config_get_dhcp_send_hostname, (NMSettingIPConfig *setting), (override)); @@ -523,4 +553,10 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { MOCK_METHOD(void, nm_client_add_connection2, (NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, GVariant *args, gboolean ignore_out_result, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); MOCK_METHOD(NMRemoteConnection*, nm_client_add_connection2_finish, (NMClient *client, GAsyncResult *result, GVariant **out_result, GError **error), (override)); MOCK_METHOD(gboolean, nm_remote_connection_delete, (NMRemoteConnection *connection, GCancellable *cancellable, GError **error), (override)); + MOCK_METHOD(NMState, nm_client_get_state, (NMClient *client), (override)); + MOCK_METHOD(gboolean, nm_client_get_nm_running, (NMClient *client), (override)); + MOCK_METHOD(const char*, nm_active_connection_get_id, (NMActiveConnection *connection), (override)); + MOCK_METHOD(const char*, nm_active_connection_get_connection_type, (NMActiveConnection *connection), (override)); + MOCK_METHOD(NMDeviceStateReason, nm_device_get_state_reason, (NMDevice *device), (override)); + MOCK_METHOD(int, nm_ip_address_get_family, (NMIPAddress *address), (override)); }; From e868794a30d2a674539d23b3ec5a4522793155db Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 29 Aug 2025 15:49:33 -0400 Subject: [PATCH 175/271] RDKEMW-5842 - Addressing spurious wakeup coverity issue (#215) * RDKEMW-5842 - Addressing spurious wakeup coverity issue Reason for change: Added an atomic variable which will be set before notify is called and the same is used to check the signal received Test Procedure: Check the connectivity monitor function properly without regression Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR --------- Signed-off-by: Gururaaja ESR Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- plugin/NetworkManagerConnectivity.cpp | 8 +++++++- plugin/NetworkManagerConnectivity.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/plugin/NetworkManagerConnectivity.cpp b/plugin/NetworkManagerConnectivity.cpp index 068bfd098..2e7a91743 100644 --- a/plugin/NetworkManagerConnectivity.cpp +++ b/plugin/NetworkManagerConnectivity.cpp @@ -530,6 +530,7 @@ namespace WPEFramework m_Ipv4InternetState = INTERNET_UNKNOWN; m_Ipv6InternetState = INTERNET_UNKNOWN; m_switchToInitial = true; + m_wakeupMonitoring = false; startConnectivityMonitor(); } @@ -576,6 +577,7 @@ namespace WPEFramework { if (m_cmRunning) { + m_wakeupMonitoring = true; m_cmCv.notify_one(); NMLOG_DEBUG("connectivity monitor is already running"); return true; @@ -596,6 +598,7 @@ namespace WPEFramework bool ConnectivityMonitor::stopConnectivityMonitor() { m_cmRunning = false; + m_wakeupMonitoring = true; m_cmCv.notify_one(); if(m_cmThrdID.joinable()) m_cmThrdID.join(); @@ -609,6 +612,7 @@ namespace WPEFramework bool ConnectivityMonitor::switchToInitialCheck() { m_switchToInitial = true; + m_wakeupMonitoring = true; m_cmCv.notify_one(); if(_instance != nullptr) { NMLOG_INFO("switching to initial check - eth %s - wlan %s", @@ -825,8 +829,10 @@ namespace WPEFramework // Wait for next interval std::unique_lock lock(m_cmMutex); - if (m_cmCv.wait_for(lock, std::chrono::seconds(timeoutInSec)) != std::cv_status::timeout) { + if (m_cmCv.wait_for(lock, std::chrono::seconds(timeoutInSec), [this] { return m_wakeupMonitoring.load(); })) + { NMLOG_INFO("connectivity monitor received signal. skipping %d sec interval", timeoutInSec); + m_wakeupMonitoring = false; } } } diff --git a/plugin/NetworkManagerConnectivity.h b/plugin/NetworkManagerConnectivity.h index 210d75044..5440f7752 100644 --- a/plugin/NetworkManagerConnectivity.h +++ b/plugin/NetworkManagerConnectivity.h @@ -149,6 +149,7 @@ namespace WPEFramework std::mutex m_cmMutex; std::atomic m_notify; std::atomic m_switchToInitial; + std::atomic m_wakeupMonitoring; std::string m_captiveURI; std::atomic m_InternetState; // IPv4 or IPv6 std::atomic m_Ipv4InternetState; // IPv4 From 7abe7ab0484abda2d372bd24fbcc6df0b2c08708 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 29 Aug 2025 17:27:38 -0400 Subject: [PATCH 176/271] Release of 1.0.0 Release of 1.0.0 --- CHANGELOG.md | 6 ++++++ CMakeLists.txt | 4 ++-- definition/NetworkManager.json | 6 +++--- docs/NetworkManagerPlugin.md | 12 +++++++----- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66f415cb0..a294157cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.0.0] - 2025-08-29 +### Added +- Implemented additional L1/L2 for libnm backends +- Addressed Coverity issues in Connectivity Monitoring Thread +- Marking official production release. + ## [0.25.0] - 2025-08-27 ### Added - Implemented SetHostname method which can send device's hostname over DHCP explicitly diff --git a/CMakeLists.txt b/CMakeLists.txt index 12e377b83..6e57e5a28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,8 @@ project(NetworkManager) find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") -set(VERSION_MAJOR 0) -set(VERSION_MINOR 25) +set(VERSION_MAJOR 1) +set(VERSION_MINOR 0) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 5b8b438e3..c1918932e 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -6,10 +6,10 @@ "class": "NetworkManager", "callsign": "org.rdk.NetworkManager", "locator": "libWPEFrameworkNetworkManager.so", - "status": "development", + "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "0.25.0" + "version": "1.0.0" }, "definitions": { "success": { @@ -1301,7 +1301,7 @@ } }, "SetHostname": { - "summary": "To configure a custom DHCP hostname instead of the default (which is typically the device name).", + "summary": "To configure a custom DHCP hostname instead of the default (which is typically the device name).\n\nSetting host name will take effect upon reconnect; like, device reboot, wake-up from deepsleep, while connecting to new Wi-Fi connection, WiFi On/Off, or renewal of the DHCP lease.", "params": { "type": "object", "properties": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 4d1d82b9a..8632c28ce 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,9 +2,9 @@ # NetworkManager Plugin -**Version: 0.25.0** +**Version: 1.0.0** -**Status: :white_circle::white_circle::white_circle:** +**Status: :black_circle::black_circle::black_circle:** org.rdk.NetworkManager interface for Thunder framework. @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 0.25.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.0.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity @@ -102,7 +102,7 @@ NetworkManager interface methods: | [GetWiFiSignalQuality](#method.GetWiFiSignalQuality) | Get WiFi signal quality of currently connected SSID | | [GetSupportedSecurityModes](#method.GetSupportedSecurityModes) | Returns the Wifi security modes that the device supports | | [GetWifiState](#method.GetWifiState) | Returns the current Wifi State | -| [SetHostname](#method.SetHostname) | To configure a custom DHCP hostname instead of the default (which is typically the device name). | +| [SetHostname](#method.SetHostname) | To configure a custom DHCP hostname instead of the default (which is typically the device name) | ## *SetLogLevel [method](#head.Methods)* @@ -1671,7 +1671,9 @@ This method takes no parameters. ## *SetHostname [method](#head.Methods)* -To configure a custom DHCP hostname instead of the default (which is typically the device name), note that the change will only take effect after a device reboot, creating a new Wi-Fi connection, reactivation of existing NetworkManager connection, or renewal of the DHCP lease. +To configure a custom DHCP hostname instead of the default (which is typically the device name). + +Setting host name will take effect upon reconnect; like, device reboot, wake-up from deepsleep, while connecting to new Wi-Fi connection, WiFi On/Off, or renewal of the DHCP lease. ### Parameters From b35aa21dfc650e3b39dcfae0f1c48810359b23e5 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 12 Sep 2025 20:32:00 +0530 Subject: [PATCH 177/271] RDKEMW-7894 : Unable to connect to WiFi/WPS when device is rebooted (#223) Reason for change: NW deletes existing device object and creates new object for wlan0 and we miss those events. We must subscribe to that event as well. Test Procedure: Verify Wifi scanning after FSR Priority:P1 Risks: Medium Signed-off-by: Muhammed Rafi c --- plugin/gnome/NetworkManagerGnomeEvents.cpp | 11 +++++++++-- plugin/gnome/NetworkManagerGnomeProxy.cpp | 2 +- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 2 ++ plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 4c17b9f0a..c5e75b482 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -351,11 +351,19 @@ namespace WPEFramework if (ipv6Config) { g_signal_connect(ipv6Config, "notify::addresses", G_CALLBACK(ip6ChangedCb), device); } + + if (NM_IS_DEVICE_WIFI(device)) + { + // Register signal handler for WiFi scanning events to detect when scan operations complete + nmEvents->wifiDevice = NM_DEVICE_WIFI(device); + NMLOG_INFO("WIFI device added, adding signal handler for last-scan"); + g_signal_connect(nmEvents->wifiDevice, "notify::" NM_DEVICE_WIFI_LAST_SCAN, G_CALLBACK(GnomeNetworkManagerEvents::onAvailableSSIDsCb), nmEvents); + } } } else NMLOG_DEBUG("device error null"); - } + } static void deviceRemovedCB(NMClient *client, NMDevice *device, NMEvents *nmEvents) { @@ -378,7 +386,6 @@ namespace WPEFramework // (gpointer)onActiveConnectionStateChanged, // NULL ); // NMLOG_ERROR("Disconnected %u signal handlers\n", disconnected_count); - } static void clientStateChangedCb (NMClient *client, GParamSpec *pspec, gpointer user_data) diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index b085c2a86..a71a87c65 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -947,7 +947,7 @@ namespace WPEFramework if(!wifi->wifiScanRequest()) { - NMLOG_WARNING("scanning reuest failed; trying to connect wps"); + NMLOG_WARNING("scanning request failed; trying to connect wps"); } if(wifi->startWPS()) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 4ecb8f900..d63406d1d 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -1171,6 +1171,7 @@ namespace WPEFramework wifiManager *_wifiManager = (static_cast(user_data)); if(nm_device_wifi_request_scan_finish(NM_DEVICE_WIFI(object), result, &error)) { _wifiManager->m_isSuccess = true; + NMLOG_DEBUG("wifi scanning request success .."); } else { @@ -1213,6 +1214,7 @@ namespace WPEFramework g_variant_unref(options); // Unreference the GVariant after passing it to the async function } else { + NMLOG_INFO("staring normal wifi scanning .."); nm_device_wifi_request_scan_async(wifiDevice, NULL, wifiScanCb, this); } wait(m_loop); diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp index ce2930596..99248e97e 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp @@ -303,7 +303,7 @@ namespace WPEFramework _nmGdbusEvents->setwifiScanOptions(false); if(!_nmGdbusClient->startWifiScan()) { - NMLOG_WARNING("scanning reuest failed; trying to connect wps"); + NMLOG_WARNING("scanning request failed; trying to connect wps"); } if(_nmGdbusClient->startWPS()) From 72aede5230af5292eb9612221e5568f4fa7709a3 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 12 Sep 2025 16:38:30 -0400 Subject: [PATCH 178/271] RDKEMW-8172 : WorkerPool::Thr crash observed while running tests (#224) Reason for change: To avoid crash of networkmanager plugin when it is running as out of process due to Thunder ComRPC sequencing issue Test Procedure: check the wpeframework process details and confirm it is running as in process Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR --- plugin/NetworkManager.conf.in | 2 +- plugin/NetworkManager.config | 2 +- tests/l2Test/libnm/l2_test_libnmproxy.cpp | 4 ++-- tests/l2Test/libnm/l2_test_libnmproxyInit.cpp | 4 ++-- tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp | 2 +- tests/l2Test/rdk/l2_test_rdkproxy.cpp | 2 +- tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugin/NetworkManager.conf.in b/plugin/NetworkManager.conf.in index 379907bb0..aaa38fe87 100644 --- a/plugin/NetworkManager.conf.in +++ b/plugin/NetworkManager.conf.in @@ -3,7 +3,7 @@ startuporder = "@PLUGIN_NETWORKMANAGER_STARTUPORDER@" autostart = "true" process= JSON() -process.add("outofprocess", "true") +process.add("outofprocess", "false") process.add("locator", "lib@MODULE_IMPL_NAME@.so") connectivity = JSON() diff --git a/plugin/NetworkManager.config b/plugin/NetworkManager.config index c70241fcd..8f2dad7d1 100644 --- a/plugin/NetworkManager.config +++ b/plugin/NetworkManager.config @@ -5,7 +5,7 @@ set (autostart true) map() key(root) map() - kv(outofprocess true) + kv(outofprocess false) end() key(connectivity) map() diff --git a/tests/l2Test/libnm/l2_test_libnmproxy.cpp b/tests/l2Test/libnm/l2_test_libnmproxy.cpp index b67cfc949..ed83abda5 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxy.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxy.cpp @@ -91,7 +91,7 @@ class NetworkManagerTest : public ::testing::Test { " \"autostart\":false," " \"configuration\":{" " \"root\":{" - " \"outofprocess\":true," + " \"outofprocess\":false," " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" " }," " \"connectivity\":{" @@ -1529,4 +1529,4 @@ TEST_F(NetworkManagerTest, SetIPSettings_static_wlan0_autoConffalse) g_object_unref(dummyActiveConn); g_object_unref(dummyRemoteConn); -} \ No newline at end of file +} diff --git a/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp b/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp index f7a3666bb..ee5d83a6a 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp @@ -81,7 +81,7 @@ class NetworkManagerInitTest : public ::testing::Test { " \"autostart\":false," " \"configuration\":{" " \"root\":{" - " \"outofprocess\":true," + " \"outofprocess\":false," " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" " }," " \"connectivity\":{" @@ -168,4 +168,4 @@ TEST_F(NetworkManagerInitTest, platformInit) EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetSupportedSecurityModes"), _T(""), response)); EXPECT_EQ(response, _T("{\"security\":{\"NONE\":0,\"WPA_PSK\":1,\"SAE\":2,\"EAP\":3},\"success\":true}")); -} \ No newline at end of file +} diff --git a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp index 7c21205cc..16b13b7bd 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp @@ -91,7 +91,7 @@ class NetworkManagerWifiTest : public ::testing::Test { " \"autostart\":false," " \"configuration\":{" " \"root\":{" - " \"outofprocess\":true," + " \"outofprocess\":false," " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" " }," " \"connectivity\":{" diff --git a/tests/l2Test/rdk/l2_test_rdkproxy.cpp b/tests/l2Test/rdk/l2_test_rdkproxy.cpp index d97eac192..5813f70dc 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxy.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxy.cpp @@ -83,7 +83,7 @@ class NetworkManagerTest : public ::testing::Test { " \"autostart\":false," " \"configuration\":{" " \"root\":{" - " \"outofprocess\":true," + " \"outofprocess\":false," " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" " }," " \"connectivity\":{" diff --git a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp index a5eddc3d8..fa833b194 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp @@ -86,7 +86,7 @@ class NetworkManagerEventTest : public ::testing::Test { " \"autostart\":false," " \"configuration\":{" " \"root\":{" - " \"outofprocess\":true," + " \"outofprocess\":false," " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" " }," " \"connectivity\":{" From b266e611ed8a47b19522f30d51d0021076787888 Mon Sep 17 00:00:00 2001 From: rdkcmf Date: Fri, 12 Sep 2025 21:48:42 +0100 Subject: [PATCH 179/271] Deploy cla action (#180) --- .github/workflows/cla.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/workflows/cla.yml diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml new file mode 100644 index 000000000..055047932 --- /dev/null +++ b/.github/workflows/cla.yml @@ -0,0 +1,13 @@ +name: "CLA" +on: + issue_comment: + types: [created] + pull_request_target: + types: [opened,closed,synchronize] + +jobs: + CLA-Lite: + name: "Signature" + uses: rdkcentral/cmf-actions/.github/workflows/cla.yml@main + secrets: + PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_ASSISTANT }} \ No newline at end of file From 050fd42d46d2a665f8f5b85fa8e9cb12f0237a92 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Sat, 13 Sep 2025 19:30:53 -0400 Subject: [PATCH 180/271] Release of 1.1.0 Release of 1.1.0 --- CHANGELOG.md | 6 ++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a294157cc..397d418c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.1.0] - 2025-09-13 +### Changed +- Subscribed for Device Addition where driver for wlan0 could be inserted late +- Moved NetworkManager as in-process-plugin +- Update comments across the repo + ## [1.0.0] - 2025-08-29 ### Added - Implemented additional L1/L2 for libnm backends diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e57e5a28..c7ae71fd4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 0) +set(VERSION_MINOR 1) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index c1918932e..ca3f8a50f 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.0.0" + "version": "1.1.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 8632c28ce..dcb1908ad 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.0.0** +**Version: 1.1.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.0.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.1.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From f10d7eb4a4c56f382164fadcc950556cf859c96b Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Mon, 15 Sep 2025 10:14:43 -0400 Subject: [PATCH 181/271] Revert "RDKEMW-8172 : WorkerPool::Thr crash observed while running tests (#224)" This reverts commit 8fca4cc1032c6ca56c98eefe8f08c5cb19a49c23. --- plugin/NetworkManager.conf.in | 2 +- plugin/NetworkManager.config | 2 +- tests/l2Test/libnm/l2_test_libnmproxy.cpp | 4 ++-- tests/l2Test/libnm/l2_test_libnmproxyInit.cpp | 4 ++-- tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp | 2 +- tests/l2Test/rdk/l2_test_rdkproxy.cpp | 2 +- tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugin/NetworkManager.conf.in b/plugin/NetworkManager.conf.in index aaa38fe87..379907bb0 100644 --- a/plugin/NetworkManager.conf.in +++ b/plugin/NetworkManager.conf.in @@ -3,7 +3,7 @@ startuporder = "@PLUGIN_NETWORKMANAGER_STARTUPORDER@" autostart = "true" process= JSON() -process.add("outofprocess", "false") +process.add("outofprocess", "true") process.add("locator", "lib@MODULE_IMPL_NAME@.so") connectivity = JSON() diff --git a/plugin/NetworkManager.config b/plugin/NetworkManager.config index 8f2dad7d1..c70241fcd 100644 --- a/plugin/NetworkManager.config +++ b/plugin/NetworkManager.config @@ -5,7 +5,7 @@ set (autostart true) map() key(root) map() - kv(outofprocess false) + kv(outofprocess true) end() key(connectivity) map() diff --git a/tests/l2Test/libnm/l2_test_libnmproxy.cpp b/tests/l2Test/libnm/l2_test_libnmproxy.cpp index ed83abda5..b67cfc949 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxy.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxy.cpp @@ -91,7 +91,7 @@ class NetworkManagerTest : public ::testing::Test { " \"autostart\":false," " \"configuration\":{" " \"root\":{" - " \"outofprocess\":false," + " \"outofprocess\":true," " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" " }," " \"connectivity\":{" @@ -1529,4 +1529,4 @@ TEST_F(NetworkManagerTest, SetIPSettings_static_wlan0_autoConffalse) g_object_unref(dummyActiveConn); g_object_unref(dummyRemoteConn); -} +} \ No newline at end of file diff --git a/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp b/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp index ee5d83a6a..f7a3666bb 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp @@ -81,7 +81,7 @@ class NetworkManagerInitTest : public ::testing::Test { " \"autostart\":false," " \"configuration\":{" " \"root\":{" - " \"outofprocess\":false," + " \"outofprocess\":true," " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" " }," " \"connectivity\":{" @@ -168,4 +168,4 @@ TEST_F(NetworkManagerInitTest, platformInit) EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetSupportedSecurityModes"), _T(""), response)); EXPECT_EQ(response, _T("{\"security\":{\"NONE\":0,\"WPA_PSK\":1,\"SAE\":2,\"EAP\":3},\"success\":true}")); -} +} \ No newline at end of file diff --git a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp index 16b13b7bd..7c21205cc 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp @@ -91,7 +91,7 @@ class NetworkManagerWifiTest : public ::testing::Test { " \"autostart\":false," " \"configuration\":{" " \"root\":{" - " \"outofprocess\":false," + " \"outofprocess\":true," " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" " }," " \"connectivity\":{" diff --git a/tests/l2Test/rdk/l2_test_rdkproxy.cpp b/tests/l2Test/rdk/l2_test_rdkproxy.cpp index 5813f70dc..d97eac192 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxy.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxy.cpp @@ -83,7 +83,7 @@ class NetworkManagerTest : public ::testing::Test { " \"autostart\":false," " \"configuration\":{" " \"root\":{" - " \"outofprocess\":false," + " \"outofprocess\":true," " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" " }," " \"connectivity\":{" diff --git a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp index fa833b194..a5eddc3d8 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp @@ -86,7 +86,7 @@ class NetworkManagerEventTest : public ::testing::Test { " \"autostart\":false," " \"configuration\":{" " \"root\":{" - " \"outofprocess\":false," + " \"outofprocess\":true," " \"locator\":\"libWPEFrameworkNetworkManagerImpl.so\"" " }," " \"connectivity\":{" From 163088e94693bf60faa3f35b01b7f9a98e879ac4 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Mon, 15 Sep 2025 10:59:44 -0400 Subject: [PATCH 182/271] Release of 1.2.0 Release of 1.2.0 --- CHANGELOG.md | 4 ++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 397d418c8..1bc655887 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.2.0] - 2025-09-15 +### Changed +- Reverted NetworkManager to continue to run as out-of-process-plugin + ## [1.1.0] - 2025-09-13 ### Changed - Subscribed for Device Addition where driver for wlan0 could be inserted late diff --git a/CMakeLists.txt b/CMakeLists.txt index c7ae71fd4..cfde2316b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 1) +set(VERSION_MINOR 2) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index ca3f8a50f..c8f9ad406 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.1.0" + "version": "1.2.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index dcb1908ad..4505383f7 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.1.0** +**Version: 1.2.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.1.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.2.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 21c1aafd6f01b3685f0d431122a16f86b07a682b Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Wed, 17 Sep 2025 08:24:55 -0400 Subject: [PATCH 183/271] RDKEMW-8302 : Install NetworkManagerProxy library for WPEFramework proxystubs (#226) Reason for change: Install NetworkManagerProxy library for WPEFramework proxystubs Test Procedure: Ensure NetworkManager Plugin is activated and running properly Risks: Low Signed-off-by: kamirt573_comcast --- interface/CMakeLists.txt | 23 +++++++++++++++++++++++ plugin/CMakeLists.txt | 9 ++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 2f3a0bbba..c7c7bfeb0 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -23,6 +23,7 @@ find_package(${NAMESPACE}Plugins REQUIRED) find_package(CompileSettingsDebug CONFIG REQUIRED) find_package(ProxyStubGenerator REQUIRED) +set(PROXYLIB ${NAMESPACE}${PROJECT_NAME}Proxy) set(ProxyStubGenerator_DIR ${CMAKE_SYSROOT}${CMAKE_INSTALL_PREFIX}/tools/cmake ${ProxyStubGenerator_DIR}) if(NOT GENERATOR_SEARCH_PATH) @@ -33,4 +34,26 @@ file(GLOB INTERFACE_HEADER ${CMAKE_CURRENT_SOURCE_DIR}) ProxyStubGenerator(INPUT "${INTERFACE_HEADER}" OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/generated" INCLUDE_PATH ${GENERATOR_SEARCH_PATH}) +file(GLOB PROXY_STUB_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/generated/ProxyStubs*.cpp") + +add_library(${PROXYLIB} SHARED ${PROXY_STUB_SOURCES} + ../plugin/Module.cpp) + +target_include_directories(${PROXYLIB} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../plugin/) + +target_link_libraries(${PROXYLIB} PRIVATE + ${NAMESPACE}Core::${NAMESPACE}Core + ${NAMESPACE}COM::${NAMESPACE}COM + CompileSettingsDebug::CompileSettingsDebug) + +set_target_properties(${PROXYLIB} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES + FRAMEWORK FALSE) + +string(TOLOWER ${NAMESPACE} NAMESPACE_LIB) + +install(TARGETS ${PROXYLIB} EXPORT ${PROXYLIB}Targets + LIBRARY DESTINATION lib/${NAMESPACE_LIB}/proxystubs COMPONENT libs) + install(FILES INetworkManager.h DESTINATION include/${NAMESPACE}/interfaces) diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 7aec66ec6..c34f91663 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -52,16 +52,12 @@ add_definitions(-DPLUGIN_BUILD_REFERENCE=${PLUGIN_BUILD_REFERENCE}) include_directories(${PROJECT_SOURCE_DIR}/interface) include_directories(${PROJECT_SOURCE_DIR}/plugin) -#Setting up source files -file(GLOB PROXY_STUB_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/../interface/generated/ProxyStubs*.cpp") - # Build the main plugin that runs inside the WPEFramework daemon add_library(${MODULE_NAME} SHARED NetworkManager.cpp NetworkManagerJsonRpc.cpp NetworkManagerLogger.cpp - Module.cpp - ${PROXY_STUB_SOURCES}) + Module.cpp) target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Core::${NAMESPACE}Core @@ -78,8 +74,7 @@ add_library(${MODULE_IMPL_NAME} SHARED NetworkManagerConnectivity.cpp NetworkManagerStunClient.cpp NetworkManagerLogger.cpp - Module.cpp - ${PROXY_STUB_SOURCES}) + Module.cpp) if(ENABLE_GNOME_NETWORKMANAGER) if(ENABLE_GNOME_GDBUS) From db7e1d807586496211c414d6c225eb566e3d9983 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 18 Sep 2025 01:23:18 +0530 Subject: [PATCH 184/271] RDK-57174: Enhance the Internet Monitoring to be supported for Ethernet & WiFi independently (#225) * connectivity monitor logic change * interface name added in parameters * curl ip null check added * curl mock added * update the trigger logic in disconnect * review comment updated --- interface/INetworkManager.h | 2 +- plugin/NetworkManager.h | 6 +- plugin/NetworkManagerConnectivity.cpp | 222 ++++++++------------ plugin/NetworkManagerConnectivity.h | 13 +- plugin/NetworkManagerImplementation.cpp | 33 ++- plugin/NetworkManagerImplementation.h | 4 +- plugin/NetworkManagerJsonRpc.cpp | 3 +- tests/l1Test/l1_test_connectivity.cpp | 2 +- tests/l2Test/rdk/CMakeLists.txt | 19 +- tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp | 43 ++-- tests/mocks/CurlWraps.cpp | 54 +++++ tests/mocks/CurlWraps.h | 31 +++ tests/mocks/CurlWrapsMock.h | 18 ++ tools/plugincli/NetworkManagerGdbusTest.cpp | 2 +- tools/plugincli/NetworkManagerLibnmTest.cpp | 2 +- 15 files changed, 274 insertions(+), 180 deletions(-) create mode 100644 tests/mocks/CurlWraps.cpp create mode 100644 tests/mocks/CurlWraps.h create mode 100644 tests/mocks/CurlWrapsMock.h diff --git a/interface/INetworkManager.h b/interface/INetworkManager.h index 23f236779..a3097d7a5 100644 --- a/interface/INetworkManager.h +++ b/interface/INetworkManager.h @@ -271,7 +271,7 @@ namespace WPEFramework virtual void onInterfaceStateChange(const InterfaceState state /* @in */, const string interface /* @in */) = 0; virtual void onActiveInterfaceChange(const string prevActiveInterface /* @in */, const string currentActiveInterface /* @in */) = 0; virtual void onIPAddressChange(const string interface /* @in */, const string ipversion /* @in */, const string ipaddress /* @in */, const IPStatus status /* @in */) = 0; - virtual void onInternetStatusChange(const InternetStatus prevState /* @in */, const InternetStatus currState /* @in */) = 0; + virtual void onInternetStatusChange(const InternetStatus prevState /* @in */, const InternetStatus currState /* @in */, const string interface /* @in */) = 0; // WiFi Notifications that other processes can subscribe to virtual void onAvailableSSIDs(const string jsonOfScanResults /* @in */) = 0; diff --git a/plugin/NetworkManager.h b/plugin/NetworkManager.h index fe15db0f2..eb1dec58a 100644 --- a/plugin/NetworkManager.h +++ b/plugin/NetworkManager.h @@ -79,9 +79,9 @@ namespace WPEFramework _parent.onIPAddressChange(interface, ipversion, ipaddress, status); } - void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) override + void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface) override { - _parent.onInternetStatusChange(prevState, currState); + _parent.onInternetStatusChange(prevState, currState, interface); } void onAvailableSSIDs(const string jsonOfScanResults) override @@ -267,7 +267,7 @@ namespace WPEFramework void onInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface); void onActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface); void onIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status); - void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState); + void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface); void onAvailableSSIDs(const string jsonOfScanResults); void onWiFiStateChange(const Exchange::INetworkManager::WiFiState state); void onWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality); diff --git a/plugin/NetworkManagerConnectivity.cpp b/plugin/NetworkManagerConnectivity.cpp index 2e7a91743..3d9b88924 100644 --- a/plugin/NetworkManagerConnectivity.cpp +++ b/plugin/NetworkManagerConnectivity.cpp @@ -150,7 +150,7 @@ namespace WPEFramework const std::lock_guard lock(m_endpointMutex); return m_Endpoints; } - +#if 0 bool DnsResolver::resolveIP(std::string& uri, Exchange::INetworkManager::IPVersion& ipversion) { struct addrinfo sockAddrProps, *resultAddr= NULL; @@ -236,7 +236,7 @@ namespace WPEFramework break; } } - +#endif static void getDeviceModel(std::string& modelNum, std::string& buildVersion) { const std::string filePath = "/etc/device.properties"; @@ -269,7 +269,7 @@ namespace WPEFramework } TestConnectivity::TestConnectivity(const std::vector& endpoints, - long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion, std::string interface) + long timeout_ms, bool headReq, uint8_t ipversion, std::string interface) { getDeviceModel(m_deviceModel, m_buildVersion); internetSate = INTERNET_UNKNOWN; @@ -305,7 +305,7 @@ namespace WPEFramework * for the network connectivity check. */ Exchange::INetworkManager::InternetStatus TestConnectivity::checkCurlResponse(const std::vector& endpoints, - long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion, std::string interface) + long timeout_ms, bool headReq, uint8_t ipversion, std::string interface) { long deadline = 0, startTime = current_time(), time_now = 0, time_earlier = 0; std::string logmsg =""; @@ -420,12 +420,31 @@ namespace WPEFramework captivePortalURI = url; } } + + // if ipversion not specified, determine it based on the resolved IP address + if(ipversion != IP_ADDRESS_V4 && ipversion != IP_ADDRESS_V6) + { + char *ip = NULL; + curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIMARY_IP, &ip); + if(ip != NULL) { + if(strchr(ip, ':')) + ipversion = IP_ADDRESS_V6; + else + ipversion = IP_ADDRESS_V4; //Fix Me: Error case handling if ip is NULL + NMLOG_DEBUG("ipversion not specified, determined ipversion = %s", (ipversion == IP_ADDRESS_V6) ? "IPv6" : "IPv4"); + } + else + { + NMLOG_WARNING("could not determine it as curl primary ip is NULL"); + } + } } } - else { - NMLOG_ERROR("INTERNET_CONNECTIVITY_MONITORING_CURL_ERROR : For endpoint = <%s> on (%s) got curl error = %d (%s)", + else + { + NMLOG_ERROR("INTERNET_CONNECTIVITY_MONITORING_CURL_ERROR : For endpoint = <%s>, interface = <%s> got curl error = %d (%s)", endpntConf, - (IP_ADDRESS_V4 == ipversion) ? "IPv4" : "IPv6", + interface.empty() ? "any" : interface.c_str(), msg->data.result, curl_easy_strerror(msg->data.result)); curlErrorCode = static_cast(msg->data.result); @@ -526,9 +545,6 @@ namespace WPEFramework m_cmRunning = false; m_notify = true; m_InternetState = INTERNET_UNKNOWN; - m_ipversion = IP_ADDRESS_V4; - m_Ipv4InternetState = INTERNET_UNKNOWN; - m_Ipv6InternetState = INTERNET_UNKNOWN; m_switchToInitial = true; m_wakeupMonitoring = false; startConnectivityMonitor(); @@ -552,18 +568,21 @@ namespace WPEFramework Exchange::INetworkManager::InternetStatus ConnectivityMonitor::getInternetState(std::string& interface, Exchange::INetworkManager::IPVersion& ipversion, bool ipVersionNotSpecified) { - NMLOG_DEBUG("getInternetState specified interface %s", interface.c_str()); - if(ipVersionNotSpecified) - ipversion = m_ipversion; /* ipversion not specified, taking global ip version */ + uint8_t ipversionLocal = static_cast(ipVersionNotSpecified ? 2 : ipversion); // 2 = both, 0 = IPv4, 1 = IPv6 + // if ipversion not specified, check both IP versions and determine it based on the resolved IP address TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, - NMCONNECTIVITY_CURL_HEAD_REQUEST, ipversion, interface); + NMCONNECTIVITY_CURL_HEAD_REQUEST, ipversionLocal, interface); + + if (interface.empty()) + interface = _instance->m_defaultInterface; + return testInternet.getInternetState(); } std::string ConnectivityMonitor::getCaptivePortalURI() { - if(m_Ipv4InternetState == INTERNET_CAPTIVE_PORTAL || m_Ipv6InternetState == INTERNET_CAPTIVE_PORTAL) + if(m_InternetState == INTERNET_CAPTIVE_PORTAL) { NMLOG_INFO("captive portal URI = %s", m_captiveURI.c_str()); return m_captiveURI; @@ -603,21 +622,32 @@ namespace WPEFramework if(m_cmThrdID.joinable()) m_cmThrdID.join(); m_InternetState = INTERNET_UNKNOWN; - m_Ipv4InternetState = INTERNET_UNKNOWN; - m_Ipv6InternetState = INTERNET_UNKNOWN; NMLOG_INFO("connectivity monitor stoped !!!"); return true; } bool ConnectivityMonitor::switchToInitialCheck() { + + if(_instance == nullptr) { + NMLOG_WARNING("networkmanagerimplementation instance is null"); + return false; + } + + if(_instance->m_defaultInterface.empty()) + { + NMLOG_WARNING("default interface not set"); + return false; + } + + m_notify = true; m_switchToInitial = true; m_wakeupMonitoring = true; m_cmCv.notify_one(); - if(_instance != nullptr) { - NMLOG_INFO("switching to initial check - eth %s - wlan %s", - _instance->m_ethConnected.load()? "up":"down", _instance->m_wlanConnected.load()? "up":"down"); - } + + NMLOG_INFO("switching to initial check - eth %s - wlan %s - default interface %s", + _instance->m_ethConnected.load()? "up":"down", _instance->m_wlanConnected.load()? "up":"down", _instance->m_defaultInterface.c_str()); + return true; } @@ -628,7 +658,7 @@ namespace WPEFramework { NMLOG_INFO("notifying internet state %s", getInternetStateString(newInternetState)); Exchange::INetworkManager::InternetStatus newState = newInternetState; - _instance->ReportInternetStatusChange(oldState , newState); + _instance->ReportInternetStatusChange(oldState , newState, _instance->m_defaultInterface); m_InternetState = newInternetState; oldState = newState; // 'm_InternetState' not exactly previous state, it may change to unknow when interface changed } @@ -641,14 +671,9 @@ namespace WPEFramework int timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; Exchange::INetworkManager::InternetStatus currentInternetState = INTERNET_NOT_AVAILABLE; int InitialRetryCount = 0; - int IdealRetryCount = 0; m_switchToInitial = true; m_InternetState = INTERNET_UNKNOWN; - m_Ipv4InternetState = INTERNET_UNKNOWN; - m_Ipv6InternetState = INTERNET_UNKNOWN; m_notify = true; - std::thread ipv4thread; - std::thread ipv6thread; while (m_cmRunning) { if (nullptr == _instance) @@ -656,8 +681,6 @@ namespace WPEFramework NMLOG_DEBUG("Must be right from the constructor; because the _instance is NULL"); timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; m_InternetState = INTERNET_NOT_AVAILABLE; - m_Ipv4InternetState = INTERNET_NOT_AVAILABLE; - m_Ipv6InternetState = INTERNET_NOT_AVAILABLE; currentInternetState = INTERNET_NOT_AVAILABLE; InitialRetryCount = 0; } @@ -666,73 +689,38 @@ namespace WPEFramework NMLOG_DEBUG("no interface connected, no ccm check"); timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; m_InternetState = INTERNET_NOT_AVAILABLE; - m_Ipv4InternetState = INTERNET_NOT_AVAILABLE; - m_Ipv6InternetState = INTERNET_NOT_AVAILABLE; currentInternetState = INTERNET_NOT_AVAILABLE; if (InitialRetryCount == 0) m_notify = true; InitialRetryCount = 1; } + else if(_instance->m_defaultInterface.empty()) + { + NMLOG_WARNING("default interface not set"); + if (InitialRetryCount == 0) + m_notify = true; + InitialRetryCount = 1; + } else if (m_switchToInitial) { - NMLOG_INFO("Initial connectivity check - index:%d current state:%s", InitialRetryCount, getInternetStateString(currentInternetState)); + if (InitialRetryCount == 0) + m_notify = true; + NMLOG_INFO("Initial connectivity check - index:%d, current state:%s, interface:%s", InitialRetryCount, getInternetStateString(currentInternetState), _instance->m_defaultInterface.c_str()); timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; + TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, + NMCONNECTIVITY_CURL_HEAD_REQUEST, 2, _instance->m_defaultInterface); + currentInternetState = testInternet.getInternetState(); - // Lambda functions to check connectivity for IPv4 and IPv6 - auto curlCheckThrdIpv4 = [&]() { - TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, - NMCONNECTIVITY_CURL_HEAD_REQUEST, IP_ADDRESS_V4); - m_Ipv4InternetState = testInternet.getInternetState(); - if(m_Ipv6InternetState == INTERNET_CAPTIVE_PORTAL) - m_captiveURI = testInternet.getCaptivePortal(); - }; - - auto curlCheckThrdIpv6 = [&]() { - TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, - NMCONNECTIVITY_CURL_HEAD_REQUEST, IP_ADDRESS_V6); - m_Ipv6InternetState = testInternet.getInternetState(); - if(m_Ipv6InternetState == INTERNET_CAPTIVE_PORTAL) - m_captiveURI = testInternet.getCaptivePortal(); - }; - - ipv4thread = std::thread (curlCheckThrdIpv4); - ipv6thread = std::thread (curlCheckThrdIpv6); - - // Wait for both threads to finish - if (ipv4thread.joinable()) - ipv4thread.join(); - if (ipv6thread.joinable()) - ipv6thread.join(); - - // Determine the current internet state based on the results - if (m_Ipv4InternetState == INTERNET_NOT_AVAILABLE && m_Ipv6InternetState == INTERNET_NOT_AVAILABLE) { - currentInternetState = INTERNET_NOT_AVAILABLE; - if (InitialRetryCount == 0) - m_notify = true; + if (currentInternetState == INTERNET_NOT_AVAILABLE) { + NMLOG_DEBUG("interface connected but no internet"); InitialRetryCount = 1; // continue same check for 5 sec - } else { - if (m_Ipv4InternetState == INTERNET_FULLY_CONNECTED || m_Ipv6InternetState == INTERNET_FULLY_CONNECTED) - { - currentInternetState = INTERNET_FULLY_CONNECTED; - m_ipversion = (m_Ipv4InternetState == INTERNET_FULLY_CONNECTED) ? IP_ADDRESS_V4 : IP_ADDRESS_V6; - } - else if (m_Ipv4InternetState == INTERNET_CAPTIVE_PORTAL || m_Ipv6InternetState == INTERNET_CAPTIVE_PORTAL) - { - currentInternetState = INTERNET_CAPTIVE_PORTAL; - m_ipversion = (m_Ipv4InternetState == INTERNET_CAPTIVE_PORTAL) ? IP_ADDRESS_V4 : IP_ADDRESS_V6; - } else if (m_Ipv4InternetState == INTERNET_LIMITED || m_Ipv6InternetState == INTERNET_LIMITED) { - currentInternetState = INTERNET_LIMITED; - m_ipversion = (m_Ipv4InternetState == INTERNET_LIMITED) ? IP_ADDRESS_V4 : IP_ADDRESS_V6; - } else { - currentInternetState = INTERNET_NOT_AVAILABLE; - m_ipversion = IP_ADDRESS_V4; - } - - if (InitialRetryCount == 0) - m_notify = true; + } + else { + if(currentInternetState == INTERNET_CAPTIVE_PORTAL) + m_captiveURI = testInternet.getCaptivePortal(); if (currentInternetState != m_InternetState) { - NMLOG_DEBUG("initial connectivity state change %s", getInternetStateString(m_InternetState)); + NMLOG_DEBUG("initial connectivity state change from %s to %s", getInternetStateString(m_InternetState), getInternetStateString(currentInternetState)); m_InternetState = currentInternetState; InitialRetryCount = 1; // reset retry count to get continuous 3 same state m_notify = true; @@ -743,21 +731,19 @@ namespace WPEFramework if (InitialRetryCount > NM_CONNECTIVITY_MONITOR_RETRY_COUNT) { m_switchToInitial = false; m_notify = true; - InitialRetryCount = 0; - NMLOG_INFO("Let us monitor internet connectivity on %s address further.", (IP_ADDRESS_V4 == m_ipversion) ? "IPv4" : "IPv6"); + NMLOG_INFO("switching to ideal ccm check interface: %s", _instance->m_defaultInterface.c_str()); } - IdealRetryCount = 0; } - // Ideal case monitoring - else { - + else + { + // ideal case check every 30 sec happenses when captive portal or limited internet timeoutInSec = NMCONNECTIVITY_MONITOR_RETRY_INTERVAL; InitialRetryCount = 0; if(m_InternetState != INTERNET_FULLY_CONNECTED) { TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, - NMCONNECTIVITY_CURL_HEAD_REQUEST, m_ipversion); + NMCONNECTIVITY_CURL_HEAD_REQUEST, 2, _instance->m_defaultInterface); // check both IP versions currentInternetState = testInternet.getInternetState(); if (currentInternetState == INTERNET_CAPTIVE_PORTAL) // if captive portal found copy the URL @@ -765,57 +751,13 @@ namespace WPEFramework if (currentInternetState != m_InternetState) { - if (currentInternetState == INTERNET_NOT_AVAILABLE && m_InternetState == INTERNET_FULLY_CONNECTED) - { - DnsResolver dnsResolver(getConnectivityMonitorEndpoints()[0], m_ipversion, testInternet.getCurlError() ); // only first endpoint with specific ipversion - if (dnsResolver()) { - NMLOG_INFO("DNS resolved, success !!!"); - IdealRetryCount = 0; - currentInternetState = INTERNET_FULLY_CONNECTED; - } - else - { - NMLOG_WARNING("DNS resolve failed !!!"); - timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; // retry in 5 sec - IdealRetryCount++; - if (IdealRetryCount >= NM_CONNECTIVITY_MONITOR_RETRY_COUNT) { - IdealRetryCount = 0; - m_InternetState = INTERNET_NOT_AVAILABLE; - m_Ipv4InternetState = INTERNET_NOT_AVAILABLE; - m_Ipv6InternetState = INTERNET_NOT_AVAILABLE; // reset all states to NO_INTERNET - currentInternetState = INTERNET_NOT_AVAILABLE; - m_switchToInitial = true; // switch to initial check after 3 retries - InitialRetryCount = 1; // reset initial retry count it will not post the event - m_notify = true; - NMLOG_DEBUG("No internet retrying completed notifying !!!"); - } else { - NMLOG_INFO("No internet retrying connection check %d ...", IdealRetryCount); - } - } - } else { - // a state change happened but it is not fully connected to no internet - // switch to initial check to get the correct state - m_switchToInitial = true; - InitialRetryCount = 0; - IdealRetryCount = 0; - timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; // retry in 5 sec - - if (m_ipversion == IP_ADDRESS_V4) - m_Ipv4InternetState = currentInternetState; - else if (m_ipversion == IP_ADDRESS_V6) - m_Ipv6InternetState = currentInternetState; - else - m_InternetState = currentInternetState; - } - } else { // ideal case no change in network state - IdealRetryCount = 0; - m_InternetState = currentInternetState; + NMLOG_INFO("ideal connectivity state change from %s to %s", getInternetStateString(m_InternetState), getInternetStateString(currentInternetState)); + m_switchToInitial = true; + m_notify = true; + InitialRetryCount = 1; + timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; // retry in 5 sec } } - else - { - /* ToDo: new method "StartInternetMonitoring()" & "StopInternetMonitoring()" methods in a upcoming user story which can be called by EPG to identify LIMITED_INTERNET scenario. */ - } } if (m_notify) { diff --git a/plugin/NetworkManagerConnectivity.h b/plugin/NetworkManagerConnectivity.h index 5440f7752..87ca75586 100644 --- a/plugin/NetworkManagerConnectivity.h +++ b/plugin/NetworkManagerConnectivity.h @@ -56,7 +56,7 @@ namespace WPEFramework { namespace Plugin { - +#if 0 class DnsResolver { public: @@ -71,7 +71,7 @@ namespace WPEFramework std::string convertUrIToDomainName(std::string& url); bool resolveIP(std::string& uri, Exchange::INetworkManager::IPVersion& ipversion); }; - +#endif /* * Save user specific endpoint into a cache file and load from the file * if endpoints are empty in case plugin is restarted. @@ -99,14 +99,14 @@ namespace WPEFramework public: TestConnectivity(const std::vector& endpoints, long timeout_ms, bool headReq, - Exchange::INetworkManager::IPVersion ipversion, std::string interface = ""); + uint8_t ipversion, std::string interface = ""); ~TestConnectivity(){} std::string getCaptivePortal() {return captivePortalURI;} Exchange::INetworkManager::InternetStatus getInternetState(){return internetSate;} int getCurlError(){return curlErrorCode;} private: Exchange::INetworkManager::InternetStatus checkCurlResponse(const std::vector& endpoints, - long timeout_ms, bool headReq, Exchange::INetworkManager::IPVersion ipversion, std::string interface); + long timeout_ms, bool headReq, uint8_t ipversion, std::string interface); Exchange::INetworkManager::InternetStatus checkInternetStateFromResponseCode(const std::vector& responses); std::string captivePortalURI; std::string m_deviceModel{}; @@ -151,10 +151,7 @@ namespace WPEFramework std::atomic m_switchToInitial; std::atomic m_wakeupMonitoring; std::string m_captiveURI; - std::atomic m_InternetState; // IPv4 or IPv6 - std::atomic m_Ipv4InternetState; // IPv4 - std::atomic m_Ipv6InternetState; // IPv6 - std::atomic m_ipversion; // IPv6 + std::atomic m_InternetState; /* manages endpoints */ EndpointManager m_endpoint; }; diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 0c3fa1567..4827ecf6a 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -613,10 +613,25 @@ namespace WPEFramework if(Exchange::INetworkManager::INTERFACE_LINK_DOWN == state || Exchange::INetworkManager::INTERFACE_REMOVED == state) { if(interface == "eth0") + { m_ethConnected.store(false); + m_defaultInterface = "wlan0"; // If WiFi is connected, make it the default interface + // As default interface is changed to wlan0, switch connectivity monitor to initial check + connectivityMonitor.switchToInitialCheck(); + } else if(interface == "wlan0") + { m_wlanConnected.store(false); - connectivityMonitor.switchToInitialCheck(); + if(m_ethConnected.load()) + m_defaultInterface = "eth0"; // If Ethernet is connected, make it the default interface + + if(m_defaultInterface == interface) + { + // When WiFi is disconnected while Ethernet is connected, we don't need to trigger connectivity monitor. + // For WiFi-only state and WiFi disconnected, we should trigger connectivity monitor. + connectivityMonitor.switchToInitialCheck(); + } + } } /* Only the Ethernet connection status is changing here. The WiFi status is updated in the WiFi state callback. */ @@ -625,8 +640,9 @@ namespace WPEFramework if(interface == "eth0") m_ethConnected.store(true); else if(interface == "wlan0") - m_wlanConnected = true; - connectivityMonitor.switchToInitialCheck(); + m_wlanConnected.store(true); + // connectivityMonitor.switchToInitialCheck(); + // FIXME : Availability of interface does not mean that it has internet connection, so not triggering connectivity monitor check here. } _notificationLock.Lock(); @@ -673,7 +689,12 @@ namespace WPEFramework else m_defaultInterface = interface; - connectivityMonitor.switchToInitialCheck(); + if(m_defaultInterface == interface) { + // As default interface is connected, switch connectivity monitor to initial check any way + connectivityMonitor.switchToInitialCheck(); + } + else + NMLOG_DEBUG("No need to trigger connectivity monitor interface is %s", interface.c_str()); } _notificationLock.Lock(); @@ -684,12 +705,12 @@ namespace WPEFramework _notificationLock.Unlock(); } - void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) + void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface) { _notificationLock.Lock(); NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); for (const auto callback : _notificationCallbacks) { - callback->onInternetStatusChange(prevState, currState); + callback->onInternetStatusChange(prevState, currState, interface); } _notificationLock.Unlock(); } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index e9eadb9aa..408e8df83 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -265,7 +265,7 @@ namespace WPEFramework void ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface); void ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface); void ReportIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status); - void ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState); + void ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface); void ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults); void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); void ReportWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality); @@ -286,7 +286,6 @@ namespace WPEFramework private: std::list _notificationCallbacks; Core::CriticalSection _notificationLock; - string m_defaultInterface; string m_publicIP; stun::client stunClient; string m_stunEndpoint; @@ -311,6 +310,7 @@ namespace WPEFramework public: std::atomic m_ethConnected; std::atomic m_wlanConnected; + string m_defaultInterface; std::string m_lastConnectedSSID; mutable ConnectivityMonitor connectivityMonitor; }; diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index 5ac09c56e..ff1dd5df6 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -1000,7 +1000,7 @@ namespace WPEFramework Notify(_T("onIPAddressChange"), parameters); } - void NetworkManager::onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) + void NetworkManager::onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface) { JsonObject parameters; Core::JSON::EnumType prevStatus(prevState); @@ -1009,6 +1009,7 @@ namespace WPEFramework parameters["prevStatus"] = prevStatus.Data(); parameters["state"] = JsonValue(currState); parameters["status"] = currStatus.Data(); + parameters["interface"] = interface; LOG_INPARAM(); Notify(_T("onInternetStatusChange"), parameters); diff --git a/tests/l1Test/l1_test_connectivity.cpp b/tests/l1Test/l1_test_connectivity.cpp index b34408be7..f68a40c8f 100644 --- a/tests/l1Test/l1_test_connectivity.cpp +++ b/tests/l1Test/l1_test_connectivity.cpp @@ -29,7 +29,7 @@ namespace WPEFramework namespace Plugin { NetworkManagerImplementation* _instance = nullptr; - void NetworkManagerImplementation::ReportInternetStatusChange(const InternetStatus prevState, const InternetStatus currState) + void NetworkManagerImplementation::ReportInternetStatusChange(const InternetStatus prevState, const InternetStatus currState, const string interface) { return; } diff --git a/tests/l2Test/rdk/CMakeLists.txt b/tests/l2Test/rdk/CMakeLists.txt index bcc895956..ed5d4faba 100644 --- a/tests/l2Test/rdk/CMakeLists.txt +++ b/tests/l2Test/rdk/CMakeLists.txt @@ -31,6 +31,7 @@ add_executable(${NM_RDK_PROXY_L2_TEST} ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/Wraps.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/CurlWraps.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerLogger.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerJsonRpc.cpp @@ -63,7 +64,23 @@ target_include_directories(${NM_RDK_PROXY_L2_TEST} PRIVATE ${gtest_SOURCE_DIR}/../googlemock/include ) -target_link_options(${NM_RDK_PROXY_L2_TEST} PRIVATE -Wl,-wrap,system -Wl,-wrap,popen -Wl,-wrap,syslog -Wl,-wrap,pclose -Wl,-wrap,getmntent -Wl,-wrap,setmntent -Wl,-wrap,v_secure_popen -Wl,-wrap,v_secure_pclose -Wl,-wrap,v_secure_system) + +target_link_options(${NM_RDK_PROXY_L2_TEST} PRIVATE + -g + -Wall + -Wl,-wrap,system + -Wl,-wrap,popen + -Wl,-wrap,syslog + -Wl,-wrap,pclose + -Wl,-wrap,getmntent + -Wl,-wrap,setmntent + -Wl,-wrap,v_secure_popen + -Wl,-wrap,v_secure_pclose + -Wl,-wrap,v_secure_system + -Wl,-wrap,curl_multi_perform + -Wl,-wrap,curl_multi_info_read + -Wl,-wrap,curl_multi_poll +) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") diff --git a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp index a5eddc3d8..33da81c51 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp @@ -25,6 +25,7 @@ #include "FactoriesImplementation.h" #include "IarmBusMock.h" #include "WrapsMock.h" +#include "CurlWrapsMock.h" #include "ServiceMock.h" #include "ThunderPortability.h" #include "COMLinkMock.h" @@ -50,6 +51,7 @@ class NetworkManagerEventTest : public ::testing::Test { // Mock classes IarmBusImplMock *p_iarmBusImplMock = nullptr; WrapsImplMock *p_wrapsImplMock = nullptr; + CurlWrapsImplMock *p_curlWrapsImplMock = nullptr; IARM_EventHandler_t _nmEventHandler{}; Core::ProxyType NetworkManagerImpl; @@ -70,6 +72,8 @@ class NetworkManagerEventTest : public ::testing::Test { IarmBus::setImpl(p_iarmBusImplMock); p_wrapsImplMock = new NiceMock ; Wraps::setImpl(p_wrapsImplMock); + p_curlWrapsImplMock = new NiceMock ; + CurlWraps::setImpl(p_curlWrapsImplMock); ON_CALL(service, COMLink()) .WillByDefault(::testing::Invoke( [this]() { @@ -180,6 +184,13 @@ class NetworkManagerEventTest : public ::testing::Test { delete p_wrapsImplMock; p_wrapsImplMock = nullptr; } + + CurlWraps::setImpl(nullptr); + if (p_curlWrapsImplMock != nullptr) + { + delete p_curlWrapsImplMock; + p_curlWrapsImplMock = nullptr; + } } }; @@ -456,7 +467,7 @@ TEST_F(NetworkManagerEventTest, onInterfaceStateChange2) EVENT_UNSUBSCRIBE(2, _T("onInterfaceStateChange"), _T("org.rdk.NetworkManager"), message); } - +/* TEST_F(NetworkManagerEventTest, onInternetStatusChange_CaptivePortal) { Core::Event onInternetStatusChange(false, true); @@ -545,9 +556,12 @@ TEST_F(NetworkManagerEventTest, onInternetStatusChange_LimitedInternet) EXPECT_EQ(response, _T("{\"ipversion\":\"IPv4\",\"interface\":\"eth0\",\"connected\":false,\"state\":1,\"status\":\"LIMITED_INTERNET\",\"success\":true}")); server.stop(); } - +*/ TEST_F(NetworkManagerEventTest, onInternetStatusChange_FULLY_CONNECTED) { + EXPECT_CALL(*p_curlWrapsImplMock, curl_multi_perform(::testing::_, ::testing::_)) + .WillRepeatedly(::testing::Return(CURLM_BAD_HANDLE)); + Core::Event onInternetStatusChange(false, true); EVENT_SUBSCRIBE(2, _T("onInternetStatusChange"), _T("org.rdk.NetworkManager"), message); @@ -562,16 +576,6 @@ TEST_F(NetworkManagerEventTest, onInternetStatusChange_FULLY_CONNECTED) return Core::ERROR_NONE; })); - SimpleHttpServer server(8080); - server.setHttpResponseCode(204); // No Content - server.setHttpMessage(""); - server.start(); - - std::string request = _T("{\"endpoints\":[\"http://localhost:8080/generate_204\"]}"); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetConnectivityTestEndpoints"), request, response)); - EXPECT_EQ(response, _T("{\"success\":true}")); - std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Allow server to start - IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "eth0", .status = true }; _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); @@ -584,17 +588,17 @@ TEST_F(NetworkManagerEventTest, onInternetStatusChange_FULLY_CONNECTED) EXPECT_EQ(Core::ERROR_NONE, onInternetStatusChange.Lock()); EVENT_UNSUBSCRIBE(2, _T("onInternetStatusChange"), _T("org.rdk.NetworkManager"), message); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Allow server to start - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("IsConnectedToInternet"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ipversion\":\"IPv4\",\"interface\":\"eth0\",\"connected\":true,\"state\":3,\"status\":\"FULLY_CONNECTED\",\"success\":true}")); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetCaptivePortalURI"), _T("{}"), response)); EXPECT_EQ(response, _T("{\"uri\":\"\",\"success\":true}")); - server.stop(); } TEST_F(NetworkManagerEventTest, GetPublicIP_SuccessWithEvent) { + EXPECT_CALL(*p_curlWrapsImplMock, curl_multi_perform(::testing::_, ::testing::_)) + .WillRepeatedly(::testing::Return(CURLM_BAD_HANDLE)); + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "wlan0", .status = true }; _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); @@ -617,6 +621,14 @@ TEST_F(NetworkManagerEventTest, GetSupportedSecurityModes) EXPECT_EQ(response, _T("{\"security\":{\"NONE\":0,\"WPA_PSK\":1,\"SAE\":2,\"EAP\":3},\"success\":true}")); } +TEST_F(NetworkManagerEventTest, IsConnectedToInternet_Failed_CurlMultiPerform) +{ + EXPECT_CALL(*p_curlWrapsImplMock, curl_multi_perform(::testing::_, ::testing::_)) + .WillRepeatedly(::testing::Return(CURLM_BAD_HANDLE)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("IsConnectedToInternet"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"ipversion\":\"IPv4\",\"interface\":\"\",\"connected\":false,\"state\":0,\"status\":\"NO_INTERNET\",\"success\":true}")); +} + TEST_F(NetworkManagerEventTest, IsConnectedToInternet_Failed) { @@ -650,6 +662,7 @@ TEST_F(NetworkManagerEventTest, IsConnectedToInternet_Failed) EXPECT_EQ(response, _T("{\"ipversion\":\"IPv4\",\"interface\":\"wlan0\",\"connected\":false,\"state\":0,\"status\":\"NO_INTERNET\",\"success\":true}")); } + /* TEST_F(NetworkManagerEventTest, FULLY_CONNECTED_wait) { diff --git a/tests/mocks/CurlWraps.cpp b/tests/mocks/CurlWraps.cpp new file mode 100644 index 000000000..6463f3981 --- /dev/null +++ b/tests/mocks/CurlWraps.cpp @@ -0,0 +1,54 @@ +#include "CurlWraps.h" +#include "CurlWrapsMock.h" +#include +#include + +extern "C" CURLMcode __wrap_curl_multi_perform(CURLM* multi_handle, int* still_running) +{ + return CurlWraps::getInstance().curl_multi_perform(multi_handle, still_running); +} + +extern "C" CURLMsg* __wrap_curl_multi_info_read(CURLM* multi_handle, int* msgs_left) +{ + return CurlWraps::getInstance().curl_multi_info_read(multi_handle, msgs_left); +} + +extern "C" CURLMcode __wrap_curl_multi_poll(CURLM* multi_handle, void* fds, unsigned int nfds, int timeout_ms, int* ret) +{ + return CurlWraps::getInstance().curl_multi_poll(multi_handle, fds, nfds, timeout_ms, ret); +} + +CurlWrapsImpl* CurlWraps::impl = nullptr; + +CurlWraps::CurlWraps() {} + +void CurlWraps::setImpl(CurlWrapsImpl* newImpl) +{ + EXPECT_TRUE((nullptr == impl) || (nullptr == newImpl)); + impl = newImpl; +} + +CurlWraps& CurlWraps::getInstance() +{ + static CurlWraps instance; + return instance; +} + +CURLMcode CurlWraps::curl_multi_perform(CURLM* multi_handle, int* still_running) +{ + EXPECT_NE(impl, nullptr); + return impl->curl_multi_perform(multi_handle, still_running); +} + +CURLMsg* CurlWraps::curl_multi_info_read(CURLM* multi_handle, int* msgs_left) +{ + EXPECT_NE(impl, nullptr); + return impl->curl_multi_info_read(multi_handle, msgs_left); +} + +CURLMcode CurlWraps::curl_multi_poll(CURLM* multi_handle, void* fds, unsigned int nfds, int timeout_ms, int* ret) +{ + EXPECT_NE(impl, nullptr); + return impl->curl_multi_poll(multi_handle, fds, nfds, timeout_ms, ret); +} + diff --git a/tests/mocks/CurlWraps.h b/tests/mocks/CurlWraps.h new file mode 100644 index 000000000..c303f453b --- /dev/null +++ b/tests/mocks/CurlWraps.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include +#include + +class CurlWrapsImpl { +public: + virtual ~CurlWrapsImpl() = default; + + virtual CURLMcode curl_multi_perform(CURLM* multi_handle, int* still_running) = 0; + virtual CURLMsg* curl_multi_info_read(CURLM* multi_handle, int* msgs_left) = 0; + virtual CURLMcode curl_multi_poll(CURLM* multi_handle, void* fds, unsigned int nfds, int timeout_ms, int* ret) = 0; +}; + +class CurlWraps { +protected: + static CurlWrapsImpl* impl; + +public: + CurlWraps(); + CurlWraps(const CurlWraps &obj) = delete; + static void setImpl(CurlWrapsImpl* newImpl); + static CurlWraps& getInstance(); + + static CURLMcode curl_multi_perform(CURLM* multi_handle, int* still_running); + static CURLMsg* curl_multi_info_read(CURLM* multi_handle, int* msgs_left); + static CURLMcode curl_multi_poll(CURLM* multi_handle, void* fds, unsigned int nfds, int timeout_ms, int* ret); +}; diff --git a/tests/mocks/CurlWrapsMock.h b/tests/mocks/CurlWrapsMock.h new file mode 100644 index 000000000..38d893446 --- /dev/null +++ b/tests/mocks/CurlWrapsMock.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include +#include + +#include "CurlWraps.h" + +class CurlWrapsImplMock : public CurlWrapsImpl { +public: + CurlWrapsImplMock():CurlWrapsImpl() {} + virtual ~CurlWrapsImplMock() = default; + + MOCK_METHOD(CURLMcode, curl_multi_perform, (CURLM* multi_handle, int* still_running), (override)); + MOCK_METHOD(CURLMsg*, curl_multi_info_read, (CURLM* multi_handle, int* msgs_left), (override)); + MOCK_METHOD(CURLMcode, curl_multi_poll, (CURLM* multi_handle, void* fds, unsigned int nfds, int timeout_ms, int* ret), (override)); +}; diff --git a/tools/plugincli/NetworkManagerGdbusTest.cpp b/tools/plugincli/NetworkManagerGdbusTest.cpp index ce972237f..25dd50cb1 100644 --- a/tools/plugincli/NetworkManagerGdbusTest.cpp +++ b/tools/plugincli/NetworkManagerGdbusTest.cpp @@ -51,7 +51,7 @@ namespace WPEFramework { NMLOG_INFO("calling 'ReportIPAddressChange' cb"); } - void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) + void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface) { NMLOG_INFO("calling 'ReportInternetStatusChange' cb"); } diff --git a/tools/plugincli/NetworkManagerLibnmTest.cpp b/tools/plugincli/NetworkManagerLibnmTest.cpp index 08254a099..33472ce5f 100644 --- a/tools/plugincli/NetworkManagerLibnmTest.cpp +++ b/tools/plugincli/NetworkManagerLibnmTest.cpp @@ -50,7 +50,7 @@ namespace WPEFramework { NMLOG_INFO("calling 'ReportIPAddressChange' cb"); } - void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState) + void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface) { NMLOG_INFO("calling 'ReportInternetStatusChange' cb"); } From 9709dd5f5ed714bf6f6f41e0c368dcd804b16e71 Mon Sep 17 00:00:00 2001 From: kamirt573_comcast Date: Wed, 17 Sep 2025 20:59:59 +0000 Subject: [PATCH 185/271] Release of 1.3.0 Release of 1.3.0 Signed-off-by: kamirt573_comcast --- CHANGELOG.md | 6 ++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 10 ++++++++-- docs/NetworkManagerPlugin.md | 8 +++++--- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bc655887..9b56bb69c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.3.0] - 2025-09-17 +### Added +- Implemented NetworkManagerProxy library which can help Thunder to Create COM-RPC connection to Out-Of-Process plugin +- Implemented Internet Connectivity Monitoring for specific to Primary Interface. +- Updated to not to post onInternetStatusChanged event when secondary interface is disturbed. + ## [1.2.0] - 2025-09-15 ### Changed - Reverted NetworkManager to continue to run as out-of-process-plugin diff --git a/CMakeLists.txt b/CMakeLists.txt index cfde2316b..2fdb5ca76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 2) +set(VERSION_MINOR 3) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index c8f9ad406..7c97839bd 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.2.0" + "version": "1.3.0" }, "definitions": { "success": { @@ -1433,13 +1433,19 @@ "summary": "The internet connection status", "type": "string", "example": "FULLY_CONNECTED" + }, + "interface":{ + "summary": "The internet status change on default interface", + "type": "string", + "example": "wlan0" } }, "required": [ "prevState", "prevStatus", "state", - "status" + "status", + "interface" ] } }, diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 4505383f7..70be96855 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.2.0** +**Version: 1.3.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.2.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.3.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity @@ -1840,6 +1840,7 @@ Triggered when internet connection state changed.The possible internet connectio | params.prevStatus | string | The previous internet connection status | | params.state | integer | The internet connection state | | params.status | string | The internet connection status | +| params.interface | string | The internet status change on default interface | ### Example @@ -1851,7 +1852,8 @@ Triggered when internet connection state changed.The possible internet connectio "prevState": 1, "prevStatus": "NO_INTERNET", "state": 4, - "status": "FULLY_CONNECTED" + "status": "FULLY_CONNECTED", + "interface": "wlan0" } } ``` From ab2b405063f8926553c88c05915288aa5429eabe Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 22 Sep 2025 15:11:36 -0400 Subject: [PATCH 186/271] netsrvmgr logging performance issue (#227) * getIPsettings caching * getIPsettings caching --- plugin/NetworkManagerImplementation.cpp | 4 +++ plugin/NetworkManagerImplementation.h | 4 +++ plugin/rdk/NetworkManagerRDKProxy.cpp | 48 +++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 4827ecf6a..2219deb9a 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -614,6 +614,8 @@ namespace WPEFramework { if(interface == "eth0") { + m_ethIPv4Address = {}; + m_ethIPv6Address = {}; m_ethConnected.store(false); m_defaultInterface = "wlan0"; // If WiFi is connected, make it the default interface // As default interface is changed to wlan0, switch connectivity monitor to initial check @@ -621,6 +623,8 @@ namespace WPEFramework } else if(interface == "wlan0") { + m_wlanIPv4Address = {}; + m_wlanIPv6Address = {}; m_wlanConnected.store(false); if(m_ethConnected.load()) m_defaultInterface = "eth0"; // If Ethernet is connected, make it the default interface diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 408e8df83..6d48b1282 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -306,6 +306,10 @@ namespace WPEFramework std::atomic m_stopThread{false}; std::mutex m_condVariableMutex; std::condition_variable m_condVariable; + IPAddress m_ethIPv4Address; + IPAddress m_wlanIPv4Address; + IPAddress m_ethIPv6Address; + IPAddress m_wlanIPv6Address; public: std::atomic m_ethConnected; diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 8130966b7..6ff557e22 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -684,6 +684,46 @@ namespace WPEFramework LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; IARM_BUS_NetSrvMgr_Iface_Settings_t iarmData = { 0 }; + string ipversionStr; + + if(interface.empty()) + { + interface = m_defaultInterface; + } + if(ipversion.empty()) + { + ipversionStr = "IPv4"; + } + else + { + ipversionStr = ipversion; + } + if ("wlan0" == interface) + { + if("IPv4" == ipversionStr && !m_wlanIPv4Address.ipaddress.empty()) + { + address = m_wlanIPv4Address; + return Core::ERROR_NONE; + } + else if("IPv6" == ipversionStr && !m_wlanIPv6Address.ipaddress.empty()) + { + address = m_wlanIPv6Address; + return Core::ERROR_NONE; + } + } + else if ("eth0" == interface) + { + if("IPv4" == ipversionStr && !m_ethIPv4Address.ipaddress.empty()) + { + address = m_ethIPv4Address; + return Core::ERROR_NONE; + } + else if("IPv6" == ipversionStr && !m_ethIPv6Address.ipaddress.empty()) + { + address = m_ethIPv6Address; + return Core::ERROR_NONE; + } + } /* Netsrvmgr returns eth0 & wlan0 as primary interface but when we want to set., we must set ETHERNET or WIFI*/ //TODO: Fix netsrvmgr to accept eth0 & wlan0 if ("wlan0" == interface) @@ -714,11 +754,19 @@ namespace WPEFramework { address.ipversion = string ("IPv4"); address.prefix = NetmaskToPrefix(iarmData.netmask); + if("eth0" == interface) + m_ethIPv4Address = address; + else if("wlan0" == interface) + m_wlanIPv4Address = address; } else if (0 == strcasecmp("ipv6", iarmData.ipversion)) { address.ipversion = string ("IPv6"); address.prefix = std::atoi(iarmData.netmask); + if("eth0" == interface) + m_ethIPv6Address = address; + else if("wlan0" == interface) + m_wlanIPv6Address = address; } rc = Core::ERROR_NONE; From 8fd3f8b0b1ea943806dabb66f6cc0c470ac27bec Mon Sep 17 00:00:00 2001 From: jincysam87 <167995204+jincysam87@users.noreply.github.com> Date: Tue, 23 Sep 2025 11:27:25 -0400 Subject: [PATCH 187/271] RDKEMW-8500 : Observed routerDiscovery crash with signature strlen (#228) Reason for change: Read/Log only if router parameters are available Test Procedure: Ensure no crash reported for routerDiscovery Risks: Low Signed-off-by: jincysaramma_sam@comcast.com --- tools/upnp/UpnpDiscoveryManager.cpp | 46 +++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/tools/upnp/UpnpDiscoveryManager.cpp b/tools/upnp/UpnpDiscoveryManager.cpp index 657aaff78..bb47fc6fd 100644 --- a/tools/upnp/UpnpDiscoveryManager.cpp +++ b/tools/upnp/UpnpDiscoveryManager.cpp @@ -139,9 +139,24 @@ bool UpnpDiscoveryManager::findGatewayDevice(const std::string& interface) /* @brief Callback getting invoked when SSDP reply is received from gateway */ void UpnpDiscoveryManager::on_device_proxy_available(GUPnPControlPoint *controlPoint, GUPnPDeviceProxy *proxy) { - m_apMake = gupnp_device_info_get_manufacturer(GUPNP_DEVICE_INFO(proxy)); - m_apModelName = gupnp_device_info_get_model_name(GUPNP_DEVICE_INFO(proxy)); - m_apModelNumber = gupnp_device_info_get_model_number(GUPNP_DEVICE_INFO(proxy)); + char* make = gupnp_device_info_get_manufacturer(GUPNP_DEVICE_INFO(proxy)); + if (make != NULL) { + m_apMake = make; + } else { + m_apMake = "Unknown"; + } + char* modelName = gupnp_device_info_get_model_name(GUPNP_DEVICE_INFO(proxy)); + if (modelName != NULL) { + m_apModelName = modelName; + } else { + m_apModelName = "Unknown"; + } + char* modelNumber = gupnp_device_info_get_model_number(GUPNP_DEVICE_INFO(proxy)); + if (modelNumber != NULL) { + m_apModelNumber = modelNumber; + } else { + m_apModelNumber = "Unknown"; + } // Remove the string after symbol <,> For example: NETGEAR,Inc. m_apMake = m_apMake.substr(0, m_apMake.find(',')); m_apModelName = m_apModelName.substr(0, m_apModelName.find(',')); @@ -157,6 +172,31 @@ void UpnpDiscoveryManager::on_device_proxy_available(GUPnPControlPoint *controlP m_gatewayDetails << m_apModelName << "," << m_apModelNumber; } logTelemetry(m_gatewayDetails.str()); + // If router make/modelName/modelNumber is not available, log all other available router details + if ((m_apMake == "Unknown") || (m_apModelName == "Unknown") || (m_apModelNumber == "Unknown")) + { + const char* location = gupnp_device_info_get_location(GUPNP_DEVICE_INFO(proxy)); + if (location != NULL) + LOG_INFO("Location URL: %s", location); + char* name = gupnp_device_info_get_friendly_name(GUPNP_DEVICE_INFO(proxy)); + if (name != NULL) + LOG_INFO("Friendly name: %s", name); + char* manuUrl = gupnp_device_info_get_manufacturer_url(GUPNP_DEVICE_INFO(proxy)); + if (manuUrl != NULL) + LOG_INFO("Manufacturer URL: %s", manuUrl); + char* modelDes = gupnp_device_info_get_model_description(GUPNP_DEVICE_INFO(proxy)); + if (modelDes != NULL) + LOG_INFO("Model Description: %s", modelDes); + char* modelUrl = gupnp_device_info_get_model_url(GUPNP_DEVICE_INFO(proxy)); + if (modelUrl != NULL) + LOG_INFO("Model URL: %s", modelUrl); + char* serialNum = gupnp_device_info_get_serial_number(GUPNP_DEVICE_INFO(proxy)); + if (serialNum != NULL) + LOG_INFO("Serial Number: %s", serialNum); + char* upc = gupnp_device_info_get_upc(GUPNP_DEVICE_INFO(proxy)); + if (upc != NULL) + LOG_INFO("Universal Product Code: %s", upc); + } exitWait(); } From c5ba52321db974753efa63018ff31bc5c61ab81c Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 23 Sep 2025 15:41:14 -0400 Subject: [PATCH 188/271] RDKEMW-7523 - Connect to Hidden SSID (#229) * RDKEMW-7523 - Connect to Hidden SSID Reason for change: To address the below points. 1. When WIFIConnect requested and if the SSID is already in scan list, we must use security mode that is identified. 2. When WIFIConnect requested and if the SSID is NOT in scan list, we must use security mode that is given. 3. Regardless of 1 or 2, the SSID must be added to known-connections only when caller asked to persist. Test Procedure: Check LNF ssid is getting saved or not, by connecting to LNF SSID using LostAndFound connectToPrivate curl command and rebooting the device Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR Gururaja_ErodeSriranganRamlingham@comcast.com --- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 115 ++++++++++++++---- tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp | 6 +- 2 files changed, 94 insertions(+), 27 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index d63406d1d..8bf8f137d 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -462,6 +462,40 @@ namespace WPEFramework g_main_loop_quit(_wifiManager->m_loop); } + static void wifiConnectTempCb(GObject *client, GAsyncResult *result, gpointer user_data) + { + GError *error = NULL; + wifiManager *_wifiManager = (static_cast(user_data)); + NMRemoteConnection *remoteConnection = NULL; + + remoteConnection = nm_client_add_connection2_finish(NM_CLIENT(client), result, NULL, &error); + + if (error) { + NMLOG_ERROR("Failed to add temporary connection: %s", error->message); + _wifiManager->m_isSuccess = false; + g_error_free(error); + g_main_loop_quit(_wifiManager->m_loop); + return; + } + + if (remoteConnection) { + NMLOG_DEBUG("Temporary connection added, now activating..."); + // Now activate the temporary connection + nm_client_activate_connection_async(_wifiManager->m_client, + NM_CONNECTION(remoteConnection), + _wifiManager->m_wifidevice, + _wifiManager->m_objectPath, + NULL, + wifiConnectCb, + _wifiManager); + g_object_unref(remoteConnection); + } else { + NMLOG_ERROR("Failed to add temporary connection - no connection returned"); + _wifiManager->m_isSuccess = false; + g_main_loop_quit(_wifiManager->m_loop); + } + } + static void wifiConnectionUpdate(GObject *rmObject, GAsyncResult *res, gpointer user_data) { NMRemoteConnection *remote_con = NM_REMOTE_CONNECTION(rmObject); @@ -799,26 +833,30 @@ namespace WPEFramework } AccessPoint = findMatchingSSID(ApList, ssidInfo.ssid); - if(AccessPoint == NULL) { + if(AccessPoint == NULL) + { NMLOG_WARNING("SSID '%s' not found !", ssidInfo.ssid.c_str()); // if(_instance != nullptr) // _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); /* ssid not found in scan list so add to known ssid it will do a scanning and connect */ - if(addToKnownSSIDs(ssidInfo)) + if(ssidInfo.persist) { - NMLOG_DEBUG("Adding to known ssid '%s' ", ssidInfo.ssid.c_str()); - deleteClientConnection(); - return activateKnownConnection(nmUtils::wlanIface(), ssidInfo.ssid); + if(addToKnownSSIDs(ssidInfo)) + { + NMLOG_DEBUG("Adding to known ssid '%s' ", ssidInfo.ssid.c_str()); + deleteClientConnection(); + return activateKnownConnection(nmUtils::wlanIface(), ssidInfo.ssid); + } + else + { + deleteClientConnection(); + return false; + } } - deleteClientConnection(); - return false; } - - getApInfo(AccessPoint, apinfo); - - if(ssidInfo.security != apinfo.security) + else { - NMLOG_WARNING("user requested wifi security '%d' != AP supported security %d ", ssidInfo.security, apinfo.security); + getApInfo(AccessPoint, apinfo); ssidInfo.security = apinfo.security; } @@ -872,18 +910,30 @@ namespace WPEFramework deleteClientConnection(); return false; } - GVariant *connSettings = nm_connection_to_dbus(m_connection, NM_CONNECTION_SERIALIZE_ALL); - nm_remote_connection_update2(NM_REMOTE_CONNECTION(m_connection), - connSettings, - NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT, // block auto connect becuse manualy activate - NULL, - NULL, - wifiConnectionUpdate, - this); + if (ssidInfo.persist) + { + // Save to persistent storage and activate + GVariant *connSettings = nm_connection_to_dbus(m_connection, NM_CONNECTION_SERIALIZE_ALL); + nm_remote_connection_update2(NM_REMOTE_CONNECTION(m_connection), + connSettings, + NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT, // block auto connect becuse manualy activate + NULL, + NULL, + wifiConnectionUpdate, + this); + } + else + { + // Don't persist changes, just activate existing connection + // Note: Any changes made by connectionBuilder will be temporary for this session only + NMLOG_DEBUG("activating existing connection without persisting changes '%s'", ssidInfo.ssid.c_str()); + m_createNewConnection = false; + nm_client_activate_connection_async(m_client, NM_CONNECTION(m_connection), m_wifidevice, m_objectPath, NULL, wifiConnectCb, this); + } } else { - NMLOG_DEBUG("creating new connection '%s' ", ssidInfo.ssid.c_str()); + NMLOG_DEBUG("creating new connection '%s' persist=%d", ssidInfo.ssid.c_str(), ssidInfo.persist); m_connection = nm_simple_connection_new(); m_objectPath = nm_object_get_path(NM_OBJECT(AccessPoint)); if(!connectionBuilder(ssidInfo, m_connection)) @@ -894,8 +944,27 @@ namespace WPEFramework deleteClientConnection(); return false; } - m_createNewConnection = true; - nm_client_add_and_activate_connection_async(m_client, m_connection, m_wifidevice, m_objectPath, NULL, wifiConnectCb, this); + if (ssidInfo.persist) + { + m_createNewConnection = true; + nm_client_add_and_activate_connection_async(m_client, m_connection, m_wifidevice, m_objectPath, NULL, wifiConnectCb, this); + } + else + { + // Create temporary connection - add to memory only, do not save to disk + m_createNewConnection = false; + GVariant *connSettings = nm_connection_to_dbus(m_connection, NM_CONNECTION_SERIALIZE_ALL); + // Use nm_client_add_connection2 without NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK + // This creates an in-memory only connection that won't persist + nm_client_add_connection2(m_client, + connSettings, + NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY, + NULL, + TRUE, + NULL, + wifiConnectTempCb, + this); + } if(m_connection) g_object_unref(m_connection); } diff --git a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp index 7c21205cc..fa67b6bf7 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp @@ -1280,10 +1280,8 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_no_access_point) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) .WillRepeatedly(::testing::Return("wlan0")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + .Times(3) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); From a753fdfcb462c2cbda4e6c7aeb5bf48f7333c36f Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Tue, 23 Sep 2025 15:45:40 -0400 Subject: [PATCH 189/271] Release of 1.4.0 Release of 1.4.0 --- CHANGELOG.md | 6 ++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b56bb69c..81f0f779e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.4.0] - 2025-09-23 +### Changed +- Implemented logic to not to persist SSID when asked +- Implemented IP Address caching to avoid making RPC request to networkmanager when interface status not changed. +- Fixed the Router Discovery app crash when AP does not support UPNP + ## [1.3.0] - 2025-09-17 ### Added - Implemented NetworkManagerProxy library which can help Thunder to Create COM-RPC connection to Out-Of-Process plugin diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fdb5ca76..dd6f1a417 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 3) +set(VERSION_MINOR 4) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 7c97839bd..ef06e267c 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.3.0" + "version": "1.4.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 70be96855..aeb550e32 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.3.0** +**Version: 1.4.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.3.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.4.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 468f9360f180a44684b20b89aece2188a603f424 Mon Sep 17 00:00:00 2001 From: rdkcmf Date: Fri, 26 Sep 2025 10:52:49 +0100 Subject: [PATCH 190/271] Deploy cla action Deploy cla action Deploy cla action --- .github/workflows/cla.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 055047932..c58b1b0b1 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -1,13 +1,20 @@ name: "CLA" + +permissions: + contents: read + pull-requests: write + actions: write + statuses: write + on: issue_comment: types: [created] pull_request_target: - types: [opened,closed,synchronize] + types: [opened, closed, synchronize] jobs: CLA-Lite: name: "Signature" - uses: rdkcentral/cmf-actions/.github/workflows/cla.yml@main + uses: rdkcentral/cmf-actions/.github/workflows/cla.yml@v1 secrets: - PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_ASSISTANT }} \ No newline at end of file + PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_ASSISTANT }} From d0314ea3a1f90ac9759704fe5a94b33e5d9fb358 Mon Sep 17 00:00:00 2001 From: rdkcmf Date: Mon, 29 Sep 2025 13:52:01 +0100 Subject: [PATCH 191/271] Deploy fossid_integration_stateless_diffscan_target_repo action #231 Deploy fossid_integration_stateless_diffscan_target_repo action --- ...sid_integration_stateless_diffscan_target_repo.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml b/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml index 704552151..7b8c1cba1 100644 --- a/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml +++ b/.github/workflows/fossid_integration_stateless_diffscan_target_repo.yml @@ -1,10 +1,17 @@ name: Fossid Stateless Diff Scan -on: pull_request +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: read jobs: call-fossid-workflow: - uses: rdkcentral/build_tools_workflows/.github/workflows/fossid_integration_stateless_diffscan.yml@develop + if: ${{ ! github.event.pull_request.head.repo.fork }} + uses: rdkcentral/build_tools_workflows/.github/workflows/fossid_integration_stateless_diffscan.yml@1.0.0 secrets: FOSSID_CONTAINER_USERNAME: ${{ secrets.FOSSID_CONTAINER_USERNAME }} FOSSID_CONTAINER_PASSWORD: ${{ secrets.FOSSID_CONTAINER_PASSWORD }} From fdb2fb877a9df5b20262a7792fbeca40d860b2c2 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Fri, 3 Oct 2025 19:14:51 +0530 Subject: [PATCH 192/271] RDKEMW-6135 : Improve L1/L2 Test coverage libnm test coverage (#232) * updated libnm L2 test case to increase the coverage * addtoknownssid added --- tests/l2Test/libnm/CMakeLists.txt | 4 + .../l2Test/libnm/l2_test_libnmproxyEvent.cpp | 194 +++++++++- tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp | 332 ++++++++++++++++++ tests/mocks/LibnmWraps.cpp | 27 ++ tests/mocks/LibnmWraps.h | 18 + tests/mocks/LibnmWrapsMock.h | 30 ++ 6 files changed, 604 insertions(+), 1 deletion(-) diff --git a/tests/l2Test/libnm/CMakeLists.txt b/tests/l2Test/libnm/CMakeLists.txt index 8ec8721a7..057bf19a8 100644 --- a/tests/l2Test/libnm/CMakeLists.txt +++ b/tests/l2Test/libnm/CMakeLists.txt @@ -136,12 +136,14 @@ target_link_options(${NM_LIBNM_PROXY_L2_TEST} PUBLIC -Wl,-wrap,nm_client_activate_connection_async -Wl,-wrap,nm_connection_get_connection_type -Wl,-wrap,nm_connection_get_id + -Wl,-wrap,nm_connection_to_dbus -Wl,-wrap,nm_client_get_connections -Wl,-wrap,nm_device_set_autoconnect -Wl,-wrap,nm_device_wifi_get_last_scan -Wl,-wrap,nm_client_activate_connection_finish -Wl,-wrap,nm_client_add_and_activate_connection_async -Wl,-wrap,nm_remote_connection_update2_finish + -Wl,-wrap,nm_remote_connection_update2 -Wl,-wrap,nm_client_add_connection2 -Wl,-wrap,nm_client_add_connection2_finish -Wl,-wrap,nm_client_add_and_activate_connection_finish @@ -158,6 +160,8 @@ target_link_options(${NM_LIBNM_PROXY_L2_TEST} PUBLIC -Wl,-wrap,nm_setting_wireless_get_ssid -Wl,-wrap,nm_connection_get_setting_wireless -Wl,-wrap,nm_remote_connection_delete + -Wl,-wrap,nm_remote_connection_delete_finish + -Wl,-wrap,nm_access_point_connection_valid ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") diff --git a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp index 3fccc439e..5b34d2bdf 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp @@ -109,7 +109,7 @@ class NetworkManagerEventTest : public ::testing::Test { if(detailed_signal == NULL) printf("g_signal_connect_data: NULL\n"); else - printf("g_signal_connect_data - siganal: %s\n", detailed_signal); + printf("g_signal_connect_data - signal: %s\n", detailed_signal); return 0; })); @@ -306,3 +306,195 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb) WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); } + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_activated) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_disconnected) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_unmanaged) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_prepare) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_PREPARE)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_config) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_CONFIG)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_ip_config) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_IP_CONFIG)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_ip_check) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_IP_CHECK)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_secondaries) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_SECONDARIES)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_deactivating) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_DEACTIVATING)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_failed) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_FAILED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_need_auth) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_NEED_AUTH)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_unknown) +{ + NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNKNOWN)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_unmanaged) +{ + NMDevice *DummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("eth0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_disconnected) +{ + NMDevice *DummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("eth0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_prepare) +{ + NMDevice *DummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_PREPARE)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("eth0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_ipconfig) +{ + NMDevice *DummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_IP_CONFIG)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("eth0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); +} diff --git a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp index fa67b6bf7..9dc75cb1f 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp @@ -1470,6 +1470,222 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_different_good_password) g_ptr_array_free(fakeDevices, TRUE); } +TEST_F(NetworkManagerWifiTest, WiFiConnect_with_connection_update) +{ + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + NMAccessPoint *dummyAp = static_cast(g_object_new(NM_TYPE_ACCESS_POINT, NULL)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) + .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x333223))); + + // AP property mocks + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) + .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) + .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) + .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength + + const char* ssid_str = "TestWiFiNetwork_1"; + GBytes* fake_ssid1 = g_bytes_new_static(ssid_str, strlen(ssid_str)); + const char* ssid_str2 = "TestWiFiNetwork_2"; + GBytes* fake_ssid2 = g_bytes_new_static(ssid_str2, strlen(ssid_str2)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) + .WillOnce(::testing::Return(fake_ssid1)) + .WillOnce(::testing::Return(fake_ssid2)) + .WillOnce(::testing::Return(fake_ssid2)); + + GPtrArray* fakeAccessPoints = g_ptr_array_new(); + g_ptr_array_add(fakeAccessPoints, reinterpret_cast(dummyAp)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_access_points(::testing::_)) + .WillOnce(::testing::Return(fakeAccessPoints)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_to_dbus(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x11111))); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_update2_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMRemoteConnection *connection, GAsyncResult *result, GError **error) -> GVariant* { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_CANCELLED, "update connection activation failed"); + return NULL; + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_update2(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMRemoteConnection *connection, GVariant *settings, NMSettingsUpdate2Flags flags, GVariant *args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(connection); + callback(source_object, nullptr, user_data); + } + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("TestWiFiNetwork_2"))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_connection_valid(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(TRUE)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork_2\",\"passphrase\": \"123499054\",\"security\":1, \"persist\":true}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_bytes_unref(fake_ssid1); + g_bytes_unref(fake_ssid2); + g_object_unref(deviceDummy); + g_ptr_array_free(fakeAccessPoints, TRUE); + g_ptr_array_free(fakeDevices, TRUE); +} + +TEST_F(NetworkManagerWifiTest, WiFiConnect_with_connection_not_valid) +{ + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + NMAccessPoint *dummyAp = static_cast(g_object_new(NM_TYPE_ACCESS_POINT, NULL)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) + .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x333223))); + + // AP property mocks + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) + .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) + .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) + .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength + + const char* ssid_str = "TestWiFiNetwork_1"; + GBytes* fake_ssid1 = g_bytes_new_static(ssid_str, strlen(ssid_str)); + const char* ssid_str2 = "TestWiFiNetwork_2"; + GBytes* fake_ssid2 = g_bytes_new_static(ssid_str2, strlen(ssid_str2)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) + .WillOnce(::testing::Return(fake_ssid1)) + .WillOnce(::testing::Return(fake_ssid2)) + .WillOnce(::testing::Return(fake_ssid2)); + + GPtrArray* fakeAccessPoints = g_ptr_array_new(); + g_ptr_array_add(fakeAccessPoints, reinterpret_cast(dummyAp)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_access_points(::testing::_)) + .WillOnce(::testing::Return(fakeAccessPoints)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_add_connection2_finish(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GAsyncResult *result, GVariant **out_result, GError **error) -> NMRemoteConnection* { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_FAILED, "add connection activation failed %s", "Network interface is busy or unavailable"); + return reinterpret_cast(NULL); + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_add_connection2(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, GVariant *args, gboolean ignore_out_result, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(client); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_delete(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMRemoteConnection *connection, GCancellable *cancellable, GError **error) -> gboolean { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_FAILED, "connection delete failed"); + return FALSE; + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_object_get_path(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("NULL"))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_to_dbus(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x11111))); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("TestWiFiNetwork_2"))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_connection_valid(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(false)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork_2\",\"passphrase\": \"123499054\",\"security\":1, \"persist\":false}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_bytes_unref(fake_ssid1); + g_bytes_unref(fake_ssid2); + g_object_unref(deviceDummy); + g_ptr_array_free(fakeAccessPoints, TRUE); + g_ptr_array_free(fakeDevices, TRUE); +} + TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_deviceFailed) { GPtrArray* fakeDevices = g_ptr_array_new(); @@ -1554,6 +1770,122 @@ TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_sae_failed) g_ptr_array_free(fakeDevices, TRUE); } +TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_sae_update_success) +{ + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("test"))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_to_dbus(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x11111))); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_update2_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMRemoteConnection *connection, GAsyncResult *result, GError **error) -> GVariant* { + GVariant* newVariant = g_variant_new_string("UpdatedVariant"); + return newVariant; + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_update2(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMRemoteConnection *connection, GVariant *settings, NMSettingsUpdate2Flags flags, GVariant *args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(connection); + callback(source_object, nullptr, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("AddToKnownSSIDs"), + _T("{" + " \"ssid\":\"test\"," + "\"passphrase\": \"5454543343\"," + "\"security\":2," + " \"persist\":false" + " }"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); + g_object_unref(conn); + g_ptr_array_free(dummyConns, TRUE); +} + +TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_sae_update_failed) +{ + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn); + + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_available_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("test"))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_to_dbus(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x11111))); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_update2_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMRemoteConnection *connection, GAsyncResult *result, GError **error) -> GVariant* { + *error = g_error_new(G_IO_ERROR, G_IO_ERROR_CANCELLED, "update connection activation failed"); + return NULL; + })); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_update2(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMRemoteConnection *connection, GVariant *settings, NMSettingsUpdate2Flags flags, GVariant *args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(connection); + callback(source_object, nullptr, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("AddToKnownSSIDs"), + _T("{" + " \"ssid\":\"test\"," + "\"passphrase\": \"5454543343\"," + "\"security\":2," + " \"persist\":false" + " }"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + g_object_unref(deviceDummy); + g_ptr_array_free(fakeDevices, TRUE); + g_object_unref(conn); + g_ptr_array_free(dummyConns, TRUE); +} + TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_sae_success) { GPtrArray* fakeDevices = g_ptr_array_new(); diff --git a/tests/mocks/LibnmWraps.cpp b/tests/mocks/LibnmWraps.cpp index e68ce06cf..ecb7c416a 100644 --- a/tests/mocks/LibnmWraps.cpp +++ b/tests/mocks/LibnmWraps.cpp @@ -46,6 +46,10 @@ extern "C" GVariant* __wrap_nm_remote_connection_update2_finish(NMRemoteConnecti return LibnmWraps::getInstance().nm_remote_connection_update2_finish(connection, result, error); } +extern "C" void __wrap_nm_remote_connection_update2(NMRemoteConnection *connection, GVariant *settings, NMSettingsUpdate2Flags flags, GVariant *args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + LibnmWraps::getInstance().nm_remote_connection_update2(connection, settings, flags, args, cancellable, callback, user_data); +} + extern "C" void __wrap_nm_client_add_connection2(NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, GVariant *args, gboolean ignore_out_result, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { LibnmWraps::getInstance().nm_client_add_connection2(client, settings, flags, args, ignore_out_result, cancellable, callback, user_data); } @@ -203,6 +207,10 @@ extern "C" guint8 __wrap_nm_access_point_get_strength(NMAccessPoint *ap) { return LibnmWraps::getInstance().nm_access_point_get_strength(ap); } +extern "C" gboolean __wrap_nm_access_point_connection_valid(NMAccessPoint *ap, NMConnection *connection) { + return LibnmWraps::getInstance().nm_access_point_connection_valid(ap, connection); +} + extern "C" NMAccessPoint* __wrap_nm_device_wifi_get_active_access_point(NMDeviceWifi *device) { return LibnmWraps::getInstance().nm_device_wifi_get_active_access_point(device); } @@ -308,6 +316,10 @@ extern "C" int __wrap_nm_ip_address_get_family(NMIPAddress *address) { return LibnmWraps::getInstance().nm_ip_address_get_family(address); } +extern "C" GVariant* __wrap_nm_connection_to_dbus(NMConnection *connection, NMConnectionSerializationFlags flags) { + return LibnmWraps::getInstance().nm_connection_to_dbus(connection, flags); +} + LibnmWrapsImpl* LibnmWraps::impl = nullptr; LibnmWraps::LibnmWraps() {} @@ -507,6 +519,11 @@ guint8 LibnmWraps::nm_access_point_get_strength(NMAccessPoint *ap) { return impl->nm_access_point_get_strength(ap); } +gboolean LibnmWraps::nm_access_point_connection_valid(NMAccessPoint *ap, NMConnection *connection) { + EXPECT_NE(impl, nullptr); + return impl->nm_access_point_connection_valid(ap, connection); +} + NMAccessPoint* LibnmWraps::nm_device_wifi_get_active_access_point(NMDeviceWifi *device) { EXPECT_NE(impl, nullptr); return impl->nm_device_wifi_get_active_access_point(device); @@ -618,6 +635,11 @@ GVariant* LibnmWraps::nm_remote_connection_update2_finish(NMRemoteConnection *co return impl->nm_remote_connection_update2_finish(connection, result, error); } +void LibnmWraps::nm_remote_connection_update2(NMRemoteConnection *connection, GVariant *settings, NMSettingsUpdate2Flags flags, GVariant *args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + EXPECT_NE(impl, nullptr); + impl->nm_remote_connection_update2(connection, settings, flags, args, cancellable, callback, user_data); +} + void LibnmWraps::nm_client_add_connection2(NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, GVariant *args, gboolean ignore_out_result, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { EXPECT_NE(impl, nullptr); impl->nm_client_add_connection2(client, settings, flags, args, ignore_out_result, cancellable, callback, user_data); @@ -693,3 +715,8 @@ int LibnmWraps::nm_ip_address_get_family(NMIPAddress* address) { EXPECT_NE(impl, nullptr); return impl->nm_ip_address_get_family(address); } + +GVariant* LibnmWraps::nm_connection_to_dbus(NMConnection *connection, NMConnectionSerializationFlags flags) { + EXPECT_NE(impl, nullptr); + return impl->nm_connection_to_dbus(connection, flags); +} diff --git a/tests/mocks/LibnmWraps.h b/tests/mocks/LibnmWraps.h index 6a6a392dc..dc62f0a92 100644 --- a/tests/mocks/LibnmWraps.h +++ b/tests/mocks/LibnmWraps.h @@ -54,6 +54,7 @@ class LibnmWrapsImpl { virtual NM80211Mode nm_access_point_get_mode(NMAccessPoint *ap) = 0; virtual guint32 nm_access_point_get_max_bitrate(NMAccessPoint *ap) = 0; virtual guint8 nm_access_point_get_strength(NMAccessPoint *ap) = 0; + virtual gboolean nm_access_point_connection_valid(NMAccessPoint *ap, NMConnection *connection) = 0; virtual NMAccessPoint* nm_device_wifi_get_active_access_point(NMDeviceWifi *device) = 0; virtual const GPtrArray* nm_device_wifi_get_access_points(NMDeviceWifi *device) = 0; virtual const GPtrArray* nm_device_get_available_connections(NMDevice* device) = 0; @@ -88,6 +89,13 @@ class LibnmWrapsImpl { virtual GVariant *nm_remote_connection_update2_finish(NMRemoteConnection *connection, GAsyncResult *result, GError **error) = 0; + virtual void nm_remote_connection_update2(NMRemoteConnection *connection, + GVariant *settings, + NMSettingsUpdate2Flags flags, + GVariant *args, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) = 0; virtual void nm_client_add_connection2(NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, @@ -131,6 +139,7 @@ class LibnmWrapsImpl { virtual const char* nm_active_connection_get_connection_type(NMActiveConnection *connection) = 0; virtual NMDeviceStateReason nm_device_get_state_reason(NMDevice *device) = 0; virtual int nm_ip_address_get_family(NMIPAddress *address) = 0; + virtual GVariant* nm_connection_to_dbus(NMConnection *connection, NMConnectionSerializationFlags flags) = 0; }; @@ -149,6 +158,7 @@ class LibnmWraps { static const char* nm_active_connection_get_connection_type(NMActiveConnection *connection); static NMDeviceStateReason nm_device_get_state_reason(NMDevice *device); static int nm_ip_address_get_family(NMIPAddress *address); + static GVariant* nm_connection_to_dbus(NMConnection *connection, NMConnectionSerializationFlags flags); static NMState nm_client_get_state(NMClient *client); static gboolean nm_client_get_nm_running(NMClient *client); static gint64 nm_device_wifi_get_last_scan(NMDeviceWifi *device); @@ -171,6 +181,13 @@ class LibnmWraps { static GVariant *nm_remote_connection_update2_finish(NMRemoteConnection *connection, GAsyncResult *result, GError **error); + static void nm_remote_connection_update2(NMRemoteConnection *connection, + GVariant *settings, + NMSettingsUpdate2Flags flags, + GVariant *args, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); static void nm_client_add_connection2(NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, @@ -224,6 +241,7 @@ class LibnmWraps { static NM80211Mode nm_access_point_get_mode(NMAccessPoint *ap); static guint32 nm_access_point_get_max_bitrate(NMAccessPoint *ap); static guint8 nm_access_point_get_strength(NMAccessPoint *ap); + static gboolean nm_access_point_connection_valid(NMAccessPoint *ap, NMConnection *connection); static NMAccessPoint* nm_device_wifi_get_active_access_point(NMDeviceWifi *device); static const GPtrArray* nm_device_wifi_get_access_points(NMDeviceWifi *device); static const GPtrArray* nm_device_get_available_connections(NMDevice* device); diff --git a/tests/mocks/LibnmWrapsMock.h b/tests/mocks/LibnmWrapsMock.h index 8e766ddac..a728ac941 100644 --- a/tests/mocks/LibnmWrapsMock.h +++ b/tests/mocks/LibnmWrapsMock.h @@ -48,6 +48,7 @@ extern "C" guint32 __real_nm_access_point_get_frequency(NMAccessPoint *ap); extern "C" NM80211Mode __real_nm_access_point_get_mode(NMAccessPoint *ap); extern "C" guint32 __real_nm_access_point_get_max_bitrate(NMAccessPoint *ap); extern "C" guint8 __real_nm_access_point_get_strength(NMAccessPoint *ap); +extern "C" gboolean __real_nm_access_point_connection_valid(NMAccessPoint *ap, NMConnection *connection); extern "C" NMAccessPoint* __real_nm_device_wifi_get_active_access_point(NMDeviceWifi *device); extern "C" void __real_nm_device_wifi_request_scan_async(NMDeviceWifi *device, @@ -91,6 +92,13 @@ extern "C" NMActiveConnection* __real_nm_client_add_and_activate_connection_fini extern "C" GVariant* __real_nm_remote_connection_update2_finish(NMRemoteConnection *connection, GAsyncResult *result, GError **error); +extern "C" void __real_nm_remote_connection_update2(NMRemoteConnection *connection, + GVariant *settings, + NMSettingsUpdate2Flags flags, + GVariant *args, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); extern "C" void __real_nm_client_add_connection2(NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, @@ -128,6 +136,7 @@ extern "C" NMSettingWireless *__real_nm_connection_get_setting_wireless(NMConnec extern "C" GBytes *__real_nm_setting_wireless_get_ssid(NMSettingWireless *setting); extern "C" NMState __real_nm_client_get_state(NMClient *client); extern "C" gboolean __real_nm_client_get_nm_running(NMClient *client); +extern "C" GVariant* __real_nm_connection_to_dbus(NMConnection *connection, NMConnectionSerializationFlags flags); class LibnmWrapsImplMock : public LibnmWrapsImpl { @@ -157,6 +166,12 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { [&](NMIPAddress* address) -> int { return __real_nm_ip_address_get_family(address); })); + + ON_CALL(*this, nm_connection_to_dbus(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMConnection* connection, NMConnectionSerializationFlags flags) -> GVariant* { + return __real_nm_connection_to_dbus(connection, flags); + })); ON_CALL(*this, nm_device_wifi_get_last_scan(::testing::_)) .WillByDefault(::testing::Invoke( [&](NMDeviceWifi* device) -> gint64 { @@ -207,6 +222,12 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { [&](NMRemoteConnection* connection, GAsyncResult* result, GError** error) -> GVariant* { return __real_nm_remote_connection_update2_finish(connection, result, error); })); + + ON_CALL(*this, nm_remote_connection_update2(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMRemoteConnection* connection, GVariant* settings, NMSettingsUpdate2Flags flags, GVariant* args, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data) { + __real_nm_remote_connection_update2(connection, settings, flags, args, cancellable, callback, user_data); + })); ON_CALL(*this, nm_client_add_connection2(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) .WillByDefault(::testing::Invoke( [&](NMClient* client, GVariant* settings, NMSettingsAddConnection2Flags flags, GVariant* args, gboolean ignore_out_result, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data) { @@ -415,6 +436,12 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { return __real_nm_access_point_get_strength(ap); })); + ON_CALL(*this, nm_access_point_connection_valid(::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](NMAccessPoint* ap, NMConnection* connection) -> gboolean { + return __real_nm_access_point_connection_valid(ap, connection); + })); + ON_CALL(*this, nm_device_wifi_get_active_access_point(::testing::_)) .WillByDefault(::testing::Invoke( [&](NMDeviceWifi* device) -> NMAccessPoint* { @@ -522,6 +549,7 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { MOCK_METHOD(NM80211Mode, nm_access_point_get_mode, (NMAccessPoint *ap), (override)); MOCK_METHOD(guint32, nm_access_point_get_max_bitrate, (NMAccessPoint *ap), (override)); MOCK_METHOD(guint8, nm_access_point_get_strength, (NMAccessPoint *ap), (override)); + MOCK_METHOD(gboolean, nm_access_point_connection_valid, (NMAccessPoint *ap, NMConnection *connection), (override)); MOCK_METHOD(NMAccessPoint*, nm_device_wifi_get_active_access_point, (NMDeviceWifi *device), (override)); MOCK_METHOD(const GPtrArray*, nm_device_wifi_get_access_points, (NMDeviceWifi *device), (override)); MOCK_METHOD(const GPtrArray*, nm_device_get_available_connections, (NMDevice *device), (override)); @@ -550,6 +578,7 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { MOCK_METHOD(GBytes*, nm_setting_wireless_get_ssid, (NMSettingWireless *setting), (override)); MOCK_METHOD(NMActiveConnection*, nm_client_add_and_activate_connection_finish, (NMClient *client, GAsyncResult *result, GError **error), (override)); MOCK_METHOD(GVariant*, nm_remote_connection_update2_finish, (NMRemoteConnection *connection, GAsyncResult *result, GError **error), (override)); + MOCK_METHOD(void, nm_remote_connection_update2, (NMRemoteConnection *connection, GVariant *settings, NMSettingsUpdate2Flags flags, GVariant *args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); MOCK_METHOD(void, nm_client_add_connection2, (NMClient *client, GVariant *settings, NMSettingsAddConnection2Flags flags, GVariant *args, gboolean ignore_out_result, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), (override)); MOCK_METHOD(NMRemoteConnection*, nm_client_add_connection2_finish, (NMClient *client, GAsyncResult *result, GVariant **out_result, GError **error), (override)); MOCK_METHOD(gboolean, nm_remote_connection_delete, (NMRemoteConnection *connection, GCancellable *cancellable, GError **error), (override)); @@ -559,4 +588,5 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { MOCK_METHOD(const char*, nm_active_connection_get_connection_type, (NMActiveConnection *connection), (override)); MOCK_METHOD(NMDeviceStateReason, nm_device_get_state_reason, (NMDevice *device), (override)); MOCK_METHOD(int, nm_ip_address_get_family, (NMIPAddress *address), (override)); + MOCK_METHOD(GVariant*, nm_connection_to_dbus, (NMConnection *connection, NMConnectionSerializationFlags flags), (override)); }; From f2133cff91f2a8327b55e1408f8faba28b247438 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 9 Oct 2025 08:02:50 +0530 Subject: [PATCH 193/271] RDKEMW-7465: GetPrimaryInterface must return empty when WiFi is off (#233) * inittail commit with m_enabeld variable * new changes * getIpsetting retun udated * error corrected * updated unit test workflow --- plugin/NetworkManagerImplementation.cpp | 20 ++++ plugin/NetworkManagerImplementation.h | 2 + plugin/gnome/NetworkManagerGnomeProxy.cpp | 95 ++++++++------- .../gnome/gdbus/NetworkManagerGdbusProxy.cpp | 24 ++++ plugin/rdk/NetworkManagerRDKProxy.cpp | 17 ++- tests/l2Test/libnm/l2_test_libnmproxy.cpp | 111 ++++++++++++------ tests/l2Test/rdk/l2_test_rdkproxy.cpp | 47 ++++++++ 7 files changed, 240 insertions(+), 76 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 2219deb9a..5498a0afe 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -47,6 +47,8 @@ namespace WPEFramework m_publicIP = ""; m_ethConnected.store(false); m_wlanConnected.store(false); + m_ethEnabled.store(false); + m_wlanEnabled.store(false); /* Set NetworkManager Out-Process name to be NWMgrPlugin */ Core::ProcessInfo().Name("NWMgrPlugin"); @@ -642,9 +644,15 @@ namespace WPEFramework if(Exchange::INetworkManager::INTERFACE_LINK_UP == state) { if(interface == "eth0") + { m_ethConnected.store(true); + m_ethEnabled.store(true); + } else if(interface == "wlan0") + { m_wlanConnected.store(true); + m_wlanEnabled.store(true); + } // connectivityMonitor.switchToInitialCheck(); // FIXME : Availability of interface does not mean that it has internet connection, so not triggering connectivity monitor check here. } @@ -663,9 +671,15 @@ namespace WPEFramework NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); if(currentActiveinterface == "eth0") + { m_ethConnected.store(true); + m_ethEnabled.store(true); + } else if (currentActiveinterface == "wlan0") + { m_wlanConnected.store(true); + m_wlanEnabled.store(true); + } // FIXME : This could be the place to define `m_defaultInterface` to incoming `currentActiveinterface`. // m_defaultInterface = currentActiveinterface; @@ -683,9 +697,15 @@ namespace WPEFramework // Switch the connectivity monitor to initial check // if ipaddress is aquired means there should be interface connected if(interface == "eth0") + { m_ethConnected.store(true); + m_ethEnabled.store(true); + } else if(interface == "wlan0") + { m_wlanConnected.store(true); + m_wlanEnabled.store(true); + } // FIXME : Availability of ip address for a given interface does not mean that its the default interface. This hardcoding will work for RDKProxy but not for Gnome. if (m_ethConnected.load() && m_wlanConnected.load()) diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 6d48b1282..87d2fb3cd 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -314,6 +314,8 @@ namespace WPEFramework public: std::atomic m_ethConnected; std::atomic m_wlanConnected; + std::atomic m_ethEnabled; + std::atomic m_wlanEnabled; string m_defaultInterface; std::string m_lastConnectedSSID; mutable ConnectivityMonitor connectivityMonitor; diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index a71a87c65..d6ca80ca8 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -281,6 +281,7 @@ namespace WPEFramework m_defaultInterface = nmUtils::wlanIface(); NMLOG_INFO("default interface is %s", m_defaultInterface.c_str()); + // getInitialConnectionState function not called here, as event monitor will report the initial state nmEvent = GnomeNetworkManagerEvents::getInstance(); nmEvent->startNetworkMangerEventMonitor(); wifi = wifiManager::getInstance(); @@ -331,11 +332,13 @@ namespace WPEFramework interface.type = INTERFACE_TYPE_WIFI; interface.name = wifiname; m_wlanConnected.store(interface.connected); + m_wlanEnabled.store(interface.enabled); } - if(ifaceStr == ethname) { + else if(ifaceStr == ethname) { interface.type = INTERFACE_TYPE_ETHERNET; interface.name = ethname; m_ethConnected.store(interface.connected); + m_ethEnabled.store(interface.enabled); } interfaceList.push_back(interface); @@ -356,7 +359,6 @@ namespace WPEFramework GError *error = NULL; NMActiveConnection *activeConn = NULL; NMRemoteConnection *remoteConn = NULL; - std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); if(client == nullptr) { @@ -364,53 +366,57 @@ namespace WPEFramework return Core::ERROR_GENERAL; } - activeConn = nm_client_get_primary_connection(client); - if (activeConn == NULL) { - NMLOG_WARNING("no active activeConn Interface found"); - NMDeviceState ethState = ifaceState(client, nmUtils::ethIface()); - /* if ethernet is connected but not completely activate then ethernet is taken as primary else wifi */ - if(ethState > NM_DEVICE_STATE_DISCONNECTED && ethState < NM_DEVICE_STATE_DEACTIVATING) - m_defaultInterface = interface = ethname; - else - m_defaultInterface = interface = wifiname; // default is wifi + if(!m_wlanEnabled.load() && !m_ethEnabled.load()) + { + NMLOG_INFO("Both iface disabled state, returning no primary interface"); + interface.clear(); + m_defaultInterface = interface; return Core::ERROR_NONE; } - remoteConn = nm_active_connection_get_connection(activeConn); - if(remoteConn == NULL) + activeConn = nm_client_get_primary_connection(client); + if (activeConn != NULL) { - NMLOG_WARNING("primary connection but remote connection error"); - NMDeviceState ethState = ifaceState(client, nmUtils::ethIface()); - /* if ethernet is connected but not completely activate then ethernet is taken as primary else wifi */ - if(ethState > NM_DEVICE_STATE_DISCONNECTED && ethState < NM_DEVICE_STATE_DEACTIVATING) - m_defaultInterface = interface = ethname; + remoteConn = nm_active_connection_get_connection(activeConn); + if(remoteConn != NULL) + { + const char *ifacePtr = nm_connection_get_interface_name(NM_CONNECTION(remoteConn)); + if(ifacePtr != NULL) + { + interface = ifacePtr; + if(interface != nmUtils::wlanIface() && interface != nmUtils::ethIface()) + { + NMLOG_WARNING("primary interface is not Ethernet or WiFi"); + interface.clear(); + } + else + { + NMLOG_DEBUG("primary interface is %s", interface.c_str()); + rc = Core::ERROR_NONE; + } + } + else + NMLOG_WARNING("interface name is missing form connection"); + } else - m_defaultInterface = interface = wifiname; // default is wifi - return Core::ERROR_NONE; + NMLOG_WARNING("primary connection but remote connection error"); } + else + NMLOG_WARNING("No primary connection"); - const char *ifacePtr = nm_connection_get_interface_name(NM_CONNECTION(remoteConn)); - if(ifacePtr == NULL) + if(rc != Core::ERROR_NONE) { - NMLOG_ERROR("nm_connection_get_interface_name is failed"); - /* Temporary mitigation for nm_connection_get_interface_name failure */ - if(m_ethConnected.load()) - interface = ethname; - else // default always wifi - interface = wifiname; + // if no active connection or libnm error, choose the default interface based on the connection state + NMDeviceState ethState = ifaceState(client, nmUtils::ethIface()); + /* if ethernet is connected but not completely activate then ethernet is taken as primary else wifi */ + if((ethState > NM_DEVICE_STATE_DISCONNECTED && ethState < NM_DEVICE_STATE_DEACTIVATING) || m_ethConnected.load()) + interface = nmUtils::ethIface(); + else + interface = nmUtils::wlanIface(); // default is wifi rc = Core::ERROR_NONE; + // TODO: if no proimary connection, should we return empty string? RDK V return empty string } - else - { - interface = ifacePtr; - if(interface != wifiname && interface != ethname) - { - NMLOG_ERROR("primary interface is not Ethernet or WiFi"); - interface.clear(); - } - else - rc = Core::ERROR_NONE; - } + m_defaultInterface = interface; return rc; } @@ -437,6 +443,12 @@ namespace WPEFramework } NMLOG_INFO("interface %s state: %s", interface.c_str(), enabled ? "enabled" : "disabled"); + // update the interface global cache state + if(interface == nmUtils::wlanIface() && _instance != NULL) + _instance->m_wlanEnabled.store(enabled); + else if(interface == nmUtils::ethIface() && _instance != NULL) + _instance->m_ethEnabled.store(enabled); + if(enabled) { sleep(1); // wait for 1 sec to change the device state @@ -558,10 +570,11 @@ namespace WPEFramework NMLOG_WARNING("default interface get failed"); return Core::ERROR_NONE; } + if(interface.empty()) { - NMLOG_DEBUG("default interface return empty default is wlan0"); - interface = wifiname; + NMLOG_WARNING("default interface is empty, no active interface"); + return Core::ERROR_GENERAL; } } else if(wifiname != interface && ethname != interface) diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp index 99248e97e..979935377 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp @@ -102,7 +102,16 @@ namespace WPEFramework uint32_t rc = Core::ERROR_GENERAL; std::vector interfaceList; if(_nmGdbusClient->getAvailableInterfaces(interfaceList)) + { + for (const auto& iface : interfaceList) + { + if (iface.name == "eth0") + m_ethEnabled.store(iface.enabled); + else if (iface.name == "wlan0") + m_wlanEnabled.store(iface.enabled); + } rc = Core::ERROR_NONE; + } else NMLOG_ERROR("GetAvailableInterfaces failed"); using Implementation = RPC::IteratorType; @@ -113,6 +122,15 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::GetPrimaryInterface (string& interface /* @out */) { + + if(!m_wlanEnabled.load() && !m_ethEnabled.load()) + { + NMLOG_INFO("Both iface disabled state, returning no primary interface"); + interface.clear(); + m_defaultInterface = interface; + return Core::ERROR_NONE; + } + if(_nmGdbusClient->getPrimaryInterface(interface)) return Core::ERROR_NONE; else @@ -131,7 +149,13 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; if(_nmGdbusClient->setInterfaceState(interface, enabled)) + { + if(interface == nmUtils::wlanIface() && _instance != NULL) + _instance->m_wlanEnabled.store(enabled); + else if(interface == nmUtils::ethIface() && _instance != NULL) + _instance->m_ethEnabled.store(enabled); rc = Core::ERROR_NONE; + } else NMLOG_ERROR("SetInterfaceState failed"); return rc; diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 6ff557e22..14e7697fc 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -545,10 +545,12 @@ namespace WPEFramework if ("eth0" == interfaceName) { tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_ETHERNET; m_ethConnected.store(tmp.connected); + m_ethEnabled.store(tmp.enabled); } else if ("wlan0" == interfaceName) { tmp.type = Exchange::INetworkManager::INTERFACE_TYPE_WIFI; m_wlanConnected.store(tmp.connected); + m_wlanEnabled.store(tmp.enabled); } interfaceList.push_back(tmp); @@ -573,6 +575,15 @@ namespace WPEFramework LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; IARM_BUS_NetSrvMgr_DefaultRoute_t defaultRoute = {0}; + + if(!m_wlanEnabled.load() && !m_ethEnabled.load()) + { + NMLOG_INFO("Both iface disabled state, returning no primary interface"); + interface.clear(); + m_defaultInterface = interface; + return Core::ERROR_NONE; + } + if (IARM_RESULT_SUCCESS == IARM_Bus_Call(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_getDefaultInterface, (void*)&defaultRoute, sizeof(defaultRoute))) { NMLOG_INFO ("Call to %s for %s returned interface = %s, gateway = %s", IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_getDefaultInterface, defaultRoute.interface, defaultRoute.gateway); @@ -608,7 +619,11 @@ namespace WPEFramework iarmData.persist = true; if (IARM_RESULT_SUCCESS == IARM_Bus_Call (IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_setInterfaceEnabled, (void *)&iarmData, sizeof(iarmData))) { - NMLOG_INFO ("Call to %s for %s success", IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_setInterfaceEnabled); + NMLOG_INFO ("Call to %s for %s success", IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_setInterfaceEnabled);\ + if(interface == "wlan0" && _instance != NULL) + _instance->m_wlanEnabled.store(enable); + else if(interface == "eth0" && _instance != NULL) + _instance->m_ethEnabled.store(enable); rc = Core::ERROR_NONE; } else diff --git a/tests/l2Test/libnm/l2_test_libnmproxy.cpp b/tests/l2Test/libnm/l2_test_libnmproxy.cpp index b67cfc949..1cf34774c 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxy.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxy.cpp @@ -340,31 +340,42 @@ TEST_F(NetworkManagerTest, SetHostName_iface_wlan0) TEST_F(NetworkManagerTest, GetPrimaryInterface_eth0) { + string interface{}; EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) .WillOnce(::testing::Return(reinterpret_cast(0x100178))); - + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); + NetworkManagerImpl2->m_ethEnabled = true; + uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); + EXPECT_EQ(result, Core::ERROR_NONE); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); - EXPECT_EQ(response, _T("{\"interface\":\"eth0\",\"success\":true}")); + EXPECT_EQ(interface, "eth0"); } TEST_F(NetworkManagerTest, GetPrimaryInterface_wlan0) { + string interface{}; EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) .WillOnce(::testing::Return(reinterpret_cast(0x100178))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) .WillOnce(::testing::Return(NM_DEVICE_STATE_UNAVAILABLE)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); - EXPECT_EQ(response, _T("{\"interface\":\"wlan0\",\"success\":true}")); + Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); + NetworkManagerImpl2->m_wlanEnabled = true; + uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); + EXPECT_EQ(result, Core::ERROR_NONE); + + EXPECT_EQ(interface, "wlan0"); } TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_null_eth0) { NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + string interface{}; EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) .WillOnce(::testing::Return(reinterpret_cast(0x100178))); @@ -378,14 +389,19 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_null_eth0) EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) .WillOnce(::testing::Return(reinterpret_cast(NULL))); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); - EXPECT_EQ(response, _T("{\"interface\":\"eth0\",\"success\":true}")); + Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); + NetworkManagerImpl2->m_ethEnabled = true; + uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); + EXPECT_EQ(result, Core::ERROR_NONE); + EXPECT_EQ(interface, "eth0"); + g_object_unref(dummyActiveConn); } TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_null_wlan0) { NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + string interface{}; EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) .WillOnce(::testing::Return(reinterpret_cast(0x100178))); @@ -399,8 +415,11 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_null_wlan0) EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) .WillOnce(::testing::Return(reinterpret_cast(NULL))); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); - EXPECT_EQ(response, _T("{\"interface\":\"wlan0\",\"success\":true}")); + Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); + NetworkManagerImpl2->m_wlanEnabled = true; + uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); + EXPECT_EQ(result, Core::ERROR_NONE); + EXPECT_EQ(interface, "wlan0"); g_object_unref(dummyActiveConn); } @@ -408,6 +427,8 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_wlan0) { NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + string interface{}; + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) .WillOnce(::testing::Return(dummyActiveConn)); @@ -417,8 +438,12 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_wlan0) EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) .WillOnce(::testing::Return("wlan0")); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); - EXPECT_EQ(response, _T("{\"interface\":\"wlan0\",\"success\":true}")); + Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); + NetworkManagerImpl2->m_wlanEnabled = true; + uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); + EXPECT_EQ(result, Core::ERROR_NONE); + EXPECT_EQ(interface, "wlan0"); + g_object_unref(dummyActiveConn); g_object_unref(dummyRemoteConn); } @@ -427,6 +452,8 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_eth0) { NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + string interface{}; + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) .WillOnce(::testing::Return(dummyActiveConn)); @@ -436,8 +463,12 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_eth0) EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) .WillOnce(::testing::Return("eth0")); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); - EXPECT_EQ(response, _T("{\"interface\":\"eth0\",\"success\":true}")); + Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); + NetworkManagerImpl2->m_ethEnabled = true; + uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); + EXPECT_EQ(result, Core::ERROR_NONE); + EXPECT_EQ(interface, "eth0"); + g_object_unref(dummyActiveConn); g_object_unref(dummyRemoteConn); } @@ -446,6 +477,11 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_unknown) { NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + string interface{}; + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) .WillOnce(::testing::Return(dummyActiveConn)); @@ -455,8 +491,12 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_unknown) EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) .WillOnce(::testing::Return("unknown")); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); - EXPECT_EQ(response, _T("{\"success\":false}")); + Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); + NetworkManagerImpl2->m_ethEnabled = true; + uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); + EXPECT_EQ(result, Core::ERROR_NONE); + EXPECT_EQ(interface, "wlan0"); + g_object_unref(dummyActiveConn); g_object_unref(dummyRemoteConn); } @@ -465,6 +505,11 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_iface_null) { NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + string interface{}; + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) .WillOnce(::testing::Return(dummyActiveConn)); @@ -472,10 +517,14 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_iface_null) .WillOnce(::testing::Return(dummyRemoteConn)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) - .WillOnce(::testing::Return(nullptr)); + .WillOnce(::testing::Return(static_cast(NULL))); + + Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); + NetworkManagerImpl2->m_ethEnabled = true; + uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); + EXPECT_EQ(result, Core::ERROR_NONE); + EXPECT_EQ(interface, "wlan0"); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); - EXPECT_EQ(response, _T("{\"interface\":\"wlan0\",\"success\":true}")); g_object_unref(dummyActiveConn); g_object_unref(dummyRemoteConn); } @@ -668,28 +717,19 @@ TEST_F(NetworkManagerTest, GetIPSettings_invalid_state) TEST_F(NetworkManagerTest, GetIPSettings_interface_Empty) { - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100172))) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNAVAILABLE)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"\"}"), response)); EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); } TEST_F(NetworkManagerTest, GetIPSettings_GetPrimary_failed) { - // EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - // .WillOnce(::testing::Return(reinterpret_cast(0x100172))) - // .WillOnce(::testing::Return(reinterpret_cast(0x100178))); - - // EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) - // .WillOnce(::testing::Return(NM_DEVICE_STATE_UNAVAILABLE)); - NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(0x100178))) + .WillOnce(::testing::Return(reinterpret_cast(0x100179))); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) .WillOnce(::testing::Return(dummyActiveConn)); @@ -699,8 +739,11 @@ TEST_F(NetworkManagerTest, GetIPSettings_GetPrimary_failed) EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) .WillOnce(::testing::Return("unknown")); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"\"}"), response)); - EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); + NetworkManagerImpl2->m_ethEnabled = true; + + string interface; const string ipversion; Exchange::INetworkManager::IPAddress address; + EXPECT_EQ(Core::ERROR_GENERAL, NetworkManagerImpl2->GetIPSettings(interface, ipversion, address)); g_object_unref(dummyActiveConn); g_object_unref(dummyRemoteConn); diff --git a/tests/l2Test/rdk/l2_test_rdkproxy.cpp b/tests/l2Test/rdk/l2_test_rdkproxy.cpp index d97eac192..03aecc534 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxy.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxy.cpp @@ -49,6 +49,7 @@ class NetworkManagerTest : public ::testing::Test { // Mock classes IarmBusImplMock *p_iarmBusImplMock = nullptr; WrapsImplMock *p_wrapsImplMock = nullptr; + IARM_EventHandler_t _nmEventHandler{}; Core::ProxyType NetworkManagerImpl; NiceMock comLinkMock; @@ -106,7 +107,35 @@ class NetworkManagerTest : public ::testing::Test { NetworkManagerImpl = Core::ProxyType::Create(); return &NetworkManagerImpl; })); + ON_CALL(*p_iarmBusImplMock, IARM_Bus_Init(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME))) + .WillByDefault(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_ENABLED_STATUS)) { + _nmEventHandler = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS)) { + _nmEventHandler = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS)) { + _nmEventHandler = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_NETWORK_MANAGER_EVENT_DEFAULT_INTERFACE)) { + _nmEventHandler = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_WIFI_MGR_EVENT_onAvailableSSIDs)) { + _nmEventHandler = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged)) { + _nmEventHandler = handler; + } + if ((string(IARM_BUS_NM_SRV_MGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_WIFI_MGR_EVENT_onError)) { + _nmEventHandler = handler; + } + return IARM_RESULT_SUCCESS; + })); ON_CALL(*p_iarmBusImplMock, IARM_Bus_Init(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME))) .WillByDefault(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); @@ -273,6 +302,9 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface) strcpy(mockDefaultRoute.interface, "eth0"); strcpy(mockDefaultRoute.gateway, "192.168.1.1"); + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "eth0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), ::testing::StrEq(IARM_BUS_NETSRVMGR_API_getDefaultInterface), ::testing::NotNull(), sizeof(mockDefaultRoute))) @@ -289,15 +321,30 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface) TEST_F(NetworkManagerTest, GetPrimaryInterface_Failed) { + EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), ::testing::StrEq(IARM_BUS_NETSRVMGR_API_getDefaultInterface), ::testing::NotNull(), ::testing::_)) .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "eth0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T("{}"), response)); EXPECT_EQ(response, _T("{\"success\":false}")); } +TEST_F(NetworkManagerTest, GetPrimaryInterface_BothInterfacesDown) +{ + + IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "eth0", .status = true }; + _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T("{}"), response)); + EXPECT_EQ(response, _T("{\"interface\":\"\",\"success\":true}")); +} + TEST_F(NetworkManagerTest, SetInterfaceState) { EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), From 72e6966d2bc9dac491d4c22738e037a8f71ac182 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:53:18 -0400 Subject: [PATCH 194/271] GetIPsettings caching for Gnome libnm networkmanager (#235) * GetIPsettings caching for Gnome libnm networkmanager Reason for change: Caching the getIpsettings for gnome libnm Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR Gururaja_ErodeSriranganRamlingham@comcast.com --- plugin/gnome/NetworkManagerGnomeProxy.cpp | 55 ++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index d6ca80ca8..aaa7118bd 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -554,6 +554,7 @@ namespace WPEFramework const char* dhcpserver; NMSettingConnection *settings = NULL; NMDevice *device = NULL; + string ipversionStr; std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); @@ -579,10 +580,51 @@ namespace WPEFramework } else if(wifiname != interface && ethname != interface) { - NMLOG_ERROR("interface: %s; not valied", interface.c_str()); + NMLOG_ERROR("interface: %s; not valid", interface.c_str()); return Core::ERROR_GENERAL; } + if(ipversion.empty()) + { + ipversionStr = "IPV4"; + } + else + { + ipversionStr = ipversion; + } + + // Add caching optimization similar to RDK proxy + if (wifiname == interface) + { + if(nmUtils::caseInsensitiveCompare(ipversionStr, "IPV4") && !m_wlanIPv4Address.ipaddress.empty()) + { + NMLOG_DEBUG("%s IPv4 address from cache", wifiname.c_str()); + result = m_wlanIPv4Address; + return Core::ERROR_NONE; + } + else if(nmUtils::caseInsensitiveCompare(ipversion, "IPV6") && !m_wlanIPv6Address.ipaddress.empty()) + { + NMLOG_DEBUG("%s IPv6 address from cache", wifiname.c_str()); + result = m_wlanIPv6Address; + return Core::ERROR_NONE; + } + } + else if (ethname == interface) + { + if(nmUtils::caseInsensitiveCompare(ipversionStr, "IPV4") && !m_ethIPv4Address.ipaddress.empty()) + { + NMLOG_DEBUG("%s IPv4 address from cache", ethname.c_str()); + result = m_ethIPv4Address; + return Core::ERROR_NONE; + } + else if(nmUtils::caseInsensitiveCompare(ipversion, "IPV6") && !m_ethIPv6Address.ipaddress.empty()) + { + NMLOG_DEBUG("%s IPv6 address from cache", ethname.c_str()); + result = m_ethIPv6Address; + return Core::ERROR_NONE; + } + } + device = nm_client_get_device_by_iface(client, interface.c_str()); if (device == NULL) { @@ -686,6 +728,12 @@ namespace WPEFramework result.dhcpserver = dhcpserver; } result.ula = ""; + + // Cache the IPv4 address + if(ethname == interface) + m_ethIPv4Address = result; + else if(wifiname == interface) + m_wlanIPv4Address = result; } } if((result.ipaddress.empty() && !(nmUtils::caseInsensitiveCompare(ipversion, "IPV4"))) || nmUtils::caseInsensitiveCompare(ipversion, "IPV6")) @@ -741,6 +789,11 @@ namespace WPEFramework if(dhcpserver) result.dhcpserver = dhcpserver; } + // Cache the IPv6 address + if(ethname == interface) + m_ethIPv6Address = result; + else if(wifiname == interface) + m_wlanIPv6Address = result; } } if(result.ipaddress.empty()) From bbb016d6758e67ea3f39ad2719469b24c0ddeb05 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 23 Oct 2025 19:32:17 +0530 Subject: [PATCH 195/271] RDKEMW-7465 : GetPrimaryInterface must return empty when WiFi is off (#238) * RDKEMW-7465: GetPrimaryInterface must return empty when WiFi is off Signed-off-by: Muhammed Rafi c * rdk workflow fix * update the loglevel * new getprimary interface logic added * remove un wanted changed --------- Signed-off-by: Muhammed Rafi c --- plugin/NetworkManagerImplementation.cpp | 25 +++ plugin/gnome/NetworkManagerGnomeProxy.cpp | 4 +- .../gnome/gdbus/NetworkManagerGdbusProxy.cpp | 13 +- plugin/rdk/NetworkManagerRDKProxy.cpp | 14 +- tests/l2Test/libnm/l2_test_libnmproxy.cpp | 209 +----------------- tests/l2Test/libnm/l2_test_libnmproxyInit.cpp | 2 +- tests/l2Test/rdk/l2_test_rdkproxy.cpp | 43 ---- tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp | 6 + 8 files changed, 43 insertions(+), 273 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 5498a0afe..69b018bb2 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -316,6 +316,23 @@ namespace WPEFramework return Core::ERROR_NONE; } + /* @brief Get the active Interface used for external world communication */ + uint32_t NetworkManagerImplementation::GetPrimaryInterface (string& interface /* @out */) + { + if(m_ethEnabled.load() && m_ethConnected.load()) + interface = "eth0"; + else if(m_wlanEnabled.load() && m_wlanConnected.load()) + interface = "wlan0"; + else + interface = ""; // no active interface + + NMLOG_DEBUG("Primary interface: %s, eth0: [enabled=%d, connected=%d], wlan0: [enabled=%d, connected=%d]", + interface.c_str(), m_ethEnabled.load(), m_ethConnected.load(), m_wlanEnabled.load(), m_wlanConnected.load()); + + m_defaultInterface = interface; + return Core::ERROR_NONE; + } + /* @brief Get the Public IP used for external world communication */ uint32_t NetworkManagerImplementation::GetPublicIP (string& interface /* @inout */, string &ipversion /* @inout */, string& ipaddress /* @out */) { @@ -657,6 +674,14 @@ namespace WPEFramework // FIXME : Availability of interface does not mean that it has internet connection, so not triggering connectivity monitor check here. } + if(Exchange::INetworkManager::INTERFACE_ADDED == state) + { + if(interface == "eth0") + m_ethEnabled.store(true); + else if(interface == "wlan0") + m_wlanEnabled.store(true); + } + _notificationLock.Lock(); NMLOG_INFO("Posting onInterfaceChange %s - %u", interface.c_str(), (unsigned)state); for (const auto callback : _notificationCallbacks) { diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index aaa7118bd..2de707c54 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -351,7 +351,7 @@ namespace WPEFramework interfacesItr = Core::Service::Create(interfaceList); return rc; } - +#if 0 /* @brief Get the active Interface used for external world communication */ uint32_t NetworkManagerImplementation::GetPrimaryInterface (string& interface /* @out */) { @@ -420,7 +420,7 @@ namespace WPEFramework m_defaultInterface = interface; return rc; } - +#endif uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) { diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp index 979935377..eff361ac1 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp @@ -119,18 +119,9 @@ namespace WPEFramework return rc; } - +#if 0 uint32_t NetworkManagerImplementation::GetPrimaryInterface (string& interface /* @out */) { - - if(!m_wlanEnabled.load() && !m_ethEnabled.load()) - { - NMLOG_INFO("Both iface disabled state, returning no primary interface"); - interface.clear(); - m_defaultInterface = interface; - return Core::ERROR_NONE; - } - if(_nmGdbusClient->getPrimaryInterface(interface)) return Core::ERROR_NONE; else @@ -144,7 +135,7 @@ namespace WPEFramework return Core::ERROR_GENERAL; } } - +#endif uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) { uint32_t rc = Core::ERROR_GENERAL; diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 14e7697fc..01885969b 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -568,7 +568,7 @@ namespace WPEFramework return rc; } - +#if 0 /* @brief Get the active Interface used for external world communication */ uint32_t NetworkManagerImplementation::GetPrimaryInterface (string& interface /* @out */) { @@ -576,14 +576,6 @@ namespace WPEFramework uint32_t rc = Core::ERROR_RPC_CALL_FAILED; IARM_BUS_NetSrvMgr_DefaultRoute_t defaultRoute = {0}; - if(!m_wlanEnabled.load() && !m_ethEnabled.load()) - { - NMLOG_INFO("Both iface disabled state, returning no primary interface"); - interface.clear(); - m_defaultInterface = interface; - return Core::ERROR_NONE; - } - if (IARM_RESULT_SUCCESS == IARM_Bus_Call(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_getDefaultInterface, (void*)&defaultRoute, sizeof(defaultRoute))) { NMLOG_INFO ("Call to %s for %s returned interface = %s, gateway = %s", IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_getDefaultInterface, defaultRoute.interface, defaultRoute.gateway); @@ -596,7 +588,7 @@ namespace WPEFramework } return rc; } - +#endif uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enable /* @in */) { LOG_ENTRY_FUNCTION(); @@ -619,7 +611,7 @@ namespace WPEFramework iarmData.persist = true; if (IARM_RESULT_SUCCESS == IARM_Bus_Call (IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_setInterfaceEnabled, (void *)&iarmData, sizeof(iarmData))) { - NMLOG_INFO ("Call to %s for %s success", IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_setInterfaceEnabled);\ + NMLOG_INFO ("Call to %s for %s success", IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_setInterfaceEnabled); if(interface == "wlan0" && _instance != NULL) _instance->m_wlanEnabled.store(enable); else if(interface == "eth0" && _instance != NULL) diff --git a/tests/l2Test/libnm/l2_test_libnmproxy.cpp b/tests/l2Test/libnm/l2_test_libnmproxy.cpp index 1cf34774c..9cb4de3cd 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxy.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxy.cpp @@ -338,195 +338,15 @@ TEST_F(NetworkManagerTest, SetHostName_iface_wlan0) g_ptr_array_free(dummyConns, TRUE); } -TEST_F(NetworkManagerTest, GetPrimaryInterface_eth0) +TEST_F(NetworkManagerTest, GetPrimaryInterface_empty) { string interface{}; - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - - Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); - NetworkManagerImpl2->m_ethEnabled = true; - uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); - EXPECT_EQ(result, Core::ERROR_NONE); - - EXPECT_EQ(interface, "eth0"); -} - -TEST_F(NetworkManagerTest, GetPrimaryInterface_wlan0) -{ - string interface{}; - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNAVAILABLE)); - - Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); - NetworkManagerImpl2->m_wlanEnabled = true; - uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); - EXPECT_EQ(result, Core::ERROR_NONE); - - EXPECT_EQ(interface, "wlan0"); -} - -TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_null_eth0) -{ - NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - string interface{}; - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) - .WillOnce(::testing::Return(dummyActiveConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) - .WillOnce(::testing::Return(reinterpret_cast(NULL))); - - Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); - NetworkManagerImpl2->m_ethEnabled = true; - uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); - EXPECT_EQ(result, Core::ERROR_NONE); - EXPECT_EQ(interface, "eth0"); - - g_object_unref(dummyActiveConn); -} - -TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_null_wlan0) -{ - NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - string interface{}; - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(reinterpret_cast(0x100178))) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNAVAILABLE)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) - .WillOnce(::testing::Return(dummyActiveConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) - .WillOnce(::testing::Return(reinterpret_cast(NULL))); - - Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); - NetworkManagerImpl2->m_wlanEnabled = true; - uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); - EXPECT_EQ(result, Core::ERROR_NONE); - EXPECT_EQ(interface, "wlan0"); - g_object_unref(dummyActiveConn); -} - -TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_wlan0) -{ - NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - string interface{}; - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) - .WillOnce(::testing::Return(dummyActiveConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) - .WillOnce(::testing::Return(dummyRemoteConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) - .WillOnce(::testing::Return("wlan0")); - - Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); - NetworkManagerImpl2->m_wlanEnabled = true; - uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); - EXPECT_EQ(result, Core::ERROR_NONE); - EXPECT_EQ(interface, "wlan0"); - - g_object_unref(dummyActiveConn); - g_object_unref(dummyRemoteConn); -} - -TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_eth0) -{ - NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - string interface{}; - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) - .WillOnce(::testing::Return(dummyActiveConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) - .WillOnce(::testing::Return(dummyRemoteConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) - .WillOnce(::testing::Return("eth0")); - Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); - NetworkManagerImpl2->m_ethEnabled = true; + NetworkManagerImpl2->m_ethEnabled = false; + NetworkManagerImpl2->m_wlanEnabled = false; uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); EXPECT_EQ(result, Core::ERROR_NONE); - EXPECT_EQ(interface, "eth0"); - - g_object_unref(dummyActiveConn); - g_object_unref(dummyRemoteConn); -} - -TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_unknown) -{ - NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - string interface{}; - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) - .WillOnce(::testing::Return(dummyActiveConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) - .WillOnce(::testing::Return(dummyRemoteConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) - .WillOnce(::testing::Return("unknown")); - - Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); - NetworkManagerImpl2->m_ethEnabled = true; - uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); - EXPECT_EQ(result, Core::ERROR_NONE); - EXPECT_EQ(interface, "wlan0"); - - g_object_unref(dummyActiveConn); - g_object_unref(dummyRemoteConn); -} - -TEST_F(NetworkManagerTest, GetPrimaryInterface_ActiveConnection_iface_null) -{ - NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - string interface{}; - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) - .WillOnce(::testing::Return(dummyActiveConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) - .WillOnce(::testing::Return(dummyRemoteConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) - .WillOnce(::testing::Return(static_cast(NULL))); - - Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); - NetworkManagerImpl2->m_ethEnabled = true; - uint32_t result = NetworkManagerImpl2->GetPrimaryInterface(interface); - EXPECT_EQ(result, Core::ERROR_NONE); - EXPECT_EQ(interface, "wlan0"); - - g_object_unref(dummyActiveConn); - g_object_unref(dummyRemoteConn); + EXPECT_EQ(interface, ""); } TEST_F(NetworkManagerTest, GetInterfaceState_Failed) @@ -723,30 +543,9 @@ TEST_F(NetworkManagerTest, GetIPSettings_interface_Empty) TEST_F(NetworkManagerTest, GetIPSettings_GetPrimary_failed) { - NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - NMRemoteConnection *dummyRemoteConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))) - .WillOnce(::testing::Return(reinterpret_cast(0x100179))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_primary_connection(::testing::_)) - .WillOnce(::testing::Return(dummyActiveConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(dummyActiveConn)) - .WillOnce(::testing::Return(dummyRemoteConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_interface_name(dummyRemoteConn)) - .WillOnce(::testing::Return("unknown")); - Core::ProxyType NetworkManagerImpl2 = Core::ProxyType::Create(); - NetworkManagerImpl2->m_ethEnabled = true; - string interface; const string ipversion; Exchange::INetworkManager::IPAddress address; EXPECT_EQ(Core::ERROR_GENERAL, NetworkManagerImpl2->GetIPSettings(interface, ipversion, address)); - - g_object_unref(dummyActiveConn); - g_object_unref(dummyRemoteConn); } TEST_F(NetworkManagerTest, GetIPSettings_Invalid_ActiveConnection) diff --git a/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp b/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp index f7a3666bb..e47f24fbc 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp @@ -152,7 +152,7 @@ TEST_F(NetworkManagerInitTest, platformInit) EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); - EXPECT_EQ(response, _T("{\"success\":false}")); + EXPECT_EQ(response, _T("{\"interface\":\"\",\"success\":true}")); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), _T("{\"interface\":\"wlan0\"}"), response)); EXPECT_EQ(response, _T("{\"success\":false}")); diff --git a/tests/l2Test/rdk/l2_test_rdkproxy.cpp b/tests/l2Test/rdk/l2_test_rdkproxy.cpp index 03aecc534..a0845dbfc 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxy.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxy.cpp @@ -296,51 +296,8 @@ TEST_F(NetworkManagerTest, GetAvailableInterfaces_Failed) EXPECT_EQ(response, _T("{\"success\":false}")); } -TEST_F(NetworkManagerTest, GetPrimaryInterface) -{ - IARM_BUS_NetSrvMgr_DefaultRoute_t mockDefaultRoute = {}; - strcpy(mockDefaultRoute.interface, "eth0"); - strcpy(mockDefaultRoute.gateway, "192.168.1.1"); - - IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "eth0", .status = true }; - _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); - - EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), - ::testing::StrEq(IARM_BUS_NETSRVMGR_API_getDefaultInterface), - ::testing::NotNull(), sizeof(mockDefaultRoute))) - .WillOnce(::testing::DoAll( - ::testing::Invoke([&mockDefaultRoute](const char*, const char*, void* arg, size_t) { - memcpy(arg, &mockDefaultRoute, sizeof(mockDefaultRoute)); - return IARM_RESULT_SUCCESS; - }) - )); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); - EXPECT_EQ(response, _T("{\"interface\":\"eth0\",\"success\":true}")); -} - -TEST_F(NetworkManagerTest, GetPrimaryInterface_Failed) -{ - - EXPECT_CALL(*p_iarmBusImplMock, IARM_Bus_Call(::testing::StrEq(IARM_BUS_NM_SRV_MGR_NAME), - ::testing::StrEq(IARM_BUS_NETSRVMGR_API_getDefaultInterface), - ::testing::NotNull(), ::testing::_)) - .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); - - IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "eth0", .status = true }; - _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); - - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"success\":false}")); -} - TEST_F(NetworkManagerTest, GetPrimaryInterface_BothInterfacesDown) { - - IARM_BUS_NetSrvMgr_Iface_EventInterfaceConnectionStatus_t ifaceEventData = { .interface = "eth0", .status = true }; - _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &ifaceEventData, sizeof(ifaceEventData)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T("{}"), response)); EXPECT_EQ(response, _T("{\"interface\":\"\",\"success\":true}")); } diff --git a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp index 33da81c51..1b174a0bb 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp @@ -585,6 +585,9 @@ TEST_F(NetworkManagerEventTest, onInternetStatusChange_FULLY_CONNECTED) .acquired = true}; _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, &ipEventData, sizeof(ipEventData)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); + EXPECT_EQ(response, _T("{\"interface\":\"eth0\",\"success\":true}")); + EXPECT_EQ(Core::ERROR_NONE, onInternetStatusChange.Lock()); EVENT_UNSUBSCRIBE(2, _T("onInternetStatusChange"), _T("org.rdk.NetworkManager"), message); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Allow server to start @@ -608,6 +611,9 @@ TEST_F(NetworkManagerEventTest, GetPublicIP_SuccessWithEvent) .acquired = true}; _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_IPADDRESS, &ipEventData, sizeof(ipEventData)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); + EXPECT_EQ(response, _T("{\"interface\":\"wlan0\",\"success\":true}")); + // Test with both IPv4 and IPv6 EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPublicIP"), _T("{}"), response)); EXPECT_TRUE(response.find("\"ipaddress\"") != std::string::npos); From dead85eb29bb8ca79b5f725f51294959a8a1f9c8 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 24 Oct 2025 15:44:56 -0400 Subject: [PATCH 196/271] Release of 1.5.0 Release of 1.5.0 --- CHANGELOG.md | 6 ++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81f0f779e..5ba101687 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.5.0] - 2025-09-23 +### Changed +- Implemented L1/L2 and Part L3 for the plugin +- Implemented IP Address caching for Gnome backend +- Implemented a logic to return appropriate value for GetPrimaryInterface + ## [1.4.0] - 2025-09-23 ### Changed - Implemented logic to not to persist SSID when asked diff --git a/CMakeLists.txt b/CMakeLists.txt index dd6f1a417..02633a966 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 4) +set(VERSION_MINOR 5) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index ef06e267c..0ab9bc03e 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.4.0" + "version": "1.5.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index aeb550e32..439e467ee 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.4.0** +**Version: 1.5.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.4.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.5.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 6d2f27d45f259593ae3de6c6b50aee1f7d42e8c6 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 28 Oct 2025 11:16:49 -0400 Subject: [PATCH 197/271] RDKEMW-7889 - Observed NWMgrPlugin & WorkerPool::Thr crash (#234) * To address the crash happened in networkmanager plugin during the shutdown sequence Co-authored-by: Balaji Punnuru --- plugin/gnome/NetworkManagerGnomeEvents.cpp | 51 ++++++++++++++++++- plugin/gnome/NetworkManagerGnomeEvents.h | 1 + .../l2Test/libnm/l2_test_libnmproxyEvent.cpp | 6 +++ tests/mocks/GLibWraps.cpp | 37 ++++++++++++-- tests/mocks/GLibWraps.h | 6 +++ tests/mocks/GLibWrapsMock.h | 2 + tests/mocks/LibnmWraps.cpp | 18 +++++-- 7 files changed, 111 insertions(+), 10 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index c5e75b482..80197a689 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -475,6 +475,11 @@ namespace WPEFramework NMLOG_INFO("registered all networkmnager dbus events"); g_main_loop_run(nmEvents->loop); + // Clean up all signal handlers after thread has stopped + if(_nmEventInstance != nullptr) + { + _nmEventInstance->cleanupSignalHandlers(); + } //g_main_loop_unref(nmEvents->loop); return nullptr; } @@ -497,23 +502,65 @@ namespace WPEFramework void GnomeNetworkManagerEvents::stopNetworkMangerEventMonitor() { // g_signal_handlers_disconnect_by_func(client, G_CALLBACK(primaryConnectionCb), NULL); + if (!isEventThrdActive) { + return; + } if (nmEvents.loop != NULL) { g_main_loop_quit(nmEvents.loop); } + if (eventThrdID) { g_thread_join(eventThrdID); // Wait for the thread to finish eventThrdID = NULL; // Reset the thread ID - NMLOG_WARNING("gnome event monitor stoped"); + NMLOG_WARNING("gnome event monitor stopped"); } isEventThrdActive = false; + + } + + void GnomeNetworkManagerEvents::cleanupSignalHandlers() + { + if(nmEvents.client == nullptr) { + return; // Already cleaned up + } + + NMLOG_DEBUG("Cleaning up signal handlers"); + + // Disconnect all client signals + g_signal_handlers_disconnect_by_data(nmEvents.client, &nmEvents); + + // Clean up device signals + const GPtrArray *devices = nm_client_get_devices(nmEvents.client); + if (devices) { + for (guint i = 0; i < devices->len; i++) { + NMDevice *device = NM_DEVICE(g_ptr_array_index(devices, i)); + if (device && NM_IS_DEVICE(device)) { + g_signal_handlers_disconnect_by_data(device, &nmEvents); + + // Clean up IP config signals + NMIPConfig *ipv4Config = nm_device_get_ip4_config(device); + NMIPConfig *ipv6Config = nm_device_get_ip6_config(device); + if (ipv4Config) { + g_signal_handlers_disconnect_by_func(ipv4Config, (gpointer)ip4ChangedCb, device); + } + if (ipv6Config) { + g_signal_handlers_disconnect_by_func(ipv6Config, (gpointer)ip6ChangedCb, device); + } + } + } + } + + NMLOG_DEBUG("Signal handlers cleanup complete"); } GnomeNetworkManagerEvents::~GnomeNetworkManagerEvents() { NMLOG_INFO("~GnomeNetworkManagerEvents"); stopNetworkMangerEventMonitor(); - if(nmEvents.client != nullptr) + if(nmEvents.client != nullptr) { g_object_unref(nmEvents.client); + nmEvents.client = nullptr; + } if (nmEvents.loop != NULL) { g_main_loop_unref(nmEvents.loop); nmEvents.loop = NULL; diff --git a/plugin/gnome/NetworkManagerGnomeEvents.h b/plugin/gnome/NetworkManagerGnomeEvents.h index 64a8aef32..ee29ce6d2 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.h +++ b/plugin/gnome/NetworkManagerGnomeEvents.h @@ -59,6 +59,7 @@ namespace WPEFramework private: static void* networkMangerEventMonitor(void *arg); static bool apToJsonObject(NMAccessPoint *ap, JsonObject& ssidObj); + void cleanupSignalHandlers(); GnomeNetworkManagerEvents(); ~GnomeNetworkManagerEvents(); std::atomicisEventThrdActive = {false}; diff --git a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp index 5b34d2bdf..2a83d1686 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp @@ -113,6 +113,12 @@ class NetworkManagerEventTest : public ::testing::Test { return 0; })); + EXPECT_CALL(*p_gLibWrapsImplMock, signal_handlers_disconnect_by_data(::testing::_, ::testing::_)) + .WillRepeatedly(::testing::Return(0)); + + EXPECT_CALL(*p_gLibWrapsImplMock, signal_handlers_disconnect_by_func(::testing::_, ::testing::_, ::testing::_)) + .WillRepeatedly(::testing::Return(0)); + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_)) .WillByDefault(::testing::Invoke( [&](const RPC::Object& object, const uint32_t waitTime, uint32_t& connectionId) { diff --git a/tests/mocks/GLibWraps.cpp b/tests/mocks/GLibWraps.cpp index 0427f8111..332c0a886 100644 --- a/tests/mocks/GLibWraps.cpp +++ b/tests/mocks/GLibWraps.cpp @@ -6,10 +6,18 @@ extern "C" gboolean __wrap_g_main_loop_is_running(GMainLoop* loop) { return GLibWraps::getInstance().g_main_loop_is_running(loop); } - extern "C" gulong __wrap_g_signal_connect_data(gpointer instance, const gchar *detailed_signal, GCallback c_handler, - gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags){ - return GLibWraps::getInstance().g_signal_connect_data(instance, detailed_signal, c_handler, data, destroy_data, connect_flags); - } +extern "C" gulong __wrap_g_signal_connect_data(gpointer instance, const gchar *detailed_signal, GCallback c_handler, + gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags){ + return GLibWraps::getInstance().g_signal_connect_data(instance, detailed_signal, c_handler, data, destroy_data, connect_flags); +} + +extern "C" guint __wrap_g_signal_handlers_disconnect_by_data(gpointer instance, gpointer data) { + return GLibWraps::getInstance().signal_handlers_disconnect_by_data(instance, data); +} + +extern "C" guint __wrap_g_signal_handlers_disconnect_by_func(gpointer instance, gpointer func, gpointer data) { + return GLibWraps::getInstance().signal_handlers_disconnect_by_func(instance, func, data); +} GLibWrapsImpl* GLibWraps::impl = nullptr; GLibWraps::GLibWraps() {} @@ -25,7 +33,10 @@ GLibWraps& GLibWraps::getInstance() { } gboolean GLibWraps::g_main_loop_is_running(GMainLoop* loop) { - EXPECT_NE(impl, nullptr); + if (impl == nullptr) { + // During cleanup, impl may be nullptr, so call the actual GLib macro directly + return g_main_loop_is_running(loop); + } return impl->g_main_loop_is_running(loop); } @@ -34,3 +45,19 @@ gulong GLibWraps::g_signal_connect_data(gpointer instance, const gchar *detailed EXPECT_NE(impl, nullptr); return impl->g_signal_connect_data(instance, detailed_signal, c_handler, data, destroy_data, connect_flags); } + +guint GLibWraps::signal_handlers_disconnect_by_data(gpointer instance, gpointer data) { + if (impl == nullptr) { + // During cleanup, impl may be nullptr, so call the actual GLib macro directly + return g_signal_handlers_disconnect_by_data(instance, data); + } + return impl->signal_handlers_disconnect_by_data(instance, data); +} + +guint GLibWraps::signal_handlers_disconnect_by_func(gpointer instance, gpointer func, gpointer data) { + if (impl == nullptr) { + // During cleanup, impl may be nullptr, so call the actual GLib macro directly + return g_signal_handlers_disconnect_by_func(instance, func, data); + } + return impl->signal_handlers_disconnect_by_func(instance, func, data); +} diff --git a/tests/mocks/GLibWraps.h b/tests/mocks/GLibWraps.h index c2465e47f..cf59617c5 100644 --- a/tests/mocks/GLibWraps.h +++ b/tests/mocks/GLibWraps.h @@ -11,6 +11,8 @@ class GLibWrapsImpl { virtual gboolean g_main_loop_is_running(GMainLoop* loop) = 0; virtual gulong g_signal_connect_data(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags) = 0; + virtual guint signal_handlers_disconnect_by_data(gpointer instance, gpointer data) = 0; + virtual guint signal_handlers_disconnect_by_func(gpointer instance, gpointer func, gpointer data) = 0; }; class GLibWraps { @@ -26,9 +28,13 @@ class GLibWraps { static gboolean g_main_loop_is_running(GMainLoop* loop); static gulong g_signal_connect_data(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags) __attribute__((visibility("default"))); + static guint signal_handlers_disconnect_by_data(gpointer instance, gpointer data) __attribute__((visibility("default"))); + static guint signal_handlers_disconnect_by_func(gpointer instance, gpointer func, gpointer data) __attribute__((visibility("default"))); }; extern "C" { gulong __wrap_g_signal_connect_data(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags) __attribute__((visibility("default"))); + guint __wrap_g_signal_handlers_disconnect_by_data(gpointer instance, gpointer data) __attribute__((visibility("default"))); + guint __wrap_g_signal_handlers_disconnect_by_func(gpointer instance, gpointer func, gpointer data) __attribute__((visibility("default"))); } diff --git a/tests/mocks/GLibWrapsMock.h b/tests/mocks/GLibWrapsMock.h index 872deb773..f1912cf97 100644 --- a/tests/mocks/GLibWrapsMock.h +++ b/tests/mocks/GLibWrapsMock.h @@ -30,4 +30,6 @@ class GLibWrapsImplMock : public GLibWrapsImpl { MOCK_METHOD(gboolean, g_main_loop_is_running, (GMainLoop* loop), (override)); MOCK_METHOD(gulong, g_signal_connect_data, (gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags), (override)); + MOCK_METHOD(guint, signal_handlers_disconnect_by_data, (gpointer instance, gpointer data), (override)); + MOCK_METHOD(guint, signal_handlers_disconnect_by_func, (gpointer instance, gpointer func, gpointer data), (override)); }; diff --git a/tests/mocks/LibnmWraps.cpp b/tests/mocks/LibnmWraps.cpp index ecb7c416a..0a5741fbb 100644 --- a/tests/mocks/LibnmWraps.cpp +++ b/tests/mocks/LibnmWraps.cpp @@ -2,6 +2,10 @@ #include #include +extern "C" const GPtrArray* __real_nm_client_get_devices(NMClient* client); + +extern "C" NMClient* __real_nm_client_new(GCancellable* cancellable, GError** error); + extern "C" gint64 __wrap_nm_device_wifi_get_last_scan(NMDeviceWifi *device) { return LibnmWraps::getInstance().nm_device_wifi_get_last_scan(device); } @@ -359,7 +363,9 @@ const char* LibnmWraps::nm_connection_get_interface_name(NMRemoteConnection *con } NMDevice* LibnmWraps::nm_client_get_device_by_iface(NMClient *client, const char *iface) { - EXPECT_NE(impl, nullptr); + if (impl == nullptr) { + nm_client_get_device_by_iface(client, iface); + } return impl->nm_client_get_device_by_iface(client, iface); } @@ -379,7 +385,10 @@ gboolean LibnmWraps::nm_device_disconnect_finish(NMDevice *device, GAsyncResult } const GPtrArray* LibnmWraps::nm_client_get_devices(NMClient* client) { - EXPECT_NE(impl, nullptr); + if (impl == nullptr) { + // During cleanup, impl may be nullptr, so call the real function directly + return __real_nm_client_get_devices(client); + } return impl->nm_client_get_devices(client); } @@ -389,7 +398,10 @@ const GPtrArray* LibnmWraps::nm_client_get_active_connections(NMClient* client) } NMClient* LibnmWraps::nm_client_new(GCancellable* cancellable, GError** error) { - EXPECT_NE(impl, nullptr); + if (impl == nullptr) { + // During cleanup, impl may be nullptr, so call the real function directly + return __real_nm_client_new(cancellable, error); + } return impl->nm_client_new(cancellable, error); } From c98ab7709654b918d058a390ba202d194d321588 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 29 Oct 2025 11:21:31 -0400 Subject: [PATCH 198/271] RDK-59357 - Port libnm Bug Fixes and Improvements to gdbus (#240) * Initial changes for libnm to gdbus * Initial changes for libnm to gdbus --------- Co-authored-by: Balaji Punnuru --- plugin/NetworkManagerImplementation.h | 3 +- .../gnome/gdbus/NetworkManagerGdbusClient.cpp | 1178 ++++++++++++++++- .../gnome/gdbus/NetworkManagerGdbusClient.h | 8 + .../gnome/gdbus/NetworkManagerGdbusEvent.cpp | 37 +- .../gnome/gdbus/NetworkManagerGdbusProxy.cpp | 63 +- .../gnome/gdbus/NetworkManagerGdbusUtils.cpp | 67 +- plugin/gnome/gdbus/NetworkManagerGdbusUtils.h | 2 + 7 files changed, 1283 insertions(+), 75 deletions(-) diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 87d2fb3cd..7c798e291 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -306,12 +306,11 @@ namespace WPEFramework std::atomic m_stopThread{false}; std::mutex m_condVariableMutex; std::condition_variable m_condVariable; + public: IPAddress m_ethIPv4Address; IPAddress m_wlanIPv4Address; IPAddress m_ethIPv6Address; IPAddress m_wlanIPv6Address; - - public: std::atomic m_ethConnected; std::atomic m_wlanConnected; std::atomic m_ethEnabled; diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp index 233611d81..e08f27079 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp @@ -27,6 +27,7 @@ #include "NetworkManagerLogger.h" #include "NetworkManagerGdbusClient.h" #include "NetworkManagerGdbusUtils.h" +#include "../NetworkManagerGnomeUtils.h" namespace WPEFramework { @@ -35,6 +36,8 @@ namespace WPEFramework extern NetworkManagerImplementation* _instance; NetworkManagerClient::NetworkManagerClient() { NMLOG_INFO("NetworkManagerClient"); + m_wpsProcessRun = false; + m_wpsActionTriggered = false; } NetworkManagerClient::~NetworkManagerClient() { @@ -429,6 +432,183 @@ namespace WPEFramework return true; } + bool updateHostnameSettings(DbusMgr& m_dbus, const std::string& connectionPath, const std::string& hostname, const std::string& interface) + { + GError *error = nullptr; + deviceInfo devInfo{}; + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, interface.c_str(), devInfo)) + return false; + + GDBusProxy *settingsProxy = m_dbus.getNetworkManagerSettingsConnectionProxy(connectionPath.c_str()); + if (settingsProxy == nullptr) { + NMLOG_ERROR("Error creating connection settings proxy"); + return false; + } + + GVariant *connectionSettings = g_dbus_proxy_call_sync( + settingsProxy, + "GetSettings", + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (connectionSettings == nullptr) { + NMLOG_ERROR("Error retrieving connection settings: %s", error->message); + g_error_free(error); + g_object_unref(settingsProxy); + return false; + } + + GVariantIter *iterator; + GVariant *settingsDict; + const gchar *settingsKey; + const gchar *existingId = nullptr; + const gchar *existingType = nullptr; + const gchar *existingInterfaceName = nullptr; + const gchar *existingKeyMgmt = nullptr; + const gchar *existingSSID = nullptr; + GVariant *existingIPv4Settings = nullptr; + GVariant *existingIPv6Settings = nullptr; + + g_variant_get(connectionSettings, "(a{sa{sv}})", &iterator); + while (g_variant_iter_loop(iterator, "{&s@a{sv}}", &settingsKey, &settingsDict)) { + GVariantIter settingsIter; + const gchar *key; + GVariant *value; + + g_variant_iter_init(&settingsIter, settingsDict); + while (g_variant_iter_loop(&settingsIter, "{&sv}", &key, &value)) { + if (g_strcmp0(key, "id") == 0) { + existingId = g_variant_get_string(value, NULL); + } else if (g_strcmp0(key, "type") == 0) { + existingType = g_variant_get_string(value, NULL); + } else if (g_strcmp0(key, "interface-name") == 0) { + existingInterfaceName = g_variant_get_string(value, NULL); + } else if (g_strcmp0(key, "ssid") == 0) { + gsize size; + const guint8 *ssid = (const guint8 *) g_variant_get_fixed_array(value, &size, sizeof(guint8)); + existingSSID = g_strndup((const gchar *)ssid, size); + } else if (g_strcmp0(key, "key-mgmt") == 0) { + existingKeyMgmt = g_variant_get_string(value, NULL); + } else if (g_strcmp0(settingsKey, "ipv4") == 0) { + existingIPv4Settings = g_variant_ref(settingsDict); + } else if (g_strcmp0(settingsKey, "ipv6") == 0) { + existingIPv6Settings = g_variant_ref(settingsDict); + } + } + } + g_variant_iter_free(iterator); + + GVariantBuilder connectionBuilder; + GVariantBuilder wifiBuilder; + GVariantBuilder settingsBuilder; + GVariantBuilder wifiSecurityBuilder; + g_variant_builder_init(&settingsBuilder, G_VARIANT_TYPE("a{sa{sv}}")); + + // Define the 'connection' dictionary with connection details + g_variant_builder_init(&connectionBuilder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&connectionBuilder, "{sv}", "id", g_variant_new_string(existingId)); + g_variant_builder_add(&connectionBuilder, "{sv}", "type", g_variant_new_string(existingType)); + g_variant_builder_add(&connectionBuilder, "{sv}", "interface-name", g_variant_new_string(existingInterfaceName)); + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "connection", &connectionBuilder); + + if (g_strcmp0(interface.c_str(), GnomeUtils::getWifiIfname()) == 0) { + // Define the '802-11-wireless' dictionary with Wi-Fi specific details + g_variant_builder_init(&wifiBuilder, G_VARIANT_TYPE("a{sv}")); + GVariantBuilder ssidBuilder; + g_variant_builder_init(&ssidBuilder, G_VARIANT_TYPE("ay")); + while (*existingSSID) { + g_variant_builder_add(&ssidBuilder, "y", *(existingSSID++)); + } + g_variant_builder_add(&wifiBuilder, "{sv}", "ssid", g_variant_builder_end(&ssidBuilder)); + g_variant_builder_add(&wifiBuilder, "{sv}", "mode", g_variant_new_string("infrastructure")); + g_variant_builder_add(&wifiBuilder, "{sv}", "security", g_variant_new_string("802-11-wireless-security")); + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "802-11-wireless", &wifiBuilder); + + // Define the '802-11-wireless-security' dictionary with security details + g_variant_builder_init(&wifiSecurityBuilder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&wifiSecurityBuilder, "{sv}", "key-mgmt", g_variant_new_string(existingKeyMgmt)); + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "802-11-wireless-security", &wifiSecurityBuilder); + } + + GVariantBuilder ipv4Builder; + g_variant_builder_init(&ipv4Builder, G_VARIANT_TYPE("a{sv}")); + GVariantBuilder ipv6Builder; + g_variant_builder_init(&ipv6Builder, G_VARIANT_TYPE("a{sv}")); + + // Add existing IPv4 settings and set hostname + if (existingIPv4Settings) + { + GVariantIter iter; + const gchar *key; + GVariant *value; + g_variant_iter_init(&iter, existingIPv4Settings); + while (g_variant_iter_loop(&iter, "{&sv}", &key, &value)) { + // Skip existing hostname properties to avoid duplicates + if (g_strcmp0(key, "dhcp-hostname") != 0 && g_strcmp0(key, "dhcp-send-hostname") != 0) { + g_variant_builder_add(&ipv4Builder, "{sv}", key, value); + } + } + } + // Now add the new hostname settings + g_variant_builder_add(&ipv4Builder, "{sv}", "dhcp-hostname", g_variant_new_string(hostname.c_str())); + g_variant_builder_add(&ipv4Builder, "{sv}", "dhcp-send-hostname", g_variant_new_boolean(TRUE)); + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "ipv4", &ipv4Builder); + + // Add existing IPv6 settings, excluding hostname-related properties + if (existingIPv6Settings) { + GVariantIter iter; + const gchar *key; + GVariant *value; + g_variant_iter_init(&iter, existingIPv6Settings); + while (g_variant_iter_loop(&iter, "{&sv}", &key, &value)) { + // Skip existing hostname properties to avoid duplicates + if (g_strcmp0(key, "dhcp-hostname") != 0 && g_strcmp0(key, "dhcp-send-hostname") != 0) { + g_variant_builder_add(&ipv6Builder, "{sv}", key, value); + } + } + } + // Now add the new hostname settings + g_variant_builder_add(&ipv6Builder, "{sv}", "dhcp-hostname", g_variant_new_string(hostname.c_str())); + g_variant_builder_add(&ipv6Builder, "{sv}", "dhcp-send-hostname", g_variant_new_boolean(TRUE)); + g_variant_builder_add(&settingsBuilder, "{sa{sv}}", "ipv6", &ipv6Builder); + + g_dbus_proxy_call_sync( + settingsProxy, + "Update", + g_variant_new("(a{sa{sv}})", &settingsBuilder), + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (error) { + NMLOG_ERROR("Error updating connection settings with hostname: %s", error->message); + g_error_free(error); + g_variant_unref(connectionSettings); + g_object_unref(settingsProxy); + return false; + } + + NMLOG_DEBUG("Successfully updated hostname settings for %s interface to: %s", interface.c_str(), hostname.c_str()); + + // Activate connection to apply changes + if(!GnomeUtils::activateConnection(m_dbus, connectionPath, devInfo.path)) + { + NMLOG_INFO("activateConnection not successful"); + } + else + NMLOG_INFO("activateConnection successful"); + + if (existingIPv4Settings) g_variant_unref(existingIPv4Settings); + if (existingIPv6Settings) g_variant_unref(existingIPv6Settings); + g_variant_unref(connectionSettings); + g_object_unref(settingsProxy); + return true; + } + bool NetworkManagerClient::getAvailableInterfaces(std::vector& interfacesList) { deviceInfo ethDevInfo{}; @@ -674,12 +854,94 @@ namespace WPEFramework { deviceInfo devInfo{}; GError* error = nullptr; + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, interface.c_str(), devInfo)) return false; GDBusProxy* deviceProxy = m_dbus.getNetworkManagerPropertyProxy(devInfo.path.c_str()); if(deviceProxy == NULL) return false; + NMLOG_INFO("interface %s state: %s", interface.c_str(), enable ? "enabled" : "disabled"); + + NMDeviceState deviceState = devInfo.state; + + if (enable) { + NMLOG_DEBUG("Enabling interface..."); + if (deviceState >= NM_DEVICE_STATE_UNAVAILABLE && devInfo.managed) // already enabled and managed + { + return true; + } + } else { + NMLOG_DEBUG("Disabling interface..."); + if (deviceState < NM_DEVICE_STATE_UNAVAILABLE && !devInfo.managed) // already disabled and unmanaged + { + return true; + } + else if (deviceState > NM_DEVICE_STATE_DISCONNECTED) { + NMLOG_DEBUG("Disconnecting device..."); + // Disconnect the device before setting it to unmanaged. + // This ensures that NetworkManager cleanly removes any IP addresses, routes, + // and DNS configuration associated with the interface. Setting an interface + // to unmanaged without disconnecting first may leave residual configuration + // that can cause networking issues. + GDBusProxy* deviceProxy = m_dbus.getNetworkManagerDeviceProxy(devInfo.path.c_str()); + if(deviceProxy != NULL) { + GVariant* disconnectResult = g_dbus_proxy_call_sync( + deviceProxy, + "Disconnect", + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error + ); + + if (error) { + NMLOG_WARNING("Error disconnecting device: %s", error->message); + g_error_free(error); + error = nullptr; + } else if (disconnectResult) { + g_variant_unref(disconnectResult); + } + g_object_unref(deviceProxy); + } + + // Wait until device is truly disconnected + int retry = 24; // 12 seconds + NMDeviceState oldDevState = NM_DEVICE_STATE_UNKNOWN; + while (retry-- > 0) { + /* Force glib event processing to update state + * This below line will create an uncertain time wait. We are taking a fixed time interval of 12 seconds. + */ + // while (g_main_context_iteration(NULL, FALSE)); + + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, interface.c_str(), devInfo)) { + break; + } + deviceState = devInfo.state; + if(oldDevState != deviceState) + { + oldDevState = deviceState; + NMLOG_WARNING("Device state: %d", deviceState); + } + + if (deviceState <= NM_DEVICE_STATE_DISCONNECTED) + break; + + g_usleep(500 * 1000); // 500ms (much faster response) + } + } + } + + if(deviceState > NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_WARNING("Device not fully disconnected (state: %d), setting to unmanaged state", deviceState); + } + + // Set the "Managed" property to enable/disable the device + /*GDBusProxy* propertyProxy = m_dbus.getNetworkManagerPropertyProxy(devInfo.path.c_str()); + if(propertyProxy == NULL) + return false;*/ GVariant* result = g_dbus_proxy_call_sync( deviceProxy, @@ -691,17 +953,44 @@ namespace WPEFramework &error ); + bool success = (error == nullptr); + if (error) { NMLOG_ERROR("Error %s network interface: %s", (enable ? "enabling" : "disabling"), error->message); g_error_free(error); } else { - NMLOG_DEBUG("Network interface %s successfully %s", (enable ? "enabled" : "disabled"), devInfo.path.c_str()); + NMLOG_DEBUG("Network interface %s successfully %s", interface.c_str(), (enable ? "enabled" : "disabled")); if (result != nullptr) { g_variant_unref(result); } } g_object_unref(deviceProxy); - return true; + + if(success) + { + // Set persistent marker file for specific interface + if(interface == GnomeUtils::getEthIfname()) + nmUtils::setMarkerFile(EthernetDisableMarker, enable); + else if(interface == GnomeUtils::getWifiIfname()) + nmUtils::setMarkerFile(WiFiDisableMarker, enable); + + // Auto-reconnection logic when interface is enabled + if(enable) { + // Wait for 1 sec to change the device state + sleep(1); + if(interface == GnomeUtils::getWifiIfname() && _instance != nullptr) { + NMLOG_INFO("Activating connection '%s' ...", _instance->m_lastConnectedSSID.c_str()); + activateKnownConnection(GnomeUtils::getWifiIfname(), _instance->m_lastConnectedSSID); + } + else if(interface == GnomeUtils::getEthIfname()) { + NMLOG_INFO("Activating connection 'Wired connection 1' ..."); + // default wired connection name is 'Wired connection 1' + activateKnownConnection(GnomeUtils::getEthIfname(), "Wired connection 1"); + } + } + } + + return success; } bool NetworkManagerClient::getInterfaceState(const std::string& interface, bool& isEnabled) @@ -748,14 +1037,21 @@ namespace WPEFramework bool NetworkManagerClient::setIPSettings(const std::string& interface, const Exchange::INetworkManager::IPAddress& address) { std::string connectionPath; + + if(interface.empty() || (interface != GnomeUtils::getEthIfname() && interface != GnomeUtils::getWifiIfname())) + { + NMLOG_ERROR("Invalid interface name: %s", interface.c_str()); + return false; + } + if (!GnomeUtils::getSettingsConnectionPath(m_dbus, connectionPath, interface)) { NMLOG_ERROR("Error: connection path not found for interface %s", interface.c_str()); return false; } if (connectionPath.empty()) { - NMLOG_ERROR("Error: Interface %s not found in active connections", interface.c_str()); - return false; + NMLOG_WARNING("No active connections available to edit for interface %s", interface.c_str()); + return true; } if(!updateIPSettings(m_dbus, connectionPath, address, interface)) { @@ -785,6 +1081,7 @@ namespace WPEFramework const gchar *IPv6Method = nullptr; deviceInfo devInfo{}; GError *error = nullptr; + string ipversionStr; std::string wifiname = GnomeUtils::getWifiIfname(), ethname = GnomeUtils::getEthIfname(); @@ -803,10 +1100,51 @@ namespace WPEFramework } else if(wifiname != interface && ethname != interface) { - NMLOG_ERROR("interface: %s; not valied", interface.c_str()); + NMLOG_ERROR("interface: %s; not valid", interface.c_str()); return false; } + if(ipversion.empty()) + { + ipversionStr = "IPV4"; + } + else + { + ipversionStr = ipversion; + } + + // Add caching optimization similar to RDK proxy + if (wifiname == interface) + { + if(nmUtils::caseInsensitiveCompare(ipversionStr, "IPV4") && !_instance->m_wlanIPv4Address.ipaddress.empty()) + { + NMLOG_DEBUG("%s IPv4 address from cache", wifiname.c_str()); + result = _instance->m_wlanIPv4Address; + return true; + } + else if(nmUtils::caseInsensitiveCompare(ipversionStr, "IPV6") && !_instance->m_wlanIPv6Address.ipaddress.empty()) + { + NMLOG_DEBUG("%s IPv6 address from cache", wifiname.c_str()); + result = _instance->m_wlanIPv6Address; + return true; + } + } + else if (ethname == interface) + { + if(nmUtils::caseInsensitiveCompare(ipversionStr, "IPV4") && !_instance->m_ethIPv4Address.ipaddress.empty()) + { + NMLOG_DEBUG("%s IPv4 address from cache", ethname.c_str()); + result = _instance->m_ethIPv4Address; + return true; + } + else if(nmUtils::caseInsensitiveCompare(ipversionStr, "IPV6") && !_instance->m_ethIPv6Address.ipaddress.empty()) + { + NMLOG_DEBUG("%s IPv6 address from cache", ethname.c_str()); + result = _instance->m_ethIPv6Address; + return true; + } + } + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, interface.c_str(), devInfo)) { return false; @@ -1212,6 +1550,26 @@ namespace WPEFramework result.primarydns = ""; result.secondarydns = ""; } + + // Cache the IP address + if(!result.ipaddress.empty()) + { + if(g_strcmp0(result.ipversion.c_str(), "IPv4") == 0) + { + if(ethname == interface) + _instance->m_ethIPv4Address = result; + else if(wifiname == interface) + _instance->m_wlanIPv4Address = result; + } + else if(g_strcmp0(result.ipversion.c_str(), "IPv6") == 0) + { + if(ethname == interface) + _instance->m_ethIPv6Address = result; + else if(wifiname == interface) + _instance->m_wlanIPv6Address = result; + } + } + if(ipv4Proxy != NULL) g_object_unref(ipv4Proxy); if(ipv6Proxy != NULL) @@ -1546,43 +1904,112 @@ namespace WPEFramework return true; } - bool updateConnctionAndactivate(DbusMgr& m_dbus, GVariantBuilder& connBuilder, const char* devicePath, const char* connPath) + bool NetworkManagerClient::isWifiScannedRecently(int timelimitInSec) { - GDBusProxy* proxy = nullptr; - GError* error = nullptr; - GVariant* result = nullptr; - - proxy = m_dbus.getNetworkManagerSettingsConnectionProxy(connPath); - if(proxy == NULL) + deviceInfo devInfo; + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), devInfo)) + { + NMLOG_ERROR("Failed to get WiFi device info"); return false; + } - result = g_dbus_proxy_call_sync (proxy, "Update", - g_variant_new("(a{sa{sv}})", connBuilder), - G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); - - if (error) { - NMLOG_ERROR("Failed to call Update : %s", error->message); - g_clear_error(&error); - g_object_unref(proxy); + if(devInfo.path.empty() || devInfo.state < NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_ERROR("WiFi device not available for scan check"); return false; } - if(result) - g_variant_unref(result); - g_object_unref(proxy); - - proxy = m_dbus.getNetworkManagerProxy(); - if(proxy == NULL) + GDBusProxy* wProxy = m_dbus.getNetworkManagerWirelessProxy(devInfo.path.c_str()); + if(wProxy == NULL) + { + NMLOG_ERROR("Failed to create wireless proxy for scan check"); return false; + } - if (error) { - NMLOG_ERROR( "Failed to create proxy: %s", error->message); - g_clear_error(&error); + // Get LastScan property + GVariant* timeVariant = g_dbus_proxy_get_cached_property(wProxy, "LastScan"); + if (!timeVariant) { + NMLOG_ERROR("Failed to get LastScan property"); + g_object_unref(wProxy); return false; } - const char* specificObject = "/"; - result = g_dbus_proxy_call_sync (proxy, "ActivateConnection", + if (!g_variant_is_of_type(timeVariant, G_VARIANT_TYPE_INT64)) { + NMLOG_ERROR("Unexpected LastScan variant type: %s", g_variant_get_type_string(timeVariant)); + g_variant_unref(timeVariant); + g_object_unref(wProxy); + return false; + } + + gint64 last_scan_time = g_variant_get_int64(timeVariant); + g_variant_unref(timeVariant); + g_object_unref(wProxy); + + if (last_scan_time <= 0) { + NMLOG_INFO("No scan has been performed yet"); + return false; + } + + // Get current time in milliseconds + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + gint64 current_time_in_msec = (gint64)ts.tv_sec * 1000 + (gint64)ts.tv_nsec / 1000000; + + gint64 time_difference_in_seconds = (current_time_in_msec - last_scan_time) / 1000; + + NMLOG_DEBUG("Last scan: %lld ms ago, limit: %d sec", (long long)time_difference_in_seconds, timelimitInSec); + + if (time_difference_in_seconds <= timelimitInSec) { + NMLOG_DEBUG("WiFi was scanned recently (%lld seconds ago), skipping scan", (long long)time_difference_in_seconds); + return true; + } + + NMLOG_DEBUG("WiFi scan is needed, last scan was %lld seconds ago", (long long)time_difference_in_seconds); + return false; + } + + bool NetworkManagerClient::getDeviceInfo(const std::string& interface, deviceInfo& devInfo) + { + return GnomeUtils::getDeviceInfoByIfname(m_dbus, interface.c_str(), devInfo); + } + + bool updateConnctionAndactivate(DbusMgr& m_dbus, GVariantBuilder& connBuilder, const char* devicePath, const char* connPath) + { + GDBusProxy* proxy = nullptr; + GError* error = nullptr; + GVariant* result = nullptr; + + proxy = m_dbus.getNetworkManagerSettingsConnectionProxy(connPath); + if(proxy == NULL) + return false; + + result = g_dbus_proxy_call_sync (proxy, "Update", + g_variant_new("(a{sa{sv}})", connBuilder), + G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); + + if (error) { + NMLOG_ERROR("Failed to call Update : %s", error->message); + g_clear_error(&error); + g_object_unref(proxy); + return false; + } + + if(result) + g_variant_unref(result); + g_object_unref(proxy); + + proxy = m_dbus.getNetworkManagerProxy(); + if(proxy == NULL) + return false; + + if (error) { + NMLOG_ERROR( "Failed to create proxy: %s", error->message); + g_clear_error(&error); + return false; + } + const char* specificObject = "/"; + + result = g_dbus_proxy_call_sync (proxy, "ActivateConnection", g_variant_new("(ooo)", connPath, devicePath, specificObject), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); @@ -1728,7 +2155,8 @@ namespace WPEFramework GVariant *ssidArray = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (const guint8 *)ssidinfo.ssid.c_str(), ssidinfo.ssid.length(), 1); g_variant_builder_add (&settingsBuilder, "{sv}", "ssid", ssidArray); g_variant_builder_add (&settingsBuilder, "{sv}", "mode", g_variant_new_string("infrastructure")); - g_variant_builder_add (&settingsBuilder, "{sv}", "hidden", g_variant_new_boolean(true)); // set hidden: yes + if(!iswpsAP) // wps never be a hidden AP, it will be always visible + g_variant_builder_add (&settingsBuilder, "{sv}", "hidden", g_variant_new_boolean(true)); // set hidden: yes g_variant_builder_add (&connBuilder, "{sa{sv}}", "802-11-wireless", &settingsBuilder); /* Adding '802-11-wireless-security' settings */ @@ -1783,14 +2211,28 @@ namespace WPEFramework } g_variant_builder_add (&connBuilder, "{sa{sv}}", "802-11-wireless-security", &settingsBuilder); + + // Get persistent hostname or fall back to device hostname + std::string hostname; + if (!GnomeUtils::readPersistentHostname(hostname)) { + const char* deviceHostname = "rdk-device"; // default hostname + hostname = deviceHostname; + NMLOG_DEBUG("No persistent hostname found, using device hostname: %s", hostname.c_str()); + } + NMLOG_INFO("DHCP hostname: %s", hostname.c_str()); + /* Adding the 'ipv4' Setting */ g_variant_builder_init (&settingsBuilder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&settingsBuilder, "{sv}", "method", g_variant_new_string ("auto")); + g_variant_builder_add (&settingsBuilder, "{sv}", "dhcp-hostname", g_variant_new_string(hostname.c_str())); + g_variant_builder_add (&settingsBuilder, "{sv}", "dhcp-send-hostname", g_variant_new_boolean(TRUE)); g_variant_builder_add (&connBuilder, "{sa{sv}}", "ipv4", &settingsBuilder); /* Adding the 'ipv6' Setting */ g_variant_builder_init (&settingsBuilder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&settingsBuilder, "{sv}", "method", g_variant_new_string ("auto")); + g_variant_builder_add (&settingsBuilder, "{sv}", "dhcp-hostname", g_variant_new_string(hostname.c_str())); + g_variant_builder_add (&settingsBuilder, "{sv}", "dhcp-send-hostname", g_variant_new_boolean(TRUE)); g_variant_builder_add (&connBuilder, "{sa{sv}}", "ipv6", &settingsBuilder); NMLOG_DEBUG("connection builder success..."); return true; @@ -1900,11 +2342,11 @@ namespace WPEFramework bool NetworkManagerClient::removeKnownSSIDs(const std::string& ssid) { bool ret = false; - if(ssid.empty()) - { - NMLOG_ERROR("ssid name is empty"); - return false; - } + bool ssidSpecified = !ssid.empty(); + bool connectionFound = false; + + if(!ssidSpecified) + NMLOG_WARNING("ssid is not specified, Deleting all available wifi connections!"); std::list paths; if(!GnomeUtils::getConnectionPaths(m_dbus, paths)) @@ -1916,13 +2358,26 @@ namespace WPEFramework for (const std::string& path : paths) { // NMLOG_DEBUG("remove connection path %s", path.c_str()); std::string connSsid; - if(getSSIDFromConnection(m_dbus, path, connSsid) && connSsid == ssid) { - ret = deleteConnection(m_dbus, path, connSsid); + if(getSSIDFromConnection(m_dbus, path, connSsid)) { + // If SSID is specified, only delete matching connections + // If SSID is empty, delete all wireless connections + if (!ssidSpecified || connSsid == ssid) { + if(deleteConnection(m_dbus, path, connSsid)) { + NMLOG_INFO("delete '%s' connection ...", connSsid.c_str()); + connectionFound = true; + ret = true; + } + } } } - if(!ret) - NMLOG_ERROR("ssid '%s' Connection remove failed", ssid.c_str()); + if(!connectionFound) + { + if(ssidSpecified) + NMLOG_WARNING("'%s' no such connection profile", ssid.c_str()); + else + NMLOG_WARNING("No wifi connection profiles found!"); + } return ret; } @@ -2039,6 +2494,21 @@ namespace WPEFramework return false; } + // Check if already connected to the requested SSID + Exchange::INetworkManager::WiFiSSIDInfo currentSSID; + if(getConnectedSSID(currentSSID)) + { + if(ssidinfo.ssid == currentSSID.ssid) + { + NMLOG_INFO("'%s' already connected !", currentSSID.ssid.c_str()); + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + return true; + } + else + NMLOG_DEBUG("wifi already connected with %s AP", currentSSID.ssid.c_str()); + } + std::list paths; if(GnomeUtils::getWifiConnectionPaths(m_dbus, deviceProp.path.c_str(), paths)) { @@ -2054,7 +2524,7 @@ namespace WPEFramework } } - /* if ap is avilable check the security is maching to user requested */ + /* if ap is available check the security is matching to user requested */ Exchange::INetworkManager::WiFiSSIDInfo apInfo{}; apInfo.ssid = ssidinfo.ssid; std::string apPathStr = "/"; // default specific object path is "/" @@ -2068,7 +2538,28 @@ namespace WPEFramework } } else + { NMLOG_WARNING("matching ssid (%s) not found in scanning result", ssidinfo.ssid.c_str()); + /* ssid not found in scan list so add to known ssid it will do a scanning and connect */ + if(ssidinfo.persist) + { + if(addToKnownSSIDs(ssidinfo)) + { + NMLOG_DEBUG("Adding to known ssid '%s' ", ssidinfo.ssid.c_str()); + return activateKnownConnection(GnomeUtils::getWifiIfname(), ssidinfo.ssid); + } + else + { + NMLOG_ERROR("Failed to add SSID '%s' to known SSIDs", ssidinfo.ssid.c_str()); + return false; + } + } + else + { + NMLOG_WARNING("SSID '%s' not found and persist is false, cannot connect", ssidinfo.ssid.c_str()); + return false; + } + } if(reuseConnection) { @@ -2078,24 +2569,56 @@ namespace WPEFramework return false; } - if(updateConnctionAndactivate(m_dbus, connBuilder, deviceProp.path.c_str(), exsistingConn.c_str())) - NMLOG_INFO("updated connection request success"); - else { - NMLOG_ERROR("wifi connect request failed"); - return false; + if (ssidinfo.persist) + { + if(updateConnctionAndactivate(m_dbus, connBuilder, deviceProp.path.c_str(), exsistingConn.c_str())) + NMLOG_INFO("updated connection request success"); + else + { + NMLOG_ERROR("wifi connect request failed"); + return false; + } + } + else + { + // Don't persist changes, just activate existing connection + // Note: Any changes made by connectionBuilder will be temporary for this session only + NMLOG_DEBUG("activating existing connection without persisting changes '%s'", ssidinfo.ssid.c_str()); + if(GnomeUtils::activateConnection(m_dbus, exsistingConn, deviceProp.path)) + NMLOG_INFO("activated existing connection without persistence"); + else { + NMLOG_ERROR("failed to activate existing connection"); + return false; + } } } else { + NMLOG_DEBUG("creating new connection '%s' persist=%d", ssidinfo.ssid.c_str(), ssidinfo.persist); if(!connectionBuilder(ssidinfo, connBuilder, iswpsAP)) { NMLOG_WARNING("connection builder failed"); return false; } - if(addNewConnctionAndactivate(m_dbus, connBuilder, deviceProp.path.c_str(), ssidinfo.persist, apPathStr.c_str())) - NMLOG_INFO("wifi connect request success"); - else { - NMLOG_ERROR("wifi connect request failed"); - return false; + if (ssidinfo.persist) + { + if(addNewConnctionAndactivate(m_dbus, connBuilder, deviceProp.path.c_str(), ssidinfo.persist, apPathStr.c_str())) + NMLOG_INFO("wifi connect request success"); + else + { + NMLOG_ERROR("wifi connect request failed"); + return false; + } + } + else + { + // Create temporary connection - add to memory only, do not save to disk + NMLOG_DEBUG("creating temporary connection for '%s'", ssidinfo.ssid.c_str()); + if(addNewConnctionAndactivate(m_dbus, connBuilder, deviceProp.path.c_str(), ssidinfo.persist, apPathStr.c_str())) + NMLOG_INFO("temporary wifi connect request success"); + else { + NMLOG_ERROR("temporary wifi connect request failed"); + return false; + } } } @@ -2111,7 +2634,8 @@ namespace WPEFramework if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), devInfo) || devInfo.path.empty()) return false; - if(devInfo.state <= NM_DEVICE_STATE_DISCONNECTED) + NMLOG_DEBUG("wifi device current state is %d !", devInfo.state); + if(devInfo.state <= NM_DEVICE_STATE_DISCONNECTED || devInfo.state == NM_DEVICE_STATE_FAILED || devInfo.state == NM_DEVICE_STATE_DEACTIVATING) { NMLOG_WARNING("wifi in disconnected state"); return true; @@ -2136,6 +2660,130 @@ namespace WPEFramework return true; } + bool NetworkManagerClient::activateKnownConnection(const std::string& interface, const std::string& knownConnectionID) + { + NMLOG_DEBUG("Activating known connection: interface=%s, connectionID=%s", interface.c_str(), knownConnectionID.c_str()); + + deviceInfo devInfo; + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, interface.c_str(), devInfo)) + { + NMLOG_ERROR("Failed to get device info for interface: %s", interface.c_str()); + return false; + } + + if(devInfo.path.empty() || devInfo.state < NM_DEVICE_STATE_UNAVAILABLE) + { + NMLOG_ERROR("Interface %s not active or available", interface.c_str()); + return false; + } + + // Set autoconnect to true for the device + GDBusProxy *deviceProxy = m_dbus.getNetworkManagerDeviceProxy(devInfo.path.c_str()); + if (deviceProxy != nullptr) { + GVariant *autoconnectValue = g_variant_new_boolean(TRUE); + GError *setError = nullptr; + g_dbus_proxy_call_sync( + deviceProxy, + "Set", + g_variant_new("(ssv)", "org.freedesktop.NetworkManager.Device", "Autoconnect", autoconnectValue), + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &setError); + + if (setError) { + NMLOG_WARNING("Failed to set autoconnect for device %s: %s", interface.c_str(), setError->message); + g_error_free(setError); + } else { + NMLOG_DEBUG("Set autoconnect=true for device %s", interface.c_str()); + } + g_object_unref(deviceProxy); + } + + // Get all connections + GError *error = nullptr; + GDBusProxy *settingsProxy = m_dbus.getNetworkManagerSettingsProxy(); + if (settingsProxy == nullptr) { + NMLOG_ERROR("Error creating NetworkManager settings proxy"); + return false; + } + + GVariant *connectionsResult = g_dbus_proxy_call_sync( + settingsProxy, + "ListConnections", + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (error || connectionsResult == nullptr) { + NMLOG_ERROR("Error retrieving connections: %s", error ? error->message : "unknown error"); + if (error) g_error_free(error); + g_object_unref(settingsProxy); + return false; + } + + GVariantIter *connectionIter; + const gchar *connectionPath; + std::string foundConnectionPath; + std::string firstWiFiConnectionPath; + + g_variant_get(connectionsResult, "(ao)", &connectionIter); + + // Find the requested connection or first WiFi connection + while (g_variant_iter_loop(connectionIter, "o", &connectionPath)) { + std::string ssid; + if(getSSIDFromConnection(m_dbus, connectionPath, ssid)) + { + NMLOG_DEBUG("Found WiFi connection: %s (SSID: %s)", connectionPath, ssid.c_str()); + + // If no specific connection requested, use first WiFi connection + if(firstWiFiConnectionPath.empty()) + firstWiFiConnectionPath = connectionPath; + + // If specific connection requested, look for exact match + if(!knownConnectionID.empty() && ssid == knownConnectionID) + { + foundConnectionPath = connectionPath; + NMLOG_INFO("Found matching connection for SSID: %s", knownConnectionID.c_str()); + break; + } + } + } + + g_variant_iter_free(connectionIter); + g_variant_unref(connectionsResult); + g_object_unref(settingsProxy); + + // Determine which connection to activate + std::string connectionToActivate; + if(!foundConnectionPath.empty()) + connectionToActivate = foundConnectionPath; + else if(knownConnectionID.empty() && !firstWiFiConnectionPath.empty()) + { + connectionToActivate = firstWiFiConnectionPath; + NMLOG_INFO("No specific connection requested, using first WiFi connection"); + } + else + { + NMLOG_ERROR("No suitable connection found. Requested: '%s'", knownConnectionID.c_str()); + return false; + } + + // Activate the connection + if(GnomeUtils::activateConnection(m_dbus, connectionToActivate, devInfo.path)) + { + NMLOG_INFO("Successfully activated known connection: %s", connectionToActivate.c_str()); + return true; + } + else + { + NMLOG_ERROR("Failed to activate connection: %s", connectionToActivate.c_str()); + return false; + } + } + static bool getWpsPbcSSIDDetails(DbusMgr& m_dbus, const char* apPath, std::string& wpsApSsid) { guint32 flags = 0; @@ -2241,11 +2889,73 @@ namespace WPEFramework return isfound; } + bool NetworkManagerClient::isActiveApSameAsWps(const std::string& wpsSSID) + { + deviceInfo devProperty{}; + GDBusProxy* wProxy = nullptr; + GVariant* result = nullptr; + bool isSame = false; + + // Get WiFi device info + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), devProperty)) + return false; + + if(devProperty.path.empty() || devProperty.state < NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_ERROR("no wifi device found"); + return false; + } + + // Get WiFi device proxy + wProxy = m_dbus.getNetworkManagerWirelessProxy(devProperty.path.c_str()); + if (wProxy == NULL) + return false; + + // Get active access point + result = g_dbus_proxy_get_cached_property(wProxy, "ActiveAccessPoint"); + if (!result) { + NMLOG_DEBUG("No active access point found"); + g_object_unref(wProxy); + return false; + } + + const gchar* activeApPath = nullptr; + g_variant_get(result, "o", &activeApPath); + + if (activeApPath && g_strcmp0(activeApPath, "/") != 0) { + // Get AP proxy and check SSID + GDBusProxy* apProxy = m_dbus.getNetworkManagerAccessPointProxy(activeApPath); + if (apProxy) { + GVariant* ssidVariant = g_dbus_proxy_get_cached_property(apProxy, "Ssid"); + if (ssidVariant) { + gsize ssid_length = 0; + const guchar *ssid_data = static_cast(g_variant_get_fixed_array(ssidVariant, &ssid_length, sizeof(guchar))); + if (ssid_data && ssid_length > 0 && ssid_length <= 32) { + std::string activeSSID(reinterpret_cast(ssid_data), ssid_length); + if (activeSSID == wpsSSID) { + NMLOG_INFO("Active AP matches WPS SSID: %s", wpsSSID.c_str()); + isSame = true; + } + } + g_variant_unref(ssidVariant); + } + g_object_unref(apProxy); + } + } + + g_variant_unref(result); + g_object_unref(wProxy); + return isSame; + } + void NetworkManagerClient::wpsProcess() { m_wpsProcessRun = true; + m_wpsActionTriggered = false; Exchange::INetworkManager::WiFiConnectTo ssidinfo{}; Exchange::INetworkManager::WiFiState state; + deviceInfo devProperty{}; + bool wpsComplete = false; NMLOG_INFO("WPS process started !"); if(!getWifiState(state)) @@ -2255,20 +2965,74 @@ namespace WPEFramework return; } - for(int retry =0; retry < GDBUS_WPS_RETRY_COUNT; retry++) + for(int retry = 0; retry < GDBUS_WPS_RETRY_COUNT; retry++) { - if(m_wpsProcessRun.load() == false) // stop wps process if reuested + if(m_wpsProcessRun.load() == false) // stop wps process if requested break; sleep(GDBUS_WPS_RETRY_WAIT_IN_MS); if(m_wpsProcessRun.load() == false) break; + + + // Get current device info for state monitoring + if(!GnomeUtils::getDeviceInfoByIfname(m_dbus, GnomeUtils::getWifiIfname(), devProperty)) + { + NMLOG_ERROR("Failed to get device info during WPS process"); + break; + } + + if(m_wpsActionTriggered) + { + // If WPS action started, monitor device state for completion + if(devProperty.state <= NM_DEVICE_STATE_DISCONNECTED) + { + NMLOG_WARNING("WPS process failed - device in disconnected state"); + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + break; + } + else if(devProperty.state > NM_DEVICE_STATE_NEED_AUTH) + { + NMLOG_INFO("WPS process completed successfully"); + wpsComplete = true; + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + break; + } + + NMLOG_INFO("WPS process not completed yet, device state: %d", devProperty.state); + if(retry >= GDBUS_WPS_RETRY_COUNT - 1) // Last retry attempt + { + NMLOG_ERROR("WPS process failed - timeout"); + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED); + break; + } + continue; + } + + // Look for WPS PBC SSID if(!findWpsPbcSSID(m_dbus, ssidinfo.ssid)) { - startWifiScan(); + if(!m_wpsActionTriggered) + { + // If WPS action not triggered, do a scanning request + startWifiScan(); + } NMLOG_DEBUG("WPS process retrying: %d ", retry+1); continue; } + // Check if already connected to the same WPS AP + if(isActiveApSameAsWps(ssidinfo.ssid)) + { + NMLOG_INFO("WPS process stopped - already connected to WPS AP '%s'", ssidinfo.ssid.c_str()); + wpsComplete = true; + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + break; + } + if(!getWifiState(state)) { NMLOG_ERROR("wifi state error ! wps process stoped !"); @@ -2278,18 +3042,39 @@ namespace WPEFramework if(Exchange::INetworkManager::WiFiState::WIFI_STATE_DISCONNECTED != state) { - /* we need a wifi disconnected state to proceed wifi PBC process */ + NMLOG_INFO("Disconnecting current connection for WPS process"); wifiDisconnect(); + sleep(3); // Wait for disconnect to complete } ssidinfo.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; ssidinfo.persist = true; + + NMLOG_INFO("Starting WPS connection to SSID: %s", ssidinfo.ssid.c_str()); + + // Mark WPS action as triggered and adjust retry count + m_wpsActionTriggered = true; + retry = GDBUS_WPS_RETRY_COUNT - 3; // Expecting WPS process will be completed in 30 sec (3 * 10sec retry) + /* security mode will be updated in wifi connect function, if not mathing to wpa-psk */ wifiConnect(ssidinfo, true); // isWps = true - break; } - NMLOG_INFO("wps process complete !!"); + // Final status reporting + if(!wpsComplete && !m_wpsActionTriggered) + { + NMLOG_WARNING("WPS AP not found"); + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + } + else if(!wpsComplete && m_wpsActionTriggered) + { + NMLOG_INFO("WPS process error"); + if(_instance != nullptr) + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED); + } + + NMLOG_INFO("WPS process thread exit"); m_wpsProcessRun = false; } @@ -2310,9 +3095,282 @@ namespace WPEFramework bool NetworkManagerClient::stopWPS() { NMLOG_DEBUG("Stop WPS %s", __FUNCTION__); - m_wpsProcessRun = false; + m_wpsProcessRun = false; + m_wpsActionTriggered = false; return m_secretAgent.UnregisterAgent(); } + bool NetworkManagerClient::modifyDefaultConnectionsConfig() + { + NMLOG_DEBUG("Initializing hostname settings for existing connections"); + + // Get persistent hostname or use default + std::string hostname; + if (!GnomeUtils::readPersistentHostname(hostname)) { + const char* deviceHostname = "rdk-device"; // default hostname + hostname = deviceHostname; + NMLOG_DEBUG("No persistent hostname found, using device hostname: %s", hostname.c_str()); + } + + GError *error = nullptr; + GDBusProxy *settingsProxy = m_dbus.getNetworkManagerSettingsProxy(); + if (settingsProxy == nullptr) { + NMLOG_ERROR("Error creating NetworkManager settings proxy"); + return false; + } + + // Get all connections + GVariant *connectionsResult = g_dbus_proxy_call_sync( + settingsProxy, + "ListConnections", + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (error || connectionsResult == nullptr) { + NMLOG_ERROR("Error retrieving connections for hostname init: %s", error ? error->message : "unknown error"); + if (error) g_error_free(error); + g_object_unref(settingsProxy); + return false; + } + + GVariantIter *connectionIter; + const gchar *connectionPath; + bool success = true; + + g_variant_get(connectionsResult, "(ao)", &connectionIter); + + while (g_variant_iter_loop(connectionIter, "o", &connectionPath)) { + // Get connection settings to check interface name + GDBusProxy *connectionProxy = m_dbus.getNetworkManagerSettingsConnectionProxy(connectionPath); + if (connectionProxy == nullptr) { + NMLOG_WARNING("Failed to create proxy for connection during hostname init: %s", connectionPath); + continue; + } + + GVariant *settingsResult = g_dbus_proxy_call_sync( + connectionProxy, + "GetSettings", + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (error || settingsResult == nullptr) { + NMLOG_WARNING("Failed to get settings for connection %s during hostname init: %s", + connectionPath, error ? error->message : "unknown error"); + if (error) { + g_error_free(error); + error = nullptr; + } + g_object_unref(connectionProxy); + continue; + } + + // Parse connection settings to get interface name + GVariantIter *settingsIter; + const gchar *settingName; + GVariant *settingDict; + std::string interfaceName; + std::string connectionType; + + g_variant_get(settingsResult, "(a{sa{sv}})", &settingsIter); + while (g_variant_iter_loop(settingsIter, "{&s@a{sv}}", &settingName, &settingDict)) { + if (g_strcmp0(settingName, "connection") == 0) { + GVariantIter dictIter; + const gchar *key; + GVariant *value; + + g_variant_iter_init(&dictIter, settingDict); + while (g_variant_iter_loop(&dictIter, "{&sv}", &key, &value)) { + if (g_strcmp0(key, "interface-name") == 0) { + interfaceName = g_variant_get_string(value, nullptr); + } else if (g_strcmp0(key, "type") == 0) { + connectionType = g_variant_get_string(value, nullptr); + } + } + } + } + g_variant_iter_free(settingsIter); + + // Only process Ethernet and WiFi connections + bool isValidInterface = false; + if (!interfaceName.empty()) { + if (interfaceName == GnomeUtils::getEthIfname() && + (connectionType == "802-3-ethernet")) { + isValidInterface = true; + } else if (interfaceName == GnomeUtils::getWifiIfname() && + (connectionType == "802-11-wireless")) { + isValidInterface = true; + } + } + + if (isValidInterface) { + NMLOG_DEBUG("Initializing hostname for existing connection: %s (interface: %s)", + connectionPath, interfaceName.c_str()); + + if (!updateHostnameSettings(m_dbus, std::string(connectionPath), hostname, interfaceName)) { + NMLOG_WARNING("Failed to initialize hostname for existing connection: %s", interfaceName.c_str()); + // Don't fail the whole operation for one connection + } else { + NMLOG_INFO("Successfully initialized hostname for existing connection: %s", interfaceName.c_str()); + } + } else { + NMLOG_DEBUG("Skipping hostname init for non-ethernet/wifi connection: %s (type: %s)", + interfaceName.c_str(), connectionType.c_str()); + } + + g_variant_unref(settingsResult); + g_object_unref(connectionProxy); + } + + g_variant_iter_free(connectionIter); + g_variant_unref(connectionsResult); + g_object_unref(settingsProxy); + + NMLOG_INFO("Completed hostname initialization for existing connections"); + return success; + } + + bool NetworkManagerClient::setHostname(const std::string& hostname) + { + NMLOG_DEBUG("Setting DHCP hostname to: %s", hostname.c_str()); + + // Validate hostname length (1-32 characters as per NetworkManager specs) + if(hostname.length() < 1 || hostname.length() > 32) + { + NMLOG_ERROR("Invalid hostname length: %zu (must be 1-32 characters)", hostname.length()); + return false; + } + + GError *error = nullptr; + GDBusProxy *settingsProxy = m_dbus.getNetworkManagerSettingsProxy(); + if (settingsProxy == nullptr) { + NMLOG_ERROR("Error creating NetworkManager settings proxy"); + return false; + } + + // Get all connections + GVariant *connectionsResult = g_dbus_proxy_call_sync( + settingsProxy, + "ListConnections", + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (error || connectionsResult == nullptr) { + NMLOG_ERROR("Error retrieving connections: %s", error ? error->message : "unknown error"); + if (error) g_error_free(error); + g_object_unref(settingsProxy); + return false; + } + + GVariantIter *connectionIter; + const gchar *connectionPath; + bool success = true; + + g_variant_get(connectionsResult, "(ao)", &connectionIter); + + while (g_variant_iter_loop(connectionIter, "o", &connectionPath)) { + // Get connection settings to check interface name + GDBusProxy *connectionProxy = m_dbus.getNetworkManagerSettingsConnectionProxy(connectionPath); + if (connectionProxy == nullptr) { + NMLOG_WARNING("Failed to create proxy for connection: %s", connectionPath); + continue; + } + + GVariant *settingsResult = g_dbus_proxy_call_sync( + connectionProxy, + "GetSettings", + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (error || settingsResult == nullptr) { + NMLOG_WARNING("Failed to get settings for connection %s: %s", + connectionPath, error ? error->message : "unknown error"); + if (error) { + g_error_free(error); + error = nullptr; + } + g_object_unref(connectionProxy); + continue; + } + + // Parse connection settings to get interface name + GVariantIter *settingsIter; + const gchar *settingName; + GVariant *settingDict; + std::string interfaceName; + std::string connectionType; + + g_variant_get(settingsResult, "(a{sa{sv}})", &settingsIter); + while (g_variant_iter_loop(settingsIter, "{&s@a{sv}}", &settingName, &settingDict)) { + if (g_strcmp0(settingName, "connection") == 0) { + GVariantIter dictIter; + const gchar *key; + GVariant *value; + + g_variant_iter_init(&dictIter, settingDict); + while (g_variant_iter_loop(&dictIter, "{&sv}", &key, &value)) { + if (g_strcmp0(key, "interface-name") == 0) { + interfaceName = g_variant_get_string(value, nullptr); + } else if (g_strcmp0(key, "type") == 0) { + connectionType = g_variant_get_string(value, nullptr); + } + } + } + } + g_variant_iter_free(settingsIter); + + // Only process Ethernet and WiFi connections + bool isValidInterface = false; + if (!interfaceName.empty()) { + if (interfaceName == GnomeUtils::getEthIfname() && + (connectionType == "802-3-ethernet")) { + isValidInterface = true; + } else if (interfaceName == GnomeUtils::getWifiIfname() && + (connectionType == "802-11-wireless")) { + isValidInterface = true; + } + } + + if (isValidInterface) { + NMLOG_DEBUG("Updating hostname for interface: %s (connection: %s)", + interfaceName.c_str(), connectionPath); + + if (!updateHostnameSettings(m_dbus, std::string(connectionPath), hostname, interfaceName)) { + NMLOG_ERROR("Failed to update hostname for interface: %s", interfaceName.c_str()); + success = false; + } + } else { + NMLOG_DEBUG("Skipping non-ethernet/wifi connection: %s (type: %s)", + interfaceName.c_str(), connectionType.c_str()); + } + + g_variant_unref(settingsResult); + g_object_unref(connectionProxy); + } + + g_variant_iter_free(connectionIter); + g_variant_unref(connectionsResult); + g_object_unref(settingsProxy); + + if (success) { + // Write hostname to persistent storage + GnomeUtils::writePersistentHostname(hostname); + NMLOG_INFO("Successfully set DHCP hostname to: %s", hostname.c_str()); + } + + return success; + } + } // WPEFramework } // Plugin diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusClient.h b/plugin/gnome/gdbus/NetworkManagerGdbusClient.h index 4b3d9afbe..25f94ace2 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusClient.h +++ b/plugin/gnome/gdbus/NetworkManagerGdbusClient.h @@ -27,6 +27,7 @@ #include "NetworkManagerGdbusMgr.h" #include "NetworkManagerSecretAgent.h" #include "NetworkManagerImplementation.h" +#include "NetworkManagerGdbusUtils.h" #include "INetworkManager.h" #define GDBUS_WPS_RETRY_WAIT_IN_MS 10 // 10 sec @@ -62,20 +63,27 @@ namespace WPEFramework bool addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo); bool removeKnownSSIDs(const std::string& ssid); bool startWifiScan(const std::string ssid = ""); + bool isWifiScannedRecently(int timelimitInSec = 5); // default 5 sec as shortest scanning interval + bool getDeviceInfo(const std::string& interface, deviceInfo& devInfo); bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo& connectInfo, bool iswpsAP = false); bool wifiDisconnect(); + bool activateKnownConnection(const std::string& interface, const std::string& knownConnectionID = ""); bool getWifiState(Exchange::INetworkManager::WiFiState &state); bool getWiFiSignalQuality(std::string& ssid, std::string& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality); bool startWPS(); bool stopWPS(); + bool setHostname(const std::string& hostname); + bool modifyDefaultConnectionsConfig(); private: NetworkManagerClient(); ~NetworkManagerClient(); void wpsProcess(); bool getMatchingSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo& ssidInfo, std::string& apPathStr); + bool isActiveApSameAsWps(const std::string& wpsSSID); std::thread m_wpsthread; std::atomic m_wpsProcessRun; + std::atomic m_wpsActionTriggered; SecretAgent m_secretAgent; DbusMgr m_dbus; }; diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp index c451b8f25..d0c50c409 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp @@ -131,9 +131,9 @@ namespace WPEFramework { const gchar *connectionType = g_variant_get_string(typeVariant, NULL); if(connectionType != NULL) { - if (0 == strncmp("802-3-ethernet", connectionType, sizeof("802-3-ethernet"))) + if (0 == strncmp("802-3-ethernet", connectionType, sizeof("802-3-ethernet")) && string("eth0_missing") != GnomeUtils::getEthIfname()) NetworkManagerEvents::onActiveInterfaceChangeCb(std::string(GnomeUtils::getEthIfname())); - else if(0 == strncmp("802-11-wireless", connectionType, sizeof("802-11-wireless"))) + else if(0 == strncmp("802-11-wireless", connectionType, sizeof("802-11-wireless")) && string("wlan0_missing") != GnomeUtils::getWifiIfname()) NetworkManagerEvents::onActiveInterfaceChangeCb(std::string(GnomeUtils::getWifiIfname())); else NMLOG_WARNING("active connection not an ethernet/wifi %s", connectionType); @@ -180,8 +180,27 @@ namespace WPEFramework NMLOG_INFO("Device Added: %s", ifname.c_str()); if(ifname == GnomeUtils::getWifiIfname() || ifname == GnomeUtils::getEthIfname() ) { + // Get device state to validate if it should be monitored + deviceInfo devInfo{}; + NetworkManagerEvents* nmEventsInstance = NetworkManagerEvents::getInstance(); + if(nmEventsInstance && GnomeUtils::getDeviceInfoByIfname(nmEventsInstance->eventDbus, ifname.c_str(), devInfo)) + { + NMDeviceState devState = devInfo.state; + // NM_DEVICE_STATE_UNAVAILABLE can occur for an Ethernet interface when it is disconnected (e.g., no cable connected). + bool isDeviceEnabled = devState >= NM_DEVICE_STATE_UNAVAILABLE && devState <= NM_DEVICE_STATE_ACTIVATED; + if(!isDeviceEnabled) + { + NMLOG_WARNING("device %s is not enabled, So no event monitor", ifname.c_str()); + return; + } + } NMLOG_INFO("monitoring device: %s", ifname.c_str()); NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, ifname.c_str()); + // Only subscribe to LastScan if it's a WiFi device and not already monitored + if(ifname == GnomeUtils::getWifiIfname() && _NetworkManagerEvents->nmEvents.wirelessProxy == nullptr) + { + subscribeForlastScanPropertyEvent(devicePath); + } // TODO monitor device // monitorDevice() } @@ -270,6 +289,7 @@ namespace WPEFramework case NM_DEVICE_STATE_DISCONNECTED: wifiState = "WIFI_STATE_DISCONNECTED"; NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_DISCONNECTED, wifiState); + NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_DOWN, GnomeUtils::getWifiIfname()); NetworkManagerEvents::onAddressChangeCb(GnomeUtils::getWifiIfname(), false, false); NetworkManagerEvents::onAddressChangeCb(GnomeUtils::getWifiIfname(), false, true); break; @@ -280,9 +300,18 @@ namespace WPEFramework case NM_DEVICE_STATE_CONFIG: wifiState = "WIFI_STATE_CONNECTING"; NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTING, wifiState); + break; + case NM_DEVICE_STATE_IP_CONFIG: + wifiState = "NM_DEVICE_STATE_IP_CONFIG"; NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_UP, GnomeUtils::getWifiIfname()); + NetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTED, wifiState); break; case NM_DEVICE_STATE_IP_CHECK: + wifiState = "NM_DEVICE_STATE_IP_CHECK"; + //NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP, GnomeUtils::getWifiIfname()); + break; + case NM_DEVICE_STATE_SECONDARIES: + wifiState = "NM_DEVICE_STATE_SECONDARIES"; NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP, GnomeUtils::getWifiIfname()); break; case NM_DEVICE_STATE_ACTIVATED: @@ -312,6 +341,7 @@ namespace WPEFramework } } } + NMLOG_INFO("wifi state: %s; reason: %d", wifiState.c_str(), static_cast(deviceStateReason)); } else if(ifname == GnomeUtils::getEthIfname()) { @@ -346,8 +376,9 @@ namespace WPEFramework NetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, GnomeUtils::getEthIfname()); } } + + NMLOG_INFO("eth0 state: %d; reason: %d", static_cast(deviceState), static_cast(deviceStateReason)); } - } static void onConnectionSignalReceivedCB (GDBusProxy *proxy, gchar *senderName, gchar *signalName, diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp index eff361ac1..6e848836e 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp @@ -21,6 +21,7 @@ #include "NetworkManagerGdbusClient.h" #include "NetworkManagerGdbusEvent.h" #include "../NetworkManagerGnomeUtils.h" +#include "NetworkManagerGdbusUtils.h" using namespace WPEFramework; using namespace WPEFramework::Plugin; @@ -95,6 +96,25 @@ namespace WPEFramework _nmGdbusClient = NetworkManagerClient::getInstance(); _nmGdbusEvents = NetworkManagerEvents::getInstance(); getInitialConnectionState(); + nmUtils::getDeviceProperties(); // get interface name form '/etc/device.proprties' + _nmGdbusClient->modifyDefaultConnectionsConfig(); + + // Set default interface based on device state + deviceInfo ethDevInfo, wifiDevInfo; + if(_nmGdbusClient->getDeviceInfo(GnomeUtils::getEthIfname(), ethDevInfo)) + { + if(ethDevInfo.state > NM_DEVICE_STATE_DISCONNECTED && ethDevInfo.state < NM_DEVICE_STATE_DEACTIVATING) + m_defaultInterface = GnomeUtils::getEthIfname(); + else + m_defaultInterface = GnomeUtils::getWifiIfname(); + } + else + m_defaultInterface = GnomeUtils::getWifiIfname(); + + NMLOG_INFO("default interface is %s", m_defaultInterface.c_str()); + + // Start event monitoring + _nmGdbusEvents->startNetworkMangerEventMonitor(); } uint32_t NetworkManagerImplementation::GetAvailableInterfaces (Exchange::INetworkManager::IInterfaceDetailsIterator*& interfacesItr/* @out */) @@ -245,22 +265,29 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::WiFiConnect(const WiFiConnectTo& ssid /* @in */) { uint32_t rc = Core::ERROR_GENERAL; - if(ssid.ssid.empty()) + // Check the last scanning time and if it exceeds 5 sec do a rescanning + if(!_nmGdbusClient->isWifiScannedRecently()) { - NMLOG_WARNING("ssid is not sepecified; so attampting to connect know ssids !"); _nmGdbusEvents->setwifiScanOptions(false); /* Enable event posting */ - if(_nmGdbusClient->startWifiScan()) + if(!_nmGdbusClient->startWifiScan()) + NMLOG_WARNING("scanning failed but try to connect"); + } + + if(ssid.ssid.empty() && _instance != NULL) + { + NMLOG_WARNING("ssid is empty activating last connected ssid !"); + if(_nmGdbusClient->activateKnownConnection(GnomeUtils::getWifiIfname(), _instance->m_lastConnectedSSID)) rc = Core::ERROR_NONE; - else - NMLOG_ERROR("StartWiFiScan failed"); } - else + else if(ssid.ssid.size() <= 32) { if(_nmGdbusClient->wifiConnect(ssid)) rc = Core::ERROR_NONE; else NMLOG_ERROR("WiFiConnect failed"); } + else + NMLOG_WARNING("SSID is invalid"); return rc; } @@ -342,5 +369,29 @@ namespace WPEFramework } return rc; } + + /* @brief Set the dhcp hostname */ + uint32_t NetworkManagerImplementation::SetHostname(const string& hostname /* @in */) + { + uint32_t rc = Core::ERROR_GENERAL; + + if(hostname.length() < 1 || hostname.length() > 32) + { + NMLOG_ERROR("Invalid hostname length: %zu", hostname.length()); + return Core::ERROR_BAD_REQUEST; + } + + if(_nmGdbusClient->setHostname(hostname)) + { + NMLOG_INFO("Successfully set hostname to: %s", hostname.c_str()); + rc = Core::ERROR_NONE; + } + else + { + NMLOG_ERROR("SetHostname failed for hostname: %s", hostname.c_str()); + } + + return rc; + } } } diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp index 746e29efe..c487d6c5a 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "NetworkManagerLogger.h" @@ -153,14 +154,16 @@ namespace WPEFramework uint8_t GnomeUtils::wifiSecurityModeFromApFlags(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags) { uint8_t security = Exchange::INetworkManager::WIFI_SECURITY_NONE; - if ((flags == NM_802_11_AP_FLAGS_NONE) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) + if ((flags != NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE) && (rsnFlags == NM_802_11_AP_SEC_NONE)) // Open network security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE; - else if (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE) + else if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) && (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE)) // WPA2/WPA3 Transition + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + else if (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE) // Pure WPA3 (SAE only): WPA3-Personal security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE; - else if (wpaFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X || rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + else if (wpaFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X || rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) // WPA2/WPA3 Enterprise: EAP present in either WPA or RSN security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP; else - security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; + security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; // WPA2-PSK //NMLOG_INFO("ap [%s] security str %s", ssid.c_str(), nmUtils::getSecurityModeString(flags, wpaFlags, rsnFlags).c_str()); return security; @@ -708,6 +711,62 @@ namespace WPEFramework g_variant_builder_add(builder, "{sv}", key, value); } } + + bool GnomeUtils::writePersistentHostname(const std::string& hostname) + { + constexpr const char* HostnameFile = "/opt/persistent/nm.plugin.hostname"; + + if (hostname.empty()) { + NMLOG_ERROR("Cannot write empty hostname to persistent storage"); + return false; + } + + std::ofstream file(HostnameFile); + if (!file.is_open()) { + NMLOG_ERROR("Failed to open %s for writing", HostnameFile); + return false; + } + + file << hostname; + bool success = !file.fail(); + file.close(); + + if (success) + NMLOG_DEBUG("Successfully wrote hostname '%s' to %s", hostname.c_str(), HostnameFile); + else + NMLOG_ERROR("Error writing hostname to %s", HostnameFile); + + return success; + } + + bool GnomeUtils::readPersistentHostname(std::string& hostname) + { + constexpr const char* HostnameFile = "/opt/persistent/nm.plugin.hostname"; + + std::ifstream file(HostnameFile); + if (!file.is_open()) { + NMLOG_DEBUG("Could not open %s - file may not exist yet", HostnameFile); + hostname = ""; + return false; + } + + std::string line; + if (std::getline(file, line)) { + // Remove any whitespace, newlines, etc. + line.erase(line.find_last_not_of("\r\n\t") + 1); + line.erase(0, line.find_first_not_of("\r\n\t")); + hostname = line; + file.close(); + + NMLOG_INFO("Read persistent hostname: '%s'", hostname.c_str()); + return true; + } + + NMLOG_WARNING("Persistent hostname file exists but is empty"); + hostname = ""; + file.close(); + return false; + } } // Plugin } // WPEFramework diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h index 3b46bbef0..f02373e5a 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h +++ b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h @@ -90,6 +90,8 @@ namespace WPEFramework static uint8_t wifiSecurityModeFromApFlags(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags); static const char* getWifiIfname(); static const char* getEthIfname(); + static bool writePersistentHostname(const std::string& hostname); + static bool readPersistentHostname(std::string& hostname); }; } // Plugin From 5102d611bc2760186f4d09c87655fb94a7b0997d Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 29 Oct 2025 19:20:31 -0400 Subject: [PATCH 199/271] RDKEMW-9195 - Request MfrMgr to Persist WiFi Settings from NetworkManager Plugin (#241) * RDKEMW-9195 - Request MfrMgr to Persist WiFi Settings from NetworkManager Plugin Reason for change: To save the wifi credentials to MfrMgr when the wifi connection is successful and remove the same when removeKnownSSID is called So that when migrating from RDKE to RDKV we will have the wifi configuration to connect Test Procedure: CDL upgrade to RDKV from RDKE and check the wifi connection persist Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR * RDKEMW-9195 - Request MfrMgr to Persist WiFi Settings from NetworkManager Plugin Reason for change: To save the wifi credentials to MfrMgr when the wifi connection is successful and remove the same when removeKnownSSID is called So that when migrating from RDKE to RDKV we will have the wifi configuration to connect Test Procedure: CDL upgrade to RDKV from RDKE and check the wifi connection persist Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR --------- Signed-off-by: Gururaaja ESR --- .github/workflows/libnm_proxy_L1_test.yml | 27 +- plugin/CMakeLists.txt | 38 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 16 + plugin/gnome/NetworkManagerGnomeMfrMgr.cpp | 347 ++++++++++++++++++ plugin/gnome/NetworkManagerGnomeMfrMgr.h | 66 ++++ plugin/gnome/NetworkManagerGnomeWIFI.cpp | 10 + ...gnome-networkmanager-mfrmgr-migration.conf | 2 + tests/l2Test/libnm/CMakeLists.txt | 1 + tests/mocks/mfrMgr.h | 62 ++++ 9 files changed, 557 insertions(+), 12 deletions(-) create mode 100644 plugin/gnome/NetworkManagerGnomeMfrMgr.cpp create mode 100644 plugin/gnome/NetworkManagerGnomeMfrMgr.h create mode 100644 plugin/gnome/systemd/gnome-networkmanager-mfrmgr-migration.conf create mode 100644 tests/mocks/mfrMgr.h diff --git a/.github/workflows/libnm_proxy_L1_test.yml b/.github/workflows/libnm_proxy_L1_test.yml index ed40fc22e..80d945d59 100644 --- a/.github/workflows/libnm_proxy_L1_test.yml +++ b/.github/workflows/libnm_proxy_L1_test.yml @@ -113,6 +113,21 @@ jobs: WIFI_INTERFACE=wlan0 DEVICE_NAME=rdk_test_device " > /etc/device.properties' + - name: Generate IARM headers + run: | + touch install/usr/lib/libIARMBus.so + touch install/usr/lib/libmfrlib.so + mkdir -p install/usr/include/rdk/iarmbus + mkdir -p install/usr/include/rdk/iarmmgrs-hal + touch install/usr/include/rdk/iarmbus/libIARM.h + touch install/usr/include/rdk/iarmmgrs-hal/mfrMgr.h + cd "${{github.workspace}}/networkmanager/tests/" + mkdir -p headers/rdk/iarmbus + mkdir -p headers/rdk/iarmmgrs-hal + cd headers + touch rdk/iarmmgrs-hal/mfrMgr.h + touch rdk/iarmbus/libIARM.h rdk/iarmbus/libIBus.h + - name: Build networkmanager with Gnome libnm Proxy run: > cmake @@ -121,11 +136,19 @@ jobs: -DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}" -DCMAKE_INSTALL_PREFIX="${{github.workspace}}/install/usr" -DCMAKE_MODULE_PATH="${{github.workspace}}/install/tools/cmake" - -DCMAKE_CXX_FLAGS=" -fprofile-arcs -ftest-coverage " + -DCMAKE_CXX_FLAGS=" -fprofile-arcs -ftest-coverage + -I ${{github.workspace}}/networkmanager/tests/headers + -I ${{github.workspace}}/networkmanager/tests/headers/rdk/iarmbus + -I ${{github.workspace}}/networkmanager/tests/headers/rdk/iarmmgrs-hal + --include ${{github.workspace}}/networkmanager/tests/mocks/Iarm.h + --include ${{github.workspace}}/networkmanager/tests/mocks/mfrMgr.h + " + -DENABLE_GNOME_NETWORKMANAGER=ON -DENABLE_GNOME_NETWORKMANAGER=ON -DENABLE_LEGACY_PLUGINS=OFF -DENABLE_UNIT_TESTING=ON - -DENABLE_PLUGIN_CLI=ON + -DENABLE_PLUGIN_CLI=OFF + -DENABLE_MIGRATION_MFRMGR_SUPPORT=ON && cmake --build build/networkmanager_libnm --target install -j8 diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index c34f91663..bd50eef66 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -36,11 +36,15 @@ endif (USE_RDK_LOGGER) if(ENABLE_GNOME_NETWORKMANAGER) -pkg_check_modules(GLIB REQUIRED glib-2.0) -pkg_check_modules(LIBNM REQUIRED libnm) -pkg_check_modules(GLIB REQUIRED gio-2.0) + pkg_check_modules(GLIB REQUIRED glib-2.0) + pkg_check_modules(LIBNM REQUIRED libnm) + pkg_check_modules(GLIB REQUIRED gio-2.0) + if(ENABLE_MIGRATION_MFRMGR_SUPPORT) + add_definitions(-DENABLE_MIGRATION_MFRMGR_SUPPORT) + find_package(IARMBus REQUIRED) + endif () else() -find_package(IARMBus REQUIRED) + find_package(IARMBus REQUIRED) endif () set(PLUGIN_NETWORKMANAGER_LOGLEVEL "5" CACHE STRING "To configure default loglevel NetworkManager plugin") @@ -97,8 +101,18 @@ if(ENABLE_GNOME_NETWORKMANAGER) gnome/NetworkManagerGnomeEvents.cpp gnome/NetworkManagerGnomeUtils.cpp NetworkManagerSecretAgent.cpp ) - target_include_directories(${MODULE_IMPL_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) - target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${LIBNM_LIBRARIES}) + if(ENABLE_MIGRATION_MFRMGR_SUPPORT) + target_sources(${MODULE_IMPL_NAME} PRIVATE + gnome/NetworkManagerGnomeMfrMgr.cpp + ) + endif() + if(ENABLE_MIGRATION_MFRMGR_SUPPORT) + target_include_directories(${MODULE_IMPL_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS} ${IARMBUS_INCLUDE_DIRS}) + target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${LIBNM_LIBRARIES} ${IARMBUS_LIBRARIES}) + else() + target_include_directories(${MODULE_IMPL_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBNM_INCLUDE_DIRS}) + target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${LIBNM_LIBRARIES}) + endif() endif() else() message("networkmanager building with RDK netsrvmgr") @@ -129,10 +143,14 @@ install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE install(TARGETS ${MODULE_IMPL_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) if(ENABLE_GNOME_NETWORKMANAGER) -install(PROGRAMS gnome/scripts/nm_interface_handler.sh - DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/rdk) -install(FILES gnome/systemd/gnome-networkmanager-migration.conf - DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/systemd/system/wpeframework-networkmanager.service.d) + install(PROGRAMS gnome/scripts/nm_interface_handler.sh + DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/rdk) + install(FILES gnome/systemd/gnome-networkmanager-migration.conf + DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/systemd/system/wpeframework-networkmanager.service.d) + if(ENABLE_MIGRATION_MFRMGR_SUPPORT) + install(FILES gnome/systemd/gnome-networkmanager-mfrmgr-migration.conf + DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/systemd/system/wpeframework-networkmanager.service.d) + endif(ENABLE_MIGRATION_MFRMGR_SUPPORT) endif(ENABLE_GNOME_NETWORKMANAGER) #Generate Plugin configuration file diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 80197a689..39db2ca59 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -30,6 +30,9 @@ #include "NetworkManagerGnomeUtils.h" #include "NetworkManagerImplementation.h" #include "INetworkManager.h" +#ifdef ENABLE_MIGRATION_MFRMGR_SUPPORT +#include "NetworkManagerGnomeMfrMgr.h" +#endif namespace WPEFramework { @@ -651,7 +654,20 @@ namespace WPEFramework void GnomeNetworkManagerEvents::onWIFIStateChanged(uint8_t state) { if(_instance != nullptr) + { _instance->ReportWiFiStateChange(static_cast(state)); +#ifdef ENABLE_MIGRATION_MFRMGR_SUPPORT + // Handle WiFi state changes for MfrMgr integration + NetworkManagerMfrManager* mfrManager = NetworkManagerMfrManager::getInstance(); + if(mfrManager != nullptr) { + if(state == Exchange::INetworkManager::WIFI_STATE_CONNECTED) + { + NMLOG_DEBUG("WiFi connected - triggering MfrMgr save"); + mfrManager->saveWiFiSettingsToMfr(); + } + } +#endif + } } void GnomeNetworkManagerEvents::onAddressChangeCb(std::string iface, std::string ipAddress, bool acquired, bool isIPv6) diff --git a/plugin/gnome/NetworkManagerGnomeMfrMgr.cpp b/plugin/gnome/NetworkManagerGnomeMfrMgr.cpp new file mode 100644 index 000000000..b9e5cc29b --- /dev/null +++ b/plugin/gnome/NetworkManagerGnomeMfrMgr.cpp @@ -0,0 +1,347 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include "NetworkManagerGnomeMfrMgr.h" +#include "NetworkManagerLogger.h" +#include "NetworkManagerImplementation.h" +#include "INetworkManager.h" +#include "mfrMgr.h" +#include +#include + +#include "libIBus.h" + +namespace WPEFramework +{ + namespace Plugin + { + extern NetworkManagerImplementation* _instance; + + static std::mutex iarm_mutex; + static bool iarm_initialized = false; + + static bool ensureIARMConnection() + { + std::lock_guard lock(iarm_mutex); + + if (!iarm_initialized) { + IARM_Result_t ret = IARM_Bus_Init("NetworkMfrMgr"); + if (ret != IARM_RESULT_SUCCESS) { + NMLOG_ERROR("IARM_Bus_Init failed: %d", ret); + return false; + } + + ret = IARM_Bus_Connect(); + if (ret != IARM_RESULT_SUCCESS) { + NMLOG_ERROR("IARM_Bus_Connect failed: %d", ret); + return false; + } + + iarm_initialized = true; + NMLOG_DEBUG("IARM Bus connection established for MfrMgr"); + } + return true; + } + + // Helper function to retrieve current WiFi connection details using nmcli and connection files + static bool getCurrentWiFiConnectionDetails(std::string& ssid, std::string& passphrase, int& security) + { + // Use nmcli to get current WiFi connection info + FILE* pipe = popen("nmcli device wifi show-password 2>/dev/null", "r"); + if (!pipe) { + NMLOG_ERROR("Failed to execute nmcli command"); + return false; + } + + char buffer[1024]; + std::string nmcliOutput; + + // Read nmcli output + while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { + nmcliOutput += buffer; + } + + int exitCode = pclose(pipe); + if (exitCode != 0) { + NMLOG_ERROR("nmcli command failed with exit code: %d", exitCode); + return false; + } + + // Parse SSID from nmcli output + size_t ssidPos = nmcliOutput.find("SSID:"); + if (ssidPos == std::string::npos) { + NMLOG_ERROR("SSID not found in nmcli output"); + return false; + } + + size_t ssidStart = nmcliOutput.find_first_not_of(" \t", ssidPos + 5); + size_t ssidEnd = nmcliOutput.find_first_of("\n\r", ssidStart); + if (ssidStart == std::string::npos || ssidEnd == std::string::npos) { + NMLOG_ERROR("Failed to parse SSID from nmcli output"); + return false; + } + + ssid = nmcliOutput.substr(ssidStart, ssidEnd - ssidStart); + NMLOG_DEBUG("Parsed SSID from nmcli: %s", ssid.c_str()); + + // Construct connection file path + std::string connectionFile = "/etc/NetworkManager/system-connections/" + ssid + ".nmconnection"; + + // Try to open the connection file + std::ifstream file(connectionFile); + if (!file.is_open()) { + NMLOG_ERROR("Failed to open NetworkManager connection file: %s", connectionFile.c_str()); + return false; + } + + // Read entire file into string buffer - more efficient than line-by-line + std::string content((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + + // Find [wifi-security] section using string search + size_t sectionStart = content.find("[wifi-security]"); + if (sectionStart == std::string::npos) { + NMLOG_DEBUG("No [wifi-security] section found in connection file"); + file.close(); + return false; + } + + // Find the end of the wifi-security section (next section or end of file) + size_t sectionEnd = content.find("\n[", sectionStart + 15); // 15 = length of "[wifi-security]" + if (sectionEnd == std::string::npos) { + sectionEnd = content.length(); + } + + // Extract just the wifi-security section + std::string wifiSection = content.substr(sectionStart, sectionEnd - sectionStart); + + std::string keyMgmt; + + // Use regex or direct string search for key-mgmt + size_t keyMgmtPos = wifiSection.find("key-mgmt="); + if (keyMgmtPos != std::string::npos) { + size_t valueStart = keyMgmtPos + 9; // Skip "key-mgmt=" + size_t valueEnd = wifiSection.find_first_of("\r\n", valueStart); + if (valueEnd == std::string::npos) valueEnd = wifiSection.length(); + keyMgmt = wifiSection.substr(valueStart, valueEnd - valueStart); + NMLOG_DEBUG("Found key-mgmt: %s", keyMgmt.c_str()); + } + + // Use direct string search for psk + size_t pskPos = wifiSection.find("psk="); + if (pskPos != std::string::npos) { + size_t valueStart = pskPos + 4; // Skip "psk=" + size_t valueEnd = wifiSection.find_first_of("\r\n", valueStart); + if (valueEnd == std::string::npos) valueEnd = wifiSection.length(); + passphrase = wifiSection.substr(valueStart, valueEnd - valueStart); + NMLOG_DEBUG("Found psk in connection file"); + } + + file.close(); + + + // Map key management to security type + if (keyMgmt.empty()) { + security = NET_WIFI_SECURITY_NONE; + } else if (keyMgmt == "none") { + security = NET_WIFI_SECURITY_NONE; + } else if (keyMgmt == "wpa-psk") { + security = NET_WIFI_SECURITY_WPA2_PSK_AES; + } else if (keyMgmt == "sae") { + security = NET_WIFI_SECURITY_WPA3_SAE; + } else { + // Default to WPA PSK for unknown key management + security = NET_WIFI_SECURITY_WPA2_PSK_AES; + } + + NMLOG_DEBUG("Retrieved WiFi connection details - SSID: %s, Security: %d, Key-mgmt: %s", + ssid.c_str(), security, keyMgmt.c_str()); + return true; + } + + NetworkManagerMfrManager* NetworkManagerMfrManager::getInstance() + { + static NetworkManagerMfrManager instance; + return &instance; + } + + NetworkManagerMfrManager::NetworkManagerMfrManager() + { + // Initialize IARM connection + if (ensureIARMConnection()) { + NMLOG_DEBUG("NetworkManagerMfrManager initialized with IARM connection"); + } else { + NMLOG_ERROR("NetworkManagerMfrManager initialization failed - IARM connection error"); + } + } + + NetworkManagerMfrManager::~NetworkManagerMfrManager() + { + std::lock_guard lock(iarm_mutex); + if (iarm_initialized) { + iarm_initialized = false; + NMLOG_DEBUG("IARM Bus connection terminated"); + } + NMLOG_DEBUG("NetworkManagerMfrManager destroyed"); + } + + bool NetworkManagerMfrManager::saveWiFiSettingsToMfr() + { + // Launch asynchronous operation to save current WiFi connection details + std::thread saveThread([this]() { + std::string ssid, passphrase; + int security; + + if (!getCurrentWiFiConnectionDetails(ssid, passphrase, security)) { + NMLOG_ERROR("Failed to retrieve current WiFi connection details for MfrMgr save"); + return; + } + + NMLOG_INFO("Retrieved current WiFi connection details for MfrMgr save - SSID: %s, Security: %d", ssid.c_str(), security); + + // Save the retrieved details synchronously + bool result = this->saveWiFiSettingsToMfrSync(ssid, passphrase, security); + if (result) { + NMLOG_DEBUG("Background WiFi connection details retrieval and save completed successfully for SSID: %s", ssid.c_str()); + } else { + NMLOG_ERROR("Background WiFi connection details retrieval and save failed for SSID: %s", ssid.c_str()); + } + }); + + // Detach the thread to run independently + saveThread.detach(); + + NMLOG_DEBUG("WiFi connection details retrieval and save operation queued for background execution"); + return true; // Return immediately, actual retrieval and save happens asynchronously + } + + bool NetworkManagerMfrManager::saveWiFiSettingsToMfrSync(const std::string& ssid, const std::string& passphrase, int security) + { + int securityMode; + if (!ensureIARMConnection()) { + NMLOG_ERROR("IARM connection not available for saving WiFi settings"); + return false; + } + + NMLOG_INFO("Saving WiFi settings to MfrMgr via IARM - SSID: %s, Security: %d", ssid.c_str(), security); + + IARM_BUS_MFRLIB_API_WIFI_Credentials_Param_t param{0}; + IARM_BUS_MFRLIB_API_WIFI_Credentials_Param_t setParam{0}; + IARM_Result_t ret; + param.requestType = WIFI_GET_CREDENTIALS; + ret = IARM_Bus_Call(IARM_BUS_MFRLIB_NAME, IARM_BUS_MFRLIB_API_WIFI_Credentials, + (void*)¶m, sizeof(param)); + if(security == Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE) + securityMode = NET_WIFI_SECURITY_NONE; + else if(security == Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE) + securityMode = NET_WIFI_SECURITY_WPA3_SAE; + else + securityMode = NET_WIFI_SECURITY_WPA2_PSK_AES; + if (ret == IARM_RESULT_SUCCESS) + { + if ((strcmp (param.wifiCredentials.cSSID, ssid.c_str()) == 0) && + (strcmp (param.wifiCredentials.cPassword, passphrase.c_str()) == 0) && + (param.wifiCredentials.iSecurityMode == securityMode)) + { + NMLOG_INFO("Same ssid info not storing it stored ssid %s new ssid %s", param.wifiCredentials.cSSID, ssid.c_str()); + return true; + } + else + { + NMLOG_INFO("ssid info is different continue to store ssid %s new ssid %s", param.wifiCredentials.cSSID, ssid.c_str()); + } + } + + // Copy SSID + strncpy(setParam.wifiCredentials.cSSID, ssid.c_str(), sizeof(setParam.wifiCredentials.cSSID)); + + // Copy passphrase - only if not empty + if (!passphrase.empty()) { + strncpy(setParam.wifiCredentials.cPassword, passphrase.c_str(), sizeof(setParam.wifiCredentials.cPassword)); + NMLOG_DEBUG("WiFi passphrase set for MfrMgr save"); + } else { + param.wifiCredentials.cPassword[0] = '\0'; // Ensure empty string + NMLOG_DEBUG("Empty passphrase - setting empty string in MfrMgr"); + } + + setParam.wifiCredentials.iSecurityMode = securityMode; + + setParam.requestType = WIFI_SET_CREDENTIALS; + NMLOG_INFO(" Set Params param.requestType = %d, param.wifiCredentials.cSSID = %s, param.wifiCredentials.cPassword = %s, param.wifiCredentials.iSecurityMode = %d", setParam.requestType, setParam.wifiCredentials.cSSID, setParam.wifiCredentials.cPassword, setParam.wifiCredentials.iSecurityMode); + // Make IARM Bus call to save credentials + ret = IARM_Bus_Call(IARM_BUS_MFRLIB_NAME, IARM_BUS_MFRLIB_API_WIFI_Credentials, + (void*)&setParam, sizeof(setParam)); + if(ret == IARM_RESULT_SUCCESS) + { + memset(¶m,0,sizeof(param)); + param.requestType = WIFI_GET_CREDENTIALS; + ret = IARM_Bus_Call(IARM_BUS_MFRLIB_NAME, IARM_BUS_MFRLIB_API_WIFI_Credentials, (void*)¶m, sizeof(param)); + if(security == Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE) + securityMode = NET_WIFI_SECURITY_NONE; + else if(security == Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE) + securityMode = NET_WIFI_SECURITY_WPA3_SAE; + else + securityMode = NET_WIFI_SECURITY_WPA2_PSK_AES; + + if (ret == IARM_RESULT_SUCCESS) + { + if ((strcmp (param.wifiCredentials.cSSID, ssid.c_str()) == 0) && + (strcmp (param.wifiCredentials.cPassword, passphrase.c_str()) == 0) && + (param.wifiCredentials.iSecurityMode == securityMode)) + { + NMLOG_INFO("Successfully stored the credentails and verified stored ssid %s current ssid %s and security_mode %d", param.wifiCredentials.cSSID, ssid.c_str(), param.wifiCredentials.iSecurityMode); + return true; + } + else + { + NMLOG_INFO("failure in storing wifi credentials ssid %s", ssid.c_str()); + } + } + } + else + { + NMLOG_ERROR("IARM Bus call failed for WiFi credentials save: %d", ret); + return false; + } + + NMLOG_INFO("Successfully saved WiFi settings to MfrMgr via IARM - SSID: %s, Security: %d", ssid.c_str(), security); + return true; + } + + bool NetworkManagerMfrManager::clearWiFiSettingsFromMfr() + { + if (!ensureIARMConnection()) { + NMLOG_ERROR("IARM connection not available for clearing WiFi settings"); + return false; + } + + NMLOG_DEBUG("Clearing WiFi settings from MfrMgr via IARM"); + + // Make IARM Bus call to clear credentials + IARM_Result_t ret = IARM_Bus_Call(IARM_BUS_MFRLIB_NAME,IARM_BUS_MFRLIB_API_WIFI_EraseAllData,0,0); + if (ret != IARM_RESULT_SUCCESS) { + NMLOG_ERROR("IARM Bus call failed for WiFi credentials clear: %d", ret); + return false; + } + + NMLOG_INFO("Successfully cleared WiFi settings from MfrMgr via IARM"); + return true; + } + + } // namespace Plugin +} // namespace WPEFramework diff --git a/plugin/gnome/NetworkManagerGnomeMfrMgr.h b/plugin/gnome/NetworkManagerGnomeMfrMgr.h new file mode 100644 index 000000000..3bc8c422f --- /dev/null +++ b/plugin/gnome/NetworkManagerGnomeMfrMgr.h @@ -0,0 +1,66 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +#include + +typedef enum _SsidSecurity +{ + NET_WIFI_SECURITY_NONE = 0, + NET_WIFI_SECURITY_WEP_64, + NET_WIFI_SECURITY_WEP_128, + NET_WIFI_SECURITY_WPA_PSK_TKIP, + NET_WIFI_SECURITY_WPA_PSK_AES, + NET_WIFI_SECURITY_WPA2_PSK_TKIP, + NET_WIFI_SECURITY_WPA2_PSK_AES, + NET_WIFI_SECURITY_WPA_ENTERPRISE_TKIP, + NET_WIFI_SECURITY_WPA_ENTERPRISE_AES, + NET_WIFI_SECURITY_WPA2_ENTERPRISE_TKIP, + NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES, + NET_WIFI_SECURITY_WPA_WPA2_PSK, + NET_WIFI_SECURITY_WPA_WPA2_ENTERPRISE, + NET_WIFI_SECURITY_WPA3_PSK_AES, + NET_WIFI_SECURITY_WPA3_SAE, + NET_WIFI_SECURITY_NOT_SUPPORTED = 99, +} SsidSecurity; + +namespace WPEFramework +{ + namespace Plugin + { + class NetworkManagerMfrManager + { + public: + static NetworkManagerMfrManager* getInstance(); + bool saveWiFiSettingsToMfr(); + bool clearWiFiSettingsFromMfr(); + + private: + NetworkManagerMfrManager(); + ~NetworkManagerMfrManager(); + + // Disable copy constructor and assignment operator + NetworkManagerMfrManager(const NetworkManagerMfrManager&) = delete; + NetworkManagerMfrManager& operator=(const NetworkManagerMfrManager&) = delete; + + bool saveWiFiSettingsToMfrSync(const std::string& ssid, const std::string& passphrase, int security); + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 8bf8f137d..f842f9ed8 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -29,6 +29,9 @@ #include "NetworkManagerGnomeWIFI.h" #include "NetworkManagerGnomeUtils.h" #include "NetworkManagerImplementation.h" +#ifdef ENABLE_MIGRATION_MFRMGR_SUPPORT +#include "NetworkManagerGnomeMfrMgr.h" +#endif using namespace std; namespace WPEFramework @@ -335,6 +338,13 @@ namespace WPEFramework NMLOG_WARNING("no active access point!; wifi device state: (%d)", deviceState); deleteClientConnection(); +#ifdef ENABLE_MIGRATION_MFRMGR_SUPPORT + NetworkManagerMfrManager* mfrManager = NetworkManagerMfrManager::getInstance(); + if (mfrManager != nullptr) + { + mfrManager->clearWiFiSettingsFromMfr(); + } +#endif return true; } diff --git a/plugin/gnome/systemd/gnome-networkmanager-mfrmgr-migration.conf b/plugin/gnome/systemd/gnome-networkmanager-mfrmgr-migration.conf new file mode 100644 index 000000000..67b628c39 --- /dev/null +++ b/plugin/gnome/systemd/gnome-networkmanager-mfrmgr-migration.conf @@ -0,0 +1,2 @@ +[Unit] +After= iarmbusd.service mfrmgr.service diff --git a/tests/l2Test/libnm/CMakeLists.txt b/tests/l2Test/libnm/CMakeLists.txt index 057bf19a8..35a7e4e42 100644 --- a/tests/l2Test/libnm/CMakeLists.txt +++ b/tests/l2Test/libnm/CMakeLists.txt @@ -28,6 +28,7 @@ add_executable(${NM_LIBNM_PROXY_L2_TEST} ${CMAKE_SOURCE_DIR}/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp ${CMAKE_SOURCE_DIR}/tests/l2Test/libnm/l2_test_libnmproxy.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/Wraps.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/LibnmWraps.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/GLibWraps.cpp diff --git a/tests/mocks/mfrMgr.h b/tests/mocks/mfrMgr.h new file mode 100644 index 000000000..8934e1d8b --- /dev/null +++ b/tests/mocks/mfrMgr.h @@ -0,0 +1,62 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +#define SSID_SIZE 32 +#define WIFI_MAX_PASSWORD_LEN 64 + +#define IARM_BUS_MFRLIB_NAME "MFRLib" +#define IARM_BUS_MFRLIB_API_WIFI_Credentials "mfrWifiCredentials" +#define IARM_BUS_MFRLIB_API_WIFI_EraseAllData "mfrWifiEraseAllData" + +/** + * @brief WIFI API return status + * + */ +typedef enum _WIFI_API_RESULT { + WIFI_API_RESULT_SUCCESS = 0, ///< operation is successful + WIFI_API_RESULT_FAILED, ///< Operation general error. This enum is deprecated + WIFI_API_RESULT_NULL_PARAM, ///< NULL argument is passed to the module + WIFI_API_RESULT_INVALID_PARAM, ///< Invalid argument is passed to the module + WIFI_API_RESULT_NOT_INITIALIZED, ///< module not initialized + WIFI_API_RESULT_OPERATION_NOT_SUPPORTED, ///< operation not supported in the specific platform + WIFI_API_RESULT_READ_WRITE_FAILED, ///< flash read/write failed or crc check failed + WIFI_API_RESULT_MAX ///< Out of range - required to be the last item of the enum +} WIFI_API_RESULT; +/** + * @brief WIFI credentials data struct + * + */ +typedef struct { + char cSSID[SSID_SIZE+1]; ///< SSID field. + char cPassword[WIFI_MAX_PASSWORD_LEN+1]; ///< password field + int iSecurityMode; ///< security mode. Platform dependent and caller is responsible to validate it +} WIFI_DATA; + +typedef enum _WifiRequestType { + WIFI_GET_CREDENTIALS = 0, + WIFI_SET_CREDENTIALS = 1 +} WifiRequestType_t; + +typedef struct _IARM_BUS_MFRLIB_API_WIFI_Credentials_Param_t { + WIFI_DATA wifiCredentials; + WifiRequestType_t requestType; + WIFI_API_RESULT returnVal; +} IARM_BUS_MFRLIB_API_WIFI_Credentials_Param_t; From 221f464f4d92b423cd65ebb79b86cd5fa0b8f211 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 31 Oct 2025 13:46:18 -0400 Subject: [PATCH 200/271] Release of 1.6.0 Release of 1.6.0 --- CHANGELOG.md | 6 ++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ba101687..0cf9af898 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.6.0] - 2025-10-31 +### Added +- Integrated MfrMgr to persist WiFi Credential for DRI & Rollback to RDK-V Backend +- Implemented proper shutdown sequence for NetworkManager Plugin. +- Updated GDbus Support with all the latest fixes that went thro libnm backend + ## [1.5.0] - 2025-09-23 ### Changed - Implemented L1/L2 and Part L3 for the plugin diff --git a/CMakeLists.txt b/CMakeLists.txt index 02633a966..1ea85ed52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 5) +set(VERSION_MINOR 6) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 0ab9bc03e..7b819ffc1 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.5.0" + "version": "1.6.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 439e467ee..5764c645f 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.5.0** +**Version: 1.6.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.5.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.6.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 581630baf8cdea02ae50a1d58695eea5131395d5 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Tue, 11 Nov 2025 21:51:16 +0530 Subject: [PATCH 201/271] RDKEMW-9930: After reboot with WiFi toggle OFF, device fails to scan (#244) * RDKEMW-9930: After reboot with WiFi toggle OFF, device fails to scan Signed-off-by: Muhammed Rafi c --- plugin/gnome/NetworkManagerGnomeEvents.cpp | 32 ++++++++++++++-------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 39db2ca59..dea7c5ef9 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -335,9 +335,11 @@ namespace WPEFramework std::string ifname = nm_device_get_iface(device); if(ifname == nmUtils::wlanIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, nmUtils::wlanIface()); + NMLOG_INFO("WIFI device added: %s", ifname.c_str()); } else if(ifname == nmUtils::ethIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, nmUtils::ethIface()); + NMLOG_INFO("ETHERNET device added: %s", ifname.c_str()); } /* ip events added only for eth0 and wlan0 */ @@ -376,10 +378,12 @@ namespace WPEFramework if(ifname == nmUtils::wlanIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::wlanIface()); g_signal_handlers_disconnect_by_func(device, (gpointer)GnomeNetworkManagerEvents::deviceStateChangeCb, nmEvents); + NMLOG_INFO("WIFI device removed: %s", ifname.c_str()); } else if(ifname == nmUtils::ethIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::ethIface()); g_signal_handlers_disconnect_by_func(device, (gpointer)GnomeNetworkManagerEvents::deviceStateChangeCb, nmEvents); + NMLOG_INFO("ETHERNET device removed: %s", ifname.c_str()); } } @@ -445,35 +449,41 @@ namespace WPEFramework if((ifname == nmUtils::ethIface()) || (ifname == nmUtils::wlanIface())) { NMDeviceState devState = nm_device_get_state(device); - // NM_DEVICE_STATE_UNAVAILABLE can occur for an Ethernet interface when it is disconnected (e.g., no cable connected). - bool isDeviceEnabled = devState >= NM_DEVICE_STATE_UNAVAILABLE && devState <= NM_DEVICE_STATE_ACTIVATED; - if(!isDeviceEnabled) + + if(devState > NM_DEVICE_STATE_DISCONNECTED && devState <= NM_DEVICE_STATE_ACTIVATED) { - NMLOG_WARNING("device %s is not enabled, So no event monitor", ifname.c_str()); - continue; + // posting device state change event if interface already connected + GnomeNetworkManagerEvents::deviceStateChangeCb(device, nullptr, nullptr); } - GnomeNetworkManagerEvents::deviceStateChangeCb(device, nullptr, nullptr); //posting event if interface already connected + + /* Register device state change event */ g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(GnomeNetworkManagerEvents::deviceStateChangeCb), nmEvents); + if(NM_IS_DEVICE_WIFI(device)) { + nmEvents->wifiDevice = NM_DEVICE_WIFI(device); + g_signal_connect(nmEvents->wifiDevice, "notify::" NM_DEVICE_WIFI_LAST_SCAN, G_CALLBACK(GnomeNetworkManagerEvents::onAvailableSSIDsCb), nmEvents); + } + NMIPConfig *ipv4Config = nm_device_get_ip4_config(device); NMIPConfig *ipv6Config = nm_device_get_ip6_config(device); if (ipv4Config) { ip4ChangedCb(ipv4Config, NULL, device); // posting event if interface already connected g_signal_connect(ipv4Config, "notify::addresses", G_CALLBACK(ip4ChangedCb), device); } + else + NMLOG_WARNING("IPv4 config is null for device: %s, No IPv4 monitor", ifname.c_str()); if (ipv6Config) { ip6ChangedCb(ipv6Config, NULL, device); g_signal_connect(ipv6Config, "notify::addresses", G_CALLBACK(ip6ChangedCb), device); } - - if(NM_IS_DEVICE_WIFI(device)) { - nmEvents->wifiDevice = NM_DEVICE_WIFI(device); - g_signal_connect(nmEvents->wifiDevice, "notify::" NM_DEVICE_WIFI_LAST_SCAN, G_CALLBACK(GnomeNetworkManagerEvents::onAvailableSSIDsCb), nmEvents); - } + else + NMLOG_WARNING("IPv6 config is null for device: %s, No IPv6 monitor", ifname.c_str()); } else NMLOG_DEBUG("device type not eth/wifi %s", ifname.c_str()); } + else + NMLOG_WARNING("device error null"); } NMLOG_INFO("registered all networkmnager dbus events"); From 38254ef62b90bb4a64532b642f9345a22ee22dd1 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 13 Nov 2025 09:07:50 -0500 Subject: [PATCH 202/271] RDKEMW-9254 - Request MfrMgr to Persist WiFi Settings from NetworkManager Plugin (#251) Reason for change: To save the wifi credentials to MfrMgr when the wifi connection is successful and remove the same when removeKnownSSID is called So that when migrating from RDKE to RDKV we will have the wifi configuration to connect Test Procedure: CDL upgrade to RDKV from RDKE and check the wifi connection persist Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR --- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index f842f9ed8..5c5dba0ce 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -338,13 +338,6 @@ namespace WPEFramework NMLOG_WARNING("no active access point!; wifi device state: (%d)", deviceState); deleteClientConnection(); -#ifdef ENABLE_MIGRATION_MFRMGR_SUPPORT - NetworkManagerMfrManager* mfrManager = NetworkManagerMfrManager::getInstance(); - if (mfrManager != nullptr) - { - mfrManager->clearWiFiSettingsFromMfr(); - } -#endif return true; } @@ -1185,6 +1178,13 @@ namespace WPEFramework } deleteClientConnection(); +#ifdef ENABLE_MIGRATION_MFRMGR_SUPPORT + NetworkManagerMfrManager* mfrManager = NetworkManagerMfrManager::getInstance(); + if (mfrManager != nullptr) + { + mfrManager->clearWiFiSettingsFromMfr(); + } +#endif // ssid is specified and connection is not found return false // all other case return true, even if no wificonnection is found return((ssidSpecified && !connectionFound)? false : true); From d2477d90de78e0a41ff8074644079438e1e19f04 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 13 Nov 2025 16:18:54 -0500 Subject: [PATCH 203/271] RDKEMW-10336 : Update GetWiFiSignalQuality to use SIGNAL_POLL (#254) * RDKEMW-10336 - Update GetWiFiSignalQuality to use BSS SIGNAL_POLL Reason for change: Update GetWiFiSignalQuality to use SIGNAL_POLL instead of BSS Test Procedure: Check the GetWiFiSignalQuality curl command Priority:P1 Risks: Medium Signed-off-by: Muhammed Rafi C --- plugin/NetworkManagerImplementation.cpp | 126 +++++++++++++-------- tests/l2Test/rdk/l2_test_rdkproxy.cpp | 51 ++++----- tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp | 13 ++- 3 files changed, 109 insertions(+), 81 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 69b018bb2..7634038a3 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -26,7 +26,7 @@ using namespace NetworkManagerLogger; #define CIDR_NETMASK_IP_LEN 32 #define SSID_COMMAND "wpa_cli status" -#define BSS_COMMAND "wpa_cli bss" +#define SIGNAL_POLL_COMMAND "wpa_cli signal_poll" namespace WPEFramework { @@ -841,116 +841,152 @@ namespace WPEFramework /* The below implementation of GetWiFiSignalQuality is a temporary mitigation. Need to be revisited */ uint32_t NetworkManagerImplementation::GetWiFiSignalQuality(string& ssid /* @out */, string& strength /* @out */, string& noise /* @out */, string& snr /* @out */, WiFiSignalQuality& quality /* @out */) { - uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - int16_t readSnr = 0; - - std::string key, value; - int16_t readNoise = 0; - string bssid{}; + std::string key{}, value{}, bssid{}, band{}; char buff[512] = {'\0'}; - FILE *fp = NULL; - /* SSID */ + /* Get BSSID and SSID from wpa_cli status */ fp = popen(SSID_COMMAND, "r"); if (!fp) { - NMLOG_ERROR("Failed in getting output from command %s",SSID_COMMAND); - return Core::ERROR_RPC_CALL_FAILED; + NMLOG_ERROR("Failed in getting output from command %s", SSID_COMMAND); + return Core::ERROR_GENERAL; } - while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) { + + while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) + { std::istringstream mystream(buff); if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) { - if (key == "bssid") { + if (key == "ssid") { + ssid = value; + } + else if (key == "bssid") { bssid = value; - break; } + if (!ssid.empty() && !bssid.empty()) + break; } } pclose(fp); - /* Noise n RSSI */ - std::string bssCommand = std::string(BSS_COMMAND) + " " + bssid; - fp = popen(bssCommand.c_str(), "r"); + /* If BSSID is empty, WiFi is disconnected */ + if (bssid.empty()) { + NMLOG_WARNING("WiFi is disconnected (BSSID is empty)"); + quality = WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; + ssid = ""; + strength = "0"; + noise = "0"; + snr = "0"; + return Core::ERROR_NONE; + } + + /*Get real-time signal data from wpa_cli signal_poll */ + fp = popen(SIGNAL_POLL_COMMAND, "r"); if (!fp) { - NMLOG_ERROR("Failed in getting output from command %s",BSS_COMMAND); - return Core::ERROR_RPC_CALL_FAILED; + NMLOG_ERROR("Failed in getting output from command %s", SIGNAL_POLL_COMMAND); + return Core::ERROR_GENERAL; } + while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) { std::istringstream mystream(buff); if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) { - if (key == "level") { + if (key == "RSSI") { strength = value; } - else if (key == "noise") { + else if (key == "NOISE") { noise = value; } - else if (key == "ssid") { - ssid = value; + else if (key == "AVG_RSSI") { // if RSSI is not available + if (strength.empty()) + strength = value; } - else if (key == "snr") { - snr = value; + else if (key == "FREQUENCY") + { + if (!value.empty()) + { + int freq = std::stoi(value); + if (freq >= 2400 && freq < 5000) + band = "2.4GHz"; + else if (freq >= 5000 && freq < 6000) + band = "5GHz"; + else if (freq >= 6000) + band = "6GHz"; + else + band = "not known"; + } } - if (!strength.empty() && !noise.empty() && !ssid.empty() && !snr.empty()) - break; } } pclose(fp); - /* NOTE: The std::stoi() will throw exception if the string input is empty; so set to 0 */ if (noise.empty()) - noise= "0"; - if (snr.empty()) - snr = "0"; + noise = "0"; if (strength.empty()) strength = "0"; - readNoise = std::stoi(noise); - readSnr = std::stoi(snr); + int16_t readRssi = std::stoi(strength); + int16_t readNoise = std::stoi(noise); + + /* Check the RSSI is within range between -10 and -100 dbm*/ + if (readRssi >= 0 || readRssi < -100) { + NMLOG_WARNING("Received RSSI (%d dBm) is out of valid range (-10 to -100 dBm); Resetting to default", readRssi); + if (readRssi >= 0) { + readRssi = -10; + } + else if (readRssi < -100) { + readRssi = -100; + } + } /* Check the Noise is within range between 0 and -96 dbm*/ if((readNoise >= 0) || (readNoise < DEFAULT_NOISE)) { NMLOG_DEBUG("Received Noise (%d) from wifi driver is not valid; so clamping it", readNoise); if (readNoise >= 0) { + readNoise = 0; noise = std::to_string(0); } else if (readNoise < DEFAULT_NOISE) { + readNoise = DEFAULT_NOISE; noise = std::to_string(DEFAULT_NOISE); } } + /*Calculate SNR = RSSI - Noise */ + int16_t calculatedSnr = readRssi - readNoise; + snr = std::to_string(calculatedSnr); + /* mapping rssi value when the SNR value is not proper */ - if(!(readSnr > 0 && readSnr <= MAX_SNR_VALUE)) + if(!(calculatedSnr > 0 && calculatedSnr <= MAX_SNR_VALUE)) { - NMLOG_WARNING("Received SNR (%d) from wifi driver is not valid; Lets map with RSSI (%s)", readSnr, strength.c_str()); - readSnr = std::stoi(strength); + NMLOG_WARNING("calculated SNR (%d) is not valid; Lets map with RSSI (%s)", calculatedSnr, strength.c_str()); + calculatedSnr = std::stoi(strength); /* Take the absolute value */ - readSnr = (readSnr < 0) ? -readSnr : readSnr; + calculatedSnr = (calculatedSnr < 0) ? -calculatedSnr : calculatedSnr; - snr = std::to_string(readSnr); + snr = std::to_string(calculatedSnr); } - NMLOG_INFO("RSSI: %s dBm; Noise: %s dBm; SNR: %s dBm", strength.c_str(), noise.c_str(), snr.c_str()); + NMLOG_INFO("ssid=%s, bssid=%s, band=%s, rssi=%s, noise=%s, snr=%s", ssid.c_str(), bssid.c_str(), band.c_str(), strength.c_str(), noise.c_str(), snr.c_str()); - if (readSnr == 0) + if (calculatedSnr == 0) { quality = WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; strength = "0"; } - else if (readSnr > 0 && readSnr < NM_WIFI_SNR_THRESHOLD_FAIR) + else if (calculatedSnr > 0 && calculatedSnr < NM_WIFI_SNR_THRESHOLD_FAIR) { quality = WiFiSignalQuality::WIFI_SIGNAL_WEAK; } - else if (readSnr > NM_WIFI_SNR_THRESHOLD_FAIR && readSnr < NM_WIFI_SNR_THRESHOLD_GOOD) + else if (calculatedSnr >= NM_WIFI_SNR_THRESHOLD_FAIR && calculatedSnr < NM_WIFI_SNR_THRESHOLD_GOOD) { quality = WiFiSignalQuality::WIFI_SIGNAL_FAIR; } - else if (readSnr > NM_WIFI_SNR_THRESHOLD_GOOD && readSnr < NM_WIFI_SNR_THRESHOLD_EXCELLENT) + else if (calculatedSnr >= NM_WIFI_SNR_THRESHOLD_GOOD && calculatedSnr < NM_WIFI_SNR_THRESHOLD_EXCELLENT) { quality = WiFiSignalQuality::WIFI_SIGNAL_GOOD; } @@ -959,9 +995,7 @@ namespace WPEFramework quality = WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT; } - rc = Core::ERROR_NONE; - - return rc; + return Core::ERROR_NONE; } void NetworkManagerImplementation::processMonitor(uint16_t interval) diff --git a/tests/l2Test/rdk/l2_test_rdkproxy.cpp b/tests/l2Test/rdk/l2_test_rdkproxy.cpp index a0845dbfc..d1b97ca9e 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxy.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxy.cpp @@ -1313,7 +1313,7 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityWpa_cliFailed) TEST_F(NetworkManagerTest, GetWiFiSignalQualityDisconnected2) { EXPECT_CALL(*p_wrapsImplMock, popen(::testing::_, ::testing::_)) - .Times(2) + .Times(1) .WillOnce(::testing::Invoke( [&](const char* command, const char* type) -> FILE* { EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli status")); @@ -1328,16 +1328,6 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityDisconnected2) rewind(tempFile); } return tempFile; - })) - .WillOnce(::testing::Invoke( - [&](const char* command, const char* type) -> FILE* { - EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli bss ")); - FILE* tempFile = tmpfile(); - if (tempFile) { - fputs("driver error", tempFile); - rewind(tempFile); - } - return tempFile; })); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); @@ -1364,21 +1354,22 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnected) })) .WillOnce(::testing::Invoke( [&](const char* command, const char* type) -> FILE* { - EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli bss aa:bb:cc:dd:ee:ff")); + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli signal_poll")); FILE* tempFile = tmpfile(); if (tempFile) { fputs("Selected interface 'wlan0'\n" - "ssid=dummySSID\n" - "noise=-117\n" - "level=-49\n" - "snr=65\n", tempFile); + "RSSI=-30\n" + "LINKSPEED=300\n" + "NOISE=-114\n" + "FREQUENCY=2417\n" + "AVG_RSSI=-30\n", tempFile); rewind(tempFile); } return tempFile; })); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Excellent\",\"snr\":\"65\",\"strength\":\"-49\",\"noise\":\"-96\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Excellent\",\"snr\":\"66\",\"strength\":\"-30\",\"noise\":\"-96\",\"success\":true}")); } TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedGood) @@ -1401,21 +1392,22 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedGood) })) .WillOnce(::testing::Invoke( [&](const char* command, const char* type) -> FILE* { - EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli bss aa:bb:cc:dd:ee:ff")); + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli signal_poll")); FILE* tempFile = tmpfile(); if (tempFile) { fputs("Selected interface 'wlan0'\n" - "ssid=dummySSID\n" - "noise=-30\n" - "level=-90\n" - "snr=33\n", tempFile); + "RSSI=\n" + "LINKSPEED=300\n" + "NOISE=-114\n" + "FREQUENCY=2417\n" + "AVG_RSSI=-90\n", tempFile); rewind(tempFile); } return tempFile; })); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Good\",\"snr\":\"33\",\"strength\":\"-90\",\"noise\":\"-30\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Weak\",\"snr\":\"6\",\"strength\":\"-90\",\"noise\":\"-96\",\"success\":true}")); } TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedLowBad) @@ -1438,21 +1430,22 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedLowBad) })) .WillOnce(::testing::Invoke( [&](const char* command, const char* type) -> FILE* { - EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli bss aa:bb:cc:dd:ee:ff")); + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli signal_poll")); FILE* tempFile = tmpfile(); if (tempFile) { fputs("Selected interface 'wlan0'\n" - "ssid=dummySSID\n" - "noise=9999\n" - "level=-120\n" - "snr=33\n", tempFile); + "RSSI=\n" + "LINKSPEED=300\n" + "NOISE=9999\n" + "FREQUENCY=5462\n" + "AVG_RSSI=-120\n", tempFile); rewind(tempFile); } return tempFile; })); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Good\",\"snr\":\"33\",\"strength\":\"-120\",\"noise\":\"0\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Excellent\",\"snr\":\"120\",\"strength\":\"-120\",\"noise\":\"0\",\"success\":true}")); } TEST_F(NetworkManagerTest, Trace_Success_ipv4) diff --git a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp index 1b174a0bb..89be4686f 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp @@ -293,7 +293,7 @@ TEST_F(NetworkManagerEventTest, onWiFiStateChange) if (tempFile) { fputs("Selected interface 'wlan0'\n" "bssid=aa:bb:cc:dd:ee:ff\n" - "freq=5462\n" + "freq=2462\n" "ssid=dummySSID\n", tempFile); rewind(tempFile); } @@ -301,14 +301,15 @@ TEST_F(NetworkManagerEventTest, onWiFiStateChange) })) .WillOnce(::testing::Invoke( [&](const char* command, const char* type) -> FILE* { - EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli bss aa:bb:cc:dd:ee:ff")); + EXPECT_THAT(string(command), ::testing::MatchesRegex("wpa_cli signal_poll")); FILE* tempFile = tmpfile(); if (tempFile) { fputs("Selected interface 'wlan0'\n" - "ssid=dummySSID\n" - "noise=-114\n" - "level=-90\n" - "snr=33\n", tempFile); + "RSSI=-30\n" + "LINKSPEED=300\n" + "NOISE=-114\n" + "FREQUENCY=2417\n" + "AVG_RSSI=-30\n", tempFile); rewind(tempFile); } return tempFile; From 19c4ee07cf3b74c91a7faa4baa5f4d471db8ad74 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Thu, 13 Nov 2025 16:30:20 -0500 Subject: [PATCH 204/271] Release of 1.7.0 Release of 1.7.0 --- CHANGELOG.md | 6 ++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cf9af898..d35758df7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.7.0] - 2025-11-13 +### Fixed +- Fixed bug MfrMgr Integration +- Subscribed to WiFi Events even when the device boots with wifi disabled +- Fixed the WiFi signal monitoring as the reporred RSSI was stale data + ## [1.6.0] - 2025-10-31 ### Added - Integrated MfrMgr to persist WiFi Credential for DRI & Rollback to RDK-V Backend diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ea85ed52..ad7109ffa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 6) +set(VERSION_MINOR 7) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 7b819ffc1..bec40206b 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.6.0" + "version": "1.7.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 5764c645f..74329490f 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.6.0** +**Version: 1.7.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.6.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.7.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 7c9afc71c6a8350bf01e10bd43eea4779a47226a Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:08:21 -0500 Subject: [PATCH 205/271] RDKEMW-10529 : Do not Print Personal information about WIFI (#255) Reason for change: Removed printing of wifi password from mfr migration changes Test Procedure: Check the log for wifi credentials Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR --- plugin/gnome/NetworkManagerGnomeMfrMgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/gnome/NetworkManagerGnomeMfrMgr.cpp b/plugin/gnome/NetworkManagerGnomeMfrMgr.cpp index b9e5cc29b..0a2d0d200 100644 --- a/plugin/gnome/NetworkManagerGnomeMfrMgr.cpp +++ b/plugin/gnome/NetworkManagerGnomeMfrMgr.cpp @@ -282,7 +282,7 @@ namespace WPEFramework setParam.wifiCredentials.iSecurityMode = securityMode; setParam.requestType = WIFI_SET_CREDENTIALS; - NMLOG_INFO(" Set Params param.requestType = %d, param.wifiCredentials.cSSID = %s, param.wifiCredentials.cPassword = %s, param.wifiCredentials.iSecurityMode = %d", setParam.requestType, setParam.wifiCredentials.cSSID, setParam.wifiCredentials.cPassword, setParam.wifiCredentials.iSecurityMode); + NMLOG_INFO(" Set Params param.requestType = %d, param.wifiCredentials.cSSID = %s, param.wifiCredentials.iSecurityMode = %d", setParam.requestType, setParam.wifiCredentials.cSSID, setParam.wifiCredentials.iSecurityMode); // Make IARM Bus call to save credentials ret = IARM_Bus_Call(IARM_BUS_MFRLIB_NAME, IARM_BUS_MFRLIB_API_WIFI_Credentials, (void*)&setParam, sizeof(setParam)); From 60517027ac78237d2ce21ba020b5756af67ccc0a Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 14 Nov 2025 14:11:27 -0500 Subject: [PATCH 206/271] Release of 1.8.0 Release of 1.8.0 --- CHANGELOG.md | 4 ++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d35758df7..9354b7c9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.8.0] - 2025-11-14 +### Fixed +- Removed logging of WiFi PII information + ## [1.7.0] - 2025-11-13 ### Fixed - Fixed bug MfrMgr Integration diff --git a/CMakeLists.txt b/CMakeLists.txt index ad7109ffa..9f8e3e91f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 7) +set(VERSION_MINOR 8) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index bec40206b..b3e40bcb8 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.7.0" + "version": "1.8.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 74329490f..17eb8d9b6 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.7.0** +**Version: 1.8.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.7.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.8.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 76ccca51913c540c833fc09022120f2f5c8ad990 Mon Sep 17 00:00:00 2001 From: DevikaJaladi <155776845+DevikaJaladi@users.noreply.github.com> Date: Wed, 19 Nov 2025 10:39:42 -0500 Subject: [PATCH 207/271] RDKEMW-10660: Adding T1 logging for ap_info_split details (#258) Reason for change: Added temporary log line for T1 to get ap_info details Test Procedure: Run grep for "bssid=" in wpeframework.log and check format should be "bssid=7a:9c:8e:13:7c:ac,ssid=Modukuru7205,rssi=-49,phyrate=1200,noise=-114,Band=5GHz" Priority:P1 Risks: Medium --- plugin/NetworkManagerImplementation.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 7634038a3..ef3165a47 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -889,6 +889,7 @@ namespace WPEFramework return Core::ERROR_GENERAL; } + std::string linkSpeed; while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) { std::istringstream mystream(buff); @@ -918,6 +919,10 @@ namespace WPEFramework else band = "not known"; } + } + else if (key == "LINKSPEED") + { + linkSpeed = value; } } } @@ -971,7 +976,8 @@ namespace WPEFramework snr = std::to_string(calculatedSnr); } - NMLOG_INFO("ssid=%s, bssid=%s, band=%s, rssi=%s, noise=%s, snr=%s", ssid.c_str(), bssid.c_str(), band.c_str(), strength.c_str(), noise.c_str(), snr.c_str()); + NMLOG_INFO("SSID:%s, BSSID:%s, Band:%s, RSSI:%s, Noise:%s, SNR:%s", ssid.c_str(), bssid.c_str(), band.c_str(), strength.c_str(), noise.c_str(), snr.c_str()); + NMLOG_INFO("bssid=%s,ssid=%s,rssi=%s,phyrate=%s,noise=%s,Band=%s", bssid.c_str(), ssid.c_str(), strength.c_str(), linkSpeed.c_str(), noise.c_str(), band.c_str()); if (calculatedSnr == 0) { From 8c6ec3e7844751af886a19a1c2a8152d221ddb0c Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 21 Nov 2025 11:27:11 -0500 Subject: [PATCH 208/271] Release of 1.9.0 Release of 1.9.0 --- CHANGELOG.md | 4 ++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 4 ++-- docs/NetworkManagerPlugin.md | 10 +++++----- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9354b7c9c..191f03f8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.9.0] - 2025-11-21 +### Added +- Added shortterm solution to print the AP Info + ## [1.8.0] - 2025-11-14 ### Fixed - Removed logging of WiFi PII information diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f8e3e91f..078d7f659 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 8) +set(VERSION_MINOR 9) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index b3e40bcb8..cb42e31a0 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.8.0" + "version": "1.9.0" }, "definitions": { "success": { @@ -135,7 +135,7 @@ "noise":{ "summary": "The WiFi Signal Noise detected in dBm", "type": "string", - "example": "-106" + "example": "-96" }, "snr":{ "summary": "Signal to Noise Ratio(SNR) in dBm", diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 17eb8d9b6..961a86ad3 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.8.0** +**Version: 1.9.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.8.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.9.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity @@ -1398,7 +1398,7 @@ This method takes no parameters. "strength": "-32", "frequency": "2.4420", "rate": "144", - "noise": "-106", + "noise": "-96", "success": true } } @@ -1552,7 +1552,7 @@ This method takes no parameters. "quality": "Excellent", "snr": "74", "strength": "-32", - "noise": "-106", + "noise": "-96", "success": true } } @@ -1947,7 +1947,7 @@ Triggered when WIFI Signal quality changed which is decided based on SNR value w "quality": "Excellent", "snr": "74", "strength": "-32", - "noise": "-106" + "noise": "-96" } } ``` From 4836c89059c4585b0138dd9cb517181079d4b66b Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 28 Nov 2025 12:56:29 -0500 Subject: [PATCH 209/271] RDKEMW-9249 - Request MfrMgr to Persist WiFi Settings from NetworkManager Plugin (#260) * RDKEMW-9249 - Request MfrMgr to Persist WiFi Settings from NetworkManager Plugin Reason for change: To save the wifi credentials to MfrMgr when the wifi connection is successful and remove the same when removeKnownSSID is called So that when migrating from RDKE to RDKV we will have the wifi configuration to connect. This checkin as the implementation to use gdbus call instead of popen to retrieve the SSID Test Procedure: CDL upgrade to RDKV from RDKE and check the wifi connection persist Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR * RDKEMW-9249 - Request MfrMgr to Persist WiFi Settings from NetworkManager Plugin Reason for change: To save the wifi credentials to MfrMgr when the wifi connection is successful and remove the same when removeKnownSSID is called So that when migrating from RDKE to RDKV we will have the wifi configuration to connect. This checkin as the implementation to use gdbus call instead of popen to retrieve the SSID Test Procedure: CDL upgrade to RDKV from RDKE and check the wifi connection persist Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR --------- Signed-off-by: Gururaaja ESR Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- plugin/CMakeLists.txt | 2 + plugin/gnome/NetworkManagerGnomeMfrMgr.cpp | 353 +++++++++++++++------ 2 files changed, 254 insertions(+), 101 deletions(-) diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index bd50eef66..a24b6bf64 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -104,6 +104,8 @@ if(ENABLE_GNOME_NETWORKMANAGER) if(ENABLE_MIGRATION_MFRMGR_SUPPORT) target_sources(${MODULE_IMPL_NAME} PRIVATE gnome/NetworkManagerGnomeMfrMgr.cpp + gnome/gdbus/NetworkManagerGdbusMgr.cpp + gnome/gdbus/NetworkManagerGdbusUtils.cpp ) endif() if(ENABLE_MIGRATION_MFRMGR_SUPPORT) diff --git a/plugin/gnome/NetworkManagerGnomeMfrMgr.cpp b/plugin/gnome/NetworkManagerGnomeMfrMgr.cpp index 0a2d0d200..12a4368d3 100644 --- a/plugin/gnome/NetworkManagerGnomeMfrMgr.cpp +++ b/plugin/gnome/NetworkManagerGnomeMfrMgr.cpp @@ -21,10 +21,14 @@ #include "NetworkManagerLogger.h" #include "NetworkManagerImplementation.h" #include "INetworkManager.h" +#include "NetworkManagerGnomeUtils.h" +#include "gdbus/NetworkManagerGdbusMgr.h" +#include "gdbus/NetworkManagerGdbusUtils.h" #include "mfrMgr.h" #include #include +#include #include "libIBus.h" namespace WPEFramework @@ -39,139 +43,286 @@ namespace WPEFramework static bool ensureIARMConnection() { std::lock_guard lock(iarm_mutex); - + if (!iarm_initialized) { IARM_Result_t ret = IARM_Bus_Init("NetworkMfrMgr"); if (ret != IARM_RESULT_SUCCESS) { NMLOG_ERROR("IARM_Bus_Init failed: %d", ret); return false; } - + ret = IARM_Bus_Connect(); if (ret != IARM_RESULT_SUCCESS) { NMLOG_ERROR("IARM_Bus_Connect failed: %d", ret); return false; } - + iarm_initialized = true; NMLOG_DEBUG("IARM Bus connection established for MfrMgr"); } return true; } - // Helper function to retrieve current WiFi connection details using nmcli and connection files + // Helper function to retrieve current WiFi connection details using GDBus utilities static bool getCurrentWiFiConnectionDetails(std::string& ssid, std::string& passphrase, int& security) { - // Use nmcli to get current WiFi connection info - FILE* pipe = popen("nmcli device wifi show-password 2>/dev/null", "r"); - if (!pipe) { - NMLOG_ERROR("Failed to execute nmcli command"); + GError *error = NULL; + GDBusProxy *connection_proxy = NULL; + GDBusProxy *device_proxy = NULL; + bool result = false; + + NMLOG_DEBUG("Retrieving WiFi connection details using GDBus utilities"); + + // Create DbusMgr instance for proxy management + DbusMgr dbusMgr; + + // Get WiFi device information using existing utility + deviceInfo devInfo; + if (!GnomeUtils::getDeviceInfoByIfname(dbusMgr, nmUtils::wlanIface(), devInfo)) { + NMLOG_ERROR("WiFi device '%s' not found", nmUtils::wlanIface()); return false; } - char buffer[1024]; - std::string nmcliOutput; - - // Read nmcli output - while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { - nmcliOutput += buffer; - } - - int exitCode = pclose(pipe); - if (exitCode != 0) { - NMLOG_ERROR("nmcli command failed with exit code: %d", exitCode); + NMLOG_DEBUG("Found WiFi device at path: %s", devInfo.path.c_str()); + + // Create device proxy to check state and refresh ActiveConnection property + device_proxy = dbusMgr.getNetworkManagerDeviceProxy(devInfo.path.c_str()); + if (!device_proxy) { + NMLOG_ERROR("Failed to create device proxy"); return false; } - // Parse SSID from nmcli output - size_t ssidPos = nmcliOutput.find("SSID:"); - if (ssidPos == std::string::npos) { - NMLOG_ERROR("SSID not found in nmcli output"); + // Check device state first + GVariant *state_variant = g_dbus_proxy_get_cached_property(device_proxy, "State"); + if (state_variant) { + guint32 device_state = g_variant_get_uint32(state_variant); + NMLOG_DEBUG("WiFi device state: %u (100=activated, 30=disconnected)", device_state); + g_variant_unref(state_variant); + + // NM_DEVICE_STATE_ACTIVATED = 100 + if (device_state != NM_DEVICE_STATE_ACTIVATED) { + NMLOG_WARNING("WiFi device not in activated state (state=%u)", device_state); + } + } + + // Force refresh ActiveConnection property from D-Bus instead of using cached value + std::string active_conn_path; + error = NULL; + GVariant *props_variant = g_dbus_proxy_call_sync(device_proxy, + "org.freedesktop.DBus.Properties.Get", + g_variant_new("(ss)", + "org.freedesktop.NetworkManager.Device", + "ActiveConnection"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (!props_variant) { + NMLOG_ERROR("Failed to get ActiveConnection property: %s", error ? error->message : "unknown"); + if (error) g_error_free(error); + g_object_unref(device_proxy); return false; } - - size_t ssidStart = nmcliOutput.find_first_not_of(" \t", ssidPos + 5); - size_t ssidEnd = nmcliOutput.find_first_of("\n\r", ssidStart); - if (ssidStart == std::string::npos || ssidEnd == std::string::npos) { - NMLOG_ERROR("Failed to parse SSID from nmcli output"); + + GVariant *active_conn_variant = NULL; + g_variant_get(props_variant, "(v)", &active_conn_variant); + + if (!active_conn_variant) { + NMLOG_ERROR("ActiveConnection property variant is NULL"); + g_variant_unref(props_variant); + g_object_unref(device_proxy); return false; } - - ssid = nmcliOutput.substr(ssidStart, ssidEnd - ssidStart); - NMLOG_DEBUG("Parsed SSID from nmcli: %s", ssid.c_str()); - // Construct connection file path - std::string connectionFile = "/etc/NetworkManager/system-connections/" + ssid + ".nmconnection"; + const gchar *active_conn_path_str = g_variant_get_string(active_conn_variant, NULL); - // Try to open the connection file - std::ifstream file(connectionFile); - if (!file.is_open()) { - NMLOG_ERROR("Failed to open NetworkManager connection file: %s", connectionFile.c_str()); + if (active_conn_path_str) { + active_conn_path = active_conn_path_str; + } + + g_variant_unref(active_conn_variant); + g_variant_unref(props_variant); + g_object_unref(device_proxy); + + NMLOG_DEBUG("ActiveConnection path: %s", active_conn_path.c_str()); + + // Check if device has an active connection + if (active_conn_path.empty() || active_conn_path == "/") { + NMLOG_ERROR("No active connection on WiFi device (path: %s)", active_conn_path.c_str()); return false; } - // Read entire file into string buffer - more efficient than line-by-line - std::string content((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + // Create active connection proxy using DbusMgr + GDBusProxy *active_conn_proxy = dbusMgr.getNetworkManagerActiveConnProxy(active_conn_path.c_str()); + if (!active_conn_proxy) { + NMLOG_ERROR("Failed to create active connection proxy"); + return false; + } - // Find [wifi-security] section using string search - size_t sectionStart = content.find("[wifi-security]"); - if (sectionStart == std::string::npos) { - NMLOG_DEBUG("No [wifi-security] section found in connection file"); - file.close(); + // Get connection path from active connection + GVariant *conn_path_variant = g_dbus_proxy_get_cached_property(active_conn_proxy, "Connection"); + if (!conn_path_variant) { + NMLOG_ERROR("Failed to get connection path from active connection"); + g_object_unref(active_conn_proxy); return false; } - - // Find the end of the wifi-security section (next section or end of file) - size_t sectionEnd = content.find("\n[", sectionStart + 15); // 15 = length of "[wifi-security]" - if (sectionEnd == std::string::npos) { - sectionEnd = content.length(); + + const gchar *connection_path = g_variant_get_string(conn_path_variant, NULL); + if (connection_path == NULL) { + NMLOG_ERROR("Connection path variant did not contain a valid string"); + g_variant_unref(conn_path_variant); + g_object_unref(active_conn_proxy); + return false; } + NMLOG_DEBUG("Connection settings path: %s", connection_path); - // Extract just the wifi-security section - std::string wifiSection = content.substr(sectionStart, sectionEnd - sectionStart); + // Create connection proxy using DbusMgr + connection_proxy = dbusMgr.getNetworkManagerSettingsConnectionProxy(connection_path); + g_variant_unref(conn_path_variant); + g_object_unref(active_conn_proxy); - std::string keyMgmt; + if (!connection_proxy) { + NMLOG_ERROR("Failed to create connection proxy"); + return false; + } - // Use regex or direct string search for key-mgmt - size_t keyMgmtPos = wifiSection.find("key-mgmt="); - if (keyMgmtPos != std::string::npos) { - size_t valueStart = keyMgmtPos + 9; // Skip "key-mgmt=" - size_t valueEnd = wifiSection.find_first_of("\r\n", valueStart); - if (valueEnd == std::string::npos) valueEnd = wifiSection.length(); - keyMgmt = wifiSection.substr(valueStart, valueEnd - valueStart); - NMLOG_DEBUG("Found key-mgmt: %s", keyMgmt.c_str()); + // Get connection settings (without secrets) + GVariant *settings_variant = g_dbus_proxy_call_sync(connection_proxy, + "GetSettings", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (!settings_variant) { + NMLOG_ERROR("Failed to get connection settings: %s", error ? error->message : "unknown"); + if (error) g_error_free(error); + g_object_unref(connection_proxy); + return false; } - // Use direct string search for psk - size_t pskPos = wifiSection.find("psk="); - if (pskPos != std::string::npos) { - size_t valueStart = pskPos + 4; // Skip "psk=" - size_t valueEnd = wifiSection.find_first_of("\r\n", valueStart); - if (valueEnd == std::string::npos) valueEnd = wifiSection.length(); - passphrase = wifiSection.substr(valueStart, valueEnd - valueStart); - NMLOG_DEBUG("Found psk in connection file"); + // Parse settings to get SSID and security type + GVariantIter *settings_iter; + g_variant_get(settings_variant, "(a{sa{sv}})", &settings_iter); + + gchar *setting_name; + GVariant *setting_dict; + security = NET_WIFI_SECURITY_NONE; + bool has_wireless_security = false; + + while (g_variant_iter_loop(settings_iter, "{s@a{sv}}", &setting_name, &setting_dict)) { + if (g_strcmp0(setting_name, "802-11-wireless") == 0) { + // Extract SSID + GVariant *ssid_variant = g_variant_lookup_value(setting_dict, "ssid", G_VARIANT_TYPE_BYTESTRING); + if (ssid_variant) { + gsize ssid_len; + const guint8 *ssid_data = static_cast(g_variant_get_fixed_array(ssid_variant, &ssid_len, sizeof(guint8))); + ssid = std::string(reinterpret_cast(ssid_data), ssid_len); + NMLOG_DEBUG("Retrieved SSID: %s", ssid.c_str()); + g_variant_unref(ssid_variant); + } + } else if (g_strcmp0(setting_name, "802-11-wireless-security") == 0) { + has_wireless_security = true; + // Extract key-mgmt + GVariant *key_mgmt_variant = g_variant_lookup_value(setting_dict, "key-mgmt", G_VARIANT_TYPE_STRING); + if (key_mgmt_variant) { + const gchar *key_mgmt = g_variant_get_string(key_mgmt_variant, NULL); + NMLOG_DEBUG("Key management: %s", key_mgmt); + + if (g_strcmp0(key_mgmt, "sae") == 0) { + security = NET_WIFI_SECURITY_WPA3_SAE; + } else if (g_strcmp0(key_mgmt, "wpa-psk") == 0) { + security = NET_WIFI_SECURITY_WPA2_PSK_AES; + } else if (g_strcmp0(key_mgmt, "wpa-eap") == 0) { + security = NET_WIFI_SECURITY_WPA2_ENTERPRISE_AES; + } else if (g_strcmp0(key_mgmt, "none") == 0) { + security = NET_WIFI_SECURITY_NONE; + } else { + security = NET_WIFI_SECURITY_WPA2_PSK_AES; + } + + g_variant_unref(key_mgmt_variant); + } + } } - file.close(); + g_variant_iter_free(settings_iter); + g_variant_unref(settings_variant); + + // Request secrets if PSK-based security + if (has_wireless_security && (security == NET_WIFI_SECURITY_WPA2_PSK_AES || security == NET_WIFI_SECURITY_WPA3_SAE)) { + NMLOG_DEBUG("Requesting secrets for PSK-based connection"); + + // Use synchronous call instead of async to avoid cancellation complexity + error = NULL; + GVariant *secrets = g_dbus_proxy_call_sync(connection_proxy, + "GetSecrets", + g_variant_new("(s)", "802-11-wireless-security"), + G_DBUS_CALL_FLAGS_NONE, + 5000, // 5 second timeout + NULL, + &error); + + if (error) { + NMLOG_WARNING("Failed to get secrets: %s", error->message); + g_error_free(error); + result = false; + } else if (secrets) { + // Parse the returned secrets + // GetSecrets returns (a{sa{sv}}) - dict of dicts + GVariantIter *iter; + g_variant_get(secrets, "(a{sa{sv}})", &iter); + + gchar *setting_name_key; + GVariant *setting_dict_value; + bool found_psk = false; + // Iterate through settings + while (g_variant_iter_loop(iter, "{s@a{sv}}", &setting_name_key, &setting_dict_value)) { + if (g_strcmp0(setting_name_key, "802-11-wireless-security") == 0) { + // Found wireless security settings + GVariantIter *setting_iter; + g_variant_get(setting_dict_value, "a{sv}", &setting_iter); - // Map key management to security type - if (keyMgmt.empty()) { - security = NET_WIFI_SECURITY_NONE; - } else if (keyMgmt == "none") { - security = NET_WIFI_SECURITY_NONE; - } else if (keyMgmt == "wpa-psk") { - security = NET_WIFI_SECURITY_WPA2_PSK_AES; - } else if (keyMgmt == "sae") { - security = NET_WIFI_SECURITY_WPA3_SAE; + gchar *key; + GVariant *value; + + // Look for psk key + while (g_variant_iter_loop(setting_iter, "{sv}", &key, &value)) { + if (g_strcmp0(key, "psk") == 0) { + const gchar *psk = g_variant_get_string(value, NULL); + if (psk) { + passphrase = psk; + NMLOG_DEBUG("Successfully retrieved PSK"); + found_psk = true; + } + break; + } + } + g_variant_iter_free(setting_iter); + break; + } + } + + g_variant_iter_free(iter); + g_variant_unref(secrets); + result = found_psk; + } else { + NMLOG_WARNING("GetSecrets returned NULL"); + result = false; + } } else { - // Default to WPA PSK for unknown key management - security = NET_WIFI_SECURITY_WPA2_PSK_AES; + // No secrets needed for open networks + result = true; } - NMLOG_DEBUG("Retrieved WiFi connection details - SSID: %s, Security: %d, Key-mgmt: %s", - ssid.c_str(), security, keyMgmt.c_str()); - return true; + // Cleanup + g_object_unref(connection_proxy); + + NMLOG_INFO("Retrieved WiFi connection details - SSID: %s, Security: %d, Has Passphrase: %s", + ssid.c_str(), security, passphrase.empty() ? "no" : "yes"); + + return result && !ssid.empty(); } NetworkManagerMfrManager* NetworkManagerMfrManager::getInstance() @@ -206,14 +357,14 @@ namespace WPEFramework std::thread saveThread([this]() { std::string ssid, passphrase; int security; - + if (!getCurrentWiFiConnectionDetails(ssid, passphrase, security)) { NMLOG_ERROR("Failed to retrieve current WiFi connection details for MfrMgr save"); return; } - + NMLOG_INFO("Retrieved current WiFi connection details for MfrMgr save - SSID: %s, Security: %d", ssid.c_str(), security); - + // Save the retrieved details synchronously bool result = this->saveWiFiSettingsToMfrSync(ssid, passphrase, security); if (result) { @@ -222,10 +373,10 @@ namespace WPEFramework NMLOG_ERROR("Background WiFi connection details retrieval and save failed for SSID: %s", ssid.c_str()); } }); - + // Detach the thread to run independently saveThread.detach(); - + NMLOG_DEBUG("WiFi connection details retrieval and save operation queued for background execution"); return true; // Return immediately, actual retrieval and save happens asynchronously } @@ -237,15 +388,15 @@ namespace WPEFramework NMLOG_ERROR("IARM connection not available for saving WiFi settings"); return false; } - + NMLOG_INFO("Saving WiFi settings to MfrMgr via IARM - SSID: %s, Security: %d", ssid.c_str(), security); - + IARM_BUS_MFRLIB_API_WIFI_Credentials_Param_t param{0}; IARM_BUS_MFRLIB_API_WIFI_Credentials_Param_t setParam{0}; IARM_Result_t ret; param.requestType = WIFI_GET_CREDENTIALS; ret = IARM_Bus_Call(IARM_BUS_MFRLIB_NAME, IARM_BUS_MFRLIB_API_WIFI_Credentials, - (void*)¶m, sizeof(param)); + (void*)¶m, sizeof(param)); if(security == Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_NONE) securityMode = NET_WIFI_SECURITY_NONE; else if(security == Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE) @@ -280,12 +431,12 @@ namespace WPEFramework } setParam.wifiCredentials.iSecurityMode = securityMode; - + setParam.requestType = WIFI_SET_CREDENTIALS; NMLOG_INFO(" Set Params param.requestType = %d, param.wifiCredentials.cSSID = %s, param.wifiCredentials.iSecurityMode = %d", setParam.requestType, setParam.wifiCredentials.cSSID, setParam.wifiCredentials.iSecurityMode); // Make IARM Bus call to save credentials ret = IARM_Bus_Call(IARM_BUS_MFRLIB_NAME, IARM_BUS_MFRLIB_API_WIFI_Credentials, - (void*)&setParam, sizeof(setParam)); + (void*)&setParam, sizeof(setParam)); if(ret == IARM_RESULT_SUCCESS) { memset(¶m,0,sizeof(param)); @@ -301,10 +452,10 @@ namespace WPEFramework if (ret == IARM_RESULT_SUCCESS) { if ((strcmp (param.wifiCredentials.cSSID, ssid.c_str()) == 0) && - (strcmp (param.wifiCredentials.cPassword, passphrase.c_str()) == 0) && - (param.wifiCredentials.iSecurityMode == securityMode)) + (strcmp (param.wifiCredentials.cPassword, passphrase.c_str()) == 0) && + (param.wifiCredentials.iSecurityMode == securityMode)) { - NMLOG_INFO("Successfully stored the credentails and verified stored ssid %s current ssid %s and security_mode %d", param.wifiCredentials.cSSID, ssid.c_str(), param.wifiCredentials.iSecurityMode); + NMLOG_INFO("Successfully stored the credentials and verified stored ssid %s current ssid %s and security_mode %d", param.wifiCredentials.cSSID, ssid.c_str(), param.wifiCredentials.iSecurityMode); return true; } else @@ -318,7 +469,7 @@ namespace WPEFramework NMLOG_ERROR("IARM Bus call failed for WiFi credentials save: %d", ret); return false; } - + NMLOG_INFO("Successfully saved WiFi settings to MfrMgr via IARM - SSID: %s, Security: %d", ssid.c_str(), security); return true; } @@ -329,16 +480,16 @@ namespace WPEFramework NMLOG_ERROR("IARM connection not available for clearing WiFi settings"); return false; } - + NMLOG_DEBUG("Clearing WiFi settings from MfrMgr via IARM"); - + // Make IARM Bus call to clear credentials IARM_Result_t ret = IARM_Bus_Call(IARM_BUS_MFRLIB_NAME,IARM_BUS_MFRLIB_API_WIFI_EraseAllData,0,0); if (ret != IARM_RESULT_SUCCESS) { NMLOG_ERROR("IARM Bus call failed for WiFi credentials clear: %d", ret); return false; - } - + } + NMLOG_INFO("Successfully cleared WiFi settings from MfrMgr via IARM"); return true; } From 403d5a434768f03db935cd4206b7b0e3f1d5a7bf Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 1 Dec 2025 12:17:12 -0500 Subject: [PATCH 210/271] RDKEMW-9855 : Add PR summary validation workflow (#242) * RDKEMW-9855 : Add PR summary validation workflow Reason for change: Added workflow for PR summary validation Test Procedure: check whether workflow passed Priority:P2 Risks: Medium Signed-off-by: Gururaaja ESR --- .github/workflows/validate_pr_desc.yml | 82 ++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 .github/workflows/validate_pr_desc.yml diff --git a/.github/workflows/validate_pr_desc.yml b/.github/workflows/validate_pr_desc.yml new file mode 100644 index 000000000..b6249ff71 --- /dev/null +++ b/.github/workflows/validate_pr_desc.yml @@ -0,0 +1,82 @@ +name: PR Title Validation +permissions: + contents: read +on: + pull_request: + branches: [develop, main, 'support/**', 'hotfix/**', 'topic/**'] + types: [opened, edited, synchronize] + +jobs: + validate-pr-title: + runs-on: ubuntu-latest + steps: + - name: Validate PR Title Only + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + # Define valid ticket IDs + VALID_TICKET_IDS=("RDKEMW") + + # Function to validate ticket format and ID + validate_ticket() { + local text="$1" + + echo "Validating PR title: $text" + + # Check if text matches the pattern - : + if [[ ! "$text" =~ ^[A-Z0-9]+-[0-9]+[[:space:]]*:[[:space:]]*.+ ]]; then + echo "ERROR: PR title format is invalid." + echo "Expected format: - : " + echo "Example: RDKEMW-123 : Fix playbook issue" + echo "" + echo "Valid ticket IDs are:" + printf "%s\n" "${VALID_TICKET_IDS[@]}" + return 1 + fi + + # Extract ticket ID from the text + local ticket_prefix=$(echo "$text" | sed -n 's/^\([A-Z0-9]\+\)-[0-9]\+[[:space:]]*:.*$/\1/p') + + if [ -z "$ticket_prefix" ]; then + echo "ERROR: Could not extract ticket ID from PR title." + echo "Expected format: - : " + echo "" + echo "Valid ticket IDs are:" + printf "%s\n" "${VALID_TICKET_IDS[@]}" + return 1 + fi + + # Check if extracted ticket ID is in the valid list + local valid=false + for valid_id in "${VALID_TICKET_IDS[@]}"; do + if [ "$ticket_prefix" = "$valid_id" ]; then + valid=true + break + fi + done + + if [ "$valid" = false ]; then + echo "ERROR: Invalid ticket ID '$ticket_prefix' in PR title" + echo "" + echo "Valid ticket IDs are:" + printf "%s\n" "${VALID_TICKET_IDS[@]}" + echo "" + echo "Your PR title should start with one of the above ticket IDs followed by a number." + echo "Example: RDKEMW-123 : Fix playbook issue" + return 1 + fi + + echo "PR title validation passed! Ticket ID: $ticket_prefix" + return 0 + } + + # Validate PR Title Only + echo "=== Validating PR Title ===" + if ! validate_ticket "$PR_TITLE"; then + echo "" + echo "VALIDATION FAILED: PR title must contain valid ticket ID from the approved list." + exit 1 + fi + + echo "" + echo "🎉 PR TITLE VALIDATION PASSED! Title contains valid ticket ID." From 7a23fd41c6e5da4c56edfe5cc4dca79e950d2720 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 4 Dec 2025 13:42:47 -0500 Subject: [PATCH 211/271] RDKEMW-11239 : VG is not being announced during and after FSR journey (#261) RDKEMW-11239 : VG is not being announced during and after FSR journey Reason for change: Updating the address structure with all the details from network manager only when IARM returned error code is NETWORK_IPADDRESS_ACQUIRED. So that we can avoid assigning and returning partial data Test Procedure: Check GetIPSettings is only populated when the error code is returned as NETWORK_IPADDRESS_ACQUIRED from NetSrvMgr Priority:P0 Risks: Medium Signed-off-by: Gururaaja ESR Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- plugin/rdk/NetworkManagerRDKProxy.cpp | 77 +++++++++++++++------------ 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 01885969b..608d22d7c 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -750,48 +750,55 @@ namespace WPEFramework if (IARM_RESULT_SUCCESS == IARM_Bus_Call (IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_getIPSettings, (void *)&iarmData, sizeof(iarmData))) { - address.autoconfig = iarmData.autoconfig; - address.dhcpserver = string(iarmData.dhcpserver); - address.ula = string(""); - address.ipaddress = string(iarmData.ipaddress); - address.gateway = string(iarmData.gateway); - address.primarydns = string(iarmData.primarydns); - address.secondarydns = string(iarmData.secondarydns); - if (0 == strcasecmp("ipv4", iarmData.ipversion)) + if(iarmData.errCode == NETWORK_IPADDRESS_ACQUIRED) { - address.ipversion = string ("IPv4"); - address.prefix = NetmaskToPrefix(iarmData.netmask); - if("eth0" == interface) - m_ethIPv4Address = address; - else if("wlan0" == interface) - m_wlanIPv4Address = address; - } - else if (0 == strcasecmp("ipv6", iarmData.ipversion)) - { - address.ipversion = string ("IPv6"); - address.prefix = std::atoi(iarmData.netmask); - if("eth0" == interface) - m_ethIPv6Address = address; - else if("wlan0" == interface) - m_wlanIPv6Address = address; - } + address.autoconfig = iarmData.autoconfig; + address.dhcpserver = string(iarmData.dhcpserver); + address.ula = string(""); + address.ipaddress = string(iarmData.ipaddress); + address.gateway = string(iarmData.gateway); + address.primarydns = string(iarmData.primarydns); + address.secondarydns = string(iarmData.secondarydns); + if (0 == strcasecmp("ipv4", iarmData.ipversion)) + { + address.ipversion = string ("IPv4"); + address.prefix = NetmaskToPrefix(iarmData.netmask); + if("eth0" == interface) + m_ethIPv4Address = address; + else if("wlan0" == interface) + m_wlanIPv4Address = address; + } + else if (0 == strcasecmp("ipv6", iarmData.ipversion)) + { + address.ipversion = string ("IPv6"); + address.prefix = std::atoi(iarmData.netmask); + if("eth0" == interface) + m_ethIPv6Address = address; + else if("wlan0" == interface) + m_wlanIPv6Address = address; + } - rc = Core::ERROR_NONE; - /* Return the default interface information */ - if (interface.empty()) + rc = Core::ERROR_NONE; + /* Return the default interface information */ + if (interface.empty()) + { + string tmpInterface = string(iarmData.interface); + if ("ETHERNET" == tmpInterface) + interface = "eth0"; + else if ("WIFI" == tmpInterface) + interface = "wlan0"; + else + rc = Core::ERROR_BAD_REQUEST; + } + } + else { - string tmpInterface = string(iarmData.interface); - if ("ETHERNET" == tmpInterface) - interface = "eth0"; - else if ("WIFI" == tmpInterface) - interface = "wlan0"; - else - rc = Core::ERROR_BAD_REQUEST; + NMLOG_WARNING("IP Address is not ready to use yet; err = %d", iarmData.errCode); } } else { - NMLOG_ERROR("NetworkManagerImplementation::GetIPSettings - Calling IARM Failed"); + NMLOG_ERROR("GetIPSettings - Calling IARM Failed"); } return rc; From 12848984e5b6acb5dc3e049cecee9cb50efa4bbe Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 5 Dec 2025 09:50:35 -0500 Subject: [PATCH 212/271] Release of 1.10.0 Release of 1.10.0 --- CHANGELOG.md | 5 +++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 191f03f8f..fc32eb2ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.10.0] - 2025-12-05 +### Fixed +- Fixed the GetIPSettings for RDK Backend to return only when all the information like DNS info retrieved +- Fixed the retrieval of psk to pass it to MfrMgr. + ## [1.9.0] - 2025-11-21 ### Added - Added shortterm solution to print the AP Info diff --git a/CMakeLists.txt b/CMakeLists.txt index 078d7f659..3117b54f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(WPEFramework) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 9) +set(VERSION_MINOR 10) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index cb42e31a0..83a085513 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -9,7 +9,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.9.0" + "version": "1.10.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 961a86ad3..2b1c51307 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.9.0** +**Version: 1.10.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.9.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.10.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 747963543a2e20613e0e9a5748d897dc65588970 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Thu, 11 Dec 2025 10:41:57 -0500 Subject: [PATCH 213/271] RDKEMW-11453 : Cleanup the component to be compatible with Thunder-R5.3.0 (#265) Reason for change: Cleanup the component to be compatible with Thunder-R5.3.0 Test Procedure: Verify Thunder-R5.3.0 build Risks: Low Signed-off-by: Karunakaran A RDKEMW-11453 : Cleanup the component to be compatible with Thunder-R5.3 (#263) Reason for change: Cleanup the component to be compatible with Thunder-R5.3 Test Procedure: Verify Thunder-R5.3 build Risks: Low Signed-off-by: Karunakaran A --- CMakeLists.txt | 16 ++++++- definition/NetworkManager.json | 1 - legacy/LegacyNetworkAPIs.cpp | 2 +- legacy/LegacyWiFiManagerAPIs.cpp | 2 +- plugin/CMakeLists.txt | 2 +- plugin/NetworkManager.h | 8 ---- tests/l2Test/CMakeLists.txt | 1 - .../l2_test_LegacyPlugin_NetworkAPIs.cpp | 40 ++++++++--------- .../l2_test_LegacyPlugin_WiFiManagerAPIs.cpp | 44 +++++++++---------- 9 files changed, 60 insertions(+), 56 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3117b54f6..50371004e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,21 @@ cmake_minimum_required(VERSION 3.3) project(NetworkManager) -find_package(WPEFramework) + +# Try WPEFramework first +find_package(WPEFramework QUIET CONFIG) + +# If WPEFramework isn't found, try Thunder +if (NOT WPEFramework_FOUND) + find_package(Thunder QUIET CONFIG) +endif() + +# Error out if neither is found +if (NOT WPEFramework_FOUND AND NOT Thunder_FOUND) + message(FATAL_ERROR + "Neither WPEFramework nor Thunder could be found.\n" + "Install one of them and ensure its CMake package is discoverable via CMAKE_PREFIX_PATH or default locations.") +endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 83a085513..0ad45e2d5 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -5,7 +5,6 @@ "title": "NetworkManager Plugin", "class": "NetworkManager", "callsign": "org.rdk.NetworkManager", - "locator": "libWPEFrameworkNetworkManager.so", "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", diff --git a/legacy/LegacyNetworkAPIs.cpp b/legacy/LegacyNetworkAPIs.cpp index bc0a669ed..7bf3b941c 100644 --- a/legacy/LegacyNetworkAPIs.cpp +++ b/legacy/LegacyNetworkAPIs.cpp @@ -25,7 +25,7 @@ using namespace WPEFramework::Plugin; #define API_VERSION_NUMBER_MAJOR 2 #define API_VERSION_NUMBER_MINOR 0 #define API_VERSION_NUMBER_PATCH 0 -#define NETWORK_MANAGER_CALLSIGN "org.rdk.NetworkManager.1" +#define NETWORK_MANAGER_CALLSIGN "org.rdk.NetworkManager" #define SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS 500 #define DEFAULT_PING_PACKETS 15 diff --git a/legacy/LegacyWiFiManagerAPIs.cpp b/legacy/LegacyWiFiManagerAPIs.cpp index dc032dc85..a075e43ef 100644 --- a/legacy/LegacyWiFiManagerAPIs.cpp +++ b/legacy/LegacyWiFiManagerAPIs.cpp @@ -26,7 +26,7 @@ using namespace WPEFramework::Plugin; #define API_VERSION_NUMBER_MAJOR 2 #define API_VERSION_NUMBER_MINOR 0 #define API_VERSION_NUMBER_PATCH 0 -#define NETWORK_MANAGER_CALLSIGN "org.rdk.NetworkManager.1" +#define NETWORK_MANAGER_CALLSIGN "org.rdk.NetworkManager" #define SUBSCRIPTION_TIMEOUT_IN_MILLISECONDS 500 #define WPA_SUPPLICANT_CONF "/opt/secure/wifi/wpa_supplicant.conf" diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index a24b6bf64..abfd9998a 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -56,7 +56,7 @@ add_definitions(-DPLUGIN_BUILD_REFERENCE=${PLUGIN_BUILD_REFERENCE}) include_directories(${PROJECT_SOURCE_DIR}/interface) include_directories(${PROJECT_SOURCE_DIR}/plugin) -# Build the main plugin that runs inside the WPEFramework daemon +# Build the main plugin that runs inside the daemon add_library(${MODULE_NAME} SHARED NetworkManager.cpp NetworkManagerJsonRpc.cpp diff --git a/plugin/NetworkManager.h b/plugin/NetworkManager.h index eb1dec58a..6529e058e 100644 --- a/plugin/NetworkManager.h +++ b/plugin/NetworkManager.h @@ -132,14 +132,6 @@ namespace WPEFramework void Deinitialize(PluginHost::IShell *service) override; string Information() const override; - //override Subscribe from IDispatcher - uint32_t Subscribe(const uint32_t channel, const string& event, const string& designator) override - { - NMLOG_DEBUG("Subscription received for %s event from channelID (%u) with designator as %s", event.c_str(), channel, designator.c_str()); - JSONRPC::Subscribe(channel, event, designator); - return Core::ERROR_NONE; - } - // Do not allow copy/move constructors NetworkManager(const NetworkManager &) = delete; NetworkManager &operator=(const NetworkManager &) = delete; diff --git a/tests/l2Test/CMakeLists.txt b/tests/l2Test/CMakeLists.txt index f9cfa9488..74c150bf7 100644 --- a/tests/l2Test/CMakeLists.txt +++ b/tests/l2Test/CMakeLists.txt @@ -20,7 +20,6 @@ cmake_minimum_required(VERSION 3.3) message ("building Networkmanager plugin l2 tests") find_package(CURL) -find_package(WPEFramework) find_package(PkgConfig REQUIRED) find_package(${NAMESPACE}Core REQUIRED) find_package(${NAMESPACE}Plugins REQUIRED) diff --git a/tests/l2Test/legacy/l2_test_LegacyPlugin_NetworkAPIs.cpp b/tests/l2Test/legacy/l2_test_LegacyPlugin_NetworkAPIs.cpp index 162315833..d55de3924 100644 --- a/tests/l2Test/legacy/l2_test_LegacyPlugin_NetworkAPIs.cpp +++ b/tests/l2Test/legacy/l2_test_LegacyPlugin_NetworkAPIs.cpp @@ -77,7 +77,7 @@ class NetworkTest : public ::testing::Test{ })) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); m_subsIfaceStateChange = true; m_subsActIfaceChange = true; m_subsIPAddrChange = true; @@ -128,7 +128,7 @@ TEST_F(NetworkTest, getInterfaces) .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); EXPECT_CALL(*mockNetworkManager, GetAvailableInterfaces(::testing::_)) @@ -183,7 +183,7 @@ TEST_F(NetworkTest, setStunEndpoint) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); EXPECT_CALL(*mockNetworkManager, SetStunEndpoint(::testing::_, ::testing::_, ::testing::_, ::testing::_)) @@ -210,7 +210,7 @@ TEST_F(NetworkTest, setInterfaceEnabled){ .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -234,7 +234,7 @@ TEST_F(NetworkTest, getDefaultInterface) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -279,7 +279,7 @@ TEST_F(NetworkTest, setIPSettings) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -309,7 +309,7 @@ TEST_F(NetworkTest, getIPSettings) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -350,7 +350,7 @@ TEST_F(NetworkTest, getIPSettingsIPv6) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -391,7 +391,7 @@ TEST_F(NetworkTest, getIPSettingsErrorEmptyString) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -428,7 +428,7 @@ TEST_F(NetworkTest, getIPSettings2) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -468,7 +468,7 @@ TEST_F(NetworkTest, isConnectedToInternet) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -501,7 +501,7 @@ TEST_F(NetworkTest, getInternetConnectionState) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -532,7 +532,7 @@ TEST_F(NetworkTest, doPing) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -578,7 +578,7 @@ TEST_F(NetworkTest, doTrace) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -627,7 +627,7 @@ TEST_F(NetworkTest, getPublicIP) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -659,7 +659,7 @@ TEST_F(NetworkTest, isInterfaceEnabled) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -700,7 +700,7 @@ TEST_F(NetworkTest, setConnectivityTestEndpoints) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -773,7 +773,7 @@ TEST_F(NetworkTest, getCaptivePortalURI) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -811,7 +811,7 @@ TEST_F(NetworkTest, getStbIp) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); EXPECT_CALL(*mockNetworkManager, GetIPSettings(::testing::_, ::testing::_, ::testing::_)) @@ -846,7 +846,7 @@ TEST_F(NetworkTest, getSTBIPFamily) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); EXPECT_CALL(*mockNetworkManager, GetIPSettings(::testing::_, ::testing::_, ::testing::_)) diff --git a/tests/l2Test/legacy/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp b/tests/l2Test/legacy/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp index aa2c8a563..aa90be474 100644 --- a/tests/l2Test/legacy/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp +++ b/tests/l2Test/legacy/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp @@ -68,7 +68,7 @@ class WiFiManagerTest : public ::testing::Test { })) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockShell); })); m_service = service; @@ -114,7 +114,7 @@ TEST_F(WiFiManagerTest, cancelWPSPairing) .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); EXPECT_CALL(*mockNetworkManager, StopWPS()) @@ -134,7 +134,7 @@ TEST_F(WiFiManagerTest, clearSSID) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); EXPECT_CALL(*mockNetworkManager, RemoveKnownSSID(::testing::_)) @@ -153,7 +153,7 @@ TEST_F(WiFiManagerTest, connect) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); EXPECT_CALL(*mockNetworkManager, WiFiConnect(::testing::_)) @@ -182,7 +182,7 @@ TEST_F(WiFiManagerTest, getConnectedSSID) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; @@ -215,7 +215,7 @@ TEST_F(WiFiManagerTest, getConnectedSSIDSAE) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; @@ -248,7 +248,7 @@ TEST_F(WiFiManagerTest, getConnectedSSIDEAP) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; @@ -281,7 +281,7 @@ TEST_F(WiFiManagerTest, getCurrentState) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); Exchange::INetworkManager::WiFiState state = Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTED; @@ -309,7 +309,7 @@ TEST_F(WiFiManagerTest, getCurrentStateFailed1) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); Exchange::INetworkManager::WiFiState state = Exchange::INetworkManager::WiFiState::WIFI_STATE_ERROR; @@ -337,7 +337,7 @@ TEST_F(WiFiManagerTest, getCurrentStateFailed2) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); Exchange::INetworkManager::WiFiState state = Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTION_INTERRUPTED; @@ -365,7 +365,7 @@ TEST_F(WiFiManagerTest, getCurrentStateDisconnected) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); Exchange::INetworkManager::WiFiState state = Exchange::INetworkManager::WiFiState::WIFI_STATE_DISCONNECTED; @@ -393,7 +393,7 @@ TEST_F(WiFiManagerTest, getCurrentStateConnected) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); Exchange::INetworkManager::WiFiState state = Exchange::INetworkManager::WiFiState::WIFI_STATE_CONNECTED; @@ -421,7 +421,7 @@ TEST_F(WiFiManagerTest, getPairedSSIDInfo) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; @@ -459,7 +459,7 @@ TEST_F(WiFiManagerTest, saveSSID) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); Exchange::INetworkManager::WiFiConnectTo ssid{}; @@ -496,7 +496,7 @@ TEST_F(WiFiManagerTest, disconnect) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); EXPECT_CALL(*mockNetworkManager, WiFiDisconnect()) @@ -519,7 +519,7 @@ TEST_F(WiFiManagerTest, initiateWPSPairing) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); EXPECT_CALL(*mockNetworkManager, StartWPS(::testing::_, ::testing::_)) @@ -549,7 +549,7 @@ TEST_F(WiFiManagerTest, startScan) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); EXPECT_CALL(*mockNetworkManager, StartWiFiScan(::testing::_, ::testing::_)) @@ -579,7 +579,7 @@ TEST_F(WiFiManagerTest, stopScan) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); EXPECT_CALL(*mockNetworkManager, StopWiFiScan()) @@ -603,7 +603,7 @@ TEST_F(WiFiManagerTest, stopScan_Error) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); EXPECT_CALL(*mockNetworkManager, StopWiFiScan()) @@ -715,7 +715,7 @@ TEST_F(WiFiManagerTest, getPairedSSID) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -751,7 +751,7 @@ TEST_F(WiFiManagerTest, isPaired) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); @@ -787,7 +787,7 @@ TEST_F(WiFiManagerTest, isPairedNoSSID) { .Times(1) .WillOnce(::testing::Invoke( [&](const uint32_t, const string& name) -> void* { - EXPECT_EQ(name, string(_T("org.rdk.NetworkManager.1"))); + EXPECT_EQ(name, string(_T("org.rdk.NetworkManager"))); return static_cast(mockNetworkManager); })); From bfecfd9457e7365a8e7d83640307766315434a22 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 19 Dec 2025 11:52:28 -0500 Subject: [PATCH 214/271] Release of 1.11.0 Release of 1.11.0 --- CHANGELOG.md | 4 ++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc32eb2ce..37b743617 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.11.0] - 2025-12-19 +### Added +- Added support to build for Thunder R5.x + ## [1.10.0] - 2025-12-05 ### Fixed - Fixed the GetIPSettings for RDK Backend to return only when all the information like DNS info retrieved diff --git a/CMakeLists.txt b/CMakeLists.txt index 50371004e..69be7c5bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 10) +set(VERSION_MINOR 11) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 0ad45e2d5..93f03d45c 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.10.0" + "version": "1.11.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 2b1c51307..17276b3f0 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.10.0** +**Version: 1.11.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.10.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.11.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 0d3581a24b5c5c44bd7bbb5738d56b1d139fb156 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 23 Dec 2025 15:55:21 -0500 Subject: [PATCH 215/271] RDKEMW-11771 : Failure connecting to ethernet during migration (#266) RDKEMW-11771 : Failure connecting to ethernet during migration Reason for change: To address ethernet connection issue during migration Test Procedure: Test with EPG changes Signed-off-by: Gururaaja ESR --- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 99 +++++++++++++++++++++++- 1 file changed, 95 insertions(+), 4 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 5c5dba0ce..ead3100e1 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -525,6 +525,56 @@ namespace WPEFramework _wifiManager->m_client, NM_CONNECTION(remote_con), _wifiManager->m_wifidevice, _wifiManager->m_objectPath, NULL, wifiConnectCb, _wifiManager); } + static NMConnection* createMinimalEthernetConnection(const std::string& iface) + { + NMConnection *connection = nm_simple_connection_new(); + + // Connection settings with autoconnect enabled + NMSettingConnection *sConnection = (NMSettingConnection *)nm_setting_connection_new(); + std::string connId = "Wired connection 1"; + g_object_set(G_OBJECT(sConnection), + NM_SETTING_CONNECTION_ID, connId.c_str(), + NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate(), + NM_SETTING_CONNECTION_TYPE, "802-3-ethernet", + NM_SETTING_CONNECTION_INTERFACE_NAME, iface.c_str(), + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, // Enable autoconnect + NULL); + nm_connection_add_setting(connection, NM_SETTING(sConnection)); + + // Wired ethernet settings + NMSettingWired *sWired = (NMSettingWired *)nm_setting_wired_new(); + nm_connection_add_setting(connection, NM_SETTING(sWired)); + + // Get hostname for DHCP + std::string hostname; + if(!nmUtils::readPersistentHostname(hostname)) + { + hostname = nmUtils::deviceHostname(); + NMLOG_DEBUG("No persistent hostname found, using device hostname"); + } + + // IPv4 settings with DHCP + NMSettingIP4Config *sIpv4 = (NMSettingIP4Config *)nm_setting_ip4_config_new(); + g_object_set(G_OBJECT(sIpv4), + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), + NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, + NULL); + nm_connection_add_setting(connection, NM_SETTING(sIpv4)); + + // IPv6 settings with DHCP + NMSettingIP6Config *sIpv6 = (NMSettingIP6Config *)nm_setting_ip6_config_new(); + g_object_set(G_OBJECT(sIpv6), + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), + NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, + NULL); + nm_connection_add_setting(connection, NM_SETTING(sIpv6)); + + NMLOG_DEBUG("Created minimal ethernet connection with autoconnect=true"); + return connection; + } + static bool connectionBuilder(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo, NMConnection *m_connection, bool iswpsAP = false) { if(ssidinfo.ssid.empty() || ssidinfo.ssid.length() > 32) @@ -715,9 +765,30 @@ namespace WPEFramework devConnections = nm_client_get_connections(m_client); if(devConnections == NULL || devConnections->len == 0) { - NMLOG_ERROR("No connections found !"); - deleteClientConnection(); - return false; + if(iface == nmUtils::ethIface()) + { + NMLOG_INFO("Creating and activating ethernet connection with autoconnect=true"); + NMConnection *ethConn = createMinimalEthernetConnection(iface); + if(ethConn == NULL) + { + NMLOG_ERROR("Failed to create ethernet connection"); + deleteClientConnection(); + return false; + } + m_isSuccess = false; + m_createNewConnection = true; + nm_client_add_and_activate_connection_async(m_client, ethConn, nmDevice, NULL, NULL, wifiConnectCb, this); + g_object_unref(ethConn); + wait(m_loop); + deleteClientConnection(); + return m_isSuccess; + } + else + { + NMLOG_ERROR("No connections found !"); + deleteClientConnection(); + return false; + } } for (guint i = 0; i < devConnections->len; i++) @@ -780,7 +851,27 @@ namespace WPEFramework } else { - NMLOG_ERROR("'%s' connection not found !", knowConnectionID.c_str()); + NMLOG_WARNING("'%s' connection not found", knowConnectionID.empty() ? iface.c_str() : knowConnectionID.c_str()); + // For ethernet, create minimal connection and activate + if(iface == nmUtils::ethIface()) + { + NMLOG_INFO("Creating and activating ethernet connection with autoconnect=true"); + NMConnection *ethConn = createMinimalEthernetConnection(iface); + if(ethConn == NULL) + { + NMLOG_ERROR("Failed to create ethernet connection"); + m_isSuccess = false; + } + else + { + m_createNewConnection = true; + nm_client_add_and_activate_connection_async(m_client, ethConn, nmDevice, NULL, NULL, wifiConnectCb, this); + g_object_unref(ethConn); + wait(m_loop); + } + } + else + NMLOG_ERROR("'%s' connection not found !", knowConnectionID.c_str()); } if(knownConnection != NULL) From 7326cf227b110da6f45c234d3f97ad728ce6fc2b Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Tue, 23 Dec 2025 19:04:33 -0500 Subject: [PATCH 216/271] Release of 1.12.0 Release of 1.12.0 --- CHANGELOG.md | 4 ++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37b743617..27c79fa3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.12.0] - 2025-12-23 +### Fixed +- Fixed the Ethernet interface enablement upon EntOS migration + ## [1.11.0] - 2025-12-19 ### Added - Added support to build for Thunder R5.x diff --git a/CMakeLists.txt b/CMakeLists.txt index 69be7c5bd..44ec77638 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 11) +set(VERSION_MINOR 12) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 93f03d45c..4435615e4 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.11.0" + "version": "1.12.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 17276b3f0..81185915b 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.11.0** +**Version: 1.12.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.11.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.12.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 9588a044238846bad5eb965d5eba2fd2975854d0 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Tue, 27 Jan 2026 21:09:21 +0530 Subject: [PATCH 217/271] RDKEMW-12614 : Always Enable WiFi upon Migration (#269) * RDKEMW-12614 Always Enable WiFi upon Migration Updated to enable WiFi when BootType as BOOT_MIGRATION Signed-off-by: Muhammed Rafi C --- plugin/gnome/scripts/nm_interface_handler.sh | 16 ++++++++++++++++ .../systemd/gnome-networkmanager-migration.conf | 5 ++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/plugin/gnome/scripts/nm_interface_handler.sh b/plugin/gnome/scripts/nm_interface_handler.sh index 12ce1514a..cf6d786fc 100644 --- a/plugin/gnome/scripts/nm_interface_handler.sh +++ b/plugin/gnome/scripts/nm_interface_handler.sh @@ -31,6 +31,13 @@ . /etc/device.properties +# Get BOOT_TYPE +if [ -f /tmp/bootType ]; then + BOOT_TYPE=$(grep "BOOT_TYPE" /tmp/bootType | cut -d '=' -f 2) +else + BOOT_TYPE="" +fi + # Ethernet NSM_ETH_MARKER="/opt/persistent/ethernet_disallowed" NM_ETH_MARKER="/opt/persistent/ethernet.interface.disable" @@ -41,6 +48,13 @@ NSM_WIFI_MARKER="/opt/persistent/wifi_disallowed" NM_WIFI_MARKER="/opt/persistent/wifi.interface.disable" WIFI_INTERFACE="$WIFI_INTERFACE" +if [ "$BOOT_TYPE" = "BOOT_MIGRATION" ]; then + echo "`/bin/timestamp` :$0: migration boot removing ethernet and wifi disable marker file" >> /opt/logs/NMMonitor.log + rm -f "$NSM_ETH_MARKER" + rm -f "$NSM_WIFI_MARKER" + exit 0 +fi + # Rename legacy netsrvmger markers to networkmanager markers if they exist if [ -f "$NSM_ETH_MARKER" ]; then mv "$NSM_ETH_MARKER" "$NM_ETH_MARKER" @@ -52,12 +66,14 @@ fi # If networkmanager Ethernet marker exists, make eth0 unmanaged if [ -f "$NM_ETH_MARKER" ]; then + echo "`/bin/timestamp` :$0: disabling eth0 interface " >> /opt/logs/NMMonitor.log nmcli device disconnect "$ETH_INTERFACE" nmcli dev set "$ETH_INTERFACE" managed no fi # If networkmanager Wi-Fi marker exists, make wlan0 unmanaged if [ -f "$NM_WIFI_MARKER" ]; then + echo "`/bin/timestamp` :$0: disabling wlan0 interface " >> /opt/logs/NMMonitor.log nmcli device disconnect "$WIFI_INTERFACE" nmcli dev set "$WIFI_INTERFACE" managed no fi diff --git a/plugin/gnome/systemd/gnome-networkmanager-migration.conf b/plugin/gnome/systemd/gnome-networkmanager-migration.conf index 7aa5fcad0..a8dd0d057 100644 --- a/plugin/gnome/systemd/gnome-networkmanager-migration.conf +++ b/plugin/gnome/systemd/gnome-networkmanager-migration.conf @@ -1,2 +1,5 @@ +[Unit] +After=NM_Bootstrap.service + [Service] -ExecStartPre=/bin/sh -c '/lib/rdk/nm_interface_handler.sh' +ExecStartPre=/lib/rdk/nm_interface_handler.sh From 9864888884d93a664c2000a5329faa3c5c04096a Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 27 Jan 2026 16:53:00 -0500 Subject: [PATCH 218/271] RDKEMW-10277: Multiple crashes observed while searching SSID (#267) * RDKEMW-10277: Multiple crashes observed while searching SSID Reason for Change: The wifiConnectionUpdate() callback registered in the wifiConnect(), got invoked after the wait(m_loop) timeout of 10sec and deleteClientConnection(). In the deleteClientConnection() function m_client is completely cleared and set to NULL. After this wifiConnectionUpdate() callback is invoked in which nm_client_activate_connection_async() uses the freed m_client, which leads to the crash. Addressed this by adding GCancellable, through which we are cancelling the pending async operations. Test Procedure: Check for crash in the issue reported scenario Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR * RDKEMW-10277: Multiple crashes observed while searching SSID Reason for Change: The wifiConnectionUpdate() callback registered in the wifiConnect(), got invoked after the wait(m_loop) timeout of 10sec and deleteClientConnection(). In the deleteClientConnection() function m_client is completely cleared and set to NULL. After this wifiConnectionUpdate() callback is invoked in which nm_client_activate_connection_async() uses the freed m_client, which leads to the crash. Addressed this by adding GCancellable, through which we are cancelling the pending async operations. Test Procedure: Check for crash in the issue reported scenario Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR --------- Signed-off-by: Gururaaja ESR --- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 110 +++++++++++++++++------ plugin/gnome/NetworkManagerGnomeWIFI.h | 3 + 2 files changed, 85 insertions(+), 28 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index ead3100e1..4717ca40a 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -42,7 +42,7 @@ namespace WPEFramework extern NetworkManagerImplementation* _instance; static std::atomic wpsProcessRun = {false}; - wifiManager::wifiManager() : m_client(nullptr), m_loop(nullptr), m_createNewConnection(false), m_objectPath(nullptr), m_wifidevice(nullptr), m_source(nullptr) { + wifiManager::wifiManager() : m_client(nullptr), m_loop(nullptr), m_createNewConnection(false), m_objectPath(nullptr), m_wifidevice(nullptr), m_source(nullptr), m_cancellable(nullptr){ NMLOG_INFO("wifiManager"); m_nmContext = g_main_context_new(); g_main_context_push_thread_default(m_nmContext); @@ -61,12 +61,29 @@ namespace WPEFramework } return false; } + + // Create new cancellable for this client session + { + std::lock_guard lock(m_cancellableMutex); + m_cancellable = g_cancellable_new(); + } return true; } void wifiManager::deleteClientConnection() { - if(m_client != NULL) { + // Cancel all pending async operations before destroying client + { + std::lock_guard lock(m_cancellableMutex); + if(m_cancellable) { + NMLOG_DEBUG("Cancelling pending async operations"); + g_cancellable_cancel(m_cancellable); + g_clear_object(&m_cancellable); + m_cancellable = NULL; + } + } + + if(m_client) { GMainContext *context = g_main_context_ref(nm_client_get_main_context(m_client)); GObject *contextBusyWatcher = nm_client_get_context_busy_watcher(m_client); g_object_add_weak_pointer(contextBusyWatcher,(gpointer *) &contextBusyWatcher); @@ -356,7 +373,7 @@ namespace WPEFramework { if(g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - NMLOG_ERROR("something went wrong no matching gerror found !"); + NMLOG_DEBUG("Disconnect operation was cancelled"); } else { @@ -391,7 +408,7 @@ namespace WPEFramework return true; } - nm_device_disconnect_async(wifiNMDevice, NULL, disconnectCb, this); + nm_device_disconnect_async(wifiNMDevice, m_cancellable, disconnectCb, this); wait(m_loop); deleteClientConnection(); return m_isSuccess; @@ -442,23 +459,30 @@ namespace WPEFramework if (_wifiManager->m_createNewConnection) { NMLOG_DEBUG("nm_client_add_and_activate_connection_finish"); activeConnection = nm_client_add_and_activate_connection_finish(NM_CLIENT(_wifiManager->m_client), result, &error); - _wifiManager->m_isSuccess = true; } else { NMLOG_DEBUG("nm_client_activate_connection_finish "); activeConnection = nm_client_activate_connection_finish(NM_CLIENT(_wifiManager->m_client), result, &error); - _wifiManager->m_isSuccess = true; } + // Check if operation was cancelled - this is expected during cleanup if (error) { - _wifiManager->m_isSuccess = false; - if (_wifiManager->m_createNewConnection) { - NMLOG_ERROR("Failed to add/activate new connection: %s", error->message); - } else { - NMLOG_ERROR("Failed to activate connection: %s", error->message); + _wifiManager->m_isSuccess = false; + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + NMLOG_DEBUG("Connection operation was cancelled"); + } + else { + if (_wifiManager->m_createNewConnection) { + NMLOG_ERROR("Failed to add/activate new connection: %s", error->message); + } else { + NMLOG_ERROR("Failed to activate connection: %s", error->message); + } } g_error_free(error); } + else { + _wifiManager->m_isSuccess = true; + } if(activeConnection) g_object_unref(activeConnection); @@ -474,7 +498,12 @@ namespace WPEFramework remoteConnection = nm_client_add_connection2_finish(NM_CLIENT(client), result, NULL, &error); if (error) { - NMLOG_ERROR("Failed to add temporary connection: %s", error->message); + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + NMLOG_DEBUG("Add temporary connection was cancelled"); + } + else { + NMLOG_ERROR("Failed to add temporary connection: %s", error->message); + } _wifiManager->m_isSuccess = false; g_error_free(error); g_main_loop_quit(_wifiManager->m_loop); @@ -483,12 +512,22 @@ namespace WPEFramework if (remoteConnection) { NMLOG_DEBUG("Temporary connection added, now activating..."); + + // Check if client is still valid before activating + if (_wifiManager->m_client == NULL) { + NMLOG_WARNING("Client was destroyed, cannot activate connection"); + _wifiManager->m_isSuccess = false; + g_object_unref(remoteConnection); + g_main_loop_quit(_wifiManager->m_loop); + return; + } + // Now activate the temporary connection nm_client_activate_connection_async(_wifiManager->m_client, NM_CONNECTION(remoteConnection), _wifiManager->m_wifidevice, _wifiManager->m_objectPath, - NULL, + _wifiManager->m_cancellable, wifiConnectCb, _wifiManager); g_object_unref(remoteConnection); @@ -520,9 +559,17 @@ namespace WPEFramework else g_variant_unref(ret); + // Check if client is still valid before activating + if (_wifiManager->m_client == NULL) { + NMLOG_WARNING("Client was destroyed, cannot activate connection"); + _wifiManager->m_isSuccess = false; + _wifiManager->quit(NULL); + return; + } + _wifiManager->m_createNewConnection = false; // no need to create new connection nm_client_activate_connection_async( - _wifiManager->m_client, NM_CONNECTION(remote_con), _wifiManager->m_wifidevice, _wifiManager->m_objectPath, NULL, wifiConnectCb, _wifiManager); + _wifiManager->m_client, NM_CONNECTION(remote_con), _wifiManager->m_wifidevice, _wifiManager->m_objectPath, _wifiManager->m_cancellable, wifiConnectCb, _wifiManager); } static NMConnection* createMinimalEthernetConnection(const std::string& iface) @@ -777,7 +824,7 @@ namespace WPEFramework } m_isSuccess = false; m_createNewConnection = true; - nm_client_add_and_activate_connection_async(m_client, ethConn, nmDevice, NULL, NULL, wifiConnectCb, this); + nm_client_add_and_activate_connection_async(m_client, ethConn, nmDevice, NULL, m_cancellable, wifiConnectCb, this); g_object_unref(ethConn); wait(m_loop); deleteClientConnection(); @@ -846,7 +893,7 @@ namespace WPEFramework { NMLOG_INFO("activating known wifi '%s' connection", knowConnectionID.c_str()); m_createNewConnection = false; // no need to create new connection - nm_client_activate_connection_async(m_client, NM_CONNECTION(knownConnection), nmDevice, specificObjPath, NULL, wifiConnectCb, this); + nm_client_activate_connection_async(m_client, NM_CONNECTION(knownConnection), nmDevice, specificObjPath, m_cancellable, wifiConnectCb, this); wait(m_loop); } else @@ -865,7 +912,7 @@ namespace WPEFramework else { m_createNewConnection = true; - nm_client_add_and_activate_connection_async(m_client, ethConn, nmDevice, NULL, NULL, wifiConnectCb, this); + nm_client_add_and_activate_connection_async(m_client, ethConn, nmDevice, NULL, m_cancellable, wifiConnectCb, this); g_object_unref(ethConn); wait(m_loop); } @@ -1022,7 +1069,7 @@ namespace WPEFramework // Note: Any changes made by connectionBuilder will be temporary for this session only NMLOG_DEBUG("activating existing connection without persisting changes '%s'", ssidInfo.ssid.c_str()); m_createNewConnection = false; - nm_client_activate_connection_async(m_client, NM_CONNECTION(m_connection), m_wifidevice, m_objectPath, NULL, wifiConnectCb, this); + nm_client_activate_connection_async(m_client, NM_CONNECTION(m_connection), m_wifidevice, m_objectPath, m_cancellable, wifiConnectCb, this); } } else @@ -1041,7 +1088,7 @@ namespace WPEFramework if (ssidInfo.persist) { m_createNewConnection = true; - nm_client_add_and_activate_connection_async(m_client, m_connection, m_wifidevice, m_objectPath, NULL, wifiConnectCb, this); + nm_client_add_and_activate_connection_async(m_client, m_connection, m_wifidevice, m_objectPath, m_cancellable, wifiConnectCb, this); } else { @@ -1055,7 +1102,7 @@ namespace WPEFramework NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY, NULL, TRUE, - NULL, + m_cancellable, wifiConnectTempCb, this); } @@ -1112,7 +1159,11 @@ namespace WPEFramework } if(error) { - NMLOG_ERROR("AddToKnownSSIDs Failed: %s", error->message); + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + NMLOG_DEBUG("Add connection operation was cancelled"); + } else { + NMLOG_ERROR("AddToKnownSSIDs Failed: %s", error->message); + } _wifiManager->m_isSuccess = false; g_error_free(error); } @@ -1183,7 +1234,7 @@ namespace WPEFramework nm_client_add_connection2(m_client, connSettings, NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK, - NULL, TRUE, NULL, + NULL, TRUE, m_cancellable, addToKnownSSIDsCb, this); } wait(m_loop); @@ -1349,8 +1400,11 @@ namespace WPEFramework _wifiManager->m_isSuccess = false; } if (error) { - NMLOG_ERROR("Scanning Failed Error: %s.", error->message); - _wifiManager->m_isSuccess = false; + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + NMLOG_DEBUG("Scan operation was cancelled"); + } else { + NMLOG_ERROR("Scanning Failed Error: %s.", error->message); + } g_error_free(error); } @@ -1370,7 +1424,7 @@ namespace WPEFramework m_isSuccess = false; if(!ssidReq.empty()) { - NMLOG_INFO("staring wifi scanning .. %s", ssidReq.c_str()); + NMLOG_INFO("starting wifi scanning .. %s", ssidReq.c_str()); GVariantBuilder builder, array_builder; GVariant *options; g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); @@ -1380,12 +1434,12 @@ namespace WPEFramework ); g_variant_builder_add(&builder, "{sv}", "ssids", g_variant_builder_end(&array_builder)); options = g_variant_builder_end(&builder); - nm_device_wifi_request_scan_options_async(wifiDevice, options, NULL, wifiScanCb, this); + nm_device_wifi_request_scan_options_async(wifiDevice, options, m_cancellable, wifiScanCb, this); g_variant_unref(options); // Unreference the GVariant after passing it to the async function } else { NMLOG_INFO("staring normal wifi scanning .."); - nm_device_wifi_request_scan_async(wifiDevice, NULL, wifiScanCb, this); + nm_device_wifi_request_scan_async(wifiDevice, m_cancellable, wifiScanCb, this); } wait(m_loop); deleteClientConnection(); @@ -1762,7 +1816,7 @@ namespace WPEFramework { if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - NMLOG_ERROR("something went wrong no matching gerror found !"); + NMLOG_DEBUG("Device Manage operation was cancelled !"); } else { diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 73e374033..ca4d1d95a 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -30,6 +30,7 @@ #include #include #include +#include #define WPS_RETRY_WAIT_IN_MS 10 // 10 sec #define WPS_RETRY_COUNT 10 @@ -101,6 +102,8 @@ namespace WPEFramework const char* m_objectPath; NMDevice *m_wifidevice; GSource *m_source; + GCancellable *m_cancellable; + std::mutex m_cancellableMutex; bool m_isSuccess = false; SecretAgent m_secretAgent; }; From ff1bf9009de9b0a0d9b4763b6f49955193c41dbb Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 30 Jan 2026 10:59:00 -0500 Subject: [PATCH 219/271] RDKEMW-13002 : ZeroConfig (IPv4LL) support for EntOS - AirPlay Devices (#270) * RDK-60375 - ZeroConfig (IPv4LL) support for EntOS - AirPlay Capable Devices Reason for Change: As Gnome networkmanager is clearing of the link local IP address periodically after cheking for dhcp. We made the DHCP timeout of IPv4 to infinity. So that Gnome networkmanager won't delete the link local IP Test Procedure: Check link local IP assigned persist after assigned Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR * RDK-60375 - ZeroConfig (IPv4LL) support for EntOS - AirPlay Capable Devices Reason for Change: As Gnome networkmanager is clearing of the link local IP address periodically after cheking for dhcp. We made the DHCP timeout of IPv4 to infinity. So that Gnome networkmanager won't delete the link local IP Test Procedure: Check link local IP assigned persist after assigned Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR --------- Signed-off-by: Gururaaja ESR --- conf/99-default-link-local | 3 +++ plugin/gnome/NetworkManagerGnomeProxy.cpp | 22 ++++++++++++++++++++++ plugin/gnome/NetworkManagerGnomeWIFI.cpp | 1 + 3 files changed, 26 insertions(+) create mode 100644 conf/99-default-link-local diff --git a/conf/99-default-link-local b/conf/99-default-link-local new file mode 100644 index 000000000..41b7da7cd --- /dev/null +++ b/conf/99-default-link-local @@ -0,0 +1,3 @@ +[connection] +ipv4.link-local=2 +ipv4.dhcp-timeout=2147483647 diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 2de707c54..85326d633 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -22,7 +22,9 @@ #include "NetworkManagerGnomeUtils.h" #include #include +#include +#define IN_IS_ADDR_LINKLOCAL(a) ((((uint32_t)ntohl(a)) & 0xffff0000U) == 0xa9fe0000U) static NMClient *client = NULL; using namespace WPEFramework; using namespace WPEFramework::Plugin; @@ -691,6 +693,7 @@ namespace WPEFramework ip4_config = nm_active_connection_get_ip4_config(conn); NMIPAddress *ipAddr = NULL; std::string ipStr; + struct sockaddr_in sa; if (ip4_config) ipByte = nm_ip_config_get_addresses(ip4_config); else @@ -704,6 +707,13 @@ namespace WPEFramework ipStr = nm_ip_address_get_address(ipAddr); if(!ipStr.empty()) { + // Skip link-local IPv4 addresses (169.254.x.x) + inet_pton(AF_INET, ipStr.c_str(), &(sa.sin_addr)); + if(IN_IS_ADDR_LINKLOCAL(sa.sin_addr.s_addr)) + { + NMLOG_DEBUG("Skipping link-local IPv4 address: %s", ipStr.c_str()); + continue; + } result.ipaddress = nm_ip_address_get_address(ipAddr); result.prefix = nm_ip_address_get_prefix(ipAddr); NMLOG_INFO("IPv4 addr: %s/%d", result.ipaddress.c_str(), result.prefix); @@ -729,6 +739,18 @@ namespace WPEFramework } result.ula = ""; + // Check if only link-local IPv4 is available (no valid global address found) + if(result.ipaddress.empty()) + { + NMLOG_WARNING("Only link-local IPv4 available on %s, not returning it", interface.c_str()); + // Clear cache for link-local only + if(ethname == interface) + m_ethIPv4Address = IPAddress(); + else if(wifiname == interface) + m_wlanIPv4Address = IPAddress(); + return Core::ERROR_GENERAL; + } + // Cache the IPv4 address if(ethname == interface) m_ethIPv4Address = result; diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 4717ca40a..c1cbdfcbd 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -779,6 +779,7 @@ namespace WPEFramework g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); // autoconf = true g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); // hostname send enabled + g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, INT32_MAX, NULL); // INT32_MAX(2147483647) = infinite timeout nm_connection_add_setting(m_connection, NM_SETTING(sIpv4Conf)); /* Build up the 'IPv6' Setting */ From 13cad82373b473dfa37bc9d7d2827846516945d4 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 30 Jan 2026 11:29:45 -0500 Subject: [PATCH 220/271] Release of 1.13.0 Release of 1.13.0 --- CHANGELOG.md | 6 ++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27c79fa3c..91e1a2573 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.13.0] - 2026-01-30 +### Added +- Implemented IPv4LL support for both Ethernet and WiFi interfaces +- Implemented logic to enable WiFi upon migration +- Fixed crash of Thunder Plugin upon Async WiFiConnect by using GCancellable + ## [1.12.0] - 2025-12-23 ### Fixed - Fixed the Ethernet interface enablement upon EntOS migration diff --git a/CMakeLists.txt b/CMakeLists.txt index 44ec77638..0b73f2317 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 1) -set(VERSION_MINOR 12) +set(VERSION_MINOR 13) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 4435615e4..86183cab7 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.12.0" + "version": "1.13.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 81185915b..275a69ece 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.12.0** +**Version: 1.13.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.12.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.13.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From e822fc112b91b56b93b7de3e4c73534736608e35 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:31:05 -0500 Subject: [PATCH 221/271] =?UTF-8?q?RDKEMW-13122:=20Wi=E2=80=91Fi=20network?= =?UTF-8?q?s=20in=20the=20picker=20are=20not=20ordered=20by=20signal=20str?= =?UTF-8?q?ength=20(#271)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * RDKEMW-13122: Wi‑Fi networks in the picker are not ordered by signal strength Reason for change: Updated the onAvailableSSID to return strength and frequency as numbers so that the UI will do the sorting. Test Procedure: Check the onAvailableSSID returns strength and frequency as numbers Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR * RDKEMW-13122: Wi‑Fi networks in the picker are not ordered by signal strength Reason for change: Updated the onAvailableSSID to return strength and frequency as numbers so that the UI will do the sorting. Test Procedure: Check the onAvailableSSID returns strength and frequency as numbers Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- definition/NetworkManager.json | 20 ++--- docs/NetworkManagerPlugin.md | 48 +++++----- interface/INetworkManager.h | 24 ++--- legacy/LegacyWiFiManagerAPIs.cpp | 18 ++-- plugin/NetworkManager.h | 4 +- plugin/NetworkManagerImplementation.cpp | 89 +++++++++---------- plugin/NetworkManagerImplementation.h | 4 +- plugin/NetworkManagerJsonRpc.cpp | 8 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 4 +- plugin/gnome/NetworkManagerGnomeUtils.cpp | 20 ++--- plugin/gnome/NetworkManagerGnomeUtils.h | 4 +- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 19 ++-- .../gnome/gdbus/NetworkManagerGdbusClient.cpp | 18 ++-- .../gnome/gdbus/NetworkManagerGdbusClient.h | 2 +- .../gnome/gdbus/NetworkManagerGdbusUtils.cpp | 19 ++-- plugin/gnome/gdbus/NetworkManagerGdbusUtils.h | 2 +- plugin/rdk/NetworkManagerRDKProxy.cpp | 21 +++-- .../l2_test_LegacyPlugin_WiFiManagerAPIs.cpp | 24 ++--- tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp | 8 +- tests/l2Test/rdk/l2_test_rdkproxy.cpp | 16 ++-- tests/mocks/INetworkManagerMock.h | 2 +- tools/plugincli/NetworkManagerGdbusTest.cpp | 7 +- tools/plugincli/NetworkManagerLibnmTest.cpp | 2 +- 23 files changed, 193 insertions(+), 190 deletions(-) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 86183cab7..cd1f98dc3 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -128,18 +128,18 @@ }, "strength":{ "summary": "The WiFi Signal RSSI value in dBm", - "type": "string", - "example": "-32" + "type": "integer", + "example": -32 }, "noise":{ "summary": "The WiFi Signal Noise detected in dBm", - "type": "string", - "example": "-96" + "type": "integer", + "example": -96 }, "snr":{ "summary": "Signal to Noise Ratio(SNR) in dBm", - "type": "string", - "example": "74" + "type": "integer", + "example": 74 }, "quality":{ "summary": "WiFi Quality based on Signal to Noise Ratio (SNR)", @@ -148,8 +148,8 @@ }, "frequency":{ "summary": "The supported frequency for this SSID in GHz", - "type": "string", - "example": "2.4420" + "type": "number", + "example": 2.4420 }, "errors": { "summary": "Error string of scan failure", @@ -1109,8 +1109,8 @@ }, "rate":{ "summary": "The physical data rate in Mbps", - "type": "string", - "example": "144" + "type": "integer", + "example": 144 }, "noise":{ "$ref": "#/definitions/noise" diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 275a69ece..47a19887a 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -1367,10 +1367,10 @@ This method takes no parameters. | result.ssid | string | The WiFi SSID Name | | result.bssid | string | The BSSID of given SSID | | result.security | string | The security mode. See the `connect` method | -| result.strength | string | The WiFi Signal RSSI value in dBm | -| result.frequency | string | The supported frequency for this SSID in GHz | -| result.rate | string | The physical data rate in Mbps | -| result.noise | string | The WiFi Signal Noise detected in dBm | +| result.strength | integer | The WiFi Signal RSSI value in dBm | +| result.frequency | number | The supported frequency for this SSID in GHz | +| result.rate | integer | The physical data rate in Mbps | +| result.noise | integer | The WiFi Signal Noise detected in dBm | | result.success | boolean | Whether the request succeeded | ### Example @@ -1395,10 +1395,10 @@ This method takes no parameters. "ssid": "myHomeSSID", "bssid": "AA:BB:CC:DD:EE:FF", "security": "2", - "strength": "-32", - "frequency": "2.4420", - "rate": "144", - "noise": "-96", + "strength": -32, + "frequency": 2.442, + "rate": 144, + "noise": -96, "success": true } } @@ -1524,9 +1524,9 @@ This method takes no parameters. | result | object | | | result.ssid | string | The WiFi SSID Name | | result.quality | string | WiFi Quality based on Signal to Noise Ratio (SNR) | -| result.snr | string | Signal to Noise Ratio(SNR) in dBm | -| result.strength | string | The WiFi Signal RSSI value in dBm | -| result.noise | string | The WiFi Signal Noise detected in dBm | +| result.snr | integer | Signal to Noise Ratio(SNR) in dBm | +| result.strength | integer | The WiFi Signal RSSI value in dBm | +| result.noise | integer | The WiFi Signal Noise detected in dBm | | result.success | boolean | Whether the request succeeded | ### Example @@ -1550,9 +1550,9 @@ This method takes no parameters. "result": { "ssid": "myHomeSSID", "quality": "Excellent", - "snr": "74", - "strength": "-32", - "noise": "-96", + "snr": 74, + "strength": -32, + "noise": -96, "success": true } } @@ -1872,8 +1872,8 @@ Triggered when scan completes or when scan cancelled. | params.ssids[#] | object | | | params.ssids[#].ssid | string | Discovered SSID | | params.ssids[#].security | integer | The security mode. See `GetSupportedSecurityModes` | -| params.ssids[#].strength | string | The WiFi Signal RSSI value in dBm | -| params.ssids[#].frequency | string | The supported frequency for this SSID in GHz | +| params.ssids[#].strength | integer | The WiFi Signal RSSI value in dBm | +| params.ssids[#].frequency | number | The supported frequency for this SSID in GHz | ### Example @@ -1886,8 +1886,8 @@ Triggered when scan completes or when scan cancelled. { "ssid": "myAP-2.4", "security": 2, - "strength": "-32", - "frequency": "2.4420" + "strength": -32, + "frequency": 2.442 } ] } @@ -1932,9 +1932,9 @@ Triggered when WIFI Signal quality changed which is decided based on SNR value w | params | object | | | params.ssid | string | The WiFi SSID Name | | params.quality | string | WiFi Quality based on Signal to Noise Ratio (SNR) | -| params.snr | string | Signal to Noise Ratio(SNR) in dBm | -| params.strength | string | The WiFi Signal RSSI value in dBm | -| params.noise | string | The WiFi Signal Noise detected in dBm | +| params.snr | integer | Signal to Noise Ratio(SNR) in dBm | +| params.strength | integer | The WiFi Signal RSSI value in dBm | +| params.noise | integer | The WiFi Signal Noise detected in dBm | ### Example @@ -1945,9 +1945,9 @@ Triggered when WIFI Signal quality changed which is decided based on SNR value w "params": { "ssid": "myHomeSSID", "quality": "Excellent", - "snr": "74", - "strength": "-32", - "noise": "-96" + "snr": 74, + "strength": -32, + "noise": -96 } } ``` diff --git a/interface/INetworkManager.h b/interface/INetworkManager.h index a3097d7a5..a4488dc56 100644 --- a/interface/INetworkManager.h +++ b/interface/INetworkManager.h @@ -130,10 +130,10 @@ namespace WPEFramework string ssid; string bssid; WIFISecurityMode security; - string strength; - string frequency; - string rate; - string noise; + int32_t strength; + double frequency; + int32_t rate; + int32_t noise; }; struct EXTERNAL WIFISecurityModeInfo { @@ -252,7 +252,7 @@ namespace WPEFramework virtual uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& pin /* @in */) = 0; virtual uint32_t StopWPS(void) = 0; virtual uint32_t GetWifiState(WiFiState &state /* @out */) = 0; - virtual uint32_t GetWiFiSignalQuality(string& ssid /* @out */, string& strength /* @out */, string& noise /* @out */, string& snr /* @out */, WiFiSignalQuality& quality /* @out */) = 0; + virtual uint32_t GetWiFiSignalQuality(string& ssid /* @out */, int& strength /* @out */, int& noise /* @out */, int& snr /* @out */, WiFiSignalQuality& quality /* @out */) = 0; virtual uint32_t GetSupportedSecurityModes(ISecurityModeIterator*& modes/* @out */) const = 0; /* @brief Set the network manager plugin log level */ @@ -268,15 +268,15 @@ namespace WPEFramework enum { ID = ID_NETWORKMANAGER_NOTIFICATION }; // Network Notifications that other processes can subscribe to - virtual void onInterfaceStateChange(const InterfaceState state /* @in */, const string interface /* @in */) = 0; - virtual void onActiveInterfaceChange(const string prevActiveInterface /* @in */, const string currentActiveInterface /* @in */) = 0; - virtual void onIPAddressChange(const string interface /* @in */, const string ipversion /* @in */, const string ipaddress /* @in */, const IPStatus status /* @in */) = 0; - virtual void onInternetStatusChange(const InternetStatus prevState /* @in */, const InternetStatus currState /* @in */, const string interface /* @in */) = 0; + virtual void onInterfaceStateChange(const InterfaceState state /* @in */, const string interface /* @in */){}; + virtual void onActiveInterfaceChange(const string prevActiveInterface /* @in */, const string currentActiveInterface /* @in */){}; + virtual void onIPAddressChange(const string interface /* @in */, const string ipversion /* @in */, const string ipaddress /* @in */, const IPStatus status /* @in */){}; + virtual void onInternetStatusChange(const InternetStatus prevState /* @in */, const InternetStatus currState /* @in */, const string interface /* @in */){}; // WiFi Notifications that other processes can subscribe to - virtual void onAvailableSSIDs(const string jsonOfScanResults /* @in */) = 0; - virtual void onWiFiStateChange(const WiFiState state /* @in */) = 0; - virtual void onWiFiSignalQualityChange(const string ssid /* @in */, const string strength /* @in */, const string noise /* @in */, const string snr /* @in */, const WiFiSignalQuality quality /* @in */) = 0; + virtual void onAvailableSSIDs(const string jsonOfScanResults /* @in */){}; + virtual void onWiFiStateChange(const WiFiState state /* @in */){}; + virtual void onWiFiSignalQualityChange(const string ssid /* @in */, const int strength /* @in */, const int noise /* @in */, const int snr /* @in */, const WiFiSignalQuality quality /* @in */){}; }; // Allow other processes to register/unregister from our notifications diff --git a/legacy/LegacyWiFiManagerAPIs.cpp b/legacy/LegacyWiFiManagerAPIs.cpp index a075e43ef..12e91b0a2 100644 --- a/legacy/LegacyWiFiManagerAPIs.cpp +++ b/legacy/LegacyWiFiManagerAPIs.cpp @@ -400,11 +400,12 @@ namespace WPEFramework { response["ssid"] = ssidInfo.ssid; response["bssid"] = ssidInfo.bssid; - response["rate"] = ssidInfo.rate; - response["noise"] = ssidInfo.noise; + response["rate"] = to_string(ssidInfo.rate); + response["noise"] = to_string(ssidInfo.noise); response["security"] = JsonValue(mapToLegacySecurityMode(ssidInfo.security)); - response["signalStrength"] = ssidInfo.strength; - response["frequency"] = ssidInfo.frequency; + response["signalStrength"] = to_string(ssidInfo.strength); + std::string freqStr = to_string(ssidInfo.frequency); + response["frequency"] = freqStr.substr(0, 3); } returnJson(rc); } @@ -911,10 +912,15 @@ namespace WPEFramework { JsonObject object = ssids[i].Object(); uint32_t security = object["security"].Number(); - object["security"] = mapToLegacySecurityMode(security); - ssidsUpdated.Add(object); + JsonObject newObject; + newObject["ssid"] = object["ssid"]; + newObject["security"] = mapToLegacySecurityMode(security); + newObject["signalStrength"] = object["strength"]; + newObject["frequency"] = object["frequency"]; + ssidsUpdated.Add(newObject); } newParameters["ssids"] = ssidsUpdated; + newParameters["moreData"] = false; newParameters.ToString(json); NMLOG_INFO("Event with %d SSIDs as, %s", ssids.Length(), json.c_str()); diff --git a/plugin/NetworkManager.h b/plugin/NetworkManager.h index 6529e058e..319476f9b 100644 --- a/plugin/NetworkManager.h +++ b/plugin/NetworkManager.h @@ -94,7 +94,7 @@ namespace WPEFramework _parent.onWiFiStateChange(state); } - void onWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality) override + void onWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality) override { _parent.onWiFiSignalQualityChange(ssid, strength, noise, snr, quality); } @@ -262,7 +262,7 @@ namespace WPEFramework void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface); void onAvailableSSIDs(const string jsonOfScanResults); void onWiFiStateChange(const Exchange::INetworkManager::WiFiState state); - void onWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality); + void onWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality); private: uint32_t _connectionId; diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index ef3165a47..cd616c54c 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -36,7 +36,6 @@ namespace WPEFramework SERVICE_REGISTRATION(NetworkManagerImplementation, NETWORKMANAGER_MAJOR_VERSION, NETWORKMANAGER_MINOR_VERSION, NETWORKMANAGER_PATCH_VERSION); NetworkManagerImplementation::NetworkManagerImplementation() - : _notificationCallbacks({}) { /* Initialize STUN Endpoints */ m_stunEndpoint = "stun.l.google.com"; @@ -81,7 +80,6 @@ namespace WPEFramework m_processMonThread.join(); } } - /** * Register a notification callback */ @@ -839,7 +837,7 @@ namespace WPEFramework } /* The below implementation of GetWiFiSignalQuality is a temporary mitigation. Need to be revisited */ - uint32_t NetworkManagerImplementation::GetWiFiSignalQuality(string& ssid /* @out */, string& strength /* @out */, string& noise /* @out */, string& snr /* @out */, WiFiSignalQuality& quality /* @out */) + uint32_t NetworkManagerImplementation::GetWiFiSignalQuality(string& ssid /* @out */, int& strength /* @out */, int& noise /* @out */, int& snr /* @out */, WiFiSignalQuality& quality /* @out */) { std::string key{}, value{}, bssid{}, band{}; char buff[512] = {'\0'}; @@ -875,9 +873,9 @@ namespace WPEFramework NMLOG_WARNING("WiFi is disconnected (BSSID is empty)"); quality = WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; ssid = ""; - strength = "0"; - noise = "0"; - snr = "0"; + strength = 0; + noise = 0; + snr = 0; return Core::ERROR_NONE; } @@ -889,38 +887,27 @@ namespace WPEFramework return Core::ERROR_GENERAL; } - std::string linkSpeed; + // Collect raw values during parsing + std::string linkSpeed, rssiValue, noiseValue, avgRssiValue, freqValue; while ((!feof(fp)) && (fgets(buff, sizeof (buff), fp) != NULL)) { std::istringstream mystream(buff); if(std::getline(std::getline(mystream, key, '=') >> std::ws, value)) { if (key == "RSSI") { - strength = value; + rssiValue = value; } else if (key == "NOISE") { - noise = value; + noiseValue = value; } - else if (key == "AVG_RSSI") { // if RSSI is not available - if (strength.empty()) - strength = value; + else if (key == "AVG_RSSI") { + avgRssiValue = value; } else if (key == "FREQUENCY") { - if (!value.empty()) - { - int freq = std::stoi(value); - if (freq >= 2400 && freq < 5000) - band = "2.4GHz"; - else if (freq >= 5000 && freq < 6000) - band = "5GHz"; - else if (freq >= 6000) - band = "6GHz"; - else - band = "not known"; - } + freqValue = value; } - else if (key == "LINKSPEED") + else if (key == "LINKSPEED") { linkSpeed = value; } @@ -928,13 +915,25 @@ namespace WPEFramework } pclose(fp); - if (noise.empty()) - noise = "0"; - if (strength.empty()) - strength = "0"; + // Helper to safely convert string to int + auto toInt = [](const std::string& str, int defaultVal = 0) -> int { + return str.empty() ? defaultVal : std::stoi(str); + }; + + // Perform conversions - use RSSI if available, otherwise fallback to AVG_RSSI + strength = toInt(!rssiValue.empty() ? rssiValue : avgRssiValue, 0); + noise = toInt(noiseValue, 0); + + // Determine band from frequency + if (!freqValue.empty()) { + int freq = std::stoi(freqValue); + band = (freq >= 2400 && freq < 5000) ? "2.4GHz" : + (freq >= 5000 && freq < 6000) ? "5GHz" : + (freq >= 6000) ? "6GHz" : "not known"; + } - int16_t readRssi = std::stoi(strength); - int16_t readNoise = std::stoi(noise); + int16_t readRssi = strength; + int16_t readNoise = noise; /* Check the RSSI is within range between -10 and -100 dbm*/ if (readRssi >= 0 || readRssi < -100) { @@ -953,36 +952,36 @@ namespace WPEFramework NMLOG_DEBUG("Received Noise (%d) from wifi driver is not valid; so clamping it", readNoise); if (readNoise >= 0) { readNoise = 0; - noise = std::to_string(0); + noise = 0; } else if (readNoise < DEFAULT_NOISE) { readNoise = DEFAULT_NOISE; - noise = std::to_string(DEFAULT_NOISE); + noise = DEFAULT_NOISE; } } /*Calculate SNR = RSSI - Noise */ int16_t calculatedSnr = readRssi - readNoise; - snr = std::to_string(calculatedSnr); + snr = calculatedSnr; /* mapping rssi value when the SNR value is not proper */ if(!(calculatedSnr > 0 && calculatedSnr <= MAX_SNR_VALUE)) { - NMLOG_WARNING("calculated SNR (%d) is not valid; Lets map with RSSI (%s)", calculatedSnr, strength.c_str()); - calculatedSnr = std::stoi(strength); + NMLOG_WARNING("calculated SNR (%d) is not valid; Lets map with RSSI (%d)", calculatedSnr, strength); + calculatedSnr = strength; /* Take the absolute value */ calculatedSnr = (calculatedSnr < 0) ? -calculatedSnr : calculatedSnr; - snr = std::to_string(calculatedSnr); + snr = calculatedSnr; } - NMLOG_INFO("SSID:%s, BSSID:%s, Band:%s, RSSI:%s, Noise:%s, SNR:%s", ssid.c_str(), bssid.c_str(), band.c_str(), strength.c_str(), noise.c_str(), snr.c_str()); - NMLOG_INFO("bssid=%s,ssid=%s,rssi=%s,phyrate=%s,noise=%s,Band=%s", bssid.c_str(), ssid.c_str(), strength.c_str(), linkSpeed.c_str(), noise.c_str(), band.c_str()); + NMLOG_INFO("SSID:%s, BSSID:%s, Band:%s, RSSI:%d, Noise:%d, SNR:%d", ssid.c_str(), bssid.c_str(), band.c_str(), strength, noise, snr); + NMLOG_INFO("bssid=%s,ssid=%s,rssi=%d,phyrate=%s,noise=%d,Band=%s", bssid.c_str(), ssid.c_str(), strength, linkSpeed.c_str(), noise, band.c_str()); if (calculatedSnr == 0) { quality = WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; - strength = "0"; + strength = 0; } else if (calculatedSnr > 0 && calculatedSnr < NM_WIFI_SNR_THRESHOLD_FAIR) { @@ -1062,9 +1061,9 @@ namespace WPEFramework while (true) { std::string ssid{}; - std::string strength{}; - std::string noise{}; - std::string snr{}; + int strength = 0; + int noise = 0; + int snr = 0; Exchange::INetworkManager::WiFiSignalQuality newSignalQuality; GetWiFiSignalQuality(ssid, strength, noise, snr, newSignalQuality); @@ -1114,10 +1113,10 @@ namespace WPEFramework _notificationLock.Unlock(); } - void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality) + void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality) { _notificationLock.Lock(); - NMLOG_INFO("Posting onWiFiSignalQualityChange %s", strength.c_str()); + NMLOG_INFO("Posting onWiFiSignalQualityChange %d", strength); for (const auto callback : _notificationCallbacks) { callback->onWiFiSignalQualityChange(ssid, strength, noise, snr, quality); } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 7c798e291..565d7ee9d 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -225,7 +225,7 @@ namespace WPEFramework uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) override; uint32_t StopWPS(void) override; uint32_t GetWifiState(WiFiState &state) override; - uint32_t GetWiFiSignalQuality(string& ssid /* @out */, string& strength /* @out */, string& noise /* @out */, string& snr /* @out */, WiFiSignalQuality& quality /* @out */) override; + uint32_t GetWiFiSignalQuality(string& ssid /* @out */, int& strength /* @out */, int& noise /* @out */, int& snr /* @out */, WiFiSignalQuality& quality /* @out */) override; uint32_t SetStunEndpoint (string const endpoint /* @in */, const uint32_t port /* @in */, const uint32_t bindTimeout /* @in */, const uint32_t cacheTimeout /* @in */) override; uint32_t GetStunEndpoint (string &endpoint /* @out */, uint32_t& port /* @out */, uint32_t& bindTimeout /* @out */, uint32_t& cacheTimeout /* @out */) const override; @@ -268,7 +268,7 @@ namespace WPEFramework void ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface); void ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults); void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); - void ReportWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality); + void ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality); private: void platform_init(void); diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index ff1dd5df6..b63a322ce 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -915,9 +915,9 @@ namespace WPEFramework LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; string ssid{}; - string strength{}; - string noise{}; - string snr{}; + int strength = 0; + int noise = 0; + int snr = 0; Exchange::INetworkManager::WiFiSignalQuality quality{}; if (_networkManager) @@ -1044,7 +1044,7 @@ namespace WPEFramework Notify(_T("onWiFiStateChange"), parameters); } - void NetworkManager::onWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality) + void NetworkManager::onWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality) { Core::JSON::EnumType iquality(quality); JsonObject parameters; diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index dea7c5ef9..90f9b03f1 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -731,7 +731,7 @@ namespace WPEFramework { GBytes *ssid = NULL; int strength = 0; - std::string freq; + double freq; int security; guint32 flags, wpaFlags, rsnFlags, apFreq; if(ap == nullptr) @@ -757,7 +757,7 @@ namespace WPEFramework security = nmUtils::wifiSecurityModeFromAp(ssidString, flags, wpaFlags, rsnFlags, false); ssidObj["security"] = security; - ssidObj["strength"] = nmUtils::convertPercentageToSignalStrengtStr(strength); + ssidObj["strength"] = nmUtils::convertPercentageToSignalStrength(strength); ssidObj["frequency"] = freq; return true; } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index 3910b6c3a..d175b27a4 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -66,10 +66,10 @@ namespace WPEFramework } // Function to convert percentage (0-100) to dBm string - const char* nmUtils::convertPercentageToSignalStrengtStr(int percentage) { + int nmUtils::convertPercentageToSignalStrength(int percentage) { if (percentage <= 0 || percentage > 100) { - return ""; + return 0; } /* @@ -85,9 +85,7 @@ namespace WPEFramework const int max_dBm = -30; const int min_dBm = -90; int dBm_value = max_dBm + ((min_dBm - max_dBm) * (100 - percentage)) / 100; - static char result[8]={0}; - snprintf(result, sizeof(result), "%d", dBm_value); - return result; + return dBm_value; } std::string nmUtils::getSecurityModeString(guint32 flag, guint32 wpaFlags, guint32 rsnFlags) @@ -180,17 +178,17 @@ namespace WPEFramework return securityStr; } - std::string nmUtils::wifiFrequencyFromAp(guint32 apFreq) + double nmUtils::wifiFrequencyFromAp(guint32 apFreq) { - std::string freq; + double freq; if (apFreq >= 2400 && apFreq < 5000) - freq = "2.4"; + freq = 2.4; else if (apFreq >= 5000 && apFreq < 6000) - freq = "5"; + freq = 5; else if (apFreq >= 6000) - freq = "6"; + freq = 6; else - freq = "Not available"; + freq = 0; return freq; } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index aab7daf0a..b9632d2ee 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -40,10 +40,10 @@ namespace WPEFramework static const char* wlanIface(); static const char* ethIface(); static const char* deviceHostname(); - static const char* convertPercentageToSignalStrengtStr(int percentage); + static int convertPercentageToSignalStrength(int percentage); static bool caseInsensitiveCompare(const std::string& str1, const std::string& str2); static uint8_t wifiSecurityModeFromAp(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags, bool doPrint = true); - static std::string wifiFrequencyFromAp(guint32 apFreq); + static double wifiFrequencyFromAp(guint32 apFreq); static std::string getSecurityModeString(guint32 flags, guint32 wpaFlags, guint32 rsnFlags); static bool setNetworkManagerlogLevelToTrace(); static void setMarkerFile(const char* filename, bool unmark = false); diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index c1cbdfcbd..0f903285c 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -261,23 +261,22 @@ namespace WPEFramework } wifiInfo.bssid = (hwaddr != nullptr) ? hwaddr : "-----"; - std::string freqStr = std::to_string((double)freq/1000); - wifiInfo.frequency = freqStr.substr(0, 5); - - wifiInfo.rate = std::to_string(bitrate); - wifiInfo.noise = std::to_string(noise); - NMLOG_DEBUG("bitrate : %s kbit/s", wifiInfo.rate.c_str()); - //TODO signal strenght to dBm - wifiInfo.strength = std::string(nmUtils::convertPercentageToSignalStrengtStr(strength)); + wifiInfo.frequency = ((double)freq/1000); + + wifiInfo.rate = bitrate; + wifiInfo.noise = noise; + NMLOG_DEBUG("bitrate : %d kbit/s", wifiInfo.rate); + //TODO signal strength to dBm + wifiInfo.strength = nmUtils::convertPercentageToSignalStrength(strength); wifiInfo.security = static_cast(nmUtils::wifiSecurityModeFromAp(wifiInfo.ssid, flags, wpaFlags, rsnFlags, doPrint)); if(doPrint) { - NMLOG_INFO("ssid: %s, frequency: %s, sterngth: %s, security: %u", wifiInfo.ssid.c_str(), wifiInfo.frequency.c_str(), wifiInfo.strength.c_str(), wifiInfo.security); + NMLOG_INFO("ssid: %s, frequency: %f, strength: %d, security: %u", wifiInfo.ssid.c_str(), wifiInfo.frequency, wifiInfo.strength, wifiInfo.security); NMLOG_DEBUG("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); } else { - NMLOG_DEBUG("ssid: %s, frequency: %s, sterngth: %s, security: %u", wifiInfo.ssid.c_str(), wifiInfo.frequency.c_str(), wifiInfo.strength.c_str(), wifiInfo.security); + NMLOG_DEBUG("ssid: %s, frequency: %f, strength: %d, security: %u", wifiInfo.ssid.c_str(), wifiInfo.frequency, wifiInfo.strength, wifiInfo.security); NMLOG_DEBUG("Mode: %s", mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc": mode == NM_802_11_MODE_INFRA ? "Infrastructure": "Unknown"); } } diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp index e08f27079..5bbbaf078 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp @@ -2382,9 +2382,9 @@ namespace WPEFramework return ret; } - bool NetworkManagerClient::getWiFiSignalQuality(string& ssid, string& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality) + bool NetworkManagerClient::getWiFiSignalQuality(string& ssid, int& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality) { - Exchange::INetworkManager::WiFiSSIDInfo ssidInfo; + Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; float rssi = 0.0f; float noise = 0.0f; float floatSignalStrength = 0.0f; @@ -2398,10 +2398,10 @@ namespace WPEFramework else { ssid = ssidInfo.ssid; - if (!ssidInfo.strength.empty()) - rssi = std::stof(ssidInfo.strength.c_str()); - if (!ssidInfo.noise.empty()) - noise = std::stof(ssidInfo.noise.c_str()); + if (ssidInfo.strength) + rssi = ssidInfo.strength; + if (ssidInfo.noise) + noise = ssidInfo.noise; floatSignalStrength = (rssi - noise); if (floatSignalStrength < 0) floatSignalStrength = 0.0; @@ -2412,7 +2412,7 @@ namespace WPEFramework if (signalStrengthOut == 0) { quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_DISCONNECTED; - signalStrength = "0"; + signalStrength = 0; } else if (signalStrengthOut > 0 && signalStrengthOut < NM_WIFI_SNR_THRESHOLD_FAIR) { @@ -2431,9 +2431,9 @@ namespace WPEFramework quality = Exchange::INetworkManager::WiFiSignalQuality::WIFI_SIGNAL_EXCELLENT; } - signalStrength = std::to_string(signalStrengthOut); + signalStrength = signalStrengthOut; - NMLOG_INFO("strength success %s dBm", signalStrength.c_str()); + NMLOG_INFO("strength success %d dBm", signalStrength); } return true; diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusClient.h b/plugin/gnome/gdbus/NetworkManagerGdbusClient.h index 25f94ace2..512ab6377 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusClient.h +++ b/plugin/gnome/gdbus/NetworkManagerGdbusClient.h @@ -69,7 +69,7 @@ namespace WPEFramework bool wifiDisconnect(); bool activateKnownConnection(const std::string& interface, const std::string& knownConnectionID = ""); bool getWifiState(Exchange::INetworkManager::WiFiState &state); - bool getWiFiSignalQuality(std::string& ssid, std::string& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality); + bool getWiFiSignalQuality(std::string& ssid, int& signalStrength, Exchange::INetworkManager::WiFiSignalQuality& quality); bool startWPS(); bool stopWPS(); bool setHostname(const std::string& hostname); diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp index c487d6c5a..ad1659a96 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.cpp @@ -393,7 +393,7 @@ namespace WPEFramework return false; } g_variant_get(result, "y", &strength); - wifiInfo.strength = GnomeUtils::convertPercentageToSignalStrengtStr((int)strength); + wifiInfo.strength = GnomeUtils::convertPercentageToSignalStrength((int)strength); g_variant_unref(result); GnomeUtils::getCachedPropertyU(proxy, "Flags", &flags); @@ -403,14 +403,13 @@ namespace WPEFramework GnomeUtils::getCachedPropertyU(proxy, "Frequency", &freq); GnomeUtils::getCachedPropertyU(proxy, "MaxBitrate", &bitrate); - std::string freqStr = std::to_string((double)freq/1000); - wifiInfo.frequency = freqStr.substr(0, 5); - wifiInfo.rate = std::to_string(bitrate); + wifiInfo.frequency = ((double)freq/1000); + wifiInfo.rate = bitrate; wifiInfo.security = static_cast(wifiSecurityModeFromApFlags(wifiInfo.ssid, flags, wpaFlags, rsnFlags)); if(noise <= 0 && noise >= DEFAULT_NOISE) - wifiInfo.noise = std::to_string(noise); + wifiInfo.noise = noise; else - wifiInfo.noise = std::to_string(0); + wifiInfo.noise = 0; // NMLOG_DEBUG("SSID: %s", wifiInfo.m_ssid.c_str()); // NMLOG_DEBUG("bssid %s", wifiInfo.m_bssid.c_str()); @@ -436,10 +435,10 @@ namespace WPEFramework } // Function to convert percentage (0-100) to dBm string - const char* GnomeUtils::convertPercentageToSignalStrengtStr(int percentage) { + int GnomeUtils::convertPercentageToSignalStrength(int percentage) { if (percentage <= 0 || percentage > 100) { - return ""; + return 0; } /* @@ -455,9 +454,7 @@ namespace WPEFramework const int max_dBm = -30; const int min_dBm = -90; int dBm_value = max_dBm + ((min_dBm - max_dBm) * (100 - percentage)) / 100; - static char result[8]={0}; - snprintf(result, sizeof(result), "%d", dBm_value); - return result; + return dBm_value; } bool GnomeUtils::getWifiConnectionPaths(DbusMgr& m_dbus, const char* devicePath, std::list& paths) diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h index f02373e5a..e79c64297 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h +++ b/plugin/gnome/gdbus/NetworkManagerGdbusUtils.h @@ -86,7 +86,7 @@ namespace WPEFramework static void addGvariantToBuilder(GVariant *variant, GVariantBuilder *builder, gboolean excludeRouteMetric); static bool convertSsidInfoToJsonObject(Exchange::INetworkManager::WiFiSSIDInfo& wifiInfo, JsonObject& ssidObj); - static const char* convertPercentageToSignalStrengtStr(int percentage); + static int convertPercentageToSignalStrength(int percentage); static uint8_t wifiSecurityModeFromApFlags(const std::string& ssid, guint32 flags, guint32 wpaFlags, guint32 rsnFlags); static const char* getWifiIfname(); static const char* getEthIfname(); diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 608d22d7c..f2a1e959a 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -266,8 +266,12 @@ namespace WPEFramework { JsonObject object = ssids[i].Object(); security = object["security"].Number(); - object["security"] = mapToNewSecurityMode(security); - ssidsUpdated.Add(object); + JsonObject newObject; + newObject["ssid"] = object["ssid"]; + newObject["security"] = mapToNewSecurityMode(security); + newObject["strength"] = object["signalStrength"]; + newObject["frequency"] = object["frequency"]; + ssidsUpdated.Add(newObject); } ::_instance->ReportAvailableSSIDs(ssidsUpdated); break; @@ -1173,24 +1177,23 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { ssidInfo.ssid = string(connectedSsid.ssid); ssidInfo.bssid = string(connectedSsid.bssid); ssidInfo.security = (WIFISecurityMode)mapToNewSecurityMode(connectedSsid.securityMode); - ssidInfo.strength = to_string((int)connectedSsid.signalStrength); - ssidInfo.rate = to_string((int)connectedSsid.rate); + ssidInfo.strength = (int)connectedSsid.signalStrength; + ssidInfo.rate = (int)connectedSsid.rate; if(((int) connectedSsid.noise >= 0) || ((int) connectedSsid.noise < DEFAULT_NOISE)) { NMLOG_DEBUG ("Received Noise (%f) from wifi driver is not valid; so clamping it", connectedSsid.noise); if (connectedSsid.noise >= 0) { - ssidInfo.noise = std::to_string(0); + ssidInfo.noise = 0; } else if (connectedSsid.noise < DEFAULT_NOISE) { - ssidInfo.noise = std::to_string(DEFAULT_NOISE); + ssidInfo.noise = DEFAULT_NOISE; } } else - ssidInfo.noise = std::to_string((int)connectedSsid.noise); + ssidInfo.noise = (int)connectedSsid.noise; - std::string freqStr = to_string((double)connectedSsid.frequency/1000); - ssidInfo.frequency = freqStr.substr(0, 5); + ssidInfo.frequency = ((double)connectedSsid.frequency/1000); NMLOG_INFO ("GetConnectedSSID Success"); rc = Core::ERROR_NONE; diff --git a/tests/l2Test/legacy/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp b/tests/l2Test/legacy/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp index aa90be474..ddb81495f 100644 --- a/tests/l2Test/legacy/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp +++ b/tests/l2Test/legacy/l2_test_LegacyPlugin_WiFiManagerAPIs.cpp @@ -188,11 +188,11 @@ TEST_F(WiFiManagerTest, getConnectedSSID) { Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; ssidInfo.ssid = "my-ssid"; ssidInfo.bssid = "00:11:22:33:44:55"; - ssidInfo.rate = "100"; - ssidInfo.noise = "-50"; + ssidInfo.rate = 100; + ssidInfo.noise = -50; ssidInfo.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK; - ssidInfo.strength = "50"; - ssidInfo.frequency = "2.4"; + ssidInfo.strength = 50; + ssidInfo.frequency = 2.4; EXPECT_CALL(*mockNetworkManager, GetConnectedSSID(::testing::_)) .WillOnce(::testing::DoAll( ::testing::SetArgReferee<0>(ssidInfo), @@ -221,11 +221,11 @@ TEST_F(WiFiManagerTest, getConnectedSSIDSAE) { Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; ssidInfo.ssid = "my-ssid"; ssidInfo.bssid = "00:11:22:33:44:55"; - ssidInfo.rate = "100"; - ssidInfo.noise = "-50"; + ssidInfo.rate = 100; + ssidInfo.noise = -50; ssidInfo.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE; - ssidInfo.strength = "50"; - ssidInfo.frequency = "2.4"; + ssidInfo.strength = 50; + ssidInfo.frequency = 2.4; EXPECT_CALL(*mockNetworkManager, GetConnectedSSID(::testing::_)) .WillOnce(::testing::DoAll( ::testing::SetArgReferee<0>(ssidInfo), @@ -254,11 +254,11 @@ TEST_F(WiFiManagerTest, getConnectedSSIDEAP) { Exchange::INetworkManager::WiFiSSIDInfo ssidInfo{}; ssidInfo.ssid = "my-ssid"; ssidInfo.bssid = "00:11:22:33:44:55"; - ssidInfo.rate = "100"; - ssidInfo.noise = "-50"; + ssidInfo.rate = 100; + ssidInfo.noise = -50; ssidInfo.security = Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_EAP; - ssidInfo.strength = "50"; - ssidInfo.frequency = "2.4"; + ssidInfo.strength = 50; + ssidInfo.frequency = 2.4; EXPECT_CALL(*mockNetworkManager, GetConnectedSSID(::testing::_)) .WillOnce(::testing::DoAll( ::testing::SetArgReferee<0>(ssidInfo), diff --git a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp index 9dc75cb1f..278dcbcbd 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp @@ -386,7 +386,7 @@ TEST_F(NetworkManagerWifiTest, GetConnectedSSID_ApNotConnected) .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T(""), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"\",\"bssid\":\"\",\"security\":0,\"strength\":\"\",\"frequency\":\"\",\"rate\":\"\",\"noise\":\"\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"\",\"bssid\":\"\",\"security\":0,\"strength\":0,\"frequency\":0,\"rate\":0,\"noise\":0,\"success\":true}")); g_object_unref(deviceDummy); g_ptr_array_free(fakeDevices, TRUE); @@ -467,7 +467,7 @@ TEST_F(NetworkManagerWifiTest, GetConnectedSSID_Connected_psk) EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T(""), response)); // Update expected response to match the mock data - EXPECT_EQ(response, _T("{\"ssid\":\"TestWiFiNetwork\",\"bssid\":\"AA:BB:CC:DD:EE:FF\",\"security\":2,\"strength\":\"-39\",\"frequency\":\"2.462\",\"rate\":\"54000\",\"noise\":\"0\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"TestWiFiNetwork\",\"bssid\":\"AA:BB:CC:DD:EE:FF\",\"security\":2,\"strength\":-39,\"frequency\":2.462,\"rate\":54000,\"noise\":0,\"success\":true}")); // Free the GBytes object g_bytes_unref(fake_ssid); @@ -528,7 +528,7 @@ TEST_F(NetworkManagerWifiTest, GetConnectedSSID_Connected_EAP) EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T(""), response)); // Update expected response to match the mock data - EXPECT_EQ(response, _T("{\"ssid\":\"TestWiFiNetwork\",\"bssid\":\"AA:BB:CC:DD:EE:FF\",\"security\":3,\"strength\":\"-39\",\"frequency\":\"2.462\",\"rate\":\"54000\",\"noise\":\"0\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"TestWiFiNetwork\",\"bssid\":\"AA:BB:CC:DD:EE:FF\",\"security\":3,\"strength\":-39,\"frequency\":2.462,\"rate\":54000,\"noise\":0,\"success\":true}")); // Free the GBytes object g_bytes_unref(fake_ssid); @@ -589,7 +589,7 @@ TEST_F(NetworkManagerWifiTest, GetConnectedSSID_Connected_ssidNull) EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T(""), response)); // Update expected response to match the mock data - EXPECT_EQ(response, _T("{\"ssid\":\"\",\"bssid\":\"AA:BB:CC:DD:EE:FF\",\"security\":1,\"strength\":\"-78\",\"frequency\":\"2.462\",\"rate\":\"54000\",\"noise\":\"0\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"\",\"bssid\":\"AA:BB:CC:DD:EE:FF\",\"security\":1,\"strength\":-78,\"frequency\":2.462,\"rate\":54000,\"noise\":0,\"success\":true}")); // Free the GBytes object g_bytes_unref(fake_ssid); diff --git a/tests/l2Test/rdk/l2_test_rdkproxy.cpp b/tests/l2Test/rdk/l2_test_rdkproxy.cpp index d1b97ca9e..5bcdc3d5a 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxy.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxy.cpp @@ -921,7 +921,7 @@ TEST_F(NetworkManagerTest, GetConnectedSSID_Success) )); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":\"-30\",\"frequency\":\"2.412\",\"rate\":\"0\",\"noise\":\"0\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":-30,\"frequency\":2.412,\"rate\":0,\"noise\":0,\"success\":true}")); } TEST_F(NetworkManagerTest, GetConnectedSSID_Success_noise_9999) @@ -946,7 +946,7 @@ TEST_F(NetworkManagerTest, GetConnectedSSID_Success_noise_9999) )); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":\"-30\",\"frequency\":\"2.412\",\"rate\":\"0\",\"noise\":\"0\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":-30,\"frequency\":2.412,\"rate\":0,\"noise\":0,\"success\":true}")); } TEST_F(NetworkManagerTest, GetConnectedSSID_Success_noise_100) @@ -971,7 +971,7 @@ TEST_F(NetworkManagerTest, GetConnectedSSID_Success_noise_100) )); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":\"-30\",\"frequency\":\"2.412\",\"rate\":\"0\",\"noise\":\"-96\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":-30,\"frequency\":2.412,\"rate\":0,\"noise\":-96,\"success\":true}")); } TEST_F(NetworkManagerTest, GetConnectedSSID_Success_noise_50) @@ -996,7 +996,7 @@ TEST_F(NetworkManagerTest, GetConnectedSSID_Success_noise_50) )); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetConnectedSSID"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":\"-30\",\"frequency\":\"2.412\",\"rate\":\"0\",\"noise\":\"-50\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"TestNetwork\",\"bssid\":\"AB:CD:EF:GH:IJ:KL\",\"security\":1,\"strength\":-30,\"frequency\":2.412,\"rate\":0,\"noise\":-50,\"success\":true}")); } TEST_F(NetworkManagerTest, GetConnectedSSID_Failed) @@ -1331,7 +1331,7 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityDisconnected2) })); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"\",\"quality\":\"Disconnected\",\"snr\":\"0\",\"strength\":\"0\",\"noise\":\"0\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"\",\"quality\":\"Disconnected\",\"snr\":0,\"strength\":0,\"noise\":0,\"success\":true}")); } TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnected) @@ -1369,7 +1369,7 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnected) })); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Excellent\",\"snr\":\"66\",\"strength\":\"-30\",\"noise\":\"-96\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Excellent\",\"snr\":66,\"strength\":-30,\"noise\":-96,\"success\":true}")); } TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedGood) @@ -1407,7 +1407,7 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedGood) })); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Weak\",\"snr\":\"6\",\"strength\":\"-90\",\"noise\":\"-96\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Weak\",\"snr\":6,\"strength\":-90,\"noise\":-96,\"success\":true}")); } TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedLowBad) @@ -1445,7 +1445,7 @@ TEST_F(NetworkManagerTest, GetWiFiSignalQualityConnectedLowBad) })); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetWiFiSignalQuality"), _T("{}"), response)); - EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Excellent\",\"snr\":\"120\",\"strength\":\"-120\",\"noise\":\"0\",\"success\":true}")); + EXPECT_EQ(response, _T("{\"ssid\":\"dummySSID\",\"quality\":\"Excellent\",\"snr\":120,\"strength\":-120,\"noise\":0,\"success\":true}")); } TEST_F(NetworkManagerTest, Trace_Success_ipv4) diff --git a/tests/mocks/INetworkManagerMock.h b/tests/mocks/INetworkManagerMock.h index b89926af1..c4a98390e 100644 --- a/tests/mocks/INetworkManagerMock.h +++ b/tests/mocks/INetworkManagerMock.h @@ -47,7 +47,7 @@ class MockINetworkManager : public WPEFramework::Exchange::INetworkManager { MOCK_METHOD(uint32_t, StartWPS, (const WiFiWPS& method, const string& pin), (override)); MOCK_METHOD(uint32_t, StopWPS, (), (override)); MOCK_METHOD(uint32_t, GetWifiState, (WPEFramework::Exchange::INetworkManager::WiFiState& state), (override)); - MOCK_METHOD(uint32_t, GetWiFiSignalQuality, (string& ssid, string& strength, string& noise, string& snr, WPEFramework::Exchange::INetworkManager::WiFiSignalQuality& quality), (override)); + MOCK_METHOD(uint32_t, GetWiFiSignalQuality, (string& ssid, int& strength, int& noise, int& snr, WPEFramework::Exchange::INetworkManager::WiFiSignalQuality& quality), (override)); MOCK_METHOD(uint32_t, GetSupportedSecurityModes, (ISecurityModeIterator*& modes), (const)); MOCK_METHOD(uint32_t, SetLogLevel, (const Logging& level), (override)); MOCK_METHOD(uint32_t, SetHostname, (const string& hostname), (override)); diff --git a/tools/plugincli/NetworkManagerGdbusTest.cpp b/tools/plugincli/NetworkManagerGdbusTest.cpp index 25dd50cb1..b44ee8720 100644 --- a/tools/plugincli/NetworkManagerGdbusTest.cpp +++ b/tools/plugincli/NetworkManagerGdbusTest.cpp @@ -63,7 +63,7 @@ namespace WPEFramework { NMLOG_INFO("calling 'ReportWiFiStateChange' cb"); } - void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality) + void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality) { NMLOG_INFO("calling 'ReportWiFiSignalQualityChange' cb"); } @@ -272,10 +272,11 @@ int main() } case 10: { - std::string ssid, signalStrength; + std::string ssid; + int signalStrength; Exchange::INetworkManager::WiFiSignalQuality quality; if (nmClient->getWiFiSignalQuality(ssid, signalStrength, quality)) { - NMLOG_INFO("SSID: %s, Signal Strength: %s, Quality: %d", ssid.c_str(), signalStrength.c_str(), quality); + NMLOG_INFO("SSID: %s, Signal Strength: %d, Quality: %d", ssid.c_str(), signalStrength, quality); } else { NMLOG_ERROR("Failed to get WiFi signal strength"); } diff --git a/tools/plugincli/NetworkManagerLibnmTest.cpp b/tools/plugincli/NetworkManagerLibnmTest.cpp index 33472ce5f..650a1ba10 100644 --- a/tools/plugincli/NetworkManagerLibnmTest.cpp +++ b/tools/plugincli/NetworkManagerLibnmTest.cpp @@ -62,7 +62,7 @@ namespace WPEFramework { NMLOG_INFO("calling 'ReportWiFiStateChange' cb"); } - void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const string strength, const string noise, const string snr, const Exchange::INetworkManager::WiFiSignalQuality quality) + void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality) { NMLOG_INFO("calling 'ReportWiFiSignalQualityChange' cb"); } From 65fd13a40a70dd95f84273a28e13d0e8150796a2 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 11 Feb 2026 13:44:38 -0500 Subject: [PATCH 222/271] =?UTF-8?q?RDKEMW-13401:=20Migration=20Device=20co?= =?UTF-8?q?nnects=20to=20Wi=E2=80=91Fi=20instead=20of=20Ethernet=20(#273)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reason for Change: As the interface type is not checked before assigning the firstconnection. Firstconnection is getting assigned with a valid wifi connection when both ethernet and wifi are connected. So even when Wired connection is activated we end in activating Wifi connection. Added interface check to avoid this Test Procedure: Migration test scenario Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR --- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 0f903285c..b6583482e 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -858,13 +858,19 @@ namespace WPEFramework std::string connTypStr = connTyp; NMLOG_DEBUG("connection id: %s, type: %s", connId != NULL ? connId : "NULL", connTypStr.c_str()); - if(connTypStr == "802-11-wireless") { + // Store first connection only if it matches the interface type + if(iface == nmUtils::wlanIface() && connTypStr == "802-11-wireless") { NMLOG_INFO("wifi conn found : %s", connId); // if no known ssid given then use first wifi connection from list // it usefule when bootup there will be no known ssid if(firstConnection == NULL) firstConnection = connection; } + else if(iface == nmUtils::ethIface() && connTypStr == "802-3-ethernet") { + NMLOG_INFO("ethernet conn found : %s", connId); + if(firstConnection == NULL) + firstConnection = connection; + } if (connId != NULL && strcmp(connId, knowConnectionID.c_str()) == 0) { From 4dee56e98fd7006c65c693d0b5fdaada6b070f92 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Wed, 11 Feb 2026 16:19:39 -0500 Subject: [PATCH 223/271] Release of 2.0.0 Release of 2.0.0 --- CHANGELOG.md | 5 +++++ CMakeLists.txt | 4 ++-- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91e1a2573..a904e2f73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [2.0.0] - 2026-02-11 +### Changed +- The onAvailableSSIDs event signature changed to report strength, noise & frequency as Number +- Fixed the Activate Connection method to connect given (Ethernet and WiFi) connectionID + ## [1.13.0] - 2026-01-30 ### Added - Implemented IPv4LL support for both Ethernet and WiFi interfaces diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b73f2317..f774427b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,8 +36,8 @@ if (NOT WPEFramework_FOUND AND NOT Thunder_FOUND) endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") -set(VERSION_MAJOR 1) -set(VERSION_MINOR 13) +set(VERSION_MAJOR 2) +set(VERSION_MINOR 0) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index cd1f98dc3..dcc4dc200 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "1.13.0" + "version": "2.0.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 47a19887a..5747075c8 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 1.13.0** +**Version: 2.0.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 1.13.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 2.0.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 246245f3de7f974745e9340cee0f702d50827021 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Sun, 15 Mar 2026 23:21:23 -0400 Subject: [PATCH 224/271] RDKEMW-15479: Update networkmanager plugin documentation (#290) Reason for change: Updated Plugin documentation Test Procedure: NA Risks: low Signed-off-by: Gururaaja ESR Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- definition/NetworkManager.json | 5 +++++ docs/NetworkManagerPlugin.md | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index dcc4dc200..0891f2ccc 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -998,6 +998,11 @@ "passphrase": { "$ref": "#/definitions/passphrase" }, + "security": { + "summary": "Optional override to explicitly select the security mode; if omitted, the mode is decided based on the highest security mode provided by the SSID. See `GetSupportedSecurityModes` for valid values.", + "type": "integer", + "example": 2 + }, "ca_cert": { "summary": "The ca_cert to be used for EAP", "type": "string", diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 5747075c8..c00be0669 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -1241,7 +1241,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#even ## *WiFiConnect [method](#head.Methods)* -Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. The security mode is decided based on the highest security mode provided by the SSID. Also when called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`. +Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. By default, the security mode is decided based on the highest security mode provided by the SSID, but it can be explicitly overridden via the optional `params.security` parameter. Also when called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`. Also see: [onWiFiStateChange](#event.onWiFiStateChange) @@ -1252,6 +1252,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) | params | object | | | params.ssid | string | The WiFi SSID Name | | params.passphrase | string | The access point password | +| params?.security | integer | *(optional)* Optional override to explicitly select the security mode; if omitted, the mode is decided based on the highest security mode provided by the SSID. See `GetSupportedSecurityModes` for valid values. | | params?.ca_cert | string | *(optional)* The ca_cert to be used for EAP | | params?.client_cert | string | *(optional)* The client_cert to be used for EAP | | params?.private_key | string | *(optional)* The private_key to be used for EAP | @@ -1282,6 +1283,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) "params": { "ssid": "myHomeSSID", "passphrase": "password", + "security": 2, "ca_cert": "...", "client_cert": "...", "private_key": "...", From 44761fde7ca665ea34f797daaeaa4100ffd0a885 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 4 Mar 2026 13:52:09 -0500 Subject: [PATCH 225/271] RDKEMW-14959: Implement T2 Eventing in Network Manager Plugin (#282) * RDK-55826: Implement T2 Eventing in Network Manager Plugin Reason for Change: Added T2 marker for the identified T1 telemetry markers Test Procedure: Check whether the T2 events are received in the elk. Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR * RDK-55826: Implement T2 Eventing in Network Manager Plugin Reason for Change: Added T2 marker for the identified T1 telemetry markers Test Procedure: Check whether the T2 events are received in the elk. Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR --------- Signed-off-by: Gururaaja ESR --- CMakeLists.txt | 7 +- plugin/CMakeLists.txt | 9 +- plugin/NetworkManagerImplementation.cpp | 52 ++++++++++++ plugin/NetworkManagerImplementation.h | 1 + plugin/gnome/NetworkManagerGnomeEvents.cpp | 35 +++++++- plugin/gnome/NetworkManagerGnomeUtils.cpp | 97 ++++++++++++++++++++++ plugin/gnome/NetworkManagerGnomeUtils.h | 2 + plugin/gnome/NetworkManagerGnomeWIFI.cpp | 1 - tools/plugincli/CMakeLists.txt | 2 +- tools/upnp/CMakeLists.txt | 4 +- 10 files changed, 202 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f774427b5..50e77090d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,13 @@ get_directory_property(SEVICES_DEFINES COMPILE_DEFINITIONS) option(ENABLE_LEGACY_PLUGINS "Enable Legacy Plugins" ON) option(USE_RDK_LOGGER "Enable RDK Logger for logging" OFF ) option(ENABLE_UNIT_TESTING "Enable unit tests" OFF) +option(USE_TELEMETRY "Enable Telemetry T2 support" OFF) +if (USE_TELEMETRY) + find_package(T2 REQUIRED) + add_compile_definitions(USE_TELEMETRY=1) + message("Telemetry support enabled") +endif(USE_TELEMETRY) add_subdirectory(interface) add_subdirectory(definition) @@ -70,4 +76,3 @@ if(ENABLE_UNIT_TESTING) add_subdirectory(tests/l1Test) add_subdirectory(tests/l2Test) endif(ENABLE_UNIT_TESTING) - diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index abfd9998a..11904b9db 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -33,7 +33,9 @@ if (USE_RDK_LOGGER) include_directories(${RDKLOGGER_INCLUDE_DIRS}) endif (USE_RDK_LOGGER) - +if (USE_TELEMETRY) + include_directories(${T2_INCLUDE_DIRS}) +endif (USE_TELEMETRY) if(ENABLE_GNOME_NETWORKMANAGER) pkg_check_modules(GLIB REQUIRED glib-2.0) @@ -141,6 +143,11 @@ if (USE_RDK_LOGGER) target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${RDKLOGGER_LIBRARIES}) endif (USE_RDK_LOGGER) +if (USE_TELEMETRY) + target_link_libraries(${MODULE_NAME} PRIVATE ${T2_LIBRARIES}) + target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${T2_LIBRARIES}) +endif (USE_TELEMETRY) + install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) install(TARGETS ${MODULE_IMPL_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index cd616c54c..b05a057ac 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -20,6 +20,12 @@ #include #include #include "NetworkManagerImplementation.h" + +#if USE_TELEMETRY +#include "NetworkManagerJsonEnum.h" +#include +#endif + using namespace WPEFramework; using namespace WPEFramework::Plugin; using namespace NetworkManagerLogger; @@ -56,6 +62,10 @@ namespace WPEFramework NetworkManagerLogger::Init(); NMLOG_INFO((_T("NWMgrPlugin Out-Of-Process Instantiation; SHA: " _T(EXPAND_AND_QUOTE(PLUGIN_BUILD_REFERENCE))))); m_processMonThread = std::thread(&NetworkManagerImplementation::processMonitor, this, NM_PROCESS_MONITOR_INTERVAL_SEC); + #if USE_TELEMETRY + // Initialize Telemetry T2 for NwMgrPlugin + t2_init("NwMgrPlugin"); + #endif } NetworkManagerImplementation::~NetworkManagerImplementation() @@ -357,6 +367,13 @@ namespace WPEFramework interface = m_defaultInterface; ipaddress = result.public_ip; +#if USE_TELEMETRY + if(ipversion == "IPv4") + { + NMLOG_INFO("NM_PUBLIC_IPV4 = %s", ipaddress.c_str()); + logTelemetry("NM_PUBLIC_IPV4", ipaddress); + } +#endif return Core::ERROR_NONE; } else @@ -710,6 +727,10 @@ namespace WPEFramework for (const auto callback : _notificationCallbacks) { callback->onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); } +#if USE_TELEMETRY + NMLOG_INFO("NM_INTERFACE_STATUS = Interface changed to %s", currentActiveinterface.c_str()); + logTelemetry("NM_INTERFACE_STATUS", "Interface changed to " + currentActiveinterface); +#endif _notificationLock.Unlock(); } @@ -756,9 +777,24 @@ namespace WPEFramework { _notificationLock.Lock(); NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); +#if USE_TELEMETRY + // Log error only when ethernet is down and there's no internet + if(currState == Exchange::INetworkManager::INTERNET_NOT_AVAILABLE && + !m_ethConnected.load() && + prevState != Exchange::INetworkManager::INTERNET_NOT_AVAILABLE) + { + NMLOG_INFO("NM_ETHERNET_CONNECTIVITY = Ethernet connectivity failed"); + logTelemetry("NM_ETHERNET_CONNECTIVITY", "Ethernet connectivity failed"); + } +#endif for (const auto callback : _notificationCallbacks) { callback->onInternetStatusChange(prevState, currState, interface); } +#if USE_TELEMETRY + string stateStr = Core::EnumerateType(currState).Data(); + NMLOG_INFO("NM_INTERNET_STATUS = %s", stateStr.c_str()); + logTelemetry("NM_INTERNET_STATUS", stateStr); +#endif _notificationLock.Unlock(); } @@ -1107,6 +1143,11 @@ namespace WPEFramework _notificationLock.Lock(); NMLOG_INFO("Posting onWiFiStateChange (%d)", state); +#if USE_TELEMETRY + string stateStr = Core::EnumerateType(state).Data(); + NMLOG_INFO("NM_WIFI_STATUS = %s", stateStr.c_str()); + logTelemetry("NM_WIFI_STATUS", stateStr); +#endif for (const auto callback : _notificationCallbacks) { callback->onWiFiStateChange(state); } @@ -1122,5 +1163,16 @@ namespace WPEFramework } _notificationLock.Unlock(); } + + void NetworkManagerImplementation::logTelemetry(const std::string& eventName, const std::string& message) + { +#if USE_TELEMETRY + T2ERROR t2error = t2_event_s(eventName.c_str(), const_cast(message.c_str())); + if (t2error != T2ERROR_SUCCESS) { + NMLOG_ERROR("t2_event_s(\"%s\", \"%s\") failed with error %d", + eventName.c_str(), message.c_str(), t2error); + } +#endif + } } } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 565d7ee9d..3ccc8ae07 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -269,6 +269,7 @@ namespace WPEFramework void ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults); void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); void ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality); + void logTelemetry(const std::string& eventName, const std::string& message); private: void platform_init(void); diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 90f9b03f1..fd6ab3618 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -271,8 +271,41 @@ namespace WPEFramework } if (nm_ip_address_get_family(address) == AF_INET) { const char *ipAddress = nm_ip_address_get_address(address); - if(ipAddress != NULL) + if(ipAddress != NULL) { GnomeNetworkManagerEvents::onAddressChangeCb(iface, ipAddress, true, false); + // Get gateway MAC address for WiFi and Ethernet after IP is acquired + if(ifname == nmUtils::wlanIface() || ifname == nmUtils::ethIface()) { + static std::map gatewayMacCache; + NMClient *client = nm_object_get_client(NM_OBJECT(device)); + if (client != NULL) { + std::string gatewayMac = nmUtils::getGatewayMacAddress(client, ifname); + if (!gatewayMac.empty()) { + // Only log when MAC changes or is first time + if (gatewayMacCache[ifname] != gatewayMac) { + gatewayMacCache[ifname] = gatewayMac; +#if USE_TELEMETRY + if(ifname == nmUtils::wlanIface()) + { + NMLOG_INFO("NM_WIFI_GW_MAC = %s", gatewayMac.c_str()); + if (_instance != nullptr) + { + _instance->logTelemetry("NM_WIFI_GW_MAC", gatewayMac); + } + } + else if(ifname == nmUtils::ethIface()) + { + NMLOG_INFO("NM_ETHERNET_GW_MAC = %s", gatewayMac.c_str()); + if (_instance != nullptr) + { + _instance->logTelemetry("NM_ETHERNET_GW_MAC", gatewayMac); + } + } +#endif + } + } + } + } + } } } } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index d175b27a4..394fedbbe 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include "Module.h" @@ -389,5 +391,100 @@ namespace WPEFramework return false; } + std::string nmUtils::resolveGatewayMac(const std::string& gatewayIp) + { + std::string mac = ""; + std::string arpFile = "/proc/net/arp"; + std::ifstream file(arpFile); + std::string line; + + if (!file.is_open()) { + NMLOG_ERROR("Failed to open %s", arpFile.c_str()); + return mac; + } + + // Skip header + std::getline(file, line); + + while (std::getline(file, line)) { + std::istringstream iss(line); + std::string ip, hwType, flags, hwAddr; + + if (iss >> ip >> hwType >> flags >> hwAddr) { + if (ip == gatewayIp && hwAddr != "00:00:00:00:00:00") { + mac = hwAddr; + NMLOG_INFO("Resolved gateway IP %s to MAC %s", gatewayIp.c_str(), mac.c_str()); + break; + } + } + } + + if (mac.empty()) { + NMLOG_WARNING("Could not resolve gateway IP %s to MAC address", gatewayIp.c_str()); + } + + return mac; + } + + std::string nmUtils::getGatewayMacAddress(NMClient* client, const std::string& interface) + { + std::string gatewayMac = ""; + + if (client == NULL) { + NMLOG_ERROR("NMClient is NULL"); + return gatewayMac; + } + + if (interface.empty()) { + NMLOG_ERROR("Interface name is empty"); + return gatewayMac; + } + + // Get all active connections and find the one for our interface + const GPtrArray *activeConnections = nm_client_get_active_connections(client); + if (!activeConnections) { + NMLOG_WARNING("No active connections found"); + return gatewayMac; + } + + for (guint i = 0; i < activeConnections->len; i++) { + NMActiveConnection *activeConn = NM_ACTIVE_CONNECTION(g_ptr_array_index(activeConnections, i)); + if (!activeConn) continue; + + // Get devices for this connection + const GPtrArray *devices = nm_active_connection_get_devices(activeConn); + if (!devices) continue; + + // Check if this connection belongs to our interface + for (guint j = 0; j < devices->len; j++) { + NMDevice *device = NM_DEVICE(g_ptr_array_index(devices, j)); + if (!device) continue; + + const char *ifname = nm_device_get_iface(device); + if (ifname && interface == ifname) { + // Found the connection for our interface + NMIPConfig *ip4Config = nm_active_connection_get_ip4_config(activeConn); + if (ip4Config) { + const char *gateway = nm_ip_config_get_gateway(ip4Config); + if (gateway) { + NMLOG_DEBUG("Found gateway IP for %s: %s", interface.c_str(), gateway); + // Use ARP to resolve gateway IP to MAC address + gatewayMac = resolveGatewayMac(gateway); + return gatewayMac; + } else { + NMLOG_WARNING("No gateway found for %s", interface.c_str()); + } + } else { + NMLOG_WARNING("No IPv4 configuration found for %s", interface.c_str()); + } + return gatewayMac; + } + } + } + + NMLOG_WARNING("No active connection found for interface %s", interface.c_str()); + return gatewayMac; + } + } // Plugin } // WPEFramework diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index b9632d2ee..dbfb24b11 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -50,6 +50,8 @@ namespace WPEFramework static bool isInterfaceEnabled(const std::string& interface); static bool writePersistentHostname(const std::string& hostname); static bool readPersistentHostname(std::string& hostname); + static std::string resolveGatewayMac(const std::string& gatewayIp); + static std::string getGatewayMacAddress(NMClient* client, const std::string& interface); }; } } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index b6583482e..5dd09070d 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -945,7 +945,6 @@ namespace WPEFramework std::string activeSSID{}; NMLOG_DEBUG("wifi connect ssid: %s, security %d persist %d", ssidInfoParam.ssid.c_str(), ssidInfoParam.security, ssidInfoParam.persist); - Exchange::INetworkManager::WiFiConnectTo ssidInfo = ssidInfoParam; m_isSuccess = false; if(!createClientNewConnection()) diff --git a/tools/plugincli/CMakeLists.txt b/tools/plugincli/CMakeLists.txt index e1f5fd621..568836764 100644 --- a/tools/plugincli/CMakeLists.txt +++ b/tools/plugincli/CMakeLists.txt @@ -85,7 +85,7 @@ if(ENABLE_GNOME_GDBUS) target_compile_options(${PLUGIN_GDBUS_CLI} PRIVATE ${COMMON_COMPILE_OPTIONS}) target_include_directories(${PLUGIN_GDBUS_CLI} PRIVATE ${COMMON_INCLUDES}) - target_link_libraries(${PLUGIN_GDBUS_CLI} PRIVATE ${COMMON_LIBS} uuid) + target_link_libraries(${PLUGIN_GDBUS_CLI} PRIVATE ${COMMON_LIBS} ${LIBNM_LIBRARIES} uuid) install(TARGETS ${PLUGIN_GDBUS_CLI} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tools/upnp/CMakeLists.txt b/tools/upnp/CMakeLists.txt index 1cfa40e84..788f0540a 100644 --- a/tools/upnp/CMakeLists.txt +++ b/tools/upnp/CMakeLists.txt @@ -34,9 +34,7 @@ if (NOT GUPNP_FOUND) endif () if (USE_TELEMETRY) - find_package(T2 REQUIRED) - add_definitions(-DUSE_TELEMETRY) - include_directories(${TELEMETRY_INCLUDE_DIRS}) + include_directories(${T2_INCLUDE_DIRS}) endif (USE_TELEMETRY) add_definitions(-DENABLE_ROUTER_DISCOVERY_MAIN) From afbb7bfe2da344b5e671107fc4c26c4cd6e51d46 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 19 Mar 2026 10:38:13 -0400 Subject: [PATCH 226/271] RDKEMW-14959: Implement T2 Eventing in Network Manager Plugin (#292) * RDKEMW-14959: Implement T2 Eventing in Network Manager Plugin Reason for Change: Added T2 marker for the identified T1 telemetry markers Test Procedure: Check whether the T2 events are received in the elk. Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR * RDKEMW-14959: Implement T2 Eventing in Network Manager Plugin Reason for Change: Added T2 marker for the identified T1 telemetry markers Test Procedure: Check whether the T2 events are received in the elk. Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR --------- Signed-off-by: Gururaaja ESR --- plugin/NetworkManagerImplementation.cpp | 5 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 61 +++++++++---------- plugin/gnome/NetworkManagerGnomeUtils.cpp | 58 +++++------------- plugin/gnome/NetworkManagerGnomeUtils.h | 2 +- tests/l2Test/libnm/CMakeLists.txt | 5 ++ .../l2Test/libnm/l2_test_libnmproxyEvent.cpp | 51 ++++++++++++++-- tests/mocks/LibnmWraps.cpp | 9 +++ tests/mocks/LibnmWraps.h | 2 + tests/mocks/LibnmWrapsMock.h | 4 ++ 9 files changed, 113 insertions(+), 84 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index b05a057ac..56cedd934 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -778,9 +778,10 @@ namespace WPEFramework _notificationLock.Lock(); NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); #if USE_TELEMETRY - // Log error only when ethernet is down and there's no internet + // Log error only when ethernet is up and there's no internet if(currState == Exchange::INetworkManager::INTERNET_NOT_AVAILABLE && - !m_ethConnected.load() && + m_ethConnected.load() && + interface == "eth0" && prevState != Exchange::INetworkManager::INTERNET_NOT_AVAILABLE) { NMLOG_INFO("NM_ETHERNET_CONNECTIVITY = Ethernet connectivity failed"); diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index fd6ab3618..16bf3376e 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -163,6 +163,20 @@ namespace WPEFramework case NM_DEVICE_STATE_ACTIVATED: wifiState = "WIFI_STATE_CONNECTED"; GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTED); +#if USE_TELEMETRY + { + static std::string lastWlanGatewayMac; + std::string gatewayMac = nmUtils::getGatewayMacAddress(device); + if (!gatewayMac.empty() && lastWlanGatewayMac != gatewayMac) { + lastWlanGatewayMac = gatewayMac; + NMLOG_INFO("NM_WIFI_GW_MAC = %s", gatewayMac.c_str()); + if (_instance != nullptr) + { + _instance->logTelemetry("NM_WIFI_GW_MAC", gatewayMac); + } + } + } +#endif break; case NM_DEVICE_STATE_DEACTIVATING: wifiState = "WIFI_STATE_CONNECTION_LOST"; @@ -211,9 +225,22 @@ namespace WPEFramework case NM_DEVICE_STATE_IP_CONFIG: GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP, nmUtils::ethIface()); break; + case NM_DEVICE_STATE_ACTIVATED: +#if USE_TELEMETRY + { + static std::string lastEthGatewayMac; + std::string gatewayMac = nmUtils::getGatewayMacAddress(device); + if (!gatewayMac.empty() && lastEthGatewayMac != gatewayMac) { + lastEthGatewayMac = gatewayMac; + NMLOG_INFO("NM_ETHERNET_GW_MAC = %s", gatewayMac.c_str()); + if (_instance != nullptr) + _instance->logTelemetry("NM_ETHERNET_GW_MAC", gatewayMac); + } + } +#endif + break; case NM_DEVICE_STATE_NEED_AUTH: case NM_DEVICE_STATE_SECONDARIES: - case NM_DEVICE_STATE_ACTIVATED: case NM_DEVICE_STATE_DEACTIVATING: default: NMLOG_WARNING("Unhandiled state change %d", deviceState); @@ -273,38 +300,6 @@ namespace WPEFramework const char *ipAddress = nm_ip_address_get_address(address); if(ipAddress != NULL) { GnomeNetworkManagerEvents::onAddressChangeCb(iface, ipAddress, true, false); - // Get gateway MAC address for WiFi and Ethernet after IP is acquired - if(ifname == nmUtils::wlanIface() || ifname == nmUtils::ethIface()) { - static std::map gatewayMacCache; - NMClient *client = nm_object_get_client(NM_OBJECT(device)); - if (client != NULL) { - std::string gatewayMac = nmUtils::getGatewayMacAddress(client, ifname); - if (!gatewayMac.empty()) { - // Only log when MAC changes or is first time - if (gatewayMacCache[ifname] != gatewayMac) { - gatewayMacCache[ifname] = gatewayMac; -#if USE_TELEMETRY - if(ifname == nmUtils::wlanIface()) - { - NMLOG_INFO("NM_WIFI_GW_MAC = %s", gatewayMac.c_str()); - if (_instance != nullptr) - { - _instance->logTelemetry("NM_WIFI_GW_MAC", gatewayMac); - } - } - else if(ifname == nmUtils::ethIface()) - { - NMLOG_INFO("NM_ETHERNET_GW_MAC = %s", gatewayMac.c_str()); - if (_instance != nullptr) - { - _instance->logTelemetry("NM_ETHERNET_GW_MAC", gatewayMac); - } - } -#endif - } - } - } - } } } } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index 394fedbbe..c819e17b9 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -426,63 +426,35 @@ namespace WPEFramework return mac; } - std::string nmUtils::getGatewayMacAddress(NMClient* client, const std::string& interface) + std::string nmUtils::getGatewayMacAddress(NMDevice* device) { std::string gatewayMac = ""; - if (client == NULL) { - NMLOG_ERROR("NMClient is NULL"); + if (!device) { + NMLOG_ERROR("device is NULL"); return gatewayMac; } - if (interface.empty()) { - NMLOG_ERROR("Interface name is empty"); + if (!NM_IS_DEVICE(device)) { + NMLOG_ERROR("device is not an NMDevice"); return gatewayMac; } - // Get all active connections and find the one for our interface - const GPtrArray *activeConnections = nm_client_get_active_connections(client); - if (!activeConnections) { - NMLOG_WARNING("No active connections found"); + NMIPConfig *ip4Config = nm_device_get_ip4_config(device); + if (!ip4Config) { + NMLOG_WARNING("No IPv4 configuration found"); return gatewayMac; } - for (guint i = 0; i < activeConnections->len; i++) { - NMActiveConnection *activeConn = NM_ACTIVE_CONNECTION(g_ptr_array_index(activeConnections, i)); - if (!activeConn) continue; - - // Get devices for this connection - const GPtrArray *devices = nm_active_connection_get_devices(activeConn); - if (!devices) continue; - - // Check if this connection belongs to our interface - for (guint j = 0; j < devices->len; j++) { - NMDevice *device = NM_DEVICE(g_ptr_array_index(devices, j)); - if (!device) continue; - - const char *ifname = nm_device_get_iface(device); - if (ifname && interface == ifname) { - // Found the connection for our interface - NMIPConfig *ip4Config = nm_active_connection_get_ip4_config(activeConn); - if (ip4Config) { - const char *gateway = nm_ip_config_get_gateway(ip4Config); - if (gateway) { - NMLOG_DEBUG("Found gateway IP for %s: %s", interface.c_str(), gateway); - // Use ARP to resolve gateway IP to MAC address - gatewayMac = resolveGatewayMac(gateway); - return gatewayMac; - } else { - NMLOG_WARNING("No gateway found for %s", interface.c_str()); - } - } else { - NMLOG_WARNING("No IPv4 configuration found for %s", interface.c_str()); - } - return gatewayMac; - } - } + const char *ifname = nm_device_get_iface(device); + const char *gateway = nm_ip_config_get_gateway(ip4Config); + if (!gateway) { + NMLOG_WARNING("No gateway found for %s", ifname ? ifname : "unknown"); + return gatewayMac; } - NMLOG_WARNING("No active connection found for interface %s", interface.c_str()); + NMLOG_DEBUG("Found gateway IP for %s: %s", ifname ? ifname : "unknown", gateway); + gatewayMac = resolveGatewayMac(gateway); return gatewayMac; } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index dbfb24b11..c74944c8f 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -51,7 +51,7 @@ namespace WPEFramework static bool writePersistentHostname(const std::string& hostname); static bool readPersistentHostname(std::string& hostname); static std::string resolveGatewayMac(const std::string& gatewayIp); - static std::string getGatewayMacAddress(NMClient* client, const std::string& interface); + static std::string getGatewayMacAddress(NMDevice* device); }; } } diff --git a/tests/l2Test/libnm/CMakeLists.txt b/tests/l2Test/libnm/CMakeLists.txt index 35a7e4e42..092cc1d3c 100644 --- a/tests/l2Test/libnm/CMakeLists.txt +++ b/tests/l2Test/libnm/CMakeLists.txt @@ -30,6 +30,7 @@ add_executable(${NM_LIBNM_PROXY_L2_TEST} ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/Wraps.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/CurlWraps.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/LibnmWraps.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/GLibWraps.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp @@ -163,6 +164,10 @@ target_link_options(${NM_LIBNM_PROXY_L2_TEST} PUBLIC -Wl,-wrap,nm_remote_connection_delete -Wl,-wrap,nm_remote_connection_delete_finish -Wl,-wrap,nm_access_point_connection_valid + -Wl,-wrap,curl_multi_perform + -Wl,-wrap,curl_multi_info_read + -Wl,-wrap,curl_multi_poll + -Wl,-wrap,nm_device_get_ip4_config ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") diff --git a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp index 2a83d1686..61ba95e13 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp @@ -26,6 +26,7 @@ #include "FactoriesImplementation.h" #include "WrapsMock.h" +#include "CurlWrapsMock.h" #include "LibnmWrapsMock.h" #include "GLibWrapsMock.h" #include "ServiceMock.h" @@ -54,6 +55,7 @@ class NetworkManagerEventTest : public ::testing::Test { GCallback nmStateChange = NULL; WrapsImplMock *p_wrapsImplMock = nullptr; + CurlWrapsImplMock *p_curlWrapsImplMock = nullptr; GLibWrapsImplMock *p_gLibWrapsImplMock = nullptr; LibnmWrapsImplMock *p_libnmWrapsImplMock = nullptr; Core::ProxyType NetworkManagerImpl; @@ -79,6 +81,18 @@ class NetworkManagerEventTest : public ::testing::Test { p_wrapsImplMock = new NiceMock ; Wraps::setImpl(p_wrapsImplMock); + + p_curlWrapsImplMock = new NiceMock ; + CurlWraps::setImpl(p_curlWrapsImplMock); + ON_CALL(*p_curlWrapsImplMock, curl_multi_perform(::testing::_, ::testing::_)) + .WillByDefault(::testing::DoAll( + ::testing::SetArgPointee<1>(0), + ::testing::Return(CURLM_OK))); + ON_CALL(*p_curlWrapsImplMock, curl_multi_info_read(::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(nullptr)); + ON_CALL(*p_curlWrapsImplMock, curl_multi_poll(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(CURLM_OK)); + ON_CALL(service, COMLink()) .WillByDefault(::testing::Invoke( [this]() { @@ -158,6 +172,13 @@ class NetworkManagerEventTest : public ::testing::Test { p_wrapsImplMock = nullptr; } + CurlWraps::setImpl(nullptr); + if (p_curlWrapsImplMock != nullptr) + { + delete p_curlWrapsImplMock; + p_curlWrapsImplMock = nullptr; + } + LibnmWraps::setImpl(nullptr); if (p_libnmWrapsImplMock != nullptr) { @@ -257,6 +278,7 @@ TEST_F(NetworkManagerEventTest, onWIFIStateChanged) TEST_F(NetworkManagerEventTest, deviceStateChangeCb) { + NMDevice *ethDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) @@ -299,11 +321,11 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb) // Test with nullptr and with mock device WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(nullptr, nullptr, nullptr); - WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); - WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); - WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); - WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); - WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(ethDummyDevice, nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(ethDummyDevice, nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(ethDummyDevice, nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(ethDummyDevice, nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(ethDummyDevice, nullptr, nullptr); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); @@ -311,6 +333,8 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb) WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); + g_object_unref(ethDummyDevice); + g_object_unref(wifiDummyDevice); } TEST_F(NetworkManagerEventTest, deviceStateChangeCb_activated) @@ -467,6 +491,7 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_unmanaged) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); + g_object_unref(DummyDevice); } TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_disconnected) @@ -479,6 +504,7 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_disconnected) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); + g_object_unref(DummyDevice); } TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_prepare) @@ -491,6 +517,7 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_prepare) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); + g_object_unref(DummyDevice); } TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_ipconfig) @@ -503,4 +530,18 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_ipconfig) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); + g_object_unref(DummyDevice); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_activated) +{ + NMDevice *DummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("eth0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(DummyDevice, nullptr, nullptr); + g_object_unref(DummyDevice); } diff --git a/tests/mocks/LibnmWraps.cpp b/tests/mocks/LibnmWraps.cpp index 0a5741fbb..3e039fd42 100644 --- a/tests/mocks/LibnmWraps.cpp +++ b/tests/mocks/LibnmWraps.cpp @@ -134,6 +134,10 @@ extern "C" const char* __wrap_nm_setting_connection_get_interface_name(NMSetting return LibnmWraps::getInstance().nm_setting_connection_get_interface_name(setting); } +extern "C" NMIPConfig* __wrap_nm_device_get_ip4_config(NMDevice* device) { + return LibnmWraps::getInstance().nm_device_get_ip4_config(device); +} + extern "C" NMIPConfig* __wrap_nm_active_connection_get_ip4_config(NMActiveConnection* connection) { return LibnmWraps::getInstance().nm_active_connection_get_ip4_config(connection); } @@ -435,6 +439,11 @@ const char* LibnmWraps::nm_setting_connection_get_interface_name(NMSettingConnec return impl->nm_setting_connection_get_interface_name(setting); } +NMIPConfig* LibnmWraps::nm_device_get_ip4_config(NMDevice* device) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_get_ip4_config(device); +} + NMIPConfig* LibnmWraps::nm_active_connection_get_ip4_config(NMActiveConnection* connection) { EXPECT_NE(impl, nullptr); return impl->nm_active_connection_get_ip4_config(connection); diff --git a/tests/mocks/LibnmWraps.h b/tests/mocks/LibnmWraps.h index dc62f0a92..e492e64d2 100644 --- a/tests/mocks/LibnmWraps.h +++ b/tests/mocks/LibnmWraps.h @@ -33,6 +33,7 @@ class LibnmWrapsImpl { virtual const char* nm_setting_ip_config_get_method(NMSettingIPConfig* setting) = 0; virtual NMSettingConnection* nm_connection_get_setting_connection(NMConnection* connection) = 0; virtual const char* nm_setting_connection_get_interface_name(NMSettingConnection* setting) = 0; + virtual NMIPConfig* nm_device_get_ip4_config(NMDevice* device) = 0; virtual NMIPConfig* nm_active_connection_get_ip4_config(NMActiveConnection* connection) = 0; virtual NMIPConfig* nm_active_connection_get_ip6_config(NMActiveConnection* connection) = 0; virtual GPtrArray* nm_ip_config_get_addresses(NMIPConfig* config) = 0; @@ -220,6 +221,7 @@ class LibnmWraps { static const char* nm_setting_ip_config_get_method(NMSettingIPConfig* setting); static NMSettingConnection* nm_connection_get_setting_connection(NMConnection* connection); static const char* nm_setting_connection_get_interface_name(NMSettingConnection* setting); + static NMIPConfig* nm_device_get_ip4_config(NMDevice* device); static NMIPConfig* nm_active_connection_get_ip4_config(NMActiveConnection* connection); static NMIPConfig* nm_active_connection_get_ip6_config(NMActiveConnection* connection); static GPtrArray* nm_ip_config_get_addresses(NMIPConfig* config); diff --git a/tests/mocks/LibnmWrapsMock.h b/tests/mocks/LibnmWrapsMock.h index a728ac941..5fb09e694 100644 --- a/tests/mocks/LibnmWrapsMock.h +++ b/tests/mocks/LibnmWrapsMock.h @@ -28,6 +28,7 @@ extern "C" NMSettingIPConfig* __real_nm_connection_get_setting_ip6_config(NMConn extern "C" const char* __real_nm_setting_ip_config_get_method(NMSettingIPConfig* setting); extern "C" NMSettingConnection* __real_nm_connection_get_setting_connection(NMConnection* connection); extern "C" const char* __real_nm_setting_connection_get_interface_name(NMSettingConnection* setting); +extern "C" NMIPConfig* __real_nm_device_get_ip4_config(NMDevice* device); extern "C" NMIPConfig* __real_nm_active_connection_get_ip4_config(NMActiveConnection* connection); extern "C" NMIPConfig* __real_nm_active_connection_get_ip6_config(NMActiveConnection* connection); extern "C" GPtrArray* __real_nm_ip_config_get_addresses(NMIPConfig* config); @@ -491,6 +492,8 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { [&](NMClient *client, GAsyncResult *result, GError **error) -> gboolean { return __real_nm_client_dbus_set_property_finish(client, result, error); })); + ON_CALL(*this, nm_device_get_ip4_config(::testing::_)) + .WillByDefault(::testing::Return(nullptr)); ON_CALL(*this, nm_remote_connection_delete(::testing::_, ::testing::_, ::testing::_)) .WillByDefault(::testing::Invoke( [&](NMRemoteConnection *connection, GCancellable *cancellable, GError **error) -> gboolean { @@ -589,4 +592,5 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { MOCK_METHOD(NMDeviceStateReason, nm_device_get_state_reason, (NMDevice *device), (override)); MOCK_METHOD(int, nm_ip_address_get_family, (NMIPAddress *address), (override)); MOCK_METHOD(GVariant*, nm_connection_to_dbus, (NMConnection *connection, NMConnectionSerializationFlags flags), (override)); + MOCK_METHOD(NMIPConfig*, nm_device_get_ip4_config, (NMDevice* device), (override)); }; From 8b2e6d134939dead8617deca28ab27cebe399d0f Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 20 Mar 2026 21:08:33 -0400 Subject: [PATCH 227/271] Release of 2.1.0 Release of 2.1.0 --- CHANGELOG.md | 5 +++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a904e2f73..36b89b1ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [2.1.0] - 2026-03-20 +### Added +- Added T2 eventing from NetworkManager +- Updated documentation of the plugin + ## [2.0.0] - 2026-02-11 ### Changed - The onAvailableSSIDs event signature changed to report strength, noise & frequency as Number diff --git a/CMakeLists.txt b/CMakeLists.txt index 50e77090d..ee88d683f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 2) -set(VERSION_MINOR 0) +set(VERSION_MINOR 1) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 0891f2ccc..d2e7a120a 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "2.0.0" + "version": "2.1.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index c00be0669..9a455e383 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 2.0.0** +**Version: 2.1.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 2.0.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 2.1.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From d54eb00d0ba093add2f2dc6bef01ee2344ef0644 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Mon, 30 Mar 2026 10:22:10 -0400 Subject: [PATCH 228/271] RDKEMW-11439: Enable RDKLogger in NetworkManager Plugin (#295) * RDKEMW-11439: Enable RDKLogger in NetworkManager Plugin Reason for Change: Enabling RDKlogger and extending the support of set and get log level to include rdk_logger API Test Procedure: Check the logs in the wpeframework.log with different log level Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR * RDKEMW-11439: Enable RDKLogger in NetworkManager Plugin Reason for Change: Enabling RDKlogger and extending the support of set and get log level to include rdk_logger API Test Procedure: Check the logs in the wpeframework.log with different log level Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR --------- Signed-off-by: Gururaaja ESR --- plugin/NetworkManagerLogger.cpp | 20 ++++++++++++++++---- plugin/NetworkManagerLogger.h | 4 ++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/plugin/NetworkManagerLogger.cpp b/plugin/NetworkManagerLogger.cpp index 7b631d37e..6a58a1fe2 100644 --- a/plugin/NetworkManagerLogger.cpp +++ b/plugin/NetworkManagerLogger.cpp @@ -102,7 +102,7 @@ namespace NetworkManagerLogger { } formattedLog[kFormatMessageSize - 1] = '\0'; #ifdef USE_RDK_LOGGER - RDK_LOG(mapTordkLogLevel(level), "LOG.RDK.NWMGR", "%s\n", formattedLog); + RDK_LOG(mapTordkLogLevel(level), RDKLOGGER_MODULE_NAME, "[%s +%d] %s\n", trimPath(file), line, formattedLog); #else const char* levelMap[] = {"Fatal", "Error", "Warn", "Info", "Debug"}; struct timeval tv; @@ -125,15 +125,27 @@ namespace NetworkManagerLogger { gDefaultLogLevel = level; NMLOG_INFO("NetworkManager logLevel:%d", level); #ifdef USE_RDK_LOGGER - // TODO : Inform RDKLogger to change the log level + rdk_logger_set_logLevel(RDKLOGGER_MODULE_NAME, mapTordkLogLevel(level)); #endif } void GetLevel(LogLevel& level) { - level = gDefaultLogLevel; #ifdef USE_RDK_LOGGER - // TODO : Inform RDKLogger to change the log level + // Query RDK Logger for the current effective level by probing from most to least verbose + if (rdk_logger_is_logLevel_enabled(RDKLOGGER_MODULE_NAME, RDK_LOG_DEBUG)) + level = DEBUG_LEVEL; + else if (rdk_logger_is_logLevel_enabled(RDKLOGGER_MODULE_NAME, RDK_LOG_INFO)) + level = INFO_LEVEL; + else if (rdk_logger_is_logLevel_enabled(RDKLOGGER_MODULE_NAME, RDK_LOG_WARN)) + level = WARNING_LEVEL; + else if (rdk_logger_is_logLevel_enabled(RDKLOGGER_MODULE_NAME, RDK_LOG_ERROR)) + level = ERROR_LEVEL; + else + level = FATAL_LEVEL; + gDefaultLogLevel = level; +#else + level = gDefaultLogLevel; #endif } } // namespace NetworkManagerLogger diff --git a/plugin/NetworkManagerLogger.h b/plugin/NetworkManagerLogger.h index 5982ba878..4c35f1abd 100644 --- a/plugin/NetworkManagerLogger.h +++ b/plugin/NetworkManagerLogger.h @@ -20,6 +20,10 @@ #ifndef NM_LOGGER_H #define NM_LOGGER_H +#ifdef USE_RDK_LOGGER +#define RDKLOGGER_MODULE_NAME "LOG.RDK.NWMGR" +#endif + #include #include #include From 86d666251e0aa4942df2c77b3dce3f69ed5d1b94 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 9 Apr 2026 16:53:40 -0400 Subject: [PATCH 229/271] RDKEMW-10793: [NetworkManager] Reduce repetitive logging (#299) Reason for Change: Changed the repetitive getIPSettings log from INFO to debug Test Procedure: Check whether the logs are getting printed in the wpeframework.log Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR --- legacy/LegacyNetworkAPIs.cpp | 21 ++++++++++++++++----- plugin/gnome/NetworkManagerGnomeProxy.cpp | 6 +++--- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/legacy/LegacyNetworkAPIs.cpp b/legacy/LegacyNetworkAPIs.cpp index 7bf3b941c..d5924ee54 100644 --- a/legacy/LegacyNetworkAPIs.cpp +++ b/legacy/LegacyNetworkAPIs.cpp @@ -31,6 +31,8 @@ using namespace WPEFramework::Plugin; #define LOG_INPARAM() { string json; parameters.ToString(json); NMLOG_INFO("params=%s", json.c_str() ); } #define LOG_OUTPARAM() { string json; response.ToString(json); NMLOG_INFO("response=%s", json.c_str() ); } +#define DEBUGLOG_INPARAM() { string json; parameters.ToString(json); NMLOG_DEBUG("params=%s", json.c_str() ); } +#define DEBUGLOG_OUTPARAM() { string json; response.ToString(json); NMLOG_DEBUG("response=%s", json.c_str() ); } #define returnJson(rc) \ { \ @@ -516,7 +518,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { uint32_t rc = Core::ERROR_GENERAL; JsonObject tmpResponse; - LOG_INPARAM(); + DEBUGLOG_INPARAM(); rc = internalGetIPSettings(parameters, tmpResponse); if (tmpResponse.HasLabel("ipaddr") && (!tmpResponse["ipaddr"].String().empty())) @@ -526,17 +528,26 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { NMLOG_INFO("IP Address not assigned to the given interface yet"); rc = Core::ERROR_GENERAL; } - returnJson(rc); + if (Core::ERROR_NONE == rc) + response["success"] = true; + else + response["success"] = false; + DEBUGLOG_OUTPARAM(); + return Core::ERROR_NONE; } uint32_t Network::getIPSettings2 (const JsonObject& parameters, JsonObject& response) { - LOG_INPARAM(); + DEBUGLOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; rc = internalGetIPSettings(parameters, response); - - returnJson(rc); + if (Core::ERROR_NONE == rc) + response["success"] = true; + else + response["success"] = false; + DEBUGLOG_OUTPARAM(); + return Core::ERROR_NONE; } uint32_t Network::isConnectedToInternet(const JsonObject& parameters, JsonObject& response) diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 85326d633..1103cee38 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -716,7 +716,7 @@ namespace WPEFramework } result.ipaddress = nm_ip_address_get_address(ipAddr); result.prefix = nm_ip_address_get_prefix(ipAddr); - NMLOG_INFO("IPv4 addr: %s/%d", result.ipaddress.c_str(), result.prefix); + NMLOG_DEBUG("IPv4 addr: %s/%d", result.ipaddress.c_str(), result.prefix); } } gateway = nm_ip_config_get_gateway(ip4_config); @@ -781,14 +781,14 @@ namespace WPEFramework if (ipStr.compare(0, 5, "fe80:") == 0 || ipStr.compare(0, 6, "fe80::") == 0) { result.ula = ipStr; - NMLOG_INFO("link-local ip: %s", result.ula.c_str()); + NMLOG_DEBUG("link-local ip: %s", result.ula.c_str()); } else { result.prefix = nm_ip_address_get_prefix(ipAddr); if(result.ipaddress.empty()) // SLAAC mutiple ip not added result.ipaddress = ipStr; - NMLOG_INFO("global ip %s/%d", ipStr.c_str(), result.prefix); + NMLOG_DEBUG("global ip %s/%d", ipStr.c_str(), result.prefix); } } } From 79d1db6bd364c58b2544b5312a58e96f1ab92afe Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Sat, 18 Apr 2026 00:03:36 +0530 Subject: [PATCH 230/271] RDKEMW-15309 : Improvements in Wifi Connection Processing in Network Manager plugin (#300) * RDK-60453 [NW-Plugin]BSSID Improvements in Wifi Connection Processing (#283) * spike Initial code change * InetworkmanagerMock fix * test case updated * api name changed * code cleanup * improved test coverage * already connected check updated * error fix * unit test case updated * update the review comments * Copilot review comments * review comment updated * doc updated * update log line * specific object path null check added * copilot review comment updated * RDKEMW-15980: Adding breakpad support in networkmanager plugin Reason for change: Integrated breakpad support in networkmanager plugin Test Procedure: Check whether minidumps are generated properly Priority:P1 Risks: Medium Signed-off-by: Gururaaja ESR * loglevel updated * address sanitizer added * add process monitor memmeory * networkmanager asan linking * wait debugg added * wificonnect scanning removed * removed address sanitizer * AP object path fix bug fix * gamilLoop getContext removed * unref m_connection * more memmory leak fix * Revert "RDKEMW-15980: Adding breakpad support in networkmanager plugin" This reverts commit 63073e785dbd32778666c3578e60d9788d9112f1. * updated review comments * create minimal eth connection update * update workflow * bssid print removed * gmainloop context issue fix added --------- Signed-off-by: Gururaaja ESR Co-authored-by: gururaajar --- definition/NetworkManager.json | 54 ++- docs/NetworkManagerPlugin.md | 65 ++- interface/INetworkManager.h | 11 + plugin/CMakeLists.txt | 2 + plugin/NetworkManager.h | 1 + plugin/NetworkManagerImplementation.h | 1 + plugin/NetworkManagerJsonRpc.cpp | 40 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 43 +- plugin/gnome/NetworkManagerGnomeProxy.cpp | 49 ++- plugin/gnome/NetworkManagerGnomeUtils.cpp | 16 +- plugin/gnome/NetworkManagerGnomeUtils.h | 1 + plugin/gnome/NetworkManagerGnomeWIFI.cpp | 392 ++++++++++++++---- plugin/gnome/NetworkManagerGnomeWIFI.h | 3 +- plugin/rdk/NetworkManagerRDKProxy.cpp | 7 + tests/l2Test/libnm/l2_test_libnmproxy.cpp | 2 +- .../l2Test/libnm/l2_test_libnmproxyEvent.cpp | 25 +- tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp | 283 ++++++++----- tests/mocks/INetworkManagerMock.h | 1 + 18 files changed, 768 insertions(+), 228 deletions(-) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index d2e7a120a..4d1fd76a5 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -262,7 +262,7 @@ } }, "GetPrimaryInterface": { - "summary": "Gets the primary/default network interface for the device. The active network interface is defined as the one that can make requests to the external network. Returns one of the supported interfaces as per `GetAvailableInterfaces`.", + "summary": "Gets the primary/default network interface for the device. The active network interface is defined as the one that can make requests to the external network. Returns one of the supported interfaces as per `GetAvailableInterfaces`. If no active network is available, it returns empty string.", "result": { "type": "object", "properties": { @@ -984,6 +984,36 @@ ] } }, + "ConnectToKnownSSID":{ + "summary": "Connects to a saved SSID. The `ssid` parameter is mandatory. Returns failure if `ssid` is not specified or not found in the saved SSIDs list.", + "events":{ + "onWiFiStateChange" : "Triggered when Wifi state changes to CONNECTING, CONNECTED .", + "onAddressChange" : "Triggered when an IP Address is assigned or lost", + "onInternetStatusChange" : "Triggered when internet connection state changed" + }, + "params": { + "type": "object", + "properties": { + "ssid": { + "$ref": "#/definitions/ssid" + } + }, + "required": [ + "ssid" + ] + }, + "result": { + "type": "object", + "properties": { + "success":{ + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] + } + }, "WiFiConnect":{ "summary": "Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. The security mode is decided based on the highest security mode provided by the SSID. Also when called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`.", "events":{ @@ -1003,6 +1033,16 @@ "type": "integer", "example": 2 }, + "bssid": { + "summary": "BSSID to connect to. If specified, restricts connection to this BSSID only. Defaults to the best available BSSID for the SSID.", + "type": "string", + "example": "00:11:22:33:44:55" + }, + "frequency": { + "summary": "Frequency band: `1` - 2.4GHz, `2` - 5GHz. If specified, connects only to SSIDs on the given frequency band. Defaults to best available.", + "type": "integer", + "example": 2 + }, "ca_cert": { "summary": "The ca_cert to be used for EAP", "type": "string", @@ -1053,11 +1093,7 @@ "type": "boolean", "example": true } - }, - "required": [ - "ssid", - "passphrase" - ] + } }, "result": { "type": "object", @@ -1469,6 +1505,11 @@ "type": "string", "example": "myAP-2.4" }, + "bssid":{ + "summary": "Discovered BSSID", + "type": "string", + "example": "00:11:22:33:44:55" + }, "security":{ "$ref": "#/definitions/security" }, @@ -1481,6 +1522,7 @@ }, "required": [ "ssid", + "bssid", "security", "strength", "frequency" diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 9a455e383..1f350da82 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -94,6 +94,7 @@ NetworkManager interface methods: | [GetKnownSSIDs](#method.GetKnownSSIDs) | Gets list of saved SSIDs | | [AddToKnownSSIDs](#method.AddToKnownSSIDs) | Saves the SSID, passphrase, and security mode for upcoming and future sessions | | [RemoveKnownSSID](#method.RemoveKnownSSID) | Remove given SSID from saved SSIDs | +| [ConnectToKnownSSID](#method.ConnectToKnownSSID) | Connects to a saved SSID | | [WiFiConnect](#method.WiFiConnect) | Initiates request to connect to the specified SSID with the given passphrase | | [WiFiDisconnect](#method.WiFiDisconnect) | Disconnects from the currently connected SSID | | [GetConnectedSSID](#method.GetConnectedSSID) | Returns the connected SSID information | @@ -257,7 +258,7 @@ This method takes no parameters. ## *GetPrimaryInterface [method](#head.Methods)* -Gets the primary/default network interface for the device. The active network interface is defined as the one that can make requests to the external network. Returns one of the supported interfaces as per `GetAvailableInterfaces`. +Gets the primary/default network interface for the device. The active network interface is defined as the one that can make requests to the external network. Returns one of the supported interfaces as per `GetAvailableInterfaces`. If no active network is available, it returns empty string. ### Parameters @@ -1238,10 +1239,58 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#even } ``` + +## *ConnectToKnownSSID [method](#head.Methods)* + +Connects to a saved SSID. The `ssid` parameter is mandatory. Returns failure if `ssid` is not specified or not found in the saved SSIDs list. + +Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) + +### Parameters + +| Name | Type | Description | +| :-------- | :-------- | :-------- | +| params | object | | +| params.ssid | string | The WiFi SSID Name | + +### Result + +| Name | Type | Description | +| :-------- | :-------- | :-------- | +| result | object | | +| result.success | boolean | Whether the request succeeded | + +### Example + +#### Request + +```json +{ + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.ConnectToKnownSSID", + "params": { + "ssid": "myHomeSSID" + } +} +``` + +#### Response + +```json +{ + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } +} +``` + ## *WiFiConnect [method](#head.Methods)* -Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. By default, the security mode is decided based on the highest security mode provided by the SSID, but it can be explicitly overridden via the optional `params.security` parameter. Also when called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`. +Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. The security mode is decided based on the highest security mode provided by the SSID. Also when called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`. Also see: [onWiFiStateChange](#event.onWiFiStateChange) @@ -1250,9 +1299,11 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.ssid | string | The WiFi SSID Name | -| params.passphrase | string | The access point password | -| params?.security | integer | *(optional)* Optional override to explicitly select the security mode; if omitted, the mode is decided based on the highest security mode provided by the SSID. See `GetSupportedSecurityModes` for valid values. | +| params?.ssid | string | *(optional)* The WiFi SSID Name | +| params?.passphrase | string | *(optional)* The access point password | +| params?.security | integer | *(optional)* Optional override to explicitly select the security mode; if omitted, the mode is decided based on the highest security mode provided by the SSID. See `GetSupportedSecurityModes` for valid values | +| params?.bssid | string | *(optional)* BSSID to connect to. If specified, restricts connection to this BSSID only. Defaults to the best available BSSID for the SSID | +| params?.frequency | integer | *(optional)* Frequency band: `1` - 2.4GHz, `2` - 5GHz. If specified, connects only to SSIDs on the given frequency band. Defaults to best available | | params?.ca_cert | string | *(optional)* The ca_cert to be used for EAP | | params?.client_cert | string | *(optional)* The client_cert to be used for EAP | | params?.private_key | string | *(optional)* The private_key to be used for EAP | @@ -1284,6 +1335,8 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) "ssid": "myHomeSSID", "passphrase": "password", "security": 2, + "bssid": "00:11:22:33:44:55", + "frequency": 2, "ca_cert": "...", "client_cert": "...", "private_key": "...", @@ -1873,6 +1926,7 @@ Triggered when scan completes or when scan cancelled. | params.ssids | array | On Available SSID's | | params.ssids[#] | object | | | params.ssids[#].ssid | string | Discovered SSID | +| params.ssids[#].bssid | string | Discovered BSSID | | params.ssids[#].security | integer | The security mode. See `GetSupportedSecurityModes` | | params.ssids[#].strength | integer | The WiFi Signal RSSI value in dBm | | params.ssids[#].frequency | number | The supported frequency for this SSID in GHz | @@ -1887,6 +1941,7 @@ Triggered when scan completes or when scan cancelled. "ssids": [ { "ssid": "myAP-2.4", + "bssid": "00:11:22:33:44:55", "security": 2, "strength": -32, "frequency": 2.442 diff --git a/interface/INetworkManager.h b/interface/INetworkManager.h index a4488dc56..15c739cff 100644 --- a/interface/INetworkManager.h +++ b/interface/INetworkManager.h @@ -103,6 +103,14 @@ namespace WPEFramework WIFI_SECURITY_EAP /* @text: EAP */, }; + enum WIFIFrequency : uint8_t + { + WIFI_FREQUENCY_NONE /* @text: NONE */, + WIFI_FREQUENCY_2_4_GHZ /* @text: 2.4GHz */, + WIFI_FREQUENCY_5_GHZ /* @text: 5GHz */, + WIFI_FREQUENCY_6_GHZ /* @text: 6GHz */, + }; + struct EXTERNAL WiFiScanResults { string ssid; WIFISecurityMode security; @@ -113,6 +121,8 @@ namespace WPEFramework struct EXTERNAL WiFiConnectTo { string ssid; string passphrase; + string bssid; + WIFIFrequency frequency; WIFISecurityMode security; string ca_cert; string client_cert; @@ -244,6 +254,7 @@ namespace WPEFramework virtual uint32_t GetKnownSSIDs(IStringIterator*& ssids /* @out */) = 0; virtual uint32_t AddToKnownSSIDs(const WiFiConnectTo& ssid /* @in */) = 0; virtual uint32_t RemoveKnownSSID(const string& ssid /* @in */) = 0; + virtual uint32_t ConnectToKnownSSID(const string& ssid /* @in */) = 0; virtual uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) = 0; virtual uint32_t WiFiDisconnect(void) = 0; diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 11904b9db..d834861d2 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -75,6 +75,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES CXX_STANDARD_REQUIRED YES FRAMEWORK FALSE) + add_library(${MODULE_IMPL_NAME} SHARED NetworkManagerImplementation.cpp NetworkManagerConnectivity.cpp @@ -135,6 +136,7 @@ target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ) + target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${CURL_LIBRARIES}) target_include_directories(${MODULE_IMPL_NAME} PRIVATE ${CURL_INCLUDE_DIRS}) diff --git a/plugin/NetworkManager.h b/plugin/NetworkManager.h index 319476f9b..6a101bdf7 100644 --- a/plugin/NetworkManager.h +++ b/plugin/NetworkManager.h @@ -247,6 +247,7 @@ namespace WPEFramework uint32_t GetKnownSSIDs(const JsonObject& parameters, JsonObject& response); uint32_t AddToKnownSSIDs(const JsonObject& parameters, JsonObject& response); uint32_t RemoveKnownSSID(const JsonObject& parameters, JsonObject& response); + uint32_t ConnectToKnownSSID(const JsonObject& parameters, JsonObject& response); uint32_t WiFiConnect(const JsonObject& parameters, JsonObject& response); uint32_t WiFiDisconnect(const JsonObject& parameters, JsonObject& response); uint32_t GetConnectedSSID(const JsonObject& parameters, JsonObject& response); diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 3ccc8ae07..8a0c33d0a 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -217,6 +217,7 @@ namespace WPEFramework uint32_t GetKnownSSIDs(IStringIterator*& ssids /* @out */) override; uint32_t AddToKnownSSIDs(const WiFiConnectTo& ssid /* @in */) override; uint32_t RemoveKnownSSID(const string& ssid /* @in */) override; + uint32_t ConnectToKnownSSID(const string& ssid /* @in */) override; uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) override; uint32_t WiFiDisconnect(void) override; diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index b63a322ce..22af0cdba 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -75,6 +75,7 @@ namespace WPEFramework Register("GetKnownSSIDs", &NetworkManager::GetKnownSSIDs, this); Register("AddToKnownSSIDs", &NetworkManager::AddToKnownSSIDs, this); Register("RemoveKnownSSID", &NetworkManager::RemoveKnownSSID, this); + Register("ConnectToKnownSSID", &NetworkManager::ConnectToKnownSSID, this); Register("WiFiConnect", &NetworkManager::WiFiConnect, this); Register("WiFiDisconnect", &NetworkManager::WiFiDisconnect, this); Register("GetConnectedSSID", &NetworkManager::GetConnectedSSID, this); @@ -112,6 +113,7 @@ namespace WPEFramework Unregister("GetKnownSSIDs"); Unregister("AddToKnownSSIDs"); Unregister("RemoveKnownSSID"); + Unregister("ConnectToKnownSSID"); Unregister("WiFiConnect"); Unregister("WiFiDisconnect"); Unregister("GetConnectedSSID"); @@ -766,6 +768,29 @@ namespace WPEFramework returnJson(rc); } + uint32_t NetworkManager::ConnectToKnownSSID(const JsonObject& parameters, JsonObject& response) + { + LOG_INPARAM(); + uint32_t rc = Core::ERROR_GENERAL; + string ssid{}; + + if (parameters.HasLabel("ssid")) + ssid = parameters["ssid"].String(); + + if (ssid.empty()) { + NMLOG_WARNING("ssid not provided or empty in ConnectToKnownSSID request!"); + rc = Core::ERROR_BAD_REQUEST; + } + else if (_networkManager) { + rc = _networkManager->ConnectToKnownSSID(ssid); + } + else { + rc = Core::ERROR_UNAVAILABLE; + } + + returnJson(rc); + } + uint32_t NetworkManager::WiFiConnect(const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; @@ -778,7 +803,20 @@ namespace WPEFramework if (parameters.HasLabel("passphrase")) ssid.passphrase = parameters["passphrase"].String(); - + + if (parameters.HasLabel("bssid")) + ssid.bssid = parameters["bssid"].String(); + if (parameters.HasLabel("frequency")) + { + int freq = parameters["frequency"].Number(); + if (freq < 1 || freq > 3) { + NMLOG_WARNING("Invalid frequency value: %d (valid: 1=2.4GHz, 2=5GHz, 3=6GHz)", freq); + rc = Core::ERROR_BAD_REQUEST; + returnJson(rc); + } + ssid.frequency = static_cast (freq); + } + if (parameters.HasLabel("security")) ssid.security= static_cast (parameters["security"].Number()); diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 16bf3376e..761c39fba 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -468,6 +468,12 @@ namespace WPEFramework g_signal_connect(nmEvents->client, NM_CLIENT_DEVICE_ADDED, G_CALLBACK(deviceAddedCB), nmEvents); g_signal_connect(nmEvents->client, NM_CLIENT_DEVICE_REMOVED, G_CALLBACK(deviceRemovedCB), nmEvents); + if(devices == nullptr) + { + NMLOG_ERROR("Failed to get device list."); + return nullptr; + } + for (u_int count = 0; count < devices->len; count++) { NMDevice *device = NM_DEVICE(g_ptr_array_index(devices, count)); @@ -776,6 +782,16 @@ namespace WPEFramework free(ssidStr); } ssidObj["ssid"] = ssidString; + const char *bssidPtr = nm_access_point_get_bssid(ap); + std::string bssid = bssidPtr ? bssidPtr : ""; + if (!bssid.empty()) { + ssidObj["bssid"] = bssid; + } + else + { + NMLOG_WARNING("BSSID is null for SSID: %s", ssidString.c_str()); + ssidObj["bssid"] = ""; + } strength = nm_access_point_get_strength(ap); apFreq = nm_access_point_get_frequency(ap); flags = nm_access_point_get_flags(ap); @@ -801,20 +817,33 @@ namespace WPEFramework NMLOG_ERROR("Not a wifi object "); return; } - JsonArray ssidList = JsonArray(); - NMAccessPoint *ap = nullptr; + const GPtrArray *accessPoints = nm_device_wifi_get_access_points(wifiDevice); + + if (accessPoints == nullptr) { + NMLOG_ERROR("scanning result No access points found !"); + _nmEventInstance->doScanNotify = false; + return; + } + + if(!_nmEventInstance->doScanNotify) + { + NMLOG_DEBUG("scan result received; notify disabled, skipping"); + return; + } + + NMLOG_INFO("No of AP Available = %d", static_cast(accessPoints->len)); + + JsonArray ssidList = JsonArray(); for (guint i = 0; i < accessPoints->len; i++) { - JsonObject ssidObj; - ap = static_cast(accessPoints->pdata[i]); + JsonObject ssidObj{}; + NMAccessPoint *ap = static_cast(accessPoints->pdata[i]); if(GnomeNetworkManagerEvents::apToJsonObject(ap, ssidObj)) ssidList.Add(ssidObj); } - NMLOG_DEBUG("No of AP Available = %d", static_cast(accessPoints->len)); - - if(_nmEventInstance->doScanNotify) { + if(_instance != nullptr) { _nmEventInstance->doScanNotify = false; _instance->ReportAvailableSSIDs(ssidList); } diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 1103cee38..a36a28c1d 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -139,7 +139,6 @@ namespace WPEFramework static bool modifyDefaultConnConfig(NMClient *client) { - GError *error = NULL; const GPtrArray *connections = NULL; NMConnection *connection = NULL; std::string hostname{}; @@ -638,7 +637,7 @@ namespace WPEFramework deviceState = nm_device_get_state(device); if(deviceState < NM_DEVICE_STATE_DISCONNECTED) { - NMLOG_WARNING("Device state is not a valid state: (%d)", deviceState); + NMLOG_WARNING("%s state is not a valid state: (%d)", interface.c_str(), deviceState); return Core::ERROR_GENERAL; } @@ -700,7 +699,7 @@ namespace WPEFramework NMLOG_WARNING("no IPv4 configurtion on %s", interface.c_str()); if(ipByte) { - for (int i = 0; i < ipByte->len; i++) + for (guint i = 0; i < ipByte->len; i++) { ipAddr = static_cast(ipByte->pdata[i]); if(ipAddr) @@ -771,7 +770,7 @@ namespace WPEFramework NMLOG_WARNING("no IPv6 configurtion on %s", interface.c_str()); if(ipArray) { - for (int i = 0; i < ipArray->len; i++) + for (guint i = 0; i < ipArray->len; i++) { ipAddr = static_cast(ipArray->pdata[i]); if(ipAddr) @@ -910,6 +909,14 @@ namespace WPEFramework return rc; } + uint32_t NetworkManagerImplementation::ConnectToKnownSSID(const string& ssid /* @in */) + { + uint32_t rc = Core::ERROR_GENERAL; + if(wifi->connectToKnownSSID(ssid)) + rc = Core::ERROR_NONE; + return rc; + } + uint32_t NetworkManagerImplementation::RemoveKnownSSID(const string& ssid /* @in */) { uint32_t rc = Core::ERROR_GENERAL; @@ -922,27 +929,33 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; - // Check the last scanning time and if it exceeds 5 sec do a rescanning - if(!wifi->isWifiScannedRecently()) + if(ssid.ssid.empty()) { - nmEvent->setwifiScanOptions(false); - if(!wifi->wifiScanRequest()) - NMLOG_WARNING("scanning failed but try to connect"); + NMLOG_WARNING("ssid is empty activating last connected ssid !"); + if(_instance != NULL && wifi->activateKnownConnection(nmUtils::wlanIface(), _instance->m_lastConnectedSSID)) + { + rc = Core::ERROR_NONE; + } + else + { + NMLOG_ERROR("activating last connected ssid failed"); + } + return rc; } - if(ssid.ssid.empty() && _instance != NULL) + if(ssid.ssid.size() > 32) { - NMLOG_WARNING("ssid is empty activating last connectd ssid !"); - if(wifi->activateKnownConnection(nmUtils::wlanIface(), _instance->m_lastConnectedSSID)) - rc = Core::ERROR_NONE; + NMLOG_WARNING("SSID is invalid"); + return rc; } - else if(ssid.ssid.size() <= 32) + + if(!ssid.bssid.empty() && !nmUtils::isValidBSSID(ssid.bssid)) { - if(wifi->wifiConnect(ssid)) - rc = Core::ERROR_NONE; + return Core::ERROR_GENERAL; } - else - NMLOG_WARNING("SSID is invalid"); + + if(wifi->wifiConnect(ssid)) + rc = Core::ERROR_NONE; return rc; } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index c819e17b9..7d97e5e83 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -195,6 +196,19 @@ namespace WPEFramework return freq; } + bool nmUtils::isValidBSSID(const std::string& bssid) + { + // Regular expression to match valid BSSID formats (e.g., "00:11:22:33:44:55") + static const std::regex bssidRegex("^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$"); + if (!std::regex_match(bssid, bssidRegex)) + { + NMLOG_ERROR("Invalid BSSID format Expected format is XX:XX:XX:XX:XX:XX where X is a hexadecimal digit."); + return false; + } + + return true; + } + bool nmUtils::caseInsensitiveCompare(const std::string& str1, const std::string& str2) { std::string upperStr1 = str1; @@ -270,7 +284,7 @@ namespace WPEFramework bool nmUtils::setNetworkManagerlogLevelToTrace() { /* set networkmanager daemon log level based on current plugin log level */ - const char* command = "nmcli general logging level TRACE domains ALL"; + const char* command = "nmcli general logging level TRACE domains PLATFORM,DEVICE,WIFI,ETHER,DNS,DHCP4,DHCP6,DEVICE,SETTINGS,DISPATCH"; // Execute the command using popen FILE *pipe = popen(command, "r"); diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index c74944c8f..e336ddc35 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -52,6 +52,7 @@ namespace WPEFramework static bool readPersistentHostname(std::string& hostname); static std::string resolveGatewayMac(const std::string& gatewayIp); static std::string getGatewayMacAddress(NMDevice* device); + static bool isValidBSSID(const std::string& bssid); }; } } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 5dd09070d..e0a6abae1 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -95,6 +95,13 @@ namespace WPEFramework g_main_context_unref(context); m_client = NULL; } + + if(m_objectPath) + { + NMLOG_DEBUG("Freeing object path"); + g_free(m_objectPath); + m_objectPath = NULL; + } } bool wifiManager::quit(NMDevice *wifiNMDevice) @@ -119,13 +126,14 @@ namespace WPEFramework bool wifiManager::wait(GMainLoop *loop, int timeOutMs) { + NMLOG_DEBUG("wait started ..."); if(g_main_loop_is_running(loop)) { NMLOG_WARNING("g_main_loop_is running"); return false; } m_source = g_timeout_source_new(timeOutMs); // 10000ms interval g_source_set_callback(m_source, (GSourceFunc)gmainLoopTimoutCB, this, NULL); - g_source_attach(m_source, NULL); + g_source_attach(m_source, g_main_loop_get_context(loop)); g_main_loop_run(loop); if(m_source != nullptr) { if(g_source_is_destroyed(m_source)) { @@ -135,7 +143,9 @@ namespace WPEFramework g_source_destroy(m_source); } g_source_unref(m_source); + m_source = nullptr; } + NMLOG_DEBUG("wait exited ..."); return true; } @@ -186,37 +196,6 @@ namespace WPEFramework return wifiDevice; } - bool static getConnectedSSID(NMDevice *device, std::string& ssidin) - { - GBytes *ssid = nullptr; - NMDeviceState deviceState = nm_device_get_state(device); - if (deviceState == NM_DEVICE_STATE_ACTIVATED) - { - NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(NM_DEVICE_WIFI(device)); - if(activeAP == nullptr) - return false; - ssid = nm_access_point_get_ssid(activeAP); - if(ssid) - { - char* ssidStr = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid)); - if(ssidStr != nullptr) - { - ssidin = ssidStr; - free(ssidStr); - } - else - { - NMLOG_ERROR("Invalid ssid length Error"); - ssidin.clear(); - return false; - } - } - NMLOG_INFO("connected ssid: %s", ssidin.c_str()); - return true; - } - return false; - } - static void getApInfo(NMAccessPoint *AccessPoint, Exchange::INetworkManager::WiFiSSIDInfo &wifiInfo, bool doPrint = true) { guint32 flags, wpaFlags, rsnFlags, freq, bitrate; @@ -281,6 +260,21 @@ namespace WPEFramework } } + bool static getConnectedAPInfo(NMDevice *device, Exchange::INetworkManager::WiFiSSIDInfo &wifiInfo) + { + NMDeviceState deviceState = nm_device_get_state(device); + if (deviceState == NM_DEVICE_STATE_ACTIVATED) + { + NMAccessPoint *activeAP = nm_device_wifi_get_active_access_point(NM_DEVICE_WIFI(device)); + if(activeAP == nullptr) + return false; + getApInfo(activeAP, wifiInfo, false); + NMLOG_INFO("connected ssid: %s", wifiInfo.ssid.c_str()); + return true; + } + return false; + } + bool wifiManager::getWifiState(Exchange::INetworkManager::WiFiState& state) { if(!createClientNewConnection()) @@ -413,36 +407,75 @@ namespace WPEFramework return m_isSuccess; } - static NMAccessPoint* findMatchingSSID(const GPtrArray* ApList, std::string& ssid) + static NMAccessPoint* findMatchingSSID(const GPtrArray* ApList, Exchange::INetworkManager::WiFiConnectTo& ssidInfo) { NMAccessPoint *AccessPoint = nullptr; - if(ssid.empty()) + if(ssidInfo.ssid.empty()) return nullptr; for (guint i = 0; i < ApList->len; i++) { std::string ssidstr{}; + bool ssidMatch = false; NMAccessPoint *ap = static_cast(g_ptr_array_index(ApList, i)); GBytes *ssidGBytes = nm_access_point_get_ssid(ap); - if(ssidGBytes) + if(ssidGBytes == nullptr) + { + NMLOG_DEBUG("hidden ssid found, bssid: %s", nm_access_point_get_bssid(ap)); + continue; + } + + char* ssidUtf8 = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssidGBytes, NULL), g_bytes_get_size(ssidGBytes)); + if(ssidUtf8 == nullptr) + { + NMLOG_WARNING("Invalid ssid length Error"); + continue; + } + + ssidstr = ssidUtf8; + free(ssidUtf8); + + if(ssidInfo.ssid == ssidstr) { - char* ssidUtf8 = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssidGBytes, NULL), g_bytes_get_size(ssidGBytes)); - if(ssidUtf8 != nullptr) + NMLOG_DEBUG("SSID matched: %s", ssidstr.c_str()); + ssidMatch = true; + } + else + { + // NMLOG_DEBUG("SSID did not match: expected %s, got %s", ssidInfo.ssid.c_str(), ssidstr.c_str()); + ssidMatch = false; + continue; + } + + if(!ssidInfo.bssid.empty()) + { + const char* bssid = nm_access_point_get_bssid(ap); + if(bssid == nullptr) { - ssidstr = ssidUtf8; - if(ssid == ssidstr) - { - AccessPoint = ap; - free(ssidUtf8); - break; - } - // NMLOG_DEBUG("ssid < %s >", ssidstr.c_str()); + NMLOG_WARNING("BSSID is NULL for AP, skipping"); + ssidMatch = false; + continue; + } + + std::string bssidStr = bssid; + if(strcasecmp(ssidInfo.bssid.c_str(), bssidStr.c_str()) == 0) + { + NMLOG_DEBUG("BSSID matched: %s", bssidStr.c_str()); + ssidMatch = true; } else - NMLOG_WARNING("Invalid ssid length Error"); + { + ssidMatch = false; + NMLOG_DEBUG("SSID matched but BSSID did not match: expected %s, got %s", ssidInfo.bssid.c_str(), bssidStr.c_str()); + continue; + } + } - if(ssidUtf8 != nullptr) - free(ssidUtf8); + if(ssidMatch) + { + NMLOG_INFO("Matching AP found : %s", ssidstr.c_str()); + AccessPoint = ap; + break; } } @@ -578,13 +611,18 @@ namespace WPEFramework // Connection settings with autoconnect enabled NMSettingConnection *sConnection = (NMSettingConnection *)nm_setting_connection_new(); std::string connId = "Wired connection 1"; - g_object_set(G_OBJECT(sConnection), - NM_SETTING_CONNECTION_ID, connId.c_str(), - NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate(), - NM_SETTING_CONNECTION_TYPE, "802-3-ethernet", - NM_SETTING_CONNECTION_INTERFACE_NAME, iface.c_str(), - NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, // Enable autoconnect - NULL); + char *uuidRawEth = nm_utils_uuid_generate(); + if (!uuidRawEth) + { + NMLOG_ERROR("Failed to generate UUID for ethernet connection"); + return nullptr; + } + g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_ID, connId.c_str(), NULL); + g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_UUID, uuidRawEth, NULL); + g_free(uuidRawEth); + g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_TYPE, "802-3-ethernet", NULL); + g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_INTERFACE_NAME, iface.c_str(), NULL); + g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NULL); // Enable autoconnect nm_connection_add_setting(connection, NM_SETTING(sConnection)); // Wired ethernet settings @@ -601,20 +639,16 @@ namespace WPEFramework // IPv4 settings with DHCP NMSettingIP4Config *sIpv4 = (NMSettingIP4Config *)nm_setting_ip4_config_new(); - g_object_set(G_OBJECT(sIpv4), - NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), - NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, - NULL); + g_object_set(G_OBJECT(sIpv4), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + g_object_set(G_OBJECT(sIpv4), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); + g_object_set(G_OBJECT(sIpv4), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); nm_connection_add_setting(connection, NM_SETTING(sIpv4)); // IPv6 settings with DHCP NMSettingIP6Config *sIpv6 = (NMSettingIP6Config *)nm_setting_ip6_config_new(); - g_object_set(G_OBJECT(sIpv6), - NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), - NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, - NULL); + g_object_set(G_OBJECT(sIpv6), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); + g_object_set(G_OBJECT(sIpv6), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); + g_object_set(G_OBJECT(sIpv6), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); nm_connection_add_setting(connection, NM_SETTING(sIpv6)); NMLOG_DEBUG("Created minimal ethernet connection with autoconnect=true"); @@ -630,14 +664,18 @@ namespace WPEFramework } /* Build up the 'connection' Setting */ NMSettingConnection *sConnection = (NMSettingConnection *) nm_setting_connection_new(); - const char *uuid = nm_utils_uuid_generate(); - g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_UUID, uuid, NULL); // uuid + char *uuidRaw = nm_utils_uuid_generate(); + if (!uuidRaw) + { + NMLOG_ERROR("Failed to generate UUID for WiFi connection"); + return false; + } + g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_UUID, uuidRaw, NULL); // uuid + g_free(uuidRaw); g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_ID, ssidinfo.ssid.c_str(), NULL); // connection id = ssid g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_INTERFACE_NAME, "wlan0", NULL); // interface name g_object_set(G_OBJECT(sConnection), NM_SETTING_CONNECTION_TYPE, "802-11-wireless", NULL); // type 802.11wireless nm_connection_add_setting(m_connection, NM_SETTING(sConnection)); - if(uuid) - g_free((void *)uuid); /* Build up the '802-11-wireless-security' settings */ NMSettingWireless *sWireless = NULL; @@ -650,8 +688,37 @@ namespace WPEFramework g_object_set(G_OBJECT(sWireless), NM_SETTING_WIRELESS_HIDDEN, true, NULL); // hidden = true if(ssid) g_bytes_unref(ssid); - // 'bssid' parameter is used to restrict the connection only to the BSSID - // g_object_set(s_wifi, NM_SETTING_WIRELESS_BSSID, bssid, NULL); + + if(!ssidinfo.bssid.empty()) + { + NMLOG_INFO("bssid: %s", ssidinfo.bssid.c_str()); + g_object_set(sWireless, NM_SETTING_WIRELESS_BSSID, ssidinfo.bssid.c_str(), NULL); + } + + if(ssidinfo.frequency != Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_NONE) + { + if(ssidinfo.frequency == Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_2_4_GHZ) + { + g_object_set(sWireless, NM_SETTING_WIRELESS_BAND, "bg", NULL); + NMLOG_INFO("frequency: %s", "bg - 2.4GHz"); + } + else if(ssidinfo.frequency == Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_5_GHZ) + { + g_object_set(sWireless, NM_SETTING_WIRELESS_BAND, "a", NULL); + NMLOG_INFO("frequency: %s", "a - 5GHz"); + } + else if(ssidinfo.frequency == Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_6_GHZ) + { + // TODO: 6GHz band support - not supported by current NetworkManager version 1.47.7 + NMLOG_WARNING("6GHz frequency band is not supported by the current NetworkManager version"); + return false; + } + else + { + NMLOG_WARNING("invalid frequency value: %d", ssidinfo.frequency); + return false; + } + } NMSettingWirelessSecurity *sSecurity = NULL; switch(ssidinfo.security) @@ -659,7 +726,6 @@ namespace WPEFramework case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK: case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE: { - sSecurity = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); nm_connection_add_setting(m_connection, NM_SETTING(sSecurity)); if(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE == ssidinfo.security) @@ -778,7 +844,6 @@ namespace WPEFramework g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); // autoconf = true g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); // hostname send enabled - g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, INT32_MAX, NULL); // INT32_MAX(2147483647) = infinite timeout nm_connection_add_setting(m_connection, NM_SETTING(sIpv4Conf)); /* Build up the 'IPv6' Setting */ @@ -790,6 +855,85 @@ namespace WPEFramework return true; } + + bool wifiManager::connectToKnownSSID(const std::string& ssid) + { + const GPtrArray *allnmConn = NULL; + const char* specificObjPath = "/"; + NMConnection *knownConnection = NULL; + bool ret = false; + + if(!createClientNewConnection()) + return ret; + + m_wifidevice = getWifiDevice(); + if(m_wifidevice == NULL) + { + deleteClientConnection(); + return false; + } + + allnmConn = nm_client_get_connections(m_client); + if(allnmConn == NULL || allnmConn->len == 0) + { + NMLOG_ERROR("No connections found !"); + deleteClientConnection(); + return ret; + } + + for (guint i = 0; i < allnmConn->len; i++) + { + NMConnection *conn = static_cast(g_ptr_array_index(allnmConn, i)); + if(conn == NULL) + continue; + + const char *connId = nm_connection_get_id(NM_CONNECTION(conn)); + if (connId == NULL) { + NMLOG_WARNING("connection id is NULL"); + continue; + } + + const char *connTyp = nm_connection_get_connection_type(NM_CONNECTION(conn)); + if (connTyp == NULL) { + NMLOG_WARNING("connection type is NULL"); + continue; + } + + std::string connTypStr = connTyp; + if(connTypStr != "802-11-wireless") + { + NMLOG_DEBUG("%s not a wifi connection", connId); + continue; + } + + if(ssid == connId) + { + knownConnection = g_object_ref(conn); + NMLOG_DEBUG("connection '%s' exists !", ssid.c_str()); + break; + } + } + + if(knownConnection != NULL) + { + NMLOG_INFO("activating known wifi '%s' connection", ssid.c_str()); + m_isSuccess = false; + m_createNewConnection = false; // no need to create new connection + nm_client_activate_connection_async(m_client, NM_CONNECTION(knownConnection), m_wifidevice, specificObjPath, m_cancellable, wifiConnectCb, this); + wait(m_loop); + g_object_unref(knownConnection); + ret = m_isSuccess; + } + else + { + NMLOG_WARNING("'%s' connection not found", ssid.c_str()); + ret = false; + } + + deleteClientConnection(); + return ret; + } + bool wifiManager::activateKnownConnection(std::string iface, std::string knowConnectionID) { const GPtrArray *devConnections = NULL; @@ -942,9 +1086,10 @@ namespace WPEFramework const GPtrArray *availableConnections = NULL; Exchange::INetworkManager::WiFiSSIDInfo apinfo; - std::string activeSSID{}; + Exchange::INetworkManager::WiFiSSIDInfo connectedApInfo; + + NMLOG_DEBUG("wifi connect ssid: %s, bssid: %s, frequency: %d, security %d, persist %d", ssidInfoParam.ssid.c_str(), ssidInfoParam.bssid.c_str(), ssidInfoParam.frequency, ssidInfoParam.security, ssidInfoParam.persist); - NMLOG_DEBUG("wifi connect ssid: %s, security %d persist %d", ssidInfoParam.ssid.c_str(), ssidInfoParam.security, ssidInfoParam.persist); Exchange::INetworkManager::WiFiConnectTo ssidInfo = ssidInfoParam; m_isSuccess = false; if(!createClientNewConnection()) @@ -957,17 +1102,32 @@ namespace WPEFramework return false; } - if(getConnectedSSID(m_wifidevice, activeSSID)) + if(getConnectedAPInfo(m_wifidevice, connectedApInfo)) { - if(ssidInfo.ssid == activeSSID) + if(ssidInfo.ssid == connectedApInfo.ssid) { - NMLOG_INFO("'%s' already connected !", activeSSID.c_str()); - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); - deleteClientConnection(); - return true; + if(ssidInfo.bssid.empty()) + { + NMLOG_INFO("'%s' Already connected !", connectedApInfo.ssid.c_str()); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + deleteClientConnection(); + return true; + } + else if (strcasecmp(ssidInfo.bssid.c_str(), connectedApInfo.bssid.c_str()) == 0) + { + NMLOG_INFO("Already connected to the requested SSID '%s' with matching BSSID", ssidInfo.ssid.c_str()); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + deleteClientConnection(); + return true; + } + else + { + NMLOG_INFO("SSID '%s' matches but BSSID mismatch (connected: %s, requested: %s), reconnecting...", + ssidInfo.ssid.c_str(), connectedApInfo.bssid.c_str(), ssidInfo.bssid.c_str()); + } } else - NMLOG_DEBUG("wifi already connected with %s AP", activeSSID.c_str()); + NMLOG_DEBUG("wifi already connected with %s AP", connectedApInfo.ssid.c_str()); } ApList = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(m_wifidevice)); @@ -978,7 +1138,7 @@ namespace WPEFramework return false; } - AccessPoint = findMatchingSSID(ApList, ssidInfo.ssid); + AccessPoint = findMatchingSSID(ApList, ssidInfo); if(AccessPoint == NULL) { NMLOG_WARNING("SSID '%s' not found !", ssidInfo.ssid.c_str()); @@ -1051,13 +1211,32 @@ namespace WPEFramework if (m_connection != NULL && NM_IS_REMOTE_CONNECTION(m_connection)) { + const char *apPath = nm_object_get_path(NM_OBJECT(AccessPoint)); + if (!apPath) + { + NMLOG_WARNING("AccessPoint object path is NULL"); + apPath = "/"; + } + + if(m_objectPath) + { + NMLOG_WARNING("Freeing object path"); + g_free(m_objectPath); + m_objectPath = NULL; + } + + m_objectPath = g_strdup(apPath); + if(!connectionBuilder(ssidInfo, m_connection)) { NMLOG_ERROR("connection builder failed"); + g_object_unref(m_connection); + m_connection = NULL; deleteClientConnection(); return false; } if (ssidInfo.persist) { + NMLOG_INFO("updating connection '%s'", ssidInfo.ssid.c_str()); // Save to persistent storage and activate GVariant *connSettings = nm_connection_to_dbus(m_connection, NM_CONNECTION_SERIALIZE_ALL); nm_remote_connection_update2(NM_REMOTE_CONNECTION(m_connection), @@ -1067,21 +1246,40 @@ namespace WPEFramework NULL, wifiConnectionUpdate, this); + g_variant_unref(connSettings); } else { // Don't persist changes, just activate existing connection // Note: Any changes made by connectionBuilder will be temporary for this session only - NMLOG_DEBUG("activating existing connection without persisting changes '%s'", ssidInfo.ssid.c_str()); + NMLOG_INFO("activating existing connection without persisting changes '%s'", ssidInfo.ssid.c_str()); m_createNewConnection = false; nm_client_activate_connection_async(m_client, NM_CONNECTION(m_connection), m_wifidevice, m_objectPath, m_cancellable, wifiConnectCb, this); } + g_object_unref(m_connection); + m_connection = NULL; } else { - NMLOG_DEBUG("creating new connection '%s' persist=%d", ssidInfo.ssid.c_str(), ssidInfo.persist); + NMLOG_INFO("creating new connection '%s' persist=%d", ssidInfo.ssid.c_str(), ssidInfo.persist); m_connection = nm_simple_connection_new(); - m_objectPath = nm_object_get_path(NM_OBJECT(AccessPoint)); + + const char *apPath = nm_object_get_path(NM_OBJECT(AccessPoint)); + if (!apPath) + { + NMLOG_WARNING("AccessPoint object path is NULL"); + apPath = "/"; + } + + if(m_objectPath) + { + NMLOG_WARNING("Freeing object path"); + g_free(m_objectPath); + m_objectPath = NULL; + } + + m_objectPath = g_strdup(apPath); + NMLOG_DEBUG("Setting object path to '%s'", m_objectPath); if(!connectionBuilder(ssidInfo, m_connection)) { NMLOG_ERROR("connection builder failed"); @@ -1110,6 +1308,7 @@ namespace WPEFramework m_cancellable, wifiConnectTempCb, this); + g_variant_unref(connSettings); } if(m_connection) g_object_unref(m_connection); @@ -1211,6 +1410,8 @@ namespace WPEFramework if(!connectionBuilder(ssidinfo, m_connection)) { NMLOG_ERROR("connection builder failed"); + g_object_unref(m_connection); + m_connection = NULL; deleteClientConnection(); return false; } @@ -1223,6 +1424,9 @@ namespace WPEFramework NULL, addToKnownSSIDsUpdateCb, this); + g_variant_unref(connSettings); + g_object_unref(m_connection); + m_connection = NULL; } else { @@ -1231,6 +1435,8 @@ namespace WPEFramework if(!connectionBuilder(ssidinfo, m_connection)) { NMLOG_ERROR("connection builder failed"); + g_object_unref(m_connection); + m_connection = NULL; deleteClientConnection(); return false; } @@ -1241,6 +1447,9 @@ namespace WPEFramework NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK, NULL, TRUE, m_cancellable, addToKnownSSIDsCb, this); + g_variant_unref(connSettings); + g_object_unref(m_connection); + m_connection = NULL; } wait(m_loop); deleteClientConnection(); @@ -1484,7 +1693,7 @@ namespace WPEFramework { GError *error = NULL; GMainLoop *loop = static_cast(user_data); - nm_client_add_and_activate_connection_finish(NM_CLIENT(client), result, &error); + NMActiveConnection *activeConnection = nm_client_add_and_activate_connection_finish(NM_CLIENT(client), result, &error); if (error) { NMLOG_ERROR("Failed to add/activate new connection: %s", error->message); @@ -1492,6 +1701,8 @@ namespace WPEFramework } else NMLOG_INFO("WPS connection added/activated successfully"); + if(activeConnection) + g_object_unref(activeConnection); g_main_loop_quit(loop); } @@ -1592,6 +1803,8 @@ namespace WPEFramework if(!g_main_context_acquire(wpsContext)) { NMLOG_ERROR("acquire wpsContext failed !!"); + g_main_context_unref(wpsContext); + wpsContext = NULL; break; } @@ -1603,6 +1816,7 @@ namespace WPEFramework if(error != NULL) { NMLOG_ERROR("Could not connect to NetworkManager: %s.", error->message); g_error_free(error); + error = NULL; } else NMLOG_ERROR("NetworkManager cleint create failed"); @@ -1718,7 +1932,7 @@ namespace WPEFramework GSource *source = g_timeout_source_new(10000); // 10000ms interval if(source != nullptr) { g_source_set_callback(source, (GSourceFunc)wpsGmainLoopTimoutCB, loop, NULL); - g_source_attach(source, NULL); + g_source_attach(source, wpsContext); g_main_loop_run(loop); if(g_source_is_destroyed(source)) { NMLOG_WARNING("Source has been destroyed"); @@ -1747,6 +1961,7 @@ namespace WPEFramework } g_main_context_pop_thread_default(wpsContext); + g_main_context_release(wpsContext); g_main_context_unref(wpsContext); wpsContext = NULL; if(client != NULL) { @@ -1774,6 +1989,7 @@ namespace WPEFramework if(wpsContext != NULL) { g_main_context_pop_thread_default(wpsContext); + g_main_context_release(wpsContext); g_main_context_unref(wpsContext); } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index ca4d1d95a..697995069 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -59,6 +59,7 @@ namespace WPEFramework bool getKnownSSIDs(std::list& ssids); bool addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo &ssidinfo); bool removeKnownSSID(const string& ssid); + bool connectToKnownSSID(const std::string& ssid); bool quit(NMDevice *wifiNMDevice); bool wait(GMainLoop *loop, int timeOutMs = 10000); // default maximium set as 10 sec bool startWPS(); @@ -99,7 +100,7 @@ namespace WPEFramework GMainLoop *m_loop; gboolean m_createNewConnection; GMainContext *m_nmContext = nullptr; - const char* m_objectPath; + char* m_objectPath = nullptr; NMDevice *m_wifidevice; GSource *m_source; GCancellable *m_cancellable; diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index f2a1e959a..670b0a6fc 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -1070,6 +1070,13 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { return rc; } + uint32_t NetworkManagerImplementation::ConnectToKnownSSID(const string& ssid /* @in */) + { + LOG_ENTRY_FUNCTION(); + NMLOG_INFO ("netsrvmgr does not support multiple known SSIDs; ConnectToKnownSSID is unavailable."); + return Core::ERROR_UNAVAILABLE; + } + uint32_t NetworkManagerImplementation::RemoveKnownSSID(const string& ssid /* @in */) { LOG_ENTRY_FUNCTION(); diff --git a/tests/l2Test/libnm/l2_test_libnmproxy.cpp b/tests/l2Test/libnm/l2_test_libnmproxy.cpp index 9cb4de3cd..bd633dd74 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxy.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxy.cpp @@ -213,7 +213,7 @@ TEST_F(NetworkManagerTest, SetLogLevel) .Times(1) .WillOnce(::testing::Invoke( [&](const char* command, const char* type) -> FILE* { - EXPECT_THAT(string(command), ::testing::MatchesRegex("nmcli general logging level TRACE domains ALL")); + EXPECT_THAT(string(command), ::testing::MatchesRegex("nmcli general logging level TRACE domains PLATFORM,DEVICE,WIFI,ETHER,DNS,DHCP4,DHCP6,DEVICE,SETTINGS,DISPATCH")); // Create a temporary file with the mock output FILE* tempFile = tmpfile(); return tempFile; diff --git a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp index 61ba95e13..c587688a6 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp @@ -235,7 +235,18 @@ TEST_F(NetworkManagerEventTest, onAddressChangeCb) TEST_F(NetworkManagerEventTest, onAvailableSSIDsCb) { - NMDeviceWifi *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), _T(""), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); GPtrArray* fakeAccessPoints = g_ptr_array_new(); g_ptr_array_add(fakeAccessPoints, reinterpret_cast(0x833332)); @@ -258,16 +269,24 @@ TEST_F(NetworkManagerEventTest, onAvailableSSIDsCb) EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) .WillOnce(::testing::Return(fake_ssid)); - + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) + .WillOnce(::testing::Return("00:11:22:33:44:55")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength + g_ptr_array_free(fakeDevices, TRUE); + WPEFramework::Plugin::GnomeNetworkManagerEvents::onAvailableSSIDsCb(nullptr, nullptr, nullptr); - WPEFramework::Plugin::GnomeNetworkManagerEvents::onAvailableSSIDsCb(deviceDummy, nullptr, nullptr); + NMDeviceWifi *deviceWifiDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::onAvailableSSIDsCb(deviceWifiDummy, nullptr, nullptr); + g_object_unref(deviceDummy); + g_object_unref(deviceWifiDummy); g_ptr_array_free(fakeAccessPoints, TRUE); } diff --git a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp index 278dcbcbd..d32f4615f 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp @@ -197,6 +197,7 @@ TEST_F(NetworkManagerWifiTest, RegisteredMethods) EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetKnownSSIDs"))); EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("AddToKnownSSIDs"))); EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("RemoveKnownSSID"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("ConnectToKnownSSID"))); EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("WiFiConnect"))); EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("WiFiDisconnect"))); EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("GetConnectedSSID"))); @@ -892,38 +893,18 @@ TEST_F(NetworkManagerWifiTest, StartWiFiScan_with_option_success) TEST_F(NetworkManagerWifiTest, WiFiConnect_long_ssid) { - GPtrArray* fakeDevices = g_ptr_array_new(); - NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); - g_ptr_array_add(fakeDevices, deviceDummy); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) - .WillRepeatedly(::testing::Return(fakeDevices)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) - .WillRepeatedly(::testing::Return("wlan0")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA32\",\"passphrase\": \"123454321\",\"security\":1, \"persist\":false }"), response)); EXPECT_EQ(response, _T("{\"success\":false}")); +} - g_object_unref(deviceDummy); - g_ptr_array_free(fakeDevices, TRUE); +TEST_F(NetworkManagerWifiTest, WiFiConnect_Wrong_bssid) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestSSID\", \"bssid\":\"00:11:22:33:44:OO\", \"passphrase\": \"123454321\",\"security\":1, \"persist\":false }"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); } TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed_device_null) { - GPtrArray* fakeDevices = g_ptr_array_new(); - NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); - g_ptr_array_add(fakeDevices, deviceDummy); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) - .WillRepeatedly(::testing::Return(fakeDevices)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) - .WillRepeatedly(::testing::Return("wlan0")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) .WillRepeatedly(::testing::Return(static_cast(NULL))); @@ -931,8 +912,6 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed_device EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T(""), response)); EXPECT_EQ(response, _T("{\"success\":false}")); - g_object_unref(deviceDummy); - g_ptr_array_free(fakeDevices, TRUE); } TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed_noconnection) @@ -945,9 +924,6 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed_noconn .WillRepeatedly(::testing::Return(fakeDevices)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) .WillRepeatedly(::testing::Return("wlan0")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) .WillRepeatedly(::testing::Return(deviceDummy)); @@ -979,9 +955,6 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed_noconn .WillRepeatedly(::testing::Return(fakeDevices)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) .WillRepeatedly(::testing::Return("wlan0")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) .WillRepeatedly(::testing::Return(deviceDummy)); @@ -1015,9 +988,6 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed_noconn .WillRepeatedly(::testing::Return(fakeDevices)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) .WillRepeatedly(::testing::Return("wlan0")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) .WillRepeatedly(::testing::Return(deviceDummy)); @@ -1054,9 +1024,6 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed_noconn .WillRepeatedly(::testing::Return(fakeDevices)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) .WillRepeatedly(::testing::Return("wlan0")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) .WillRepeatedly(::testing::Return(deviceDummy)); @@ -1093,9 +1060,6 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_failed) .WillRepeatedly(::testing::Return(fakeDevices)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) .WillRepeatedly(::testing::Return("wlan0")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) .WillRepeatedly(::testing::Return(deviceDummy)); @@ -1153,9 +1117,6 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_success) .WillRepeatedly(::testing::Return(fakeDevices)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) .WillRepeatedly(::testing::Return("wlan0")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_)) .WillRepeatedly(::testing::Return(deviceDummy)); @@ -1196,6 +1157,70 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_activateKnownConnection_success) g_ptr_array_free(fakeDevices, TRUE); } +TEST_F(NetworkManagerWifiTest, Connect_To_Known_SSID) +{ + GPtrArray* fakeDevices = g_ptr_array_new(); + NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + g_ptr_array_add(fakeDevices, deviceDummy); + + GPtrArray* dummyConns = g_ptr_array_new(); + NMConnection *conn1 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + NMConnection *conn2 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + NMConnection *conn3 = reinterpret_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); + g_ptr_array_add(dummyConns, conn1); + g_ptr_array_add(dummyConns, conn2); + g_ptr_array_add(dummyConns, conn3); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) + .WillRepeatedly(::testing::Return(fakeDevices)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))) + .WillOnce(::testing::Return(reinterpret_cast(dummyConns))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast(NULL))) + .WillOnce(::testing::Return("TestEthConnection")) + .WillOnce(::testing::Return("TestConnection")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_connection_type(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("802-11-wired"))) + .WillOnce(::testing::Return(reinterpret_cast("802-11-wireless"))); + + EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + NMActiveConnection *dummyActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_activate_connection_finish(::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Return(dummyActiveConn)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_activate_connection_async(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillOnce(::testing::Invoke([](NMClient* client, NMConnection* connection, NMDevice* device, const char* specific_object, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data) { + if (callback) { + GObject* source_object = G_OBJECT(client); + GAsyncResult* result = nullptr; + callback(source_object, result, user_data); + } + })); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ConnectToKnownSSID"), _T("{ \"ssid\":\"TestConnection\" }"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("ConnectToKnownSSID"), _T("{ \"ssid\":\"TestConnection\" }"), response)); + EXPECT_EQ(response, _T("{\"success\":true}")); + + g_object_unref(deviceDummy); + g_object_unref(conn1); + g_object_unref(conn2); + g_object_unref(conn3); + g_object_unref(dummyActiveConn); + g_ptr_array_free(dummyConns, TRUE); + g_ptr_array_free(fakeDevices, TRUE); +} + TEST_F(NetworkManagerWifiTest, WiFiConnect_with_same_ssid) { GPtrArray* fakeDevices = g_ptr_array_new(); @@ -1209,19 +1234,41 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_same_ssid) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) - .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); - // Setup the Access Point mock calls EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) .WillOnce(::testing::Return(reinterpret_cast(0x333223))); const char* ssid_str = "TestWiFiNetwork"; GBytes* fake_ssid = g_bytes_new_static(ssid_str, strlen(ssid_str)); + // AP property mocks + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) .WillOnce(::testing::Return(fake_ssid)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) + .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) + .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) + .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork\",\"passphrase\": \"123454321\",\"security\":1, \"persist\":false}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork\",\"passphrase\": \"123454321\",\"security\":2, \"persist\":false}"), response)); EXPECT_EQ(response, _T("{\"success\":true}")); g_bytes_unref(fake_ssid); @@ -1242,23 +1289,42 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_Ap_list_null) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) - .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); - // Setup the Access Point mock calls EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) .WillOnce(::testing::Return(reinterpret_cast(0x333223))); - const char* ssid_str = "TestWiFiNetwork_1"; + const char* ssid_str = "TestWiFiNetwork"; GBytes* fake_ssid = g_bytes_new_static(ssid_str, strlen(ssid_str)); + // AP property mocks + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_ssid(::testing::_)) .WillOnce(::testing::Return(fake_ssid)); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) + .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) + .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + + EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) + .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_access_points(::testing::_)) .WillOnce(::testing::Return(reinterpret_cast(NULL))); - // GPtrArray* fakeAccessPoints = g_ptr_array_new(); - // g_ptr_array_add(fakeAccessPoints, reinterpret_cast(NULL)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("WiFiConnect"), _T("{ \"ssid\":\"TestWiFiNetwork_0\",\"passphrase\": \"123454321\",\"security\":1, \"persist\":false}"), response)); EXPECT_EQ(response, _T("{\"success\":false}")); @@ -1280,14 +1346,10 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_no_access_point) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) .WillRepeatedly(::testing::Return("wlan0")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .Times(3) .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) - .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x333223))); + .WillOnce(::testing::Return(reinterpret_cast(NULL))); const char* ssid_str = "TestWiFiNetwork_1"; GBytes* fake_ssid1 = g_bytes_new_static(ssid_str, strlen(ssid_str)); @@ -1326,36 +1388,41 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_different_ssid) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) - .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) .WillOnce(::testing::Return(reinterpret_cast(0x333223))); // AP property mocks EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))) .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))) .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) - .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))); + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) - .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:F2")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) - .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + .WillOnce(::testing::Return(static_cast(2462))) // Channel 11 (2.4GHz) + .WillOnce(::testing::Return(static_cast(2462))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))) .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) - .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + .WillOnce(::testing::Return(static_cast(54000))) // 54 Mbps + .WillOnce(::testing::Return(static_cast(54000))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) - .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength + .WillOnce(::testing::Return(static_cast(85))) // 85% signal strength + .WillOnce(::testing::Return(static_cast(85))); const char* ssid_str = "TestWiFiNetwork_1"; GBytes* fake_ssid1 = g_bytes_new_static(ssid_str, strlen(ssid_str)); @@ -1406,36 +1473,41 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_different_good_password) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) - .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) .WillOnce(::testing::Return(reinterpret_cast(0x333223))); // AP property mocks EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))) .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))) .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) - .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))); + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) - .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:F2")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) - .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + .WillOnce(::testing::Return(static_cast(2462))) // Channel 11 (2.4GHz) + .WillOnce(::testing::Return(static_cast(2462))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))) .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) - .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + .WillOnce(::testing::Return(static_cast(54000))) // 54 Mbps + .WillOnce(::testing::Return(static_cast(54000))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) - .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength + .WillOnce(::testing::Return(static_cast(85))) // 85% signal strength + .WillOnce(::testing::Return(static_cast(85))); const char* ssid_str = "TestWiFiNetwork_1"; GBytes* fake_ssid1 = g_bytes_new_static(ssid_str, strlen(ssid_str)); @@ -1489,36 +1561,41 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_connection_update) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) - .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) .WillOnce(::testing::Return(reinterpret_cast(0x333223))); // AP property mocks EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))) .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))) .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) - .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))); + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) - .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:F2")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) - .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + .WillOnce(::testing::Return(static_cast(2462))) // Channel 11 (2.4GHz) + .WillOnce(::testing::Return(static_cast(2462))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))) .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) - .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + .WillOnce(::testing::Return(static_cast(54000))) // 54 Mbps + .WillOnce(::testing::Return(static_cast(54000))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) - .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength + .WillOnce(::testing::Return(static_cast(85))) // 85% signal strength + .WillOnce(::testing::Return(static_cast(85))); const char* ssid_str = "TestWiFiNetwork_1"; GBytes* fake_ssid1 = g_bytes_new_static(ssid_str, strlen(ssid_str)); @@ -1534,12 +1611,16 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_connection_update) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_access_points(::testing::_)) .WillOnce(::testing::Return(fakeAccessPoints)); + GVariant* fakeConnSettings = g_variant_new_boolean(TRUE); EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_to_dbus(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x11111))); + .WillOnce(::testing::Return(fakeConnSettings)); EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) .WillRepeatedly(::testing::Return(true)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_object_get_path(::testing::_)) + .WillOnce(::testing::Return(reinterpret_cast("NULL"))); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_remote_connection_update2_finish(::testing::_, ::testing::_, ::testing::_)) .WillOnce(::testing::Invoke([](NMRemoteConnection *connection, GAsyncResult *result, GError **error) -> GVariant* { *error = g_error_new(G_IO_ERROR, G_IO_ERROR_CANCELLED, "update connection activation failed"); @@ -1592,36 +1673,41 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_connection_not_valid) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_last_scan(::testing::_)) - .WillOnce(::testing::Return(nm_utils_get_timestamp_msec() - 10)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_wifi_get_active_access_point(::testing::_)) .WillOnce(::testing::Return(reinterpret_cast(0x333223))); // AP property mocks EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))) .WillOnce(::testing::Return(static_cast(NM_802_11_AP_FLAGS_PRIVACY))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_wpa_flags(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))) .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_rsn_flags(::testing::_)) - .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))); + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_SAE))) + .WillOnce(::testing::Return(static_cast(NM_802_11_AP_SEC_KEY_MGMT_PSK))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_bssid(::testing::_)) - .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")); + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:FF")) + .WillOnce(::testing::Return("AA:BB:CC:DD:EE:F2")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_frequency(::testing::_)) - .WillOnce(::testing::Return(static_cast(2462))); // Channel 11 (2.4GHz) + .WillOnce(::testing::Return(static_cast(2462))) // Channel 11 (2.4GHz) + .WillOnce(::testing::Return(static_cast(2462))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_mode(::testing::_)) + .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))) .WillOnce(::testing::Return(static_cast(NM_802_11_MODE_INFRA))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_max_bitrate(::testing::_)) - .WillOnce(::testing::Return(static_cast(54000))); // 54 Mbps + .WillOnce(::testing::Return(static_cast(54000))) // 54 Mbps + .WillOnce(::testing::Return(static_cast(54000))); EXPECT_CALL(*p_libnmWrapsImplMock, nm_access_point_get_strength(::testing::_)) - .WillOnce(::testing::Return(static_cast(85))); // 85% signal strength + .WillOnce(::testing::Return(static_cast(85))) // 85% signal strength + .WillOnce(::testing::Return(static_cast(85))); const char* ssid_str = "TestWiFiNetwork_1"; GBytes* fake_ssid1 = g_bytes_new_static(ssid_str, strlen(ssid_str)); @@ -1661,8 +1747,9 @@ TEST_F(NetworkManagerWifiTest, WiFiConnect_with_connection_not_valid) EXPECT_CALL(*p_libnmWrapsImplMock, nm_object_get_path(::testing::_)) .WillOnce(::testing::Return(reinterpret_cast("NULL"))); + GVariant* fakeConnSettings = g_variant_new_boolean(TRUE); EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_to_dbus(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x11111))); + .WillOnce(::testing::Return(fakeConnSettings)); EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) .WillRepeatedly(::testing::Return(true)); @@ -1793,8 +1880,9 @@ TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_sae_update_success) EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) .WillOnce(::testing::Return(reinterpret_cast("test"))); + GVariant* fakeConnSettings = g_variant_new_boolean(TRUE); EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_to_dbus(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x11111))); + .WillOnce(::testing::Return(fakeConnSettings)); EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) .WillRepeatedly(::testing::Return(true)); @@ -1851,8 +1939,9 @@ TEST_F(NetworkManagerWifiTest, AddToKnownSSIDs_sae_update_failed) EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_)) .WillOnce(::testing::Return(reinterpret_cast("test"))); + GVariant* fakeConnSettings = g_variant_new_boolean(TRUE); EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_to_dbus(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x11111))); + .WillOnce(::testing::Return(fakeConnSettings)); EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_)) .WillRepeatedly(::testing::Return(true)); diff --git a/tests/mocks/INetworkManagerMock.h b/tests/mocks/INetworkManagerMock.h index c4a98390e..27a8b2875 100644 --- a/tests/mocks/INetworkManagerMock.h +++ b/tests/mocks/INetworkManagerMock.h @@ -41,6 +41,7 @@ class MockINetworkManager : public WPEFramework::Exchange::INetworkManager { MOCK_METHOD(uint32_t, GetKnownSSIDs, (IStringIterator*& ssids), (override)); MOCK_METHOD(uint32_t, AddToKnownSSIDs, (const WiFiConnectTo& ssid), (override)); MOCK_METHOD(uint32_t, RemoveKnownSSID, (const string& ssid), (override)); + MOCK_METHOD(uint32_t, ConnectToKnownSSID, (const string& ssid), (override)); MOCK_METHOD(uint32_t, WiFiConnect, (const WiFiConnectTo& ssid), (override)); MOCK_METHOD(uint32_t, WiFiDisconnect, (), (override)); MOCK_METHOD(uint32_t, GetConnectedSSID, (WiFiSSIDInfo& ssidInfo), (override)); From 698c9eacd3eaf0cc09f152ad979991af3e2dacf2 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:16:05 -0400 Subject: [PATCH 231/271] RDKEMW-16150: Let's get connected" displayed during Migration testing (#296) * RDKEMW-16150: Let's get connected" displayed during Migration testing Reason for Change: Deleting all the connections only in case of BOOT_MIGRATION so that networkmanager connecting to the eth0 connection can be avoided and we can create new "Wired Connection 1" to connect. Test Procedure: Migration Scenario Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR * RDKEMW-16150: Let's get connected" displayed during Migration testing Reason for Change: Deleting all the connections only in case of BOOT_MIGRATION so that networkmanager connecting to the eth0 connection can be avoided and we can create new "Wired Connection 1" to connect. Test Procedure: Migration Scenario Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR --------- Signed-off-by: Gururaaja ESR --- plugin/gnome/NetworkManagerGnomeProxy.cpp | 131 +++++++++++++++++++--- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 60 ++++++++++ plugin/gnome/NetworkManagerGnomeWIFI.h | 1 + 3 files changed, 174 insertions(+), 18 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index a36a28c1d..9e9fe13c7 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -422,6 +422,7 @@ namespace WPEFramework return rc; } #endif + uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) { @@ -437,33 +438,127 @@ namespace WPEFramework return Core::ERROR_GENERAL; } - if(!wifi->setInterfaceState(interface, enabled)) + // For ethernet enable: run BOOT_MIGRATION cleanup first, then setInterfaceState + if(enabled && interface == nmUtils::ethIface()) { - NMLOG_ERROR("interface state change failed"); - return Core::ERROR_GENERAL; - } + // Check boot type and delete all ethernet NM connections if BOOT_MIGRATION + { + const char* bootFile = "/tmp/bootType"; + std::ifstream file(bootFile); - NMLOG_INFO("interface %s state: %s", interface.c_str(), enabled ? "enabled" : "disabled"); - // update the interface global cache state - if(interface == nmUtils::wlanIface() && _instance != NULL) - _instance->m_wlanEnabled.store(enabled); - else if(interface == nmUtils::ethIface() && _instance != NULL) - _instance->m_ethEnabled.store(enabled); + if(file.is_open()) + { + std::string line, bootTypeValue; + while(std::getline(file, line)) + { + const std::string key = "BOOT_TYPE="; + auto pos = line.find(key); + if(pos != std::string::npos) + { + bootTypeValue = line.substr(pos + key.size()); + break; + } + } + + if(bootTypeValue == "BOOT_MIGRATION") + { + NMLOG_INFO("BOOT_MIGRATION detected, deleting all wired NM connections"); + + // Bring down the ethernet interface before wiping its connections + // so NM doesn't immediately re-activate them during deletion. + NMDevice *ethDev = nm_client_get_device_by_iface(client, interface.c_str()); + if(ethDev) + { + GError *discError = nullptr; + if(!nm_device_disconnect(ethDev, nullptr, &discError)) + { + NMLOG_WARNING("Failed to disconnect %s before migration cleanup: %s", + interface.c_str(), + discError ? discError->message : "unknown error"); + if(discError) g_error_free(discError); + } + } + + const GPtrArray *connections = nm_client_get_connections(client); + if(connections && connections->len > 0) + { + /* Snapshot the list before iterating: nm_client_get_connections() + * returns an internal array that can be mutated as connections + * are removed, so we must not iterate it while deleting. */ + GPtrArray *snapshot = g_ptr_array_new_full(connections->len, g_object_unref); + for(guint i = 0; i < connections->len; ++i) + { + NMRemoteConnection *conn = NM_REMOTE_CONNECTION(connections->pdata[i]); + if(!conn) continue; + NMSettingConnection *sCon = nm_connection_get_setting_connection(NM_CONNECTION(conn)); + if(!sCon) continue; + const char *connType = nm_setting_connection_get_connection_type(sCon); + if(g_strcmp0(connType, NM_SETTING_WIRED_SETTING_NAME) != 0) + { + NMLOG_DEBUG("Skipping non-wired connection type: %s", connType ? connType : "null"); + continue; + } + g_ptr_array_add(snapshot, g_object_ref(conn)); + } + + for(guint i = 0; i < snapshot->len; ++i) + { + NMRemoteConnection *conn = NM_REMOTE_CONNECTION(snapshot->pdata[i]); + GError *error = nullptr; + if(!nm_remote_connection_delete(conn, nullptr, &error)) + { + const char *connId = nm_connection_get_id(NM_CONNECTION(conn)); + NMLOG_ERROR("Failed to delete connection %s: %s", + connId ? connId : "", + error ? error->message : "unknown error"); + if(error) g_error_free(error); + } + } + g_ptr_array_unref(snapshot); + } + } + } + } + + NMLOG_INFO("Adding minimal ethernet connection profile ..."); + wifi->addMinimalEthernetConnection(nmUtils::ethIface()); + + if(!wifi->setInterfaceState(interface, enabled)) + { + NMLOG_ERROR("interface state change failed"); + return Core::ERROR_GENERAL; + } + + NMLOG_INFO("interface %s state: %s", interface.c_str(), enabled ? "enabled" : "disabled"); + if(_instance != NULL) + _instance->m_ethEnabled.store(enabled); - if(enabled) - { sleep(1); // wait for 1 sec to change the device state + NMLOG_INFO("Activating connection 'Wired connection 1' ..."); + // default wired connection name is 'Wired connection 1' + wifi->activateKnownConnection(nmUtils::ethIface(), "Wired connection 1"); + } + else + { + if(!wifi->setInterfaceState(interface, enabled)) + { + NMLOG_ERROR("interface state change failed"); + return Core::ERROR_GENERAL; + } + + NMLOG_INFO("interface %s state: %s", interface.c_str(), enabled ? "enabled" : "disabled"); + // update the interface global cache state if(interface == nmUtils::wlanIface() && _instance != NULL) + _instance->m_wlanEnabled.store(enabled); + else if(interface == nmUtils::ethIface() && _instance != NULL) + _instance->m_ethEnabled.store(enabled); + + if(enabled && interface == nmUtils::wlanIface() && _instance != NULL) { + sleep(1); // wait for 1 sec to change the device state NMLOG_INFO("Activating connection '%s' ...", _instance->m_lastConnectedSSID.c_str()); wifi->activateKnownConnection(nmUtils::wlanIface(), _instance->m_lastConnectedSSID); } - else if(interface == nmUtils::ethIface()) - { - NMLOG_INFO("Activating connection 'Wired connection 1' ..."); - // default wired connection name is 'Wired connection 1' - wifi->activateKnownConnection(nmUtils::ethIface(), "Wired connection 1"); - } } return Core::ERROR_NONE; diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index e0a6abae1..589cbb964 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -655,6 +655,66 @@ namespace WPEFramework return connection; } + static void addMinimalEthernetConnectionCb(GObject *client, GAsyncResult *result, gpointer user_data) + { + GError *error = NULL; + wifiManager *_wifiManager = static_cast(user_data); + NMRemoteConnection *remoteConn = nm_client_add_connection2_finish(NM_CLIENT(client), result, NULL, &error); + if (error) { + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + NMLOG_DEBUG("addMinimalEthernetConnection operation was cancelled"); + g_error_free(error); + if (remoteConn) + g_object_unref(remoteConn); + if (_wifiManager->m_loop && g_main_loop_is_running(_wifiManager->m_loop)) { + g_main_loop_quit(_wifiManager->m_loop); + } + return; // do not alter m_isSuccess on cancellation + } + NMLOG_ERROR("addMinimalEthernetConnection error: %s", error->message); + _wifiManager->m_isSuccess = false; + g_error_free(error); + } + else if (!remoteConn) { + NMLOG_ERROR("addMinimalEthernetConnection failed"); + _wifiManager->m_isSuccess = false; + } + else { + NMLOG_INFO("addMinimalEthernetConnection success"); + _wifiManager->m_isSuccess = true; + g_object_unref(remoteConn); + } + g_main_loop_quit(_wifiManager->m_loop); + } + + bool wifiManager::addMinimalEthernetConnection(std::string iface) + { + if (!createClientNewConnection()) + return false; + + NMConnection *ethConn = createMinimalEthernetConnection(iface); + if (ethConn == NULL) + { + NMLOG_ERROR("Failed to create minimal ethernet connection"); + deleteClientConnection(); + return false; + } + + GVariant *connSettings = nm_connection_to_dbus(ethConn, NM_CONNECTION_SERIALIZE_ALL); + g_object_unref(ethConn); + + m_isSuccess = false; + nm_client_add_connection2(m_client, + connSettings, + NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK, + NULL, TRUE, m_cancellable, + addMinimalEthernetConnectionCb, this); + g_variant_unref(connSettings); + wait(m_loop); + deleteClientConnection(); + return m_isSuccess; + } + static bool connectionBuilder(const Exchange::INetworkManager::WiFiConnectTo& ssidinfo, NMConnection *m_connection, bool iswpsAP = false) { if(ssidinfo.ssid.empty() || ssidinfo.ssid.length() > 32) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 697995069..51164aa50 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -67,6 +67,7 @@ namespace WPEFramework bool setInterfaceState(std::string interface, bool enabled); bool setIpSettings(const string interface, const Exchange::INetworkManager::IPAddress &address); bool setPrimaryInterface(const string interface); + bool addMinimalEthernetConnection(std::string iface); private: NMDevice *getWifiDevice(); From 481b3de207fe0c36c362cc94b053dc8d7990ef71 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 29 Apr 2026 14:32:13 -0400 Subject: [PATCH 232/271] RDKEMW-17624: Fixed potential causes of plugin crash (#303) Reason for Change: Fixed potential causes of plugin crash Test Procedure: Monitor for networkmanager plugin crash Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR --- legacy/LegacyNetworkAPIs.cpp | 3 + legacy/LegacyWiFiManagerAPIs.cpp | 3 + plugin/NetworkManagerConnectivity.cpp | 120 +++++++++-------- plugin/NetworkManagerImplementation.cpp | 31 +++-- plugin/NetworkManagerImplementation.h | 25 +++- plugin/NetworkManagerJsonRpc.cpp | 6 + plugin/gnome/NetworkManagerGnomeProxy.cpp | 125 +++++++++++++----- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 19 ++- .../gnome/gdbus/NetworkManagerGdbusProxy.cpp | 21 ++- plugin/rdk/NetworkManagerRDKProxy.cpp | 20 ++- tests/l2Test/libnm/l2_test_libnmproxy.cpp | 3 +- 11 files changed, 261 insertions(+), 115 deletions(-) diff --git a/legacy/LegacyNetworkAPIs.cpp b/legacy/LegacyNetworkAPIs.cpp index d5924ee54..071466cdd 100644 --- a/legacy/LegacyNetworkAPIs.cpp +++ b/legacy/LegacyNetworkAPIs.cpp @@ -783,6 +783,9 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { } } endpointsIter = (Core::Service::Create(endpoints)); + if (endpointsIter == nullptr) { + returnJson(rc); + } auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); if (_nwmgr) diff --git a/legacy/LegacyWiFiManagerAPIs.cpp b/legacy/LegacyWiFiManagerAPIs.cpp index 12e91b0a2..9132ed097 100644 --- a/legacy/LegacyWiFiManagerAPIs.cpp +++ b/legacy/LegacyWiFiManagerAPIs.cpp @@ -653,6 +653,9 @@ namespace WPEFramework } ssids = (Core::Service::Create(inputSSIDlist)); + if (ssids == nullptr) { + returnJson(rc); + } } auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); diff --git a/plugin/NetworkManagerConnectivity.cpp b/plugin/NetworkManagerConnectivity.cpp index 3d9b88924..93825d512 100644 --- a/plugin/NetworkManagerConnectivity.cpp +++ b/plugin/NetworkManagerConnectivity.cpp @@ -575,7 +575,7 @@ namespace WPEFramework NMCONNECTIVITY_CURL_HEAD_REQUEST, ipversionLocal, interface); if (interface.empty()) - interface = _instance->m_defaultInterface; + interface = _instance->getDefaultInterface(); return testInternet.getInternetState(); } @@ -634,7 +634,9 @@ namespace WPEFramework return false; } - if(_instance->m_defaultInterface.empty()) + string defaultIface = _instance->getDefaultInterface(); + + if(defaultIface.empty()) { NMLOG_WARNING("default interface not set"); return false; @@ -646,7 +648,7 @@ namespace WPEFramework m_cmCv.notify_one(); NMLOG_INFO("switching to initial check - eth %s - wlan %s - default interface %s", - _instance->m_ethConnected.load()? "up":"down", _instance->m_wlanConnected.load()? "up":"down", _instance->m_defaultInterface.c_str()); + _instance->m_ethConnected.load()? "up":"down", _instance->m_wlanConnected.load()? "up":"down", defaultIface.c_str()); return true; } @@ -658,7 +660,8 @@ namespace WPEFramework { NMLOG_INFO("notifying internet state %s", getInternetStateString(newInternetState)); Exchange::INetworkManager::InternetStatus newState = newInternetState; - _instance->ReportInternetStatusChange(oldState , newState, _instance->m_defaultInterface); + string defaultIface = _instance->getDefaultInterface(); + _instance->ReportInternetStatusChange(oldState, newState, defaultIface); m_InternetState = newInternetState; oldState = newState; // 'm_InternetState' not exactly previous state, it may change to unknow when interface changed } @@ -694,68 +697,73 @@ namespace WPEFramework m_notify = true; InitialRetryCount = 1; } - else if(_instance->m_defaultInterface.empty()) - { - NMLOG_WARNING("default interface not set"); - if (InitialRetryCount == 0) - m_notify = true; - InitialRetryCount = 1; - } - else if (m_switchToInitial) + else { - if (InitialRetryCount == 0) - m_notify = true; - NMLOG_INFO("Initial connectivity check - index:%d, current state:%s, interface:%s", InitialRetryCount, getInternetStateString(currentInternetState), _instance->m_defaultInterface.c_str()); - timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; - TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, - NMCONNECTIVITY_CURL_HEAD_REQUEST, 2, _instance->m_defaultInterface); - currentInternetState = testInternet.getInternetState(); + string defaultIface = _instance->getDefaultInterface(); - if (currentInternetState == INTERNET_NOT_AVAILABLE) { - NMLOG_DEBUG("interface connected but no internet"); - InitialRetryCount = 1; // continue same check for 5 sec - } - else { - if(currentInternetState == INTERNET_CAPTIVE_PORTAL) - m_captiveURI = testInternet.getCaptivePortal(); - - if (currentInternetState != m_InternetState) { - NMLOG_DEBUG("initial connectivity state change from %s to %s", getInternetStateString(m_InternetState), getInternetStateString(currentInternetState)); - m_InternetState = currentInternetState; - InitialRetryCount = 1; // reset retry count to get continuous 3 same state + if(defaultIface.empty()) + { + NMLOG_WARNING("default interface not set"); + if (InitialRetryCount == 0) m_notify = true; - } - InitialRetryCount++; + InitialRetryCount = 1; } - - if (InitialRetryCount > NM_CONNECTIVITY_MONITOR_RETRY_COUNT) { - m_switchToInitial = false; - m_notify = true; - NMLOG_INFO("switching to ideal ccm check interface: %s", _instance->m_defaultInterface.c_str()); - } - } - else - { - // ideal case check every 30 sec happenses when captive portal or limited internet - timeoutInSec = NMCONNECTIVITY_MONITOR_RETRY_INTERVAL; - InitialRetryCount = 0; - - if(m_InternetState != INTERNET_FULLY_CONNECTED) + else if (m_switchToInitial) { + if (InitialRetryCount == 0) + m_notify = true; + NMLOG_INFO("Initial connectivity check - index:%d, current state:%s, interface:%s", InitialRetryCount, getInternetStateString(currentInternetState), defaultIface.c_str()); + timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, - NMCONNECTIVITY_CURL_HEAD_REQUEST, 2, _instance->m_defaultInterface); // check both IP versions + NMCONNECTIVITY_CURL_HEAD_REQUEST, 2, defaultIface); currentInternetState = testInternet.getInternetState(); - if (currentInternetState == INTERNET_CAPTIVE_PORTAL) // if captive portal found copy the URL - m_captiveURI = testInternet.getCaptivePortal(); + if (currentInternetState == INTERNET_NOT_AVAILABLE) { + NMLOG_DEBUG("interface connected but no internet"); + InitialRetryCount = 1; // continue same check for 5 sec + } + else { + if(currentInternetState == INTERNET_CAPTIVE_PORTAL) + m_captiveURI = testInternet.getCaptivePortal(); + + if (currentInternetState != m_InternetState) { + NMLOG_DEBUG("initial connectivity state change from %s to %s", getInternetStateString(m_InternetState), getInternetStateString(currentInternetState)); + m_InternetState = currentInternetState; + InitialRetryCount = 1; // reset retry count to get continuous 3 same state + m_notify = true; + } + InitialRetryCount++; + } - if (currentInternetState != m_InternetState) - { - NMLOG_INFO("ideal connectivity state change from %s to %s", getInternetStateString(m_InternetState), getInternetStateString(currentInternetState)); - m_switchToInitial = true; + if (InitialRetryCount > NM_CONNECTIVITY_MONITOR_RETRY_COUNT) { + m_switchToInitial = false; m_notify = true; - InitialRetryCount = 1; - timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; // retry in 5 sec + NMLOG_INFO("switching to ideal ccm check interface: %s", defaultIface.c_str()); + } + } + else + { + // ideal case check every 30 sec happenses when captive portal or limited internet + timeoutInSec = NMCONNECTIVITY_MONITOR_RETRY_INTERVAL; + InitialRetryCount = 0; + + if(m_InternetState != INTERNET_FULLY_CONNECTED) + { + TestConnectivity testInternet(m_endpoint(), NMCONNECTIVITY_CURL_REQUEST_TIMEOUT_MS, + NMCONNECTIVITY_CURL_HEAD_REQUEST, 2, defaultIface); // check both IP versions + currentInternetState = testInternet.getInternetState(); + + if (currentInternetState == INTERNET_CAPTIVE_PORTAL) // if captive portal found copy the URL + m_captiveURI = testInternet.getCaptivePortal(); + + if (currentInternetState != m_InternetState) + { + NMLOG_INFO("ideal connectivity state change from %s to %s", getInternetStateString(m_InternetState), getInternetStateString(currentInternetState)); + m_switchToInitial = true; + m_notify = true; + InitialRetryCount = 1; + timeoutInSec = NMCONNECTIVITY_MONITOR_MIN_INTERVAL; // retry in 5 sec + } } } } diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 56cedd934..b4b5bca6a 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -73,6 +73,7 @@ namespace WPEFramework NMLOG_INFO("NetworkManager Out-Of-Process Shutdown/Cleanup"); connectivityMonitor.stopConnectivityMonitor(); _instance = nullptr; + platform_deinit(); if(m_registrationThread.joinable()) { m_registrationThread.join(); @@ -250,6 +251,9 @@ namespace WPEFramework LOG_ENTRY_FUNCTION(); std::vector tmpEndpoints = connectivityMonitor.getConnectivityMonitorEndpoints(); endpoints = (Core::Service::Create(tmpEndpoints)); + if(endpoints == nullptr) { + return Core::ERROR_GENERAL; + } return Core::ERROR_NONE; } @@ -311,7 +315,7 @@ namespace WPEFramework ipversion = "IPv4"; if(interface.empty()) - interface = m_defaultInterface; + interface = getDefaultInterface(); return Core::ERROR_NONE; } @@ -337,7 +341,7 @@ namespace WPEFramework NMLOG_DEBUG("Primary interface: %s, eth0: [enabled=%d, connected=%d], wlan0: [enabled=%d, connected=%d]", interface.c_str(), m_ethEnabled.load(), m_ethConnected.load(), m_wlanEnabled.load(), m_wlanConnected.load()); - m_defaultInterface = interface; + setDefaultInterface(interface); return Core::ERROR_NONE; } @@ -364,7 +368,7 @@ namespace WPEFramework ipversion = "IPv4"; if (interface.empty()) - interface = m_defaultInterface; + interface = getDefaultInterface(); ipaddress = result.public_ip; #if USE_TELEMETRY @@ -637,7 +641,9 @@ namespace WPEFramework using Implementation = RPC::IteratorType; security = Core::Service::Create(modeInfo); - + if (security == nullptr) { + return Core::ERROR_GENERAL; + } return Core::ERROR_NONE; } @@ -651,7 +657,7 @@ namespace WPEFramework m_ethIPv4Address = {}; m_ethIPv6Address = {}; m_ethConnected.store(false); - m_defaultInterface = "wlan0"; // If WiFi is connected, make it the default interface + setDefaultInterface("wlan0"); // If WiFi is connected, make it the default interface // As default interface is changed to wlan0, switch connectivity monitor to initial check connectivityMonitor.switchToInitialCheck(); } @@ -660,10 +666,11 @@ namespace WPEFramework m_wlanIPv4Address = {}; m_wlanIPv6Address = {}; m_wlanConnected.store(false); + bool triggerConnectivityCheck; if(m_ethConnected.load()) - m_defaultInterface = "eth0"; // If Ethernet is connected, make it the default interface - - if(m_defaultInterface == interface) + setDefaultInterface("eth0"); // If Ethernet is connected, make it the default interface + triggerConnectivityCheck = (getDefaultInterface() == interface); + if(triggerConnectivityCheck) { // When WiFi is disconnected while Ethernet is connected, we don't need to trigger connectivity monitor. // For WiFi-only state and WiFi disconnected, we should trigger connectivity monitor. @@ -752,12 +759,14 @@ namespace WPEFramework } // FIXME : Availability of ip address for a given interface does not mean that its the default interface. This hardcoding will work for RDKProxy but not for Gnome. + bool isDefaultIface; if (m_ethConnected.load() && m_wlanConnected.load()) - m_defaultInterface = "eth0"; + setDefaultInterface("eth0"); else - m_defaultInterface = interface; + setDefaultInterface(interface); + isDefaultIface = (getDefaultInterface() == interface); - if(m_defaultInterface == interface) { + if(isDefaultIface) { // As default interface is connected, switch connectivity monitor to initial check any way connectivityMonitor.switchToInitialCheck(); } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 8a0c33d0a..f5bd49b17 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -26,6 +26,7 @@ #include #include #include +#include using namespace std; @@ -34,6 +35,10 @@ using namespace std; #include "NetworkManagerConnectivity.h" #include "NetworkManagerStunClient.h" +/* Forward declarations to avoid pulling GLib/libnm headers into this header */ +typedef struct _NMClient NMClient; +typedef struct _GMainContext GMainContext; + /* * Receiver thermal noise + BW factor + assumed noise figure (NF) (dB) * for a 20MHz channel, @@ -274,6 +279,7 @@ namespace WPEFramework private: void platform_init(void); + void platform_deinit(void); void platform_logging(const NetworkManagerLogger::LogLevel& level); void getInitialConnectionState(void); void executeExternally(NetworkEvents event, const string commandToExecute, string& response); @@ -317,9 +323,26 @@ namespace WPEFramework std::atomic m_wlanConnected; std::atomic m_ethEnabled; std::atomic m_wlanEnabled; - string m_defaultInterface; std::string m_lastConnectedSSID; + NMClient *m_nmClient{nullptr}; /* proxy NMClient — bound to m_nmContext */ + GMainContext *m_nmContext{nullptr}; /* isolated context, not the global default */ mutable ConnectivityMonitor connectivityMonitor; + + string getDefaultInterface() const + { + std::lock_guard lock(m_defaultInterfaceMutex); + return m_defaultInterface; + } + + void setDefaultInterface(const string& iface) + { + std::lock_guard lock(m_defaultInterfaceMutex); + m_defaultInterface = iface; + } + + private: + string m_defaultInterface; + mutable std::mutex m_defaultInterfaceMutex; }; } } diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index 22af0cdba..5ed0b60f7 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -429,6 +429,9 @@ namespace WPEFramework } } endpointsIter = (Core::Service::Create(endpoints)); + if(endpointsIter == nullptr){ + returnJson(rc); + } if (_networkManager) rc = _networkManager->SetConnectivityTestEndpoints(endpointsIter); @@ -664,6 +667,9 @@ namespace WPEFramework } } ssids = (Core::Service::Create(ssidslist)); + if(ssids == nullptr){ + returnJson(rc); + } } if (_networkManager) diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 9e9fe13c7..b661a8de3 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -25,7 +25,6 @@ #include #define IN_IS_ADDR_LINKLOCAL(a) ((((uint32_t)ntohl(a)) & 0xffff0000U) == 0xa9fe0000U) -static NMClient *client = NULL; using namespace WPEFramework; using namespace WPEFramework::Plugin; using namespace std; @@ -196,7 +195,7 @@ namespace WPEFramework const GPtrArray *connections = NULL; NMConnection *connection = NULL; - if (client == nullptr) { + if (m_nmClient == nullptr) { NMLOG_ERROR("NMClient is NULL"); return Core::ERROR_GENERAL; } @@ -207,7 +206,7 @@ namespace WPEFramework return Core::ERROR_BAD_REQUEST; } - connections = nm_client_get_connections(client); + connections = nm_client_get_connections(m_nmClient); if (connections == NULL || connections->len == 0) { NMLOG_ERROR("Could not get nm connections"); @@ -250,6 +249,12 @@ namespace WPEFramework return Core::ERROR_NONE; } + void NetworkManagerImplementation::platform_deinit() + { + if(m_nmClient) { g_object_unref(m_nmClient); m_nmClient = nullptr; } + if(m_nmContext) { g_main_context_unref(m_nmContext); m_nmContext = nullptr; } + } + void NetworkManagerImplementation::platform_logging(const NetworkManagerLogger::LogLevel& level) { /* set networkmanager daemon log level based on current plugin log level */ @@ -264,24 +269,35 @@ namespace WPEFramework GError *error = NULL; // initialize the NMClient object - client = nm_client_new(NULL, &error); - if (client == NULL) { + // Create an isolated GMainContext so this m_nmClient's D-Bus socket is NOT a + // source on the global default context. The event thread runs the default + // context via g_main_loop_run(); without isolation it would own and mutate + // this m_nmClient's GObjects concurrently with the RPC thread. + m_nmContext = g_main_context_new(); + g_main_context_push_thread_default(m_nmContext); + m_nmClient = nm_client_new(NULL, &error); + g_main_context_pop_thread_default(m_nmContext); + if (m_nmClient == NULL) { if (error) { NMLOG_FATAL("Error initializing NMClient: %s", error->message); g_error_free(error); } + if (m_nmContext) { + g_main_context_unref(m_nmContext); + m_nmContext = nullptr; + } return; } nmUtils::getDeviceProperties(); // get interface name form '/etc/device.proprties' - modifyDefaultConnConfig(client); - NMDeviceState ethState = ifaceState(client, nmUtils::ethIface()); + modifyDefaultConnConfig(m_nmClient); + NMDeviceState ethState = ifaceState(m_nmClient, nmUtils::ethIface()); if(ethState > NM_DEVICE_STATE_DISCONNECTED && ethState < NM_DEVICE_STATE_DEACTIVATING) - m_defaultInterface = nmUtils::ethIface(); + setDefaultInterface(nmUtils::ethIface()); else - m_defaultInterface = nmUtils::wlanIface(); + setDefaultInterface(nmUtils::wlanIface()); - NMLOG_INFO("default interface is %s", m_defaultInterface.c_str()); + NMLOG_INFO("default interface is %s", getDefaultInterface().c_str()); // getInitialConnectionState function not called here, as event monitor will report the initial state nmEvent = GnomeNetworkManagerEvents::getInstance(); nmEvent->startNetworkMangerEventMonitor(); @@ -294,12 +310,17 @@ namespace WPEFramework std::vector interfaceList; std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); - if(client == nullptr) { - NMLOG_FATAL("client connection null:"); + if(m_nmClient == nullptr) { + NMLOG_FATAL("NMClient is null"); return Core::ERROR_GENERAL; } - GPtrArray *devices = const_cast(nm_client_get_devices(client)); + if (m_nmContext) { + for (int i = 0; i < 100 && g_main_context_iteration(m_nmContext, FALSE); ++i){ + // Intentional empty body: just flushing the event queue + } + } + GPtrArray *devices = const_cast(nm_client_get_devices(m_nmClient)); if (devices == NULL) { NMLOG_ERROR("Failed to get device list."); return Core::ERROR_GENERAL; @@ -350,6 +371,9 @@ namespace WPEFramework using Implementation = RPC::IteratorType; interfacesItr = Core::Service::Create(interfaceList); + if(interfacesItr == nullptr) { + return Core::ERROR_GENERAL; + } return rc; } #if 0 @@ -426,9 +450,9 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) { - if(client == nullptr) + if(m_nmClient == nullptr) { - NMLOG_WARNING("client connection null:"); + NMLOG_WARNING("NMClient is null"); return Core::ERROR_RPC_CALL_FAILED; } @@ -466,7 +490,7 @@ namespace WPEFramework // Bring down the ethernet interface before wiping its connections // so NM doesn't immediately re-activate them during deletion. - NMDevice *ethDev = nm_client_get_device_by_iface(client, interface.c_str()); + NMDevice *ethDev = nm_client_get_device_by_iface(m_nmClient, interface.c_str()); if(ethDev) { GError *discError = nullptr; @@ -479,7 +503,7 @@ namespace WPEFramework } } - const GPtrArray *connections = nm_client_get_connections(client); + const GPtrArray *connections = nm_client_get_connections(m_nmClient); if(connections && connections->len > 0) { /* Snapshot the list before iterating: nm_client_get_connections() @@ -570,19 +594,26 @@ namespace WPEFramework bool isIfaceFound = false; std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); - if(client == nullptr) - { - NMLOG_WARNING("client connection null:"); - return Core::ERROR_RPC_CALL_FAILED; - } - if(interface.empty() || (wifiname != interface && ethname != interface)) { NMLOG_ERROR("interface: %s; not valied", interface.c_str()!=nullptr? interface.c_str():"empty"); return Core::ERROR_GENERAL; } - GPtrArray *devices = const_cast(nm_client_get_devices(client)); + if(m_nmClient == nullptr) + { + NMLOG_WARNING("NMClient is null"); + return Core::ERROR_RPC_CALL_FAILED; + } + + if (m_nmContext) { + for (int i = 0; i < 100 && g_main_context_iteration(m_nmContext, FALSE); ++i){ + // Intentional empty body: just flushing the event queue + } + } + + GPtrArray *devices = const_cast(nm_client_get_devices(m_nmClient)); + if (devices == NULL) { NMLOG_ERROR("Failed to get device list."); return Core::ERROR_GENERAL; @@ -654,12 +685,6 @@ namespace WPEFramework std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); - if(client == nullptr) - { - NMLOG_WARNING("client connection null:"); - return Core::ERROR_RPC_CALL_FAILED; - } - if(interface.empty()) { if(Core::ERROR_NONE != GetPrimaryInterface(interface)) @@ -721,7 +746,24 @@ namespace WPEFramework } } - device = nm_client_get_device_by_iface(client, interface.c_str()); + if(m_nmClient == nullptr) + { + NMLOG_WARNING("NMClient is null"); + return Core::ERROR_RPC_CALL_FAILED; + } + + /* Drain any pending D-Bus property-change events queued on m_nmContext + * before reading libnm GObject state. Because m_nmContext is isolated + * from the event thread, nobody else can run it — so this loop is + * single-threaded and safe. It ensures m_nmClient reflects the latest state + * from NetworkManager before we start iterating connections/addresses. */ + if (m_nmContext) { + for (int i = 0; i < 100 && g_main_context_iteration(m_nmContext, FALSE); ++i){ + // Intentional empty body: just flushing the event queue + } + } + + device = nm_client_get_device_by_iface(m_nmClient, interface.c_str()); if (device == NULL) { NMLOG_FATAL("libnm doesn't have device corresponding to %s", interface.c_str()); @@ -739,7 +781,7 @@ namespace WPEFramework // if(ipversion.empty()) // NMLOG_DEBUG("ipversion is empty default value IPv4"); - const GPtrArray *connections = nm_client_get_active_connections(client); + const GPtrArray *connections = nm_client_get_active_connections(m_nmClient); if(connections == NULL) { NMLOG_WARNING("no active connection; ip is not assigned to interface"); @@ -796,9 +838,14 @@ namespace WPEFramework { for (guint i = 0; i < ipByte->len; i++) { + ipStr.clear(); ipAddr = static_cast(ipByte->pdata[i]); if(ipAddr) - ipStr = nm_ip_address_get_address(ipAddr); + { + const char* addr = nm_ip_address_get_address(ipAddr); + if(addr) + ipStr = addr; + } if(!ipStr.empty()) { // Skip link-local IPv4 addresses (169.254.x.x) @@ -808,7 +855,7 @@ namespace WPEFramework NMLOG_DEBUG("Skipping link-local IPv4 address: %s", ipStr.c_str()); continue; } - result.ipaddress = nm_ip_address_get_address(ipAddr); + result.ipaddress = ipStr; result.prefix = nm_ip_address_get_prefix(ipAddr); NMLOG_DEBUG("IPv4 addr: %s/%d", result.ipaddress.c_str(), result.prefix); } @@ -867,9 +914,14 @@ namespace WPEFramework { for (guint i = 0; i < ipArray->len; i++) { + ipStr.clear(); ipAddr = static_cast(ipArray->pdata[i]); if(ipAddr) - ipStr = nm_ip_address_get_address(ipAddr); + { + const char* addr = nm_ip_address_get_address(ipAddr); + if(addr) + ipStr = addr; + } if(!ipStr.empty()) { if (ipStr.compare(0, 5, "fe80:") == 0 || ipStr.compare(0, 6, "fe80::") == 0) @@ -983,6 +1035,9 @@ namespace WPEFramework if (!ssidList.empty()) { ssids = Core::Service::Create(ssidList); + if(ssids == nullptr) { + return Core::ERROR_GENERAL; + } rc = Core::ERROR_NONE; } else diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 589cbb964..583b4b141 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -1879,7 +1879,11 @@ namespace WPEFramework error = NULL; } else - NMLOG_ERROR("NetworkManager cleint create failed"); + NMLOG_ERROR("NetworkManager client create failed"); + g_main_context_pop_thread_default(wpsContext); + g_main_context_release(wpsContext); + g_main_context_unref(wpsContext); + wpsContext = NULL; break; } @@ -1887,6 +1891,10 @@ namespace WPEFramework if(wifidevice == NULL) { NMLOG_ERROR("Failed to get device list."); + g_main_context_pop_thread_default(wpsContext); + g_main_context_release(wpsContext); + g_main_context_unref(wpsContext); + wpsContext = NULL; break; } @@ -1926,6 +1934,10 @@ namespace WPEFramework if(ApList == NULL) { NMLOG_ERROR("Aplist Error !"); + g_main_context_pop_thread_default(wpsContext); + g_main_context_release(wpsContext); + g_main_context_unref(wpsContext); + wpsContext = NULL; break; } @@ -2018,6 +2030,11 @@ namespace WPEFramework { /* if wps action not triggerd do a scanning request */ nm_device_wifi_request_scan(NM_DEVICE_WIFI(wifidevice), NULL, &error); + if(error) { + NMLOG_WARNING("WiFi scan request failed: %s", error->message); + g_error_free(error); + error = NULL; + } } g_main_context_pop_thread_default(wpsContext); diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp index 6e848836e..73aa49d93 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp @@ -90,6 +90,11 @@ namespace WPEFramework nmUtils::setNetworkManagerlogLevelToTrace(); } + void NetworkManagerImplementation::platform_deinit() + { + return; + } + void NetworkManagerImplementation::platform_init() { ::_instance = this; @@ -104,14 +109,14 @@ namespace WPEFramework if(_nmGdbusClient->getDeviceInfo(GnomeUtils::getEthIfname(), ethDevInfo)) { if(ethDevInfo.state > NM_DEVICE_STATE_DISCONNECTED && ethDevInfo.state < NM_DEVICE_STATE_DEACTIVATING) - m_defaultInterface = GnomeUtils::getEthIfname(); + setDefaultInterface(GnomeUtils::getEthIfname()); else - m_defaultInterface = GnomeUtils::getWifiIfname(); + setDefaultInterface(GnomeUtils::getWifiIfname()); } else - m_defaultInterface = GnomeUtils::getWifiIfname(); + setDefaultInterface(GnomeUtils::getWifiIfname()); - NMLOG_INFO("default interface is %s", m_defaultInterface.c_str()); + NMLOG_INFO("default interface is %s", getDefaultInterface().c_str()); // Start event monitoring _nmGdbusEvents->startNetworkMangerEventMonitor(); @@ -136,6 +141,9 @@ namespace WPEFramework NMLOG_ERROR("GetAvailableInterfaces failed"); using Implementation = RPC::IteratorType; interfacesItr = Core::Service::Create(interfaceList); + if(interfacesItr == nullptr){ + return Core::ERROR_GENERAL; + } return rc; } @@ -148,7 +156,7 @@ namespace WPEFramework { if(_nmGdbusClient->getDefaultInterface(interface)) { - _instance->m_defaultInterface = interface; + _instance->setDefaultInterface(interface); return Core::ERROR_NONE; } else @@ -234,6 +242,9 @@ namespace WPEFramework if(_nmGdbusClient->getKnownSSIDs(ssidList) && !ssidList.empty()) { ssids = Core::Service::Create(ssidList); + if(ssids == nullptr) { + return Core::ERROR_GENERAL; + } rc = Core::ERROR_NONE; } else diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 670b0a6fc..f218d61c6 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -399,8 +399,8 @@ namespace WPEFramework if(iface.connected) { NMLOG_INFO("'%s' interface is connected", iface.name.c_str()); - if(m_defaultInterface != iface.name) - ReportActiveInterfaceChange(m_defaultInterface, iface.name); + if(getDefaultInterface() != iface.name) + ReportActiveInterfaceChange(getDefaultInterface(), iface.name); Exchange::INetworkManager::IPAddress addrv4; Exchange::INetworkManager::IPAddress addrv6; std::string ipversion = "IPv4"; @@ -444,6 +444,11 @@ namespace WPEFramework return Core::ERROR_NONE; } + void NetworkManagerImplementation::platform_deinit() + { + return; + } + void NetworkManagerImplementation::platform_init() { LOG_ENTRY_FUNCTION(); @@ -562,6 +567,9 @@ namespace WPEFramework } using Implementation = RPC::IteratorType; interfacesItr = Core::Service::Create(interfaceList); + if(interfacesItr == nullptr) { + return Core::ERROR_GENERAL; + } rc = Core::ERROR_NONE; } @@ -583,7 +591,8 @@ namespace WPEFramework if (IARM_RESULT_SUCCESS == IARM_Bus_Call(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_getDefaultInterface, (void*)&defaultRoute, sizeof(defaultRoute))) { NMLOG_INFO ("Call to %s for %s returned interface = %s, gateway = %s", IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETSRVMGR_API_getDefaultInterface, defaultRoute.interface, defaultRoute.gateway); - interface = m_defaultInterface = defaultRoute.interface; + interface = defaultRoute.interface; + setDefaultInterface(defaultRoute.interface); rc = Core::ERROR_NONE; } else @@ -699,7 +708,7 @@ namespace WPEFramework if(interface.empty()) { - interface = m_defaultInterface; + interface = getDefaultInterface(); } if(ipversion.empty()) { @@ -1037,6 +1046,9 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { NMLOG_INFO ("GetKnownSSIDs Success"); ssids = Core::Service::Create(ssidList); + if(ssids == nullptr) { + return Core::ERROR_GENERAL; + } rc = Core::ERROR_NONE; } else diff --git a/tests/l2Test/libnm/l2_test_libnmproxy.cpp b/tests/l2Test/libnm/l2_test_libnmproxy.cpp index bd633dd74..e4f9b1ec8 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxy.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxy.cpp @@ -770,7 +770,6 @@ TEST_F(NetworkManagerTest, GetIPSettings_ipv4_config_valid) .WillOnce(::testing::Return("192.168.1.0")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_address_get_address(::testing::_)) - .WillOnce(::testing::Return("192.168.1.2")) .WillOnce(::testing::Return("192.168.1.2")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_addresses(::testing::_)) @@ -1371,4 +1370,4 @@ TEST_F(NetworkManagerTest, SetIPSettings_static_wlan0_autoConffalse) g_object_unref(dummyActiveConn); g_object_unref(dummyRemoteConn); -} \ No newline at end of file +} From cea0da05b03de770e4ce967f0446f28885fc6219 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Thu, 30 Apr 2026 12:13:55 -0400 Subject: [PATCH 233/271] Release of 2.2.0 Release of 2.2.0 --- CHANGELOG.md | 8 ++++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36b89b1ac..7fa5294bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,14 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [2.2.0] - 2026-04-30 +### Added +- Added new method to connection to specific known SSID +- Extended WiFiConnect method to support BSSID and specific Band +- Defaulted to use RDKLogger and avoided redundant logging for few methods +- Added Minimal Ethernet Connection Profile for migration handling +- General improvements on RPC methods & crash resilience + ## [2.1.0] - 2026-03-20 ### Added - Added T2 eventing from NetworkManager diff --git a/CMakeLists.txt b/CMakeLists.txt index ee88d683f..99ffdb2dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 2) -set(VERSION_MINOR 1) +set(VERSION_MINOR 2) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 4d1fd76a5..2252aed05 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "2.1.0" + "version": "2.2.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 1f350da82..9e4d969cf 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 2.1.0** +**Version: 2.2.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 2.1.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 2.2.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 4b3f282e8732440d330a79057753ea998ea4dad7 Mon Sep 17 00:00:00 2001 From: jincysam87 <167995204+jincysam87@users.noreply.github.com> Date: Thu, 7 May 2026 11:51:16 -0400 Subject: [PATCH 234/271] RDKEMW-15139 : WiFi toogle OFF response took 12sec (#305) Reason for change: In SetInterfaceState(), nm_device_get_state() was not returning the state correctly Test Procedure: Check wifi on/off via curl command Risks: Medium Signed-off-by: jincysaramma_sam@comcast.com --- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 25 +++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 583b4b141..2348124d8 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -2199,24 +2199,27 @@ namespace WPEFramework // that can cause networking issues. nm_device_disconnect_async(device, nullptr, disconnectCb, this); wait(m_loop); - // Wait until device is truly disconnected + + // Identify the correct context + GMainContext *device_context = g_main_loop_get_context(m_loop); int retry = 24; // 12 seconds NMDeviceState oldDevState = NM_DEVICE_STATE_UNKNOWN; while (retry-- > 0) { - /* Force glib event processing to update state - * This below line will create an uncertain time wait. We are taking a fixed time interval of 12 seconds. - */ - // while (g_main_context_iteration(NULL, FALSE)); - g_usleep(500 * 1000); // give some time to NM to process the request + // If there are multiple messages backed up, process a bounded number + // of pending iterations so this path cannot stall indefinitely if the + // context keeps receiving new work. + while (g_main_context_iteration(device_context, FALSE)); + + // Fetch the updated state deviceState = nm_device_get_state(device); - if(oldDevState != deviceState) - { + if(oldDevState != deviceState) { oldDevState = deviceState; - NMLOG_WARNING("Device state: %d", deviceState); + NMLOG_WARNING("Device state: %d Retry: %d", deviceState, retry); } - - if (deviceState <= NM_DEVICE_STATE_DISCONNECTED) + if (deviceState <= NM_DEVICE_STATE_DISCONNECTED) { break; + } + g_usleep(500 * 1000); // give some time to NM to process the request } } } From 58cecb5d3f368424741a04f45cf602c865e85e59 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 15 May 2026 13:27:39 -0400 Subject: [PATCH 235/271] RDKEMW-18663: Changed the autostart option for the plugins (#304) * RDK-60581: Changed the autostart option for the plugins Reason for Change: Autostart of the plugins are changved to false Test Procedure: Check whether the plugin starts in sqeuence and there is no regression Priority: P1 Risks: Medium * RDK-60581: Changed the autostart option for the plugins Reason for Change: Autostart of the plugins are changved to false Test Procedure: Check whether the plugin starts in sqeuence and there is no regression Priority: P1 Risks: Medium --- legacy/LegacyNetworkAPIs.conf.in | 2 +- legacy/LegacyNetworkAPIs.config | 2 +- legacy/LegacyWiFiManagerAPIs.conf.in | 2 +- legacy/LegacyWiFiManagerAPIs.config | 2 +- plugin/CMakeLists.txt | 4 ---- plugin/NetworkManager.conf.in | 2 +- plugin/NetworkManager.config | 2 +- .../gnome/systemd/gnome-networkmanager-mfrmgr-migration.conf | 2 -- 8 files changed, 6 insertions(+), 12 deletions(-) delete mode 100644 plugin/gnome/systemd/gnome-networkmanager-mfrmgr-migration.conf diff --git a/legacy/LegacyNetworkAPIs.conf.in b/legacy/LegacyNetworkAPIs.conf.in index c9e5db2c5..39cf67b9c 100644 --- a/legacy/LegacyNetworkAPIs.conf.in +++ b/legacy/LegacyNetworkAPIs.conf.in @@ -1,4 +1,4 @@ precondition = ["Platform"] callsign = "org.rdk.Network" -autostart = "true" +autostart = "false" startuporder = "@PLUGIN_LEGACY_NW_STARTUPORDER@" diff --git a/legacy/LegacyNetworkAPIs.config b/legacy/LegacyNetworkAPIs.config index 74572ce99..34c60c67c 100644 --- a/legacy/LegacyNetworkAPIs.config +++ b/legacy/LegacyNetworkAPIs.config @@ -1,4 +1,4 @@ -set (autostart true) +set (autostart false) set (preconditions Platform) set (callsign "org.rdk.Network") set (startuporder ${PLUGIN_LEGACY_NW_STARTUPORDER}) diff --git a/legacy/LegacyWiFiManagerAPIs.conf.in b/legacy/LegacyWiFiManagerAPIs.conf.in index 80e3c699c..02f461124 100644 --- a/legacy/LegacyWiFiManagerAPIs.conf.in +++ b/legacy/LegacyWiFiManagerAPIs.conf.in @@ -1,4 +1,4 @@ precondition = ["Platform"] callsign = "org.rdk.Wifi" -autostart = "true" +autostart = "false" startuporder = "@PLUGIN_LEGACY_WIFI_STARTUPORDER@" diff --git a/legacy/LegacyWiFiManagerAPIs.config b/legacy/LegacyWiFiManagerAPIs.config index 13a832da9..7aa4dfb37 100644 --- a/legacy/LegacyWiFiManagerAPIs.config +++ b/legacy/LegacyWiFiManagerAPIs.config @@ -1,4 +1,4 @@ -set (autostart true) +set (autostart false) set (preconditions Platform) set (callsign "org.rdk.Wifi") set (startuporder ${PLUGIN_LEGACY_WIFI_STARTUPORDER}) diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index d834861d2..a5b12d948 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -158,10 +158,6 @@ if(ENABLE_GNOME_NETWORKMANAGER) DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/rdk) install(FILES gnome/systemd/gnome-networkmanager-migration.conf DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/systemd/system/wpeframework-networkmanager.service.d) - if(ENABLE_MIGRATION_MFRMGR_SUPPORT) - install(FILES gnome/systemd/gnome-networkmanager-mfrmgr-migration.conf - DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/systemd/system/wpeframework-networkmanager.service.d) - endif(ENABLE_MIGRATION_MFRMGR_SUPPORT) endif(ENABLE_GNOME_NETWORKMANAGER) #Generate Plugin configuration file diff --git a/plugin/NetworkManager.conf.in b/plugin/NetworkManager.conf.in index 379907bb0..b48762963 100644 --- a/plugin/NetworkManager.conf.in +++ b/plugin/NetworkManager.conf.in @@ -1,6 +1,6 @@ callsign= "org.rdk.NetworkManager" startuporder = "@PLUGIN_NETWORKMANAGER_STARTUPORDER@" -autostart = "true" +autostart = "false" process= JSON() process.add("outofprocess", "true") diff --git a/plugin/NetworkManager.config b/plugin/NetworkManager.config index c70241fcd..595635098 100644 --- a/plugin/NetworkManager.config +++ b/plugin/NetworkManager.config @@ -1,6 +1,6 @@ set(callsign "org.rdk.NetworkManager") set (startuporder ${PLUGIN_NETWORKMANAGER_STARTUPORDER}) -set (autostart true) +set (autostart false) map() key(root) diff --git a/plugin/gnome/systemd/gnome-networkmanager-mfrmgr-migration.conf b/plugin/gnome/systemd/gnome-networkmanager-mfrmgr-migration.conf deleted file mode 100644 index 67b628c39..000000000 --- a/plugin/gnome/systemd/gnome-networkmanager-mfrmgr-migration.conf +++ /dev/null @@ -1,2 +0,0 @@ -[Unit] -After= iarmbusd.service mfrmgr.service From 3735bc68710f915317bf708aac9009eac9d70d66 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Thu, 21 May 2026 14:51:23 -0400 Subject: [PATCH 236/271] Release of 2.3.0 Release of 2.3.0 --- CHANGELOG.md | 5 +++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fa5294bb..07c248184 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [2.3.0] - 2026-05-21 +### Fixed +- Fixed the issue which leads Enabling and Disabling of interfaces are taking longer +- Configured the NetworkManager Thunder Plugin to not to autostart; a systemd service will activate the plugin on boot-up + ## [2.2.0] - 2026-04-30 ### Added - Added new method to connection to specific known SSID diff --git a/CMakeLists.txt b/CMakeLists.txt index 99ffdb2dc..a04ad16b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 2) -set(VERSION_MINOR 2) +set(VERSION_MINOR 3) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 2252aed05..65fb6e6c9 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "2.2.0" + "version": "2.3.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 9e4d969cf..2c31542f4 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 2.2.0** +**Version: 2.3.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 2.2.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 2.3.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 6954ba0d6abe6eae6df187efef9a6e453204a842 Mon Sep 17 00:00:00 2001 From: jincysam87 <167995204+jincysam87@users.noreply.github.com> Date: Thu, 28 May 2026 10:37:47 -0400 Subject: [PATCH 237/271] RDK-61444 : Network Manager Plugin to support Scan Specific SSID (#306) Reason for change: Support to scan multiple SSIDs Test Procedure: Test wifi scan API with multiple SSIDs Risks: Low Signed-off-by: [jincysaramma_sam@comcast.com](mailto:jincysaramma_sam@comcast.com) --- .github/workflows/validate_pr_desc.yml | 2 +- definition/NetworkManager.json | 26 +++++++---- docs/NetworkManagerPlugin.md | 17 ++++--- interface/INetworkManager.h | 4 +- legacy/LegacyWiFiManagerAPIs.cpp | 28 ++++++++++-- plugin/NetworkManagerImplementation.cpp | 31 +++++++++---- plugin/NetworkManagerImplementation.h | 4 +- plugin/NetworkManagerJsonEnum.h | 7 +++ plugin/NetworkManagerJsonRpc.cpp | 44 ++++++++++++++---- plugin/gnome/NetworkManagerGnomeProxy.cpp | 45 +++++++++++++++---- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 28 ++++++------ plugin/gnome/NetworkManagerGnomeWIFI.h | 3 +- .../gnome/gdbus/NetworkManagerGdbusProxy.cpp | 2 +- plugin/rdk/NetworkManagerRDKProxy.cpp | 15 ++++--- tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp | 2 +- tests/l2Test/rdk/l2_test_rdkproxy.cpp | 4 +- tests/mocks/INetworkManagerMock.h | 2 +- tools/plugincli/NetworkManagerLibnmTest.cpp | 3 +- 18 files changed, 192 insertions(+), 75 deletions(-) diff --git a/.github/workflows/validate_pr_desc.yml b/.github/workflows/validate_pr_desc.yml index b6249ff71..3264db93f 100644 --- a/.github/workflows/validate_pr_desc.yml +++ b/.github/workflows/validate_pr_desc.yml @@ -15,7 +15,7 @@ jobs: PR_TITLE: ${{ github.event.pull_request.title }} run: | # Define valid ticket IDs - VALID_TICKET_IDS=("RDKEMW") + VALID_TICKET_IDS=("RDKEMW" "RDK") # Function to validate ticket format and ID validate_ticket() { diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 65fb6e6c9..8ada9b760 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -846,17 +846,27 @@ } }, "StartWiFiScan":{ - "summary": "Initiates WiFi scaning. This method supports scanning for specific range of frequency like 2.4GHz only or 5GHz only or 6GHz only or ALL. When no input passed about the frequency to be scanned, it scans for all. When list of SSIDs to be scanned specifically, it can be passed as input. It publishes 'onAvailableSSIDs' event upon completion.", + "summary": "Initiates WiFi scanning. This method supports scanning specific frequency bands (2.4GHz, 5GHz, 6GHz). When no input is passed for frequency, it scans all supported frequencies. When list of SSIDs to be scanned specifically, it can be passed as input. It publishes 'onAvailableSSIDs' event upon completion.", "events": { "onAvailableSSIDs" : "Triggered when list of SSIDs is available after the scan completes." }, "params": { "type": "object", "properties": { - "frequency": { - "summary": "The frequency to scan. An empty or `null` value scans all frequencies.", - "type": "string", - "example": "5" + "frequencies": { + "summary": "Frequency bands to scan. Omit this field or pass \"ALL\" to scan all frequencies.", + "type": "array", + "items": { + "summary": "The frequency to scan.", + "type": "string", + "enum": [ + "ALL", + "2.4", + "5", + "6" + ], + "example": "2.4" + } }, "ssids": { "summary": "The list of SSIDs to be scanned.", @@ -1233,7 +1243,7 @@ } }, "GetWiFiSignalQuality":{ - "summary": "Get WiFi signal quality of currently connected SSID. The signal quality is identifed based on the Signal to Noise ratio which is calculated as SNR = rssi - noise. The possible states are\n* 'Excellent' : More than 40 dBm\n* 'Good' : 40 dBm to 25 dBm\n* 'Fair' : 25 dBm to 18 dBm\n* 'Weak' : 18 dBm to 0 dBm\n* 'Disconnected' : 0 dBm\n", + "summary": "Get WiFi signal quality of currently connected SSID. The signal quality is identified based on the Signal to Noise ratio which is calculated as SNR = rssi - noise. The possible states are\n* 'Excellent' : More than 40 dBm\n* 'Good' : 40 dBm to 25 dBm\n* 'Fair' : 25 dBm to 18 dBm\n* 'Weak' : 18 dBm to 0 dBm\n* 'Disconnected' : 0 dBm\n", "events":{ "onWiFiSignalQualityChange" : "Triggered when Wifi signal strength switches between Excellent, Good, Fair, Weak." }, @@ -1294,7 +1304,7 @@ "example": 2 }, "EAP": { - "summary": "Supports security mode WPA enterpise", + "summary": "Supports security mode WPA enterprise", "type": "integer", "example": 3 } @@ -1455,7 +1465,7 @@ "type": "object", "properties": { "prevState":{ - "summary": "The privious internet connection state", + "summary": "The previous internet connection state", "type": "integer", "example": 1 }, diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 2c31542f4..bba3aa46f 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -89,7 +89,7 @@ NetworkManager interface methods: | [GetPublicIP](#method.GetPublicIP) | Gets the internet/public IP Address of the device | | [Ping](#method.Ping) | Pings the specified endpoint with the specified number of packets | | [Trace](#method.Trace) | Traces the specified endpoint with the specified number of packets using `traceroute` | -| [StartWiFiScan](#method.StartWiFiScan) | Initiates WiFi scaning | +| [StartWiFiScan](#method.StartWiFiScan) | Initiates WiFi scanning | | [StopWiFiScan](#method.StopWiFiScan) | Stops WiFi scanning | | [GetKnownSSIDs](#method.GetKnownSSIDs) | Gets list of saved SSIDs | | [AddToKnownSSIDs](#method.AddToKnownSSIDs) | Saves the SSID, passphrase, and security mode for upcoming and future sessions | @@ -1006,7 +1006,7 @@ Traces the specified endpoint with the specified number of packets using `tracer ## *StartWiFiScan [method](#head.Methods)* -Initiates WiFi scaning. This method supports scanning for specific range of frequency like 2.4GHz only or 5GHz only or 6GHz only or ALL. When no input passed about the frequency to be scanned, it scans for all. When list of SSIDs to be scanned specifically, it can be passed as input. It publishes 'onAvailableSSIDs' event upon completion. +Initiates WiFi scanning. This method supports scanning specific frequency bands (2.4GHz, 5GHz, 6GHz). When no input is passed for frequency, it scans all supported frequencies. When list of SSIDs to be scanned specifically, it can be passed as input. It publishes 'onAvailableSSIDs' event upon completion. Also see: [onAvailableSSIDs](#event.onAvailableSSIDs) @@ -1015,7 +1015,8 @@ Also see: [onAvailableSSIDs](#event.onAvailableSSIDs) | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params?.frequency | string | *(optional)* The frequency to scan. An empty or `null` value scans all frequencies | +| params?.frequencies | array | *(optional)* Frequency bands to scan. Omit this field or pass "ALL" to scan all frequencies | +| params?.frequencies[#] | string | *(optional)* The frequency to scan | | params?.ssids | array | *(optional)* The list of SSIDs to be scanned | | params?.ssids[#] | string | *(optional)* The SSID to scan | @@ -1036,7 +1037,9 @@ Also see: [onAvailableSSIDs](#event.onAvailableSSIDs) "id": 42, "method": "org.rdk.NetworkManager.1.StartWiFiScan", "params": { - "frequency": "5", + "frequencies": [ + "2.4" + ], "ssids": [ "Xfinity Mobile" ] @@ -1558,7 +1561,7 @@ This method takes no parameters. ## *GetWiFiSignalQuality [method](#head.Methods)* -Get WiFi signal quality of currently connected SSID. The signal quality is identifed based on the Signal to Noise ratio which is calculated as SNR = rssi - noise. The possible states are +Get WiFi signal quality of currently connected SSID. The signal quality is identified based on the Signal to Noise ratio which is calculated as SNR = rssi - noise. The possible states are * 'Excellent' : More than 40 dBm * 'Good' : 40 dBm to 25 dBm * 'Fair' : 25 dBm to 18 dBm @@ -1631,7 +1634,7 @@ This method takes no parameters. | result.security.NONE | integer | Security mode for open network | | result.security.WPA_PSK | integer | Supports security mode WPA,WPA-PSK,WPA2-PSK, WPA3-Personal-Transition | | result.security.SAE | integer | Supports security mode WPA3-Personal | -| result.security.EAP | integer | Supports security mode WPA enterpise | +| result.security.EAP | integer | Supports security mode WPA enterprise | | result.success | boolean | Whether the request succeeded | ### Example @@ -1891,7 +1894,7 @@ Triggered when internet connection state changed.The possible internet connectio | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.prevState | integer | The privious internet connection state | +| params.prevState | integer | The previous internet connection state | | params.prevStatus | string | The previous internet connection status | | params.state | integer | The internet connection state | | params.status | string | The internet connection status | diff --git a/interface/INetworkManager.h b/interface/INetworkManager.h index 15c739cff..ce8cb5090 100644 --- a/interface/INetworkManager.h +++ b/interface/INetworkManager.h @@ -105,7 +105,7 @@ namespace WPEFramework enum WIFIFrequency : uint8_t { - WIFI_FREQUENCY_NONE /* @text: NONE */, + WIFI_FREQUENCY_ALL /* @text: ALL */, WIFI_FREQUENCY_2_4_GHZ /* @text: 2.4GHz */, WIFI_FREQUENCY_5_GHZ /* @text: 5GHz */, WIFI_FREQUENCY_6_GHZ /* @text: 6GHz */, @@ -248,7 +248,7 @@ namespace WPEFramework // WiFi Specific Methods /* @brief Initiate a WIFI Scan; This is Async method and returns the scan results as Event */ - virtual uint32_t StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) = 0; + virtual uint32_t StartWiFiScan(IStringIterator* const frequencies /* @in */, IStringIterator* const ssids/* @in */) = 0; virtual uint32_t StopWiFiScan(void) = 0; virtual uint32_t GetKnownSSIDs(IStringIterator*& ssids /* @out */) = 0; diff --git a/legacy/LegacyWiFiManagerAPIs.cpp b/legacy/LegacyWiFiManagerAPIs.cpp index 9132ed097..9a6573ff5 100644 --- a/legacy/LegacyWiFiManagerAPIs.cpp +++ b/legacy/LegacyWiFiManagerAPIs.cpp @@ -634,12 +634,27 @@ namespace WPEFramework { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string frequency{}; + Exchange::INetworkManager::IStringIterator* frequencies = nullptr; Exchange::INetworkManager::IStringIterator* ssids = NULL; - if (parameters.HasLabel("frequency")) - frequency = parameters["frequency"].String(); + { + std::vector frequencyList; + if (Core::JSON::Variant::type::STRING == parameters["frequency"].Content()) + { + frequencyList.push_back(parameters["frequency"].String()); + } + else + { + NMLOG_ERROR("Unexpected variant type in frequency parameter."); + returnJson(rc); + } + + frequencies = (Core::Service::Create(frequencyList)); + if (frequencies == nullptr) { + returnJson(rc); + } + } if (parameters.HasLabel("ssid")) { @@ -654,6 +669,8 @@ namespace WPEFramework ssids = (Core::Service::Create(inputSSIDlist)); if (ssids == nullptr) { + if (frequencies) + frequencies->Release(); returnJson(rc); } } @@ -661,12 +678,15 @@ namespace WPEFramework auto _nwmgr = m_service->QueryInterfaceByCallsign(NETWORK_MANAGER_CALLSIGN); if (_nwmgr) { - rc = _nwmgr->StartWiFiScan(frequency, ssids); + rc = _nwmgr->StartWiFiScan(frequencies, ssids); _nwmgr->Release(); } else rc = Core::ERROR_UNAVAILABLE; + if (frequencies) + frequencies->Release(); + if (ssids) ssids->Release(); diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index b4b5bca6a..c1fe15f8a 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -590,7 +590,6 @@ namespace WPEFramework return; } - void NetworkManagerImplementation::filterScanResults(JsonArray &ssids) { JsonArray result; @@ -598,27 +597,41 @@ namespace WPEFramework std::unordered_set scanForSsidsSet(m_filterSsidslist.begin(), m_filterSsidslist.end()); // If neither SSID list nor frequency is provided, exit - if (m_filterSsidslist.empty() && m_filterfrequency.empty()) + if (m_filterSsidslist.empty() && m_filterFrequencies.empty()) { NMLOG_DEBUG("Neither SSID nor Frequency is provided. Exiting function."); return; } - if (!m_filterfrequency.empty()) - { - filterFreq = std::stod(m_filterfrequency); - } - for (int i = 0; i < ssids.Length(); i++) { JsonObject object = ssids[i].Object(); string ssid = object["ssid"].String(); string frequency = object["frequency"].String(); - double frequencyValue = std::stod(frequency); bool ssidMatches = scanForSsidsSet.empty() || scanForSsidsSet.find(ssid) != scanForSsidsSet.end(); - bool freqMatches = m_filterfrequency.empty() || (filterFreq == frequencyValue); + bool freqMatches = m_filterFrequencies.empty(); + if (!freqMatches) + { + for (const auto& selectedFrequency : m_filterFrequencies) + { + if (selectedFrequency == "ALL") + { + freqMatches = true; + break; + } + else + { + filterFreq = std::stod(selectedFrequency); + if (filterFreq == frequencyValue) + { + freqMatches = true; + break; + } + } + } + } if (ssidMatches && freqMatches) result.Add(object); diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index f5bd49b17..a1563787e 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -216,7 +216,7 @@ namespace WPEFramework // WiFi Specific Methods /* @brief Initiate a WIFI Scan; This is Async method and returns the scan results as Event */ - uint32_t StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) override; + uint32_t StartWiFiScan(IStringIterator* const frequencies /* @in */, IStringIterator* const ssids/* @in */) override; uint32_t StopWiFiScan(void) override; uint32_t GetKnownSSIDs(IStringIterator*& ssids /* @out */) override; @@ -301,7 +301,7 @@ namespace WPEFramework uint16_t m_stunBindTimeout; uint16_t m_stunCacheTimeout; std::thread m_registrationThread; - string m_filterfrequency; + std::vector m_filterFrequencies; std::vector m_filterSsidslist; std::thread m_monitorThread; diff --git a/plugin/NetworkManagerJsonEnum.h b/plugin/NetworkManagerJsonEnum.h index 07b9318a5..d47768e1a 100644 --- a/plugin/NetworkManagerJsonEnum.h +++ b/plugin/NetworkManagerJsonEnum.h @@ -96,4 +96,11 @@ ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::IPStatus) { Exchange::INetworkManager::IPStatus::IP_ACQUIRED, _TXT("ACQUIRED") }, ENUM_CONVERSION_END(Exchange::INetworkManager::IPStatus) +ENUM_CONVERSION_BEGIN(Exchange::INetworkManager::WIFIFrequency) + { Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_ALL, _TXT("ALL") }, + { Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_2_4_GHZ, _TXT("2.4") }, + { Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_5_GHZ, _TXT("5") }, + { Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_6_GHZ, _TXT("6") }, +ENUM_CONVERSION_END(Exchange::INetworkManager::WIFIFrequency) + } diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index 5ed0b60f7..d49e6c5d4 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -642,19 +642,40 @@ namespace WPEFramework { LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; - string frequency{}; - Exchange::INetworkManager::IStringIterator* ssids = NULL; + Exchange::INetworkManager::IStringIterator* frequencies = nullptr; + Exchange::INetworkManager::IStringIterator* ssids = NULL; - if (parameters.HasLabel("frequency")) - frequency = parameters["frequency"].String(); + if (parameters.HasLabel("frequencies")) + { + JsonArray array = parameters["frequencies"].Array(); + std::vector frequencyList; + JsonArray::Iterator index(array.Elements()); - if (parameters.HasLabel("ssids")) + while (index.Next() == true) + { + if (Core::JSON::Variant::type::STRING == index.Current().Content()) + { + frequencyList.push_back(index.Current().String()); + } + else + { + NMLOG_ERROR("Unexpected variant type in frequency array."); + returnJson(rc); + } + } + frequencies = Core::Service::Create(frequencyList); + if (frequencies == nullptr) { + returnJson(rc); + } + } + + if (parameters.HasLabel("ssids")) { JsonArray array = parameters["ssids"].Array(); std::vector ssidslist; - JsonArray::Iterator index(array.Elements()); + JsonArray::Iterator index(array.Elements()); - while (index.Next() == true) + while (index.Next() == true) { if (Core::JSON::Variant::type::STRING == index.Current().Content()) { @@ -663,20 +684,27 @@ namespace WPEFramework else { NMLOG_ERROR("Unexpected variant type in SSID array."); + if (frequencies) + frequencies->Release(); returnJson(rc); } } ssids = (Core::Service::Create(ssidslist)); if(ssids == nullptr){ + if (frequencies) + frequencies->Release(); returnJson(rc); } } if (_networkManager) - rc = _networkManager->StartWiFiScan(frequency, ssids); + rc = _networkManager->StartWiFiScan(frequencies, ssids); else rc = Core::ERROR_UNAVAILABLE; + if (frequencies) + frequencies->Release(); + if (ssids) ssids->Release(); diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index b661a8de3..b2010fe94 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -986,32 +986,61 @@ namespace WPEFramework return rc; } - uint32_t NetworkManagerImplementation::StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) + uint32_t NetworkManagerImplementation::StartWiFiScan(IStringIterator* const frequencies /* @in */, IStringIterator* const ssids/* @in */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; //Cleared the Existing Store filterred SSID list m_filterSsidslist.clear(); - m_filterfrequency.clear(); + m_filterFrequencies.clear(); if(ssids) { string tmpssidlist{}; while (ssids->Next(tmpssidlist) == true) { - m_filterSsidslist.push_back(tmpssidlist.c_str()); - NMLOG_DEBUG("%s added to SSID filtering", tmpssidlist.c_str()); + if (!tmpssidlist.empty()) + { + m_filterSsidslist.push_back(tmpssidlist.c_str()); + NMLOG_DEBUG("%s added to SSID filtering", tmpssidlist.c_str()); + } + else + { + NMLOG_DEBUG("Empty SSID encountered in input list; skipping."); + } } } - if (!frequency.empty()) + if (frequencies) { - m_filterfrequency = frequency; - NMLOG_DEBUG("Scan SSIDs of frequency %s", m_filterfrequency.c_str()); + string frequency{}; + while (frequencies->Next(frequency) == true) + { + if (!frequency.empty()) + { + Core::JSON::EnumType parsedFrequency; + parsedFrequency.FromString(frequency); + const string normalizedFrequency = parsedFrequency.Data(); + if ((!normalizedFrequency.empty()) && (normalizedFrequency == frequency)) + { + m_filterFrequencies.push_back(normalizedFrequency); + NMLOG_DEBUG("Frequency %s added to scan filtering", normalizedFrequency.c_str()); + } + else + { + NMLOG_ERROR("Invalid frequency value: %s", frequency.c_str()); + return Core::ERROR_BAD_REQUEST; + } + } + else + { + NMLOG_DEBUG("Empty frequency encountered in input list; skipping."); + } + } } nmEvent->setwifiScanOptions(true); - if(wifi->wifiScanRequest(m_filterSsidslist.size() == 1 ? m_filterSsidslist[0] : "")) + if(wifi->wifiScanRequest(m_filterSsidslist)) rc = Core::ERROR_NONE; return rc; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 2348124d8..7fb4bb5df 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -755,7 +755,7 @@ namespace WPEFramework g_object_set(sWireless, NM_SETTING_WIRELESS_BSSID, ssidinfo.bssid.c_str(), NULL); } - if(ssidinfo.frequency != Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_NONE) + if(ssidinfo.frequency != Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_ALL) { if(ssidinfo.frequency == Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_2_4_GHZ) { @@ -1685,7 +1685,7 @@ namespace WPEFramework g_main_loop_quit(_wifiManager->m_loop); } - bool wifiManager::wifiScanRequest(std::string ssidReq) + bool wifiManager::wifiScanRequest(const std::vector& ssidsToFilter) { if(!createClientNewConnection()) return false; @@ -1696,23 +1696,25 @@ namespace WPEFramework return false; } m_isSuccess = false; - if(!ssidReq.empty()) + if(!ssidsToFilter.empty()) { - NMLOG_INFO("starting wifi scanning .. %s", ssidReq.c_str()); - GVariantBuilder builder, array_builder; + NMLOG_INFO("Starting wifi scanning for %d SSIDs:",static_cast(ssidsToFilter.size())); + GVariantBuilder nm_variant, nm_array_variant; GVariant *options; - g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_init(&array_builder, G_VARIANT_TYPE("aay")); - g_variant_builder_add(&array_builder, "@ay", - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (const guint8 *) ssidReq.c_str(), ssidReq.length(), 1) - ); - g_variant_builder_add(&builder, "{sv}", "ssids", g_variant_builder_end(&array_builder)); - options = g_variant_builder_end(&builder); + g_variant_builder_init(&nm_variant, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init(&nm_array_variant, G_VARIANT_TYPE("aay")); + for (const auto& ssid : ssidsToFilter) { + g_variant_builder_add(&nm_array_variant, "@ay", + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (const guint8 *) ssid.c_str(), ssid.length(), 1) + ); + } + g_variant_builder_add(&nm_variant, "{sv}", "ssids", g_variant_builder_end(&nm_array_variant)); + options = g_variant_builder_end(&nm_variant); nm_device_wifi_request_scan_options_async(wifiDevice, options, m_cancellable, wifiScanCb, this); g_variant_unref(options); // Unreference the GVariant after passing it to the async function } else { - NMLOG_INFO("staring normal wifi scanning .."); + NMLOG_INFO("Starting normal wifi scanning .."); nm_device_wifi_request_scan_async(wifiDevice, m_cancellable, wifiScanCb, this); } wait(m_loop); diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 51164aa50..4d0fa0861 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -31,6 +31,7 @@ #include #include #include +#include #define WPS_RETRY_WAIT_IN_MS 10 // 10 sec #define WPS_RETRY_COUNT 10 @@ -54,7 +55,7 @@ namespace WPEFramework bool activateKnownConnection(std::string iface, std::string knowConnectionID=""); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo &ssidInfo); - bool wifiScanRequest(std::string ssidReq = ""); + bool wifiScanRequest(const std::vector& ssidsToFilter = {}); bool isWifiScannedRecently(int timelimitInSec = 5); // default 5 sec as shotest scanning interval bool getKnownSSIDs(std::list& ssids); bool addToKnownSSIDs(const Exchange::INetworkManager::WiFiConnectTo &ssidinfo); diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp index 73aa49d93..3cbb977ec 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp @@ -216,7 +216,7 @@ namespace WPEFramework return rc; } - uint32_t NetworkManagerImplementation::StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) + uint32_t NetworkManagerImplementation::StartWiFiScan(IStringIterator* const frequencies /* @in */, IStringIterator* const ssids/* @in */) { uint32_t rc = Core::ERROR_GENERAL; _nmGdbusEvents->setwifiScanOptions(true); /* Enable event posting */ diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index f218d61c6..0bbde194c 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -965,7 +965,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { return rc; } - uint32_t NetworkManagerImplementation::StartWiFiScan(const string& frequency /* @in */, IStringIterator* const ssids/* @in */) + uint32_t NetworkManagerImplementation::StartWiFiScan(IStringIterator* const frequencies /* @in */, IStringIterator* const ssids/* @in */) { LOG_ENTRY_FUNCTION(); uint32_t rc = Core::ERROR_RPC_CALL_FAILED; @@ -974,8 +974,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { //Cleared the Existing Store filterred SSID list m_filterSsidslist.clear(); - m_filterfrequency.clear(); - + m_filterFrequencies.clear(); if(ssids) { string ssidlist{}; @@ -986,10 +985,14 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { } } - if (!frequency.empty()) + if (frequencies) { - m_filterfrequency = frequency; - NMLOG_DEBUG("Scan SSIDs of frequency %s", m_filterfrequency.c_str()); + string frequencyList{}; + while (frequencies->Next(frequencyList) == true) + { + m_filterFrequencies.push_back(frequencyList.c_str()); + NMLOG_DEBUG("%s added to Frequency filtering", frequencyList.c_str()); + } } memset(¶m, 0, sizeof(param)); diff --git a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp index d32f4615f..c0086a003 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp @@ -768,7 +768,7 @@ TEST_F(NetworkManagerWifiTest, StartWiFiScan_with_Frequency) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), _T("{\"frequency\":\"5\", \"ssids\":[\"Testssid_1\", \"Testssid_2\"]}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), _T("{\"frequencies\":[\"2.4\",\"5\"], \"ssids\":[\"Testssid_1\", \"Testssid_2\"]}"), response)); EXPECT_EQ(response, _T("{\"success\":false}")); g_object_unref(deviceDummy); diff --git a/tests/l2Test/rdk/l2_test_rdkproxy.cpp b/tests/l2Test/rdk/l2_test_rdkproxy.cpp index 5bcdc3d5a..0d13caceb 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxy.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxy.cpp @@ -661,7 +661,7 @@ TEST_F(NetworkManagerTest, StartWiFiScan_Success) )); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), - _T("{\"frequency\":\"2.4GHz\"}"), response)); + _T("{\"frequency\":[\"2.4\"]}"), response)); EXPECT_EQ(response, _T("{\"success\":true}")); } @@ -673,7 +673,7 @@ TEST_F(NetworkManagerTest, StartWiFiScan_Failed) .WillOnce(::testing::Return(IARM_RESULT_IPCCORE_FAIL)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StartWiFiScan"), - _T("{\"frequency\":\"2.4GHz\"}"), response)); + _T("{\"frequency\":[\"2.4\"]}"), response)); EXPECT_EQ(response, _T("{\"success\":false}")); } diff --git a/tests/mocks/INetworkManagerMock.h b/tests/mocks/INetworkManagerMock.h index 27a8b2875..d9a217191 100644 --- a/tests/mocks/INetworkManagerMock.h +++ b/tests/mocks/INetworkManagerMock.h @@ -36,7 +36,7 @@ class MockINetworkManager : public WPEFramework::Exchange::INetworkManager { MOCK_METHOD(uint32_t, GetPublicIP, (string& interface, string& ipversion, string& ipaddress), (override)); MOCK_METHOD(uint32_t, Ping, (const string ipversion, const string endpoint, const uint32_t count, const uint16_t timeout, const string guid, string& response), (override)); MOCK_METHOD(uint32_t, Trace, (const string ipversion, const string endpoint, const uint32_t nqueries, const string guid, string& response), (override)); - MOCK_METHOD(uint32_t, StartWiFiScan, (const string& frequency, IStringIterator* const ssids), (override)); + MOCK_METHOD(uint32_t, StartWiFiScan, (IStringIterator* const frequencies, IStringIterator* const ssids), (override)); MOCK_METHOD(uint32_t, StopWiFiScan, (), (override)); MOCK_METHOD(uint32_t, GetKnownSSIDs, (IStringIterator*& ssids), (override)); MOCK_METHOD(uint32_t, AddToKnownSSIDs, (const WiFiConnectTo& ssid), (override)); diff --git a/tools/plugincli/NetworkManagerLibnmTest.cpp b/tools/plugincli/NetworkManagerLibnmTest.cpp index 650a1ba10..3a358b565 100644 --- a/tools/plugincli/NetworkManagerLibnmTest.cpp +++ b/tools/plugincli/NetworkManagerLibnmTest.cpp @@ -220,7 +220,8 @@ int main() NMLOG_INFO("Sending WiFi scan request%s", ssid.empty() ? " (all SSIDs)" : (" for SSID: " + ssid).c_str()); - if (wifiMgr->wifiScanRequest(ssid)) { + bool scanRequestSent = ssid.empty() ? wifiMgr->wifiScanRequest() : wifiMgr->wifiScanRequest({ssid}); + if (scanRequestSent) { NMLOG_INFO("WiFi scan request sent successfully."); } else { NMLOG_ERROR("Failed to send WiFi scan request."); From d159c6c830ed9346c0f5703e7b0abc60674d9cd3 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Thu, 28 May 2026 23:04:08 +0530 Subject: [PATCH 238/271] RDKEMW-18247 : Panel is listing as a PLATCO device in Router client list in WiFi mode (#313) * RDKEMW-18247 Panel is listing as a PLATCO device in Router client list in WiFi mode Reason for change: Set the NetworkManager dhcp-hostname in the connection profile to use the default hostname instead of the device name. --- .github/workflows/libnm_proxy_L1_test.yml | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 +-- plugin/gnome/NetworkManagerGnomeProxy.cpp | 9 +++++- plugin/gnome/NetworkManagerGnomeUtils.cpp | 10 +++---- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 36 ++++++++++++++++------- 6 files changed, 43 insertions(+), 20 deletions(-) diff --git a/.github/workflows/libnm_proxy_L1_test.yml b/.github/workflows/libnm_proxy_L1_test.yml index 80d945d59..d947d643f 100644 --- a/.github/workflows/libnm_proxy_L1_test.yml +++ b/.github/workflows/libnm_proxy_L1_test.yml @@ -111,7 +111,7 @@ jobs: run: | sudo bash -c 'echo "ETHERNET_INTERFACE=eth0 WIFI_INTERFACE=wlan0 - DEVICE_NAME=rdk_test_device " > /etc/device.properties' + DEFAULT_HOSTNAME=rdk_test_device " > /etc/device.properties' - name: Generate IARM headers run: | diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 8ada9b760..70cf138d4 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -1351,7 +1351,7 @@ } }, "SetHostname": { - "summary": "To configure a custom DHCP hostname instead of the default (which is typically the device name).\n\nSetting host name will take effect upon reconnect; like, device reboot, wake-up from deepsleep, while connecting to new Wi-Fi connection, WiFi On/Off, or renewal of the DHCP lease.", + "summary": "To configure a custom DHCP hostname instead of the default (which is typically the default hostname).\n\nSetting host name will take effect upon reconnect; like, device reboot, wake-up from deepsleep, while connecting to new Wi-Fi connection, WiFi On/Off, or renewal of the DHCP lease.", "params": { "type": "object", "properties": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index bba3aa46f..a1aac7ccf 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -103,7 +103,7 @@ NetworkManager interface methods: | [GetWiFiSignalQuality](#method.GetWiFiSignalQuality) | Get WiFi signal quality of currently connected SSID | | [GetSupportedSecurityModes](#method.GetSupportedSecurityModes) | Returns the Wifi security modes that the device supports | | [GetWifiState](#method.GetWifiState) | Returns the current Wifi State | -| [SetHostname](#method.SetHostname) | To configure a custom DHCP hostname instead of the default (which is typically the device name) | +| [SetHostname](#method.SetHostname) | To configure a custom DHCP hostname instead of the default (which is typically the default hostname) | ## *SetLogLevel [method](#head.Methods)* @@ -1729,7 +1729,7 @@ This method takes no parameters. ## *SetHostname [method](#head.Methods)* -To configure a custom DHCP hostname instead of the default (which is typically the device name). +To configure a custom DHCP hostname instead of the default (which is typically the default hostname). Setting host name will take effect upon reconnect; like, device reboot, wake-up from deepsleep, while connecting to new Wi-Fi connection, WiFi On/Off, or renewal of the DHCP lease. diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index b2010fe94..81b57dd0d 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -150,7 +150,14 @@ namespace WPEFramework // read persistent hostname if exist if(!nmUtils::readPersistentHostname(hostname)) { - hostname = nmUtils::deviceHostname(); // default hostname as device name + hostname = nmUtils::deviceHostname(); // default hostname as default hostname + } + + // Validate hostname is non-empty regardless of source (persistent or default) + if(hostname.empty()) + { + NMLOG_WARNING("Hostname is empty. No modification will be made to NM connections."); + return false; } connections = nm_client_get_connections(client); diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index 7d97e5e83..fa2b28690 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -40,7 +40,7 @@ namespace WPEFramework { static std::string m_ethifname = "eth0"; static std::string m_wlanifname = "wlan0"; - static std::string m_deviceHostname = "rdk-device"; // Device name can be empty if not set in /etc/device.properties + static std::string m_deviceHostname = "rdk-device"; // default hostname can be empty if not set in /etc/device.properties const char* nmUtils::wlanIface() {return m_wlanifname.c_str();} const char* nmUtils::ethIface() {return m_ethifname.c_str();} @@ -261,14 +261,14 @@ namespace WPEFramework } } - if (line.find("DEVICE_NAME=") != std::string::npos) { + if (line.find("DEFAULT_HOSTNAME=") != std::string::npos) { deviceHostname = line.substr(line.find('=') + 1); deviceHostname.erase(deviceHostname.find_last_not_of("\r\n\t") + 1); deviceHostname.erase(0, deviceHostname.find_first_not_of("\r\n\t")); if(deviceHostname.empty()) { - NMLOG_WARNING("DEVICE_NAME is empty in /etc/device.properties"); - deviceHostname = ""; // set empty device name + NMLOG_WARNING("DEFAULT_HOSTNAME is empty in /etc/device.properties"); + deviceHostname = ""; // set empty default hostname } } } @@ -277,7 +277,7 @@ namespace WPEFramework m_wlanifname = wifiIfname; m_ethifname = ethIfname; m_deviceHostname = deviceHostname; - NMLOG_INFO("/etc/device.properties eth: %s, wlan: %s, device name: %s", m_ethifname.c_str(), m_wlanifname.c_str(), m_deviceHostname.c_str()); + NMLOG_INFO("/etc/device.properties eth: %s, wlan: %s, default hostname: %s", m_ethifname.c_str(), m_wlanifname.c_str(), m_deviceHostname.c_str()); return true; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 7fb4bb5df..4e52fc117 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -637,18 +637,27 @@ namespace WPEFramework NMLOG_DEBUG("No persistent hostname found, using device hostname"); } + if(hostname.empty()) + NMLOG_WARNING("dhcp hostname: "); + else + NMLOG_INFO("dhcp hostname: %s", hostname.c_str()); + // IPv4 settings with DHCP NMSettingIP4Config *sIpv4 = (NMSettingIP4Config *)nm_setting_ip4_config_new(); g_object_set(G_OBJECT(sIpv4), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - g_object_set(G_OBJECT(sIpv4), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); - g_object_set(G_OBJECT(sIpv4), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); + if(!hostname.empty()) { + g_object_set(G_OBJECT(sIpv4), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); + g_object_set(G_OBJECT(sIpv4), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); + } nm_connection_add_setting(connection, NM_SETTING(sIpv4)); // IPv6 settings with DHCP NMSettingIP6Config *sIpv6 = (NMSettingIP6Config *)nm_setting_ip6_config_new(); g_object_set(G_OBJECT(sIpv6), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); - g_object_set(G_OBJECT(sIpv6), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); - g_object_set(G_OBJECT(sIpv6), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); + if(!hostname.empty()) { + g_object_set(G_OBJECT(sIpv6), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); + g_object_set(G_OBJECT(sIpv6), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); + } nm_connection_add_setting(connection, NM_SETTING(sIpv6)); NMLOG_DEBUG("Created minimal ethernet connection with autoconnect=true"); @@ -894,23 +903,30 @@ namespace WPEFramework if(!nmUtils::readPersistentHostname(hostname)) { hostname = nmUtils::deviceHostname(); - NMLOG_DEBUG("no persistent hostname found taking device name as hostname !"); + NMLOG_DEBUG("No persistent hostname found, using device hostname"); } - NMLOG_INFO("dhcp hostname: %s", hostname.c_str()); + if(hostname.empty()) + NMLOG_WARNING("dhcp hostname: "); + else + NMLOG_INFO("dhcp hostname: %s", hostname.c_str()); /* Build up the 'IPv4' Setting */ NMSettingIP4Config *sIpv4Conf = (NMSettingIP4Config *) nm_setting_ip4_config_new(); g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); // autoconf = true - g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); - g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); // hostname send enabled + if(!hostname.empty()) { + g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); + g_object_set(G_OBJECT(sIpv4Conf), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); // hostname send enabled + } nm_connection_add_setting(m_connection, NM_SETTING(sIpv4Conf)); /* Build up the 'IPv6' Setting */ NMSettingIP6Config *sIpv6Conf = (NMSettingIP6Config *) nm_setting_ip6_config_new(); g_object_set(G_OBJECT(sIpv6Conf), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); // autoconf = true - g_object_set(G_OBJECT(sIpv6Conf), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); - g_object_set(G_OBJECT(sIpv6Conf), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); // hostname send enabled + if(!hostname.empty()) { + g_object_set(G_OBJECT(sIpv6Conf), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname.c_str(), NULL); + g_object_set(G_OBJECT(sIpv6Conf), NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, TRUE, NULL); // hostname send enabled + } nm_connection_add_setting(m_connection, NM_SETTING(sIpv6Conf)); return true; } From 4c292bba8eea23c9431d6e1325c88a93284e9f5f Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Thu, 28 May 2026 15:19:41 -0400 Subject: [PATCH 239/271] Release of 3.0.0 Release of 3.0.0 --- CHANGELOG.md | 5 +++++ CMakeLists.txt | 4 ++-- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07c248184..c1726e44d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [3.0.0] - 2026-05-28 +### Changed +- The device hostname header that used to retrive has changed as "DEFAULT_HOSTNAME" +- Updated the WiFiStartScan to scan for specific SSID and also updated to take array of freq band as input instead of single freq + ## [2.3.0] - 2026-05-21 ### Fixed - Fixed the issue which leads Enabling and Disabling of interfaces are taking longer diff --git a/CMakeLists.txt b/CMakeLists.txt index a04ad16b5..fbc2ec83f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,8 +36,8 @@ if (NOT WPEFramework_FOUND AND NOT Thunder_FOUND) endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") -set(VERSION_MAJOR 2) -set(VERSION_MINOR 3) +set(VERSION_MAJOR 3) +set(VERSION_MINOR 0) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 70cf138d4..5e95f9357 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "2.3.0" + "version": "3.0.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index a1aac7ccf..a15fc6a4d 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 2.3.0** +**Version: 3.0.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 2.3.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.0.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 3a6999d6c9185c8b805e76a7beac5762b6b84a9c Mon Sep 17 00:00:00 2001 From: Anand73-n Date: Thu, 4 Jun 2026 18:17:44 +0530 Subject: [PATCH 240/271] RDK-61440: Implementation of handling PowerMode Change in NM plugin (#308) * RDK-61440: Implementation of handling PowerMode Change in NM plugin Reason for change: Ctrl ntwrk state based on PowerMode transitions Test procedure: Change the PowerMode state and verify the behavior Risks: low Priority: P1 Signed-off-by: Anand N Co-authored-by: Karunakaran A --- .github/workflows/gdbus_proxy_L1_test.yml | 5 + .github/workflows/legacy_L1_L2_test.yml | 5 + .github/workflows/libnm_proxy_L1_test.yml | 10 +- .github/workflows/rdk_proxy_L1_L2_test.yml | 5 + CMakeLists.txt | 7 + plugin/CMakeLists.txt | 1 + plugin/NetworkManagerImplementation.cpp | 123 +++++++++ plugin/NetworkManagerImplementation.h | 15 + plugin/NetworkManagerPowerClient.cpp | 303 +++++++++++++++++++++ plugin/NetworkManagerPowerClient.h | 175 ++++++++++++ plugin/gnome/NetworkManagerGnomeProxy.cpp | 16 ++ plugin/gnome/NetworkManagerGnomeWIFI.cpp | 189 ++++++++++++- plugin/gnome/NetworkManagerGnomeWIFI.h | 13 +- plugin/rdk/NetworkManagerRDKProxy.cpp | 14 + tests/l2Test/libnm/CMakeLists.txt | 1 + tests/l2Test/rdk/CMakeLists.txt | 1 + tests/mocks/thunder/IPowerManager.h | 85 ++++++ 17 files changed, 958 insertions(+), 10 deletions(-) create mode 100644 plugin/NetworkManagerPowerClient.cpp create mode 100644 plugin/NetworkManagerPowerClient.h create mode 100644 tests/mocks/thunder/IPowerManager.h diff --git a/.github/workflows/gdbus_proxy_L1_test.yml b/.github/workflows/gdbus_proxy_L1_test.yml index 242ca6bda..16edc038e 100644 --- a/.github/workflows/gdbus_proxy_L1_test.yml +++ b/.github/workflows/gdbus_proxy_L1_test.yml @@ -107,6 +107,11 @@ jobs: && cmake --build build/ThunderInterfaces --target install -j8 + - name: Install IPowerManager header + run: | + IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) + cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IPowerManager.h "$IFACE_DIR/" + - name: Build networkmanager with Gnome GDBUS Proxy run: > cmake diff --git a/.github/workflows/legacy_L1_L2_test.yml b/.github/workflows/legacy_L1_L2_test.yml index b3645cce6..03538a0ae 100644 --- a/.github/workflows/legacy_L1_L2_test.yml +++ b/.github/workflows/legacy_L1_L2_test.yml @@ -110,6 +110,11 @@ jobs: && cmake --build build/ThunderInterfaces --target install -j8 + - name: Install IPowerManager header + run: | + IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) + cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IPowerManager.h "$IFACE_DIR/" + - name: Generate IARM headers run: | touch install/usr/lib/libIARMBus.so diff --git a/.github/workflows/libnm_proxy_L1_test.yml b/.github/workflows/libnm_proxy_L1_test.yml index d947d643f..e5f64deff 100644 --- a/.github/workflows/libnm_proxy_L1_test.yml +++ b/.github/workflows/libnm_proxy_L1_test.yml @@ -12,7 +12,8 @@ env: jobs: L1-tests: name: Build and run unit tests - runs-on: ubuntu-22.04 + # Note: Ubuntu 24.04 is required for libnm 1.46 which is needed for NetworkManagerPowerClient support + runs-on: ubuntu-24.04 steps: # Set up Thunder cache @@ -107,6 +108,11 @@ jobs: && cmake --build build/ThunderInterfaces --target install -j8 + - name: Install IPowerManager header + run: | + IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) + cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IPowerManager.h "$IFACE_DIR/" + - name: Generate dependency files run: | sudo bash -c 'echo "ETHERNET_INTERFACE=eth0 @@ -160,7 +166,7 @@ jobs: - name: Generate coverage run: | - lcov -c -o coverage.info -d build/networkmanager_libnm/ + lcov --rc geninfo_unexecuted_blocks=1 -c -o coverage.info -d build/networkmanager_libnm/ --ignore-errors mismatch lcov -e coverage.info '*/networkmanager/plugin/gnome/*' -o filtered_coverage.info - name: Generate the html report diff --git a/.github/workflows/rdk_proxy_L1_L2_test.yml b/.github/workflows/rdk_proxy_L1_L2_test.yml index 4fb464fe0..fc89bc38e 100644 --- a/.github/workflows/rdk_proxy_L1_L2_test.yml +++ b/.github/workflows/rdk_proxy_L1_L2_test.yml @@ -107,6 +107,11 @@ jobs: && cmake --build build/ThunderInterfaces --target install -j8 + - name: Install IPowerManager header + run: | + IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) + cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IPowerManager.h "$IFACE_DIR/" + - name: Generate IARM headers run: | touch install/usr/lib/libIARMBus.so diff --git a/CMakeLists.txt b/CMakeLists.txt index fbc2ec83f..a5d13178b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,13 @@ option(ENABLE_LEGACY_PLUGINS "Enable Legacy Plugins" ON) option(USE_RDK_LOGGER "Enable RDK Logger for logging" OFF ) option(ENABLE_UNIT_TESTING "Enable unit tests" OFF) option(USE_TELEMETRY "Enable Telemetry T2 support" OFF) +option(ENABLE_ETHERNET_CONNECTION_HANDLING + "Enable pre-sleep Ethernet deactivation" OFF) + +if(ENABLE_ETHERNET_CONNECTION_HANDLING) + add_definitions(-DENABLE_ETHERNET_CONNECTION_HANDLING) + message(STATUS "Ethernet connection handling: enabled") +endif() if (USE_TELEMETRY) find_package(T2 REQUIRED) diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index a5b12d948..6090b8f15 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -81,6 +81,7 @@ add_library(${MODULE_IMPL_NAME} SHARED NetworkManagerConnectivity.cpp NetworkManagerStunClient.cpp NetworkManagerLogger.cpp + NetworkManagerPowerClient.cpp Module.cpp) if(ENABLE_GNOME_NETWORKMANAGER) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index c1fe15f8a..35d6a6f42 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -54,6 +54,8 @@ namespace WPEFramework m_wlanConnected.store(false); m_ethEnabled.store(false); m_wlanEnabled.store(false); + m_ethDisconnectedForSleep.store(false); + m_wlanDisconnectedForSleep.store(false); /* Set NetworkManager Out-Process name to be NWMgrPlugin */ Core::ProcessInfo().Name("NWMgrPlugin"); @@ -71,6 +73,7 @@ namespace WPEFramework NetworkManagerImplementation::~NetworkManagerImplementation() { NMLOG_INFO("NetworkManager Out-Of-Process Shutdown/Cleanup"); + m_powerClient.reset(); connectivityMonitor.stopConnectivityMonitor(); _instance = nullptr; platform_deinit(); @@ -199,6 +202,7 @@ namespace WPEFramework NetworkManagerImplementation::platform_init(); /* change gnome networkmanager or netsrvmgr logg level */ NetworkManagerImplementation::platform_logging(static_cast (config.loglevel.Value())); + m_powerClient.reset(new NetworkManagerPowerClient(*this)); return(Core::ERROR_NONE); } @@ -1197,5 +1201,124 @@ namespace WPEFramework } #endif } + + void NetworkManagerImplementation::OnPowerModePreChange( + const Exchange::IPowerManager::PowerState currentState, + const Exchange::IPowerManager::PowerState newState, + std::function sendAck) + { + // Called from NetworkManagerPowerClient's power thread. + NMLOG_DEBUG("OnPowerModePreChange: current=%d new=%d", + static_cast(currentState), static_cast(newState)); + + using PowerState = Exchange::IPowerManager::PowerState; + + if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) + { + if (m_wlanEnabled.load() && m_wlanConnected.load()) + { + NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — disconnecting WiFi"); + + uint32_t rcWifiDown = WiFiDisconnect(); + if (rcWifiDown == Core::ERROR_NONE) + { + m_wlanDisconnectedForSleep.store(true); + } + else + { + NMLOG_ERROR("OnPowerModePreChange: WiFiDisconnect failed (rc=%u), will not reconnect on wakeup", rcWifiDown); + } + } + else + { + NMLOG_DEBUG("OnPowerModePreChange: going to DeepSleep — WiFi not connected, skipping disconnect"); + } +#ifdef ENABLE_ETHERNET_CONNECTION_HANDLING + if (m_ethEnabled.load() && m_ethConnected.load()) + { + NMLOG_INFO("OnPowerModePreChange: going to DeepSleep — deactivating Ethernet"); + + uint32_t rcEthDown = EthernetDeactivate(); + if (rcEthDown == Core::ERROR_NONE) + { + m_ethDisconnectedForSleep.store(true); + } + else + { + NMLOG_ERROR("OnPowerModePreChange: EthernetDeactivate failed (rc=%u), will not activate on wakeup", rcEthDown); + } + } + else + { + NMLOG_DEBUG("OnPowerModePreChange: going to DeepSleep — Ethernet not activated, skipping deactivate"); + } +#endif + } + else if (currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) + { + if (m_wlanDisconnectedForSleep.load()) + { + if (!m_lastConnectedSSID.empty()) + { + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting to '%s'", + m_lastConnectedSSID.c_str()); + uint32_t rcWifiUp = ConnectToKnownSSID(m_lastConnectedSSID); + if (rcWifiUp == Core::ERROR_NONE) + { + m_wlanDisconnectedForSleep.store(false); + } + else + { + NMLOG_ERROR("OnPowerModePreChange: ConnectToKnownSSID failed (rc=%u)", rcWifiUp); + } + } + else + { + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — no last SSID, skipping reconnect"); + } + } + else + { + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — WiFi was not connected or was already down before sleep, skipping reconnect"); + } + } + sendAck(); + } + + void NetworkManagerImplementation::OnPowerModeChanged( + const Exchange::IPowerManager::PowerState currentState, + const Exchange::IPowerManager::PowerState newState) + { + NMLOG_INFO("OnPowerModeChanged: current=%d new=%d", + static_cast(currentState), static_cast(newState)); + if (currentState == Exchange::IPowerManager::PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { + + if (m_wlanEnabled.load() && m_wlanConnected.load()) + { + // Waking from DeepSleep with Network Standby ON: the AP may have + // changed channel while the device slept (802.11 CSA). Trigger an + // active scan so the driver discovers the AP on its new channel. + NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, triggering active WiFi scan"); + if (StartWiFiScan(nullptr, nullptr) != Core::ERROR_NONE) + { + NMLOG_ERROR("OnPowerModeChanged: StartWiFiScan failed"); + } + + NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, requesting DHCP lease on wlan0"); + if (ReacquireDHCPLease("wlan0") != Core::ERROR_NONE) + { + NMLOG_ERROR("OnPowerModeChanged: ReacquireDHCPLease(wlan0) failed"); + } + } + if (m_ethEnabled.load() && m_ethConnected.load()) + { + NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, requesting DHCP lease on eth0"); + if (ReacquireDHCPLease("eth0") != Core::ERROR_NONE) + { + NMLOG_ERROR("OnPowerModeChanged: ReacquireDHCPLease(eth0) failed"); + } + } + } + } } } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index a1563787e..bff75ba71 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -27,6 +27,7 @@ #include #include #include +#include using namespace std; @@ -34,6 +35,7 @@ using namespace std; #include "NetworkManagerLogger.h" #include "NetworkManagerConnectivity.h" #include "NetworkManagerStunClient.h" +#include "NetworkManagerPowerClient.h" /* Forward declarations to avoid pulling GLib/libnm headers into this header */ typedef struct _NMClient NMClient; @@ -63,6 +65,7 @@ namespace WPEFramework namespace Plugin { class NetworkManagerImplementation : public Exchange::INetworkManager + , public INetworkPowerCallback { enum NetworkEvents { @@ -226,6 +229,8 @@ namespace WPEFramework uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) override; uint32_t WiFiDisconnect(void) override; + uint32_t EthernetDeactivate(void); + uint32_t ReacquireDHCPLease(const string& iface); uint32_t GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) override; uint32_t StartWPS(const WiFiWPS& method /* @in */, const string& wps_pin /* @in */) override; @@ -277,6 +282,13 @@ namespace WPEFramework void ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality); void logTelemetry(const std::string& eventName, const std::string& message); + // INetworkPowerCallback overrides + void OnPowerModePreChange(const Exchange::IPowerManager::PowerState currentState, + const Exchange::IPowerManager::PowerState newState, + std::function sendAck) override; + void OnPowerModeChanged(const Exchange::IPowerManager::PowerState currentState, + const Exchange::IPowerManager::PowerState newState) override; + private: void platform_init(void); void platform_deinit(void); @@ -314,6 +326,7 @@ namespace WPEFramework std::atomic m_stopThread{false}; std::mutex m_condVariableMutex; std::condition_variable m_condVariable; + std::unique_ptr m_powerClient; public: IPAddress m_ethIPv4Address; IPAddress m_wlanIPv4Address; @@ -323,6 +336,8 @@ namespace WPEFramework std::atomic m_wlanConnected; std::atomic m_ethEnabled; std::atomic m_wlanEnabled; + std::atomic m_ethDisconnectedForSleep; + std::atomic m_wlanDisconnectedForSleep; std::string m_lastConnectedSSID; NMClient *m_nmClient{nullptr}; /* proxy NMClient — bound to m_nmContext */ GMainContext *m_nmContext{nullptr}; /* isolated context, not the global default */ diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp new file mode 100644 index 000000000..3d6d2ed95 --- /dev/null +++ b/plugin/NetworkManagerPowerClient.cpp @@ -0,0 +1,303 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2026 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include "NetworkManagerPowerClient.h" +#include "NetworkManagerLogger.h" +#include + +using namespace WPEFramework; +using namespace WPEFramework::Exchange; +using namespace WPEFramework::Plugin; + +// --------------------------------------------------------------------------- +// NetworkManagerPowerClient +// --------------------------------------------------------------------------- + +NetworkManagerPowerClient::NetworkManagerPowerClient(INetworkPowerCallback& callback) + : mCallback(callback) + , mPreChangeNotification(*this) + , mChangedNotification(*this) +{ + NMLOG_INFO("connecting to PowerManager"); + if (auto r = Open(RPC::CommunicationTimeOut, Connector(), "org.rdk.PowerManager"); r == Core::ERROR_NONE) { + // Connected; Operational() will be called by the framework when the proxy is ready + } else { + NMLOG_ERROR("failed to open link to PowerManager (error %u)", r); + } +} + +NetworkManagerPowerClient::~NetworkManagerPowerClient() +{ + NMLOG_INFO("shutting down"); + // Stop the power-event thread first so any in-flight work completes + // before we release the COM-RPC proxy. + mStopThread = true; + mQueueCv.notify_one(); + if (mPowerThread.joinable()) { + mPowerThread.join(); + } + unregisterEvents(); + Close(Core::infinite); +} + +bool NetworkManagerPowerClient::IsValid() const +{ + LOG_ENTRY_FUNCTION(); + + return mPowerManager != nullptr; +} + +bool NetworkManagerPowerClient::getNetworkStandbyMode() const +{ + LOG_ENTRY_FUNCTION(); + + bool standbyMode = false; + if (IsValid()) { + if (auto r = mPowerManager->GetNetworkStandbyMode(standbyMode); r != Core::ERROR_NONE) { + NMLOG_ERROR("GetNetworkStandbyMode failed (%u)", r); + } + } + return standbyMode; +} + +void NetworkManagerPowerClient::sendPowerModePreChangeComplete(int transactionId) +{ + LOG_ENTRY_FUNCTION(); + + if (IsValid()) { + if (mClientId == 0) { + NMLOG_ERROR("sendPowerModePreChangeComplete called with invalid clientId=0, skipping"); + return; + } + NMLOG_DEBUG("sending PowerModePreChangeComplete for transactionId=%d, mClientId=%u", transactionId, mClientId); + mPowerManager->PowerModePreChangeComplete(mClientId, transactionId); + } +} + +void NetworkManagerPowerClient::sendDelayPowerModeChange(int transactionId, int seconds) +{ + LOG_ENTRY_FUNCTION(); + + if (IsValid()) { + if (mClientId == 0) { + NMLOG_ERROR("sendDelayPowerModeChange called with invalid clientId=0, skipping"); + return; + } + if (auto r = mPowerManager->DelayPowerModeChangeBy(mClientId, transactionId, seconds); r != Core::ERROR_NONE) { + NMLOG_ERROR("DelayPowerModeChangeBy failed (%u)", r); + } + } +} + +void NetworkManagerPowerClient::Operational(bool upAndRunning) +{ + NMLOG_DEBUG("Operational(%s)", upAndRunning ? "true" : "false"); + if (upAndRunning) { + if (!IsValid()) { + mPowerManager = Interface(); + registerEvents(); + // Start the dedicated power-event thread after registration so it + // is ready to handle events as soon as they can arrive. + mStopThread = false; + mPowerThread = std::thread(&NetworkManagerPowerClient::powerThreadLoop, this); + } + } else { + // Stop the power-event thread before unregistering so any in-flight + // event that was already enqueued is drained. + mStopThread = true; + mQueueCv.notify_one(); + if (mPowerThread.joinable()) { + mPowerThread.join(); + } + unregisterEvents(); + } +} + +void NetworkManagerPowerClient::registerEvents() +{ + NMLOG_DEBUG("registering events"); + if (!IsValid()) { + NMLOG_ERROR("not in valid state, skipping event registration"); + return; + } + if (auto r = mPowerManager->AddPowerModePreChangeClient("org.rdk.NetworkManager", mClientId); r != Core::ERROR_NONE) { + NMLOG_ERROR("AddPowerModePreChangeClient failed (%u) — skipping pre-change sink", r); + // mClientId stays 0; do NOT register mPreChangeNotification + } else { + NMLOG_INFO("registered as pre-change client, mClientId=%u", mClientId); + if (auto r2 = mPowerManager->Register(&mPreChangeNotification); r2 != Core::ERROR_NONE) { + NMLOG_ERROR("register(preChange) failed (%u)", r2); + } + } + if (auto r = mPowerManager->Register(&mChangedNotification); r != Core::ERROR_NONE) { + NMLOG_ERROR("register(changed) failed (%u)", r); + } +} + +void NetworkManagerPowerClient::unregisterEvents() +{ + NMLOG_DEBUG("unregistering events"); + if (!IsValid()) { + NMLOG_ERROR("not in valid state, skipping event unregistration"); + return; + } + // NOTE: RemovePowerModePreChangeClient MUST be called before Unregister + if (mClientId != 0) { + if (auto r = mPowerManager->RemovePowerModePreChangeClient(mClientId); r != Core::ERROR_NONE) { + NMLOG_ERROR("removePowerModePreChangeClient failed (%u)", r); + } + if (auto r = mPowerManager->Unregister(&mPreChangeNotification); r != Core::ERROR_NONE) { + NMLOG_ERROR("unregister(preChange) failed (%u)", r); + } + mClientId = 0; + } + if (auto r = mPowerManager->Unregister(&mChangedNotification); r != Core::ERROR_NONE) { + NMLOG_ERROR("unregister(changed) failed (%u)", r); + } + + mPowerManager->Release(); + mPowerManager = nullptr; +} + +// --------------------------------------------------------------------------- +// Power event thread +// --------------------------------------------------------------------------- + +void NetworkManagerPowerClient::powerThreadLoop() +{ + NMLOG_DEBUG("power event thread started"); + while (true) { + PowerEvent event{}; + { + std::unique_lock lock(mQueueMutex); + mQueueCv.wait(lock, [this]{ return !mEventQueue.empty() || mStopThread.load(); }); + + if (mStopThread) { + // Drain remaining events with fast acks before exiting so + // PowerManager is never left waiting on a stale transaction. + // CHANGED events have no ack protocol — skip them. + std::vector pending; + while (!mEventQueue.empty()) { + pending.push_back(mEventQueue.front()); + mEventQueue.pop(); + } + lock.unlock(); + for (const auto& e : pending) { + if (e.type == PowerEvent::EventType::PRE_CHANGE) { + sendPowerModePreChangeComplete(e.transactionId); + } + } + break; + } + + event = mEventQueue.front(); + mEventQueue.pop(); + } + // Lock released — process event on this thread (blocking is fine here) + + const bool toDeepSleep = (event.newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP); + const bool fromDeepSleep = (event.currentState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP); + + if (event.type == PowerEvent::EventType::CHANGED) { + // Wakeup notification — no ack required. + if (fromDeepSleep && event.standbyMode) { + NMLOG_INFO("power thread — wakeup from DeepSleep standby ON"); + mCallback.OnPowerModeChanged(event.currentState, event.newState); + } else { + NMLOG_DEBUG("power thread — CHANGED event, no action (fromDeepSleep=%d networkStandbyMode=%d)", + fromDeepSleep, event.standbyMode); + } + continue; + } + + // PRE_CHANGE event processing below + auto sendAck = [transactionId = event.transactionId, this]() { + sendPowerModePreChangeComplete(transactionId); + }; + + if ((toDeepSleep || fromDeepSleep) && !event.standbyMode) { + // Deep-sleep transition with Network Standby OFF: delegate to + // NetworkManagerImplementation (WiFiDisconnect / reconnect) which + // will call sendAck() when done. + NMLOG_INFO("power thread — %s DeepSleep standby OFF", + toDeepSleep ? "to" : "from"); + mCallback.OnPowerModePreChange(event.currentState, event.newState, sendAck); + } else { + // standby ON or non-DeepSleep: no WiFi action needed, ack immediately. + NMLOG_DEBUG("power thread ack (standbyMode=%d toDeepSleep=%d fromDeepSleep=%d)", + event.standbyMode, toDeepSleep, fromDeepSleep); + sendAck(); + } + } + NMLOG_INFO("power event thread stopped"); +} + +// --------------------------------------------------------------------------- +// PreChangeNotification +// --------------------------------------------------------------------------- + +void NetworkManagerPowerClient::PreChangeNotification::OnPowerModePreChange( + const PowerState currentState, const PowerState newState, + const int transactionId, const int stateChangeAfter) +{ + NMLOG_DEBUG("OnPowerModePreChange current=%d new=%d txId=%d after=%ds", + static_cast(currentState), static_cast(newState), transactionId, stateChangeAfter); + + // Query standby mode + const bool standbyMode = mClient.getNetworkStandbyMode(); + + // Cache for use by ChangedNotification + mClient.mLastChangeStandbyMode = standbyMode; + + // Reserve a delay window now (before returning) so PowerManager knows to + // wait at least 5 s. + if (newState == PowerState::POWER_STATE_STANDBY_DEEP_SLEEP && !standbyMode) { + mClient.sendDelayPowerModeChange(transactionId, 5); + } + + // Enqueue and return immediately so the COM-RPC dispatcher thread is freed. + { + std::lock_guard lock(mClient.mQueueMutex); + mClient.mEventQueue.push(PowerEvent{PowerEvent::EventType::PRE_CHANGE, + currentState, newState, standbyMode, transactionId}); + } + mClient.mQueueCv.notify_one(); +} + +// --------------------------------------------------------------------------- +// ChangedNotification +// --------------------------------------------------------------------------- + +void NetworkManagerPowerClient::ChangedNotification::OnPowerModeChanged( + const PowerState currentState, const PowerState newState) +{ + NMLOG_DEBUG("OnPowerModeChanged current=%d new=%d", + static_cast(currentState), static_cast(newState)); + + // Use the cached standby mode + const bool standbyMode = mClient.mLastChangeStandbyMode; + + // Enqueue and return immediately so the COM-RPC dispatcher thread is freed. + { + std::lock_guard lock(mClient.mQueueMutex); + mClient.mEventQueue.push(PowerEvent{PowerEvent::EventType::CHANGED, + currentState, newState, standbyMode, 0}); + } + mClient.mQueueCv.notify_one(); +} diff --git a/plugin/NetworkManagerPowerClient.h b/plugin/NetworkManagerPowerClient.h new file mode 100644 index 000000000..73949e0eb --- /dev/null +++ b/plugin/NetworkManagerPowerClient.h @@ -0,0 +1,175 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2026 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +#include "Module.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace WPEFramework { +namespace Plugin { + +/** + * Callback interface that decouples NetworkManagerPowerClient from + * NetworkManagerImplementation. The implementation receives power state + * transitions and must call sendAck() exactly once per OnPowerModePreChange. + */ +struct INetworkPowerCallback { + virtual ~INetworkPowerCallback() = default; + + /** + * Called when a power mode pre-change event arrives that involves + * POWER_STATE_STANDBY_DEEP_SLEEP (either as the new state or the current + * state). The implementation MUST call sendAck() exactly once. + */ + virtual void OnPowerModePreChange(const Exchange::IPowerManager::PowerState currentState, + const Exchange::IPowerManager::PowerState newState, + std::function sendAck) = 0; + + /** + * Called when a power mode changed event arrives (informational only; + * no ack required). + */ + virtual void OnPowerModeChanged(const Exchange::IPowerManager::PowerState currentState, + const Exchange::IPowerManager::PowerState newState) = 0; +}; + +/** + * - Inherits SmartInterfaceType for automatic + * reconnect / Operational() lifecycle callbacks. + * - Registers as an AddPowerModePreChangeClient so it participates + * in the pre-change ack protocol. + * - Delegates DeepSleep transitions to INetworkPowerCallback. + * - Sends a fast-path PowerModePreChangeComplete for all other transitions. + * + * Lifecycle: + * Construction → Open() connects to PowerManager (async). + * Operational(true) → registers events; IsValid() returns true. + * Operational(false) → unregisters events and releases proxy. + * Destruction → unregisterEvents() then Close() . + */ +class NetworkManagerPowerClient : protected RPC::SmartInterfaceType { +public: + using PowerState = Exchange::IPowerManager::PowerState; + + explicit NetworkManagerPowerClient(INetworkPowerCallback& callback); + ~NetworkManagerPowerClient() override; + + NetworkManagerPowerClient(const NetworkManagerPowerClient&) = delete; + NetworkManagerPowerClient& operator=(const NetworkManagerPowerClient&) = delete; + + /** Returns true when the PowerManager COMRPC proxy is available. */ + bool IsValid() const; + + /** Queries the current Network Standby mode from PowerManager. */ + bool getNetworkStandbyMode() const; + + /** Sends PowerModePreChangeComplete to PowerManager. */ + void sendPowerModePreChangeComplete(int transactionId); + + /** Requests a delay window extension via DelayPowerModeChangeBy. */ + void sendDelayPowerModeChange(int transactionId, int seconds); + +private: + // ----------------------------------------------------------------------- + // IModePreChangeNotification sink + // ----------------------------------------------------------------------- + class PreChangeNotification : public Exchange::IPowerManager::IModePreChangeNotification { + public: + explicit PreChangeNotification(NetworkManagerPowerClient& client) + : mClient(client) {} + + void OnPowerModePreChange(const PowerState currentState, const PowerState newState, + const int transactionId, const int stateChangeAfter) override; + + BEGIN_INTERFACE_MAP(PreChangeNotification) + INTERFACE_ENTRY(Exchange::IPowerManager::IModePreChangeNotification) + END_INTERFACE_MAP + + private: + NetworkManagerPowerClient& mClient; + }; + + // ----------------------------------------------------------------------- + // IModeChangedNotification sink + // ----------------------------------------------------------------------- + class ChangedNotification : public Exchange::IPowerManager::IModeChangedNotification { + public: + explicit ChangedNotification(NetworkManagerPowerClient& client) : mClient(client) {} + + void OnPowerModeChanged(const PowerState currentState, const PowerState newState) override; + + BEGIN_INTERFACE_MAP(ChangedNotification) + INTERFACE_ENTRY(Exchange::IPowerManager::IModeChangedNotification) + END_INTERFACE_MAP + + private: + NetworkManagerPowerClient& mClient; + }; + + // ----------------------------------------------------------------------- + // SmartInterfaceType lifecycle callback + // ----------------------------------------------------------------------- + void Operational(bool upAndRunning) override; + + void registerEvents(); + void unregisterEvents(); + void powerThreadLoop(); + + + // ----------------------------------------------------------------------- + // Members + // ----------------------------------------------------------------------- + INetworkPowerCallback& mCallback; + Exchange::IPowerManager* mPowerManager{nullptr}; + Core::Sink mPreChangeNotification; + Core::Sink mChangedNotification; + uint32_t mClientId{0}; + + // Power-event thread: receives events enqueued by the COM-RPC dispatcher + // thread and processes them (WiFiDisconnect etc.) without blocking the + // dispatcher. + struct PowerEvent { + enum class EventType { PRE_CHANGE, CHANGED }; + + EventType type; + PowerState currentState; + PowerState newState; + bool standbyMode; + int transactionId; + }; + + std::thread mPowerThread; + std::queue mEventQueue; + std::mutex mQueueMutex; + std::condition_variable mQueueCv; + std::atomic mStopThread{false}; + // Cached standby mode from the last PRE_CHANGE event. + std::atomic mLastChangeStandbyMode{false}; +}; + +} // namespace Plugin +} // namespace WPEFramework diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 81b57dd0d..81d1e9332 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -1154,6 +1154,22 @@ namespace WPEFramework return rc; } + uint32_t NetworkManagerImplementation::EthernetDeactivate(void) + { + uint32_t rc = Core::ERROR_GENERAL; + if(wifi->ethernetDeactivate()) + rc = Core::ERROR_NONE; + return rc; + } + + uint32_t NetworkManagerImplementation::ReacquireDHCPLease(const string& iface) + { + uint32_t rc = Core::ERROR_GENERAL; + if(wifi->reacquireDhcpLease(iface)) + rc = Core::ERROR_NONE; + return rc; + } + uint32_t NetworkManagerImplementation::GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 4e52fc117..58872d481 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -45,7 +45,11 @@ namespace WPEFramework wifiManager::wifiManager() : m_client(nullptr), m_loop(nullptr), m_createNewConnection(false), m_objectPath(nullptr), m_wifidevice(nullptr), m_source(nullptr), m_cancellable(nullptr){ NMLOG_INFO("wifiManager"); m_nmContext = g_main_context_new(); - g_main_context_push_thread_default(m_nmContext); + // g_main_context_push_thread_default(m_nmContext); + // Do NOT push m_nmContext here. Pushing here permanently locks ownership + // to the constructor thread (owner_count stays at 1, never released). + // All callers — must push/pop around + // each createClientNewConnection()/deleteClientConnection() pair instead. m_loop = g_main_loop_new(m_nmContext, FALSE); } @@ -53,12 +57,21 @@ namespace WPEFramework { GError *error = NULL; + // Serialize concurrent wifi operations from different threads + m_opMutex.lock(); + + g_main_context_push_thread_default(m_nmContext); + m_client = nm_client_new(NULL, &error); if (!m_client || !m_loop) { if (error) { NMLOG_ERROR("Could not connect to NetworkManager: %s.", error->message); g_error_free(error); } + g_clear_object(&m_client); + m_client = nullptr; + g_main_context_pop_thread_default(m_nmContext); + m_opMutex.unlock(); return false; } @@ -79,7 +92,7 @@ namespace WPEFramework NMLOG_DEBUG("Cancelling pending async operations"); g_cancellable_cancel(m_cancellable); g_clear_object(&m_cancellable); - m_cancellable = NULL; + m_cancellable = nullptr; } } @@ -93,15 +106,21 @@ namespace WPEFramework g_main_context_iteration(context, TRUE); } g_main_context_unref(context); - m_client = NULL; + m_client = nullptr; } if(m_objectPath) { NMLOG_DEBUG("Freeing object path"); g_free(m_objectPath); - m_objectPath = NULL; + m_objectPath = nullptr; } + + // Pop the context pushed in createClientNewConnection() + if (m_nmContext) + g_main_context_pop_thread_default(m_nmContext); + // Release operation lock acquired in createClientNewConnection() + m_opMutex.unlock(); } bool wifiManager::quit(NMDevice *wifiNMDevice) @@ -407,6 +426,168 @@ namespace WPEFramework return m_isSuccess; } + static void ethernetDeactivateCb(GObject *object, GAsyncResult *result, gpointer user_data) + { + NMClient *client = NM_CLIENT(object); + GError *error = NULL; + wifiManager *_wifiManager = static_cast(user_data); + + NMLOG_DEBUG("ethernet connection deactivating..."); + _wifiManager->m_isSuccess = true; + if (!nm_client_deactivate_connection_finish(client, result, &error)) + { + NMLOG_ERROR("ethernet connection deactivate failed !"); + if(error != NULL) + { + if(g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + { + NMLOG_DEBUG("Deactivate operation was cancelled"); + } + else + { + NMLOG_ERROR("Deactivate error: %s", error->message); + } + g_error_free(error); + } + _wifiManager->m_isSuccess = false; + } + _wifiManager->quit(NULL); + } + + bool wifiManager::ethernetDeactivate() + { + NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; + if(!createClientNewConnection()) + return false; + + NMDevice *ethDevice = nm_client_get_device_by_iface(m_client, nmUtils::ethIface()); + if(ethDevice == NULL) { + NMLOG_WARNING("ethernet device not found !"); + deleteClientConnection(); + return false; + } + + deviceState = nm_device_get_state(ethDevice); + NMLOG_DEBUG("ethernet device current state is %d !", deviceState); + if (deviceState <= NM_DEVICE_STATE_DISCONNECTED || deviceState == NM_DEVICE_STATE_FAILED || deviceState == NM_DEVICE_STATE_DEACTIVATING) + { + NMLOG_WARNING("ethernet already disconnected !"); + deleteClientConnection(); + return true; + } + + NMActiveConnection *activeConn = nm_device_get_active_connection(ethDevice); + if(activeConn == NULL) { + NMLOG_WARNING("ethernet has no active connection, nothing to deactivate !"); + deleteClientConnection(); + return true; + } + + nm_client_deactivate_connection_async(m_client, activeConn, m_cancellable, ethernetDeactivateCb, this); + wait(m_loop); + deleteClientConnection(); + return m_isSuccess; + } + + static void appliedConnCb(GObject *src, GAsyncResult *res, gpointer user_data) + { + wifiManager *_wifiManager = static_cast(user_data); + GError *error = NULL; + guint64 versionId = 0; + NMConnection *conn = nm_device_get_applied_connection_finish( + NM_DEVICE(src), res, &versionId, &error); + if (error) { + NMLOG_ERROR("reacquireDhcpLease: get_applied_connection failed: %s", error->message); + g_error_free(error); + _wifiManager->m_appliedConn = nullptr; + _wifiManager->m_isSuccess = false; + } else { + _wifiManager->m_appliedConn = conn; + _wifiManager->m_versionId = versionId; + _wifiManager->m_isSuccess = true; + } + if (_wifiManager->m_loop) + g_main_loop_quit(_wifiManager->m_loop); + } + + static void reappliedCb(GObject *src, GAsyncResult *res, gpointer user_data) + { + wifiManager *_wifiManager = static_cast(user_data); + GError *error = NULL; + nm_device_reapply_finish(NM_DEVICE(src), res, &error); + if (error) { + NMLOG_ERROR("reacquireDhcpLease: reapply failed: %s", error->message); + g_error_free(error); + _wifiManager->m_isSuccess = false; + } else { + _wifiManager->m_isSuccess = true; + } + if (_wifiManager->m_loop) + g_main_loop_quit(_wifiManager->m_loop); + NMLOG_DEBUG("reacquireDhcpLease: reapply completed for '%s'", nm_device_get_iface(NM_DEVICE(src))); + } + + bool wifiManager::reacquireDhcpLease(const std::string& iface) + { + /* No direct libnm API to trigger a DHCP renew, hence by toggling ipv4.auto-route-ext-gw on the + * APPLIED connection (not the stored profile) and calling reapply(). + */ + if(!createClientNewConnection()) + return false; + + NMDevice *device = nm_client_get_device_by_iface(m_client, iface.c_str()); + if (device == NULL) { + NMLOG_ERROR("reacquireDhcpLease: device '%s' not found", iface.c_str()); + deleteClientConnection(); + return false; + } + + /* Round 1: fetch what NM actually has applied in memory */ + m_isSuccess = false; + m_appliedConn = nullptr; + nm_device_get_applied_connection_async(device, 0, m_cancellable, appliedConnCb, this); + wait(m_loop); + + if (!m_isSuccess || m_appliedConn == nullptr) { + NMLOG_ERROR("reacquireDhcpLease: could not get applied connection for '%s'", iface.c_str()); + deleteClientConnection(); + return false; + } + + NMSettingIPConfig *s_ip4 = NM_SETTING_IP_CONFIG( + nm_connection_get_setting(m_appliedConn, NM_TYPE_SETTING_IP4_CONFIG)); + if (s_ip4 == NULL) { + NMLOG_ERROR("reacquireDhcpLease: no IPv4 settings on '%s'", iface.c_str()); + g_object_unref(m_appliedConn); + m_appliedConn = nullptr; + deleteClientConnection(); + return false; + } + + NMTernary currentVal = NM_TERNARY_DEFAULT; + g_object_get(s_ip4, NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, ¤tVal, NULL); + NMTernary newVal = (currentVal == NM_TERNARY_DEFAULT) ? NM_TERNARY_TRUE : NM_TERNARY_DEFAULT; + NMLOG_DEBUG("reacquireDhcpLease: '%s' auto-route-ext-gw %d -> %d (in-memory only)", + iface.c_str(), static_cast(currentVal), static_cast(newVal)); + g_object_set(s_ip4, NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, newVal, NULL); + + /* Round 2: reapply with version_id for race safety — no disk write */ + m_isSuccess = false; + nm_device_reapply_async(device, m_appliedConn, m_versionId, 0, m_cancellable, reappliedCb, this); + wait(m_loop); + + if (!m_isSuccess) { + NMLOG_ERROR("reacquireDhcpLease: reapply failed for '%s'", iface.c_str()); + } else { + NMLOG_INFO("reacquireDhcpLease: reapply successful on '%s'", iface.c_str()); + } + + g_object_unref(m_appliedConn); + m_appliedConn = nullptr; + deleteClientConnection(); + return m_isSuccess; + } + static NMAccessPoint* findMatchingSSID(const GPtrArray* ApList, Exchange::INetworkManager::WiFiConnectTo& ssidInfo) { NMAccessPoint *AccessPoint = nullptr; diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index 4d0fa0861..cfc741fb2 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -52,6 +52,8 @@ namespace WPEFramework bool getWifiState(Exchange::INetworkManager::WiFiState& state); bool wifiDisconnect(); + bool ethernetDeactivate(); + bool reacquireDhcpLease(const std::string& iface); bool activateKnownConnection(std::string iface, std::string knowConnectionID=""); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo &ssidInfo); @@ -76,14 +78,14 @@ namespace WPEFramework wifiManager(); ~wifiManager() { NMLOG_INFO("~wifiManager"); + if(m_client != NULL) { + deleteClientConnection(); // handles pop + } if (m_nmContext) { - g_main_context_pop_thread_default(m_nmContext); + // Do NOT pop here — deleteClientConnection already popped g_main_context_unref(m_nmContext); m_nmContext = NULL; } - if(m_client != NULL) { - deleteClientConnection(); - } if(m_loop != NULL) { g_main_loop_unref(m_loop); m_loop = NULL; @@ -107,7 +109,10 @@ namespace WPEFramework GSource *m_source; GCancellable *m_cancellable; std::mutex m_cancellableMutex; + std::mutex m_opMutex; // serializes concurrent wifi operations from different threads bool m_isSuccess = false; + NMConnection *m_appliedConn = nullptr; + guint64 m_versionId = 0; SecretAgent m_secretAgent; }; } // Plugin diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index 0bbde194c..b163ae3c0 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -1180,6 +1180,20 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { return rc; } + uint32_t NetworkManagerImplementation::EthernetDeactivate(void) + { + /* No-op on RDK platform */ + NMLOG_INFO("EthernetDeactivate: no-op on RDK platform"); + return Core::ERROR_UNAVAILABLE; + } + + uint32_t NetworkManagerImplementation::ReacquireDHCPLease(const string& iface) + { + /* No-op on RDK platform */ + NMLOG_INFO("ReacquireDHCPLease: no-op on RDK platform (iface=%s)", iface.c_str()); + return Core::ERROR_UNAVAILABLE; + } + uint32_t NetworkManagerImplementation::GetConnectedSSID(WiFiSSIDInfo& ssidInfo /* @out */) { LOG_ENTRY_FUNCTION(); diff --git a/tests/l2Test/libnm/CMakeLists.txt b/tests/l2Test/libnm/CMakeLists.txt index 092cc1d3c..9b1a44d03 100644 --- a/tests/l2Test/libnm/CMakeLists.txt +++ b/tests/l2Test/libnm/CMakeLists.txt @@ -39,6 +39,7 @@ add_executable(${NM_LIBNM_PROXY_L2_TEST} ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerImplementation.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerPowerClient.cpp ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeProxy.cpp ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeWIFI.cpp ${CMAKE_SOURCE_DIR}/plugin/gnome/NetworkManagerGnomeEvents.cpp diff --git a/tests/l2Test/rdk/CMakeLists.txt b/tests/l2Test/rdk/CMakeLists.txt index ed5d4faba..3a94c63d7 100644 --- a/tests/l2Test/rdk/CMakeLists.txt +++ b/tests/l2Test/rdk/CMakeLists.txt @@ -38,6 +38,7 @@ add_executable(${NM_RDK_PROXY_L2_TEST} ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerImplementation.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivity.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerStunClient.cpp + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerPowerClient.cpp ${CMAKE_SOURCE_DIR}/plugin/rdk/NetworkManagerRDKProxy.cpp ${PROXY_STUB_SOURCES} ) diff --git a/tests/mocks/thunder/IPowerManager.h b/tests/mocks/thunder/IPowerManager.h new file mode 100644 index 000000000..30c1d4d75 --- /dev/null +++ b/tests/mocks/thunder/IPowerManager.h @@ -0,0 +1,85 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2026 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +/** + * Minimal CI stub for IPowerManager — compatible with Thunder R4.4.3. + * + * This file is used only during CI builds (gdbus/libnm L1 proxy tests) where + * the full entservices-apis stack is not available. It defines exactly the + * surface consumed by NetworkManagerPowerClient and nothing more. + * + * DO NOT use this file outside of test/CI contexts. + */ + +#include + +namespace WPEFramework { +namespace Exchange { + + struct EXTERNAL IPowerManager : virtual public Core::IUnknown { + + // Stub ID — not used for COM lookup in L1 unit tests. + enum { ID = 0x8180 }; + + enum PowerState : uint8_t { + POWER_STATE_UNKNOWN = 0, + POWER_STATE_OFF = 1, + POWER_STATE_STANDBY = 2, + POWER_STATE_ON = 3, + POWER_STATE_STANDBY_LIGHT_SLEEP = 4, + POWER_STATE_STANDBY_DEEP_SLEEP = 5, + }; + + // @event + struct EXTERNAL IModePreChangeNotification : virtual public Core::IUnknown { + enum { ID = 0x8182 }; + virtual void OnPowerModePreChange(const PowerState currentState, + const PowerState newState, + const int transactionId, + const int stateChangeAfter) {} + }; + + // @event + struct EXTERNAL IModeChangedNotification : virtual public Core::IUnknown { + enum { ID = 0x8183 }; + virtual void OnPowerModeChanged(const PowerState currentState, + const PowerState newState) {} + }; + + virtual Core::hresult Register(IModePreChangeNotification* notification) {}; + virtual Core::hresult Unregister(const IModePreChangeNotification* notification) {}; + + virtual Core::hresult Register(IModeChangedNotification* notification) {}; + virtual Core::hresult Unregister(const IModeChangedNotification* notification) {}; + + virtual Core::hresult AddPowerModePreChangeClient(const string& clientName, + uint32_t& clientId) {}; + virtual Core::hresult RemovePowerModePreChangeClient(const uint32_t clientId) {}; + virtual Core::hresult PowerModePreChangeComplete(const uint32_t clientId, + const int transactionId) {}; + virtual Core::hresult DelayPowerModeChangeBy(const uint32_t clientId, + const int transactionId, + const int delayPeriod) {}; + virtual Core::hresult GetNetworkStandbyMode(bool& standbyMode) {}; + }; + +} // namespace Exchange +} // namespace WPEFramework From 8a6ff5098f495951229b6c0601fdcf9601c123c8 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Mon, 8 Jun 2026 14:35:27 -0400 Subject: [PATCH 241/271] Release of 3.1.0 Release of 3.1.0 --- CHANGELOG.md | 6 ++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1726e44d..0632cc531 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [3.1.0] - 2026-06-08 +### Changed +- Handled Power State changes within NetworkManager as below, +- Transition to DeepSleep will disconnect when NSM is OFF +- Transition from DeepSleep will Renew IP when NSM is ON + ## [3.0.0] - 2026-05-28 ### Changed - The device hostname header that used to retrive has changed as "DEFAULT_HOSTNAME" diff --git a/CMakeLists.txt b/CMakeLists.txt index a5d13178b..2e35057b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 3) -set(VERSION_MINOR 0) +set(VERSION_MINOR 1) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 5e95f9357..65e021f19 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "3.0.0" + "version": "3.1.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index a15fc6a4d..957f585df 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 3.0.0** +**Version: 3.1.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.0.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.1.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 8b5ec231a3231579afda5dfff3b8ab1286c821f6 Mon Sep 17 00:00:00 2001 From: tukken-comcast Date: Mon, 8 Jun 2026 21:56:44 +0530 Subject: [PATCH 242/271] RDK-61247: IP caching and refresh logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RDK-61247: IP caching and refresh logic (#310) * AI agent's initial code modifications as per approved plan * fix(gnome-events): address three IP cache gaps from initial implementation - Subscribe to notify::options on NMDhcpConfig in all three wiring sites (device-added, startup walk, ip4/ip6ConfigChangedCb) so dhcpserver stays current across mid-lease renewals; remove stale TODO comment - Replace IpFamilyCache::globalAddresses (std::set) + prefix (uint32_t) with std::map so toIPAddress() always projects ipaddress and prefix from the same entry - Remove dead GnomeNetworkManagerEvents::onAddressChangeCb() definition and declaration, superseded by the cache-diff path in refreshIpFamilyCache * fix: replace narrow fe80: string check with correct IPv6 fe80::/10 detection Extract isIPv6LinkLocal() helper into NetworkManagerImplementation.h and use it at all four call sites. Also remove now-unused #include . * fix: fix build errors after IpFamilyCache::globalAddresses type change Update cache insert calls in gnome and rdk proxy fallback paths to use the map API (insert({addr, prefix})) and remove the now-absent top-level c->prefix field assignments. * fix(ip-cache): read IP config from device instead of active connection refreshIpFamilyCache() was reading addresses from nm_active_connection_get_ip4/6_config(), which returns NULL on platforms like xione-uk where NetworkManager does not manage the IP configuration directly. The signal handlers (ip4ChangedCb, ip6ChangedCb) are connected to the device-level NMIPConfig objects, so the cache must also read from nm_device_get_ip4/6_config() to see the same addresses that triggered the notification. This mismatch caused the cache to remain empty and no IP_ACQUIRED events were ever emitted despite signals firing correctly. * fix(ip-cache): guard DNS array access to prevent out-of-bounds read nm_ip_config_get_nameservers() returns a NULL-terminated strv. In newer libnm versions this is guaranteed non-NULL even when empty (returns a pointer to {NULL}). The previous code accessed dnsArr[1] unconditionally after checking dnsArr non-NULL, which reads past the single-element allocation when there are zero DNS servers configured. On the xione-uk platform, the device-level IP config has addresses from the kernel but no DNS servers via NetworkManager, so the returned strv is empty. Reading dnsArr[1] past the allocation boundary causes SIGSEGV on this embedded platform. Fix: only access dnsArr[1] when dnsArr[0] is confirmed non-NULL. Also use the correct const type to avoid the C-style cast. * fix(ip-cache): emit IP_LOST events on interface disconnect Three changes fix the missing IP_LOST events when disconnecting: 1. Call refreshIpFamilyCache in deviceStateChangeCb before reporting INTERFACE_LINK_DOWN or INTERFACE_REMOVED. When NM disconnects a device, it batches State and Ip4Config/Ip6Config property changes into a single D-Bus PropertiesChanged signal. libnm updates all properties atomically then emits notify signals in arbitrary order. If notify::state fires before notify::ip4-config, the cache was being cleared (by ReportInterfaceStateChange) before refreshIpFamilyCache could diff against it. By explicitly calling refreshIpFamilyCache from the state callback, the diff runs while the cache still has the old addresses, producing IP_LOST events through the canonical path with proper logging. 2. ReportInterfaceStateChange now emits IP_LOST for every cached address before clearing the cache. This is a safety net: if refreshIpFamilyCache already handled the transition (because notify::ip4-config fired first), the cache will be empty and this emits nothing. If it didn't, this catches any remaining addresses. 3. Move the nm_device_get_ip4/6_config() read outside the if(conn) gate in refreshIpFamilyCache. The device-level IP config does not require an active connection, so the cache can detect address presence or absence during teardown when the active connection is already gone. * fix(ip-cache): emit IP_LOST events reliably on interface disconnect - refreshIpFamilyCache now checks device state: when devState <= NM_DEVICE_STATE_DISCONNECTED, it skips the libnm read so newCache is empty and the diff emits IP_LOST for all cached addresses. This eliminates the signal-ordering dead zone where addresses were still present in libnm but about to be cleared. - Remove IP_LOST emission from ReportInterfaceStateChange (was duplicating the cache-clear + emit logic). That function now only manages interface state (connected flags, default interface, connectivity monitor). - Move the authoritative 'IP acquired:'/'IP lost:' log line into ReportIPAddressChange, which is the single guaranteed call site for every IP event regardless of origin. - Remove the now-redundant 'IP acquired:'/'IP lost:' prints from refreshIpFamilyCache's diff section. Verified: disconnect produces exactly one IP_LOST per cached address, no spurious IP_ACQUIRED, and IP_LOST events precede LINK_DOWN. * refactor: replace named IpFamilyCache fields with map-based storage Replace four hardcoded cache fields (m_ethIPv4Cache, m_wlanIPv4Cache, m_ethIPv6Cache, m_wlanIPv6Cache) with a single std::map keyed by (interface, ipFamily) pair. Add getIpCache() convenience accessor. Change toIPAddress(bool isIPv6) to toIPAddress() with auto-detection via inet_pton, since the cache is already partitioned by IP family. This removes ~60 lines of repetitive if/else-if interface selection boilerplate across all backends (GnomeProxy, GdbusClient, RDKProxy) and eliminates hardcoded interface-name assumptions from the storage layer. * fix(ip-cache): populate IPAddress.ula with actual ULA, not link-local The IPAddress.ula field was incorrectly being populated with IPv6 link-local addresses (fe80::/10). ULA (Unique Local Address, fc00::/7) is a different address class — analogous to RFC 1918 private IPv4. Changes: - Add isIPv6ULA() helper using the same bitmask as NetworkManager's nm_ip6_addr_is_ula(): (s6_addr32[0] & 0xfe000000) == 0xfc000000 - Add ulaAddress field to IpFamilyCache, separate from linkLocalAddress - Map IpFamilyCache::ulaAddress to IPAddress::ula in toIPAddress() - Add three-way IPv6 classification (link-local / ULA / global) in GnomeEvents, GnomeProxy, GdbusClient, GdbusEvent, and RDK proxy - ULA addresses are NOT reported as global: they do not go into globalAddresses and do not trigger IP_ACQUIRED/IP_LOST events - Fix pre-existing gdbus bug: globalAddresses.insert() now uses the correct {address, prefix} pair instead of bare string - Fix NetworkManager.json example to use valid ULA (fd00::/8 prefix) - Fix docs example: IPv4 result should have empty ula field - Replace IN_IS_ADDR_LINKLOCAL macro with isIPv4LinkLocal() inline helper for consistency with the IPv6 helpers; remove now-unnecessary arpa/inet.h includes from GnomeProxy and GnomeEvents * feat(ip-cache): filter MAC-based EUI-64 global IPv6 from GetIPSettings Store interface HW address in IpFamilyCache.macAddress (populated from nm_device_get_hw_address). toIPAddress() iterates globalAddresses preferring non-MAC-based globals; falls back to MAC-based if all are EUI-64 derived. Direct-read (fallback) path in GnomeProxy also filters at selection time. Adds isIPv6MacBased() helper to detect EUI-64 addresses derived from the interface MAC. * refactor(GetIPSettings): remove fallback path, serve exclusively from event-driven cache The event thread seeds the IP cache synchronously during startup (via refreshIpFamilyCache) before entering g_main_loop_run(), so the cache is always populated before any RPC can arrive. The fallback path that read directly from the RPC thread's m_nmClient was effectively dead code. Remove the ~250-line fallback (m_nmClient reads, connection lookups, IPv4/IPv6 address iteration, and fallback cache writes). On cache miss, return Core::ERROR_GENERAL with a warning log. Also remove the now-unused isAutoConnectEnabled() helper and its 10 local variable declarations that only served the fallback. * refactor(ip-cache): split address containers and move helpers out of header - Split IpFamilyCache into three containers: globalAddresses (map, event-diffable), linkLocalAddresses (set), uniqueLocalAddresses (set) - Move isIPv4LinkLocal, isIPv6LinkLocal, isIPv6ULA, toIPAddress from inline header definitions to NetworkManagerImplementation.cpp - Add explicit constructors to GlobalAddressInfo for C++11 compatibility - Simplify event diffing in refreshIpFamilyCache to operate on globalAddresses keys directly without type filtering * fix: address PR review feedback on IP cache helpers and proxy - isIPv6ULA: replace non-portable s6_addr32 with s6_addr[0] byte check - isIPv6MacBased: rewrite with binary EUI-64 comparison via inet_pton and memcmp, fixing broken string matching from inet_ntop zero suppression - Add parseMac() helper accepting both colon-separated and bare hex MACs - Add #include and for memcmp/sscanf - cleanupSignalHandlers: explicitly disconnect DHCP option callbacks - Remove stale 'GetIPSettings fallback path' comment - GetIPSettings: return ERROR_NONE with empty result when cache has no entry for the requested interface+family, since absence of an address is not an error - GetIPSettings: reset result to IPAddress{} with correct ipversion before cache lookup, and preserve requested family after toIPAddress() - Remove onAddressChangeCb L2 test: the old callback was replaced by event-driven cache diffs in refreshIpFamilyCache(); the test had no assertions and exercised only dead compatibility code - deviceAddedCB: seed IP cache after attaching signal handlers so GetIPSettings returns data immediately for hotplugged devices - Encapsulate m_ipCacheMap/m_ipCacheMutex as private; expose lookupIpCache() and swapIpCache() locked accessors to prevent unsynchronised access from outside the class - lookupIpCache returns IPAddress directly (via toIPAddress() under the lock) instead of copying the entire IpFamilyCache by value - refreshIpFamilyCache: make this an internal helper function - deviceRemovedCB: disconnect all IP-config, DHCP, and device-level signal handlers symmetrically with deviceAddedCB, and clear the IP cache (emitting IP_LOST events) to prevent stale entries and handler accumulation on device removal/re-addition * fix(gnome): use device-level DHCP config API to fix empty dhcpserver in GetIPSettings The ActiveConnection's Dhcp4Config property is not populated until the connection reaches ACTIVATED state, but ip4ChangedCb fires earlier (when addresses appear on the IP config object). At that point, nm_active_connection_get_dhcp4_config() returns NULL, causing refreshIpFamilyCache() to store an empty dhcpserver in the cache. Switch to nm_device_get_dhcp4_config() / nm_device_get_dhcp6_config() which read from the Device object's Dhcp4Config property. This property is set when the device enters IP_CONFIG state and its options are populated before the IP address appears — ensuring dhcpserver is available when the cache is built. Apply the same fix to DHCP signal handler connections in ip4ConfigChangedCb, ip6ConfigChangedCb, deviceAddedCB, networkMangerEventMonitor, deviceRemovedCB, and cleanupSignalHandlers. * build(backends): gate legacy IP members and export backend macros * test(libnm): update L1 tests for cache-based GetIPSettings and refreshIpFamilyCache - Remove 5 GetIPSettings error-path tests that exercised libnm API call sequences no longer present in the cache-based implementation - Replace 5 GetIPSettings data tests with cache-based equivalents that populate IpFamilyCache via swapIpCache() and verify the JSON-RPC response - Fix 5 event tests (disconnected/unmanaged/unknown for wlan0 and eth0) by changing nm_device_get_iface and nm_device_get_state from WillOnce to WillRepeatedly to accommodate additional calls from refreshIpFamilyCache() - Fix platformInit test: GetIPSettings now returns success:true with empty data for valid interfaces when the cache is empty * tests: fix segfault in cache tests by using _instance global The Instantiate mock on COMLink was never invoked because RootConfig parses ConfigLine looking for 'root' at the top level, but the test's JSON nests it inside 'configuration'. This caused Root() to take the in-process path via ServiceAdministrator, bypassing COMLink entirely. As a result, the NetworkManagerImpl ProxyType member was never populated (null _realObject). The new cache tests that call NetworkManagerImpl->swapIpCache() dereferenced null, crashing at mutex offset 0x3d0. Fix by using the Plugin::_instance global pointer which is set during platform_init() in the in-process instantiation path. * tests: add 9 new GetIPSettings test scenarios for IP cache behavior Add test coverage for IP cache and address selection logic: - IPv6 MAC-based fallback when all globals are MAC-derived - IPv6 prefer non-MAC-based global address selection - IPv6 only-cached request for IPv4 returns empty - Cache invalidation returns success:true with empty fields - IP version case insensitivity (ipv4/IPV6/etc) - IPv6 ULA-only cache (no global -> address fields omitted) - swapIpCache returns old global address keys - Separate IPv4/IPv6 caches per interface - Cache clearing via invalid cache swap * tests: add utility function tests for IP address classification Add 14 tests for pure utility functions introduced with IP cache: - isIPv4LinkLocal: link-local (169.254/16), non-link-local, invalid input - isIPv6LinkLocal: link-local (fe80::/10), non-link-local, invalid input - isIPv6ULA: ULA (fc00::/7 including fc and fd), non-ULA, invalid input - isIPv6MacBased: EUI-64 match with colon and plain hex MAC formats, non-matching, privacy extension, and invalid inputs (also exercises parseMac indirectly) * tests: add disconnect cache-clearing event tests Add 3 behavioral tests verifying that device disconnect events clear the IP cache: - disconnect_clears_ipv4_cache_eth0 - disconnect_clears_ipv6_cache_wlan0 - disconnect_clears_both_ip_family_caches Tests use public APIs (swapIpCache, deviceStateChangeCb, GetIPSettings) and assert observable behavior rather than internal NM API call sequences. * fix: restore IP address cache clearing on disconnect for RDK/GDBUS backends The m_eth*Address and m_wlan*Address fields were no longer being cleared in ReportInterfaceStateChange on link-down/remove, causing stale IP settings to be returned by GetIPSettings in the RDK and GDBUS backends. Restore the clearing, guarded by preprocessor checks for NM_BACKEND_GDBUS and NM_BACKEND_RDK since these fields are not defined for the libnm backend. Also fix lookupIpCache to set out.ipversion from the requested ipFamily rather than relying on toIPAddress() inference, which could default to "IPv4" when the cache is valid but contains no addresses. This makes lookupIpCache self-consistent for any future callers. Reason for change: Updated the documentation Test Procedure: Verify docs/NetworkManagerPlugin.md reflects content in definition/NetworkManager.json Priority: P1 Risk: Low --- CMakeLists.txt | 8 + definition/NetworkManager.json | 4 +- docs/NetworkManagerPlugin.md | 4 +- plugin/NetworkManagerImplementation.cpp | 159 ++++- plugin/NetworkManagerImplementation.h | 53 ++ plugin/gnome/NetworkManagerGnomeEvents.cpp | 437 +++++++----- plugin/gnome/NetworkManagerGnomeEvents.h | 1 - plugin/gnome/NetworkManagerGnomeProxy.cpp | 301 +-------- tests/l2Test/libnm/l2_test_libnmproxy.cpp | 639 ++++++++++-------- .../l2Test/libnm/l2_test_libnmproxyEvent.cpp | 146 +++- tests/l2Test/libnm/l2_test_libnmproxyInit.cpp | 2 +- 11 files changed, 976 insertions(+), 778 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e35057b7..750e5657a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,14 @@ if(ENABLE_ETHERNET_CONNECTION_HANDLING) message(STATUS "Ethernet connection handling: enabled") endif() +# Backend identity macros are consumed by shared headers; define them globally +# so all targets (plugin, tests, tools) compile against the same API surface. +if(ENABLE_GNOME_NETWORKMANAGER AND ENABLE_GNOME_GDBUS) + add_compile_definitions(NM_BACKEND_GDBUS=1) +elseif(NOT ENABLE_GNOME_NETWORKMANAGER) + add_compile_definitions(NM_BACKEND_RDK=1) +endif() + if (USE_TELEMETRY) find_package(T2 REQUIRED) add_compile_definitions(USE_TELEMETRY=1) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 65e021f19..00471428f 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -47,9 +47,9 @@ "example": 24 }, "ula": { - "summary": "The IPv6 Unified Local Address", + "summary": "The IPv6 Unique Local Address", "type": "string", - "example": "d00:410:2016::" + "example": "fd00:410:2016::" }, "gateway": { "summary": "The gateway address", diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 957f585df..1b4a5d111 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -418,7 +418,7 @@ Gets the IP setting for the given interface. | result.ipaddress | string | The IP address | | result.prefix | integer | The prefix number | | result.gateway | string | The gateway address | -| result.ula | string | The IPv6 Unified Local Address | +| result.ula | string | The IPv6 Unique Local Address | | result.primarydns | string | The primary DNS address | | result.secondarydns | string | The secondary DNS address | | result.success | boolean | Whether the request succeeded | @@ -453,7 +453,7 @@ Gets the IP setting for the given interface. "ipaddress": "192.168.1.101", "prefix": 24, "gateway": "192.168.1.1", - "ula": "d00:410:2016::", + "ula": "fd00:410:2016::", "primarydns": "192.168.1.1", "secondarydns": "192.168.1.2", "success": true diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 35d6a6f42..b10b375b5 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -19,6 +19,9 @@ #include #include +#include +#include +#include #include "NetworkManagerImplementation.h" #if USE_TELEMETRY @@ -671,8 +674,10 @@ namespace WPEFramework { if(interface == "eth0") { +#if defined(NM_BACKEND_GDBUS) || defined(NM_BACKEND_RDK) m_ethIPv4Address = {}; m_ethIPv6Address = {}; +#endif m_ethConnected.store(false); setDefaultInterface("wlan0"); // If WiFi is connected, make it the default interface // As default interface is changed to wlan0, switch connectivity monitor to initial check @@ -680,8 +685,10 @@ namespace WPEFramework } else if(interface == "wlan0") { +#if defined(NM_BACKEND_GDBUS) || defined(NM_BACKEND_RDK) m_wlanIPv4Address = {}; m_wlanIPv6Address = {}; +#endif m_wlanConnected.store(false); bool triggerConnectivityCheck; if(m_ethConnected.load()) @@ -792,7 +799,9 @@ namespace WPEFramework } _notificationLock.Lock(); - NMLOG_INFO("Posting onIPAddressChange %s - %s", ipaddress.c_str(), interface.c_str()); + NMLOG_INFO("Posting onIPAddressChange %s: %s %s %s", + (Exchange::INetworkManager::IP_ACQUIRED == status) ? "IP acquired" : "IP lost", + interface.c_str(), ipversion.c_str(), ipaddress.c_str()); for (const auto callback : _notificationCallbacks) { callback->onIPAddressChange(interface, ipversion, ipaddress, status); } @@ -1320,5 +1329,153 @@ namespace WPEFramework } } } + + bool isIPv4LinkLocal(const std::string& addr) + { + struct in_addr sa{}; + return inet_pton(AF_INET, addr.c_str(), &sa) == 1 && + (ntohl(sa.s_addr) & 0xffff0000u) == 0xa9fe0000u; + } + + bool isIPv6LinkLocal(const std::string& addr) + { + struct in6_addr sa6{}; + return inet_pton(AF_INET6, addr.c_str(), &sa6) == 1 && + sa6.s6_addr[0] == 0xfe && (sa6.s6_addr[1] & 0xc0) == 0x80; + } + + bool isIPv6ULA(const std::string& addr) + { + struct in6_addr sa6{}; + return inet_pton(AF_INET6, addr.c_str(), &sa6) == 1 && + (sa6.s6_addr[0] & 0xfe) == 0xfc; + } + + /* Parse a MAC string into 6 bytes. Accepts both "AA:BB:CC:DD:EE:FF" and "aabbccddeeff". */ + static bool parseMac(const std::string& mac, uint8_t out[6]) + { + unsigned int b[6]; + if (mac.size() >= 17 && + sscanf(mac.c_str(), "%02x:%02x:%02x:%02x:%02x:%02x", + &b[0], &b[1], &b[2], &b[3], &b[4], &b[5]) == 6) + { + for (int i = 0; i < 6; ++i) out[i] = static_cast(b[i]); + return true; + } + if (mac.size() >= 12 && + sscanf(mac.c_str(), "%02x%02x%02x%02x%02x%02x", + &b[0], &b[1], &b[2], &b[3], &b[4], &b[5]) == 6) + { + for (int i = 0; i < 6; ++i) out[i] = static_cast(b[i]); + return true; + } + return false; + } + + bool isIPv6MacBased(const std::string& ipv6Addr, const std::string& macAddr) + { + struct in6_addr sa6{}; + uint8_t mac[6]; + if (inet_pton(AF_INET6, ipv6Addr.c_str(), &sa6) != 1 || !parseMac(macAddr, mac)) + return false; + + /* Build 8-byte EUI-64 identifier from 6-byte MAC: + mac[0..2] | ff:fe | mac[3..5], then flip the U/L bit (bit 1) of byte 0. */ + uint8_t eui64[8]; + eui64[0] = mac[0] ^ 0x02; // flip Universal/Local bit + eui64[1] = mac[1]; + eui64[2] = mac[2]; + eui64[3] = 0xff; + eui64[4] = 0xfe; + eui64[5] = mac[3]; + eui64[6] = mac[4]; + eui64[7] = mac[5]; + + /* Compare against the interface-ID (last 8 bytes) of the IPv6 address. */ + if (memcmp(&sa6.s6_addr[8], eui64, 8) == 0) + { + NMLOG_DEBUG("MAC %s based global v6 address %s", macAddr.c_str(), ipv6Addr.c_str()); + return true; + } + return false; + } + + bool NetworkManagerImplementation::lookupIpCache( + const std::string& iface, const std::string& ipFamily, + Exchange::INetworkManager::IPAddress& out) const + { + std::lock_guard lock(m_ipCacheMutex); + auto it = m_ipCacheMap.find({iface, ipFamily}); + if (it != m_ipCacheMap.end() && it->second.valid) { + out = it->second.toIPAddress(); + out.ipversion = ipFamily; + return true; + } + return false; + } + + std::set NetworkManagerImplementation::swapIpCache( + const std::string& iface, const std::string& ipFamily, + IpFamilyCache newCache) + { + std::set oldKeys; + std::lock_guard lock(m_ipCacheMutex); + IpFamilyCache& cache = m_ipCacheMap[{iface, ipFamily}]; + for (const auto& kv : cache.globalAddresses) + oldKeys.insert(kv.first); + cache = std::move(newCache); + return oldKeys; + } + + Exchange::INetworkManager::IPAddress IpFamilyCache::toIPAddress() const + { + Exchange::INetworkManager::IPAddress addr{}; + /* Detect IP version from any available address. */ + bool isIPv6 = false; + { + const std::string* sample = nullptr; + if (!globalAddresses.empty()) + sample = &globalAddresses.begin()->first; + else if (!uniqueLocalAddresses.empty()) + sample = &(*uniqueLocalAddresses.begin()); + else if (!linkLocalAddresses.empty()) + sample = &(*linkLocalAddresses.begin()); + if (sample) { + struct in6_addr sa6{}; + isIPv6 = (inet_pton(AF_INET6, sample->c_str(), &sa6) == 1); + } + } + addr.ipversion = isIPv6 ? "IPv6" : "IPv4"; + addr.autoconfig = autoconfig; + addr.dhcpserver = dhcpserver; + addr.ula = uniqueLocalAddresses.empty() ? "" : *uniqueLocalAddresses.begin(); + addr.gateway = gateway; + addr.primarydns = primarydns; + addr.secondarydns = secondarydns; + /* Prefer non-MAC-based global; fall back to MAC-based if all are MAC-based. */ + const std::string* bestGlobal = nullptr; + uint32_t bestPrefix = 0; + const std::string* fallbackMac = nullptr; + uint32_t fallbackMacPrefix = 0; + for (const auto& kv : globalAddresses) { + if (kv.second.type == ADDR_GLOBAL) { + bestGlobal = &kv.first; + bestPrefix = kv.second.prefix; + break; + } + if (!fallbackMac) { + fallbackMac = &kv.first; + fallbackMacPrefix = kv.second.prefix; + } + } + if (bestGlobal) { + addr.ipaddress = *bestGlobal; + addr.prefix = bestPrefix; + } else if (fallbackMac) { + addr.ipaddress = *fallbackMac; + addr.prefix = fallbackMacPrefix; + } + return addr; + } } } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index bff75ba71..6f4ab5bd1 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -26,8 +26,10 @@ #include #include #include +#include #include #include +#include using namespace std; @@ -64,6 +66,47 @@ namespace WPEFramework { namespace Plugin { + /* Returns true if the given string is an IPv4 link-local address (169.254.0.0/16). */ + bool isIPv4LinkLocal(const std::string& addr); + + /* Returns true if the given string is an IPv6 link-local address (fe80::/10). */ + bool isIPv6LinkLocal(const std::string& addr); + + /* Returns true if the given string is an IPv6 Unique Local Address (ULA, fc00::/7). */ + bool isIPv6ULA(const std::string& addr); + + /* Returns true if the given global IPv6 address is derived (EUI-64) from the MAC. */ + bool isIPv6MacBased(const std::string& ipv6Addr, const std::string& macAddr); + + /* Sub-classification of global-scope addresses in the IP cache. */ + enum GlobalAddressType : uint8_t { + ADDR_GLOBAL, // non-MAC-based global (preferred by GetIPSettings) + ADDR_GLOBAL_MAC_BASED, // EUI-64 global derived from interface MAC (fallback) + }; + + struct GlobalAddressInfo { + uint32_t prefix; + GlobalAddressType type; + GlobalAddressInfo() : prefix(0), type(ADDR_GLOBAL) {} + GlobalAddressInfo(uint32_t p, GlobalAddressType t) : prefix(p), type(t) {} + }; + + /* Per-interface, per-address-family cache populated by libnm events. */ + struct IpFamilyCache { + bool valid = false; + std::map globalAddresses; // event-diffable global addresses + std::set linkLocalAddresses; // fe80::/10 or 169.254.x.x — not diffed for events + std::set uniqueLocalAddresses; // fc00::/7 (IPv6 only) — not diffed for events + std::string gateway; + std::string primarydns; + std::string secondarydns; + std::string dhcpserver; + bool autoconfig = false; + + Exchange::INetworkManager::IPAddress toIPAddress() const; + void clear() { *this = IpFamilyCache{}; } + }; + class NetworkManagerImplementation : public Exchange::INetworkManager , public INetworkPowerCallback { @@ -328,10 +371,18 @@ namespace WPEFramework std::condition_variable m_condVariable; std::unique_ptr m_powerClient; public: +#if defined(NM_BACKEND_GDBUS) || defined(NM_BACKEND_RDK) IPAddress m_ethIPv4Address; IPAddress m_wlanIPv4Address; IPAddress m_ethIPv6Address; IPAddress m_wlanIPv6Address; +#endif + bool lookupIpCache(const std::string& iface, const std::string& ipFamily, + Exchange::INetworkManager::IPAddress& out) const; + std::set swapIpCache(const std::string& iface, + const std::string& ipFamily, + IpFamilyCache newCache); + std::atomic m_ethConnected; std::atomic m_wlanConnected; std::atomic m_ethEnabled; @@ -358,6 +409,8 @@ namespace WPEFramework private: string m_defaultInterface; mutable std::mutex m_defaultInterfaceMutex; + std::map, IpFamilyCache> m_ipCacheMap; + mutable std::mutex m_ipCacheMutex; }; } } diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 761c39fba..7a87cc200 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -30,6 +30,8 @@ #include "NetworkManagerGnomeUtils.h" #include "NetworkManagerImplementation.h" #include "INetworkManager.h" +#include + #ifdef ENABLE_MIGRATION_MFRMGR_SUPPORT #include "NetworkManagerGnomeMfrMgr.h" #endif @@ -74,6 +76,198 @@ namespace WPEFramework } } + /* Refresh the per-interface/per-family IP cache from current libnm state and + emit acquired/lost events for address-set differences. + + Build a fresh IpFamilyCache from current libnm state for one device/family, + swap it into _instance under the cache mutex, then emit acquired/lost events + for any address-set differences outside the lock. */ + static void refreshIpFamilyCache(NMDevice* device, bool isIPv6) + { + if (!device || !NM_IS_DEVICE(device) || !_instance) + return; + + const char* iface = nm_device_get_iface(device); + if (!iface) return; + std::string ifname = iface; + + bool isEth = (ifname == nmUtils::ethIface()); + bool isWlan = (ifname == nmUtils::wlanIface()); + if (!isEth && !isWlan) return; + + /* Build the new snapshot locally (no locks held during NM calls). + * Skip the NM read when the device is in a disconnected/down state + * so that newCache stays empty and the diff emits IP_LOST for every + * address still in the cache. This also prevents spurious + * "IP acquired" events from intermediate NM signals (nameserver, + * gateway clearing) that fire after the cache has been emptied + * but before NM clears addresses on the config object. */ + NMDeviceState devState = nm_device_get_state(device); + bool skipRead = (devState <= NM_DEVICE_STATE_DISCONNECTED); + IpFamilyCache newCache; + NMActiveConnection* conn = skipRead ? nullptr : nm_device_get_active_connection(device); + if (conn) { + /* autoconfig: method "auto" or "dhcp" → true */ + NMConnection* nmConn = NM_CONNECTION(nm_active_connection_get_connection(conn)); + if (nmConn) { + NMSettingIPConfig* ipSetting = isIPv6 + ? NM_SETTING_IP_CONFIG(nm_connection_get_setting_ip6_config(nmConn)) + : NM_SETTING_IP_CONFIG(nm_connection_get_setting_ip4_config(nmConn)); + if (ipSetting) { + const char* method = nm_setting_ip_config_get_method(ipSetting); + newCache.autoconfig = method && + (g_strcmp0(method, "auto") == 0 || g_strcmp0(method, "dhcp") == 0); + } + } + } + + /* IP config read is device-level and does not require an active connection. */ + NMIPConfig* ipConfig = skipRead ? nullptr + : (isIPv6 ? nm_device_get_ip6_config(device) + : nm_device_get_ip4_config(device)); + + if (ipConfig) { + GPtrArray* ipAddresses = nm_ip_config_get_addresses(ipConfig); + std::string macAddr; + if (isIPv6) { + const char* hw = nm_device_get_hw_address(device); + if (hw) macAddr = hw; + } + if (ipAddresses) { + for (guint i = 0; i < ipAddresses->len; i++) { + NMIPAddress* addr = (NMIPAddress*)g_ptr_array_index(ipAddresses, i); + if (!addr) continue; + const char* addrStr = nm_ip_address_get_address(addr); + if (!addrStr) continue; + std::string addrString = addrStr; + uint32_t prefix = nm_ip_address_get_prefix(addr); + if (isIPv6) { + if (isIPv6LinkLocal(addrString)) { + newCache.linkLocalAddresses.insert(addrString); + } else if (isIPv6ULA(addrString)) { + newCache.uniqueLocalAddresses.insert(addrString); + } else { + GlobalAddressType type = (!macAddr.empty() && isIPv6MacBased(addrString, macAddr)) + ? ADDR_GLOBAL_MAC_BASED : ADDR_GLOBAL; + newCache.globalAddresses.emplace(addrString, GlobalAddressInfo{prefix, type}); + } + } else { + if (isIPv4LinkLocal(addrString)) { + newCache.linkLocalAddresses.insert(addrString); + } else { + newCache.globalAddresses.emplace(addrString, GlobalAddressInfo{prefix, ADDR_GLOBAL}); + } + } + } + } + + const char* gw = nm_ip_config_get_gateway(ipConfig); + if (gw) newCache.gateway = gw; + + const char* const* dnsArr = nm_ip_config_get_nameservers(ipConfig); + if (dnsArr && dnsArr[0]) { + newCache.primarydns = dnsArr[0]; + if (dnsArr[1]) newCache.secondarydns = dnsArr[1]; + } + + NMDhcpConfig* dhcpConfig = isIPv6 + ? nm_device_get_dhcp6_config(device) + : nm_device_get_dhcp4_config(device); + if (dhcpConfig) { + const char* server = nm_dhcp_config_get_one_option(dhcpConfig, "dhcp_server_identifier"); + if (server) newCache.dhcpserver = server; + } + + newCache.valid = true; + } + + /* Swap new snapshot into instance cache; collect old global address keys for diff. */ + std::set oldKeys = _instance->swapIpCache( + ifname, isIPv6 ? "IPv6" : "IPv4", newCache); + + /* Emit address acquired/lost events from global-address key diff (outside the lock). */ + std::string family = isIPv6 ? "IPv6" : "IPv4"; + for (const auto& kv : newCache.globalAddresses) { + if (oldKeys.find(kv.first) == oldKeys.end()) { + _instance->ReportIPAddressChange(ifname, family, kv.first, Exchange::INetworkManager::IP_ACQUIRED); + } + } + for (const auto& key : oldKeys) { + if (newCache.globalAddresses.find(key) == newCache.globalAddresses.end()) { + _instance->ReportIPAddressChange(ifname, family, key, Exchange::INetworkManager::IP_LOST); + } + } + } + + static void ip4ChangedCb(NMIPConfig *ipConfig, GParamSpec *pspec, gpointer userData) + { + NMDevice *device = (NMDevice*)userData; + if (!device || !NM_IS_DEVICE(device)) return; + refreshIpFamilyCache(device, false); + } + + static void ip6ChangedCb(NMIPConfig *ipConfig, GParamSpec *pspec, gpointer userData) + { + NMDevice *device = (NMDevice*)userData; + if (!device || !NM_IS_DEVICE(device)) return; + refreshIpFamilyCache(device, true); + } + + /* Called when DHCP options change mid-lease (e.g. renewed with different server/options). */ + static void dhcp4OptionsCb(NMDhcpConfig *dhcpConfig, GParamSpec *pspec, gpointer userData) + { + NMDevice *device = (NMDevice*)userData; + if (!device || !NM_IS_DEVICE(device)) return; + refreshIpFamilyCache(device, false); + } + + static void dhcp6OptionsCb(NMDhcpConfig *dhcpConfig, GParamSpec *pspec, gpointer userData) + { + NMDevice *device = (NMDevice*)userData; + if (!device || !NM_IS_DEVICE(device)) return; + refreshIpFamilyCache(device, true); + } + + /* Called when the ip4-config or ip6-config object on a device is replaced + (e.g. after reconnect). Re-attaches notify handlers to the new object. */ + static void ip4ConfigChangedCb(NMDevice *device, GParamSpec *pspec, gpointer userData) + { + if (!device || !NM_IS_DEVICE(device)) return; + NMIPConfig* ipv4Config = nm_device_get_ip4_config(device); + if (ipv4Config) { + g_signal_handlers_disconnect_by_func(ipv4Config, (gpointer)ip4ChangedCb, device); + g_signal_connect(ipv4Config, "notify::addresses", G_CALLBACK(ip4ChangedCb), device); + g_signal_connect(ipv4Config, "notify::gateway", G_CALLBACK(ip4ChangedCb), device); + g_signal_connect(ipv4Config, "notify::nameservers", G_CALLBACK(ip4ChangedCb), device); + } + /* Re-attach DHCP options handler to the (possibly new) DHCP config object. */ + NMDhcpConfig* dhcp4 = nm_device_get_dhcp4_config(device); + if (dhcp4) { + g_signal_handlers_disconnect_by_func(dhcp4, (gpointer)dhcp4OptionsCb, device); + g_signal_connect(dhcp4, "notify::options", G_CALLBACK(dhcp4OptionsCb), device); + } + refreshIpFamilyCache(device, false); + } + + static void ip6ConfigChangedCb(NMDevice *device, GParamSpec *pspec, gpointer userData) + { + if (!device || !NM_IS_DEVICE(device)) return; + NMIPConfig* ipv6Config = nm_device_get_ip6_config(device); + if (ipv6Config) { + g_signal_handlers_disconnect_by_func(ipv6Config, (gpointer)ip6ChangedCb, device); + g_signal_connect(ipv6Config, "notify::addresses", G_CALLBACK(ip6ChangedCb), device); + g_signal_connect(ipv6Config, "notify::gateway", G_CALLBACK(ip6ChangedCb), device); + g_signal_connect(ipv6Config, "notify::nameservers", G_CALLBACK(ip6ChangedCb), device); + } + /* Re-attach DHCP options handler to the (possibly new) DHCP config object. */ + NMDhcpConfig* dhcp6 = nm_device_get_dhcp6_config(device); + if (dhcp6) { + g_signal_handlers_disconnect_by_func(dhcp6, (gpointer)dhcp6OptionsCb, device); + g_signal_connect(dhcp6, "notify::options", G_CALLBACK(dhcp6OptionsCb), device); + } + refreshIpFamilyCache(device, true); + } + void GnomeNetworkManagerEvents::deviceStateChangeCb(NMDevice *device, GParamSpec *pspec, NMEvents *nmEvents) { static bool isEthDisabled = false; @@ -125,11 +319,15 @@ namespace WPEFramework case NM_DEVICE_STATE_UNKNOWN: wifiState = "WIFI_STATE_UNINSTALLED"; GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_UNINSTALLED); + refreshIpFamilyCache(device, false); + refreshIpFamilyCache(device, true); GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::wlanIface()); break; case NM_DEVICE_STATE_UNMANAGED: wifiState = "WIFI_STATE_DISABLED"; GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_DISABLED); + refreshIpFamilyCache(device, false); + refreshIpFamilyCache(device, true); GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::wlanIface()); isWlanDisabled = true; break; @@ -137,6 +335,8 @@ namespace WPEFramework case NM_DEVICE_STATE_DISCONNECTED: wifiState = "WIFI_STATE_DISCONNECTED"; GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_DISCONNECTED); + refreshIpFamilyCache(device, false); + refreshIpFamilyCache(device, true); GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_DOWN, nmUtils::wlanIface()); break; case NM_DEVICE_STATE_PREPARE: @@ -212,11 +412,15 @@ namespace WPEFramework { case NM_DEVICE_STATE_UNKNOWN: case NM_DEVICE_STATE_UNMANAGED: + refreshIpFamilyCache(device, false); + refreshIpFamilyCache(device, true); GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::ethIface()); isEthDisabled = true; break; case NM_DEVICE_STATE_UNAVAILABLE: case NM_DEVICE_STATE_DISCONNECTED: + refreshIpFamilyCache(device, false); + refreshIpFamilyCache(device, true); GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_DOWN, nmUtils::ethIface()); break; case NM_DEVICE_STATE_PREPARE: @@ -261,101 +465,6 @@ namespace WPEFramework } } - static void ip4ChangedCb(NMIPConfig *ipConfig, GParamSpec *pspec, gpointer userData) - { - if (!ipConfig) { - NMLOG_ERROR("IP config is null"); - return; - } - - NMDevice *device = (NMDevice*)userData; - if((device == NULL) || (!NM_IS_DEVICE(device))) - return; - - const char* iface = nm_device_get_iface(device); - if(iface == NULL) - return; - std::string ifname = iface; - - GPtrArray *addresses = nm_ip_config_get_addresses(ipConfig); - if (!addresses) { - NMLOG_ERROR("No addresses found"); - return; - } - else { - if(addresses->len == 0) { - GnomeNetworkManagerEvents::onAddressChangeCb(ifname, "", false, false); - return; - } - } - - for (guint i = 0; i < addresses->len; ++i) { - NMIPAddress *address = (NMIPAddress *)g_ptr_array_index(addresses, i); - if(address == NULL) - { - NMLOG_WARNING("IPv4 address is null"); - continue; - } - if (nm_ip_address_get_family(address) == AF_INET) { - const char *ipAddress = nm_ip_address_get_address(address); - if(ipAddress != NULL) { - GnomeNetworkManagerEvents::onAddressChangeCb(iface, ipAddress, true, false); - } - } - } - } - - static void ip6ChangedCb(NMIPConfig *ipConfig, GParamSpec *pspec, gpointer userData) - { - if (!ipConfig) { - NMLOG_ERROR("ip config is null"); - return; - } - - NMDevice *device = (NMDevice*)userData; - if( ((device != NULL) && NM_IS_DEVICE(device)) ) - { - const char* iface = nm_device_get_iface(device); - if(iface == NULL) - return; - std::string ifname = iface; - GPtrArray *addresses = nm_ip_config_get_addresses(ipConfig); - if (!addresses) { - NMLOG_ERROR("No addresses found"); - return; - } - else { - if(addresses->len == 0) { - GnomeNetworkManagerEvents::onAddressChangeCb(ifname, "", false, true); - return; - } - } - - for (guint i = 0; i < addresses->len; ++i) { - NMIPAddress *address = (NMIPAddress *)g_ptr_array_index(addresses, i); - if(address == NULL) - { - NMLOG_WARNING("IPv6 address is null"); - continue; - } - if (nm_ip_address_get_family(address) == AF_INET6) { - const char *ipaddr = nm_ip_address_get_address(address); - //int prefix = nm_ip_address_get_prefix(address); - if(ipaddr != NULL) { - std::string ipAddress = ipaddr; - if (ipAddress.compare(0, 5, "fe80:") == 0 || - ipAddress.compare(0, 6, "fe80::") == 0) { - NMLOG_DEBUG("%s It's link-local ip", ipAddress.c_str()); - continue; // It's link-local so skiping - } - GnomeNetworkManagerEvents::onAddressChangeCb(iface, ipAddress, true, true); - break; // SLAAC protocol may include multip ipv6 address posting only one Global address - } - } - } - } - } - static void deviceAddedCB(NMClient *client, NMDevice *device, NMEvents *nmEvents) { if( ((device != NULL) && NM_IS_DEVICE(device)) ) @@ -374,17 +483,35 @@ namespace WPEFramework if(ifname == nmUtils::ethIface() || ifname == nmUtils::wlanIface()) { g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(GnomeNetworkManagerEvents::deviceStateChangeCb), nmEvents); - // TODO call notify::" NM_DEVICE_ACTIVE_CONNECTION if needed + g_signal_connect(device, "notify::ip4-config", G_CALLBACK(ip4ConfigChangedCb), nmEvents); + g_signal_connect(device, "notify::ip6-config", G_CALLBACK(ip6ConfigChangedCb), nmEvents); NMIPConfig *ipv4Config = nm_device_get_ip4_config(device); NMIPConfig *ipv6Config = nm_device_get_ip6_config(device); if (ipv4Config) { - g_signal_connect(ipv4Config, "notify::addresses", G_CALLBACK(ip4ChangedCb), device); + g_signal_connect(ipv4Config, "notify::addresses", G_CALLBACK(ip4ChangedCb), device); + g_signal_connect(ipv4Config, "notify::gateway", G_CALLBACK(ip4ChangedCb), device); + g_signal_connect(ipv4Config, "notify::nameservers", G_CALLBACK(ip4ChangedCb), device); } if (ipv6Config) { - g_signal_connect(ipv6Config, "notify::addresses", G_CALLBACK(ip6ChangedCb), device); + g_signal_connect(ipv6Config, "notify::addresses", G_CALLBACK(ip6ChangedCb), device); + g_signal_connect(ipv6Config, "notify::gateway", G_CALLBACK(ip6ChangedCb), device); + g_signal_connect(ipv6Config, "notify::nameservers", G_CALLBACK(ip6ChangedCb), device); } + /* Subscribe to DHCP option changes so dhcpserver stays current mid-lease. */ + NMDhcpConfig* dhcp4Added = nm_device_get_dhcp4_config(device); + NMDhcpConfig* dhcp6Added = nm_device_get_dhcp6_config(device); + if (dhcp4Added) + g_signal_connect(dhcp4Added, "notify::options", G_CALLBACK(dhcp4OptionsCb), device); + if (dhcp6Added) + g_signal_connect(dhcp6Added, "notify::options", G_CALLBACK(dhcp6OptionsCb), device); + + /* Seed the IP cache so GetIPSettings works immediately if the + device already has an address (e.g. hotplug in activated state). */ + refreshIpFamilyCache(device, false); + refreshIpFamilyCache(device, true); + if (NM_IS_DEVICE_WIFI(device)) { // Register signal handler for WiFi scanning events to detect when scan operations complete @@ -405,14 +532,45 @@ namespace WPEFramework std::string ifname = nm_device_get_iface(device); if(ifname == nmUtils::wlanIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::wlanIface()); - g_signal_handlers_disconnect_by_func(device, (gpointer)GnomeNetworkManagerEvents::deviceStateChangeCb, nmEvents); NMLOG_INFO("WIFI device removed: %s", ifname.c_str()); } else if(ifname == nmUtils::ethIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::ethIface()); - g_signal_handlers_disconnect_by_func(device, (gpointer)GnomeNetworkManagerEvents::deviceStateChangeCb, nmEvents); NMLOG_INFO("ETHERNET device removed: %s", ifname.c_str()); } + else { + return; // not a tracked interface + } + + /* Disconnect all device-level signals (state, ip4/ip6-config changes). */ + g_signal_handlers_disconnect_by_data(device, nmEvents); + + /* Disconnect IP config property signals (addresses, gateway, nameservers). */ + NMIPConfig *ipv4Config = nm_device_get_ip4_config(device); + NMIPConfig *ipv6Config = nm_device_get_ip6_config(device); + if (ipv4Config) + g_signal_handlers_disconnect_by_func(ipv4Config, (gpointer)ip4ChangedCb, device); + if (ipv6Config) + g_signal_handlers_disconnect_by_func(ipv6Config, (gpointer)ip6ChangedCb, device); + + /* Disconnect DHCP option signals. */ + NMDhcpConfig* dhcp4 = nm_device_get_dhcp4_config(device); + NMDhcpConfig* dhcp6 = nm_device_get_dhcp6_config(device); + if (dhcp4) + g_signal_handlers_disconnect_by_func(dhcp4, (gpointer)dhcp4OptionsCb, device); + if (dhcp6) + g_signal_handlers_disconnect_by_func(dhcp6, (gpointer)dhcp6OptionsCb, device); + + /* Clear IP cache for the removed device (emits IP_LOST for any cached addresses). */ + if (_instance) { + for (const char* family : {"IPv4", "IPv6"}) { + IpFamilyCache empty; + std::set oldKeys = _instance->swapIpCache(ifname, family, empty); + for (const auto& key : oldKeys) { + _instance->ReportIPAddressChange(ifname, family, key, Exchange::INetworkManager::IP_LOST); + } + } + } } // guint disconnected_count = g_signal_handlers_disconnect_matched( _nmEventInstance->activeConn, @@ -492,6 +650,8 @@ namespace WPEFramework /* Register device state change event */ g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(GnomeNetworkManagerEvents::deviceStateChangeCb), nmEvents); + g_signal_connect(device, "notify::ip4-config", G_CALLBACK(ip4ConfigChangedCb), nmEvents); + g_signal_connect(device, "notify::ip6-config", G_CALLBACK(ip6ConfigChangedCb), nmEvents); if(NM_IS_DEVICE_WIFI(device)) { nmEvents->wifiDevice = NM_DEVICE_WIFI(device); g_signal_connect(nmEvents->wifiDevice, "notify::" NM_DEVICE_WIFI_LAST_SCAN, G_CALLBACK(GnomeNetworkManagerEvents::onAvailableSSIDsCb), nmEvents); @@ -500,18 +660,32 @@ namespace WPEFramework NMIPConfig *ipv4Config = nm_device_get_ip4_config(device); NMIPConfig *ipv6Config = nm_device_get_ip6_config(device); if (ipv4Config) { - ip4ChangedCb(ipv4Config, NULL, device); // posting event if interface already connected - g_signal_connect(ipv4Config, "notify::addresses", G_CALLBACK(ip4ChangedCb), device); + g_signal_connect(ipv4Config, "notify::addresses", G_CALLBACK(ip4ChangedCb), device); + g_signal_connect(ipv4Config, "notify::gateway", G_CALLBACK(ip4ChangedCb), device); + g_signal_connect(ipv4Config, "notify::nameservers", G_CALLBACK(ip4ChangedCb), device); } else NMLOG_WARNING("IPv4 config is null for device: %s, No IPv4 monitor", ifname.c_str()); if (ipv6Config) { - ip6ChangedCb(ipv6Config, NULL, device); - g_signal_connect(ipv6Config, "notify::addresses", G_CALLBACK(ip6ChangedCb), device); + g_signal_connect(ipv6Config, "notify::addresses", G_CALLBACK(ip6ChangedCb), device); + g_signal_connect(ipv6Config, "notify::gateway", G_CALLBACK(ip6ChangedCb), device); + g_signal_connect(ipv6Config, "notify::nameservers", G_CALLBACK(ip6ChangedCb), device); } else NMLOG_WARNING("IPv6 config is null for device: %s, No IPv6 monitor", ifname.c_str()); + + /* Subscribe to DHCP option changes so dhcpserver stays current mid-lease. */ + NMDhcpConfig* dhcp4Init = nm_device_get_dhcp4_config(device); + NMDhcpConfig* dhcp6Init = nm_device_get_dhcp6_config(device); + if (dhcp4Init) + g_signal_connect(dhcp4Init, "notify::options", G_CALLBACK(dhcp4OptionsCb), device); + if (dhcp6Init) + g_signal_connect(dhcp6Init, "notify::options", G_CALLBACK(dhcp6OptionsCb), device); + + /* Seed the IP cache from current state for already-connected devices. */ + refreshIpFamilyCache(device, false); + refreshIpFamilyCache(device, true); } else NMLOG_DEBUG("device type not eth/wifi %s", ifname.c_str()); @@ -593,6 +767,14 @@ namespace WPEFramework if (ipv6Config) { g_signal_handlers_disconnect_by_func(ipv6Config, (gpointer)ip6ChangedCb, device); } + + // Clean up DHCP option signals + NMDhcpConfig* dhcp4 = nm_device_get_dhcp4_config(device); + NMDhcpConfig* dhcp6 = nm_device_get_dhcp6_config(device); + if (dhcp4) + g_signal_handlers_disconnect_by_func(dhcp4, (gpointer)dhcp4OptionsCb, device); + if (dhcp6) + g_signal_handlers_disconnect_by_func(dhcp6, (gpointer)dhcp6OptionsCb, device); } } } @@ -714,53 +896,6 @@ namespace WPEFramework } } - void GnomeNetworkManagerEvents::onAddressChangeCb(std::string iface, std::string ipAddress, bool acquired, bool isIPv6) - { - /* - * notify::addresses g signal only send ipaddress when accuired time only. - * we need to post ip address when ipaddress lost case also so we caching the ip address per interface - */ - static std::map ipv6Map; - static std::map ipv4Map; - - if(acquired) - { - if (isIPv6) - { - if (ipv6Map[iface].find(ipAddress) == std::string::npos) { // same ip comes multiple time so avoding that - ipv6Map[iface] = ipAddress; - } - else // same ip not posting - return; - } - else - { - ipv4Map[iface] = ipAddress; - } - } - else - { - if (isIPv6) - { - ipAddress = ipv6Map[iface]; - ipv6Map[iface].clear(); - } - else - { - ipAddress = ipv4Map[iface]; - ipv4Map[iface].clear(); - } - if(ipAddress.empty()) - return; // empty ip address not posting event - } - Exchange::INetworkManager::IPStatus ipStatus{}; - if (acquired) - ipStatus = Exchange::INetworkManager::IP_ACQUIRED; - if(_instance != nullptr) - _instance->ReportIPAddressChange(iface, isIPv6?"IPv6":"IPv4", ipAddress, ipStatus); - NMLOG_INFO("iface:%s - ipaddress:%s - %s - %s", iface.c_str(), ipAddress.c_str(), acquired?"acquired":"lost", isIPv6?"isIPv6":"isIPv4"); - } - bool GnomeNetworkManagerEvents::apToJsonObject(NMAccessPoint *ap, JsonObject& ssidObj) { GBytes *ssid = NULL; diff --git a/plugin/gnome/NetworkManagerGnomeEvents.h b/plugin/gnome/NetworkManagerGnomeEvents.h index ee29ce6d2..bf282de78 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.h +++ b/plugin/gnome/NetworkManagerGnomeEvents.h @@ -44,7 +44,6 @@ namespace WPEFramework public: static void onInterfaceStateChangeCb(uint8_t newState, std::string iface); // ReportInterfaceStateChange - static void onAddressChangeCb(std::string iface, std::string ipAddress, bool acqired, bool isIPv6); // ReportIPAddressChange static void onActiveInterfaceChangeCb(std::string newInterface); // ReportActiveInterfaceChange static void onAvailableSSIDsCb(NMDeviceWifi *wifiDevice, GParamSpec *pspec, gpointer userData); // ReportAvailableSSIDs static void onWIFIStateChanged(uint8_t state); // ReportWiFiStateChange diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 81d1e9332..234a8df9b 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -22,9 +22,6 @@ #include "NetworkManagerGnomeUtils.h" #include #include -#include - -#define IN_IS_ADDR_LINKLOCAL(a) ((((uint32_t)ntohl(a)) & 0xffff0000U) == 0xa9fe0000U) using namespace WPEFramework; using namespace WPEFramework::Plugin; using namespace std; @@ -656,40 +653,9 @@ namespace WPEFramework return Core::ERROR_GENERAL; } - bool static isAutoConnectEnabled(NMActiveConnection* activeConn) - { - NMConnection *connection = NM_CONNECTION(nm_active_connection_get_connection(activeConn)); - if(connection == NULL) - return false; - - NMSettingIPConfig *ipConfig = nm_connection_get_setting_ip4_config(connection); - if(ipConfig) - { - const char* ipConfMethod = nm_setting_ip_config_get_method (ipConfig); - if(ipConfMethod != NULL && g_strcmp0(ipConfMethod, "auto") == 0) - return true; - else - NMLOG_WARNING("ip configuration: %s", ipConfMethod != NULL? ipConfMethod: "null"); - } - - return false; - } - /* @brief Get IP Address Of the Interface */ uint32_t NetworkManagerImplementation::GetIPSettings(string& interface /* @inout */, const string &ipversion /* @in */, IPAddress& result /* @out */) { - NMActiveConnection *conn = NULL; - NMIPConfig *ip4_config = NULL; - NMIPConfig *ip6_config = NULL; - const gchar *gateway = NULL; - char **dnsArr = NULL; - NMDhcpConfig *dhcp4_config = NULL; - NMDhcpConfig *dhcp6_config = NULL; - const char* dhcpserver; - NMSettingConnection *settings = NULL; - NMDevice *device = NULL; - string ipversionStr; - std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); if(interface.empty()) @@ -712,271 +678,22 @@ namespace WPEFramework return Core::ERROR_GENERAL; } - if(ipversion.empty()) - { - ipversionStr = "IPV4"; - } - else - { - ipversionStr = ipversion; - } - - // Add caching optimization similar to RDK proxy - if (wifiname == interface) - { - if(nmUtils::caseInsensitiveCompare(ipversionStr, "IPV4") && !m_wlanIPv4Address.ipaddress.empty()) - { - NMLOG_DEBUG("%s IPv4 address from cache", wifiname.c_str()); - result = m_wlanIPv4Address; - return Core::ERROR_NONE; - } - else if(nmUtils::caseInsensitiveCompare(ipversion, "IPV6") && !m_wlanIPv6Address.ipaddress.empty()) - { - NMLOG_DEBUG("%s IPv6 address from cache", wifiname.c_str()); - result = m_wlanIPv6Address; - return Core::ERROR_NONE; - } - } - else if (ethname == interface) - { - if(nmUtils::caseInsensitiveCompare(ipversionStr, "IPV4") && !m_ethIPv4Address.ipaddress.empty()) - { - NMLOG_DEBUG("%s IPv4 address from cache", ethname.c_str()); - result = m_ethIPv4Address; - return Core::ERROR_NONE; - } - else if(nmUtils::caseInsensitiveCompare(ipversion, "IPV6") && !m_ethIPv6Address.ipaddress.empty()) - { - NMLOG_DEBUG("%s IPv6 address from cache", ethname.c_str()); - result = m_ethIPv6Address; - return Core::ERROR_NONE; - } - } - - if(m_nmClient == nullptr) - { - NMLOG_WARNING("NMClient is null"); - return Core::ERROR_RPC_CALL_FAILED; - } - - /* Drain any pending D-Bus property-change events queued on m_nmContext - * before reading libnm GObject state. Because m_nmContext is isolated - * from the event thread, nobody else can run it — so this loop is - * single-threaded and safe. It ensures m_nmClient reflects the latest state - * from NetworkManager before we start iterating connections/addresses. */ - if (m_nmContext) { - for (int i = 0; i < 100 && g_main_context_iteration(m_nmContext, FALSE); ++i){ - // Intentional empty body: just flushing the event queue - } - } - - device = nm_client_get_device_by_iface(m_nmClient, interface.c_str()); - if (device == NULL) - { - NMLOG_FATAL("libnm doesn't have device corresponding to %s", interface.c_str()); - return Core::ERROR_GENERAL; - } - - NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; - deviceState = nm_device_get_state(device); - if(deviceState < NM_DEVICE_STATE_DISCONNECTED) - { - NMLOG_WARNING("%s state is not a valid state: (%d)", interface.c_str(), deviceState); - return Core::ERROR_GENERAL; - } + string ipversionStr = ipversion.empty() ? "IPv4" : ipversion; + std::string family = nmUtils::caseInsensitiveCompare(ipversionStr, "IPv6") ? "IPv6" : "IPv4"; - // if(ipversion.empty()) - // NMLOG_DEBUG("ipversion is empty default value IPv4"); + result = IPAddress{}; - const GPtrArray *connections = nm_client_get_active_connections(m_nmClient); - if(connections == NULL) + // Serve from event-driven cache + if (lookupIpCache(interface, family, result)) { - NMLOG_WARNING("no active connection; ip is not assigned to interface"); - return Core::ERROR_GENERAL; + NMLOG_DEBUG("%s %s address from cache", interface.c_str(), family.c_str()); } - - for (guint i = 0; i < connections->len; i++) - { - if(connections->pdata[i] == NULL) - continue; - - NMActiveConnection *connection = NM_ACTIVE_CONNECTION(connections->pdata[i]); - if (connection == nullptr) - continue; - - NMRemoteConnection* retConn = nm_active_connection_get_connection(connection); - if(retConn == NULL) - { - NMLOG_INFO("remote connection is null"); - continue; - } - - settings = nm_connection_get_setting_connection(NM_CONNECTION(retConn)); - if(settings == NULL) - continue; - if (g_strcmp0(nm_setting_connection_get_interface_name(settings), interface.c_str()) == 0) - { - conn = connection; - break; - } - } - - if (conn == NULL) + else { - NMLOG_WARNING("no active connection on %s interface", interface.c_str()); - return Core::ERROR_GENERAL; + NMLOG_DEBUG("no %s address on %s", family.c_str(), interface.c_str()); } + result.ipversion = family; - result.autoconfig = isAutoConnectEnabled(conn); - - if(ipversion.empty() || nmUtils::caseInsensitiveCompare(ipversion, "IPV4")) - { - const GPtrArray *ipByte = nullptr; - result.ipversion = "IPv4"; - ip4_config = nm_active_connection_get_ip4_config(conn); - NMIPAddress *ipAddr = NULL; - std::string ipStr; - struct sockaddr_in sa; - if (ip4_config) - ipByte = nm_ip_config_get_addresses(ip4_config); - else - NMLOG_WARNING("no IPv4 configurtion on %s", interface.c_str()); - if(ipByte) - { - for (guint i = 0; i < ipByte->len; i++) - { - ipStr.clear(); - ipAddr = static_cast(ipByte->pdata[i]); - if(ipAddr) - { - const char* addr = nm_ip_address_get_address(ipAddr); - if(addr) - ipStr = addr; - } - if(!ipStr.empty()) - { - // Skip link-local IPv4 addresses (169.254.x.x) - inet_pton(AF_INET, ipStr.c_str(), &(sa.sin_addr)); - if(IN_IS_ADDR_LINKLOCAL(sa.sin_addr.s_addr)) - { - NMLOG_DEBUG("Skipping link-local IPv4 address: %s", ipStr.c_str()); - continue; - } - result.ipaddress = ipStr; - result.prefix = nm_ip_address_get_prefix(ipAddr); - NMLOG_DEBUG("IPv4 addr: %s/%d", result.ipaddress.c_str(), result.prefix); - } - } - gateway = nm_ip_config_get_gateway(ip4_config); - if(gateway) - result.gateway = gateway; - dnsArr = (char **)nm_ip_config_get_nameservers(ip4_config); - if(dnsArr) - { - if(dnsArr[0]) - result.primarydns = std::string(dnsArr[0]); - if(dnsArr[1]) - result.secondarydns = std::string(dnsArr[1]); - } - dhcp4_config = nm_active_connection_get_dhcp4_config(conn); - if(dhcp4_config) - { - dhcpserver = nm_dhcp_config_get_one_option (dhcp4_config, "dhcp_server_identifier"); - if(dhcpserver) - result.dhcpserver = dhcpserver; - } - result.ula = ""; - - // Check if only link-local IPv4 is available (no valid global address found) - if(result.ipaddress.empty()) - { - NMLOG_WARNING("Only link-local IPv4 available on %s, not returning it", interface.c_str()); - // Clear cache for link-local only - if(ethname == interface) - m_ethIPv4Address = IPAddress(); - else if(wifiname == interface) - m_wlanIPv4Address = IPAddress(); - return Core::ERROR_GENERAL; - } - - // Cache the IPv4 address - if(ethname == interface) - m_ethIPv4Address = result; - else if(wifiname == interface) - m_wlanIPv4Address = result; - } - } - if((result.ipaddress.empty() && !(nmUtils::caseInsensitiveCompare(ipversion, "IPV4"))) || nmUtils::caseInsensitiveCompare(ipversion, "IPV6")) - { - std::string ipStr; - const GPtrArray *ipArray = nullptr; - result.ipversion = "IPv6"; - NMIPAddress *ipAddr = nullptr; - ip6_config = nm_active_connection_get_ip6_config(conn); - if(ip6_config) - ipArray = nm_ip_config_get_addresses(ip6_config); - else - NMLOG_WARNING("no IPv6 configurtion on %s", interface.c_str()); - if(ipArray) - { - for (guint i = 0; i < ipArray->len; i++) - { - ipStr.clear(); - ipAddr = static_cast(ipArray->pdata[i]); - if(ipAddr) - { - const char* addr = nm_ip_address_get_address(ipAddr); - if(addr) - ipStr = addr; - } - if(!ipStr.empty()) - { - if (ipStr.compare(0, 5, "fe80:") == 0 || ipStr.compare(0, 6, "fe80::") == 0) - { - result.ula = ipStr; - NMLOG_DEBUG("link-local ip: %s", result.ula.c_str()); - } - else - { - result.prefix = nm_ip_address_get_prefix(ipAddr); - if(result.ipaddress.empty()) // SLAAC mutiple ip not added - result.ipaddress = ipStr; - NMLOG_DEBUG("global ip %s/%d", ipStr.c_str(), result.prefix); - } - } - } - - gateway = nm_ip_config_get_gateway(ip6_config); - if(gateway) - result.gateway= gateway; - dnsArr = (char **)nm_ip_config_get_nameservers(ip6_config); - if(dnsArr) - { - if(dnsArr[0]) - result.primarydns = std::string(dnsArr[0]); - if(dnsArr[1]) - result.secondarydns = std::string(dnsArr[1]); - } - dhcp6_config = nm_active_connection_get_dhcp6_config(conn); - if(dhcp6_config) - { - dhcpserver = nm_dhcp_config_get_one_option (dhcp6_config, "dhcp_server_identifier"); - if(dhcpserver) - result.dhcpserver = dhcpserver; - } - // Cache the IPv6 address - if(ethname == interface) - m_ethIPv6Address = result; - else if(wifiname == interface) - m_wlanIPv6Address = result; - } - } - if(result.ipaddress.empty()) - { - result.autoconfig = true; - if(ipversion.empty()) - result.ipversion = "IPv4"; - } return Core::ERROR_NONE; } diff --git a/tests/l2Test/libnm/l2_test_libnmproxy.cpp b/tests/l2Test/libnm/l2_test_libnmproxy.cpp index e4f9b1ec8..0a3dad69d 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxy.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxy.cpp @@ -40,6 +40,8 @@ using namespace WPEFramework; using ::testing::NiceMock; +namespace WPEFramework { namespace Plugin { extern NetworkManagerImplementation* _instance; } } + class NetworkManagerTest : public ::testing::Test { protected: Core::ProxyType plugin; @@ -515,24 +517,15 @@ TEST_F(NetworkManagerTest, GetIPSettings_unknown_iface) EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); } -TEST_F(NetworkManagerTest, GetIPSettings_invalidDevice) -{ - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(NULL))); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); - EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); -} - -TEST_F(NetworkManagerTest, GetIPSettings_invalid_state) +TEST_F(NetworkManagerTest, GetIPSettings_emptyCache) { - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); - + /* With no cache populated, GetIPSettings should still succeed but return no IP data */ EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); - EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"interface\":\"eth0\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ipversion\":\"IPv4\"") != std::string::npos); + /* No ipaddress key when cache is empty */ + EXPECT_TRUE(response.find("\"ipaddress\"") == std::string::npos); } TEST_F(NetworkManagerTest, GetIPSettings_interface_Empty) @@ -548,348 +541,408 @@ TEST_F(NetworkManagerTest, GetIPSettings_GetPrimary_failed) EXPECT_EQ(Core::ERROR_GENERAL, NetworkManagerImpl2->GetIPSettings(interface, ipversion, address)); } -TEST_F(NetworkManagerTest, GetIPSettings_Invalid_ActiveConnection) +TEST_F(NetworkManagerTest, GetIPSettings_ipv4_fromCache) { - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(NULL))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + /* Populate IPv4 cache for eth0, then verify GetIPSettings returns cached data */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.globalAddresses["192.168.1.2"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); + cache.gateway = "192.168.1.1"; + cache.primarydns = "8.8.8.8"; + cache.secondarydns = "8.8.4.4"; + cache.dhcpserver = "192.168.1.11"; + cache.autoconfig = true; + Plugin::_instance->swapIpCache("eth0", "IPv4", cache); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); - EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"interface\":\"eth0\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ipversion\":\"IPv4\"") != std::string::npos); + EXPECT_TRUE(response.find("\"autoconfig\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\":\"192.168.1.2\"") != std::string::npos); + EXPECT_TRUE(response.find("\"prefix\":24") != std::string::npos); + EXPECT_TRUE(response.find("\"gateway\":\"192.168.1.1\"") != std::string::npos); + EXPECT_TRUE(response.find("\"primarydns\":\"8.8.8.8\"") != std::string::npos); + EXPECT_TRUE(response.find("\"secondarydns\":\"8.8.4.4\"") != std::string::npos); + EXPECT_TRUE(response.find("\"dhcpserver\":\"192.168.1.11\"") != std::string::npos); } -TEST_F(NetworkManagerTest, GetIPSettings_Invalid_Connection) +TEST_F(NetworkManagerTest, GetIPSettings_ipv4_autoconfig) { - GPtrArray* dummyActiveConn = g_ptr_array_new(); - NMActiveConnection *nullConnection = static_cast(NULL); - NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - g_ptr_array_add(dummyActiveConn, nullConnection); - g_ptr_array_add(dummyActiveConn, ethActiveConn); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(NULL))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + /* Populate IPv4 cache with autoconfig=true but no IP address */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.autoconfig = true; + Plugin::_instance->swapIpCache("eth0", "IPv4", cache); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); - EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); - - g_object_unref(ethActiveConn); - g_ptr_array_free(dummyActiveConn, TRUE); + std::string expectedResponse = + _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"success\":true}"); + EXPECT_EQ(response, expectedResponse); } -TEST_F(NetworkManagerTest, GetIPSettings_valid_ConnectionSettingsEmpty) +TEST_F(NetworkManagerTest, GetIPSettings_ipv4_staticConfig) { - GPtrArray* dummyActiveConn = g_ptr_array_new(); - NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - NMRemoteConnection* retConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - g_ptr_array_add(dummyActiveConn, ethActiveConn); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(NULL))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) - .WillOnce(::testing::Return(retConn)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + /* Populate IPv4 cache with autoconfig=false (static config) */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.autoconfig = false; + cache.globalAddresses["192.168.1.100"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); + cache.gateway = "192.168.1.1"; + Plugin::_instance->swapIpCache("eth0", "IPv4", cache); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); - EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); - - g_object_unref(ethActiveConn); - g_ptr_array_free(dummyActiveConn, TRUE); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"autoconfig\":false") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\":\"192.168.1.100\"") != std::string::npos); } -TEST_F(NetworkManagerTest, GetIPSettings_ipv4_config) +TEST_F(NetworkManagerTest, GetIPSettings_wlan0_fromCache) { - GPtrArray* dummyActiveConn = g_ptr_array_new(); - NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - NMRemoteConnection* retConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - g_ptr_array_add(dummyActiveConn, ethActiveConn); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_ip4_config(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(NULL))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_connection_get_interface_name(::testing::_)) - .WillOnce(::testing::Return("eth0")); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100173))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) - .WillOnce(::testing::Return(retConn)) - .WillOnce(::testing::Return(reinterpret_cast(NULL))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); + /* Populate IPv4 cache for wlan0 */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.autoconfig = true; + cache.globalAddresses["10.0.0.5"] = Plugin::GlobalAddressInfo(8, Plugin::ADDR_GLOBAL); + cache.gateway = "10.0.0.1"; + cache.primarydns = "1.1.1.1"; + Plugin::_instance->swapIpCache("wlan0", "IPv4", cache); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"wlan0\"}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"interface\":\"wlan0\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\":\"10.0.0.5\"") != std::string::npos); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); +TEST_F(NetworkManagerTest, GetIPSettings_ipv4_config_valid) +{ + /* Populate full IPv4 cache for eth0 and verify all fields */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.autoconfig = true; + cache.globalAddresses["192.168.1.2"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); + cache.gateway = "192.168.1.0"; + cache.primarydns = "8.8.8.8"; + cache.secondarydns = "8.8.4.4"; + cache.dhcpserver = "192.168.1.11"; + Plugin::_instance->swapIpCache("eth0", "IPv4", cache); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); - std::string expectedResponse = - _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"success\":true}"); - EXPECT_EQ(response, expectedResponse); - g_object_unref(ethActiveConn); - g_ptr_array_free(dummyActiveConn, TRUE); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"secondarydns\":\"8.8.4.4\"") != std::string::npos); + EXPECT_TRUE(response.find("\"primarydns\":\"8.8.8.8\"") != std::string::npos); + EXPECT_TRUE(response.find("\"interface\":\"eth0\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\":\"192.168.1.2\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ula\":\"\"") != std::string::npos); + EXPECT_TRUE(response.find("\"dhcpserver\":\"192.168.1.11\"") != std::string::npos); + EXPECT_TRUE(response.find("\"gateway\":\"192.168.1.0\"") != std::string::npos); } -TEST_F(NetworkManagerTest, GetIPSettings_ipv4_configAutoConftrue) +TEST_F(NetworkManagerTest, GetIPSettings_ipv6_config_valid) { - GPtrArray* dummyActiveConn = g_ptr_array_new(); - NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - NMRemoteConnection* retConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - g_ptr_array_add(dummyActiveConn, ethActiveConn); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_ip4_config(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(NULL))); + /* Populate full IPv6 cache for eth0 and verify all fields */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.autoconfig = true; + cache.globalAddresses["2001:db8:1:2:3:4:5:6"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL); + cache.uniqueLocalAddresses.insert("fd12::1234:5678:abcd:ef01"); + cache.gateway = "2001:4860:4860::1"; + cache.primarydns = "2001:4860:4860::8888"; + cache.secondarydns = "2001:4860:4860::8844"; + cache.dhcpserver = "2001:db8::1"; + Plugin::_instance->swapIpCache("eth0", "IPv6", cache); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_connection_get_interface_name(::testing::_)) - .WillOnce(::testing::Return("eth0")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv6\"}"), response)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"ipversion\":\"IPv6\"") != std::string::npos); + EXPECT_TRUE(response.find("\"secondarydns\":\"2001:4860:4860::8844\"") != std::string::npos); + EXPECT_TRUE(response.find("\"primarydns\":\"2001:4860:4860::8888\"") != std::string::npos); + EXPECT_TRUE(response.find("\"interface\":\"eth0\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\":\"2001:db8:1:2:3:4:5:6\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ula\":\"fd12::1234:5678:abcd:ef01\"") != std::string::npos); + EXPECT_TRUE(response.find("\"prefix\":64") != std::string::npos); + EXPECT_TRUE(response.find("\"dhcpserver\":\"2001:db8::1\"") != std::string::npos); + EXPECT_TRUE(response.find("\"gateway\":\"2001:4860:4860::1\"") != std::string::npos); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_ip_config_get_method(::testing::_)) - .WillOnce(::testing::Return("auto")); +TEST_F(NetworkManagerTest, GetIPSettings_ipv6_mac_based_fallback) +{ + /* When all global addresses are MAC-based, toIPAddress should use the MAC-based one */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.autoconfig = true; + cache.globalAddresses["2001:db8::aabb:ccff:fedd:eeff"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL_MAC_BASED); + cache.gateway = "fe80::1"; + Plugin::_instance->swapIpCache("eth0", "IPv6", cache); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_ip4_config(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv6\"}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\":\"2001:db8::aabb:ccff:fedd:eeff\"") != std::string::npos); + EXPECT_TRUE(response.find("\"prefix\":64") != std::string::npos); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) - .WillOnce(::testing::Return(retConn)) - .WillOnce(::testing::Return(reinterpret_cast(retConn))); +TEST_F(NetworkManagerTest, GetIPSettings_ipv6_prefer_non_mac_global) +{ + /* ADDR_GLOBAL should be preferred over ADDR_GLOBAL_MAC_BASED */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.autoconfig = true; + /* Insert MAC-based first to ensure it's not selected by insertion order */ + cache.globalAddresses["2001:db8::aabb:ccff:fedd:eeff"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL_MAC_BASED); + cache.globalAddresses["2001:db8::1234:5678"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL); + Plugin::_instance->swapIpCache("eth0", "IPv6", cache); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv6\"}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\":\"2001:db8::1234:5678\"") != std::string::npos); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); +TEST_F(NetworkManagerTest, GetIPSettings_ipv6_only_cached_request_ipv4) +{ + /* Only IPv6 cached, but IPv4 requested — should return success with no IP */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.autoconfig = true; + cache.globalAddresses["2001:db8::1"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL); + Plugin::_instance->swapIpCache("eth0", "IPv6", cache); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv4\"}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"ipversion\":\"IPv4\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\"") == std::string::npos); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); +TEST_F(NetworkManagerTest, GetIPSettings_cache_invalidated) +{ + /* Cache exists but valid=false — should return success with no IP data */ + Plugin::IpFamilyCache cache; + cache.valid = false; + cache.globalAddresses["192.168.1.5"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); + Plugin::_instance->swapIpCache("eth0", "IPv4", cache); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); - std::string expectedResponse = - _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"success\":true}"); - EXPECT_EQ(response, expectedResponse); - - g_object_unref(ethActiveConn); - g_ptr_array_free(dummyActiveConn, TRUE); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\"") == std::string::npos); } -TEST_F(NetworkManagerTest, GetIPSettings_ipv4_configAutoConfNull) +TEST_F(NetworkManagerTest, GetIPSettings_ipversion_case_insensitive) { - GPtrArray* dummyActiveConn = g_ptr_array_new(); - NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - NMRemoteConnection* retConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - g_ptr_array_add(dummyActiveConn, ethActiveConn); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_ip4_config(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(NULL))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_connection_get_interface_name(::testing::_)) - .WillOnce(::testing::Return("eth0")); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100173))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_ip_config_get_method(::testing::_)) - .WillOnce(::testing::Return("not auto")); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_ip4_config(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100173))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) - .WillOnce(::testing::Return(retConn)) - .WillOnce(::testing::Return(reinterpret_cast(retConn))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + /* ipversion "ipv6" (lowercase) should be treated as IPv6 */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.autoconfig = true; + cache.globalAddresses["2001:db8::99"] = Plugin::GlobalAddressInfo(128, Plugin::ADDR_GLOBAL); + Plugin::_instance->swapIpCache("eth0", "IPv6", cache); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"ipv6\"}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\":\"2001:db8::99\"") != std::string::npos); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); +TEST_F(NetworkManagerTest, GetIPSettings_ipv6_ula_only) +{ + /* Cache has only ULA addresses, no global — ipaddress is empty so the + JSON-RPC layer (NetworkManagerJsonRpc.cpp) skips all address fields + including ula, gateway, etc. Only interface/ipversion/autoconfig/success + are returned. */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.autoconfig = true; + cache.uniqueLocalAddresses.insert("fd00::1234:abcd"); + cache.gateway = "fe80::1"; + Plugin::_instance->swapIpCache("eth0", "IPv6", cache); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv6\"}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + /* No global address → ipaddress empty → JSON-RPC omits address detail fields */ + EXPECT_TRUE(response.find("\"ipaddress\"") == std::string::npos); + EXPECT_TRUE(response.find("\"ula\"") == std::string::npos); + EXPECT_TRUE(response.find("\"gateway\"") == std::string::npos); + EXPECT_TRUE(response.find("\"autoconfig\":true") != std::string::npos); +} +TEST_F(NetworkManagerTest, GetIPSettings_swapIpCache_returns_old_keys) +{ + /* Verify swapIpCache returns the old global address keys */ + Plugin::IpFamilyCache cache1; + cache1.valid = true; + cache1.globalAddresses["192.168.1.10"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); + cache1.globalAddresses["192.168.1.20"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); + Plugin::_instance->swapIpCache("eth0", "IPv4", cache1); + + /* Now swap with a new cache and check old keys are returned */ + Plugin::IpFamilyCache cache2; + cache2.valid = true; + cache2.globalAddresses["10.0.0.1"] = Plugin::GlobalAddressInfo(8, Plugin::ADDR_GLOBAL); + std::set oldKeys = Plugin::_instance->swapIpCache("eth0", "IPv4", cache2); + + EXPECT_EQ(oldKeys.size(), 2u); + EXPECT_TRUE(oldKeys.count("192.168.1.10") == 1); + EXPECT_TRUE(oldKeys.count("192.168.1.20") == 1); + + /* Verify the new cache is now active */ EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); - std::string expectedResponse = - _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\",\"autoconfig\":true,\"success\":true}"); - EXPECT_EQ(response, expectedResponse); - - g_object_unref(ethActiveConn); - g_ptr_array_free(dummyActiveConn, TRUE); + EXPECT_TRUE(response.find("\"ipaddress\":\"10.0.0.1\"") != std::string::npos); } -TEST_F(NetworkManagerTest, GetIPSettings_ipv4_config_valid) +TEST_F(NetworkManagerTest, GetIPSettings_separate_ipv4_ipv6_caches) { - NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - NMRemoteConnection* retConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - NMIPAddress* ipv4Addr = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - - GPtrArray* dummyActiveConn = g_ptr_array_new(); - GPtrArray* ipvAddr = g_ptr_array_new(); - g_ptr_array_add(dummyActiveConn, ethActiveConn); - g_ptr_array_add(ipvAddr, ipv4Addr); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_dhcp_config_get_one_option(::testing::_, ::testing::_)) - .WillOnce(::testing::Return("192.168.1.11")); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_dhcp4_config(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100170))); - - const char* fakeDnsServers[] = {"8.8.8.8", "8.8.4.4", nullptr}; - EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_nameservers(::testing::_)) - .WillOnce(::testing::Return(fakeDnsServers)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_gateway(::testing::_)) - .WillOnce(::testing::Return("192.168.1.0")); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_address_get_address(::testing::_)) - .WillOnce(::testing::Return("192.168.1.2")); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_addresses(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(ipvAddr))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_ip4_config(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100171))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_connection_get_interface_name(::testing::_)) - .WillOnce(::testing::Return("eth0")); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100173))); + /* IPv4 and IPv6 caches for the same interface should be independent */ + Plugin::IpFamilyCache cache4; + cache4.valid = true; + cache4.autoconfig = true; + cache4.globalAddresses["192.168.1.50"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); + Plugin::_instance->swapIpCache("eth0", "IPv4", cache4); + + Plugin::IpFamilyCache cache6; + cache6.valid = true; + cache6.autoconfig = true; + cache6.globalAddresses["2001:db8::50"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL); + cache6.uniqueLocalAddresses.insert("fd12::50"); + Plugin::_instance->swapIpCache("eth0", "IPv6", cache6); + + /* Query IPv4 */ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv4\"}"), response)); + EXPECT_TRUE(response.find("\"ipaddress\":\"192.168.1.50\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ipversion\":\"IPv4\"") != std::string::npos); + + /* Query IPv6 */ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv6\"}"), response)); + EXPECT_TRUE(response.find("\"ipaddress\":\"2001:db8::50\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ipversion\":\"IPv6\"") != std::string::npos); + EXPECT_TRUE(response.find("\"ula\":\"fd12::50\"") != std::string::npos); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) - .WillOnce(::testing::Return(retConn)) - .WillOnce(::testing::Return(reinterpret_cast(NULL))); +TEST_F(NetworkManagerTest, GetIPSettings_cache_cleared) +{ + /* Populate cache, then swap with empty/invalid cache — simulates disconnect */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.globalAddresses["192.168.1.99"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); + Plugin::_instance->swapIpCache("eth0", "IPv4", cache); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + /* Verify it's there */ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); + EXPECT_TRUE(response.find("\"ipaddress\":\"192.168.1.99\"") != std::string::npos); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); + /* Clear cache by swapping with default (valid=false) */ + Plugin::IpFamilyCache empty; + Plugin::_instance->swapIpCache("eth0", "IPv4", empty); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); - EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); - EXPECT_TRUE(response.find("\"secondarydns\":\"8.8.4.4\"") != std::string::npos); - EXPECT_TRUE(response.find("\"primarydns\":\"8.8.8.8\"") != std::string::npos); - EXPECT_TRUE(response.find("\"interface\":\"eth0\"") != std::string::npos); - EXPECT_TRUE(response.find("\"ipaddress\":\"192.168.1.2\"") != std::string::npos); - EXPECT_TRUE(response.find("\"ula\":\"\"") != std::string::npos); - EXPECT_TRUE(response.find("\"dhcpserver\":\"192.168.1.11\"") != std::string::npos); - EXPECT_TRUE(response.find("\"gateway\":\"192.168.1.0\"") != std::string::npos); - - g_object_unref(ethActiveConn); - g_object_unref(retConn); - g_object_unref(ipv4Addr); - g_ptr_array_free(dummyActiveConn, TRUE); - g_ptr_array_free(ipvAddr, TRUE); + EXPECT_TRUE(response.find("\"ipaddress\"") == std::string::npos); } -TEST_F(NetworkManagerTest, GetIPSettings_ipv6_config_valid) -{ - NMActiveConnection *ethActiveConn = static_cast(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL)); - NMRemoteConnection* retConn = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - NMIPAddress* ipv6Addr = static_cast(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL)); - - GPtrArray* dummyActiveConn = g_ptr_array_new(); - GPtrArray* ipvAddr = g_ptr_array_new(); - g_ptr_array_add(dummyActiveConn, ethActiveConn); - g_ptr_array_add(ipvAddr, ipv6Addr); - g_ptr_array_add(ipvAddr, reinterpret_cast(0x100176)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_dhcp_config_get_one_option(::testing::_, ::testing::_)) - .WillOnce(::testing::Return("2001:db8::1")); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_dhcp6_config(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100170))); - - const char* fakeDnsServers[] = {"2001:4860:4860::8888", "2001:4860:4860::8844", nullptr}; - EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_nameservers(::testing::_)) - .WillOnce(::testing::Return(fakeDnsServers)); +/* ──────────────────────────────────────────────────────────────────────────── + * Utility function tests — isIPv4LinkLocal, isIPv6LinkLocal, isIPv6ULA, + * isIPv6MacBased (which exercises parseMac internally). + * ──────────────────────────────────────────────────────────────────────────── */ - EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_gateway(::testing::_)) - .WillOnce(::testing::Return("2001:4860:4860::1")); +TEST_F(NetworkManagerTest, isIPv4LinkLocal_true_for_169_254) +{ + EXPECT_TRUE(Plugin::isIPv4LinkLocal("169.254.0.1")); + EXPECT_TRUE(Plugin::isIPv4LinkLocal("169.254.255.255")); + EXPECT_TRUE(Plugin::isIPv4LinkLocal("169.254.100.50")); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_address_get_prefix(::testing::_)) - .WillOnce(::testing::Return(64)); +TEST_F(NetworkManagerTest, isIPv4LinkLocal_false_for_non_link_local) +{ + EXPECT_FALSE(Plugin::isIPv4LinkLocal("192.168.1.1")); + EXPECT_FALSE(Plugin::isIPv4LinkLocal("10.0.0.1")); + EXPECT_FALSE(Plugin::isIPv4LinkLocal("169.253.255.255")); + EXPECT_FALSE(Plugin::isIPv4LinkLocal("169.255.0.1")); + EXPECT_FALSE(Plugin::isIPv4LinkLocal("0.0.0.0")); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_address_get_address(::testing::_)) - .WillOnce(::testing::Return("2001:db8:1:2:3:4:5:6")) - .WillOnce(::testing::Return("fe80::1234:5678:abcd:ef01")); +TEST_F(NetworkManagerTest, isIPv4LinkLocal_false_for_invalid_input) +{ + EXPECT_FALSE(Plugin::isIPv4LinkLocal("")); + EXPECT_FALSE(Plugin::isIPv4LinkLocal("not_an_ip")); + EXPECT_FALSE(Plugin::isIPv4LinkLocal("fe80::1")); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_ip_config_get_addresses(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(ipvAddr))); +TEST_F(NetworkManagerTest, isIPv6LinkLocal_true_for_fe80) +{ + EXPECT_TRUE(Plugin::isIPv6LinkLocal("fe80::1")); + EXPECT_TRUE(Plugin::isIPv6LinkLocal("fe80::abcd:1234:5678:9abc")); + EXPECT_TRUE(Plugin::isIPv6LinkLocal("fe80::ffff:ffff:ffff:ffff")); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_ip6_config(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100171))); +TEST_F(NetworkManagerTest, isIPv6LinkLocal_false_for_non_link_local) +{ + EXPECT_FALSE(Plugin::isIPv6LinkLocal("2001:db8::1")); + EXPECT_FALSE(Plugin::isIPv6LinkLocal("fd00::1")); + EXPECT_FALSE(Plugin::isIPv6LinkLocal("::1")); + EXPECT_FALSE(Plugin::isIPv6LinkLocal("fc00::1")); + EXPECT_FALSE(Plugin::isIPv6LinkLocal("fec0::1")); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_setting_connection_get_interface_name(::testing::_)) - .WillOnce(::testing::Return("eth0")); +TEST_F(NetworkManagerTest, isIPv6LinkLocal_false_for_invalid_input) +{ + EXPECT_FALSE(Plugin::isIPv6LinkLocal("")); + EXPECT_FALSE(Plugin::isIPv6LinkLocal("not_an_ip")); + EXPECT_FALSE(Plugin::isIPv6LinkLocal("169.254.1.1")); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_setting_connection(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100173))); +TEST_F(NetworkManagerTest, isIPv6ULA_true_for_fc_fd) +{ + EXPECT_TRUE(Plugin::isIPv6ULA("fc00::1")); + EXPECT_TRUE(Plugin::isIPv6ULA("fd00::1")); + EXPECT_TRUE(Plugin::isIPv6ULA("fd12:3456:789a::1")); + EXPECT_TRUE(Plugin::isIPv6ULA("fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_active_connection_get_connection(::testing::_)) - .WillOnce(::testing::Return(retConn)) - .WillOnce(::testing::Return(reinterpret_cast(NULL))); +TEST_F(NetworkManagerTest, isIPv6ULA_false_for_non_ula) +{ + EXPECT_FALSE(Plugin::isIPv6ULA("2001:db8::1")); + EXPECT_FALSE(Plugin::isIPv6ULA("fe80::1")); + EXPECT_FALSE(Plugin::isIPv6ULA("::1")); + EXPECT_FALSE(Plugin::isIPv6ULA("fb00::1")); + EXPECT_FALSE(Plugin::isIPv6ULA("fe00::1")); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); +TEST_F(NetworkManagerTest, isIPv6ULA_false_for_invalid_input) +{ + EXPECT_FALSE(Plugin::isIPv6ULA("")); + EXPECT_FALSE(Plugin::isIPv6ULA("garbage")); + EXPECT_FALSE(Plugin::isIPv6ULA("192.168.1.1")); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_active_connections(::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(dummyActiveConn))); +TEST_F(NetworkManagerTest, isIPv6MacBased_true_for_eui64_colon_mac) +{ + /* MAC AA:BB:CC:DD:EE:FF → EUI-64: A8:BB:CC:FF:FE:DD:EE:FF + (byte 0: 0xAA ^ 0x02 = 0xA8, insert FF:FE in middle) */ + EXPECT_TRUE(Plugin::isIPv6MacBased("2001:db8::a8bb:ccff:fedd:eeff", "AA:BB:CC:DD:EE:FF")); +} - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_, ::testing::_)) - .WillOnce(::testing::Return(reinterpret_cast(0x100178))); +TEST_F(NetworkManagerTest, isIPv6MacBased_true_for_eui64_plain_mac) +{ + /* Same MAC in plain hex format */ + EXPECT_TRUE(Plugin::isIPv6MacBased("2001:db8::a8bb:ccff:fedd:eeff", "aabbccddeeff")); +} - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv6\"}"), response)); +TEST_F(NetworkManagerTest, isIPv6MacBased_false_for_non_eui64) +{ + /* Address that doesn't match the MAC's EUI-64 */ + EXPECT_FALSE(Plugin::isIPv6MacBased("2001:db8::1234:5678:9abc:def0", "AA:BB:CC:DD:EE:FF")); +} - EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); - EXPECT_TRUE(response.find("\"ipversion\":\"IPv6\"") != std::string::npos); - EXPECT_TRUE(response.find("\"secondarydns\":\"2001:4860:4860::8844\"") != std::string::npos); - EXPECT_TRUE(response.find("\"primarydns\":\"2001:4860:4860::8888\"") != std::string::npos); - EXPECT_TRUE(response.find("\"interface\":\"eth0\"") != std::string::npos); - EXPECT_TRUE(response.find("\"ipaddress\":\"2001:db8:1:2:3:4:5:6\"") != std::string::npos); - EXPECT_TRUE(response.find("\"ula\":\"fe80::1234:5678:abcd:ef01\"") != std::string::npos); - EXPECT_TRUE(response.find("\"prefix\":64") != std::string::npos); - EXPECT_TRUE(response.find("\"dhcpserver\":\"2001:db8::1\"") != std::string::npos); - EXPECT_TRUE(response.find("\"gateway\":\"2001:4860:4860::1\"") != std::string::npos); +TEST_F(NetworkManagerTest, isIPv6MacBased_false_for_privacy_address) +{ + /* Privacy extension address — random interface ID, not MAC-based */ + EXPECT_FALSE(Plugin::isIPv6MacBased("2001:db8::4f2a:8c91:e3d7:b560", "00:11:22:33:44:55")); +} - g_object_unref(ethActiveConn); - g_object_unref(retConn); - g_object_unref(ipv6Addr); - g_ptr_array_free(dummyActiveConn, TRUE); - g_ptr_array_free(ipvAddr, TRUE); +TEST_F(NetworkManagerTest, isIPv6MacBased_false_for_invalid_inputs) +{ + EXPECT_FALSE(Plugin::isIPv6MacBased("", "AA:BB:CC:DD:EE:FF")); + EXPECT_FALSE(Plugin::isIPv6MacBased("2001:db8::1", "")); + EXPECT_FALSE(Plugin::isIPv6MacBased("not_ipv6", "AA:BB:CC:DD:EE:FF")); + EXPECT_FALSE(Plugin::isIPv6MacBased("2001:db8::1", "not_a_mac")); + EXPECT_FALSE(Plugin::isIPv6MacBased("192.168.1.1", "AA:BB:CC:DD:EE:FF")); } TEST_F(NetworkManagerTest, SetInterfaceState_deviceFailed_wlan0) diff --git a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp index c587688a6..dfecf5fd6 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp @@ -42,6 +42,8 @@ using namespace WPEFramework; using ::testing::NiceMock; +namespace WPEFramework { namespace Plugin { extern NetworkManagerImplementation* _instance; } } + class NetworkManagerEventTest : public ::testing::Test { protected: Core::ProxyType plugin; @@ -208,31 +210,6 @@ TEST_F(NetworkManagerEventTest, onInterfaceStateChangeCb) WPEFramework::Plugin::GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_DISABLED, "eth0"); } -TEST_F(NetworkManagerEventTest, onAddressChangeCb) -{ - // Test acquiring IPv4 address - WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth0", "192.168.1.100", true, false); - - // Test acquiring IPv6 address - WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth0", "2001:db8::1", true, true); - - // Test acquiring same IPv6 address again (should skip posting) - WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth0", "2001:db8::1", true, true); - - // Test acquiring different IPv6 address - WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth0", "2001:db8::2", true, true); - - // Test losing IPv4 address - WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth0", "", false, false); - - // Test losing IPv6 address - WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth0", "", false, true); - - // Test losing IP on interface with empty cache (should skip posting) - WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth1", "", false, false); - WPEFramework::Plugin::GnomeNetworkManagerEvents::onAddressChangeCb("eth1", "", false, true); -} - TEST_F(NetworkManagerEventTest, onAvailableSSIDsCb) { GPtrArray* fakeDevices = g_ptr_array_new(); @@ -372,9 +349,9 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_disconnected) { NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) - .WillOnce(::testing::Return("wlan0")); + .WillRepeatedly(::testing::Return("wlan0")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); @@ -384,9 +361,9 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_unmanaged) { NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) - .WillOnce(::testing::Return("wlan0")); + .WillRepeatedly(::testing::Return("wlan0")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); @@ -492,9 +469,9 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_unknown) { NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNKNOWN)); + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_UNKNOWN)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) - .WillOnce(::testing::Return("wlan0")); + .WillRepeatedly(::testing::Return("wlan0")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); @@ -504,9 +481,9 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_unmanaged) { NMDevice *DummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) - .WillOnce(::testing::Return("eth0")); + .WillRepeatedly(::testing::Return("eth0")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); @@ -517,9 +494,9 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_disconnected) { NMDevice *DummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) - .WillOnce(::testing::Return("eth0")); + .WillRepeatedly(::testing::Return("eth0")); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); @@ -564,3 +541,102 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_activated) WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(DummyDevice, nullptr, nullptr); g_object_unref(DummyDevice); } + +/* ──────────────────────────────────────────────────────────────────────────── + * Cache-clearing tests — verify that disconnect events clear the IP cache. + * These test observable behavior (cache state after disconnect) rather than + * internal NM API call sequences, so they remain stable across refactors. + * ──────────────────────────────────────────────────────────────────────────── */ + +TEST_F(NetworkManagerEventTest, disconnect_clears_ipv4_cache_eth0) +{ + /* Pre-populate the IPv4 cache for eth0 */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.globalAddresses["192.168.1.50"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); + cache.gateway = "192.168.1.1"; + Plugin::_instance->swapIpCache("eth0", "IPv4", cache); + + /* Verify cache is populated */ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\"}"), response)); + EXPECT_TRUE(response.find("\"ipaddress\":\"192.168.1.50\"") != std::string::npos); + + /* Trigger eth0 disconnect — refreshIpFamilyCache runs with skipRead=true, + swapping an empty cache and clearing the old addresses. */ + NMDevice *DummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("eth0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(DummyDevice, nullptr, nullptr); + g_object_unref(DummyDevice); + + /* Cache should now be empty — GetIPSettings returns success but no address fields */ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\"}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\"") == std::string::npos); +} + +TEST_F(NetworkManagerEventTest, disconnect_clears_ipv6_cache_wlan0) +{ + /* Pre-populate the IPv6 cache for wlan0 */ + Plugin::IpFamilyCache cache; + cache.valid = true; + cache.globalAddresses["2001:db8::1"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL); + cache.gateway = "fe80::1"; + Plugin::_instance->swapIpCache("wlan0", "IPv6", cache); + + /* Verify cache is populated */ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"wlan0\",\"ipversion\":\"IPv6\"}"), response)); + EXPECT_TRUE(response.find("\"ipaddress\":\"2001:db8::1\"") != std::string::npos); + + /* Trigger wlan0 disconnect */ + NMDevice *DummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("wlan0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); + g_object_unref(DummyDevice); + + /* Cache should now be empty */ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"wlan0\",\"ipversion\":\"IPv6\"}"), response)); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("\"ipaddress\"") == std::string::npos); +} + +TEST_F(NetworkManagerEventTest, disconnect_clears_both_ip_family_caches) +{ + /* Pre-populate both IPv4 and IPv6 caches for eth0 */ + Plugin::IpFamilyCache cache4; + cache4.valid = true; + cache4.globalAddresses["192.168.1.50"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); + Plugin::_instance->swapIpCache("eth0", "IPv4", cache4); + + Plugin::IpFamilyCache cache6; + cache6.valid = true; + cache6.globalAddresses["2001:db8::99"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL); + Plugin::_instance->swapIpCache("eth0", "IPv6", cache6); + + /* Trigger disconnect — refreshIpFamilyCache is called for BOTH families */ + NMDevice *DummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillRepeatedly(::testing::Return(NM_DEVICE_STATE_DISCONNECTED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillRepeatedly(::testing::Return("eth0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(DummyDevice, nullptr, nullptr); + g_object_unref(DummyDevice); + + /* Both families should be cleared */ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\"}"), response)); + EXPECT_TRUE(response.find("\"ipaddress\"") == std::string::npos); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv6\"}"), response)); + EXPECT_TRUE(response.find("\"ipaddress\"") == std::string::npos); +} diff --git a/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp b/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp index e47f24fbc..b550b3d6f 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp @@ -158,7 +158,7 @@ TEST_F(NetworkManagerInitTest, platformInit) EXPECT_EQ(response, _T("{\"success\":false}")); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"wlan0\"}"), response)); - EXPECT_EQ(response, _T("{\"success\":false}")); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetHostname"), _T("{\"hostname\":\"test-host\"}"), response)); EXPECT_EQ(response, _T("{\"success\":false}")); From cc1bc19080875ffe5693d29ec2c488b8a732b364 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Tue, 9 Jun 2026 15:18:42 -0400 Subject: [PATCH 243/271] Release of 3.2.0 Release of 3.2.0 --- CHANGELOG.md | 4 ++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0632cc531..d0d819295 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [3.2.0] - 2026-06-09 +### Added +- Implemented IP Caching logic to avoid multiple hard fetches from Gnome & invalidating the cache on change. + ## [3.1.0] - 2026-06-08 ### Changed - Handled Power State changes within NetworkManager as below, diff --git a/CMakeLists.txt b/CMakeLists.txt index 750e5657a..7406368de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 3) -set(VERSION_MINOR 1) +set(VERSION_MINOR 2) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 00471428f..c5b90912d 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "3.1.0" + "version": "3.2.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 1b4a5d111..cd07ba67c 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 3.1.0** +**Version: 3.2.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.1.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.2.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From df3edf0292d67673625e2b54ccb062acb934d95d Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 12 Jun 2026 09:26:38 -0400 Subject: [PATCH 244/271] RDKEMW-19267: WPEFramework crash observed with VSS increase (#315) Reason for Change: The persistent m_nmClient created during platform_init() subscribed to all D-Bus PropertyChanged signals from the NetworkManager daemon. Its isolated m_nmContext was never continuously drained, causing every signal (device state changes, DHCP renewals, WiFi scan updates, DNS changes) to queue indefinitely as GSource objects. This produced memory leak that grew gradually over time. The fix adopts the same create-per-call pattern already used by wifiManager: each proxy API call creates a temporary NMClient, uses it for the synchronous libnm query, then destroys it via the contextBusyWatcher drain loop. Between calls no client exists, so no D-Bus subscription is active and no signals accumulate. No GMainLoop or background thread is required since all proxy operations are synchronous. Test Procedure: Longrun scenario and observe for memory leaks Priority: P1 Risks: Medium --- plugin/NetworkManagerImplementation.h | 4 +- plugin/gnome/NetworkManagerGnomeProxy.cpp | 218 +++++++++++++--------- 2 files changed, 134 insertions(+), 88 deletions(-) diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 6f4ab5bd1..65baa0b11 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -40,7 +40,6 @@ using namespace std; #include "NetworkManagerPowerClient.h" /* Forward declarations to avoid pulling GLib/libnm headers into this header */ -typedef struct _NMClient NMClient; typedef struct _GMainContext GMainContext; /* @@ -390,8 +389,7 @@ namespace WPEFramework std::atomic m_ethDisconnectedForSleep; std::atomic m_wlanDisconnectedForSleep; std::string m_lastConnectedSSID; - NMClient *m_nmClient{nullptr}; /* proxy NMClient — bound to m_nmContext */ - GMainContext *m_nmContext{nullptr}; /* isolated context, not the global default */ + GMainContext *m_nmContext{nullptr}; /* isolated context for per-call NMClient creation */ mutable ConnectivityMonitor connectivityMonitor; string getDefaultInterface() const diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 234a8df9b..932dd9a82 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -30,6 +30,40 @@ namespace WPEFramework { namespace Plugin { + /* + * Per-call NMClient helpers (same pattern as wifiManager). + * A fresh NMClient is created for each proxy API call and destroyed + * immediately after use, so no D-Bus signals accumulate between calls. + */ + static NMClient* createProxyClient(GMainContext *ctx) + { + GError *error = NULL; + g_main_context_push_thread_default(ctx); + NMClient *client = nm_client_new(NULL, &error); + g_main_context_pop_thread_default(ctx); + if (!client) { + if (error) { + NMLOG_ERROR("Failed to create NMClient: %s", error->message); + g_error_free(error); + } + } + return client; + } + + static void deleteProxyClient(NMClient *client) + { + if (!client) + return; + GMainContext *context = g_main_context_ref(nm_client_get_main_context(client)); + GObject *contextBusyWatcher = nm_client_get_context_busy_watcher(client); + g_object_add_weak_pointer(contextBusyWatcher, (gpointer *)&contextBusyWatcher); + g_clear_object(&client); + while (contextBusyWatcher) { + g_main_context_iteration(context, TRUE); + } + g_main_context_unref(context); + } + wifiManager *wifi = nullptr; GnomeNetworkManagerEvents *nmEvent = nullptr; NetworkManagerImplementation* _instance = nullptr; @@ -196,11 +230,8 @@ namespace WPEFramework /* @brief Set the dhcp hostname */ uint32_t NetworkManagerImplementation::SetHostname(const string& hostname /* @in */) { - const GPtrArray *connections = NULL; - NMConnection *connection = NULL; - - if (m_nmClient == nullptr) { - NMLOG_ERROR("NMClient is NULL"); + if (m_nmContext == nullptr) { + NMLOG_ERROR("NMContext is NULL"); return Core::ERROR_GENERAL; } @@ -210,10 +241,17 @@ namespace WPEFramework return Core::ERROR_BAD_REQUEST; } - connections = nm_client_get_connections(m_nmClient); + NMClient *client = createProxyClient(m_nmContext); + if (client == nullptr) { + NMLOG_ERROR("Failed to create NMClient for SetHostname"); + return Core::ERROR_GENERAL; + } + + const GPtrArray *connections = nm_client_get_connections(client); if (connections == NULL || connections->len == 0) { NMLOG_ERROR("Could not get nm connections"); + deleteProxyClient(client); return Core::ERROR_GENERAL; } @@ -221,7 +259,7 @@ namespace WPEFramework for (uint32_t i = 0; i < connections->len; i++) { - connection = NM_CONNECTION(connections->pdata[i]); + NMConnection *connection = NM_CONNECTION(connections->pdata[i]); if(connection != NULL) { const char *iface = nm_connection_get_interface_name(connection); @@ -240,6 +278,7 @@ namespace WPEFramework if(!setHostname(connection, hostname)) { NMLOG_ERROR("Failed to set hostname for connection at index %d", i); + deleteProxyClient(client); return Core::ERROR_GENERAL; } } @@ -247,6 +286,8 @@ namespace WPEFramework NMLOG_ERROR("Connection at index %d is NULL", i); } + deleteProxyClient(client); + // Write the hostname to persistent storage nmUtils::writePersistentHostname(hostname); @@ -255,7 +296,6 @@ namespace WPEFramework void NetworkManagerImplementation::platform_deinit() { - if(m_nmClient) { g_object_unref(m_nmClient); m_nmClient = nullptr; } if(m_nmContext) { g_main_context_unref(m_nmContext); m_nmContext = nullptr; } } @@ -270,38 +310,31 @@ namespace WPEFramework void NetworkManagerImplementation::platform_init() { ::_instance = this; - GError *error = NULL; - // initialize the NMClient object - // Create an isolated GMainContext so this m_nmClient's D-Bus socket is NOT a - // source on the global default context. The event thread runs the default - // context via g_main_loop_run(); without isolation it would own and mutate - // this m_nmClient's GObjects concurrently with the RPC thread. + // Create an isolated GMainContext for per-call NMClient creation. m_nmContext = g_main_context_new(); - g_main_context_push_thread_default(m_nmContext); - m_nmClient = nm_client_new(NULL, &error); - g_main_context_pop_thread_default(m_nmContext); - if (m_nmClient == NULL) { - if (error) { - NMLOG_FATAL("Error initializing NMClient: %s", error->message); - g_error_free(error); - } - if (m_nmContext) { - g_main_context_unref(m_nmContext); - m_nmContext = nullptr; - } + + // Create a temporary client for one-time init work + NMClient *initClient = createProxyClient(m_nmContext); + if (initClient == NULL) { + NMLOG_FATAL("Error initializing NMClient during platform_init"); + g_main_context_unref(m_nmContext); + m_nmContext = nullptr; return; } nmUtils::getDeviceProperties(); // get interface name form '/etc/device.proprties' - modifyDefaultConnConfig(m_nmClient); - NMDeviceState ethState = ifaceState(m_nmClient, nmUtils::ethIface()); + modifyDefaultConnConfig(initClient); + NMDeviceState ethState = ifaceState(initClient, nmUtils::ethIface()); if(ethState > NM_DEVICE_STATE_DISCONNECTED && ethState < NM_DEVICE_STATE_DEACTIVATING) setDefaultInterface(nmUtils::ethIface()); else setDefaultInterface(nmUtils::wlanIface()); NMLOG_INFO("default interface is %s", getDefaultInterface().c_str()); + + deleteProxyClient(initClient); + // getInitialConnectionState function not called here, as event monitor will report the initial state nmEvent = GnomeNetworkManagerEvents::getInstance(); nmEvent->startNetworkMangerEventMonitor(); @@ -314,20 +347,22 @@ namespace WPEFramework std::vector interfaceList; std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); - if(m_nmClient == nullptr) { - NMLOG_FATAL("NMClient is null"); + if(m_nmContext == nullptr) { + NMLOG_FATAL("NMContext is null"); return Core::ERROR_GENERAL; } - if (m_nmContext) { - for (int i = 0; i < 100 && g_main_context_iteration(m_nmContext, FALSE); ++i){ - // Intentional empty body: just flushing the event queue - } + NMClient *client = createProxyClient(m_nmContext); + if (client == nullptr) { + NMLOG_FATAL("Failed to create NMClient for GetAvailableInterfaces"); + return Core::ERROR_GENERAL; } - GPtrArray *devices = const_cast(nm_client_get_devices(m_nmClient)); + + GPtrArray *devices = const_cast(nm_client_get_devices(client)); if (devices == NULL) { NMLOG_ERROR("Failed to get device list."); - return Core::ERROR_GENERAL; + deleteProxyClient(client); + return rc; } for (guint j = 0; j < devices->len; j++) @@ -373,6 +408,11 @@ namespace WPEFramework } } + deleteProxyClient(client); + + if (rc != Core::ERROR_NONE) + return rc; + using Implementation = RPC::IteratorType; interfacesItr = Core::Service::Create(interfaceList); if(interfacesItr == nullptr) { @@ -454,9 +494,9 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) { - if(m_nmClient == nullptr) + if(m_nmContext == nullptr) { - NMLOG_WARNING("NMClient is null"); + NMLOG_WARNING("NMContext is null"); return Core::ERROR_RPC_CALL_FAILED; } @@ -492,57 +532,62 @@ namespace WPEFramework { NMLOG_INFO("BOOT_MIGRATION detected, deleting all wired NM connections"); - // Bring down the ethernet interface before wiping its connections - // so NM doesn't immediately re-activate them during deletion. - NMDevice *ethDev = nm_client_get_device_by_iface(m_nmClient, interface.c_str()); - if(ethDev) + NMClient *client = createProxyClient(m_nmContext); + if (client != nullptr) { - GError *discError = nullptr; - if(!nm_device_disconnect(ethDev, nullptr, &discError)) + // Bring down the ethernet interface before wiping its connections + // so NM doesn't immediately re-activate them during deletion. + NMDevice *ethDev = nm_client_get_device_by_iface(client, interface.c_str()); + if(ethDev) { - NMLOG_WARNING("Failed to disconnect %s before migration cleanup: %s", - interface.c_str(), - discError ? discError->message : "unknown error"); - if(discError) g_error_free(discError); + GError *discError = nullptr; + if(!nm_device_disconnect(ethDev, nullptr, &discError)) + { + NMLOG_WARNING("Failed to disconnect %s before migration cleanup: %s", + interface.c_str(), + discError ? discError->message : "unknown error"); + if(discError) g_error_free(discError); + } } - } - const GPtrArray *connections = nm_client_get_connections(m_nmClient); - if(connections && connections->len > 0) - { - /* Snapshot the list before iterating: nm_client_get_connections() - * returns an internal array that can be mutated as connections - * are removed, so we must not iterate it while deleting. */ - GPtrArray *snapshot = g_ptr_array_new_full(connections->len, g_object_unref); - for(guint i = 0; i < connections->len; ++i) + const GPtrArray *connections = nm_client_get_connections(client); + if(connections && connections->len > 0) { - NMRemoteConnection *conn = NM_REMOTE_CONNECTION(connections->pdata[i]); - if(!conn) continue; - NMSettingConnection *sCon = nm_connection_get_setting_connection(NM_CONNECTION(conn)); - if(!sCon) continue; - const char *connType = nm_setting_connection_get_connection_type(sCon); - if(g_strcmp0(connType, NM_SETTING_WIRED_SETTING_NAME) != 0) + /* Snapshot the list before iterating: nm_client_get_connections() + * returns an internal array that can be mutated as connections + * are removed, so we must not iterate it while deleting. */ + GPtrArray *snapshot = g_ptr_array_new_full(connections->len, g_object_unref); + for(guint i = 0; i < connections->len; ++i) { - NMLOG_DEBUG("Skipping non-wired connection type: %s", connType ? connType : "null"); - continue; + NMRemoteConnection *conn = NM_REMOTE_CONNECTION(connections->pdata[i]); + if(!conn) continue; + NMSettingConnection *sCon = nm_connection_get_setting_connection(NM_CONNECTION(conn)); + if(!sCon) continue; + const char *connType = nm_setting_connection_get_connection_type(sCon); + if(g_strcmp0(connType, NM_SETTING_WIRED_SETTING_NAME) != 0) + { + NMLOG_DEBUG("Skipping non-wired connection type: %s", connType ? connType : "null"); + continue; + } + g_ptr_array_add(snapshot, g_object_ref(conn)); } - g_ptr_array_add(snapshot, g_object_ref(conn)); - } - for(guint i = 0; i < snapshot->len; ++i) - { - NMRemoteConnection *conn = NM_REMOTE_CONNECTION(snapshot->pdata[i]); - GError *error = nullptr; - if(!nm_remote_connection_delete(conn, nullptr, &error)) + for(guint i = 0; i < snapshot->len; ++i) { - const char *connId = nm_connection_get_id(NM_CONNECTION(conn)); - NMLOG_ERROR("Failed to delete connection %s: %s", - connId ? connId : "", - error ? error->message : "unknown error"); - if(error) g_error_free(error); + NMRemoteConnection *conn = NM_REMOTE_CONNECTION(snapshot->pdata[i]); + GError *error = nullptr; + if(!nm_remote_connection_delete(conn, nullptr, &error)) + { + const char *connId = nm_connection_get_id(NM_CONNECTION(conn)); + NMLOG_ERROR("Failed to delete connection %s: %s", + connId ? connId : "", + error ? error->message : "unknown error"); + if(error) g_error_free(error); + } } + g_ptr_array_unref(snapshot); } - g_ptr_array_unref(snapshot); + deleteProxyClient(client); } } } @@ -604,22 +649,23 @@ namespace WPEFramework return Core::ERROR_GENERAL; } - if(m_nmClient == nullptr) + if(m_nmContext == nullptr) { - NMLOG_WARNING("NMClient is null"); + NMLOG_WARNING("NMContext is null"); return Core::ERROR_RPC_CALL_FAILED; } - if (m_nmContext) { - for (int i = 0; i < 100 && g_main_context_iteration(m_nmContext, FALSE); ++i){ - // Intentional empty body: just flushing the event queue - } + NMClient *client = createProxyClient(m_nmContext); + if (client == nullptr) { + NMLOG_ERROR("Failed to create NMClient for GetInterfaceState"); + return Core::ERROR_RPC_CALL_FAILED; } - GPtrArray *devices = const_cast(nm_client_get_devices(m_nmClient)); + GPtrArray *devices = const_cast(nm_client_get_devices(client)); if (devices == NULL) { NMLOG_ERROR("Failed to get device list."); + deleteProxyClient(client); return Core::ERROR_GENERAL; } @@ -646,6 +692,8 @@ namespace WPEFramework } } + deleteProxyClient(client); + if(isIfaceFound) return Core::ERROR_NONE; else From a6e6508abd1f2f20f87b76e5aa7ce8ba997f612c Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 12 Jun 2026 11:57:38 -0400 Subject: [PATCH 245/271] Release of 3.3.0 Release of 3.3.0 --- CHANGELOG.md | 4 ++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0d819295..d262c5e6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [3.3.0] - 2026-06-12 +### Fixed +- Fixed the memory leak that caused by the persistent m_nmClient and m_nmContext. + ## [3.2.0] - 2026-06-09 ### Added - Implemented IP Caching logic to avoid multiple hard fetches from Gnome & invalidating the cache on change. diff --git a/CMakeLists.txt b/CMakeLists.txt index 7406368de..6d4cc1db6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 3) -set(VERSION_MINOR 2) +set(VERSION_MINOR 3) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index c5b90912d..f79bd812e 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "3.2.0" + "version": "3.3.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index cd07ba67c..3d109f0a0 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 3.2.0** +**Version: 3.3.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.2.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.3.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From dd175a2c9c7b7fbcd8d2ce08c4c2f5f926b23329 Mon Sep 17 00:00:00 2001 From: jincysam87 <167995204+jincysam87@users.noreply.github.com> Date: Wed, 1 Jul 2026 11:27:04 -0400 Subject: [PATCH 246/271] RDKEMW-20574 : Fix the notification locks in networkmanager plugin (#319) Reason for change: Fix the notification locks in networkmanager plugin Priority: P1 Test Procedure: Check the test steps in RDKEMW-20574 Risks: medium Signed-off-by: jincysaramma_sam@comcast.com --- plugin/NetworkManagerImplementation.cpp | 39 +++++++++++++++-------- plugin/NetworkManagerImplementation.h | 3 +- plugin/NetworkManagerLogger.h | 2 +- plugin/gnome/NetworkManagerGnomeProxy.cpp | 19 +++++++---- plugin/rdk/NetworkManagerRDKProxy.cpp | 2 ++ 5 files changed, 43 insertions(+), 22 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index b10b375b5..1beffab6c 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -597,14 +597,16 @@ namespace WPEFramework return; } - void NetworkManagerImplementation::filterScanResults(JsonArray &ssids) + void NetworkManagerImplementation::filterScanResults(JsonArray &ssids, + const std::vector& filterSsidslist, + const std::vector& filterFrequencies) { JsonArray result; double filterFreq = 0.0; - std::unordered_set scanForSsidsSet(m_filterSsidslist.begin(), m_filterSsidslist.end()); + std::unordered_set scanForSsidsSet(filterSsidslist.begin(), filterSsidslist.end()); // If neither SSID list nor frequency is provided, exit - if (m_filterSsidslist.empty() && m_filterFrequencies.empty()) + if (filterSsidslist.empty() && filterFrequencies.empty()) { NMLOG_DEBUG("Neither SSID nor Frequency is provided. Exiting function."); return; @@ -618,10 +620,10 @@ namespace WPEFramework double frequencyValue = std::stod(frequency); bool ssidMatches = scanForSsidsSet.empty() || scanForSsidsSet.find(ssid) != scanForSsidsSet.end(); - bool freqMatches = m_filterFrequencies.empty(); + bool freqMatches = filterFrequencies.empty(); if (!freqMatches) { - for (const auto& selectedFrequency : m_filterFrequencies) + for (const auto& selectedFrequency : filterFrequencies) { if (selectedFrequency == "ALL") { @@ -738,7 +740,6 @@ namespace WPEFramework void NetworkManagerImplementation::ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface) { - _notificationLock.Lock(); NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); if(currentActiveinterface == "eth0") @@ -754,15 +755,15 @@ namespace WPEFramework // FIXME : This could be the place to define `m_defaultInterface` to incoming `currentActiveinterface`. // m_defaultInterface = currentActiveinterface; - + _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); } + _notificationLock.Unlock(); #if USE_TELEMETRY NMLOG_INFO("NM_INTERFACE_STATUS = Interface changed to %s", currentActiveinterface.c_str()); logTelemetry("NM_INTERFACE_STATUS", "Interface changed to " + currentActiveinterface); -#endif - _notificationLock.Unlock(); +#endif } void NetworkManagerImplementation::ReportIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status) @@ -810,7 +811,6 @@ namespace WPEFramework void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface) { - _notificationLock.Lock(); NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); #if USE_TELEMETRY // Log error only when ethernet is up and there's no internet @@ -823,15 +823,16 @@ namespace WPEFramework logTelemetry("NM_ETHERNET_CONNECTIVITY", "Ethernet connectivity failed"); } #endif + _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onInternetStatusChange(prevState, currState, interface); } + _notificationLock.Unlock(); #if USE_TELEMETRY string stateStr = Core::EnumerateType(currState).Data(); NMLOG_INFO("NM_INTERNET_STATUS = %s", stateStr.c_str()); logTelemetry("NM_INTERNET_STATUS", stateStr); #endif - _notificationLock.Unlock(); } int32_t NetworkManagerImplementation::logSSIDs(Logging level, const JsonArray &ssids) @@ -855,7 +856,6 @@ namespace WPEFramework void NetworkManagerImplementation::ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults) { - _notificationLock.Lock(); string jsonOfWiFiScanResults; string jsonOfFilterScanResults; JsonArray filterResult = arrayofWiFiScanResults; @@ -864,12 +864,23 @@ namespace WPEFramework NMLOG_DEBUG("Discovered %d SSIDs before filtering as,", filterResult.Length()); logSSIDs(LOG_LEVEL_DEBUG, filterResult); - filterScanResults(filterResult); + // Snapshot filter vectors under lock, then release before calling filterScanResults + // to ensure exception-safety (std::stod can throw). + std::vector ssidsSnapshot; + std::vector frequenciesSnapshot; + m_filterVectorsLock.Lock(); + ssidsSnapshot = m_filterSsidslist; + frequenciesSnapshot = m_filterFrequencies; + m_filterVectorsLock.Unlock(); + + // Call filterScanResults outside the lock with snapshots (exception-safe) + filterScanResults(filterResult, ssidsSnapshot, frequenciesSnapshot); filterResult.ToString(jsonOfFilterScanResults); NMLOG_INFO("Posting onAvailableSSIDs event with %d SSIDs as,", filterResult.Length()); logSSIDs(LOG_LEVEL_INFO, filterResult); + _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onAvailableSSIDs(jsonOfFilterScanResults); } @@ -1177,13 +1188,13 @@ namespace WPEFramework m_wlanConnected.store(false); /* Any other state is considered as WiFi not connected. */ } - _notificationLock.Lock(); NMLOG_INFO("Posting onWiFiStateChange (%d)", state); #if USE_TELEMETRY string stateStr = Core::EnumerateType(state).Data(); NMLOG_INFO("NM_WIFI_STATUS = %s", stateStr.c_str()); logTelemetry("NM_WIFI_STATUS", stateStr); #endif + _notificationLock.Lock(); for (const auto callback : _notificationCallbacks) { callback->onWiFiStateChange(state); } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 65baa0b11..b7bffe916 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -338,7 +338,7 @@ namespace WPEFramework void getInitialConnectionState(void); void executeExternally(NetworkEvents event, const string commandToExecute, string& response); void threadEventRegistration(bool iarmInit, bool iarmConnect); - void filterScanResults(JsonArray &ssids); + void filterScanResults(JsonArray &ssids, const std::vector& filterSsidslist, const std::vector& filterFrequencies); void startWiFiSignalQualityMonitor(int interval); void stopWiFiSignalQualityMonitor(); void monitorThreadFunction(int interval); @@ -348,6 +348,7 @@ namespace WPEFramework private: std::list _notificationCallbacks; Core::CriticalSection _notificationLock; + Core::CriticalSection m_filterVectorsLock; string m_publicIP; stun::client stunClient; string m_stunEndpoint; diff --git a/plugin/NetworkManagerLogger.h b/plugin/NetworkManagerLogger.h index 4c35f1abd..b5484c35c 100644 --- a/plugin/NetworkManagerLogger.h +++ b/plugin/NetworkManagerLogger.h @@ -70,7 +70,7 @@ void logPrint(LogLevel level, const char* file, const char* func, int line, cons #define NMLOG_ERROR(FMT, ...) logPrint(NetworkManagerLogger::ERROR_LEVEL, __FILE__, __func__, __LINE__, FMT, ##__VA_ARGS__) #define NMLOG_FATAL(FMT, ...) logPrint(NetworkManagerLogger::FATAL_LEVEL, __FILE__,__func__, __LINE__, FMT, ##__VA_ARGS__) -#define LOG_ENTRY_FUNCTION() { NMLOG_DEBUG("Entering"); } +#define LOG_ENTRY_FUNCTION() { NMLOG_INFO("Entering %s", __func__); } } // namespace NetworkManagerLogger diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 932dd9a82..30d065e87 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -762,9 +762,8 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_RPC_CALL_FAILED; - //Cleared the Existing Store filterred SSID list - m_filterSsidslist.clear(); - m_filterFrequencies.clear(); + std::vector filteredSsids; + std::vector filteredFrequencies; if(ssids) { @@ -773,7 +772,7 @@ namespace WPEFramework { if (!tmpssidlist.empty()) { - m_filterSsidslist.push_back(tmpssidlist.c_str()); + filteredSsids.push_back(tmpssidlist); NMLOG_DEBUG("%s added to SSID filtering", tmpssidlist.c_str()); } else @@ -795,7 +794,7 @@ namespace WPEFramework const string normalizedFrequency = parsedFrequency.Data(); if ((!normalizedFrequency.empty()) && (normalizedFrequency == frequency)) { - m_filterFrequencies.push_back(normalizedFrequency); + filteredFrequencies.push_back(normalizedFrequency); NMLOG_DEBUG("Frequency %s added to scan filtering", normalizedFrequency.c_str()); } else @@ -811,8 +810,16 @@ namespace WPEFramework } } + m_filterVectorsLock.Lock(); + // Replace existing stored filters only after successful parsing/validation. + m_filterSsidslist.clear(); + m_filterFrequencies.clear(); + m_filterSsidslist = filteredSsids; + m_filterFrequencies = filteredFrequencies; + m_filterVectorsLock.Unlock(); + nmEvent->setwifiScanOptions(true); - if(wifi->wifiScanRequest(m_filterSsidslist)) + if(wifi->wifiScanRequest(filteredSsids)) rc = Core::ERROR_NONE; return rc; } diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index b163ae3c0..b6b70e1a2 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -973,6 +973,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { IARM_Result_t retVal = IARM_RESULT_SUCCESS; //Cleared the Existing Store filterred SSID list + m_filterVectorsLock.Lock(); m_filterSsidslist.clear(); m_filterFrequencies.clear(); if(ssids) @@ -994,6 +995,7 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { NMLOG_DEBUG("%s added to Frequency filtering", frequencyList.c_str()); } } + m_filterVectorsLock.Unlock(); memset(¶m, 0, sizeof(param)); From 6d2649657e662204c6ba88b861f0364817804a59 Mon Sep 17 00:00:00 2001 From: Anand73-n Date: Mon, 6 Jul 2026 19:37:44 +0530 Subject: [PATCH 247/271] RDKEMW-20973: reconnect failure on deepsleep wakeup (#321) Reason for change: fix deepsleep reconnect failure due to "wpa_cli status" returning empty BSSID, which cleared last SSID. Test procedure: WiFi should reconnect on DeepSleep wakeup Risks: low Priority: P1 Signed-off-by: Anand N --- plugin/NetworkManagerImplementation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 1beffab6c..c0120534d 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1151,7 +1151,8 @@ namespace WPEFramework GetWiFiSignalQuality(ssid, strength, noise, snr, newSignalQuality); - m_lastConnectedSSID = ssid; // last connected ssid used in wifiConnect + if (!ssid.empty()) + m_lastConnectedSSID = ssid; // last connected ssid used in wifiConnect if (oldSignalQuality != newSignalQuality) { oldSignalQuality = newSignalQuality; From 2c451c787e226f2952e6c91aa6c47b1014c40c5d Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 17 Jul 2026 10:06:21 -0400 Subject: [PATCH 248/271] RDKEMW-21453: LegacyNetworkAPIs logs are not printed under wpeframework logs (#324) * RDKEMW-21453: LegacyNetworkAPIs logs are not printed under wpeframework logs Reason for Change: Fixed the legacy prints not printing issue Test Procedure: Check whether legacy prints are getting printed Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR * Addressed compilation issue * Addressed the legacy prints missing issue * Addressed the legacy prints missing issue --------- Signed-off-by: Gururaaja ESR --- legacy/LegacyNetworkAPIs.cpp | 1 + legacy/LegacyWiFiManagerAPIs.cpp | 1 + plugin/NetworkManager.cpp | 11 +++++------ plugin/NetworkManagerImplementation.cpp | 6 +++--- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/legacy/LegacyNetworkAPIs.cpp b/legacy/LegacyNetworkAPIs.cpp index 071466cdd..4e31974c5 100644 --- a/legacy/LegacyNetworkAPIs.cpp +++ b/legacy/LegacyNetworkAPIs.cpp @@ -96,6 +96,7 @@ namespace WPEFramework const string Network::Initialize(PluginHost::IShell* service ) { + NetworkManagerLogger::Init(); m_service = service; m_service->AddRef(); string message{}; diff --git a/legacy/LegacyWiFiManagerAPIs.cpp b/legacy/LegacyWiFiManagerAPIs.cpp index 9a6573ff5..02c9da61b 100644 --- a/legacy/LegacyWiFiManagerAPIs.cpp +++ b/legacy/LegacyWiFiManagerAPIs.cpp @@ -128,6 +128,7 @@ namespace WPEFramework const string WiFiManager::Initialize(PluginHost::IShell* service ) { + NetworkManagerLogger::Init(); m_service = service; string message{}; diff --git a/plugin/NetworkManager.cpp b/plugin/NetworkManager.cpp index 1049e5035..97e55ee68 100644 --- a/plugin/NetworkManager.cpp +++ b/plugin/NetworkManager.cpp @@ -84,12 +84,6 @@ namespace WPEFramework // Still running inside the main WPEFramework process - the child process will have now been spawned and registered if necessary if (_networkManager != nullptr) { - - // Set the plugin log level - Exchange::INetworkManager::Logging _loglevel; - _networkManager->GetLogLevel(_loglevel); - NetworkManagerLogger::SetLevel(static_cast (_loglevel)); - // Register Notifications SYSLOG(Logging::Startup, (_T("Registering Notification to NetworkManager"))); _networkManager->Register(&_notification); @@ -103,6 +97,11 @@ namespace WPEFramework { SYSLOG(Logging::Startup, (_T("Configuring successful"))); } + + // Set the plugin log level + Exchange::INetworkManager::Logging _loglevel; + _networkManager->GetLogLevel(_loglevel); + NetworkManagerLogger::SetLevel(static_cast (_loglevel)); // Register all custom JSON-RPC methods SYSLOG(Logging::Startup, (_T("Registering JSONRPC Methods"))); RegisterAllMethods(); diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index c0120534d..99c98b397 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -65,7 +65,7 @@ namespace WPEFramework /* Initialize Network Manager */ NetworkManagerLogger::Init(); - NMLOG_INFO((_T("NWMgrPlugin Out-Of-Process Instantiation; SHA: " _T(EXPAND_AND_QUOTE(PLUGIN_BUILD_REFERENCE))))); + SYSLOG(::WPEFramework::Logging::Startup, (_T("NWMgrPlugin Out-Of-Process Instantiation; SHA: ") _T(EXPAND_AND_QUOTE(PLUGIN_BUILD_REFERENCE)))); m_processMonThread = std::thread(&NetworkManagerImplementation::processMonitor, this, NM_PROCESS_MONITOR_INTERVAL_SEC); #if USE_TELEMETRY // Initialize Telemetry T2 for NwMgrPlugin @@ -142,12 +142,12 @@ namespace WPEFramework Configuration config; if(configLine.empty()) { - NMLOG_FATAL("config line : is empty !"); + SYSLOG(::WPEFramework::Logging::Shutdown, (_T("config line is empty"))); return Core::ERROR_GENERAL; } else { - NMLOG_INFO("Loading the incoming configuration : %s", configLine.c_str()); + SYSLOG(::WPEFramework::Logging::Startup, (_T("Loading incoming configuration"))); config.FromString(configLine); } From 13b410248cf98e5b8ee3caceb24d90c7b0e4597c Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Fri, 17 Jul 2026 10:08:26 -0400 Subject: [PATCH 249/271] RDKEMW-21513: Added telemetry T2 event posting for IPv6 public IP (#325) Reason for Change: Posting telemetry T2 event for IPv6 public IP Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- plugin/NetworkManagerImplementation.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 99c98b397..1b3870968 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -384,6 +384,11 @@ namespace WPEFramework NMLOG_INFO("NM_PUBLIC_IPV4 = %s", ipaddress.c_str()); logTelemetry("NM_PUBLIC_IPV4", ipaddress); } + else + { + NMLOG_INFO("NM_PUBLIC_IPV6 = %s", ipaddress.c_str()); + logTelemetry("NM_PUBLIC_IPV6", ipaddress); + } #endif return Core::ERROR_NONE; } From 786d88f16aa24ad122bcd737be9615360ac96578 Mon Sep 17 00:00:00 2001 From: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Date: Fri, 17 Jul 2026 14:49:44 -0400 Subject: [PATCH 250/271] RDKEMW-20646 : Using dedicated Eventing thread to send the events (#322) Reason for change: All the NetworkManager Events are published from the calling thread context; somethings are from NMEvent, NMThread, somethings are from Connectivity thread and WiFiQualityMonitoring thread. When consumer is not responding properly, this will lead to extended lock & Sometimes Gnome NetworkManager Crash. To avoid this, all the events are sent thro dedicated eventing thread. NOTE: The Thread::WorkerPool that is default created by the Thunder is always using the main thread when available even though worker pool is available. So this is of no use. Test Procedure: Verify All the Networking Events Risks: Medium Signed-off-by: Karunakaran A GetLogLevel(_loglevel); NetworkManagerLogger::SetLevel(static_cast (_loglevel)); + // Register all custom JSON-RPC methods SYSLOG(Logging::Startup, (_T("Registering JSONRPC Methods"))); RegisterAllMethods(); diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 1b3870968..1ba0509af 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -67,6 +67,12 @@ namespace WPEFramework NetworkManagerLogger::Init(); SYSLOG(::WPEFramework::Logging::Startup, (_T("NWMgrPlugin Out-Of-Process Instantiation; SHA: ") _T(EXPAND_AND_QUOTE(PLUGIN_BUILD_REFERENCE)))); m_processMonThread = std::thread(&NetworkManagerImplementation::processMonitor, this, NM_PROCESS_MONITOR_INTERVAL_SEC); + + /* Start dedicated event dispatch thread */ + m_eventThreadStop.store(false); + m_eventThread = std::thread(&NetworkManagerImplementation::eventThreadFunction, this); + NMLOG_INFO("Event dispatch thread started"); + #if USE_TELEMETRY // Initialize Telemetry T2 for NwMgrPlugin t2_init("NwMgrPlugin"); @@ -87,6 +93,17 @@ namespace WPEFramework /* Stop WiFi Signal Monitoring */ stopWiFiSignalQualityMonitor(); + /* Stop event dispatch thread */ + { + std::unique_lock lock(m_eventMutex); + m_eventThreadStop.store(true); + m_eventCondVar.notify_one(); + } + if (m_eventThread.joinable()) { + m_eventThread.join(); + NMLOG_INFO("Event dispatch thread stopped"); + } + { std::unique_lock lock(m_processMonMutex); m_processMonThreadStop.store(true); @@ -338,6 +355,7 @@ namespace WPEFramework /* @brief Get the active Interface used for external world communication */ uint32_t NetworkManagerImplementation::GetPrimaryInterface (string& interface /* @out */) { + LOG_ENTRY_FUNCTION(); if(m_ethEnabled.load() && m_ethConnected.load()) interface = "eth0"; else if(m_wlanEnabled.load() && m_wlanConnected.load()) @@ -402,6 +420,7 @@ namespace WPEFramework /* @brief Set the network manager plugin log level */ uint32_t NetworkManagerImplementation::SetLogLevel(const Logging& level /* @in */) { + LOG_ENTRY_FUNCTION(); NetworkManagerLogger::SetLevel(static_cast(level)); platform_logging(static_cast(level)); NMLOG_DEBUG("loglevel %d", level); @@ -411,6 +430,7 @@ namespace WPEFramework /* @brief Get the network manager plugin log level */ uint32_t NetworkManagerImplementation::GetLogLevel(Logging& level /* @out */) { + LOG_ENTRY_FUNCTION(); LogLevel inLevel; NetworkManagerLogger::GetLevel(inLevel); @@ -421,6 +441,7 @@ namespace WPEFramework /* @brief Request for ping and get the response in as event. The GUID used in the request will be returned in the event. */ uint32_t NetworkManagerImplementation::Ping (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const uint16_t timeOutInSeconds /* @in */, const string guid /* @in */, string& response /* @out */) { + LOG_ENTRY_FUNCTION(); char cmd[100] = ""; string tempResult = ""; if (endpoint.empty() || (ipversion != "IPv4" && ipversion != "IPv6")) @@ -452,6 +473,7 @@ namespace WPEFramework /* @brief Request for trace get the response in as event. The GUID used in the request will be returned in the event. */ uint32_t NetworkManagerImplementation::Trace (const string ipversion /* @in */, const string endpoint /* @in */, const uint32_t noOfRequest /* @in */, const string guid /* @in */, string& response /* @out */) { + LOG_ENTRY_FUNCTION(); char cmd[256] = ""; string tempResult = ""; if (endpoint.empty() || (ipversion != "IPv4" && ipversion != "IPv6")) @@ -482,6 +504,7 @@ namespace WPEFramework void NetworkManagerImplementation::executeExternally(NetworkEvents event, const string commandToExecute, string& response) { + LOG_ENTRY_FUNCTION(); FILE *pipe = NULL; string output{}; char buffer[1024]; @@ -579,7 +602,7 @@ namespace WPEFramework } pingResult.ToString(response); - NMLOG_INFO("Response is, %s", response.c_str()); + NMLOG_DEBUG("Response is, %s", response.c_str()); } else if (NETMGR_TRACE == event) { @@ -597,15 +620,16 @@ namespace WPEFramework pclose(pipe); list.ToString(response); - NMLOG_INFO("Response is, %s", response.c_str()); + NMLOG_DEBUG("Response is, %s", response.c_str()); } return; } - void NetworkManagerImplementation::filterScanResults(JsonArray &ssids, - const std::vector& filterSsidslist, - const std::vector& filterFrequencies) + void NetworkManagerImplementation::filterScanResults(JsonArray &ssids, + const std::vector& filterSsidslist, + const std::vector& filterFrequencies) { + LOG_ENTRY_FUNCTION(); JsonArray result; double filterFreq = 0.0; std::unordered_set scanForSsidsSet(filterSsidslist.begin(), filterSsidslist.end()); @@ -674,6 +698,151 @@ namespace WPEFramework return Core::ERROR_NONE; } + + void NetworkManagerImplementation::enqueueEvent(NMPublishEvents event, EventDataVariant&& data) + { + LOG_ENTRY_FUNCTION(); + if (m_eventThreadStop.load(std::memory_order_relaxed)) + { + NMLOG_WARNING("Dropping event %d because event thread is stopping", event); + return; + } + { + std::lock_guard lock(m_eventMutex); + m_eventQueue.push({event, std::move(data)}); + NMLOG_DEBUG("Event %d queued, queue size: %zu", event, m_eventQueue.size()); + } + m_eventCondVar.notify_one(); + } + + void NetworkManagerImplementation::eventThreadFunction() + { + NMLOG_INFO("Event thread started"); + + while (!m_eventThreadStop.load()) { + std::unique_lock lock(m_eventMutex); + + // Wait for events or stop signal + m_eventCondVar.wait(lock, [this] { + return !m_eventQueue.empty() || m_eventThreadStop.load(); + }); + + // Process all queued events + while (!m_eventQueue.empty() && !m_eventThreadStop.load()) { + EventData eventData = std::move(m_eventQueue.front()); + m_eventQueue.pop(); + + // Unlock while processing to avoid blocking new events + lock.unlock(); + + NMLOG_DEBUG("Processing event %d from queue", eventData.event); + dispatchEvent(eventData.event, eventData.data); + + lock.lock(); + } + } + + NMLOG_INFO("Event thread exiting"); + } + + void NetworkManagerImplementation::dispatchEvent(NMPublishEvents event, const EventDataVariant& data) + { + LOG_ENTRY_FUNCTION(); + std::list callbacks; + /* + * Avoid holding _notificationLock while notifying subscribers: callbacks can be slow and may + * call back into NetworkManager, risking deadlock. Take a snapshot of callbacks with an + * extra reference, then release each reference after the invocation. + */ + _notificationLock.Lock(); + for (auto* tmpCB : _notificationCallbacks) { + tmpCB->AddRef(); + callbacks.push_back(tmpCB); + } + _notificationLock.Unlock(); + + switch(event) + { + case NM_ON_INTERFACESTATE_CHANGE: + { + NMLOG_INFO("Publishing onInterfaceStateChange Event"); + const auto& eventData = std::get(data); + for (const auto callback : callbacks) { + callback->onInterfaceStateChange(eventData.state, eventData.interface); + callback->Release(); + } + } + break; + case NM_ON_ACTIVEINTERFACE_CHANGE: + { + NMLOG_INFO("Publishing onActiveInterfaceChange Event"); + const auto& eventData = std::get(data); + for (const auto callback : callbacks) { + callback->onActiveInterfaceChange(eventData.prevActiveInterface, eventData.currentActiveInterface); + callback->Release(); + } + } + break; + case NM_ON_IPADDRESS_CHANGE: + { + NMLOG_INFO("Publishing onIPAddressChange Event"); + const auto& eventData = std::get(data); + for (const auto callback : callbacks) { + callback->onIPAddressChange(eventData.interface, eventData.ipversion, eventData.ipaddress, eventData.status); + callback->Release(); + } + } + break; + case NM_ON_INTERNETSTATUS_CHANGE: + { + NMLOG_INFO("Publishing onInternetStatusChange Event"); + const auto& eventData = std::get(data); + for (const auto callback : callbacks) { + callback->onInternetStatusChange(eventData.prevState, eventData.currState, eventData.interface); + callback->Release(); + } + } + break; + case NM_ON_AVAILABLESSIDS: + { + NMLOG_INFO("Publishing onAvailableSSIDs Event"); + const auto& eventData = std::get(data); + for (const auto callback : callbacks) { + callback->onAvailableSSIDs(eventData.jsonResult); + callback->Release(); + } + } + break; + case NM_ON_WIFISTATE_CHANGE: + { + NMLOG_INFO("Publishing onWiFiStateChange Event"); + const auto& eventData = std::get(data); + for (const auto callback : callbacks) { + callback->onWiFiStateChange(eventData.state); + callback->Release(); + } + } + break; + case NM_ON_WIFISIGNALQUALITY_CHANGE: + { + NMLOG_INFO("Publishing onWiFiSignalQualityChange Event"); + const auto& eventData = std::get(data); + for (const auto callback : callbacks) { + callback->onWiFiSignalQualityChange(eventData.ssid, eventData.strength, eventData.noise, eventData.snr, eventData.quality); + callback->Release(); + } + } + break; + default: + { + for (const auto callback : callbacks) { + callback->Release(); + } + } + break; + } + } + void NetworkManagerImplementation::ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface) { LOG_ENTRY_FUNCTION(); @@ -735,17 +904,17 @@ namespace WPEFramework m_wlanEnabled.store(true); } - _notificationLock.Lock(); - NMLOG_INFO("Posting onInterfaceChange %s - %u", interface.c_str(), (unsigned)state); - for (const auto callback : _notificationCallbacks) { - callback->onInterfaceStateChange(state, interface); + { + InterfaceStateChangeData eventData{state, interface}; + NMLOG_INFO("Posting onInterfaceChange %s - %u", interface.c_str(), (unsigned)state); + enqueueEvent(NM_ON_INTERFACESTATE_CHANGE, std::move(eventData)); } - _notificationLock.Unlock(); + return; } void NetworkManagerImplementation::ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface) { - NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); + LOG_ENTRY_FUNCTION(); if(currentActiveinterface == "eth0") { @@ -758,13 +927,11 @@ namespace WPEFramework m_wlanEnabled.store(true); } - // FIXME : This could be the place to define `m_defaultInterface` to incoming `currentActiveinterface`. - // m_defaultInterface = currentActiveinterface; - _notificationLock.Lock(); - for (const auto callback : _notificationCallbacks) { - callback->onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); + { + ActiveInterfaceChangeData eventData{prevActiveInterface, currentActiveinterface}; + NMLOG_INFO("Posting onActiveInterfaceChange %s", currentActiveinterface.c_str()); + enqueueEvent(NM_ON_ACTIVEINTERFACE_CHANGE, std::move(eventData)); } - _notificationLock.Unlock(); #if USE_TELEMETRY NMLOG_INFO("NM_INTERFACE_STATUS = Interface changed to %s", currentActiveinterface.c_str()); logTelemetry("NM_INTERFACE_STATUS", "Interface changed to " + currentActiveinterface); @@ -804,19 +971,17 @@ namespace WPEFramework NMLOG_DEBUG("No need to trigger connectivity monitor interface is %s", interface.c_str()); } - _notificationLock.Lock(); - NMLOG_INFO("Posting onIPAddressChange %s: %s %s %s", - (Exchange::INetworkManager::IP_ACQUIRED == status) ? "IP acquired" : "IP lost", - interface.c_str(), ipversion.c_str(), ipaddress.c_str()); - for (const auto callback : _notificationCallbacks) { - callback->onIPAddressChange(interface, ipversion, ipaddress, status); + { + IPAddressChangeData eventData{interface, ipversion, ipaddress, status}; + NMLOG_INFO("Posting onIPAddressChange %s: %s %s %s", (Exchange::INetworkManager::IP_ACQUIRED == status) ? "IP acquired" : "IP lost", + interface.c_str(), ipversion.c_str(), ipaddress.c_str()); + enqueueEvent(NM_ON_IPADDRESS_CHANGE, std::move(eventData)); } - _notificationLock.Unlock(); } void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface) { - NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); + LOG_ENTRY_FUNCTION(); #if USE_TELEMETRY // Log error only when ethernet is up and there's no internet if(currState == Exchange::INetworkManager::INTERNET_NOT_AVAILABLE && @@ -828,11 +993,12 @@ namespace WPEFramework logTelemetry("NM_ETHERNET_CONNECTIVITY", "Ethernet connectivity failed"); } #endif - _notificationLock.Lock(); - for (const auto callback : _notificationCallbacks) { - callback->onInternetStatusChange(prevState, currState, interface); + { + InternetStatusChangeData eventData{prevState, currState, interface}; + NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); + enqueueEvent(NM_ON_INTERNETSTATUS_CHANGE, std::move(eventData)); } - _notificationLock.Unlock(); + #if USE_TELEMETRY string stateStr = Core::EnumerateType(currState).Data(); NMLOG_INFO("NM_INTERNET_STATUS = %s", stateStr.c_str()); @@ -842,6 +1008,7 @@ namespace WPEFramework int32_t NetworkManagerImplementation::logSSIDs(Logging level, const JsonArray &ssids) { + LOG_ENTRY_FUNCTION(); Logging inLevel; GetLogLevel(inLevel); if (level > inLevel) @@ -861,6 +1028,7 @@ namespace WPEFramework void NetworkManagerImplementation::ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults) { + LOG_ENTRY_FUNCTION(); string jsonOfWiFiScanResults; string jsonOfFilterScanResults; JsonArray filterResult = arrayofWiFiScanResults; @@ -885,15 +1053,15 @@ namespace WPEFramework NMLOG_INFO("Posting onAvailableSSIDs event with %d SSIDs as,", filterResult.Length()); logSSIDs(LOG_LEVEL_INFO, filterResult); - _notificationLock.Lock(); - for (const auto callback : _notificationCallbacks) { - callback->onAvailableSSIDs(jsonOfFilterScanResults); + { + AvailableSSIDsData eventData{jsonOfFilterScanResults}; + enqueueEvent(NM_ON_AVAILABLESSIDS, std::move(eventData)); } - _notificationLock.Unlock(); } void NetworkManagerImplementation::startWiFiSignalQualityMonitor(int interval) { + LOG_ENTRY_FUNCTION(); if (m_isRunning.load()) { NMLOG_INFO("WiFiSignalQualityMonitor Thread is already running."); return; @@ -909,6 +1077,7 @@ namespace WPEFramework void NetworkManagerImplementation::stopWiFiSignalQualityMonitor() { + LOG_ENTRY_FUNCTION(); if (!m_isRunning.load()) return; // No thread to stop @@ -1093,6 +1262,7 @@ namespace WPEFramework void NetworkManagerImplementation::processMonitor(uint16_t interval) { + LOG_ENTRY_FUNCTION(); pid_t pid = getpid(); string path = "/proc/"; @@ -1144,6 +1314,7 @@ namespace WPEFramework void NetworkManagerImplementation::monitorThreadFunction(int interval) { + LOG_ENTRY_FUNCTION(); static Exchange::INetworkManager::WiFiSignalQuality oldSignalQuality = Exchange::INetworkManager::WIFI_SIGNAL_DISCONNECTED; NMLOG_INFO("WiFiSignalQualityMonitor thread started ! (%d)", interval); while (true) @@ -1182,6 +1353,7 @@ namespace WPEFramework void NetworkManagerImplementation::ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state) { + LOG_ENTRY_FUNCTION(); /* start signal strength monitor when wifi connected */ if(INetworkManager::WiFiState::WIFI_STATE_CONNECTED == state) { @@ -1200,25 +1372,25 @@ namespace WPEFramework NMLOG_INFO("NM_WIFI_STATUS = %s", stateStr.c_str()); logTelemetry("NM_WIFI_STATUS", stateStr); #endif - _notificationLock.Lock(); - for (const auto callback : _notificationCallbacks) { - callback->onWiFiStateChange(state); + { + WiFiStateChangeData eventData{state}; + enqueueEvent(NM_ON_WIFISTATE_CHANGE, std::move(eventData)); } - _notificationLock.Unlock(); } void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality) { - _notificationLock.Lock(); - NMLOG_INFO("Posting onWiFiSignalQualityChange %d", strength); - for (const auto callback : _notificationCallbacks) { - callback->onWiFiSignalQualityChange(ssid, strength, noise, snr, quality); + LOG_ENTRY_FUNCTION(); + { + WiFiSignalQualityChangeData eventData{ssid, strength, noise, snr, quality}; + NMLOG_INFO("Posting onWiFiSignalQualityChange %d", strength); + enqueueEvent(NM_ON_WIFISIGNALQUALITY_CHANGE, std::move(eventData)); } - _notificationLock.Unlock(); } void NetworkManagerImplementation::logTelemetry(const std::string& eventName, const std::string& message) { + LOG_ENTRY_FUNCTION(); #if USE_TELEMETRY T2ERROR t2error = t2_event_s(eventName.c_str(), const_cast(message.c_str())); if (t2error != T2ERROR_SUCCESS) { @@ -1233,6 +1405,7 @@ namespace WPEFramework const Exchange::IPowerManager::PowerState newState, std::function sendAck) { + LOG_ENTRY_FUNCTION(); // Called from NetworkManagerPowerClient's power thread. NMLOG_DEBUG("OnPowerModePreChange: current=%d new=%d", static_cast(currentState), static_cast(newState)); @@ -1315,6 +1488,7 @@ namespace WPEFramework const Exchange::IPowerManager::PowerState currentState, const Exchange::IPowerManager::PowerState newState) { + LOG_ENTRY_FUNCTION(); NMLOG_INFO("OnPowerModeChanged: current=%d new=%d", static_cast(currentState), static_cast(newState)); if (currentState == Exchange::IPowerManager::PowerState::POWER_STATE_STANDBY_DEEP_SLEEP) { @@ -1446,6 +1620,7 @@ namespace WPEFramework Exchange::INetworkManager::IPAddress IpFamilyCache::toIPAddress() const { + LOG_ENTRY_FUNCTION(); Exchange::INetworkManager::IPAddress addr{}; /* Detect IP version from any available address. */ bool isIPv6 = false; diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index b7bffe916..bafe337fc 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -30,6 +30,8 @@ #include #include #include +#include +#include using namespace std; @@ -209,20 +211,70 @@ namespace WPEFramework Core::JSON::DecUInt32 loglevel; }; + enum NMPublishEvents { + NM_ON_INTERFACESTATE_CHANGE = 0, + NM_ON_ACTIVEINTERFACE_CHANGE, + NM_ON_IPADDRESS_CHANGE, + NM_ON_INTERNETSTATUS_CHANGE, + NM_ON_AVAILABLESSIDS, + NM_ON_WIFISTATE_CHANGE, + NM_ON_WIFISIGNALQUALITY_CHANGE + }; - class Job : public Core::IDispatch { - public: - Job(function work) - : _work(work) - { - } - void Dispatch() override - { - _work(); - } + // Typed event data structures + struct InterfaceStateChangeData { + Exchange::INetworkManager::InterfaceState state; + string interface; + }; - private: - function _work; + struct ActiveInterfaceChangeData { + string prevActiveInterface; + string currentActiveInterface; + }; + + struct IPAddressChangeData { + string interface; + string ipversion; + string ipaddress; + Exchange::INetworkManager::IPStatus status; + }; + + struct InternetStatusChangeData { + Exchange::INetworkManager::InternetStatus prevState; + Exchange::INetworkManager::InternetStatus currState; + string interface; + }; + + struct AvailableSSIDsData { + string jsonResult; // Pre-serialized JSON string + }; + + struct WiFiStateChangeData { + Exchange::INetworkManager::WiFiState state; + }; + + struct WiFiSignalQualityChangeData { + string ssid; + int strength; + int noise; + int snr; + Exchange::INetworkManager::WiFiSignalQuality quality; + }; + + using EventDataVariant = std::variant< + std::monostate, + InterfaceStateChangeData, + ActiveInterfaceChangeData, + IPAddressChangeData, + InternetStatusChangeData, + AvailableSSIDsData, + WiFiStateChangeData, + WiFiSignalQualityChangeData + >; + + struct EventData { + NMPublishEvents event; + EventDataVariant data; }; public: @@ -344,6 +396,9 @@ namespace WPEFramework void monitorThreadFunction(int interval); int32_t logSSIDs(Logging level, const JsonArray &ssids); void processMonitor(uint16_t interval); + void eventThreadFunction(); + void enqueueEvent(NMPublishEvents event, EventDataVariant&& data); + void dispatchEvent(NMPublishEvents event, const EventDataVariant& data); private: std::list _notificationCallbacks; @@ -365,6 +420,12 @@ namespace WPEFramework std::atomic m_processMonThreadStop{false}; std::condition_variable m_processMonCondVar; + std::thread m_eventThread; + std::queue m_eventQueue; + std::mutex m_eventMutex; + std::condition_variable m_eventCondVar; + std::atomic m_eventThreadStop{false}; + std::atomic m_isRunning{false}; std::atomic m_stopThread{false}; std::mutex m_condVariableMutex; diff --git a/tests/l1Test/CMakeLists.txt b/tests/l1Test/CMakeLists.txt index dfae9937d..ec7b8c37e 100644 --- a/tests/l1Test/CMakeLists.txt +++ b/tests/l1Test/CMakeLists.txt @@ -44,7 +44,7 @@ if(ENABLE_ROUTER_DISCOVERY_TOOL) ) set_target_properties(${NM_ROUTER_DISCOVERY_L1_TEST} PROPERTIES - CXX_STANDARD 11 + CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES ) @@ -78,7 +78,7 @@ target_link_libraries(${NM_CLASS_L1_TEST} PRIVATE ) set_target_properties(${NM_CLASS_L1_TEST} PROPERTIES - CXX_STANDARD 11 + CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES ) diff --git a/tests/l2Test/legacy/CMakeLists.txt b/tests/l2Test/legacy/CMakeLists.txt index 5106f18ed..ae1688612 100644 --- a/tests/l2Test/legacy/CMakeLists.txt +++ b/tests/l2Test/legacy/CMakeLists.txt @@ -40,11 +40,11 @@ add_executable(${NM_LEGACY_NETWORK_UT} ) set_target_properties(${NM_LEGACY_WIFI_UT} PROPERTIES - CXX_STANDARD 11 + CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES ) set_target_properties(${NM_LEGACY_NETWORK_UT} PROPERTIES - CXX_STANDARD 11 + CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES ) diff --git a/tests/l2Test/libnm/CMakeLists.txt b/tests/l2Test/libnm/CMakeLists.txt index 9b1a44d03..17be8eea4 100644 --- a/tests/l2Test/libnm/CMakeLists.txt +++ b/tests/l2Test/libnm/CMakeLists.txt @@ -49,7 +49,7 @@ add_executable(${NM_LIBNM_PROXY_L2_TEST} ) set_target_properties(${NM_LIBNM_PROXY_L2_TEST} PROPERTIES - CXX_STANDARD 11 + CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES ) diff --git a/tests/l2Test/rdk/CMakeLists.txt b/tests/l2Test/rdk/CMakeLists.txt index 3a94c63d7..cc5ecc594 100644 --- a/tests/l2Test/rdk/CMakeLists.txt +++ b/tests/l2Test/rdk/CMakeLists.txt @@ -44,7 +44,7 @@ add_executable(${NM_RDK_PROXY_L2_TEST} ) set_target_properties(${NM_RDK_PROXY_L2_TEST} PROPERTIES - CXX_STANDARD 11 + CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES ) diff --git a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp index 89be4686f..1fb8a27c7 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp @@ -235,6 +235,7 @@ TEST_F(NetworkManagerEventTest, onInterfaceStateChange) EXPECT_EQ(Core::ERROR_NONE, onInterfaceStateChange.Lock()); + sleep(5); EVENT_UNSUBSCRIBE(2, _T("onInterfaceStateChange"), _T("org.rdk.NetworkManager"), message); } @@ -464,6 +465,7 @@ TEST_F(NetworkManagerEventTest, onInterfaceStateChange2) _nmEventHandler(IARM_BUS_NM_SRV_MGR_NAME, IARM_BUS_NETWORK_MANAGER_EVENT_INTERFACE_CONNECTION_STATUS, &eventData, sizeof(eventData)); EXPECT_EQ(Core::ERROR_NONE, onInterfaceStateChange.Lock()); + sleep(5); EVENT_UNSUBSCRIBE(2, _T("onInterfaceStateChange"), _T("org.rdk.NetworkManager"), message); diff --git a/tools/plugincli/CMakeLists.txt b/tools/plugincli/CMakeLists.txt index 568836764..6784ff846 100644 --- a/tools/plugincli/CMakeLists.txt +++ b/tools/plugincli/CMakeLists.txt @@ -74,7 +74,7 @@ if(ENABLE_GNOME_GDBUS) ) set_target_properties(${PLUGIN_GDBUS_CLI} PROPERTIES - CXX_STANDARD 11 + CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES ) @@ -106,7 +106,7 @@ else() ) set_target_properties(${PLUGIN_LIBNM_CLI} PROPERTIES - CXX_STANDARD 11 + CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES ) From b151527d553967362242ac5c4a5129baf7a897b6 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 17 Jul 2026 14:56:05 -0400 Subject: [PATCH 251/271] Release of 3.4.0 Release of 3.4.0 --- CHANGELOG.md | 7 +++++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d262c5e6f..d5dd29bfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,13 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [3.4.0] - 2026-07-17 +### Fixed +- Fixed the logging failure within the inprogress plugins +- Added mutex before accessing the scan filters +- Added t2 event for IPv6 Public IP +- Added thread to publish the events without blocking the caller notification thread + ## [3.3.0] - 2026-06-12 ### Fixed - Fixed the memory leak that caused by the persistent m_nmClient and m_nmContext. diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d4cc1db6..8fe5ee162 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 3) -set(VERSION_MINOR 3) +set(VERSION_MINOR 4) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index f79bd812e..84facd1ef 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "3.3.0" + "version": "3.4.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 3d109f0a0..978dd2e80 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 3.3.0** +**Version: 3.4.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.3.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.4.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From b9ad7a47e78668e9cb735925bc6ebd75601166ae Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 30 Jul 2026 14:10:19 -0400 Subject: [PATCH 252/271] RDKEMW-22276: Coverity integration for networkmanager plugin (#331) * Added cov_build.sh script * Added all the required files for coverity * Addressed copilot reported issues * Addressed compilation issue * updated the comments * Changed the permission of workflow to read only --- .github/workflows/native_full_build.yml | 26 ++++ build_dependencies.sh | 193 ++++++++++++++++++++++++ cov_build.sh | 74 +++++++++ 3 files changed, 293 insertions(+) create mode 100644 .github/workflows/native_full_build.yml create mode 100644 build_dependencies.sh create mode 100644 cov_build.sh diff --git a/.github/workflows/native_full_build.yml b/.github/workflows/native_full_build.yml new file mode 100644 index 000000000..c7a10413d --- /dev/null +++ b/.github/workflows/native_full_build.yml @@ -0,0 +1,26 @@ +name: Build Component in Native Environment + +on: + push: + branches: [ main, develop, 'support/**', 'hotfix/**', 'topic/**' ] + pull_request: + branches: [ main, develop, 'support/**', 'hotfix/**', 'topic/**' ] + +permissions: + contents: read + +jobs: + build-networkmanager: + name: Build networkmanager component in github rdkcentral + # Ubuntu 24.04 provides libnm 1.46, closer to the version used in RDK(1.43.7). + runs-on: ubuntu-24.04 + + steps: + + - name: Checkout code + uses: actions/checkout@v3 + + - name: native build + run: | + sh -x build_dependencies.sh + sh -x cov_build.sh diff --git a/build_dependencies.sh b/build_dependencies.sh new file mode 100644 index 000000000..8aad62f39 --- /dev/null +++ b/build_dependencies.sh @@ -0,0 +1,193 @@ +#!/usr/bin/env bash +# +# build_dependencies.sh - Install system packages and build the Thunder +# ecosystem (ThunderTools, Thunder, ThunderInterfaces) plus the mock +# dependency files required to build networkmanager for Coverity. +# +# This is the first half of the old cov_build.sh: everything that prepares +# the environment. The component itself is built by cov_build.sh, which is +# run afterwards from the same workspace. +# +# Usage: +# ./build_dependencies.sh +# +# Override any of the environment variables below on the command line, e.g.: +# THUNDER_REF=R4.4.3 ./build_dependencies.sh +# + +# Re-exec under bash if started with a non-bash shell (e.g. `sh build_dependencies.sh`, +# where sh is dash). This script relies on bash features such as `pipefail` +# and ${BASH_SOURCE[0]}, which dash does not support. +if [ -z "${BASH_VERSION:-}" ]; then + exec bash "$0" "$@" +fi + +set -euo pipefail + +# --------------------------------------------------------------------------- +# Configuration (mirrors the workflow `env:` block) +# --------------------------------------------------------------------------- +BUILD_TYPE="${BUILD_TYPE:-Debug}" +THUNDER_REF="${THUNDER_REF:-R4.4.3}" +THUNDERTOOLS_REF="${THUNDERTOOLS_REF:-${THUNDER_REF}}" +INTERFACES_REF="${INTERFACES_REF:-${THUNDER_REF}}" + +# Root workspace directory. In CI this is ${{ github.workspace }}. +# The Thunder repositories and install tree live inside the networkmanager +# checkout so the layout is self-contained and shared with cov_build.sh. +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WORKSPACE="${WORKSPACE:-${SCRIPT_DIR}}" +NETWORKMANAGER_DIR="${NETWORKMANAGER_DIR:-${SCRIPT_DIR}}" +INSTALL_DIR="${WORKSPACE}/install/usr" +MODULE_PATH="${WORKSPACE}/install/tools/cmake" + +NPROC="$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 4)" + +log() { printf '\n\033[1;34m==> %s\033[0m\n' "$*"; } + +# Use sudo only when it exists (CI build containers usually run as root and +# do not ship sudo). Otherwise run the command directly. +if command -v sudo >/dev/null 2>&1; then + SUDO="sudo" +else + SUDO="" +fi + +# --------------------------------------------------------------------------- +# Install system packages +# --------------------------------------------------------------------------- +log "Installing system packages" +${SUDO} apt-get update +${SUDO} apt-get install -y \ + build-essential \ + cmake \ + pkg-config \ + libglib2.0-dev \ + libnm-dev \ + libcurl4-openssl-dev \ + lcov \ + ninja-build + +# --------------------------------------------------------------------------- +# Install Python dependencies +# --------------------------------------------------------------------------- +log "Installing Python dependencies" +if command -v pip >/dev/null 2>&1; then + pip install --break-system-packages jsonref || pip install jsonref || true +elif command -v pip3 >/dev/null 2>&1; then + pip3 install --break-system-packages jsonref || pip3 install jsonref || true +else + echo "pip not found; skipping jsonref install" +fi + +# --------------------------------------------------------------------------- +# Clone Thunder repositories +# --------------------------------------------------------------------------- +clone_repo() { + # clone_repo + local url="$1" path="$2" ref="$3" + if [ ! -d "${path}/.git" ]; then + log "Cloning ${url} (${ref}) into ${path}" + git clone --branch "${ref}" "${url}" "${path}" + else + log "Repository ${path} already present; fetching ${ref}" + git -C "${path}" fetch origin "${ref}" + git -C "${path}" checkout "${ref}" + fi +} + +clone_repo "https://github.com/rdkcentral/ThunderTools" \ + "${WORKSPACE}/ThunderTools" "${THUNDERTOOLS_REF}" +clone_repo "https://github.com/rdkcentral/Thunder" \ + "${WORKSPACE}/Thunder" "${THUNDER_REF}" +clone_repo "https://github.com/rdkcentral/ThunderInterfaces" \ + "${WORKSPACE}/ThunderInterfaces" "${INTERFACES_REF}" + +# --------------------------------------------------------------------------- +# Apply Thunder SubscribeStub patch +# --------------------------------------------------------------------------- +log "Applying Thunder SubscribeStub patch" +( + cd "${WORKSPACE}/Thunder" + git apply "${NETWORKMANAGER_DIR}/tests/patches/thunder/SubscribeStub.patch" 2>/dev/null \ + || echo "Patch already applied or not needed" +) + +# --------------------------------------------------------------------------- +# Build ThunderTools +# --------------------------------------------------------------------------- +log "Building ThunderTools" +cmake \ + -S "${WORKSPACE}/ThunderTools" \ + -B "${WORKSPACE}/build/ThunderTools" \ + -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ + -DCMAKE_MODULE_PATH="${MODULE_PATH}" \ + -DGENERIC_CMAKE_MODULE_PATH="${MODULE_PATH}" +cmake --build "${WORKSPACE}/build/ThunderTools" --target install -j"${NPROC}" + +# --------------------------------------------------------------------------- +# Build Thunder +# --------------------------------------------------------------------------- +log "Building Thunder" +cmake \ + -S "${WORKSPACE}/Thunder" \ + -B "${WORKSPACE}/build/Thunder" \ + -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ + -DCMAKE_MODULE_PATH="${MODULE_PATH}" \ + -DBUILD_TYPE="${BUILD_TYPE}" \ + -DBINDING=127.0.0.1 \ + -DPORT=9998 +cmake --build "${WORKSPACE}/build/Thunder" --target install -j"${NPROC}" + +# --------------------------------------------------------------------------- +# Build ThunderInterfaces +# --------------------------------------------------------------------------- +log "Building ThunderInterfaces" +cmake \ + -S "${WORKSPACE}/ThunderInterfaces" \ + -B "${WORKSPACE}/build/ThunderInterfaces" \ + -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ + -DCMAKE_MODULE_PATH="${MODULE_PATH}" +cmake --build "${WORKSPACE}/build/ThunderInterfaces" --target install -j"${NPROC}" + +# --------------------------------------------------------------------------- +# Install IPowerManager header into the Thunder interfaces include path +# --------------------------------------------------------------------------- +log "Installing IPowerManager header" +IFACE_DIR="$(find "${INSTALL_DIR}/include" -maxdepth 2 -name "interfaces" -type d | head -1)" +if [ -z "${IFACE_DIR}" ] || [ ! -d "${IFACE_DIR}" ]; then + echo "Error: Thunder interfaces include dir not found under ${INSTALL_DIR}/include" >&2 + exit 1 +fi +cp "${NETWORKMANAGER_DIR}/tests/mocks/thunder/IPowerManager.h" "${IFACE_DIR}/" + +# --------------------------------------------------------------------------- +# Generate dependency files +# --------------------------------------------------------------------------- +log "Generating /etc/device.properties" +${SUDO} tee /etc/device.properties >/dev/null <<'EOF' +ETHERNET_INTERFACE=eth0 +WIFI_INTERFACE=wlan0 +DEFAULT_HOSTNAME=rdk_test_device +EOF + +# --------------------------------------------------------------------------- +# Generate IARM headers/stubs +# --------------------------------------------------------------------------- +log "Generating IARM headers" +mkdir -p "${INSTALL_DIR}/lib" +printf 'void __nm_cov_stub(void){}\n' | ${CC:-cc} -fPIC -shared -x c - -o "${INSTALL_DIR}/lib/libIARMBus.so" +printf 'void __nm_cov_stub(void){}\n' | ${CC:-cc} -fPIC -shared -x c - -o "${INSTALL_DIR}/lib/libmfrlib.so" +mkdir -p "${INSTALL_DIR}/include/rdk/iarmbus" +mkdir -p "${INSTALL_DIR}/include/rdk/iarmmgrs-hal" +touch "${INSTALL_DIR}/include/rdk/iarmbus/libIARM.h" +touch "${INSTALL_DIR}/include/rdk/iarmmgrs-hal/mfrMgr.h" +( + cd "${NETWORKMANAGER_DIR}/tests" + mkdir -p headers/rdk/iarmbus + mkdir -p headers/rdk/iarmmgrs-hal + touch headers/rdk/iarmmgrs-hal/mfrMgr.h + touch headers/rdk/iarmbus/libIARM.h headers/rdk/iarmbus/libIBus.h +) + +log "Dependencies ready. Run cov_build.sh to build networkmanager." diff --git a/cov_build.sh b/cov_build.sh new file mode 100644 index 000000000..72c2222f9 --- /dev/null +++ b/cov_build.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# +# cov_build.sh - Coverity-friendly build of networkmanager with the Gnome +# libnm proxy. +# +# This is the second half of the original cov_build.sh: it builds only the +# networkmanager component. The Thunder ecosystem and mock dependency files +# it relies on are produced by build_dependencies.sh, which must be run first +# from the same workspace. +# +# Usage: +# ./build_dependencies.sh +# ./cov_build.sh +# +# Override any of the environment variables below on the command line, e.g.: +# THUNDER_REF=R4.4.3 ./cov_build.sh +# + +# Re-exec under bash if started with a non-bash shell (e.g. `sh cov_build.sh`, +# where sh is dash). This script relies on bash features such as `pipefail` +# and ${BASH_SOURCE[0]}, which dash does not support. +if [ -z "${BASH_VERSION:-}" ]; then + exec bash "$0" "$@" +fi + +set -euo pipefail + +# --------------------------------------------------------------------------- +# Configuration (must match build_dependencies.sh so the paths line up) +# --------------------------------------------------------------------------- +# Optional cross-compile toolchain file (empty for native builds). +TOOLCHAIN_FILE="${TOOLCHAIN_FILE:-}" + +# Root workspace directory. In CI this is ${{ github.workspace }}. +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WORKSPACE="${WORKSPACE:-${SCRIPT_DIR}}" +NETWORKMANAGER_DIR="${NETWORKMANAGER_DIR:-${SCRIPT_DIR}}" +INSTALL_DIR="${WORKSPACE}/install/usr" +MODULE_PATH="${WORKSPACE}/install/tools/cmake" + +NPROC="$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 4)" + +log() { printf '\n\033[1;34m==> %s\033[0m\n' "$*"; } + +# --------------------------------------------------------------------------- +# Build networkmanager with Gnome libnm Proxy +# --------------------------------------------------------------------------- +log "Building networkmanager with Gnome libnm Proxy" +NM_CXX_FLAGS=" -fprofile-arcs -ftest-coverage \ +-I ${NETWORKMANAGER_DIR}/tests/headers \ +-I ${NETWORKMANAGER_DIR}/tests/headers/rdk/iarmbus \ +-I ${NETWORKMANAGER_DIR}/tests/headers/rdk/iarmmgrs-hal \ +--include ${NETWORKMANAGER_DIR}/tests/mocks/Iarm.h \ +--include ${NETWORKMANAGER_DIR}/tests/mocks/mfrMgr.h " + +TOOLCHAIN_ARG=() +if [ -n "${TOOLCHAIN_FILE}" ]; then + TOOLCHAIN_ARG=(-DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN_FILE}") +fi + +cmake \ + -S "${NETWORKMANAGER_DIR}" \ + -B "${WORKSPACE}/build/networkmanager_libnm" \ + "${TOOLCHAIN_ARG[@]}" \ + -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ + -DCMAKE_PREFIX_PATH="${INSTALL_DIR}" \ + -DCMAKE_MODULE_PATH="${MODULE_PATH}" \ + -DCMAKE_CXX_FLAGS="${NM_CXX_FLAGS}" \ + -DENABLE_GNOME_NETWORKMANAGER=ON \ + -DENABLE_LEGACY_PLUGINS=OFF \ + -DENABLE_UNIT_TESTING=ON \ + -DENABLE_PLUGIN_CLI=OFF \ + -DENABLE_MIGRATION_MFRMGR_SUPPORT=ON +cmake --build "${WORKSPACE}/build/networkmanager_libnm" --target install -j"${NPROC}" From 69af4aaf24f856f40eae4a2789b356becaa0944b Mon Sep 17 00:00:00 2001 From: Anand73-n Date: Sat, 1 Aug 2026 00:41:40 +0530 Subject: [PATCH 253/271] RDKEMW-22632: Order service start after PowerManager (#327) * RDKEMW-21821: Order service start after PowerManager Reason for change: Ensure PowerManager service is started before NetworkManager Test procedure: Reboot, then inspect the order units actually started Risks: low Priority: P1 Signed-off-by: Anand N Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- plugin/CMakeLists.txt | 2 ++ plugin/NetworkManagerPowerClient.cpp | 3 ++- plugin/gnome/systemd/nm-powermanager.conf | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 plugin/gnome/systemd/nm-powermanager.conf diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 32d065dcf..588a243da 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -160,6 +160,8 @@ if(ENABLE_GNOME_NETWORKMANAGER) DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/rdk) install(FILES gnome/systemd/gnome-networkmanager-migration.conf DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/systemd/system/wpeframework-networkmanager.service.d) + install(FILES gnome/systemd/nm-powermanager.conf + DESTINATION ${CMAKE_INSTALL_PREFIX}/../lib/systemd/system/wpeframework-networkmanager.service.d) endif(ENABLE_GNOME_NETWORKMANAGER) #Generate Plugin configuration file diff --git a/plugin/NetworkManagerPowerClient.cpp b/plugin/NetworkManagerPowerClient.cpp index 3d6d2ed95..94a8694b4 100644 --- a/plugin/NetworkManagerPowerClient.cpp +++ b/plugin/NetworkManagerPowerClient.cpp @@ -34,12 +34,13 @@ NetworkManagerPowerClient::NetworkManagerPowerClient(INetworkPowerCallback& call , mPreChangeNotification(*this) , mChangedNotification(*this) { - NMLOG_INFO("connecting to PowerManager"); + NMLOG_INFO("NetworkManagerPowerClient ctor"); if (auto r = Open(RPC::CommunicationTimeOut, Connector(), "org.rdk.PowerManager"); r == Core::ERROR_NONE) { // Connected; Operational() will be called by the framework when the proxy is ready } else { NMLOG_ERROR("failed to open link to PowerManager (error %u)", r); } + NMLOG_INFO("NetworkManagerPowerClient ctor ends"); } NetworkManagerPowerClient::~NetworkManagerPowerClient() diff --git a/plugin/gnome/systemd/nm-powermanager.conf b/plugin/gnome/systemd/nm-powermanager.conf new file mode 100644 index 000000000..7e8c3f01a --- /dev/null +++ b/plugin/gnome/systemd/nm-powermanager.conf @@ -0,0 +1,4 @@ +[Unit] +# Ensure NetworkManager starts after PowerManager +Wants=wpeframework-powermanager.service +After=wpeframework-powermanager.service From ba28f96c5a650546471b4573f91fdcb18b994723 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Sun, 2 Aug 2026 06:54:29 -0400 Subject: [PATCH 254/271] Release of 3.5.0 Release of 3.5.0 --- CHANGELOG.md | 5 +++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5dd29bfd..55382106c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [3.5.0] - 2026-08-02 +### Added +- Added Coverity WorkFlow +- Added PowerManager boot dependency + ## [3.4.0] - 2026-07-17 ### Fixed - Fixed the logging failure within the inprogress plugins diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fe5ee162..d21cefdb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 3) -set(VERSION_MINOR 4) +set(VERSION_MINOR 5) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 84facd1ef..d52205092 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "3.4.0" + "version": "3.5.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 978dd2e80..b65a75fd2 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 3.4.0** +**Version: 3.5.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.4.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.5.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From cf542bd82c10db89bd7c8626ebf651c78da556d8 Mon Sep 17 00:00:00 2001 From: jincysam87 <167995204+jincysam87@users.noreply.github.com> Date: Tue, 11 Aug 2026 14:04:29 -0400 Subject: [PATCH 255/271] RDKEMW-23357 : Failed to Connect to Hidden SSID (#333) Reason for change: wifi connect call with invalid/hidden SSID results in IPC timeout Test Procedure: Issue wifi connect does not timeout even if SSID is invalid/hidden Risks: Medium Signed-off-by: jincysaramma_sam@cable.comcast.com --- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index 58872d481..c75063340 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -1404,6 +1404,7 @@ namespace WPEFramework /* ssid not found in scan list so add to known ssid it will do a scanning and connect */ if(ssidInfo.persist) { + deleteClientConnection(); if(addToKnownSSIDs(ssidInfo)) { NMLOG_DEBUG("Adding to known ssid '%s' ", ssidInfo.ssid.c_str()); From b3362c75d0671c13c992101392890525dd9f6303 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Tue, 11 Aug 2026 14:11:38 -0400 Subject: [PATCH 256/271] Release of 3.6.0 Release of 3.6.0 --- CHANGELOG.md | 4 ++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55382106c..851e39f72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [3.6.0] - 2026-08-11 +### Fixed +- Fixed the issue with connecting to a SSID that is not present in scan list + ## [3.5.0] - 2026-08-02 ### Added - Added Coverity WorkFlow diff --git a/CMakeLists.txt b/CMakeLists.txt index d21cefdb0..724fb37e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 3) -set(VERSION_MINOR 5) +set(VERSION_MINOR 6) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index d52205092..2922b9835 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "3.5.0" + "version": "3.6.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index b65a75fd2..fd6d97dcf 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 3.5.0** +**Version: 3.6.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.5.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.6.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 77cde04b2028ac89fd1970ab863b4536f4009300 Mon Sep 17 00:00:00 2001 From: tukken-comcast Date: Sat, 22 Aug 2026 05:50:42 +0530 Subject: [PATCH 257/271] RDK-62042: Improve performance of GetAvailableInterfaces and GetInterfaceState (#337) * RDK-62042: Improve performance of GetAvailableInterfaces and GetInterfaceState Serve interface-state reads from an event-maintained cache. GetAvailableInterfaces and GetInterfaceState on the Gnome backend created a throwaway NMClient per call (nm_client_new), which synchronously dumps NetworkManager's entire object model and cost ~300ms-1.4s, blowing the 100ms SLA for GetAvailableInterfaces. Serve both reads from a gnome-owned cache of raw NMDeviceState (plus MAC), maintained solely by the event monitor: - Record state on the startup device walk, device-added, and every notify::state transition; drop the entry on device-removed. - Capture the MAC and keep it in sync whenever NM reports a new HW address. - Derive enabled/connected at read time from a single canonical definition, removing the prior >= vs > drift between the two APIs. - Make the reads pure: drop their side-effect writes to the shared connected/enabled atomics (the event path is now the sole writer). - Treat an interface absent from the cache as omitted, and an empty interface list as a valid (successful) result rather than an error. The cache holds a libnm type, so it lives in the Gnome backend; the backend-agnostic NetworkManagerImplementation header stays libnm-free. Add microsecond-resolution [PERF] instrumentation for both reads across the JSON-RPC and impl layers. It is logged at DEBUG level so it stays silent in normal operation and can be enabled on demand for diagnostics. When either COM-RPC read takes one second or more, also emit a WARN so pathological latencies surface without enabling DEBUG. Gate the log level check ahead of message formatting in NetworkManagerLogger::logPrint. Previously vsnprintf ran unconditionally and the level was only checked afterward, so every disabled log still paid the formatting cost. This affects all logging: disabled logs (at any level) now short-circuit before formatting. The RDK-logger build gates on rdk_logger_is_logLevel_enabled and the native build on the configured level, so filtering stays authoritative for each variant. Rework the libnm L1 tests to drive GetAvailableInterfaces and GetInterfaceState through the event-state cache (the sole public writer) instead of mocking the per-call NMClient device enumeration, and reset the process-global cache in test setup for order-independent runs. * Updated include Function Name Updated include Function Name --------- Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- plugin/NetworkManagerJsonRpc.cpp | 22 +++ plugin/NetworkManagerLogger.cpp | 14 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 67 ++++++++- plugin/gnome/NetworkManagerGnomeEvents.h | 17 +++ plugin/gnome/NetworkManagerGnomeProxy.cpp | 139 ++++-------------- tests/l2Test/libnm/l2_test_libnmproxy.cpp | 136 ++++++----------- tests/l2Test/libnm/l2_test_libnmproxyInit.cpp | 10 +- 7 files changed, 197 insertions(+), 208 deletions(-) diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index d49e6c5d4..053ba8f7f 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -21,6 +21,8 @@ #include "INetworkManager.h" #include "NetworkManagerJsonEnum.h" +#include + #define LOG_INPARAM() { string json; parameters.ToString(json); NMLOG_INFO("params=%s", json.c_str() ); } #define LOG_OUTPARAM() { string json; response.ToString(json); NMLOG_INFO("response=%s", json.c_str() ); } @@ -164,11 +166,19 @@ namespace WPEFramework Exchange::INetworkManager::IInterfaceDetailsIterator* _interfaces{}; + const auto tStart = std::chrono::steady_clock::now(); + if (_networkManager) rc = _networkManager->GetAvailableInterfaces(_interfaces); else rc = Core::ERROR_UNAVAILABLE; + const auto tAfterComRpc = std::chrono::steady_clock::now(); + const long long comRpcUs = static_cast(std::chrono::duration_cast(tAfterComRpc - tStart).count()); + NMLOG_DEBUG("[PERF] GetAvailableInterfaces COM-RPC call took %lld us", comRpcUs); + if (comRpcUs >= 1000000) + NMLOG_WARNING("[PERF] GetAvailableInterfaces COM-RPC call took %lld us (>= 1s)", comRpcUs); + if (Core::ERROR_NONE == rc) { if (_interfaces != nullptr) @@ -193,6 +203,11 @@ namespace WPEFramework } } + const auto tEnd = std::chrono::steady_clock::now(); + NMLOG_DEBUG("[PERF] GetAvailableInterfaces iterator drain+serialize took %lld us, total %lld us", + static_cast(std::chrono::duration_cast(tEnd - tAfterComRpc).count()), + static_cast(std::chrono::duration_cast(tEnd - tStart).count())); + returnJson(rc); } @@ -241,6 +256,8 @@ namespace WPEFramework LOG_INPARAM(); uint32_t rc = Core::ERROR_GENERAL; + const auto tStart = std::chrono::steady_clock::now(); + if (parameters.HasLabel("interface")) { const string interface = parameters["interface"].String(); @@ -259,6 +276,11 @@ namespace WPEFramework else rc = Core::ERROR_BAD_REQUEST; + const long long comRpcUs = static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now() - tStart).count()); + NMLOG_DEBUG("[PERF] GetInterfaceState COM-RPC call took %lld us", comRpcUs); + if (comRpcUs >= 1000000) + NMLOG_WARNING("[PERF] GetInterfaceState COM-RPC call took %lld us (>= 1s)", comRpcUs); + returnJson(rc); } diff --git a/plugin/NetworkManagerLogger.cpp b/plugin/NetworkManagerLogger.cpp index 6a58a1fe2..99aa51bde 100644 --- a/plugin/NetworkManagerLogger.cpp +++ b/plugin/NetworkManagerLogger.cpp @@ -84,6 +84,15 @@ namespace NetworkManagerLogger { void logPrint(LogLevel level, const char* file, const char* func, int line, const char* format, ...) { + // Gate on level before formatting so disabled logs incur no vsnprintf cost. +#ifdef USE_RDK_LOGGER + if (!rdk_logger_is_logLevel_enabled(RDKLOGGER_MODULE_NAME, mapTordkLogLevel(level))) + return; +#else + if (gDefaultLogLevel < level) + return; +#endif + size_t n = 0; const short kFormatMessageSize = 1024; char formattedLog[kFormatMessageSize] = {0}; @@ -102,16 +111,13 @@ namespace NetworkManagerLogger { } formattedLog[kFormatMessageSize - 1] = '\0'; #ifdef USE_RDK_LOGGER - RDK_LOG(mapTordkLogLevel(level), RDKLOGGER_MODULE_NAME, "[%s +%d] %s\n", trimPath(file), line, formattedLog); + RDK_LOG(mapTordkLogLevel(level), RDKLOGGER_MODULE_NAME, "[%s +%d] %s : %s\n", trimPath(file), line, func, formattedLog); #else const char* levelMap[] = {"Fatal", "Error", "Warn", "Info", "Debug"}; struct timeval tv; struct tm* lt; const char* fileName = trimPath(file); - if (gDefaultLogLevel < level) - return; - gettimeofday(&tv, NULL); lt = localtime(&tv.tv_sec); diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 7a87cc200..35793d79b 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "Module.h" #include "NetworkManagerGnomeEvents.h" @@ -44,6 +45,49 @@ namespace WPEFramework extern NetworkManagerImplementation* _instance; static GnomeNetworkManagerEvents *_nmEventInstance = nullptr; + /* Gnome-owned interface-state cache (raw NMDeviceState + MAC per interface). + Written only by the event monitor; read by the proxy's pure readers. */ + static std::map _ifaceStateCache; + static std::mutex _ifaceStateCacheMutex; + + bool GnomeNetworkManagerEvents::isInterfaceStateEnabled(NMDeviceState state) + { + return (state >= NM_DEVICE_STATE_UNAVAILABLE); + } + + bool GnomeNetworkManagerEvents::isInterfaceStateConnected(NMDeviceState state) + { + return (state > NM_DEVICE_STATE_DISCONNECTED && state < NM_DEVICE_STATE_DEACTIVATING); + } + + void GnomeNetworkManagerEvents::updateInterfaceStateCache(const std::string& iface, NMDeviceState state, const char* mac) + { + if (iface.empty()) + return; + std::lock_guard lock(_ifaceStateCacheMutex); + InterfaceStateInfo& info = _ifaceStateCache[iface]; + info.state = state; + info.present = true; + if (mac != nullptr && mac[0] != '\0') + info.mac = mac; // keep in sync when NM reports a new/randomized HW address + } + + void GnomeNetworkManagerEvents::removeInterfaceStateCache(const std::string& iface) + { + std::lock_guard lock(_ifaceStateCacheMutex); + _ifaceStateCache.erase(iface); + } + + bool GnomeNetworkManagerEvents::getInterfaceStateCache(const std::string& iface, InterfaceStateInfo& out) + { + std::lock_guard lock(_ifaceStateCacheMutex); + auto it = _ifaceStateCache.find(iface); + if (it == _ifaceStateCache.end() || !it->second.present) + return false; + out = it->second; + return true; + } + static void primaryConnectionCb(NMClient *client, GParamSpec *param, NMEvents *nmEvents) { NMActiveConnection *primaryConn; @@ -276,8 +320,11 @@ namespace WPEFramework return; NMDeviceState deviceState; deviceState = nm_device_get_state(device); - std::string ifname = nm_device_get_iface(device); + const char* iface = nm_device_get_iface(device); + if (!iface) return; + std::string ifname = iface; NMDeviceStateReason reason = nm_device_get_state_reason(device); + updateInterfaceStateCache(ifname, deviceState, nm_device_get_hw_address(device)); if(ifname == nmUtils::wlanIface()) { if(!NM_IS_DEVICE_WIFI(device)) { @@ -469,7 +516,9 @@ namespace WPEFramework { if( ((device != NULL) && NM_IS_DEVICE(device)) ) { - std::string ifname = nm_device_get_iface(device); + const char* iface = nm_device_get_iface(device); + if (!iface) return; + std::string ifname = iface; if(ifname == nmUtils::wlanIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ADDED, nmUtils::wlanIface()); NMLOG_INFO("WIFI device added: %s", ifname.c_str()); @@ -482,6 +531,7 @@ namespace WPEFramework /* ip events added only for eth0 and wlan0 */ if(ifname == nmUtils::ethIface() || ifname == nmUtils::wlanIface()) { + GnomeNetworkManagerEvents::updateInterfaceStateCache(ifname, nm_device_get_state(device), nm_device_get_hw_address(device)); g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(GnomeNetworkManagerEvents::deviceStateChangeCb), nmEvents); g_signal_connect(device, "notify::ip4-config", G_CALLBACK(ip4ConfigChangedCb), nmEvents); g_signal_connect(device, "notify::ip6-config", G_CALLBACK(ip6ConfigChangedCb), nmEvents); @@ -529,7 +579,9 @@ namespace WPEFramework { if( ((device != NULL) && NM_IS_DEVICE(device)) ) { - std::string ifname = nm_device_get_iface(device); + const char* iface = nm_device_get_iface(device); + if (!iface) return; + std::string ifname = iface; if(ifname == nmUtils::wlanIface()) { GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::wlanIface()); NMLOG_INFO("WIFI device removed: %s", ifname.c_str()); @@ -542,6 +594,10 @@ namespace WPEFramework return; // not a tracked interface } + /* Device is gone: drop it from the cache so the reads omit it + (matches the original live-device-list behaviour). */ + GnomeNetworkManagerEvents::removeInterfaceStateCache(ifname); + /* Disconnect all device-level signals (state, ip4/ip6-config changes). */ g_signal_handlers_disconnect_by_data(device, nmEvents); @@ -637,10 +693,13 @@ namespace WPEFramework NMDevice *device = NM_DEVICE(g_ptr_array_index(devices, count)); if( ((device != NULL) && NM_IS_DEVICE(device)) ) { - std::string ifname = nm_device_get_iface(device); + const char* iface = nm_device_get_iface(device); + if (!iface) continue; + std::string ifname = iface; if((ifname == nmUtils::ethIface()) || (ifname == nmUtils::wlanIface())) { NMDeviceState devState = nm_device_get_state(device); + GnomeNetworkManagerEvents::updateInterfaceStateCache(ifname, devState, nm_device_get_hw_address(device)); if(devState > NM_DEVICE_STATE_DISCONNECTED && devState <= NM_DEVICE_STATE_ACTIVATED) { diff --git a/plugin/gnome/NetworkManagerGnomeEvents.h b/plugin/gnome/NetworkManagerGnomeEvents.h index bf282de78..2bc31f9b1 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.h +++ b/plugin/gnome/NetworkManagerGnomeEvents.h @@ -43,12 +43,29 @@ namespace WPEFramework { public: + /* Gnome-owned cache of live NM device state, kept out of the + backend-agnostic NetworkManagerImplementation (holds a libnm type). */ + struct InterfaceStateInfo { + NMDeviceState state = NM_DEVICE_STATE_UNKNOWN; + std::string mac; + bool present = false; + }; + static void onInterfaceStateChangeCb(uint8_t newState, std::string iface); // ReportInterfaceStateChange static void onActiveInterfaceChangeCb(std::string newInterface); // ReportActiveInterfaceChange static void onAvailableSSIDsCb(NMDeviceWifi *wifiDevice, GParamSpec *pspec, gpointer userData); // ReportAvailableSSIDs static void onWIFIStateChanged(uint8_t state); // ReportWiFiStateChange static void deviceStateChangeCb(NMDevice *device, GParamSpec *pspec, NMEvents *nmEvents); + /* Interface-state cache: sole writer is the event monitor; readers + (GetAvailableInterfaces / GetInterfaceState) are pure. */ + static void updateInterfaceStateCache(const std::string& iface, NMDeviceState state, const char* mac); + static void removeInterfaceStateCache(const std::string& iface); + static bool getInterfaceStateCache(const std::string& iface, InterfaceStateInfo& out); + /* Canonical enabled/connected definitions shared by both read APIs. */ + static bool isInterfaceStateEnabled(NMDeviceState state); + static bool isInterfaceStateConnected(NMDeviceState state); + public: static GnomeNetworkManagerEvents* getInstance(); bool startNetworkMangerEventMonitor(); diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 30d065e87..65b2fc4ba 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -22,6 +22,7 @@ #include "NetworkManagerGnomeUtils.h" #include #include +#include using namespace WPEFramework; using namespace WPEFramework::Plugin; using namespace std; @@ -347,77 +348,37 @@ namespace WPEFramework std::vector interfaceList; std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); - if(m_nmContext == nullptr) { - NMLOG_FATAL("NMContext is null"); - return Core::ERROR_GENERAL; - } - - NMClient *client = createProxyClient(m_nmContext); - if (client == nullptr) { - NMLOG_FATAL("Failed to create NMClient for GetAvailableInterfaces"); - return Core::ERROR_GENERAL; - } + const auto tEntry = std::chrono::steady_clock::now(); - GPtrArray *devices = const_cast(nm_client_get_devices(client)); - if (devices == NULL) { - NMLOG_ERROR("Failed to get device list."); - deleteProxyClient(client); - return rc; - } - - for (guint j = 0; j < devices->len; j++) + /* Serve from the event-maintained cache; no per-call NMClient. An interface + * absent from the cache (not yet reported by NM) is simply omitted; an empty + * list is a valid result (ground reality), not an error. */ + for (int i = 0; i < 2; ++i) { - NMDevice *device = NM_DEVICE(devices->pdata[j]); - if(device != NULL) - { - const char* ifacePtr = nm_device_get_iface(device); - if(ifacePtr == nullptr) - continue; - std::string ifaceStr = ifacePtr; - if(ifaceStr == wifiname || ifaceStr == ethname) // only wifi and ethenet taking - { - NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; - Exchange::INetworkManager::InterfaceDetails interface{}; - const char* macAddr = nm_device_get_hw_address(device); - if(macAddr != nullptr) { - interface.mac = macAddr; - } - deviceState = nm_device_get_state(device); - interface.enabled = (deviceState >= NM_DEVICE_STATE_UNAVAILABLE)? true : false; - if(deviceState > NM_DEVICE_STATE_DISCONNECTED && deviceState < NM_DEVICE_STATE_DEACTIVATING) - interface.connected = true; - else - interface.connected = false; + const std::string& ifname = (i == 0) ? ethname : wifiname; + GnomeNetworkManagerEvents::InterfaceStateInfo info; + if (!GnomeNetworkManagerEvents::getInterfaceStateCache(ifname, info)) + continue; - if(ifaceStr == wifiname) { - interface.type = INTERFACE_TYPE_WIFI; - interface.name = wifiname; - m_wlanConnected.store(interface.connected); - m_wlanEnabled.store(interface.enabled); - } - else if(ifaceStr == ethname) { - interface.type = INTERFACE_TYPE_ETHERNET; - interface.name = ethname; - m_ethConnected.store(interface.connected); - m_ethEnabled.store(interface.enabled); - } + Exchange::INetworkManager::InterfaceDetails interface{}; + interface.type = (i == 0) ? INTERFACE_TYPE_ETHERNET : INTERFACE_TYPE_WIFI; + interface.name = ifname; + interface.mac = info.mac; + interface.enabled = GnomeNetworkManagerEvents::isInterfaceStateEnabled(info.state); + interface.connected = GnomeNetworkManagerEvents::isInterfaceStateConnected(info.state); - interfaceList.push_back(interface); - rc = Core::ERROR_NONE; - } - } + interfaceList.push_back(interface); } - deleteProxyClient(client); - - if (rc != Core::ERROR_NONE) - return rc; - using Implementation = RPC::IteratorType; interfacesItr = Core::Service::Create(interfaceList); if(interfacesItr == nullptr) { return Core::ERROR_GENERAL; } + rc = Core::ERROR_NONE; + + NMLOG_DEBUG("[PERF] GetAvailableInterfaces (impl) total %lld us", + static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now() - tEntry).count())); return rc; } #if 0 @@ -640,65 +601,29 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::GetInterfaceState(const string& interface/* @in */, bool& isEnabled /* @out */) { isEnabled = false; - bool isIfaceFound = false; std::string wifiname = nmUtils::wlanIface(), ethname = nmUtils::ethIface(); + const auto tEntry = std::chrono::steady_clock::now(); + if(interface.empty() || (wifiname != interface && ethname != interface)) { NMLOG_ERROR("interface: %s; not valied", interface.c_str()!=nullptr? interface.c_str():"empty"); return Core::ERROR_GENERAL; } - if(m_nmContext == nullptr) + /* Serve from the event-maintained cache; no per-call NMClient. */ + GnomeNetworkManagerEvents::InterfaceStateInfo info; + if (!GnomeNetworkManagerEvents::getInterfaceStateCache(interface, info)) { - NMLOG_WARNING("NMContext is null"); - return Core::ERROR_RPC_CALL_FAILED; - } - - NMClient *client = createProxyClient(m_nmContext); - if (client == nullptr) { - NMLOG_ERROR("Failed to create NMClient for GetInterfaceState"); - return Core::ERROR_RPC_CALL_FAILED; - } - - GPtrArray *devices = const_cast(nm_client_get_devices(client)); - - if (devices == NULL) { - NMLOG_ERROR("Failed to get device list."); - deleteProxyClient(client); + NMLOG_WARNING("%s : state not known yet", interface.c_str()); return Core::ERROR_GENERAL; } - for (guint j = 0; j < devices->len; j++) - { - NMDevice *device = NM_DEVICE(devices->pdata[j]); - if(device != NULL) - { - const char* iface = nm_device_get_iface(device); - if(iface != NULL) - { - std::string ifaceStr; - ifaceStr.assign(iface); - NMDeviceState deviceState = NM_DEVICE_STATE_UNKNOWN; - if(ifaceStr == interface) - { - isIfaceFound = true; - deviceState = nm_device_get_state(device); - isEnabled = (deviceState > NM_DEVICE_STATE_UNAVAILABLE) ? true : false; - NMLOG_INFO("%s : %s", ifaceStr.c_str(), isEnabled?"enabled":"disabled"); - break; - } - } - } - } - - deleteProxyClient(client); - - if(isIfaceFound) - return Core::ERROR_NONE; - else - NMLOG_ERROR("%s : not found", interface.c_str()); - return Core::ERROR_GENERAL; + isEnabled = GnomeNetworkManagerEvents::isInterfaceStateEnabled(info.state); + NMLOG_INFO("%s : %s", interface.c_str(), isEnabled?"enabled":"disabled"); + NMLOG_DEBUG("[PERF] GetInterfaceState (impl) total %lld us", + static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now() - tEntry).count())); + return Core::ERROR_NONE; } /* @brief Get IP Address Of the Interface */ diff --git a/tests/l2Test/libnm/l2_test_libnmproxy.cpp b/tests/l2Test/libnm/l2_test_libnmproxy.cpp index 0a3dad69d..a102c7eac 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxy.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxy.cpp @@ -35,6 +35,7 @@ #include "NetworkManagerImplementation.h" #include "NetworkManagerLogger.h" #include "NetworkManager.h" +#include "NetworkManagerGnomeEvents.h" #include using namespace WPEFramework; @@ -150,6 +151,11 @@ class NetworkManagerTest : public ::testing::Test { std::cerr << "Failed to create /etc/device.properties file." << std::endl; } } + + /* Interface-state cache is a process-global static; reset the known + interfaces so each test starts from a deterministic empty state. */ + Plugin::GnomeNetworkManagerEvents::removeInterfaceStateCache("eth0"); + Plugin::GnomeNetworkManagerEvents::removeInterfaceStateCache("wlan0"); } virtual ~NetworkManagerTest() override @@ -353,59 +359,37 @@ TEST_F(NetworkManagerTest, GetPrimaryInterface_empty) TEST_F(NetworkManagerTest, GetInterfaceState_Failed) { - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) - .WillRepeatedly(::testing::Return(nullptr)); - + /* wlan0 not present in the event cache -> state unknown -> failure */ EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), _T("{\"interface\":\"wlan0\"}"), response)); EXPECT_EQ(response, _T("{\"success\":false}")); } TEST_F(NetworkManagerTest, GetInterfaceState_WifiEth) { - GPtrArray* fakeDevices = g_ptr_array_new(); - - NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); - g_ptr_array_add(fakeDevices, deviceDummy); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) - .WillRepeatedly(::testing::Return(fakeDevices)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) - .WillOnce(::testing::Return("wlan0")) - .WillOnce(::testing::Return("eth0")); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); // disabled + Plugin::GnomeNetworkManagerEvents::updateInterfaceStateCache("wlan0", NM_DEVICE_STATE_ACTIVATED, "66:77:88:99:AA:BB"); + Plugin::GnomeNetworkManagerEvents::updateInterfaceStateCache("eth0", NM_DEVICE_STATE_UNMANAGED, "00:11:22:33:44:55"); // disabled EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), _T("{\"interface\":\"wlan0\"}"), response)); EXPECT_EQ(response, _T("{\"enabled\":true,\"success\":true}")); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), _T("{\"interface\":\"eth0\"}"), response)); EXPECT_EQ(response, _T("{\"enabled\":false,\"success\":true}")); - - g_object_unref(deviceDummy); - g_ptr_array_free(fakeDevices, TRUE); } TEST_F(NetworkManagerTest, GetInterfaceState_WifiEthNotFound) { - GPtrArray* fakeDevices = g_ptr_array_new(); - - NMDevice *deviceDummy = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); - g_ptr_array_add(fakeDevices, deviceDummy); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) - .WillRepeatedly(::testing::Return(fakeDevices)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) - .WillOnce(::testing::Return("wlan1")); + /* Only eth0 known to the cache; querying wlan0 -> not found -> failure */ + Plugin::GnomeNetworkManagerEvents::updateInterfaceStateCache("eth0", NM_DEVICE_STATE_ACTIVATED, "00:11:22:33:44:55"); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), _T("{\"interface\":\"wlan0\"}"), response)); EXPECT_EQ(response, _T("{\"success\":false}")); +} - g_object_unref(deviceDummy); - g_ptr_array_free(fakeDevices, TRUE); +TEST_F(NetworkManagerTest, GetInterfaceState_emptyInterface) +{ + /* Empty interface name is rejected before any cache lookup */ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetInterfaceState"), _T("{\"interface\":\"\"}"), response)); + EXPECT_EQ(response, _T("{\"success\":false}")); } TEST_F(NetworkManagerTest, GetInterfaceState_unknown) @@ -421,38 +405,19 @@ TEST_F(NetworkManagerTest, GetInterfaceState_unknown) EXPECT_EQ(isEnabled, false); } -TEST_F(NetworkManagerTest, GetAvailableInterfaces_DevicesNull) +TEST_F(NetworkManagerTest, GetAvailableInterfaces_emptyCache) { - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) - .WillOnce(::testing::Return(nullptr)); + /* No interfaces reported by NM yet -> empty list is a valid (successful) result */ EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T(""), response)); - EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("eth0") == std::string::npos); + EXPECT_TRUE(response.find("wlan0") == std::string::npos); } TEST_F(NetworkManagerTest, GetAvailableInterfaces_Enabled) { - GPtrArray* fakeDevices = g_ptr_array_new(); - NMDevice *ethDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); - NMDevice* wifiDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); - g_ptr_array_add(fakeDevices, wifiDevice); - g_ptr_array_add(fakeDevices, ethDevice); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) - .WillOnce(::testing::Return(fakeDevices)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(ethDevice)) - .WillOnce(::testing::Return("eth0")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(wifiDevice)) - .WillOnce(::testing::Return("wlan0")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_hw_address(ethDevice)) - .WillOnce(::testing::Return("00:11:22:33:44:55")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_hw_address(wifiDevice)) - .WillOnce(::testing::Return("66:77:88:99:AA:BB")); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(ethDevice)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(wifiDevice)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNAVAILABLE)); + Plugin::GnomeNetworkManagerEvents::updateInterfaceStateCache("eth0", NM_DEVICE_STATE_ACTIVATED, "00:11:22:33:44:55"); + Plugin::GnomeNetworkManagerEvents::updateInterfaceStateCache("wlan0", NM_DEVICE_STATE_UNAVAILABLE, "66:77:88:99:AA:BB"); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T(""), response)); EXPECT_TRUE(response.find("wlan0") != std::string::npos); @@ -460,40 +425,16 @@ TEST_F(NetworkManagerTest, GetAvailableInterfaces_Enabled) std::string expectedResponse = _T("{\"interfaces\":[") - _T("{\"type\":\"WIFI\",\"name\":\"wlan0\",\"mac\":\"66:77:88:99:AA:BB\",\"enabled\":true,\"connected\":false},") - _T("{\"type\":\"ETHERNET\",\"name\":\"eth0\",\"mac\":\"00:11:22:33:44:55\",\"enabled\":true,\"connected\":true}") + _T("{\"type\":\"ETHERNET\",\"name\":\"eth0\",\"mac\":\"00:11:22:33:44:55\",\"enabled\":true,\"connected\":true},") + _T("{\"type\":\"WIFI\",\"name\":\"wlan0\",\"mac\":\"66:77:88:99:AA:BB\",\"enabled\":true,\"connected\":false}") _T("],\"success\":true}"); EXPECT_EQ(response, expectedResponse); - - g_object_unref(ethDevice); - g_object_unref(wifiDevice); - g_ptr_array_free(fakeDevices, TRUE); } TEST_F(NetworkManagerTest, GetAvailableInterfaces_disabled) { - GPtrArray* fakeDevices = g_ptr_array_new(); - NMDevice *ethDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); - NMDevice* wifiDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); - g_ptr_array_add(fakeDevices, wifiDevice); - g_ptr_array_add(fakeDevices, ethDevice); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_)) - .WillOnce(::testing::Return(fakeDevices)); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(ethDevice)) - .WillOnce(::testing::Return("eth0")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(wifiDevice)) - .WillOnce(::testing::Return("wlan0")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_hw_address(ethDevice)) - .WillOnce(::testing::Return("00:11:22:33:44:55")); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_hw_address(wifiDevice)) - .WillOnce(::testing::Return("66:77:88:99:AA:BB")); - - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(ethDevice)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); - EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(wifiDevice)) - .WillOnce(::testing::Return(NM_DEVICE_STATE_UNMANAGED)); + Plugin::GnomeNetworkManagerEvents::updateInterfaceStateCache("eth0", NM_DEVICE_STATE_UNMANAGED, "00:11:22:33:44:55"); + Plugin::GnomeNetworkManagerEvents::updateInterfaceStateCache("wlan0", NM_DEVICE_STATE_UNMANAGED, "66:77:88:99:AA:BB"); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T(""), response)); EXPECT_TRUE(response.find("wlan0") != std::string::npos); @@ -501,14 +442,25 @@ TEST_F(NetworkManagerTest, GetAvailableInterfaces_disabled) std::string expectedResponse = _T("{\"interfaces\":[") - _T("{\"type\":\"WIFI\",\"name\":\"wlan0\",\"mac\":\"66:77:88:99:AA:BB\",\"enabled\":false,\"connected\":false},") - _T("{\"type\":\"ETHERNET\",\"name\":\"eth0\",\"mac\":\"00:11:22:33:44:55\",\"enabled\":false,\"connected\":false}") + _T("{\"type\":\"ETHERNET\",\"name\":\"eth0\",\"mac\":\"00:11:22:33:44:55\",\"enabled\":false,\"connected\":false},") + _T("{\"type\":\"WIFI\",\"name\":\"wlan0\",\"mac\":\"66:77:88:99:AA:BB\",\"enabled\":false,\"connected\":false}") _T("],\"success\":true}"); EXPECT_EQ(response, expectedResponse); +} - g_object_unref(ethDevice); - g_object_unref(wifiDevice); - g_ptr_array_free(fakeDevices, TRUE); +TEST_F(NetworkManagerTest, GetAvailableInterfaces_onlyEthernet) +{ + /* Only eth0 reported by NM; wlan0 (absent from cache) is omitted from the list */ + Plugin::GnomeNetworkManagerEvents::updateInterfaceStateCache("eth0", NM_DEVICE_STATE_ACTIVATED, "00:11:22:33:44:55"); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T(""), response)); + EXPECT_TRUE(response.find("wlan0") == std::string::npos); + + std::string expectedResponse = + _T("{\"interfaces\":[") + _T("{\"type\":\"ETHERNET\",\"name\":\"eth0\",\"mac\":\"00:11:22:33:44:55\",\"enabled\":true,\"connected\":true}") + _T("],\"success\":true}"); + EXPECT_EQ(response, expectedResponse); } TEST_F(NetworkManagerTest, GetIPSettings_unknown_iface) diff --git a/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp b/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp index b550b3d6f..52d2a1399 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyInit.cpp @@ -33,6 +33,7 @@ #include "NetworkManagerImplementation.h" #include "NetworkManagerLogger.h" #include "NetworkManager.h" +#include "NetworkManagerGnomeEvents.h" #include using namespace WPEFramework; @@ -123,6 +124,10 @@ class NetworkManagerInitTest : public ::testing::Test { virtual void SetUp() override { + /* Interface-state cache is a process-global static shared across suites; + clear the known interfaces so platform_init failure yields an empty cache. */ + Plugin::GnomeNetworkManagerEvents::removeInterfaceStateCache("eth0"); + Plugin::GnomeNetworkManagerEvents::removeInterfaceStateCache("wlan0"); } virtual ~NetworkManagerInitTest() override @@ -149,7 +154,10 @@ TEST_F(NetworkManagerInitTest, platformInit) NetworkManagerLogger::SetLevel(static_cast(NetworkManagerLogger::DEBUG_LEVEL)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetAvailableInterfaces"), _T(""), response)); - EXPECT_TRUE(response.find("\"success\":false") != std::string::npos); + /* platform_init failed (no NMClient) -> event cache never populated -> empty list, still success */ + EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); + EXPECT_TRUE(response.find("eth0") == std::string::npos); + EXPECT_TRUE(response.find("wlan0") == std::string::npos); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetPrimaryInterface"), _T(""), response)); EXPECT_EQ(response, _T("{\"interface\":\"\",\"success\":true}")); From 88e8bd1baee769f1bb288aa9537ffe9000048b89 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Sat, 22 Aug 2026 11:27:48 -0400 Subject: [PATCH 258/271] Release of 3.7.0 Release of 3.7.0 --- CHANGELOG.md | 4 ++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 851e39f72..fe546edd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [3.7.0] - 2026-08-21 +### Changed +- Implemented a caching logic about the status of the interface & update based on events + ## [3.6.0] - 2026-08-11 ### Fixed - Fixed the issue with connecting to a SSID that is not present in scan list diff --git a/CMakeLists.txt b/CMakeLists.txt index 724fb37e9..f02326d7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 3) -set(VERSION_MINOR 6) +set(VERSION_MINOR 7) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 2922b9835..014a649f5 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "3.6.0" + "version": "3.7.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index fd6d97dcf..74341a26b 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 3.6.0** +**Version: 3.7.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.6.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.7.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 2832534c70fa04c677e3f048628518804b86a600 Mon Sep 17 00:00:00 2001 From: me-ha-p Date: Tue, 25 Aug 2026 21:58:34 +0530 Subject: [PATCH 259/271] RDKEMW-21048: Mutex to access m_lastConnectedSSID in NMPlugin (#339) * RDKEMW-21048: Use mutex to access m_lastConnectedSSID in NetworkManager Plugin Reason for change: Use mutex to access m_lastConnectedSSID in NetworkManager Plugin. Priority: P2 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * Updated the logging and removed TAB Signed-off-by: Karunakaran A --------- Signed-off-by: Mehavarshni_Palaniswamy@comcast.com Signed-off-by: Karunakaran A --- plugin/NetworkManagerImplementation.cpp | 9 +++++---- plugin/NetworkManagerImplementation.h | 13 +++++++++++++ plugin/gnome/NetworkManagerGnomeProxy.cpp | 10 ++++++---- plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp | 5 +++-- plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp | 5 +++-- 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 1ba0509af..8325a9453 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1328,7 +1328,7 @@ namespace WPEFramework GetWiFiSignalQuality(ssid, strength, noise, snr, newSignalQuality); if (!ssid.empty()) - m_lastConnectedSSID = ssid; // last connected ssid used in wifiConnect + setLastConnectedSSID(ssid); // last connected ssid used in wifiConnect if (oldSignalQuality != newSignalQuality) { oldSignalQuality = newSignalQuality; @@ -1457,11 +1457,12 @@ namespace WPEFramework { if (m_wlanDisconnectedForSleep.load()) { - if (!m_lastConnectedSSID.empty()) + const std::string lastConnectedSSID = getLastConnectedSSID(); + if (!lastConnectedSSID.empty()) { NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting to '%s'", - m_lastConnectedSSID.c_str()); - uint32_t rcWifiUp = ConnectToKnownSSID(m_lastConnectedSSID); + lastConnectedSSID.c_str()); + uint32_t rcWifiUp = ConnectToKnownSSID(lastConnectedSSID); if (rcWifiUp == Core::ERROR_NONE) { m_wlanDisconnectedForSleep.store(false); diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index bafe337fc..1b6cb6c51 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -466,9 +466,22 @@ namespace WPEFramework m_defaultInterface = iface; } + void setLastConnectedSSID(const std::string& ssid) + { + std::lock_guard lock(m_lastConnectedSSIDMutex); + m_lastConnectedSSID = ssid; + } + + std::string getLastConnectedSSID() const + { + std::lock_guard lock(m_lastConnectedSSIDMutex); + return m_lastConnectedSSID; + } + private: string m_defaultInterface; mutable std::mutex m_defaultInterfaceMutex; + mutable std::mutex m_lastConnectedSSIDMutex; std::map, IpFamilyCache> m_ipCacheMap; mutable std::mutex m_ipCacheMutex; }; diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 65b2fc4ba..057ba1bf6 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -590,8 +590,9 @@ namespace WPEFramework if(enabled && interface == nmUtils::wlanIface() && _instance != NULL) { sleep(1); // wait for 1 sec to change the device state - NMLOG_INFO("Activating connection '%s' ...", _instance->m_lastConnectedSSID.c_str()); - wifi->activateKnownConnection(nmUtils::wlanIface(), _instance->m_lastConnectedSSID); + const string lastConnectedSSID = _instance->getLastConnectedSSID(); + NMLOG_INFO("Activating connection '%s' ...", lastConnectedSSID.c_str()); + wifi->activateKnownConnection(nmUtils::wlanIface(), lastConnectedSSID); } } @@ -814,8 +815,9 @@ namespace WPEFramework if(ssid.ssid.empty()) { - NMLOG_WARNING("ssid is empty activating last connected ssid !"); - if(_instance != NULL && wifi->activateKnownConnection(nmUtils::wlanIface(), _instance->m_lastConnectedSSID)) + const string lastConnectedSSID = _instance->getLastConnectedSSID(); + NMLOG_WARNING("ssid is empty activating last connected ssid (%s) !", lastConnectedSSID.c_str()); + if(_instance != NULL && wifi->activateKnownConnection(nmUtils::wlanIface(), lastConnectedSSID)) { rc = Core::ERROR_NONE; } diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp index 5bbbaf078..15c9be098 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp @@ -979,8 +979,9 @@ namespace WPEFramework // Wait for 1 sec to change the device state sleep(1); if(interface == GnomeUtils::getWifiIfname() && _instance != nullptr) { - NMLOG_INFO("Activating connection '%s' ...", _instance->m_lastConnectedSSID.c_str()); - activateKnownConnection(GnomeUtils::getWifiIfname(), _instance->m_lastConnectedSSID); + const std::string lastConnectedSSID = _instance->getLastConnectedSSID(); + NMLOG_INFO("Activating connection '%s' ...", lastConnectedSSID.c_str()); + activateKnownConnection(GnomeUtils::getWifiIfname(), lastConnectedSSID); } else if(interface == GnomeUtils::getEthIfname()) { NMLOG_INFO("Activating connection 'Wired connection 1' ..."); diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp index 3cbb977ec..0f8a0ddf9 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp @@ -286,8 +286,9 @@ namespace WPEFramework if(ssid.ssid.empty() && _instance != NULL) { - NMLOG_WARNING("ssid is empty activating last connected ssid !"); - if(_nmGdbusClient->activateKnownConnection(GnomeUtils::getWifiIfname(), _instance->m_lastConnectedSSID)) + const string lastConnectedSSID = _instance->getLastConnectedSSID(); + NMLOG_WARNING("ssid is empty activating last connected ssid (%s) !", lastConnectedSSID.c_str()); + if(_nmGdbusClient->activateKnownConnection(GnomeUtils::getWifiIfname(), lastConnectedSSID)) rc = Core::ERROR_NONE; } else if(ssid.ssid.size() <= 32) From 4a81a71b2a51dacd14de014bc90c8f9fd35a52d9 Mon Sep 17 00:00:00 2001 From: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Date: Mon, 31 Aug 2026 20:21:59 +0530 Subject: [PATCH 260/271] RDK-61898: Internet Status Publishing in Deep Sleep Scenarios (#340) * connectivity monitor tirgger for connectivity check * updated connectivity ideal thread * updated error * internet status change trigger updated * updated log line * updated review commments * Comment line change Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * copilot review comment addressed --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- plugin/NetworkManagerConnectivity.cpp | 13 ++++--------- plugin/NetworkManagerImplementation.cpp | 4 ++++ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/plugin/NetworkManagerConnectivity.cpp b/plugin/NetworkManagerConnectivity.cpp index 93825d512..57243aaef 100644 --- a/plugin/NetworkManagerConnectivity.cpp +++ b/plugin/NetworkManagerConnectivity.cpp @@ -634,21 +634,15 @@ namespace WPEFramework return false; } - string defaultIface = _instance->getDefaultInterface(); - - if(defaultIface.empty()) - { - NMLOG_WARNING("default interface not set"); - return false; - } - m_notify = true; m_switchToInitial = true; m_wakeupMonitoring = true; m_cmCv.notify_one(); + string defaultIface = _instance->getDefaultInterface(); NMLOG_INFO("switching to initial check - eth %s - wlan %s - default interface %s", - _instance->m_ethConnected.load()? "up":"down", _instance->m_wlanConnected.load()? "up":"down", defaultIface.c_str()); + _instance->m_ethConnected.load()? "up":"down", _instance->m_wlanConnected.load()? "up":"down", + defaultIface.empty() ? "none" : defaultIface.c_str()); return true; } @@ -704,6 +698,7 @@ namespace WPEFramework if(defaultIface.empty()) { NMLOG_WARNING("default interface not set"); + currentInternetState = INTERNET_NOT_AVAILABLE; if (InitialRetryCount == 0) m_notify = true; InitialRetryCount = 1; diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 8325a9453..efdba7faa 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1481,6 +1481,8 @@ namespace WPEFramework { NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — WiFi was not connected or was already down before sleep, skipping reconnect"); } + // DeepSleep wake (Network Standby OFF): re-verify connectivity so internet status is re-published. + connectivityMonitor.switchToInitialCheck(); } sendAck(); } @@ -1519,6 +1521,8 @@ namespace WPEFramework NMLOG_ERROR("OnPowerModeChanged: ReacquireDHCPLease(eth0) failed"); } } + // DeepSleep → Standby wake (Network Standby ON): re-verify connectivity so internet status is re-published. + connectivityMonitor.switchToInitialCheck(); } } From 27b7fa0b8154d3ab72b327ef7b38be7df047f985 Mon Sep 17 00:00:00 2001 From: me-ha-p Date: Tue, 1 Sep 2026 20:47:51 +0530 Subject: [PATCH 261/271] RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Info (#336) * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Enhance onWiFiStateChange event payload to include the connected or affected Wi-Fi SSID. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Enhance onWiFiStateChange event payload to include the connected or affected Wi-Fi SSID. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Enhance onWiFiStateChange event payload to include the connected or affected Wi-Fi SSID. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Enhance onWiFiStateChange event payload to include the connected or affected Wi-Fi SSID. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Enhance onWiFiStateChange event payload to include the connected or affected Wi-Fi SSID. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Enhance onWiFiStateChange event payload to include the connected or affected Wi-Fi SSID. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Enhance onWiFiStateChange event payload to include the connected or affected Wi-Fi SSID. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Enhance onWiFiStateChange event payload to include the connected or affected Wi-Fi SSID. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Enhance onWiFiStateChange event payload to include the connected or affected Wi-Fi SSID. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Enhance onWiFiStateChange event payload to include the connected or affected Wi-Fi SSID. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Enhance onWiFiStateChange event payload to include the connected or affected Wi-Fi SSID. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * Updated to address tab and default value Signed-off-by: Karunakaran A * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com * RDKEMW-22842: onWiFiStateChange Event to Include Wi-Fi Profile Information Reason for change: onWiFiStateChange event currently reports only the Wi-Fi connection state. Enhance onWiFiStateChange event payload to include the connected or affected Wi-Fi SSID. Priority: P1 Test Procedure: Refer ticket Risks: Low Signed-off-by: Mehavarshni_Palaniswamy@comcast.com --------- Signed-off-by: Mehavarshni_Palaniswamy@comcast.com Signed-off-by: Karunakaran A Co-authored-by: mpalan315 Co-authored-by: Karunakaran A --- definition/NetworkManager.json | 8 +++- docs/NetworkManagerPlugin.md | 4 +- interface/INetworkManager.h | 2 +- plugin/NetworkManager.h | 6 +-- plugin/NetworkManagerImplementation.cpp | 41 +++++++++++------- plugin/NetworkManagerImplementation.h | 5 ++- plugin/NetworkManagerJsonRpc.cpp | 3 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 42 +++++++++++-------- plugin/gnome/NetworkManagerGnomeEvents.h | 2 +- plugin/gnome/NetworkManagerGnomeProxy.cpp | 7 ++-- plugin/gnome/NetworkManagerGnomeWIFI.cpp | 16 +++---- .../gnome/gdbus/NetworkManagerGdbusClient.cpp | 14 +++---- .../gnome/gdbus/NetworkManagerGdbusEvent.cpp | 2 +- .../gnome/gdbus/NetworkManagerGdbusProxy.cpp | 2 +- plugin/rdk/NetworkManagerRDKProxy.cpp | 4 +- tools/plugincli/NetworkManagerGdbusTest.cpp | 4 +- tools/plugincli/NetworkManagerLibnmTest.cpp | 2 +- 17 files changed, 97 insertions(+), 67 deletions(-) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 014a649f5..b85d5e3cb 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -1556,11 +1556,17 @@ "summary": "WiFi status", "type": "string", "example": "WIFI_STATE_CONNECTED" + }, + "ssid": { + "summary": "The SSID associated with the Wi-Fi profile causing the state transition. Disconnected state, contains the SSID associated with the connection that was disconnected. The SSID will be empty when WPS initiated and no AP found with WPS enabled.", + "type": "string", + "example": "myHomeSSID" } }, "required": [ "state", - "status" + "status", + "ssid" ] } }, diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 74341a26b..31ff2ca96 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -1966,6 +1966,7 @@ Triggered when WIFI connection state get changed. The possible states are define | params | object | | | params.state | integer | WiFi State | | params.status | string | WiFi status | +| params.ssid | string | The SSID associated with the Wi-Fi profile causing the state transition. Disconnected state, contains the SSID associated with the connection that was disconnected | ### Example @@ -1975,7 +1976,8 @@ Triggered when WIFI connection state get changed. The possible states are define "method": "client.events.1.onWiFiStateChange", "params": { "state": 5, - "status": "WIFI_STATE_CONNECTED" + "status": "WIFI_STATE_CONNECTED", + "ssid": "myHomeSSID" } } ``` diff --git a/interface/INetworkManager.h b/interface/INetworkManager.h index ce8cb5090..8e6cabeae 100644 --- a/interface/INetworkManager.h +++ b/interface/INetworkManager.h @@ -286,7 +286,7 @@ namespace WPEFramework // WiFi Notifications that other processes can subscribe to virtual void onAvailableSSIDs(const string jsonOfScanResults /* @in */){}; - virtual void onWiFiStateChange(const WiFiState state /* @in */){}; + virtual void onWiFiStateChange(const WiFiState state /* @in */, const string ssid /* @in */){}; virtual void onWiFiSignalQualityChange(const string ssid /* @in */, const int strength /* @in */, const int noise /* @in */, const int snr /* @in */, const WiFiSignalQuality quality /* @in */){}; }; diff --git a/plugin/NetworkManager.h b/plugin/NetworkManager.h index 6a101bdf7..d8a47e77c 100644 --- a/plugin/NetworkManager.h +++ b/plugin/NetworkManager.h @@ -89,9 +89,9 @@ namespace WPEFramework _parent.onAvailableSSIDs(jsonOfScanResults); } - void onWiFiStateChange(const Exchange::INetworkManager::WiFiState state) override + void onWiFiStateChange(const Exchange::INetworkManager::WiFiState state, const string ssid) override { - _parent.onWiFiStateChange(state); + _parent.onWiFiStateChange(state, ssid); } void onWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality) override @@ -262,7 +262,7 @@ namespace WPEFramework void onIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status); void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface); void onAvailableSSIDs(const string jsonOfScanResults); - void onWiFiStateChange(const Exchange::INetworkManager::WiFiState state); + void onWiFiStateChange(const Exchange::INetworkManager::WiFiState state, const string ssid); void onWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality); private: diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index efdba7faa..8d90d17ee 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -424,7 +424,7 @@ namespace WPEFramework NetworkManagerLogger::SetLevel(static_cast(level)); platform_logging(static_cast(level)); NMLOG_DEBUG("loglevel %d", level); - return Core::ERROR_NONE; + return Core::ERROR_NONE; } /* @brief Get the network manager plugin log level */ @@ -626,8 +626,8 @@ namespace WPEFramework } void NetworkManagerImplementation::filterScanResults(JsonArray &ssids, - const std::vector& filterSsidslist, - const std::vector& filterFrequencies) + const std::vector& filterSsidslist, + const std::vector& filterFrequencies) { LOG_ENTRY_FUNCTION(); JsonArray result; @@ -818,7 +818,7 @@ namespace WPEFramework NMLOG_INFO("Publishing onWiFiStateChange Event"); const auto& eventData = std::get(data); for (const auto callback : callbacks) { - callback->onWiFiStateChange(eventData.state); + callback->onWiFiStateChange(eventData.state, eventData.ssid); callback->Release(); } } @@ -1037,7 +1037,7 @@ namespace WPEFramework NMLOG_DEBUG("Discovered %d SSIDs before filtering as,", filterResult.Length()); logSSIDs(LOG_LEVEL_DEBUG, filterResult); - // Snapshot filter vectors under lock, then release before calling filterScanResults + // Snapshot filter vectors under lock, then release before calling filterScanResults // to ensure exception-safety (std::stod can throw). std::vector ssidsSnapshot; std::vector frequenciesSnapshot; @@ -1164,7 +1164,7 @@ namespace WPEFramework { freqValue = value; } - else if (key == "LINKSPEED") + else if (key == "LINKSPEED") { linkSpeed = value; } @@ -1327,9 +1327,6 @@ namespace WPEFramework GetWiFiSignalQuality(ssid, strength, noise, snr, newSignalQuality); - if (!ssid.empty()) - setLastConnectedSSID(ssid); // last connected ssid used in wifiConnect - if (oldSignalQuality != newSignalQuality) { oldSignalQuality = newSignalQuality; NetworkManagerImplementation::ReportWiFiSignalQualityChange(ssid, strength, noise, snr, newSignalQuality); @@ -1351,29 +1348,46 @@ namespace WPEFramework m_stopThread.store(false); } - void NetworkManagerImplementation::ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state) + void NetworkManagerImplementation::ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state, const string ssid) { LOG_ENTRY_FUNCTION(); + + std::string reportSSID; + /* start signal strength monitor when wifi connected */ if(INetworkManager::WiFiState::WIFI_STATE_CONNECTED == state) { m_wlanConnected.store(true); + if(!ssid.empty()) + { + setLastConnectedSSID(ssid); + reportSSID = ssid; + } + else + { + reportSSID = getLastConnectedSSID(); + } startWiFiSignalQualityMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC); } else { stopWiFiSignalQualityMonitor(); m_wlanConnected.store(false); /* Any other state is considered as WiFi not connected. */ + + if(INetworkManager::WiFiState::WIFI_STATE_DISCONNECTED == state) + reportSSID = getLastConnectedSSID(); /* previously connected SSID, or empty */ + else + reportSSID = ssid; /* SSID currently being attempted */ } - NMLOG_INFO("Posting onWiFiStateChange (%d)", state); + NMLOG_INFO("Posting onWiFiStateChange (%d) ssid: %s", state, reportSSID.c_str()); #if USE_TELEMETRY string stateStr = Core::EnumerateType(state).Data(); NMLOG_INFO("NM_WIFI_STATUS = %s", stateStr.c_str()); logTelemetry("NM_WIFI_STATUS", stateStr); #endif { - WiFiStateChangeData eventData{state}; + WiFiStateChangeData eventData{state, reportSSID}; enqueueEvent(NM_ON_WIFISTATE_CHANGE, std::move(eventData)); } } @@ -1460,8 +1474,7 @@ namespace WPEFramework const std::string lastConnectedSSID = getLastConnectedSSID(); if (!lastConnectedSSID.empty()) { - NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting to '%s'", - lastConnectedSSID.c_str()); + NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — reconnecting to '%s'", lastConnectedSSID.c_str()); uint32_t rcWifiUp = ConnectToKnownSSID(lastConnectedSSID); if (rcWifiUp == Core::ERROR_NONE) { diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 1b6cb6c51..81f148cf8 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -251,6 +251,7 @@ namespace WPEFramework struct WiFiStateChangeData { Exchange::INetworkManager::WiFiState state; + string ssid; }; struct WiFiSignalQualityChangeData { @@ -372,7 +373,7 @@ namespace WPEFramework void ReportIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status); void ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface); void ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults); - void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); + void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state, const string ssid); void ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality); void logTelemetry(const std::string& eventName, const std::string& message); @@ -450,7 +451,6 @@ namespace WPEFramework std::atomic m_wlanEnabled; std::atomic m_ethDisconnectedForSleep; std::atomic m_wlanDisconnectedForSleep; - std::string m_lastConnectedSSID; GMainContext *m_nmContext{nullptr}; /* isolated context for per-call NMClient creation */ mutable ConnectivityMonitor connectivityMonitor; @@ -481,6 +481,7 @@ namespace WPEFramework private: string m_defaultInterface; mutable std::mutex m_defaultInterfaceMutex; + std::string m_lastConnectedSSID; mutable std::mutex m_lastConnectedSSIDMutex; std::map, IpFamilyCache> m_ipCacheMap; mutable std::mutex m_ipCacheMutex; diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index 053ba8f7f..d16f5f0d0 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -1127,12 +1127,13 @@ namespace WPEFramework Notify(_T("onAvailableSSIDs"), parameters); } - void NetworkManager::onWiFiStateChange(const Exchange::INetworkManager::WiFiState state) + void NetworkManager::onWiFiStateChange(const Exchange::INetworkManager::WiFiState state, const string ssid) { JsonObject parameters; Core::JSON::EnumType iState{state}; parameters["state"] = JsonValue(state); parameters["status"] = iState.Data(); + parameters["ssid"] = ssid; LOG_INPARAM(); Notify(_T("onWiFiStateChange"), parameters); diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 35793d79b..739c00763 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -332,32 +332,40 @@ namespace WPEFramework return; } std::string wifiState; + /* SSID NM is activating (pairing/connecting); empty once the activation is torn down */ + std::string attemptingSSID = ""; + if(NMActiveConnection *wifiActiveConn = nm_device_get_active_connection(device)) + { + const char* connId = nm_active_connection_get_id(wifiActiveConn); + if(connId != NULL) + attemptingSSID = connId; + } switch (reason) { case NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE: wifiState = "WIFI_STATE_UNINSTALLED"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_UNINSTALLED); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_UNINSTALLED, attemptingSSID); break; case NM_DEVICE_STATE_REASON_SSID_NOT_FOUND: wifiState = "WIFI_STATE_SSID_NOT_FOUND"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND, attemptingSSID); break; case NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT: // supplicant took too long to authenticate case NM_DEVICE_STATE_REASON_NO_SECRETS: wifiState = "WIFI_STATE_AUTHENTICATION_FAILED"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_AUTHENTICATION_FAILED); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_AUTHENTICATION_FAILED, attemptingSSID); break; case NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED: // 802.1x supplicant failed wifiState = "WIFI_STATE_ERROR"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_ERROR); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_ERROR, attemptingSSID); break; case NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED: // 802.1x supplicant configuration failed wifiState = "WIFI_STATE_CONNECTION_INTERRUPTED"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTION_INTERRUPTED); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTION_INTERRUPTED, attemptingSSID); break; case NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT: // 802.1x supplicant disconnected wifiState = "WIFI_STATE_INVALID_CREDENTIALS"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_INVALID_CREDENTIALS); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_INVALID_CREDENTIALS, attemptingSSID); break; default: { @@ -365,14 +373,14 @@ namespace WPEFramework { case NM_DEVICE_STATE_UNKNOWN: wifiState = "WIFI_STATE_UNINSTALLED"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_UNINSTALLED); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_UNINSTALLED, attemptingSSID); refreshIpFamilyCache(device, false); refreshIpFamilyCache(device, true); GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::wlanIface()); break; case NM_DEVICE_STATE_UNMANAGED: wifiState = "WIFI_STATE_DISABLED"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_DISABLED); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_DISABLED, attemptingSSID); refreshIpFamilyCache(device, false); refreshIpFamilyCache(device, true); GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_REMOVED, nmUtils::wlanIface()); @@ -381,23 +389,23 @@ namespace WPEFramework case NM_DEVICE_STATE_UNAVAILABLE: case NM_DEVICE_STATE_DISCONNECTED: wifiState = "WIFI_STATE_DISCONNECTED"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_DISCONNECTED); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_DISCONNECTED, attemptingSSID); refreshIpFamilyCache(device, false); refreshIpFamilyCache(device, true); GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_DOWN, nmUtils::wlanIface()); break; case NM_DEVICE_STATE_PREPARE: wifiState = "WIFI_STATE_PAIRING"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_PAIRING); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_PAIRING, attemptingSSID); break; case NM_DEVICE_STATE_CONFIG: wifiState = "WIFI_STATE_CONNECTING"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTING); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTING, attemptingSSID); break; case NM_DEVICE_STATE_IP_CONFIG: wifiState = "NM_DEVICE_STATE_IP_CONFIG"; GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_LINK_UP, nmUtils::wlanIface()); - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTED, attemptingSSID); break; case NM_DEVICE_STATE_IP_CHECK: wifiState = "NM_DEVICE_STATE_IP_CHECK"; @@ -409,7 +417,7 @@ namespace WPEFramework break; case NM_DEVICE_STATE_ACTIVATED: wifiState = "WIFI_STATE_CONNECTED"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTED, attemptingSSID); #if USE_TELEMETRY { static std::string lastWlanGatewayMac; @@ -427,11 +435,11 @@ namespace WPEFramework break; case NM_DEVICE_STATE_DEACTIVATING: wifiState = "WIFI_STATE_CONNECTION_LOST"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTION_LOST); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTION_LOST, attemptingSSID); break; case NM_DEVICE_STATE_FAILED: wifiState = "WIFI_STATE_CONNECTION_FAILED"; - GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED); + GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED, attemptingSSID); break; case NM_DEVICE_STATE_NEED_AUTH: //GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTION_INTERRUPTED); @@ -936,11 +944,11 @@ namespace WPEFramework _instance->ReportInterfaceStateChange(static_cast(newState), iface); } - void GnomeNetworkManagerEvents::onWIFIStateChanged(uint8_t state) + void GnomeNetworkManagerEvents::onWIFIStateChanged(uint8_t state, std::string ssid) { if(_instance != nullptr) { - _instance->ReportWiFiStateChange(static_cast(state)); + _instance->ReportWiFiStateChange(static_cast(state), ssid); #ifdef ENABLE_MIGRATION_MFRMGR_SUPPORT // Handle WiFi state changes for MfrMgr integration NetworkManagerMfrManager* mfrManager = NetworkManagerMfrManager::getInstance(); diff --git a/plugin/gnome/NetworkManagerGnomeEvents.h b/plugin/gnome/NetworkManagerGnomeEvents.h index 2bc31f9b1..acf78a9cf 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.h +++ b/plugin/gnome/NetworkManagerGnomeEvents.h @@ -54,7 +54,7 @@ namespace WPEFramework static void onInterfaceStateChangeCb(uint8_t newState, std::string iface); // ReportInterfaceStateChange static void onActiveInterfaceChangeCb(std::string newInterface); // ReportActiveInterfaceChange static void onAvailableSSIDsCb(NMDeviceWifi *wifiDevice, GParamSpec *pspec, gpointer userData); // ReportAvailableSSIDs - static void onWIFIStateChanged(uint8_t state); // ReportWiFiStateChange + static void onWIFIStateChanged(uint8_t state, std::string ssid = ""); // ReportWiFiStateChange static void deviceStateChangeCb(NMDevice *device, GParamSpec *pspec, NMEvents *nmEvents); /* Interface-state cache: sole writer is the event monitor; readers diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 057ba1bf6..7c877f5fe 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -590,7 +590,7 @@ namespace WPEFramework if(enabled && interface == nmUtils::wlanIface() && _instance != NULL) { sleep(1); // wait for 1 sec to change the device state - const string lastConnectedSSID = _instance->getLastConnectedSSID(); + const string lastConnectedSSID = getLastConnectedSSID(); NMLOG_INFO("Activating connection '%s' ...", lastConnectedSSID.c_str()); wifi->activateKnownConnection(nmUtils::wlanIface(), lastConnectedSSID); } @@ -815,9 +815,8 @@ namespace WPEFramework if(ssid.ssid.empty()) { - const string lastConnectedSSID = _instance->getLastConnectedSSID(); - NMLOG_WARNING("ssid is empty activating last connected ssid (%s) !", lastConnectedSSID.c_str()); - if(_instance != NULL && wifi->activateKnownConnection(nmUtils::wlanIface(), lastConnectedSSID)) + NMLOG_WARNING("ssid is empty activating last connected ssid !"); + if(_instance != NULL && wifi->activateKnownConnection(nmUtils::wlanIface(), getLastConnectedSSID())) { rc = Core::ERROR_NONE; } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index c75063340..148e54ef2 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -1366,14 +1366,14 @@ namespace WPEFramework if(ssidInfo.bssid.empty()) { NMLOG_INFO("'%s' Already connected !", connectedApInfo.ssid.c_str()); - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED, connectedApInfo.ssid); deleteClientConnection(); return true; } else if (strcasecmp(ssidInfo.bssid.c_str(), connectedApInfo.bssid.c_str()) == 0) { NMLOG_INFO("Already connected to the requested SSID '%s' with matching BSSID", ssidInfo.ssid.c_str()); - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED, connectedApInfo.ssid); deleteClientConnection(); return true; } @@ -2042,7 +2042,7 @@ namespace WPEFramework bool wpsActionTriggerd = false; if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTING); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTING, ""); for(int retry = 0; retry < WPS_RETRY_COUNT; retry++) { @@ -2105,7 +2105,7 @@ namespace WPEFramework if(state <= NM_DEVICE_STATE_DISCONNECTED) { if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND, wifiConnectInfo.ssid); // TODO post correct error code insted of WIFI_STATE_SSID_NOT_FOUND // sedning WIFI_STATE_SSID_NOT_FOUND to avoid UI stuck issue break; @@ -2124,7 +2124,7 @@ namespace WPEFramework // wifi state stuck in betwen disconnected and connected NMLOG_ERROR("WPS process failed"); if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND, wifiConnectInfo.ssid); // TODO post correct error code insted of WIFI_STATE_SSID_NOT_FOUND // sedning WIFI_STATE_SSID_NOT_FOUND to avoid UI stuck issue } @@ -2155,7 +2155,7 @@ namespace WPEFramework wpsComplete = true; //TODO Post SSID connected event ? if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED, wpsApInfo.ssid); } else @@ -2254,13 +2254,13 @@ namespace WPEFramework { NMLOG_WARNING("WPS AP not found"); if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND, ""); } else if(!wpsComplete) { NMLOG_INFO("WPS process Error"); if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED, wifiConnectInfo.ssid); } if(wpsContext != NULL) diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp index 15c9be098..1ee31c41b 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusClient.cpp @@ -2503,7 +2503,7 @@ namespace WPEFramework { NMLOG_INFO("'%s' already connected !", currentSSID.ssid.c_str()); if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED, currentSSID.ssid); return true; } else @@ -2989,7 +2989,7 @@ namespace WPEFramework { NMLOG_WARNING("WPS process failed - device in disconnected state"); if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND, ssidinfo.ssid); break; } else if(devProperty.state > NM_DEVICE_STATE_NEED_AUTH) @@ -2997,7 +2997,7 @@ namespace WPEFramework NMLOG_INFO("WPS process completed successfully"); wpsComplete = true; if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED, ssidinfo.ssid); break; } @@ -3006,7 +3006,7 @@ namespace WPEFramework { NMLOG_ERROR("WPS process failed - timeout"); if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED, ssidinfo.ssid); break; } continue; @@ -3030,7 +3030,7 @@ namespace WPEFramework NMLOG_INFO("WPS process stopped - already connected to WPS AP '%s'", ssidinfo.ssid.c_str()); wpsComplete = true; if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTED, ssidinfo.ssid); break; } @@ -3066,13 +3066,13 @@ namespace WPEFramework { NMLOG_WARNING("WPS AP not found"); if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_SSID_NOT_FOUND, ssidinfo.ssid); } else if(!wpsComplete && m_wpsActionTriggered) { NMLOG_INFO("WPS process error"); if(_instance != nullptr) - _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED); + _instance->ReportWiFiStateChange(Exchange::INetworkManager::WIFI_STATE_CONNECTION_FAILED, ssidinfo.ssid); } NMLOG_INFO("WPS process thread exit"); diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp index d0c50c409..8811f5dc7 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusEvent.cpp @@ -690,7 +690,7 @@ namespace WPEFramework { NMLOG_DEBUG("wifi state changed: %d ; NM wifi: %s", state, wifiStateStr.c_str()); if(_instance != nullptr) - _instance->ReportWiFiStateChange(static_cast(state)); + _instance->ReportWiFiStateChange(static_cast(state), ""); } void NetworkManagerEvents::onAddressChangeCb(std::string iface, bool acquired, bool isIPv6, std::string ipAddress) diff --git a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp index 0f8a0ddf9..33254fc4d 100644 --- a/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp +++ b/plugin/gnome/gdbus/NetworkManagerGdbusProxy.cpp @@ -286,7 +286,7 @@ namespace WPEFramework if(ssid.ssid.empty() && _instance != NULL) { - const string lastConnectedSSID = _instance->getLastConnectedSSID(); + const string lastConnectedSSID = getLastConnectedSSID(); NMLOG_WARNING("ssid is empty activating last connected ssid (%s) !", lastConnectedSSID.c_str()); if(_nmGdbusClient->activateKnownConnection(GnomeUtils::getWifiIfname(), lastConnectedSSID)) rc = Core::ERROR_NONE; diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index b6b70e1a2..e8be4680b 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -282,7 +282,7 @@ namespace WPEFramework Exchange::INetworkManager::WiFiState state = Exchange::INetworkManager::WIFI_STATE_DISCONNECTED; NMLOG_INFO("Event IARM_BUS_WIFI_MGR_EVENT_onWIFIStateChanged received; state=%d", e->data.wifiStateChange.state); state = to_wifi_state(e->data.wifiStateChange.state); - ::_instance->ReportWiFiStateChange(state); + ::_instance->ReportWiFiStateChange(state, ""); break; } case IARM_BUS_WIFI_MGR_EVENT_onError: @@ -290,7 +290,7 @@ namespace WPEFramework IARM_BUS_WiFiSrvMgr_EventData_t* e = (IARM_BUS_WiFiSrvMgr_EventData_t *) data; Exchange::INetworkManager::WiFiState state = errorcode_to_wifi_state(e->data.wifiError.code); NMLOG_INFO("Event IARM_BUS_WIFI_MGR_EVENT_onError received; code=%d", e->data.wifiError.code); - ::_instance->ReportWiFiStateChange(state); + ::_instance->ReportWiFiStateChange(state, ""); break; } default: diff --git a/tools/plugincli/NetworkManagerGdbusTest.cpp b/tools/plugincli/NetworkManagerGdbusTest.cpp index b44ee8720..fd28a945f 100644 --- a/tools/plugincli/NetworkManagerGdbusTest.cpp +++ b/tools/plugincli/NetworkManagerGdbusTest.cpp @@ -59,9 +59,9 @@ namespace WPEFramework { NMLOG_INFO("calling 'ReportAvailableSSIDs' cb"); } - void NetworkManagerImplementation::ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state) + void NetworkManagerImplementation::ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state, const string ssid) { - NMLOG_INFO("calling 'ReportWiFiStateChange' cb"); + NMLOG_INFO("calling 'ReportWiFiStateChange' cb (state=%d, ssid='%s')", state, ssid.c_str()); } void NetworkManagerImplementation::ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality) { diff --git a/tools/plugincli/NetworkManagerLibnmTest.cpp b/tools/plugincli/NetworkManagerLibnmTest.cpp index 3a358b565..924a9f7ad 100644 --- a/tools/plugincli/NetworkManagerLibnmTest.cpp +++ b/tools/plugincli/NetworkManagerLibnmTest.cpp @@ -58,7 +58,7 @@ namespace WPEFramework { NMLOG_INFO("calling 'ReportAvailableSSIDs' cb"); } - void NetworkManagerImplementation::ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state) + void NetworkManagerImplementation::ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state, const string ssid) { NMLOG_INFO("calling 'ReportWiFiStateChange' cb"); } From ff3b475c5308ac50152abdebc986ee4d46288127 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Tue, 1 Sep 2026 23:14:16 -0400 Subject: [PATCH 262/271] RDK-61724: Update Network Manager to publish a new event for route change. (#328) * onroutechange event implementation * Added macro to conditional compilation * Modified the code to have separate client to get connectivity status form the connectivity plugin * Added RFC for connectivity manager enabling in networkmanager * Added enable of USE_RFCAPI in proper place * updated with macro USE_CONNECTIVITYCHECKMGR * Added the documentation * Added Bridging of events between networkmanager and connectivity manager * Addressed the crash issue * To Fix the crash * Added reason for isconnectedtointernet API * Updated with compilation issue fix * Added cache logic to read the internet status from connectivitymgr plugin * Changed the reason into default instead of function overloading * Changed connected field to return true for LIMITED_INTERNET state only when connectivitymgr plugin is in use * Fixed compilation issue * Addressed copilot review comments * Addressed copilot review comments * Added more clarity to documentation for reason. Also added copilot review comments * Added reason to the oninternetstatuschange event * Addressed the review comment * Addressed copilot review comments * Addressed review comments * To fix L1 and L2 issue * For rdk proxy this test is not required * Update name of the RFC return code Update name of the RFC return code * Updated with review comments * Corrected variable name * Updated the missed change * Added header chrono * Fixed L1 and L2 issue * Fixed L1 and L2 issue * Change ConnectivityMonitor to non smart pointer to match old way * Fixed compilation issue * Addressed L1 test failure * To test * Removed unused code * Update NetworkManagerImplementation.cpp --------- Co-authored-by: Gururaaja E S R Co-authored-by: RAFI <103924677+cmuhammedrafi@users.noreply.github.com> Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> --- .github/workflows/gdbus_proxy_L1_test.yml | 7 + .github/workflows/legacy_L1_L2_test.yml | 7 + .github/workflows/libnm_proxy_L1_test.yml | 7 + .github/workflows/rdk_proxy_L1_L2_test.yml | 7 + CMakeLists.txt | 11 + definition/NetworkManager.json | 55 ++- docs/NetworkManagerPlugin.md | 39 +- interface/INetworkManager.h | 14 +- plugin/CMakeLists.txt | 27 +- plugin/NetworkManager.cpp | 16 + plugin/NetworkManager.h | 13 +- plugin/NetworkManagerConnectivityClient.cpp | 342 ++++++++++++++++++ plugin/NetworkManagerConnectivityClient.h | 145 ++++++++ plugin/NetworkManagerImplementation.cpp | 229 ++++++++++-- plugin/NetworkManagerImplementation.h | 28 +- plugin/NetworkManagerJsonRpc.cpp | 27 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 26 ++ tests/l1Test/l1_test_connectivity.cpp | 2 +- .../l2_test_LegacyPlugin_NetworkAPIs.cpp | 8 +- tests/l2Test/libnm/CMakeLists.txt | 13 + tests/l2Test/rdk/CMakeLists.txt | 13 + tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp | 74 ++++ tests/l2Test/rdk/l2_test_rdkproxyImpl.cpp | 160 ++++++++ tests/mocks/INetworkManagerMock.h | 2 +- tests/mocks/thunder/IConnectivityCheck.h | 73 ++++ tools/plugincli/NetworkManagerGdbusTest.cpp | 2 +- tools/plugincli/NetworkManagerLibnmTest.cpp | 2 +- 27 files changed, 1296 insertions(+), 53 deletions(-) create mode 100644 plugin/NetworkManagerConnectivityClient.cpp create mode 100644 plugin/NetworkManagerConnectivityClient.h create mode 100644 tests/mocks/thunder/IConnectivityCheck.h diff --git a/.github/workflows/gdbus_proxy_L1_test.yml b/.github/workflows/gdbus_proxy_L1_test.yml index 16edc038e..ea62e0169 100644 --- a/.github/workflows/gdbus_proxy_L1_test.yml +++ b/.github/workflows/gdbus_proxy_L1_test.yml @@ -112,6 +112,13 @@ jobs: IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IPowerManager.h "$IFACE_DIR/" + - name: Install IConnectivityCheck header + run: | + IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) + CPC_IFACE_DIR="$(dirname "$IFACE_DIR")/interfaces_cpc/interfaces" + mkdir -p "$CPC_IFACE_DIR" + cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IConnectivityCheck.h "$CPC_IFACE_DIR/" + - name: Build networkmanager with Gnome GDBUS Proxy run: > cmake diff --git a/.github/workflows/legacy_L1_L2_test.yml b/.github/workflows/legacy_L1_L2_test.yml index 03538a0ae..2fc3eff08 100644 --- a/.github/workflows/legacy_L1_L2_test.yml +++ b/.github/workflows/legacy_L1_L2_test.yml @@ -115,6 +115,13 @@ jobs: IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IPowerManager.h "$IFACE_DIR/" + - name: Install IConnectivityCheck header + run: | + IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) + CPC_IFACE_DIR="$(dirname "$IFACE_DIR")/interfaces_cpc/interfaces" + mkdir -p "$CPC_IFACE_DIR" + cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IConnectivityCheck.h "$CPC_IFACE_DIR/" + - name: Generate IARM headers run: | touch install/usr/lib/libIARMBus.so diff --git a/.github/workflows/libnm_proxy_L1_test.yml b/.github/workflows/libnm_proxy_L1_test.yml index e5f64deff..6a60ae3fa 100644 --- a/.github/workflows/libnm_proxy_L1_test.yml +++ b/.github/workflows/libnm_proxy_L1_test.yml @@ -113,6 +113,13 @@ jobs: IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IPowerManager.h "$IFACE_DIR/" + - name: Install IConnectivityCheck header + run: | + IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) + CPC_IFACE_DIR="$(dirname "$IFACE_DIR")/interfaces_cpc/interfaces" + mkdir -p "$CPC_IFACE_DIR" + cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IConnectivityCheck.h "$CPC_IFACE_DIR/" + - name: Generate dependency files run: | sudo bash -c 'echo "ETHERNET_INTERFACE=eth0 diff --git a/.github/workflows/rdk_proxy_L1_L2_test.yml b/.github/workflows/rdk_proxy_L1_L2_test.yml index fc89bc38e..3871ab948 100644 --- a/.github/workflows/rdk_proxy_L1_L2_test.yml +++ b/.github/workflows/rdk_proxy_L1_L2_test.yml @@ -112,6 +112,13 @@ jobs: IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IPowerManager.h "$IFACE_DIR/" + - name: Install IConnectivityCheck header + run: | + IFACE_DIR=$(find ${{github.workspace}}/install/usr/include -maxdepth 2 -name "interfaces" -type d | head -1) + CPC_IFACE_DIR="$(dirname "$IFACE_DIR")/interfaces_cpc/interfaces" + mkdir -p "$CPC_IFACE_DIR" + cp ${{github.workspace}}/networkmanager/tests/mocks/thunder/IConnectivityCheck.h "$CPC_IFACE_DIR/" + - name: Generate IARM headers run: | touch install/usr/lib/libIARMBus.so diff --git a/CMakeLists.txt b/CMakeLists.txt index f02326d7a..cb8361604 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ option(ENABLE_LEGACY_PLUGINS "Enable Legacy Plugins" ON) option(USE_RDK_LOGGER "Enable RDK Logger for logging" OFF ) option(ENABLE_UNIT_TESTING "Enable unit tests" OFF) option(USE_TELEMETRY "Enable Telemetry T2 support" OFF) +option(USE_CONNECTIVITYCHECKMGR "Enable ConnectivityCheckMgr delegation (compiles the delegation client and reads the TR-181 RFC feature flag via rfcapi)" OFF) option(ENABLE_ETHERNET_CONNECTION_HANDLING "Enable pre-sleep Ethernet deactivation" OFF) @@ -77,6 +78,16 @@ if (USE_TELEMETRY) message("Telemetry support enabled") endif(USE_TELEMETRY) +# Optional ConnectivityCheckMgr delegation. Compiles the delegation client and pulls +# in the rfcapi library used to read the TR-181 RFC feature flag at runtime, e.g. +# Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.ConnectivityCheckMgr.Enable. +if (USE_CONNECTIVITYCHECKMGR) + find_library(RFCAPI_LIBRARY rfcapi REQUIRED) + find_path(RFCAPI_INCLUDE_DIR rfcapi.h) + add_compile_definitions(USE_CONNECTIVITYCHECKMGR=1) + message(STATUS "ConnectivityCheckMgr delegation enabled (rfcapi lib=${RFCAPI_LIBRARY}, include=${RFCAPI_INCLUDE_DIR})") +endif(USE_CONNECTIVITYCHECKMGR) + add_subdirectory(interface) add_subdirectory(definition) add_subdirectory(plugin) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index b85d5e3cb..15c9ab530 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -609,17 +609,23 @@ "connected": { "summary": "`true` if internet connectivity is detected, otherwise `false`", "type": "boolean", - "example": true + "example": false }, "state": { "summary": "Internet state", "type": "integer", - "example": 3 + "example": 1 }, "status": { "summary": "Internet status", "type": "string", - "example": "FULLY_CONNECTED" + "example": "NO_INTERNET" + }, + "reason": { + "summary": "Reason for current status (present when status is NO_INTERNET)", + "type": "string", + "enum": ["NOT_CONFIGURED", "WAITING_INTERFACE", "WAITING_GATEWAY", "PROBE_FAILED"], + "example": "PROBE_FAILED" }, "success": { "$ref": "#/definitions/success" @@ -1437,6 +1443,36 @@ ] } }, + "onRouteChange":{ + "summary": "Triggered when the default route changes and a new gateway/DNS becomes available for an interface.", + "params": { + "type": "object", + "properties": { + "interface":{ + "$ref": "#/definitions/interface" + }, + "ipversion": { + "$ref": "#/definitions/ipversion" + }, + "ipaddress": { + "$ref": "#/definitions/ipaddress" + }, + "gateway": { + "$ref": "#/definitions/gateway" + }, + "primarydns": { + "$ref": "#/definitions/primarydns" + } + }, + "required": [ + "interface", + "ipversion", + "ipaddress", + "gateway", + "primarydns" + ] + } + }, "onActiveInterfaceChange":{ "summary": "Triggered when the primary/active interface changes", "params": { @@ -1467,27 +1503,32 @@ "prevState":{ "summary": "The previous internet connection state", "type": "integer", - "example": 1 + "example": 3 }, "prevStatus":{ "summary": "The previous internet connection status", "type": "string", - "example": "NO_INTERNET" + "example": "FULLY_CONNECTED" }, "state":{ "summary": "The internet connection state", "type": "integer", - "example": 4 + "example": 1 }, "status":{ "summary": "The internet connection status", "type": "string", - "example": "FULLY_CONNECTED" + "example": "NO_INTERNET" }, "interface":{ "summary": "The internet status change on default interface", "type": "string", "example": "wlan0" + }, + "reason":{ + "summary": "The ConnectivityCheckMgr reason when status is NO_INTERNET", + "type": "string", + "example": "PROBE_FAILED" } }, "required": [ diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 31ff2ca96..94efba092 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -740,6 +740,7 @@ Seeks whether the device has internet connectivity. This API might take up to 5s | result.connected | boolean | `true` if internet connectivity is detected, otherwise `false` | | result.state | integer | Internet state | | result.status | string | Internet status | +| result?.reason | string | *(optional)* Reason for current status (present when status is NO_INTERNET) | | result.success | boolean | Whether the request succeeded | ### Example @@ -768,8 +769,9 @@ Seeks whether the device has internet connectivity. This API might take up to 5s "ipversion": "IPv4", "interface": "wlan0", "connected": true, - "state": 3, - "status": "FULLY_CONNECTED", + "state": 1, + "status": "NO_INTERNET", + "reason": "PROBE_FAILED", "success": true } } @@ -1787,6 +1789,7 @@ NetworkManager interface events: | :-------- | :-------- | | [onInterfaceStateChange](#event.onInterfaceStateChange) | Triggered when an interface state is changed | | [onAddressChange](#event.onAddressChange) | Triggered when an IP Address is assigned or lost | +| [onRouteChange](#event.onRouteChange) | Triggered when the default route changes and a new gateway/DNS becomes available for an interface | | [onActiveInterfaceChange](#event.onActiveInterfaceChange) | Triggered when the primary/active interface changes | | [onInternetStatusChange](#event.onInternetStatusChange) | Triggered when internet connection state changed | | [onAvailableSSIDs](#event.onAvailableSSIDs) | Triggered when scan completes or when scan cancelled | @@ -1858,6 +1861,38 @@ Triggered when an IP Address is assigned or lost. } ``` + +## *onRouteChange [event](#head.Notifications)* + +Triggered when the default route changes and a new gateway/DNS becomes available for an interface. + +### Parameters + +| Name | Type | Description | +| :-------- | :-------- | :-------- | +| params | object | | +| params.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | +| params.ipversion | string | Either IPv4 or IPv6 | +| params.ipaddress | string | The IP address | +| params.gateway | string | The gateway address | +| params.primarydns | string | The primary DNS address | + +### Example + +```json +{ + "jsonrpc": "2.0", + "method": "client.events.1.onRouteChange", + "params": { + "interface": "wlan0", + "ipversion": "IPv4", + "ipaddress": "192.168.1.101", + "gateway": "192.168.1.1", + "primarydns": "192.168.1.1" + } +} +``` + ## *onActiveInterfaceChange [event](#head.Notifications)* diff --git a/interface/INetworkManager.h b/interface/INetworkManager.h index 8e6cabeae..d551f9dec 100644 --- a/interface/INetworkManager.h +++ b/interface/INetworkManager.h @@ -229,8 +229,9 @@ namespace WPEFramework /* @brief Set ConnectivityTest Endpoints */ virtual uint32_t SetConnectivityTestEndpoints(IStringIterator* const endpoints /* @in */) = 0; - /* @brief Get Internet Connectivty Status */ - virtual uint32_t IsConnectedToInternet(string &ipversion /* @inout */, string &interface /* @inout */, InternetStatus& status /* @out */) = 0; + /* @brief Get Internet Connectivity Status */ + virtual uint32_t IsConnectedToInternet(string &ipversion /* @inout */, string &interface /* @inout */, InternetStatus& status /* @out */, string& reason /* @out */ = EmptyReason()) = 0; + /* @brief Get Authentication URL if the device is behind Captive Portal */ virtual uint32_t GetCaptivePortalURI(string &uri/* @out */) const = 0; @@ -282,17 +283,24 @@ namespace WPEFramework virtual void onInterfaceStateChange(const InterfaceState state /* @in */, const string interface /* @in */){}; virtual void onActiveInterfaceChange(const string prevActiveInterface /* @in */, const string currentActiveInterface /* @in */){}; virtual void onIPAddressChange(const string interface /* @in */, const string ipversion /* @in */, const string ipaddress /* @in */, const IPStatus status /* @in */){}; - virtual void onInternetStatusChange(const InternetStatus prevState /* @in */, const InternetStatus currState /* @in */, const string interface /* @in */){}; + virtual void onInternetStatusChange(const InternetStatus prevState /* @in */, const InternetStatus currState /* @in */, const string interface /* @in */, const string reason /* @in */){}; // WiFi Notifications that other processes can subscribe to virtual void onAvailableSSIDs(const string jsonOfScanResults /* @in */){}; virtual void onWiFiStateChange(const WiFiState state /* @in */, const string ssid /* @in */){}; virtual void onWiFiSignalQualityChange(const string ssid /* @in */, const int strength /* @in */, const int noise /* @in */, const int snr /* @in */, const WiFiSignalQuality quality /* @in */){}; + virtual void onRouteChange(const string interface /* @in */, const string ipversion /* @in */, const string ipaddress /* @in */, const string gateway /* @in */, const string primarydns /* @in */){}; }; // Allow other processes to register/unregister from our notifications virtual uint32_t Register(INetworkManager::INotification* notification) = 0; virtual uint32_t Unregister(INetworkManager::INotification* notification) = 0; + private: + static string& EmptyReason() + { + static thread_local string reason; + return reason; + } }; } } diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 588a243da..6f19009db 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -76,15 +76,40 @@ set_target_properties(${MODULE_NAME} PROPERTIES CXX_STANDARD_REQUIRED YES FRAMEWORK FALSE) +if(USE_CONNECTIVITYCHECKMGR) + target_link_libraries(${MODULE_NAME} PRIVATE ${RFCAPI_LIBRARY}) + if(RFCAPI_INCLUDE_DIR) + target_include_directories(${MODULE_NAME} PRIVATE ${RFCAPI_INCLUDE_DIR}) + endif() +endif() add_library(${MODULE_IMPL_NAME} SHARED NetworkManagerImplementation.cpp - NetworkManagerConnectivity.cpp NetworkManagerStunClient.cpp NetworkManagerLogger.cpp NetworkManagerPowerClient.cpp Module.cpp) +# The built-in ConnectivityMonitor is always compiled. The ConnectivityCheckMgr +# delegation client (NetworkManagerConnectivityClient.cpp) is compiled only when +# USE_CONNECTIVITYCHECKMGR is enabled; runtime selection between the two backends +# is done in resolveConnectivityCheckMgrEnabled(). STUN is unaffected either way. +target_sources(${MODULE_IMPL_NAME} PRIVATE + NetworkManagerConnectivity.cpp) + +# Optional ConnectivityCheckMgr delegation. The USE_CONNECTIVITYCHECKMGR option, +# rfcapi library discovery, and the USE_CONNECTIVITYCHECKMGR compile definition are +# declared in the top-level CMakeLists.txt (mirroring USE_TELEMETRY). When enabled we +# compile the delegation client and link the rfcapi library used to read the TR-181 +# feature flag. +if(USE_CONNECTIVITYCHECKMGR) + target_sources(${MODULE_IMPL_NAME} PRIVATE NetworkManagerConnectivityClient.cpp) + target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${RFCAPI_LIBRARY}) + if(RFCAPI_INCLUDE_DIR) + target_include_directories(${MODULE_IMPL_NAME} PRIVATE ${RFCAPI_INCLUDE_DIR}) + endif() +endif() + if(ENABLE_GNOME_NETWORKMANAGER) if(ENABLE_GNOME_GDBUS) message("networkmanager building with gdbus") diff --git a/plugin/NetworkManager.cpp b/plugin/NetworkManager.cpp index 10ed45984..aaeb6a8e6 100644 --- a/plugin/NetworkManager.cpp +++ b/plugin/NetworkManager.cpp @@ -20,6 +20,11 @@ #include "NetworkManager.h" #include +#ifdef USE_CONNECTIVITYCHECKMGR +#include +#include "rfcapi.h" +#endif + namespace WPEFramework { namespace Plugin @@ -40,6 +45,7 @@ namespace WPEFramework _service(nullptr), _networkManagerImpl(nullptr), _networkManager(nullptr), + m_useConnectivityCheckMgr(false), _notification(this) { } @@ -95,6 +101,16 @@ namespace WPEFramework } else { +#ifdef USE_CONNECTIVITYCHECKMGR + RFC_ParamData_t rfcParam = {0}; + const WDMP_STATUS rfcRetCode = getRFCParameter( + const_cast("NetworkManager"), + const_cast("Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.ConnectivityCheckMgr.Enable"), + &rfcParam); + if (rfcRetCode == WDMP_SUCCESS || rfcRetCode == WDMP_ERR_DEFAULT_VALUE) { + m_useConnectivityCheckMgr = (strcasecmp(rfcParam.value, "true") == 0); + } +#endif SYSLOG(Logging::Startup, (_T("Configuring successful"))); } diff --git a/plugin/NetworkManager.h b/plugin/NetworkManager.h index d8a47e77c..dea887e94 100644 --- a/plugin/NetworkManager.h +++ b/plugin/NetworkManager.h @@ -79,9 +79,14 @@ namespace WPEFramework _parent.onIPAddressChange(interface, ipversion, ipaddress, status); } - void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface) override + void onRouteChange(const string interface, const string ipversion, const string ipaddress, const string gateway, const string primarydns) override { - _parent.onInternetStatusChange(prevState, currState, interface); + _parent.onRouteChange(interface, ipversion, ipaddress, gateway, primarydns); + } + + void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface, const string reason) override + { + _parent.onInternetStatusChange(prevState, currState, interface, reason); } void onAvailableSSIDs(const string jsonOfScanResults) override @@ -260,7 +265,8 @@ namespace WPEFramework void onInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface); void onActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface); void onIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status); - void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface); + void onRouteChange(const string interface, const string ipversion, const string ipaddress, const string gateway, const string primarydns); + void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface, const string reason); void onAvailableSSIDs(const string jsonOfScanResults); void onWiFiStateChange(const Exchange::INetworkManager::WiFiState state, const string ssid); void onWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality); @@ -270,6 +276,7 @@ namespace WPEFramework PluginHost::IShell *_service; PluginHost::IPlugin* _networkManagerImpl; Exchange::INetworkManager *_networkManager; + bool m_useConnectivityCheckMgr; Core::Sink _notification; string m_publicIPAddress; string m_publicIPAddressType; diff --git a/plugin/NetworkManagerConnectivityClient.cpp b/plugin/NetworkManagerConnectivityClient.cpp new file mode 100644 index 000000000..db8eeaaa8 --- /dev/null +++ b/plugin/NetworkManagerConnectivityClient.cpp @@ -0,0 +1,342 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2026 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#include "NetworkManagerConnectivityClient.h" +#include "NetworkManagerLogger.h" +#include +#include + +using namespace WPEFramework; +using namespace WPEFramework::Exchange; +using namespace WPEFramework::Plugin; + +// --------------------------------------------------------------------------- +// NetworkManagerConnectivityClient +// --------------------------------------------------------------------------- + +NetworkManagerConnectivityClient::NetworkManagerConnectivityClient() + : mNotification(*this) +{ + NMLOG_INFO("ConnectivityCheckMgr client created; opening link asynchronously"); + mOpenThread = std::thread(&NetworkManagerConnectivityClient::openThreadLoop, this); +} + +NetworkManagerConnectivityClient::~NetworkManagerConnectivityClient() +{ + NMLOG_INFO("shutting down"); + { + std::lock_guard lock(mOpenMutex); + mStopOpenThread = true; + } + mOpenCv.notify_one(); + if (mOpenThread.joinable()) { + mOpenThread.join(); + } + + // Unregister without holding mLock to avoid deadlock when a notification + // arrives concurrently and tries to acquire mLock inside notifyInternetStatusChanged. + unregisterEvents(); + { + std::lock_guard lock(mLock); + if (mConnectivity != nullptr) { + mConnectivity->Release(); + mConnectivity = nullptr; + } + } + Close(Core::infinite); +} + +void NetworkManagerConnectivityClient::openThreadLoop() +{ + constexpr auto retryInterval = std::chrono::seconds(5); + + while (!mStopOpenThread.load()) { + NMLOG_INFO("connecting to ConnectivityCheckMgr"); + const uint32_t r = Open(RPC::CommunicationTimeOut, Connector(), "org.rdk.ConnectivityCheckMgr"); + if (r == Core::ERROR_NONE) { + // Connected; Operational() is invoked by the framework when the proxy is ready. + NMLOG_INFO("link to ConnectivityCheckMgr opened"); + return; + } + + NMLOG_WARNING("failed to open link to ConnectivityCheckMgr (error %u); retrying", r); + + std::unique_lock lock(mOpenMutex); + mOpenCv.wait_for(lock, retryInterval, [this] { return mStopOpenThread.load(); }); + } +} + +bool NetworkManagerConnectivityClient::IsValid() const +{ + LOG_ENTRY_FUNCTION(); + std::lock_guard lock(mLock); + return mConnectivity != nullptr; +} + +void NetworkManagerConnectivityClient::Operational(bool upAndRunning) +{ + NMLOG_DEBUG("Operational(%s)", upAndRunning ? "true" : "false"); + if (upAndRunning) { + { + std::lock_guard lock(mLock); + if (mConnectivity != nullptr) { + return; // already connected + } + mConnectivity = Interface(); + mHasCachedStatus = false; + mCachedStatus = Exchange::INetworkManager::INTERNET_UNKNOWN; + mCachedReason.clear(); + } + // Register without holding mLock: Register() can dispatch a synchronous + // notification on some Thunder builds, which would deadlock if mLock is held. + registerEvents(); + } else { + // Unregister without holding mLock for the same reason. + unregisterEvents(); + std::lock_guard lock(mLock); + if (mConnectivity != nullptr) { + mConnectivity->Release(); + mConnectivity = nullptr; + } + mHasCachedStatus = false; + mCachedStatus = Exchange::INetworkManager::INTERNET_UNKNOWN; + mCachedReason.clear(); + } +} + +Exchange::IConnectivityCheck* NetworkManagerConnectivityClient::acquireInterface() const +{ + std::lock_guard lock(mLock); + if (mConnectivity != nullptr) { + mConnectivity->AddRef(); + } + return mConnectivity; +} + +void NetworkManagerConnectivityClient::SetInternetStatusChangeHandler(InternetStatusChangeHandler handler) +{ + std::unique_lock lock(mLock); + mHandlerDrainCv.wait(lock, [this] { return !mHandlerClearInProgress; }); + + if (handler) { + mInternetStatusChangeHandler = std::move(handler); + return; + } + + // Clearing is a drain barrier. It must not be called by the active handler. + mHandlerClearInProgress = true; + mInternetStatusChangeHandler = nullptr; + mHandlerDrainCv.wait(lock, [this] { return mHandlersInFlight == 0; }); + mHandlerClearInProgress = false; + lock.unlock(); + mHandlerDrainCv.notify_all(); +} + +void NetworkManagerConnectivityClient::registerEvents() +{ + Exchange::IConnectivityCheck* connectivity = nullptr; + { + std::lock_guard lock(mLock); + if (mConnectivity == nullptr || mNotificationRegistered) { + return; + } + // Claim the flag before dropping mLock so a concurrent caller cannot register twice. + mNotificationRegistered = true; + connectivity = mConnectivity; + connectivity->AddRef(); + } + + const uint32_t r = connectivity->Register(&mNotification); + connectivity->Release(); + + if (r != Core::ERROR_NONE) { + NMLOG_ERROR("ConnectivityCheckMgr register(notification) failed (%u)", r); + std::lock_guard lock(mLock); + mNotificationRegistered = false; + return; + } + + NMLOG_INFO("registered for ConnectivityCheckMgr internet-status notifications"); +} + +void NetworkManagerConnectivityClient::unregisterEvents() +{ + Exchange::IConnectivityCheck* connectivity = nullptr; + { + std::lock_guard lock(mLock); + if (!mNotificationRegistered) { + return; + } + mNotificationRegistered = false; + if (mConnectivity == nullptr) { + return; + } + connectivity = mConnectivity; + connectivity->AddRef(); + } + + if (const uint32_t r = connectivity->Unregister(&mNotification); r != Core::ERROR_NONE) { + NMLOG_ERROR("ConnectivityCheckMgr unregister(notification) failed (%u)", r); + } + connectivity->Release(); +} + +void NetworkManagerConnectivityClient::notifyInternetStatusChanged(Exchange::IConnectivityCheck::InternetStatus status, + const std::string& reason) +{ + const NmInternetStatus mapped = mapStatus(status); + // Only NO_INTERNET carries a meaningful reason; keep the handler consistent with the cache. + const std::string filteredReason = (status == Exchange::IConnectivityCheck::NO_INTERNET) ? reason : std::string(); + + InternetStatusChangeHandler handler; + { + std::lock_guard lock(mLock); + mCachedStatus = mapped; + mCachedReason = filteredReason; + mHasCachedStatus = true; + if (mHandlerClearInProgress) { + return; + } + handler = mInternetStatusChangeHandler; + if (handler) { + ++mHandlersInFlight; + } + } + + if (!handler) { + return; + } + + struct HandlerCompletion { + explicit HandlerCompletion(NetworkManagerConnectivityClient& client) + : client(client) {} + ~HandlerCompletion() + { + client.completeInternetStatusChangeHandler(); + } + + NetworkManagerConnectivityClient& client; + } completion(*this); + + handler(mapped, filteredReason); +} + +void NetworkManagerConnectivityClient::completeInternetStatusChangeHandler() +{ + std::lock_guard lock(mLock); + --mHandlersInFlight; + if (mHandlersInFlight == 0) { + mHandlerDrainCv.notify_all(); + } +} + +void NetworkManagerConnectivityClient::Notification::OnInternetStatusChange( + const Exchange::IConnectivityCheck::InternetStatus status, + const string& reason) +{ + mParent.notifyInternetStatusChanged(status, reason); +} + +NetworkManagerConnectivityClient::NmInternetStatus +NetworkManagerConnectivityClient::mapStatus(Exchange::IConnectivityCheck::InternetStatus status) +{ + switch (status) { + case Exchange::IConnectivityCheck::NO_INTERNET: return Exchange::INetworkManager::INTERNET_NOT_AVAILABLE; + case Exchange::IConnectivityCheck::LIMITED_INTERNET: return Exchange::INetworkManager::INTERNET_LIMITED; + case Exchange::IConnectivityCheck::CAPTIVE_PORTAL: return Exchange::INetworkManager::INTERNET_CAPTIVE_PORTAL; + case Exchange::IConnectivityCheck::FULLY_CONNECTED: return Exchange::INetworkManager::INTERNET_FULLY_CONNECTED; + case Exchange::IConnectivityCheck::UNKNOWN: + default: return Exchange::INetworkManager::INTERNET_UNKNOWN; + } +} + +NetworkManagerConnectivityClient::NmInternetStatus +NetworkManagerConnectivityClient::getInternetState() +{ + std::string reason; + return getInternetState(reason); +} + +NetworkManagerConnectivityClient::NmInternetStatus +NetworkManagerConnectivityClient::getInternetState(std::string& reason) +{ + LOG_ENTRY_FUNCTION(); + reason.clear(); + + { + std::lock_guard lock(mLock); + if (mHasCachedStatus) { + reason = mCachedReason; + return mCachedStatus; + } + } + + // Cold path only: no notification received yet, so seed the cache once. + Exchange::IConnectivityCheck* connectivity = acquireInterface(); + if (connectivity == nullptr) { + NMLOG_WARNING("ConnectivityCheckMgr not available; returning INTERNET_UNKNOWN"); + return Exchange::INetworkManager::INTERNET_UNKNOWN; + } + + Exchange::IConnectivityCheck::StatusInfo info{}; + const uint32_t r = connectivity->GetInternetStatus(info); + connectivity->Release(); + + if (r != Core::ERROR_NONE) { + NMLOG_ERROR("ConnectivityCheckMgr GetInternetStatus failed (%u)", r); + return Exchange::INetworkManager::INTERNET_UNKNOWN; + } + + const NmInternetStatus mapped = mapStatus(info.status); + if (info.status == Exchange::IConnectivityCheck::NO_INTERNET) { + reason = info.reason; + } + + { + std::lock_guard lock(mLock); + // A notification may have landed while the RPC was in flight; it is newer. + if (!mHasCachedStatus) { + mCachedStatus = mapped; + mCachedReason = reason; + mHasCachedStatus = true; + } + } + return mapped; +} + +std::string NetworkManagerConnectivityClient::getCaptivePortalURI() +{ + LOG_ENTRY_FUNCTION(); + std::string uri; + + Exchange::IConnectivityCheck* connectivity = acquireInterface(); + if (connectivity == nullptr) { + NMLOG_WARNING("ConnectivityCheckMgr not available; returning empty captive-portal URI"); + return uri; + } + + const uint32_t r = connectivity->GetCaptivePortalURI(uri); + connectivity->Release(); + + if (r != Core::ERROR_NONE) { + NMLOG_ERROR("ConnectivityCheckMgr GetCaptivePortalURI failed (%u)", r); + uri.clear(); + } + return uri; +} diff --git a/plugin/NetworkManagerConnectivityClient.h b/plugin/NetworkManagerConnectivityClient.h new file mode 100644 index 000000000..09b9c5d59 --- /dev/null +++ b/plugin/NetworkManagerConnectivityClient.h @@ -0,0 +1,145 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2026 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +#include "Module.h" +#include "INetworkManager.h" +// IConnectivityCheck is generated/installed by entservices-cpc-apis under interfaces_cpc, +// not the standard Thunder interfaces/ path. +#include +#include +#include +#include +#include +#include +#include + +namespace WPEFramework { +namespace Plugin { + +/** + * COM-RPC client that delegates internet-connectivity queries to the + * ConnectivityCheckMgr plugin (org.rdk.ConnectivityCheckMgr). + * + * Because the delegation lives in the out-of-process implementation, both the + * JSON-RPC surface (shell -> implementation) and direct COM-RPC callers of + * INetworkManager::IsConnectedToInternet / GetCaptivePortalURI are served + * consistently. + * + * Mirrors NetworkManagerPowerClient: + * - Inherits SmartInterfaceType for automatic + * connect / reconnect and Operational() lifecycle callbacks. + * + * Lifecycle: + * Construction -> Open() connects to ConnectivityCheckMgr (async). + * Operational(true) -> acquires the proxy; IsValid() returns true. + * Operational(false) -> releases the proxy. + * Destruction -> Close(). + * + * All queries fall back to INTERNET_UNKNOWN / empty when the plugin is not + * available, so callers never crash on a boot-order race or NM/CCM restart. + */ +class NetworkManagerConnectivityClient : protected RPC::SmartInterfaceType { +public: + using NmInternetStatus = Exchange::INetworkManager::InternetStatus; + using InternetStatusChangeHandler = std::function; + + NetworkManagerConnectivityClient(); + ~NetworkManagerConnectivityClient() override; + + NetworkManagerConnectivityClient(const NetworkManagerConnectivityClient&) = delete; + NetworkManagerConnectivityClient& operator=(const NetworkManagerConnectivityClient&) = delete; + + /** Returns true when the ConnectivityCheckMgr COMRPC proxy is available. */ + bool IsValid() const; + + /** Delegated internet status, mapped to NetworkManager's InternetStatus. */ + NmInternetStatus getInternetState(); + + /** Delegated internet status and its current NO_INTERNET reason. */ + NmInternetStatus getInternetState(std::string& reason); + + /** Delegated captive-portal URI (empty when unavailable / not captive). */ + std::string getCaptivePortalURI(); + + /** Sets/clears callback invoked when ConnectivityCheckMgr publishes internet-status changes. */ + void SetInternetStatusChangeHandler(InternetStatusChangeHandler handler); + +private: + class Notification : public Exchange::IConnectivityCheck::INotification { + public: + explicit Notification(NetworkManagerConnectivityClient& parent) + : mParent(parent) {} + + void OnInternetStatusChange(const Exchange::IConnectivityCheck::InternetStatus status, + const string& reason) override; + + BEGIN_INTERFACE_MAP(Notification) + INTERFACE_ENTRY(Exchange::IConnectivityCheck::INotification) + END_INTERFACE_MAP + + private: + NetworkManagerConnectivityClient& mParent; + }; + + // SmartInterfaceType lifecycle callback. + void Operational(bool upAndRunning) override; + + void registerEvents(); + void unregisterEvents(); + void notifyInternetStatusChanged(Exchange::IConnectivityCheck::InternetStatus status, + const std::string& reason); + void completeInternetStatusChangeHandler(); + void openThreadLoop(); + + /* Returns an AddRef'd proxy (nullptr when unavailable) so the caller can invoke + * ConnectivityCheckMgr without holding mLock across the blocking COM-RPC call. */ + Exchange::IConnectivityCheck* acquireInterface() const; + + // 1:1 mapping ConnectivityCheckMgr InternetStatus -> NetworkManager InternetStatus. + static NmInternetStatus mapStatus(Exchange::IConnectivityCheck::InternetStatus status); + + mutable std::mutex mLock; + Exchange::IConnectivityCheck* mConnectivity{nullptr}; + Core::Sink mNotification; + InternetStatusChangeHandler mInternetStatusChangeHandler; + std::condition_variable mHandlerDrainCv; + uint32_t mHandlersInFlight{0}; + bool mHandlerClearInProgress{false}; + bool mNotificationRegistered{false}; // guarded by mLock + + // Status cache kept current by OnInternetStatusChange, so the hot + // isConnectedToInternet path needs no cross-process round trip. + NmInternetStatus mCachedStatus{Exchange::INetworkManager::INTERNET_UNKNOWN}; + std::string mCachedReason; + bool mHasCachedStatus{false}; + + // Open() runs on its own thread so plugin Configure() never blocks on, or + // re-enters, a ConnectivityCheckMgr that is not activated yet. + std::thread mOpenThread; + std::mutex mOpenMutex; + std::condition_variable mOpenCv; + std::atomic mStopOpenThread{false}; + + friend class NetworkManagerConnectivityClientTestAccess; +}; + +} // namespace Plugin +} // namespace WPEFramework diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 8d90d17ee..ac828bdad 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -24,6 +24,11 @@ #include #include "NetworkManagerImplementation.h" +#ifdef USE_CONNECTIVITYCHECKMGR +#include +#include "rfcapi.h" +#endif + #if USE_TELEMETRY #include "NetworkManagerJsonEnum.h" #include @@ -83,7 +88,18 @@ namespace WPEFramework { NMLOG_INFO("NetworkManager Out-Of-Process Shutdown/Cleanup"); m_powerClient.reset(); - connectivityMonitor.stopConnectivityMonitor(); +#ifdef USE_CONNECTIVITYCHECKMGR + if (connectivityClient) { + // Clear the handler first so no in-flight callback can reach this + // (partially-destroyed) object, then tear down the COM-RPC client. + connectivityClient->SetInternetStatusChangeHandler(nullptr); + connectivityClient.reset(); + } +#endif + if(!m_useConnectivityCheckMgr) + { + connectivityMonitor.stopConnectivityMonitor(); + } _instance = nullptr; platform_deinit(); if(m_registrationThread.joinable()) @@ -171,6 +187,30 @@ namespace WPEFramework NetworkManagerLogger::SetLevel(static_cast (config.loglevel.Value())); NMLOG_DEBUG("loglevel %d", config.loglevel.Value()); + /* Resolve the connectivity backend at runtime (replaces the old + * USE_CONNECTIVITY_CHECK_MGR compile-time macro). */ + m_useConnectivityCheckMgr = resolveConnectivityCheckMgrEnabled(config); +#ifdef USE_CONNECTIVITYCHECKMGR + if(m_useConnectivityCheckMgr) + { + /* Stop the built-in monitor (started by its constructor) so it does + * not run alongside the delegation client. */ + connectivityMonitor.stopConnectivityMonitor(); + if(!connectivityClient) + connectivityClient.reset(new NetworkManagerConnectivityClient()); + connectivityClient->SetInternetStatusChangeHandler( + [this](const Exchange::INetworkManager::InternetStatus status, const std::string& reason) { + OnDelegatedInternetStatusChange(status, reason); + }); + { + std::lock_guard lock(m_bridgedStatusMutex); + m_hasBridgedInternetStatus = false; + m_lastBridgedInternetStatus = Exchange::INetworkManager::INTERNET_UNKNOWN; + } + NMLOG_INFO("Connectivity delegated to ConnectivityCheckMgr (runtime selection)"); + } +#endif + /* STUN configuration copy */ m_stunEndpoint = config.stun.stunEndpoint.Value(); m_stunPort = config.stun.port.Value(); @@ -204,18 +244,22 @@ namespace WPEFramework connectEndpts.push_back(config.connectivityConf.endpoint_5.Value().c_str()); } - /* check whether the endpoint is already loaded from Cache; if Yes, do not use the one from configuration */ - if (connectivityMonitor.getConnectivityMonitorEndpoints().size() < 1) + /* Only seed endpoints when none are active; endpoints restored from the + * EndpointManager cache on restart must not be overwritten. */ + if (!m_useConnectivityCheckMgr && connectivityMonitor.getConnectivityMonitorEndpoints().size() < 1) { - NMLOG_INFO("Use the connectivity endpoint from config"); - connectivityMonitor.setConnectivityMonitorEndpoints(connectEndpts); - } - else if (connectEndpts.size() < 1) - { - std::vector backup; - NMLOG_INFO("Connectivity endpoints are empty in config; use the default"); - backup.push_back("http://clients3.google.com/generate_204"); - connectivityMonitor.setConnectivityMonitorEndpoints(backup); + if (connectEndpts.size() < 1) + { + std::vector backup; + NMLOG_INFO("Connectivity endpoints are empty in config; use the default"); + backup.push_back("http://clients3.google.com/generate_204"); + connectivityMonitor.setConnectivityMonitorEndpoints(backup); + } + else + { + NMLOG_INFO("Use the connectivity endpoint from config"); + connectivityMonitor.setConnectivityMonitorEndpoints(connectEndpts); + } } /* As all the configuration is set, lets instantiate platform */ @@ -226,6 +270,31 @@ namespace WPEFramework return(Core::ERROR_NONE); } + /* @brief Resolve whether internet-connectivity queries are delegated to the + * ConnectivityCheckMgr plugin. Precedence: RFC feature flag (when the + * RFC API is compiled in) -> config-line fallback -> default false. */ + bool NetworkManagerImplementation::resolveConnectivityCheckMgrEnabled(const Configuration& config) const + { + LOG_ENTRY_FUNCTION(); +#ifdef USE_CONNECTIVITYCHECKMGR + RFC_ParamData_t rfcParam = {0}; + WDMP_STATUS wdmpStatus = getRFCParameter(const_cast("NetworkManager"), + "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.ConnectivityCheckMgr.Enable", + &rfcParam); + if (wdmpStatus == WDMP_SUCCESS || wdmpStatus == WDMP_ERR_DEFAULT_VALUE) + { + bool enabled = (0 == strcasecmp(rfcParam.value, "true")); + NMLOG_INFO("RFC ConnectivityCheckMgr.Enable = '%s' -> %s", rfcParam.value, + enabled ? "delegate" : "internal monitor"); + return enabled; + } +#else + (void)config; + NMLOG_INFO("ConnectivityCheckMgr delegation not compiled in; using built-in monitor"); +#endif + return false; + } + /* @brief Get STUN Endpoint to be used for identifying Public IP */ uint32_t NetworkManagerImplementation::GetStunEndpoint (string &endpoint /* @out */, uint32_t& port /* @out */, uint32_t& bindTimeout /* @out */, uint32_t& cacheTimeout /* @out */) const { @@ -273,7 +342,15 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::GetConnectivityTestEndpoints(IStringIterator*& endpoints/* @out */) const { LOG_ENTRY_FUNCTION(); - std::vector tmpEndpoints = connectivityMonitor.getConnectivityMonitorEndpoints(); + /* Endpoints are owned by ConnectivityCheckMgr when delegation is active. */ + if(m_useConnectivityCheckMgr) + { + NMLOG_WARNING("GetConnectivityTestEndpoints is not supported while connectivity is delegated to ConnectivityCheckMgr"); + return Core::ERROR_NOT_SUPPORTED; + } + + std::vector tmpEndpoints; + tmpEndpoints = connectivityMonitor.getConnectivityMonitorEndpoints(); endpoints = (Core::Service::Create(tmpEndpoints)); if(endpoints == nullptr) { return Core::ERROR_GENERAL; @@ -286,6 +363,13 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::SetConnectivityTestEndpoints(IStringIterator* const endpoints /* @in */) { LOG_ENTRY_FUNCTION(); + /* Endpoints are owned by ConnectivityCheckMgr when delegation is active. */ + if(m_useConnectivityCheckMgr) + { + NMLOG_WARNING("SetConnectivityTestEndpoints is not supported while connectivity is delegated to ConnectivityCheckMgr"); + return Core::ERROR_NOT_SUPPORTED; + } + std::vector tmpEndpoints; if(endpoints && (endpoints->Count() >= 1)) @@ -305,9 +389,10 @@ namespace WPEFramework } /* @brief Get Internet Connectivty Status */ - uint32_t NetworkManagerImplementation::IsConnectedToInternet(string &ipversion /* @inout */, string &interface /* @inout */, InternetStatus &result /* @out */) + uint32_t NetworkManagerImplementation::IsConnectedToInternet(string &ipversion /* @inout */, string &interface /* @inout */, InternetStatus &result /* @out */, string& reason /* @out */) { LOG_ENTRY_FUNCTION(); + reason.clear(); Exchange::INetworkManager::IPVersion curlIPversion = Exchange::INetworkManager::IP_ADDRESS_V4; bool ipVersionNotSpecified = false; @@ -332,7 +417,18 @@ namespace WPEFramework return Core::ERROR_BAD_REQUEST; } - result = connectivityMonitor.getInternetState(interface, curlIPversion, ipVersionNotSpecified); +#ifdef USE_CONNECTIVITYCHECKMGR + if(m_useConnectivityCheckMgr) + { + (void)ipVersionNotSpecified; + result = connectivityClient ? connectivityClient->getInternetState(reason) + : Exchange::INetworkManager::INTERNET_UNKNOWN; + } + else +#endif + { + result = connectivityMonitor.getInternetState(interface, curlIPversion, ipVersionNotSpecified); + } if (Exchange::INetworkManager::IP_ADDRESS_V6 == curlIPversion) ipversion = "IPv6"; else @@ -348,7 +444,12 @@ namespace WPEFramework uint32_t NetworkManagerImplementation::GetCaptivePortalURI(string &uri /* @out */) const { LOG_ENTRY_FUNCTION(); - uri = connectivityMonitor.getCaptivePortalURI(); +#ifdef USE_CONNECTIVITYCHECKMGR + if(m_useConnectivityCheckMgr) + uri = connectivityClient ? connectivityClient->getCaptivePortalURI() : std::string(); + else +#endif + uri = connectivityMonitor.getCaptivePortalURI(); return Core::ERROR_NONE; } @@ -798,7 +899,7 @@ namespace WPEFramework NMLOG_INFO("Publishing onInternetStatusChange Event"); const auto& eventData = std::get(data); for (const auto callback : callbacks) { - callback->onInternetStatusChange(eventData.prevState, eventData.currState, eventData.interface); + callback->onInternetStatusChange(eventData.prevState, eventData.currState, eventData.interface, eventData.reason); callback->Release(); } } @@ -857,7 +958,8 @@ namespace WPEFramework m_ethConnected.store(false); setDefaultInterface("wlan0"); // If WiFi is connected, make it the default interface // As default interface is changed to wlan0, switch connectivity monitor to initial check - connectivityMonitor.switchToInitialCheck(); + if(!m_useConnectivityCheckMgr) + connectivityMonitor.switchToInitialCheck(); } else if(interface == "wlan0") { @@ -874,7 +976,8 @@ namespace WPEFramework { // When WiFi is disconnected while Ethernet is connected, we don't need to trigger connectivity monitor. // For WiFi-only state and WiFi disconnected, we should trigger connectivity monitor. - connectivityMonitor.switchToInitialCheck(); + if(!m_useConnectivityCheckMgr) + connectivityMonitor.switchToInitialCheck(); } } } @@ -965,7 +1068,8 @@ namespace WPEFramework if(isDefaultIface) { // As default interface is connected, switch connectivity monitor to initial check any way - connectivityMonitor.switchToInitialCheck(); + if(!m_useConnectivityCheckMgr) + connectivityMonitor.switchToInitialCheck(); } else NMLOG_DEBUG("No need to trigger connectivity monitor interface is %s", interface.c_str()); @@ -979,7 +1083,43 @@ namespace WPEFramework } } - void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface) + void NetworkManagerImplementation::ReportRouteChange(const string& interface, const string& ipversion) + { + string iface = interface; + Exchange::INetworkManager::IPAddress settings{}; + if (GetIPSettings(iface, ipversion, settings) != Core::ERROR_NONE) { + return; + } + ReportRouteChange(interface, ipversion, settings); + } + + void NetworkManagerImplementation::ReportRouteChange(const string& interface, const string& ipversion, const Exchange::INetworkManager::IPAddress& settings) + { + if (settings.ipaddress.empty() || settings.gateway.empty() || settings.primarydns.empty()) { + return; + } + + /* Snapshot the callbacks with an extra reference and invoke them outside + * _notificationLock; see dispatchEvent for the rationale. */ + std::list callbacks; + _notificationLock.Lock(); + for (auto* tmpCB : _notificationCallbacks) { + tmpCB->AddRef(); + callbacks.push_back(tmpCB); + } + _notificationLock.Unlock(); + + NMLOG_INFO("Posting onRouteChange %s %s ip=%s gw=%s dns=%s", + interface.c_str(), ipversion.c_str(), settings.ipaddress.c_str(), + settings.gateway.c_str(), settings.primarydns.c_str()); + for (const auto callback : callbacks) { + callback->onRouteChange(interface, ipversion, settings.ipaddress, + settings.gateway, settings.primarydns); + callback->Release(); + } + } + + void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface, const string& reason) { LOG_ENTRY_FUNCTION(); #if USE_TELEMETRY @@ -994,7 +1134,8 @@ namespace WPEFramework } #endif { - InternetStatusChangeData eventData{prevState, currState, interface}; + const string noInternetReason = (currState == Exchange::INetworkManager::INTERNET_NOT_AVAILABLE) ? reason : string(); + InternetStatusChangeData eventData{prevState, currState, interface, noInternetReason}; NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); enqueueEvent(NM_ON_INTERNETSTATUS_CHANGE, std::move(eventData)); } @@ -1006,6 +1147,40 @@ namespace WPEFramework #endif } + void NetworkManagerImplementation::OnDelegatedInternetStatusChange(const Exchange::INetworkManager::InternetStatus currState, const string& reason) + { + LOG_ENTRY_FUNCTION(); + +#ifdef USE_CONNECTIVITYCHECKMGR + if (!m_useConnectivityCheckMgr) { + NMLOG_DEBUG("Ignoring delegated internet-status event because delegation is disabled"); + return; + } + + Exchange::INetworkManager::InternetStatus prevState = Exchange::INetworkManager::INTERNET_UNKNOWN; + { + std::lock_guard lock(m_bridgedStatusMutex); + if (m_hasBridgedInternetStatus && m_lastBridgedInternetStatus == currState) { + NMLOG_DEBUG("Skipping duplicate delegated internet-status event state=%u", static_cast(currState)); + return; + } + if (m_hasBridgedInternetStatus) { + prevState = m_lastBridgedInternetStatus; + } + m_lastBridgedInternetStatus = currState; + m_hasBridgedInternetStatus = true; + } + + const string activeInterface = getDefaultInterface(); + NMLOG_INFO("Bridging ConnectivityCheckMgr internet-status event prev=%u curr=%u iface=%s", + static_cast(prevState), static_cast(currState), activeInterface.c_str()); + ReportInternetStatusChange(prevState, currState, activeInterface, reason); +#else + (void)currState; + (void)reason; +#endif + } + int32_t NetworkManagerImplementation::logSSIDs(Logging level, const JsonArray &ssids) { LOG_ENTRY_FUNCTION(); @@ -1495,7 +1670,10 @@ namespace WPEFramework NMLOG_INFO("OnPowerModePreChange: waking from DeepSleep — WiFi was not connected or was already down before sleep, skipping reconnect"); } // DeepSleep wake (Network Standby OFF): re-verify connectivity so internet status is re-published. - connectivityMonitor.switchToInitialCheck(); + if(!m_useConnectivityCheckMgr) + { + connectivityMonitor.switchToInitialCheck(); + } } sendAck(); } @@ -1535,7 +1713,10 @@ namespace WPEFramework } } // DeepSleep → Standby wake (Network Standby ON): re-verify connectivity so internet status is re-published. - connectivityMonitor.switchToInitialCheck(); + if(!m_useConnectivityCheckMgr) + { + connectivityMonitor.switchToInitialCheck(); + } } } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 81f148cf8..e22923aa8 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -38,6 +38,9 @@ using namespace std; #include "INetworkManager.h" #include "NetworkManagerLogger.h" #include "NetworkManagerConnectivity.h" +#ifdef USE_CONNECTIVITYCHECKMGR +#include "NetworkManagerConnectivityClient.h" +#endif #include "NetworkManagerStunClient.h" #include "NetworkManagerPowerClient.h" @@ -243,6 +246,7 @@ namespace WPEFramework Exchange::INetworkManager::InternetStatus prevState; Exchange::INetworkManager::InternetStatus currState; string interface; + string reason; }; struct AvailableSSIDsData { @@ -342,7 +346,7 @@ namespace WPEFramework uint32_t SetConnectivityTestEndpoints(IStringIterator* const endpoints /* @in */) override; /* @brief Get Internet Connectivty Status */ - uint32_t IsConnectedToInternet(string &ipversion /* @inout */, string &interface /* @inout */, InternetStatus &result /* @out */) override; + uint32_t IsConnectedToInternet(string &ipversion /* @inout */, string &interface /* @inout */, InternetStatus &result /* @out */, string& reason /* @out */) override; /* @brief Get Authentication URL if the device is behind Captive Portal */ uint32_t GetCaptivePortalURI(string &endpoints/* @out */) const override; @@ -371,7 +375,10 @@ namespace WPEFramework void ReportInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state, const string interface); void ReportActiveInterfaceChange(const string prevActiveInterface, const string currentActiveinterface); void ReportIPAddressChange(const string interface, const string ipversion, const string ipaddress, const Exchange::INetworkManager::IPStatus status); - void ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface); + void ReportRouteChange(const string& interface, const string& ipversion); + void ReportRouteChange(const string& interface, const string& ipversion, const Exchange::INetworkManager::IPAddress& settings); + void ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface, const string& reason = string()); + void OnDelegatedInternetStatusChange(const Exchange::INetworkManager::InternetStatus currState, const string& reason = string()); void ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults); void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state, const string ssid); void ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality); @@ -388,6 +395,11 @@ namespace WPEFramework void platform_init(void); void platform_deinit(void); void platform_logging(const NetworkManagerLogger::LogLevel& level); + /* Resolve whether connectivity is delegated to ConnectivityCheckMgr: + * RFC flag Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.ConnectivityCheckMgr.Enable + * (when USE_CONNECTIVITYCHECKMGR is built in) takes precedence, then the config-line + * fallback key, then default false (built-in monitor). */ + bool resolveConnectivityCheckMgrEnabled(const Configuration& config) const; void getInitialConnectionState(void); void executeExternally(NetworkEvents event, const string commandToExecute, string& response); void threadEventRegistration(bool iarmInit, bool iarmConnect); @@ -452,7 +464,19 @@ namespace WPEFramework std::atomic m_ethDisconnectedForSleep; std::atomic m_wlanDisconnectedForSleep; GMainContext *m_nmContext{nullptr}; /* isolated context for per-call NMClient creation */ + /* Runtime connectivity backend selection (replaces the old + * USE_CONNECTIVITY_CHECK_MGR compile-time macro). When + * m_useConnectivityCheckMgr is true, connectivity queries are + * delegated to ConnectivityCheckMgr via connectivityClient; + * otherwise the built-in connectivityMonitor is used. */ + bool m_useConnectivityCheckMgr {false}; mutable ConnectivityMonitor connectivityMonitor; +#ifdef USE_CONNECTIVITYCHECKMGR + mutable std::unique_ptr connectivityClient; +#endif + std::mutex m_bridgedStatusMutex; + Exchange::INetworkManager::InternetStatus m_lastBridgedInternetStatus {Exchange::INetworkManager::INTERNET_UNKNOWN}; + bool m_hasBridgedInternetStatus {false}; string getDefaultInterface() const { diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index d16f5f0d0..7429cba43 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -473,6 +473,7 @@ namespace WPEFramework Exchange::INetworkManager::InternetStatus result; string ipversion{}; string interface{}; + string reason{}; if (parameters.HasLabel("ipversion")) ipversion = parameters["ipversion"].String(); @@ -480,7 +481,7 @@ namespace WPEFramework interface = parameters["interface"].String(); if (_networkManager) - rc = _networkManager->IsConnectedToInternet(ipversion, interface, result); + rc = _networkManager->IsConnectedToInternet(ipversion, interface, result, reason); else rc = Core::ERROR_UNAVAILABLE; @@ -489,9 +490,13 @@ namespace WPEFramework Core::JSON::EnumType status(result); response["ipversion"] = ipversion; response["interface"] = interface; - response["connected"] = (Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED == result); + response["connected"] = (Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED == result + || (m_useConnectivityCheckMgr && + Exchange::INetworkManager::InternetStatus::INTERNET_LIMITED == result)); response["state"] = JsonValue(status); response["status"] = status.Data(); + if (result == Exchange::INetworkManager::InternetStatus::INTERNET_NOT_AVAILABLE && !reason.empty()) + response["reason"] = reason; } returnJson(rc); } @@ -1094,7 +1099,20 @@ namespace WPEFramework Notify(_T("onIPAddressChange"), parameters); } - void NetworkManager::onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface) + void NetworkManager::onRouteChange(const string interface, const string ipversion, const string ipaddress, const string gateway, const string primarydns) + { + JsonObject parameters; + parameters["interface"] = interface; + parameters["ipversion"] = ipversion; + parameters["ipaddress"] = ipaddress; + parameters["gateway"] = gateway; + parameters["primarydns"] = primarydns; + + LOG_INPARAM(); + Notify(_T("onRouteChange"), parameters); + } + + void NetworkManager::onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface, const string reason) { JsonObject parameters; Core::JSON::EnumType prevStatus(prevState); @@ -1104,6 +1122,9 @@ namespace WPEFramework parameters["state"] = JsonValue(currState); parameters["status"] = currStatus.Data(); parameters["interface"] = interface; + if (currState == Exchange::INetworkManager::INTERNET_NOT_AVAILABLE && !reason.empty()) { + parameters["reason"] = reason; + } LOG_INPARAM(); Notify(_T("onInternetStatusChange"), parameters); diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 739c00763..e2918b9c9 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -241,6 +241,23 @@ namespace WPEFramework _instance->ReportIPAddressChange(ifname, family, key, Exchange::INetworkManager::IP_LOST); } } + + /* Coalesced "route ready" event: emit once address + gateway + primary DNS + are all populated for this family. The notify::addresses / + notify::gateway / notify::nameservers subscriptions on NMIPConfig all + funnel here, so a single emission per snapshot covers all three. + Each family emits independently — dual-stack consumers will see one + event per family. */ + if (newCache.valid + && !newCache.globalAddresses.empty() + && !newCache.gateway.empty() + && !newCache.primarydns.empty()) { + /* Values are already in hand from the snapshot we just built, so emit + them directly instead of having ReportRouteChange re-query the cache. */ + Exchange::INetworkManager::IPAddress ipAddress = newCache.toIPAddress(); + ipAddress.ipversion = family; + _instance->ReportRouteChange(ifname, family, ipAddress); + } } static void ip4ChangedCb(NMIPConfig *ipConfig, GParamSpec *pspec, gpointer userData) @@ -909,6 +926,15 @@ namespace WPEFramework _instance->ReportActiveInterfaceChange(oldIface, newIface); NMLOG_INFO("old interface - %s new interface - %s", oldIface.c_str(), newIface.c_str()); oldIface = newIface; + + /* Default-route owner changed (e.g. eth0↔wlan0 failover). The new primary + already has its IP/gateway/DNS in the cache from prior refreshIpFamilyCache, + so emit a coalesced route-ready event for both families — ReportRouteChange + is a no-op for whichever family isn't fully populated. */ + if (_instance != nullptr && !newIface.empty() && newIface != "Unknown") { + _instance->ReportRouteChange(newIface, "IPv4"); + _instance->ReportRouteChange(newIface, "IPv6"); + } } } diff --git a/tests/l1Test/l1_test_connectivity.cpp b/tests/l1Test/l1_test_connectivity.cpp index f68a40c8f..5ce589559 100644 --- a/tests/l1Test/l1_test_connectivity.cpp +++ b/tests/l1Test/l1_test_connectivity.cpp @@ -29,7 +29,7 @@ namespace WPEFramework namespace Plugin { NetworkManagerImplementation* _instance = nullptr; - void NetworkManagerImplementation::ReportInternetStatusChange(const InternetStatus prevState, const InternetStatus currState, const string interface) + void NetworkManagerImplementation::ReportInternetStatusChange(const InternetStatus prevState, const InternetStatus currState, const string interface, const string& reason) { return; } diff --git a/tests/l2Test/legacy/l2_test_LegacyPlugin_NetworkAPIs.cpp b/tests/l2Test/legacy/l2_test_LegacyPlugin_NetworkAPIs.cpp index d55de3924..1eee1dcdc 100644 --- a/tests/l2Test/legacy/l2_test_LegacyPlugin_NetworkAPIs.cpp +++ b/tests/l2Test/legacy/l2_test_LegacyPlugin_NetworkAPIs.cpp @@ -472,10 +472,10 @@ TEST_F(NetworkTest, isConnectedToInternet) { return static_cast(mockNetworkManager); })); - EXPECT_CALL(*mockNetworkManager, IsConnectedToInternet(::testing::_, ::testing::_, ::testing::_)) + EXPECT_CALL(*mockNetworkManager, IsConnectedToInternet(::testing::_, ::testing::_, ::testing::_, ::testing::_)) .Times(1) .WillOnce(::testing::Invoke( - [&](string& , string&, WPEFramework::Exchange::INetworkManager::InternetStatus& result) -> uint32_t + [&](string& , string&, WPEFramework::Exchange::INetworkManager::InternetStatus& result, string&) -> uint32_t { result = WPEFramework::Exchange::INetworkManager::InternetStatus::INTERNET_FULLY_CONNECTED; return Core::ERROR_NONE; @@ -505,10 +505,10 @@ TEST_F(NetworkTest, getInternetConnectionState) { return static_cast(mockNetworkManager); })); - EXPECT_CALL(*mockNetworkManager, IsConnectedToInternet(::testing::_, ::testing::_, ::testing::_)) + EXPECT_CALL(*mockNetworkManager, IsConnectedToInternet(::testing::_, ::testing::_, ::testing::_, ::testing::_)) .Times(1) .WillOnce(::testing::Invoke( - [&](const string&, const string&, Exchange::INetworkManager::InternetStatus& status) { + [&](const string&, const string&, Exchange::INetworkManager::InternetStatus& status, string&) { status = Exchange::INetworkManager::InternetStatus::INTERNET_CAPTIVE_PORTAL; return Core::ERROR_NONE; })); diff --git a/tests/l2Test/libnm/CMakeLists.txt b/tests/l2Test/libnm/CMakeLists.txt index 17be8eea4..d05bf0a2f 100644 --- a/tests/l2Test/libnm/CMakeLists.txt +++ b/tests/l2Test/libnm/CMakeLists.txt @@ -48,6 +48,12 @@ add_executable(${NM_LIBNM_PROXY_L2_TEST} ${PROXY_STUB_SOURCES} ) +if(USE_CONNECTIVITYCHECKMGR) + target_sources(${NM_LIBNM_PROXY_L2_TEST} PRIVATE + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivityClient.cpp + ) +endif() + set_target_properties(${NM_LIBNM_PROXY_L2_TEST} PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES @@ -183,4 +189,11 @@ target_link_libraries(${NM_LIBNM_PROXY_L2_TEST} PRIVATE ${GIO_LIBRARIES} ) +if(USE_CONNECTIVITYCHECKMGR) + target_link_libraries(${NM_LIBNM_PROXY_L2_TEST} PRIVATE ${RFCAPI_LIBRARY}) + if(RFCAPI_INCLUDE_DIR) + target_include_directories(${NM_LIBNM_PROXY_L2_TEST} PRIVATE ${RFCAPI_INCLUDE_DIR}) + endif() +endif() + install(TARGETS ${NM_LIBNM_PROXY_L2_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/l2Test/rdk/CMakeLists.txt b/tests/l2Test/rdk/CMakeLists.txt index cc5ecc594..8e8939608 100644 --- a/tests/l2Test/rdk/CMakeLists.txt +++ b/tests/l2Test/rdk/CMakeLists.txt @@ -43,6 +43,12 @@ add_executable(${NM_RDK_PROXY_L2_TEST} ${PROXY_STUB_SOURCES} ) +if(USE_CONNECTIVITYCHECKMGR) + target_sources(${NM_RDK_PROXY_L2_TEST} PRIVATE + ${CMAKE_SOURCE_DIR}/plugin/NetworkManagerConnectivityClient.cpp + ) +endif() + set_target_properties(${NM_RDK_PROXY_L2_TEST} PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES @@ -92,4 +98,11 @@ target_link_libraries(${NM_RDK_PROXY_L2_TEST} PRIVATE ${CURL_LIBRARIES} ) +if(USE_CONNECTIVITYCHECKMGR) + target_link_libraries(${NM_RDK_PROXY_L2_TEST} PRIVATE ${RFCAPI_LIBRARY}) + if(RFCAPI_INCLUDE_DIR) + target_include_directories(${NM_RDK_PROXY_L2_TEST} PRIVATE ${RFCAPI_INCLUDE_DIR}) + endif() +endif() + install(TARGETS ${NM_RDK_PROXY_L2_TEST} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp index 1fb8a27c7..7c27e2b24 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxyEvent.cpp @@ -17,8 +17,12 @@ * limitations under the License. **/ #include +#include +#include +#include #include #include +#include #include #include @@ -40,6 +44,22 @@ using namespace WPEFramework; using ::testing::NiceMock; +#ifdef USE_CONNECTIVITYCHECKMGR +namespace WPEFramework { +namespace Plugin { +class NetworkManagerConnectivityClientTestAccess { +public: + static void Notify(NetworkManagerConnectivityClient& client, + const Exchange::IConnectivityCheck::InternetStatus status, + const std::string& reason) + { + client.notifyInternetStatusChanged(status, reason); + } +}; +} // namespace Plugin +} // namespace WPEFramework +#endif + class NetworkManagerEventTest : public ::testing::Test { protected: Core::ProxyType plugin; @@ -560,6 +580,60 @@ TEST_F(NetworkManagerEventTest, onInternetStatusChange_LimitedInternet) server.stop(); } */ + +#ifdef USE_CONNECTIVITYCHECKMGR +TEST(NetworkManagerConnectivityClientTest, ClearsHandlerAfterAdmittedCallbackCompletes) +{ + NetworkManagerConnectivityClient client; + std::promise callbackEntered; + std::future callbackEnteredFuture = callbackEntered.get_future(); + std::promise allowCallbackCompletion; + std::shared_future allowCallbackCompletionFuture = allowCallbackCompletion.get_future().share(); + std::promise handlerCleared; + std::future handlerClearedFuture = handlerCleared.get_future(); + + client.SetInternetStatusChangeHandler( + [&callbackEntered, allowCallbackCompletionFuture](const Exchange::INetworkManager::InternetStatus, + const std::string&) { + callbackEntered.set_value(); + allowCallbackCompletionFuture.wait(); + }); + + std::thread notificationThread([&client] { + NetworkManagerConnectivityClientTestAccess::Notify( + client, Exchange::IConnectivityCheck::FULLY_CONNECTED, std::string()); + }); + EXPECT_EQ(std::future_status::ready, callbackEnteredFuture.wait_for(std::chrono::seconds(1))); + + std::thread clearThread([&client, &handlerCleared] { + client.SetInternetStatusChangeHandler(nullptr); + handlerCleared.set_value(); + }); + EXPECT_EQ(std::future_status::timeout, handlerClearedFuture.wait_for(std::chrono::milliseconds(0))); + + allowCallbackCompletion.set_value(); + notificationThread.join(); + clearThread.join(); + EXPECT_EQ(std::future_status::ready, handlerClearedFuture.wait_for(std::chrono::milliseconds(0))); +} + +TEST(NetworkManagerConnectivityClientTest, DoesNotInvokeHandlerAfterClear) +{ + NetworkManagerConnectivityClient client; + std::atomic callbackCount{0}; + + client.SetInternetStatusChangeHandler( + [&callbackCount](const Exchange::INetworkManager::InternetStatus, const std::string&) { + ++callbackCount; + }); + client.SetInternetStatusChangeHandler(nullptr); + + NetworkManagerConnectivityClientTestAccess::Notify( + client, Exchange::IConnectivityCheck::FULLY_CONNECTED, std::string()); + + EXPECT_EQ(0u, callbackCount.load()); +} +#endif TEST_F(NetworkManagerEventTest, onInternetStatusChange_FULLY_CONNECTED) { EXPECT_CALL(*p_curlWrapsImplMock, curl_multi_perform(::testing::_, ::testing::_)) diff --git a/tests/l2Test/rdk/l2_test_rdkproxyImpl.cpp b/tests/l2Test/rdk/l2_test_rdkproxyImpl.cpp index ebae2073f..7158090d5 100644 --- a/tests/l2Test/rdk/l2_test_rdkproxyImpl.cpp +++ b/tests/l2Test/rdk/l2_test_rdkproxyImpl.cpp @@ -22,6 +22,8 @@ #include #include +#include +#include #include "NetworkManagerImplementation.h" #include "NetworkManager.h" #include "IarmBusMock.h" @@ -38,6 +40,88 @@ using namespace WPEFramework::Plugin; using IStringIterator = RPC::IIteratorType; using ::testing::NiceMock; +namespace { +class InternetStatusNotificationProbe : public Exchange::INetworkManager::INotification { +public: + void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, + const Exchange::INetworkManager::InternetStatus currState, + const string interface, + const string reason) override + { + std::lock_guard lock(mutex); + ++count; + lastPrev = prevState; + lastCurr = currState; + lastInterface = interface; + lastReason = reason; + cv.notify_all(); + } + + bool WaitForCount(const size_t expected, const std::chrono::milliseconds timeout) + { + std::unique_lock lock(mutex); + return cv.wait_for(lock, timeout, [&]() { return count >= expected; }); + } + + size_t Count() const + { + std::lock_guard lock(mutex); + return count; + } + + Exchange::INetworkManager::InternetStatus LastPrev() const + { + std::lock_guard lock(mutex); + return lastPrev; + } + + Exchange::INetworkManager::InternetStatus LastCurr() const + { + std::lock_guard lock(mutex); + return lastCurr; + } + + string LastInterface() const + { + std::lock_guard lock(mutex); + return lastInterface; + } + + string LastReason() const + { + std::lock_guard lock(mutex); + return lastReason; + } + + uint32_t AddRef() const override + { + return Core::ERROR_NONE; + } + + uint32_t Release() const override + { + return Core::ERROR_NONE; + } + + void* QueryInterface(const uint32_t id) override + { + if ((id == Exchange::INetworkManager::INotification::ID) || (id == Core::IUnknown::ID)) { + return static_cast(this); + } + return nullptr; + } + +private: + mutable std::mutex mutex; + std::condition_variable cv; + size_t count {0}; + Exchange::INetworkManager::InternetStatus lastPrev {Exchange::INetworkManager::INTERNET_UNKNOWN}; + Exchange::INetworkManager::InternetStatus lastCurr {Exchange::INetworkManager::INTERNET_UNKNOWN}; + string lastInterface; + string lastReason; +}; +} // namespace + class NetworkManagerImplTest : public ::testing::Test { protected: static Core::ProxyType NetworkManagerImplementation; @@ -261,3 +345,79 @@ TEST_F(NetworkManagerImplTest, SetConnectivityTestEndpoints_TooManyEndpoints) { endpoints->Release(); } +#ifdef USE_CONNECTIVITYCHECKMGR +TEST_F(NetworkManagerImplTest, DelegatedInternetStatusBridgePublishesAndDeduplicates) +{ + InternetStatusNotificationProbe notification; + ASSERT_EQ(interface->Register(¬ification), Core::ERROR_NONE); + + NetworkManagerImplementation->setDefaultInterface("eth0"); + NetworkManagerImplementation->OnDelegatedInternetStatusChange(Exchange::INetworkManager::INTERNET_LIMITED); + + EXPECT_TRUE(notification.WaitForCount(1, std::chrono::milliseconds(1000))); + EXPECT_EQ(notification.LastCurr(), Exchange::INetworkManager::INTERNET_LIMITED); + EXPECT_EQ(notification.LastInterface(), "eth0"); + + // Same state is deduplicated. + NetworkManagerImplementation->OnDelegatedInternetStatusChange(Exchange::INetworkManager::INTERNET_LIMITED); + EXPECT_EQ(notification.Count(), static_cast(1)); + + // New state transition is published. + NetworkManagerImplementation->OnDelegatedInternetStatusChange(Exchange::INetworkManager::INTERNET_FULLY_CONNECTED); + EXPECT_TRUE(notification.WaitForCount(2, std::chrono::milliseconds(1000))); + EXPECT_EQ(notification.LastPrev(), Exchange::INetworkManager::INTERNET_LIMITED); + EXPECT_EQ(notification.LastCurr(), Exchange::INetworkManager::INTERNET_FULLY_CONNECTED); + + EXPECT_EQ(interface->Unregister(¬ification), Core::ERROR_NONE); +} + +TEST_F(NetworkManagerImplTest, DelegatedNoInternetReasonIsPublishedOnlyForNoInternet) +{ + InternetStatusNotificationProbe notification; + ASSERT_EQ(interface->Register(¬ification), Core::ERROR_NONE); + + NetworkManagerImplementation->setDefaultInterface("eth0"); + NetworkManagerImplementation->OnDelegatedInternetStatusChange( + Exchange::INetworkManager::INTERNET_NOT_AVAILABLE, "PROBE_FAILED"); + + EXPECT_TRUE(notification.WaitForCount(1, std::chrono::milliseconds(1000))); + EXPECT_EQ(notification.LastCurr(), Exchange::INetworkManager::INTERNET_NOT_AVAILABLE); + EXPECT_EQ(notification.LastReason(), "PROBE_FAILED"); + + NetworkManagerImplementation->OnDelegatedInternetStatusChange( + Exchange::INetworkManager::INTERNET_FULLY_CONNECTED, "STALE_REASON"); + + EXPECT_TRUE(notification.WaitForCount(2, std::chrono::milliseconds(1000))); + EXPECT_EQ(notification.LastCurr(), Exchange::INetworkManager::INTERNET_FULLY_CONNECTED); + EXPECT_TRUE(notification.LastReason().empty()); + + EXPECT_EQ(interface->Unregister(¬ification), Core::ERROR_NONE); +} + +TEST_F(NetworkManagerImplTest, BuiltInMonitorInternetStatusEventOmitsReason) +{ + InternetStatusNotificationProbe notification; + ASSERT_EQ(interface->Register(¬ification), Core::ERROR_NONE); + + NetworkManagerImplementation->ReportInternetStatusChange( + Exchange::INetworkManager::INTERNET_UNKNOWN, + Exchange::INetworkManager::INTERNET_NOT_AVAILABLE, "eth0"); + + EXPECT_TRUE(notification.WaitForCount(1, std::chrono::milliseconds(1000))); + EXPECT_TRUE(notification.LastReason().empty()); + + EXPECT_EQ(interface->Unregister(¬ification), Core::ERROR_NONE); +} + +TEST_F(NetworkManagerImplTest, DelegatedInternetStatusBridgeIgnoredWhenDelegationDisabled) +{ + InternetStatusNotificationProbe notification; + ASSERT_EQ(interface->Register(¬ification), Core::ERROR_NONE); + + NetworkManagerImplementation->OnDelegatedInternetStatusChange(Exchange::INetworkManager::INTERNET_LIMITED); + EXPECT_FALSE(notification.WaitForCount(1, std::chrono::milliseconds(250))); + + EXPECT_EQ(interface->Unregister(¬ification), Core::ERROR_NONE); +} +#endif + diff --git a/tests/mocks/INetworkManagerMock.h b/tests/mocks/INetworkManagerMock.h index d9a217191..c7fd2408e 100644 --- a/tests/mocks/INetworkManagerMock.h +++ b/tests/mocks/INetworkManagerMock.h @@ -31,7 +31,7 @@ class MockINetworkManager : public WPEFramework::Exchange::INetworkManager { MOCK_METHOD(uint32_t, SetStunEndpoint, (string const endpoint, const uint32_t port, const uint32_t timeout, const uint32_t cacheLifetime), (override)); MOCK_METHOD(uint32_t, GetConnectivityTestEndpoints, (IStringIterator*& endpoints), (const)); MOCK_METHOD(uint32_t, SetConnectivityTestEndpoints, (IStringIterator* const endpoints), (override)); - MOCK_METHOD(uint32_t, IsConnectedToInternet, (string& ipversion, string& interface, WPEFramework::Exchange::INetworkManager::InternetStatus& status), (override)); + MOCK_METHOD(uint32_t, IsConnectedToInternet, (string& ipversion, string& interface, WPEFramework::Exchange::INetworkManager::InternetStatus& status, string& reason), (override)); MOCK_METHOD(uint32_t, GetCaptivePortalURI, (string& uri), (const)); MOCK_METHOD(uint32_t, GetPublicIP, (string& interface, string& ipversion, string& ipaddress), (override)); MOCK_METHOD(uint32_t, Ping, (const string ipversion, const string endpoint, const uint32_t count, const uint16_t timeout, const string guid, string& response), (override)); diff --git a/tests/mocks/thunder/IConnectivityCheck.h b/tests/mocks/thunder/IConnectivityCheck.h new file mode 100644 index 000000000..7898ffbdc --- /dev/null +++ b/tests/mocks/thunder/IConnectivityCheck.h @@ -0,0 +1,73 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2026 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +/** + * Minimal CI stub for IConnectivityCheck — compatible with Thunder R4.4.3. + * + * This file is used only during CI builds (rdk proxy L1/L2 tests) where the + * full entservices-cpc-apis stack is not available. It defines exactly the + * surface consumed by NetworkManagerConnectivityClient and nothing more. + * + * DO NOT use this file outside of test/CI contexts. + */ + +#include + +namespace WPEFramework { +namespace Exchange { + + struct EXTERNAL IConnectivityCheck : virtual public Core::IUnknown { + + // Stub ID — not used for COM lookup in L1/L2 unit tests. + enum { ID = 0x8190 }; + + enum InternetStatus : uint8_t { + NO_INTERNET, + LIMITED_INTERNET, + CAPTIVE_PORTAL, + FULLY_CONNECTED, + UNKNOWN, + }; + + struct EXTERNAL StatusInfo { + InternetStatus status; + string reason; + string interface; + string ipversion; + }; + + struct EXTERNAL INotification : virtual public Core::IUnknown { + enum { ID = 0x8191 }; + + virtual void OnInternetStatusChange(const InternetStatus status, const string& reason) {} + virtual void OnExternalProbeResult(const InternetStatus status, const string& reason, + const string& captivePortalURI) {} + }; + + virtual Core::hresult GetInternetStatus(StatusInfo& info /* @out */) const {}; + virtual Core::hresult GetCaptivePortalURI(string& uri /* @out */) const {}; + + virtual Core::hresult Register(INotification* notification) {}; + virtual Core::hresult Unregister(INotification* notification) {}; + }; + +} // namespace Exchange +} // namespace WPEFramework diff --git a/tools/plugincli/NetworkManagerGdbusTest.cpp b/tools/plugincli/NetworkManagerGdbusTest.cpp index fd28a945f..abeb5f38a 100644 --- a/tools/plugincli/NetworkManagerGdbusTest.cpp +++ b/tools/plugincli/NetworkManagerGdbusTest.cpp @@ -51,7 +51,7 @@ namespace WPEFramework { NMLOG_INFO("calling 'ReportIPAddressChange' cb"); } - void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface) + void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface, const string& reason) { NMLOG_INFO("calling 'ReportInternetStatusChange' cb"); } diff --git a/tools/plugincli/NetworkManagerLibnmTest.cpp b/tools/plugincli/NetworkManagerLibnmTest.cpp index 924a9f7ad..34ece13ce 100644 --- a/tools/plugincli/NetworkManagerLibnmTest.cpp +++ b/tools/plugincli/NetworkManagerLibnmTest.cpp @@ -50,7 +50,7 @@ namespace WPEFramework { NMLOG_INFO("calling 'ReportIPAddressChange' cb"); } - void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface) + void NetworkManagerImplementation::ReportInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState, const Exchange::INetworkManager::InternetStatus currState, const string interface, const string& reason) { NMLOG_INFO("calling 'ReportInternetStatusChange' cb"); } From a9ffe66a506d5e63c8e2a97675ccead4da4d76cf Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Thu, 3 Sep 2026 11:10:04 -0400 Subject: [PATCH 263/271] Release of 4.0.0 Release of 4.0.0 --- CHANGELOG.md | 9 +++++++++ CMakeLists.txt | 4 ++-- definition/NetworkManager.json | 27 +++++++++++---------------- docs/NetworkManagerPlugin.md | 18 +++++++++--------- 4 files changed, 31 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe546edd9..459b82e00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,15 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [4.0.0] - 2026-09-03 +### Added +- Implemented a new `onRouteChange` event notify availability of IP Route either from WiFi or Ethernet +- Integrated new InternetConnectivityManager external component to identify the internet availability without having 204 endpoint +- Publishing onInternetStatusChange event upon wake-up +- Added mutex protection before accessing lastConnectedSSID +- Changed the onWiFiStateChange event to include SSID name +- Updated documentation for events and method descriptions. + ## [3.7.0] - 2026-08-21 ### Changed - Implemented a caching logic about the status of the interface & update based on events diff --git a/CMakeLists.txt b/CMakeLists.txt index cb8361604..636dd3ea8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,8 +36,8 @@ if (NOT WPEFramework_FOUND AND NOT Thunder_FOUND) endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") -set(VERSION_MAJOR 3) -set(VERSION_MINOR 7) +set(VERSION_MAJOR 4) +set(VERSION_MINOR 0) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 15c9ab530..a4535b5d5 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "3.7.0" + "version": "4.0.0" }, "definitions": { "success": { @@ -29,7 +29,7 @@ "autoconfig": { "summary": "`true` if DHCP is used, `false` if IP is configured manually", "type": "boolean", - "example": true + "example": false }, "dhcpserver": { "summary": "The DHCP Server address", @@ -409,9 +409,9 @@ } }, "SetIPSettings":{ - "summary": "Sets the IP settings for the given interface.", + "summary": "Sets the IP settings for the given interface. The `interface`, `ipversion`, and `autoconfig` parameters are mandatory. When `autoconfig` is `false`, the `ipaddress`, `prefix`, `gateway`, `primarydns`, and `secondarydns` parameters must also be provided.", "events":{ - "onAddressChange" : "Triggered when the device connects to router.", + "onIPAddressChange" : "Triggered when the device connects to router.", "onInternetStatusChange" : "Triggered when each IP address is lost or acquired." }, "params": { @@ -445,12 +445,7 @@ "required": [ "interface", "ipversion", - "autoconfig", - "ipaddress", - "prefix", - "gateway", - "primarydns", - "secondarydns" + "autoconfig" ] }, "result": { @@ -974,7 +969,7 @@ "summary": "Remove given SSID from saved SSIDs. This method just removes an entry from the list and of the list is having only one entry thats being removed, it will initiate a disconnect.", "events":{ "onWiFiStateChange" : "Triggered when Wifi state changes to DISCONNECTED", - "onAddressChange" : "Triggered when an IP Address is assigned or lost", + "onIPAddressChange" : "Triggered when an IP Address is assigned or lost", "onInternetStatusChange" : "Triggered when internet connection state changed" }, "params": { @@ -1004,7 +999,7 @@ "summary": "Connects to a saved SSID. The `ssid` parameter is mandatory. Returns failure if `ssid` is not specified or not found in the saved SSIDs list.", "events":{ "onWiFiStateChange" : "Triggered when Wifi state changes to CONNECTING, CONNECTED .", - "onAddressChange" : "Triggered when an IP Address is assigned or lost", + "onIPAddressChange" : "Triggered when an IP Address is assigned or lost", "onInternetStatusChange" : "Triggered when internet connection state changed" }, "params": { @@ -1031,7 +1026,7 @@ } }, "WiFiConnect":{ - "summary": "Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. The security mode is decided based on the highest security mode provided by the SSID. Also when called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`.", + "summary": "Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. The security mode is decided based on the highest security mode provided by the SSID. Also when called with no arguments, this method attempts to connect to the last connected SSID. See `AddToKnownSSIDs`.", "events":{ "onWiFiStateChange" : "Triggered when Wifi state changes to CONNECTING, CONNECTED ." }, @@ -1127,7 +1122,7 @@ "summary": "Disconnects from the currently connected SSID. A event will be posted upon completion", "events":{ "onWIFIStateChange" : "Triggered when Wifi state changes to DISCONNECTED (only if currently connected).", - "onAddressChange" : "Triggered when an IP Address is assigned or lost", + "onIPAddressChange" : "Triggered when an IP Address is assigned or lost", "onInternetStatusChange" : "Triggered when internet connection state changed" }, "result": { @@ -1192,7 +1187,7 @@ "summary": "Initiates a connection using Wifi Protected Setup (WPS). An existing connection will be disconnected before attempting to initiate a new connection. Failure in WPS pairing will trigger an error event.\n\nIf the `method` parameter is set to `SERIALIZED_PIN`, then RDK retrieves the serialized pin using the Manufacturer (MFR) API. If the `method` parameter is set to `PIN`, then RDK use the pin supplied as part of the request. If the `method` parameter is set to `PBC`, then RDK uses Push Button Configuration (PBC) to obtain the pin.", "events":{ "onWIFIStateChange" : "Triggered when Wifi state changes to DISCONNECTED (only if currently connected), CONNECTING, CONNECTED.", - "onAddressChange" : "Triggered when an IP Address is assigned or lost", + "onIPAddressChange" : "Triggered when an IP Address is assigned or lost", "onInternetStatusChange" : "Triggered when internet connection state changed" }, "params": { @@ -1411,7 +1406,7 @@ ] } }, - "onAddressChange":{ + "onIPAddressChange":{ "summary": "Triggered when an IP Address is assigned or lost.", "params": { "type": "object", diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 94efba092..aa7b78290 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 3.7.0** +**Version: 4.0.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 3.7.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 4.0.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity @@ -464,7 +464,7 @@ Gets the IP setting for the given interface. ## *SetIPSettings [method](#head.Methods)* -Sets the IP settings for the given interface. +Sets the IP settings for the given interface. The `interface`, `ipversion`, and `autoconfig` parameters are mandatory. When `autoconfig` is `false`, the `ipaddress`, `prefix`, `gateway`, `primarydns`, and `secondarydns` parameters must also be provided. Also see: [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) @@ -476,11 +476,11 @@ Also see: [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#e | params.interface | string | An interface, such as `eth0` or `wlan0`, depending upon availability of the given interface | | params.ipversion | string | Either IPv4 or IPv6 | | params.autoconfig | boolean | `true` if DHCP is used, `false` if IP is configured manually | -| params.ipaddress | string | The IP address | -| params.prefix | integer | The prefix number | -| params.gateway | string | The gateway address | -| params.primarydns | string | The primary DNS address | -| params.secondarydns | string | The secondary DNS address | +| params?.ipaddress | string | *(optional)* The IP address | +| params?.prefix | integer | *(optional)* The prefix number | +| params?.gateway | string | *(optional)* The gateway address | +| params?.primarydns | string | *(optional)* The primary DNS address | +| params?.secondarydns | string | *(optional)* The secondary DNS address | ### Result @@ -501,7 +501,7 @@ Also see: [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#e "params": { "interface": "wlan0", "ipversion": "IPv4", - "autoconfig": true, + "autoconfig": false, "ipaddress": "192.168.1.101", "prefix": 24, "gateway": "192.168.1.1", From 1f60bbfbe9ea9ce2b9dee9c57602ec51353866e8 Mon Sep 17 00:00:00 2001 From: DevikaJaladi <155776845+DevikaJaladi@users.noreply.github.com> Date: Thu, 10 Sep 2026 19:08:47 -0400 Subject: [PATCH 264/271] RDKEMW-24853: Remove rescan request upon wake-up(NSM-ON) (#350) Reason for change: Remove explicit rescan request upon wake-up(NSM-ON). Test Procedure: Change the channel in AP or change the timeout for SAE GTK_REKEY when the box is in DeepSleep & wake-up; ensure WiFi reconnected with 10s; wake-up journey. Priority: P1 Risks: Low Signed-off-by: Devika Jaladi Co-authored-by: Karunakaran A --- plugin/NetworkManagerImplementation.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index ac828bdad..d6819d40d 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1689,15 +1689,6 @@ namespace WPEFramework if (m_wlanEnabled.load() && m_wlanConnected.load()) { - // Waking from DeepSleep with Network Standby ON: the AP may have - // changed channel while the device slept (802.11 CSA). Trigger an - // active scan so the driver discovers the AP on its new channel. - NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, triggering active WiFi scan"); - if (StartWiFiScan(nullptr, nullptr) != Core::ERROR_NONE) - { - NMLOG_ERROR("OnPowerModeChanged: StartWiFiScan failed"); - } - NMLOG_INFO("OnPowerModeChanged: waking from DeepSleep, requesting DHCP lease on wlan0"); if (ReacquireDHCPLease("wlan0") != Core::ERROR_NONE) { From b9ae26db300a119db92e965c1c79cbb62fdd60a4 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Thu, 10 Sep 2026 19:15:15 -0400 Subject: [PATCH 265/271] Release of 4.1.0 Release of 4.1.0 --- CHANGELOG.md | 4 ++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 459b82e00..007e6fb9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [4.1.0] - 2026-09-10 +### Changed +- Removed the explicit ReScan upon Wake-Up from DeepSleep because the Gnome NW sends SCAN requests with "AllowRoam" false which leads supplicant to Not to connect to WiFi; it ends-up scan-only + ## [4.0.0] - 2026-09-03 ### Added - Implemented a new `onRouteChange` event notify availability of IP Route either from WiFi or Ethernet diff --git a/CMakeLists.txt b/CMakeLists.txt index 636dd3ea8..8d839aa24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 4) -set(VERSION_MINOR 0) +set(VERSION_MINOR 1) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index a4535b5d5..5a22a2d1f 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "4.0.0" + "version": "4.1.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index aa7b78290..2fe6f9a15 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 4.0.0** +**Version: 4.1.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 4.0.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 4.1.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From 4563d199b9f3eda071f6860ed20a9fcd14a86df2 Mon Sep 17 00:00:00 2001 From: tukken-comcast Date: Fri, 11 Sep 2026 21:56:44 +0530 Subject: [PATCH 266/271] RDKEMW-23908: Reduce default ping count from 3 to 1 and timeout from 3s to 1s (#345) * RDKEMW-23908: Reduce default ping count (3->1), timeout (3s->1s), interval (0.2s->0.002s) Reason for change: Current Ping method is synchronous and blocks other method calls while ping is executing. This fix is a mitigation. A proper fix requires methods like Ping that trigger long-running operations to be asynchronous. Test Procedure: Refer ticket Risks: Low Signed-off-by: Tony_Ukken2@comcast.com Co-authored-by: Karunakaran A <48997923+karuna2git@users.noreply.github.com> Co-authored-by: Karunakaran A --- definition/NetworkManager.json | 22 ++++++------ docs/NetworkManagerPlugin.md | 46 +++++++++++++------------ legacy/LegacyNetworkAPIs.cpp | 4 +-- plugin/NetworkManagerImplementation.cpp | 4 +-- plugin/NetworkManagerJsonRpc.cpp | 4 +-- 5 files changed, 42 insertions(+), 38 deletions(-) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 5a22a2d1f..f89f6da17 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -69,7 +69,7 @@ "port":{ "summary": "STUN server port", "type": "integer", - "example": "3478" + "example": 3478 }, "endpoint":{ "summary": "The host name or IP address", @@ -79,7 +79,7 @@ "cacheLifetime":{ "summary": "STUN server cache timeout", "type": "integer", - "example": "0" + "example": 0 }, "state": { "summary": "The given State", @@ -92,7 +92,7 @@ "example": "" }, "count": { - "summary": "The number of requests to send. Default is 3.", + "summary": "The number of requests to send. Default is 1.", "type": "integer", "example": 10 }, @@ -104,7 +104,7 @@ "timeout":{ "summary": "Timeout", "type": "integer", - "example": "30" + "example": 30 }, "ssid":{ "summary": "The WiFi SSID Name", @@ -710,8 +710,10 @@ "count": { "$ref": "#/definitions/count" }, - "timeout": { - "$ref": "#/definitions/timeout" + "timeout":{ + "summary": "Timeout in seconds. Default is 1", + "type": "integer", + "example": 5 }, "guid": { "$ref": "#/definitions/guid" @@ -1121,7 +1123,7 @@ "WiFiDisconnect":{ "summary": "Disconnects from the currently connected SSID. A event will be posted upon completion", "events":{ - "onWIFIStateChange" : "Triggered when Wifi state changes to DISCONNECTED (only if currently connected).", + "onWiFiStateChange" : "Triggered when Wifi state changes to DISCONNECTED (only if currently connected).", "onIPAddressChange" : "Triggered when an IP Address is assigned or lost", "onInternetStatusChange" : "Triggered when internet connection state changed" }, @@ -1186,7 +1188,7 @@ "StartWPS":{ "summary": "Initiates a connection using Wifi Protected Setup (WPS). An existing connection will be disconnected before attempting to initiate a new connection. Failure in WPS pairing will trigger an error event.\n\nIf the `method` parameter is set to `SERIALIZED_PIN`, then RDK retrieves the serialized pin using the Manufacturer (MFR) API. If the `method` parameter is set to `PIN`, then RDK use the pin supplied as part of the request. If the `method` parameter is set to `PBC`, then RDK uses Push Button Configuration (PBC) to obtain the pin.", "events":{ - "onWIFIStateChange" : "Triggered when Wifi state changes to DISCONNECTED (only if currently connected), CONNECTING, CONNECTED.", + "onWiFiStateChange" : "Triggered when Wifi state changes to DISCONNECTED (only if currently connected), CONNECTING, CONNECTED.", "onIPAddressChange" : "Triggered when an IP Address is assigned or lost", "onInternetStatusChange" : "Triggered when internet connection state changed" }, @@ -1229,7 +1231,7 @@ "StopWPS":{ "summary": "Cancels the in-progress WPS pairing operation. The operation forcefully stops the in-progress pairing attempt and aborts the current scan. WPS pairing must be in-progress for the operation to succeed.", "events":{ - "onWIFIStateChange" : "Triggered when Wifi state changes to DISCONNECTED." + "onWiFiStateChange" : "Triggered when Wifi state changes to DISCONNECTED." }, "result": { "type": "object", @@ -1586,7 +1588,7 @@ "state":{ "summary": "WiFi State", "type": "integer", - "example": "5" + "example": 5 }, "status": { "summary": "WiFi status", diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 2fe6f9a15..6a8e9d291 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -448,7 +448,7 @@ Gets the IP setting for the given interface. "result": { "interface": "wlan0", "ipversion": "IPv4", - "autoconfig": true, + "autoconfig": false, "dhcpserver": "192.168.1.1", "ipaddress": "192.168.1.101", "prefix": 24, @@ -466,7 +466,7 @@ Gets the IP setting for the given interface. Sets the IP settings for the given interface. The `interface`, `ipversion`, and `autoconfig` parameters are mandatory. When `autoconfig` is `false`, the `ipaddress`, `prefix`, `gateway`, `primarydns`, and `secondarydns` parameters must also be provided. -Also see: [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) +Also see: [onIPAddressChange](#event.onIPAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) ### Parameters @@ -768,7 +768,7 @@ Seeks whether the device has internet connectivity. This API might take up to 5s "result": { "ipversion": "IPv4", "interface": "wlan0", - "connected": true, + "connected": false, "state": 1, "status": "NO_INTERNET", "reason": "PROBE_FAILED", @@ -885,8 +885,8 @@ Pings the specified endpoint with the specified number of packets. | params | object | | | params.endpoint | string | The host name or IP address | | params.ipversion | string | Either IPv4 or IPv6 | -| params?.count | integer | *(optional)* The number of requests to send. Default is 3 | -| params?.timeout | integer | *(optional)* Timeout | +| params?.count | integer | *(optional)* The number of requests to send. Default is 1 | +| params?.timeout | integer | *(optional)* Timeout in seconds. Default is 1 | | params?.guid | string | *(optional)* The globally unique identifier | ### Result @@ -919,7 +919,7 @@ Pings the specified endpoint with the specified number of packets. "endpoint": "45.57.221.20", "ipversion": "IPv4", "count": 10, - "timeout": 30, + "timeout": 5, "guid": "..." } } @@ -1201,7 +1201,7 @@ Saves the SSID, passphrase, and security mode for upcoming and future sessions. Remove given SSID from saved SSIDs. This method just removes an entry from the list and of the list is having only one entry thats being removed, it will initiate a disconnect. -Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) +Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onIPAddressChange](#event.onIPAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) ### Parameters @@ -1249,7 +1249,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#even Connects to a saved SSID. The `ssid` parameter is mandatory. Returns failure if `ssid` is not specified or not found in the saved SSIDs list. -Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) +Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onIPAddressChange](#event.onIPAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) ### Parameters @@ -1295,7 +1295,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#even ## *WiFiConnect [method](#head.Methods)* -Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. The security mode is decided based on the highest security mode provided by the SSID. Also when called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`. +Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. The security mode is decided based on the highest security mode provided by the SSID. Also when called with no arguments, this method attempts to connect to the last connected SSID. See `AddToKnownSSIDs`. Also see: [onWiFiStateChange](#event.onWiFiStateChange) @@ -1373,7 +1373,7 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) Disconnects from the currently connected SSID. A event will be posted upon completion. -Also see: [onWIFIStateChange](#event.onWIFIStateChange), [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) +Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onIPAddressChange](#event.onIPAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) ### Parameters @@ -1471,7 +1471,7 @@ Initiates a connection using Wifi Protected Setup (WPS). An existing connection If the `method` parameter is set to `SERIALIZED_PIN`, then RDK retrieves the serialized pin using the Manufacturer (MFR) API. If the `method` parameter is set to `PIN`, then RDK use the pin supplied as part of the request. If the `method` parameter is set to `PBC`, then RDK uses Push Button Configuration (PBC) to obtain the pin. -Also see: [onWIFIStateChange](#event.onWIFIStateChange), [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) +Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onIPAddressChange](#event.onIPAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) ### Parameters @@ -1523,7 +1523,7 @@ Also see: [onWIFIStateChange](#event.onWIFIStateChange), [onAddressChange](#even Cancels the in-progress WPS pairing operation. The operation forcefully stops the in-progress pairing attempt and aborts the current scan. WPS pairing must be in-progress for the operation to succeed. -Also see: [onWIFIStateChange](#event.onWIFIStateChange) +Also see: [onWiFiStateChange](#event.onWiFiStateChange) ### Parameters @@ -1788,7 +1788,7 @@ NetworkManager interface events: | Event | Description | | :-------- | :-------- | | [onInterfaceStateChange](#event.onInterfaceStateChange) | Triggered when an interface state is changed | -| [onAddressChange](#event.onAddressChange) | Triggered when an IP Address is assigned or lost | +| [onIPAddressChange](#event.onIPAddressChange) | Triggered when an IP Address is assigned or lost | | [onRouteChange](#event.onRouteChange) | Triggered when the default route changes and a new gateway/DNS becomes available for an interface | | [onActiveInterfaceChange](#event.onActiveInterfaceChange) | Triggered when the primary/active interface changes | | [onInternetStatusChange](#event.onInternetStatusChange) | Triggered when internet connection state changed | @@ -1831,8 +1831,8 @@ Triggered when an interface state is changed. The possible states are } ``` - -## *onAddressChange [event](#head.Notifications)* + +## *onIPAddressChange [event](#head.Notifications)* Triggered when an IP Address is assigned or lost. @@ -1851,7 +1851,7 @@ Triggered when an IP Address is assigned or lost. ```json { "jsonrpc": "2.0", - "method": "client.events.1.onAddressChange", + "method": "client.events.1.onIPAddressChange", "params": { "interface": "wlan0", "ipaddress": "192.168.1.101", @@ -1934,6 +1934,7 @@ Triggered when internet connection state changed.The possible internet connectio | params.state | integer | The internet connection state | | params.status | string | The internet connection status | | params.interface | string | The internet status change on default interface | +| params?.reason | string | *(optional)* The ConnectivityCheckMgr reason when status is NO_INTERNET | ### Example @@ -1942,11 +1943,12 @@ Triggered when internet connection state changed.The possible internet connectio "jsonrpc": "2.0", "method": "client.events.1.onInternetStatusChange", "params": { - "prevState": 1, - "prevStatus": "NO_INTERNET", - "state": 4, - "status": "FULLY_CONNECTED", - "interface": "wlan0" + "prevState": 3, + "prevStatus": "FULLY_CONNECTED", + "state": 1, + "status": "NO_INTERNET", + "interface": "wlan0", + "reason": "PROBE_FAILED" } } ``` @@ -2001,7 +2003,7 @@ Triggered when WIFI connection state get changed. The possible states are define | params | object | | | params.state | integer | WiFi State | | params.status | string | WiFi status | -| params.ssid | string | The SSID associated with the Wi-Fi profile causing the state transition. Disconnected state, contains the SSID associated with the connection that was disconnected | +| params.ssid | string | The SSID associated with the Wi-Fi profile causing the state transition. Disconnected state, contains the SSID associated with the connection that was disconnected. The SSID will be empty when WPS initiated and no AP found with WPS enabled | ### Example diff --git a/legacy/LegacyNetworkAPIs.cpp b/legacy/LegacyNetworkAPIs.cpp index 4e31974c5..172e43f3a 100644 --- a/legacy/LegacyNetworkAPIs.cpp +++ b/legacy/LegacyNetworkAPIs.cpp @@ -621,8 +621,8 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { { string guid{}; string ipversion{"IPv4"}; - uint32_t noOfRequest = 3; - uint16_t timeOutInSeconds = 3; + uint32_t noOfRequest = 1; + uint16_t timeOutInSeconds = 1; endpoint = parameters["endpoint"].String(); diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index d6819d40d..801e5df46 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -552,11 +552,11 @@ namespace WPEFramework } if(0 == strcasecmp("IPv6", ipversion.c_str())) { - snprintf(cmd, sizeof(cmd), "ping6 -c %d -W %d -i 0.2 '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); + snprintf(cmd, sizeof(cmd), "ping6 -c %d -W %d -i 0.002 '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); } else { - snprintf(cmd, sizeof(cmd), "ping -c %d -W %d -i 0.2 '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); + snprintf(cmd, sizeof(cmd), "ping -c %d -W %d -i 0.002 '%s' 2>&1", noOfRequest, timeOutInSeconds, endpoint.c_str()); } NMLOG_DEBUG ("The Command is %s", cmd); diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index 7429cba43..6e309e6ff 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -581,8 +581,8 @@ namespace WPEFramework { string guid{}; string ipversion{"IPv4"}; - uint32_t noOfRequest = 3; - uint16_t timeOutInSeconds = 3; + uint32_t noOfRequest = 1; + uint16_t timeOutInSeconds = 1; endpoint = parameters["endpoint"].String(); From f0292c96ccf7a4adc7ee51ab9f33b2eb3ab862f5 Mon Sep 17 00:00:00 2001 From: Karunakaran A Date: Fri, 11 Sep 2026 12:30:19 -0400 Subject: [PATCH 267/271] Release of 4.2.0 Release of 4.2.0 --- CHANGELOG.md | 5 +++++ CMakeLists.txt | 2 +- definition/NetworkManager.json | 2 +- docs/NetworkManagerPlugin.md | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 007e6fb9a..f9efdbef3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ All notable changes to this RDK Service will be documented in this file. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [4.2.0] - 2026-09-11 +### Changed +- Changed the default values for the number of ping request sent, the timeout and also the interval between the ping packets. +- Moving Ping and Trace methods as ASYNC is being designed + ## [4.1.0] - 2026-09-10 ### Changed - Removed the explicit ReScan upon Wake-Up from DeepSleep because the Gnome NW sends SCAN requests with "AllowRoam" false which leads supplicant to Not to connect to WiFi; it ends-up scan-only diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d839aa24..a860fcfa1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(VERSION_MAJOR 4) -set(VERSION_MINOR 1) +set(VERSION_MINOR 2) set(VERSION_PATCH 0) add_compile_definitions(NETWORKMANAGER_MAJOR_VERSION=${VERSION_MAJOR}) diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index f89f6da17..6cc483656 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -8,7 +8,7 @@ "status": "production", "description": "A Unified `NetworkManager` plugin that allows you to manage Ethernet and Wifi interfaces on the device.", "sourcelocation": "https://github.com/rdkcentral/networkmanager/blob/main/definition/NetworkManager.json", - "version": "4.1.0" + "version": "4.2.0" }, "definitions": { "success": { diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 6a8e9d291..62c3269cc 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -2,7 +2,7 @@ # NetworkManager Plugin -**Version: 4.1.0** +**Version: 4.2.0** **Status: :black_circle::black_circle::black_circle:** @@ -23,7 +23,7 @@ org.rdk.NetworkManager interface for Thunder framework. ## Scope -This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 4.1.0). It includes detailed specification about its methods provided and notifications sent. +This document describes purpose and functionality of the org.rdk.NetworkManager interface (version 4.2.0). It includes detailed specification about its methods provided and notifications sent. ## Case Sensitivity From e980ed4a35d121accc02db1b9c67958e47b8f0d8 Mon Sep 17 00:00:00 2001 From: rdkdevpilot Date: Tue, 15 Sep 2026 20:49:14 +0530 Subject: [PATCH 268/271] Fix PASS_BY_VALUE in NetworkManagerImplementation.cpp Defect ID: 6e0dbd42-72b3-4b14-a740-56f0130fd7fb --- plugin/NetworkManagerImplementation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index 801e5df46..d91127295 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1797,7 +1797,7 @@ namespace WPEFramework std::set NetworkManagerImplementation::swapIpCache( const std::string& iface, const std::string& ipFamily, - IpFamilyCache newCache) + IpFamilyCache&& newCache) { std::set oldKeys; std::lock_guard lock(m_ipCacheMutex); From 31b48f1967573e6569754c22eb19e798e969b339 Mon Sep 17 00:00:00 2001 From: gururaajar Date: Sun, 20 Sep 2026 23:01:14 -0400 Subject: [PATCH 269/271] Updated the devpilot fix --- plugin/NetworkManagerImplementation.h | 2 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 40 +++++++++++++--------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index e22923aa8..d0c10ba16 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -455,7 +455,7 @@ namespace WPEFramework Exchange::INetworkManager::IPAddress& out) const; std::set swapIpCache(const std::string& iface, const std::string& ipFamily, - IpFamilyCache newCache); + IpFamilyCache&& newCache); std::atomic m_ethConnected; std::atomic m_wlanConnected; diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index e2918b9c9..962680935 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -226,18 +226,33 @@ namespace WPEFramework } /* Swap new snapshot into instance cache; collect old global address keys for diff. */ + std::set newKeys; + for (const auto& address : newCache.globalAddresses) { + newKeys.insert(address.first); + } + + std::string family = isIPv6 ? "IPv6" : "IPv4"; + const bool routeReady = newCache.valid + && !newCache.globalAddresses.empty() + && !newCache.gateway.empty() + && !newCache.primarydns.empty(); + Exchange::INetworkManager::IPAddress routeAddress; + if (routeReady) { + routeAddress = newCache.toIPAddress(); + routeAddress.ipversion = family; + } + std::set oldKeys = _instance->swapIpCache( - ifname, isIPv6 ? "IPv6" : "IPv4", newCache); + ifname, family, std::move(newCache)); /* Emit address acquired/lost events from global-address key diff (outside the lock). */ - std::string family = isIPv6 ? "IPv6" : "IPv4"; - for (const auto& kv : newCache.globalAddresses) { - if (oldKeys.find(kv.first) == oldKeys.end()) { - _instance->ReportIPAddressChange(ifname, family, kv.first, Exchange::INetworkManager::IP_ACQUIRED); + for (const auto& key : newKeys) { + if (oldKeys.find(key) == oldKeys.end()) { + _instance->ReportIPAddressChange(ifname, family, key, Exchange::INetworkManager::IP_ACQUIRED); } } for (const auto& key : oldKeys) { - if (newCache.globalAddresses.find(key) == newCache.globalAddresses.end()) { + if (newKeys.find(key) == newKeys.end()) { _instance->ReportIPAddressChange(ifname, family, key, Exchange::INetworkManager::IP_LOST); } } @@ -248,15 +263,8 @@ namespace WPEFramework funnel here, so a single emission per snapshot covers all three. Each family emits independently — dual-stack consumers will see one event per family. */ - if (newCache.valid - && !newCache.globalAddresses.empty() - && !newCache.gateway.empty() - && !newCache.primarydns.empty()) { - /* Values are already in hand from the snapshot we just built, so emit - them directly instead of having ReportRouteChange re-query the cache. */ - Exchange::INetworkManager::IPAddress ipAddress = newCache.toIPAddress(); - ipAddress.ipversion = family; - _instance->ReportRouteChange(ifname, family, ipAddress); + if (routeReady) { + _instance->ReportRouteChange(ifname, family, routeAddress); } } @@ -646,7 +654,7 @@ namespace WPEFramework if (_instance) { for (const char* family : {"IPv4", "IPv6"}) { IpFamilyCache empty; - std::set oldKeys = _instance->swapIpCache(ifname, family, empty); + std::set oldKeys = _instance->swapIpCache(ifname, family, std::move(empty)); for (const auto& key : oldKeys) { _instance->ReportIPAddressChange(ifname, family, key, Exchange::INetworkManager::IP_LOST); } From af7f187796b73d754fc5ea836fb2e0ba843a00f4 Mon Sep 17 00:00:00 2001 From: gururaajar Date: Sun, 20 Sep 2026 23:17:50 -0400 Subject: [PATCH 270/271] Updated the fix --- plugin/NetworkManagerImplementation.cpp | 4 +-- plugin/NetworkManagerImplementation.h | 2 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 40 +++++++++------------- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index d91127295..a2c9e11ef 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1797,14 +1797,14 @@ namespace WPEFramework std::set NetworkManagerImplementation::swapIpCache( const std::string& iface, const std::string& ipFamily, - IpFamilyCache&& newCache) + const IpFamilyCache& newCache) { std::set oldKeys; std::lock_guard lock(m_ipCacheMutex); IpFamilyCache& cache = m_ipCacheMap[{iface, ipFamily}]; for (const auto& kv : cache.globalAddresses) oldKeys.insert(kv.first); - cache = std::move(newCache); + cache = newCache; return oldKeys; } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index d0c10ba16..3b317ccc0 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -455,7 +455,7 @@ namespace WPEFramework Exchange::INetworkManager::IPAddress& out) const; std::set swapIpCache(const std::string& iface, const std::string& ipFamily, - IpFamilyCache&& newCache); + const IpFamilyCache& newCache); std::atomic m_ethConnected; std::atomic m_wlanConnected; diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 962680935..e2918b9c9 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -226,33 +226,18 @@ namespace WPEFramework } /* Swap new snapshot into instance cache; collect old global address keys for diff. */ - std::set newKeys; - for (const auto& address : newCache.globalAddresses) { - newKeys.insert(address.first); - } - - std::string family = isIPv6 ? "IPv6" : "IPv4"; - const bool routeReady = newCache.valid - && !newCache.globalAddresses.empty() - && !newCache.gateway.empty() - && !newCache.primarydns.empty(); - Exchange::INetworkManager::IPAddress routeAddress; - if (routeReady) { - routeAddress = newCache.toIPAddress(); - routeAddress.ipversion = family; - } - std::set oldKeys = _instance->swapIpCache( - ifname, family, std::move(newCache)); + ifname, isIPv6 ? "IPv6" : "IPv4", newCache); /* Emit address acquired/lost events from global-address key diff (outside the lock). */ - for (const auto& key : newKeys) { - if (oldKeys.find(key) == oldKeys.end()) { - _instance->ReportIPAddressChange(ifname, family, key, Exchange::INetworkManager::IP_ACQUIRED); + std::string family = isIPv6 ? "IPv6" : "IPv4"; + for (const auto& kv : newCache.globalAddresses) { + if (oldKeys.find(kv.first) == oldKeys.end()) { + _instance->ReportIPAddressChange(ifname, family, kv.first, Exchange::INetworkManager::IP_ACQUIRED); } } for (const auto& key : oldKeys) { - if (newKeys.find(key) == newKeys.end()) { + if (newCache.globalAddresses.find(key) == newCache.globalAddresses.end()) { _instance->ReportIPAddressChange(ifname, family, key, Exchange::INetworkManager::IP_LOST); } } @@ -263,8 +248,15 @@ namespace WPEFramework funnel here, so a single emission per snapshot covers all three. Each family emits independently — dual-stack consumers will see one event per family. */ - if (routeReady) { - _instance->ReportRouteChange(ifname, family, routeAddress); + if (newCache.valid + && !newCache.globalAddresses.empty() + && !newCache.gateway.empty() + && !newCache.primarydns.empty()) { + /* Values are already in hand from the snapshot we just built, so emit + them directly instead of having ReportRouteChange re-query the cache. */ + Exchange::INetworkManager::IPAddress ipAddress = newCache.toIPAddress(); + ipAddress.ipversion = family; + _instance->ReportRouteChange(ifname, family, ipAddress); } } @@ -654,7 +646,7 @@ namespace WPEFramework if (_instance) { for (const char* family : {"IPv4", "IPv6"}) { IpFamilyCache empty; - std::set oldKeys = _instance->swapIpCache(ifname, family, std::move(empty)); + std::set oldKeys = _instance->swapIpCache(ifname, family, empty); for (const auto& key : oldKeys) { _instance->ReportIPAddressChange(ifname, family, key, Exchange::INetworkManager::IP_LOST); } From 2aee7a991058dc83db0dee55d3d82d7c89b8eaf1 Mon Sep 17 00:00:00 2001 From: gururaajar Date: Tue, 22 Sep 2026 22:13:36 -0400 Subject: [PATCH 271/271] Updated the devpilot fix --- plugin/NetworkManagerImplementation.cpp | 4 +- plugin/NetworkManagerImplementation.h | 2 +- plugin/gnome/NetworkManagerGnomeEvents.cpp | 41 +++++++++++-------- tests/l2Test/libnm/l2_test_libnmproxy.cpp | 37 +++++++++-------- .../l2Test/libnm/l2_test_libnmproxyEvent.cpp | 9 ++-- 5 files changed, 52 insertions(+), 41 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index a2c9e11ef..d91127295 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -1797,14 +1797,14 @@ namespace WPEFramework std::set NetworkManagerImplementation::swapIpCache( const std::string& iface, const std::string& ipFamily, - const IpFamilyCache& newCache) + IpFamilyCache&& newCache) { std::set oldKeys; std::lock_guard lock(m_ipCacheMutex); IpFamilyCache& cache = m_ipCacheMap[{iface, ipFamily}]; for (const auto& kv : cache.globalAddresses) oldKeys.insert(kv.first); - cache = newCache; + cache = std::move(newCache); return oldKeys; } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 3b317ccc0..d0c10ba16 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -455,7 +455,7 @@ namespace WPEFramework Exchange::INetworkManager::IPAddress& out) const; std::set swapIpCache(const std::string& iface, const std::string& ipFamily, - const IpFamilyCache& newCache); + IpFamilyCache&& newCache); std::atomic m_ethConnected; std::atomic m_wlanConnected; diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index e2918b9c9..56a71625e 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -32,6 +32,7 @@ #include "NetworkManagerImplementation.h" #include "INetworkManager.h" #include +#include #ifdef ENABLE_MIGRATION_MFRMGR_SUPPORT #include "NetworkManagerGnomeMfrMgr.h" @@ -226,18 +227,33 @@ namespace WPEFramework } /* Swap new snapshot into instance cache; collect old global address keys for diff. */ + std::set newKeys; + for (const auto& address : newCache.globalAddresses) { + newKeys.insert(address.first); + } + + std::string family = isIPv6 ? "IPv6" : "IPv4"; + const bool routeReady = newCache.valid + && !newCache.globalAddresses.empty() + && !newCache.gateway.empty() + && !newCache.primarydns.empty(); + Exchange::INetworkManager::IPAddress routeAddress; + if (routeReady) { + routeAddress = newCache.toIPAddress(); + routeAddress.ipversion = family; + } + std::set oldKeys = _instance->swapIpCache( - ifname, isIPv6 ? "IPv6" : "IPv4", newCache); + ifname, family, std::move(newCache)); /* Emit address acquired/lost events from global-address key diff (outside the lock). */ - std::string family = isIPv6 ? "IPv6" : "IPv4"; - for (const auto& kv : newCache.globalAddresses) { - if (oldKeys.find(kv.first) == oldKeys.end()) { - _instance->ReportIPAddressChange(ifname, family, kv.first, Exchange::INetworkManager::IP_ACQUIRED); + for (const auto& key : newKeys) { + if (oldKeys.find(key) == oldKeys.end()) { + _instance->ReportIPAddressChange(ifname, family, key, Exchange::INetworkManager::IP_ACQUIRED); } } for (const auto& key : oldKeys) { - if (newCache.globalAddresses.find(key) == newCache.globalAddresses.end()) { + if (newKeys.find(key) == newKeys.end()) { _instance->ReportIPAddressChange(ifname, family, key, Exchange::INetworkManager::IP_LOST); } } @@ -248,15 +264,8 @@ namespace WPEFramework funnel here, so a single emission per snapshot covers all three. Each family emits independently — dual-stack consumers will see one event per family. */ - if (newCache.valid - && !newCache.globalAddresses.empty() - && !newCache.gateway.empty() - && !newCache.primarydns.empty()) { - /* Values are already in hand from the snapshot we just built, so emit - them directly instead of having ReportRouteChange re-query the cache. */ - Exchange::INetworkManager::IPAddress ipAddress = newCache.toIPAddress(); - ipAddress.ipversion = family; - _instance->ReportRouteChange(ifname, family, ipAddress); + if (routeReady) { + _instance->ReportRouteChange(ifname, family, routeAddress); } } @@ -646,7 +655,7 @@ namespace WPEFramework if (_instance) { for (const char* family : {"IPv4", "IPv6"}) { IpFamilyCache empty; - std::set oldKeys = _instance->swapIpCache(ifname, family, empty); + std::set oldKeys = _instance->swapIpCache(ifname, family, std::move(empty)); for (const auto& key : oldKeys) { _instance->ReportIPAddressChange(ifname, family, key, Exchange::INetworkManager::IP_LOST); } diff --git a/tests/l2Test/libnm/l2_test_libnmproxy.cpp b/tests/l2Test/libnm/l2_test_libnmproxy.cpp index a102c7eac..883f24db8 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxy.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxy.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "FactoriesImplementation.h" #include "WrapsMock.h" @@ -504,7 +505,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_ipv4_fromCache) cache.secondarydns = "8.8.4.4"; cache.dhcpserver = "192.168.1.11"; cache.autoconfig = true; - Plugin::_instance->swapIpCache("eth0", "IPv4", cache); + Plugin::_instance->swapIpCache("eth0", "IPv4", std::move(cache)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); @@ -525,7 +526,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_ipv4_autoconfig) Plugin::IpFamilyCache cache; cache.valid = true; cache.autoconfig = true; - Plugin::_instance->swapIpCache("eth0", "IPv4", cache); + Plugin::_instance->swapIpCache("eth0", "IPv4", std::move(cache)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); std::string expectedResponse = @@ -541,7 +542,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_ipv4_staticConfig) cache.autoconfig = false; cache.globalAddresses["192.168.1.100"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); cache.gateway = "192.168.1.1"; - Plugin::_instance->swapIpCache("eth0", "IPv4", cache); + Plugin::_instance->swapIpCache("eth0", "IPv4", std::move(cache)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); @@ -558,7 +559,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_wlan0_fromCache) cache.globalAddresses["10.0.0.5"] = Plugin::GlobalAddressInfo(8, Plugin::ADDR_GLOBAL); cache.gateway = "10.0.0.1"; cache.primarydns = "1.1.1.1"; - Plugin::_instance->swapIpCache("wlan0", "IPv4", cache); + Plugin::_instance->swapIpCache("wlan0", "IPv4", std::move(cache)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"wlan0\"}"), response)); EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); @@ -577,7 +578,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_ipv4_config_valid) cache.primarydns = "8.8.8.8"; cache.secondarydns = "8.8.4.4"; cache.dhcpserver = "192.168.1.11"; - Plugin::_instance->swapIpCache("eth0", "IPv4", cache); + Plugin::_instance->swapIpCache("eth0", "IPv4", std::move(cache)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); @@ -603,7 +604,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_ipv6_config_valid) cache.primarydns = "2001:4860:4860::8888"; cache.secondarydns = "2001:4860:4860::8844"; cache.dhcpserver = "2001:db8::1"; - Plugin::_instance->swapIpCache("eth0", "IPv6", cache); + Plugin::_instance->swapIpCache("eth0", "IPv6", std::move(cache)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv6\"}"), response)); @@ -627,7 +628,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_ipv6_mac_based_fallback) cache.autoconfig = true; cache.globalAddresses["2001:db8::aabb:ccff:fedd:eeff"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL_MAC_BASED); cache.gateway = "fe80::1"; - Plugin::_instance->swapIpCache("eth0", "IPv6", cache); + Plugin::_instance->swapIpCache("eth0", "IPv6", std::move(cache)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv6\"}"), response)); EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); @@ -644,7 +645,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_ipv6_prefer_non_mac_global) /* Insert MAC-based first to ensure it's not selected by insertion order */ cache.globalAddresses["2001:db8::aabb:ccff:fedd:eeff"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL_MAC_BASED); cache.globalAddresses["2001:db8::1234:5678"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL); - Plugin::_instance->swapIpCache("eth0", "IPv6", cache); + Plugin::_instance->swapIpCache("eth0", "IPv6", std::move(cache)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv6\"}"), response)); EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); @@ -658,7 +659,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_ipv6_only_cached_request_ipv4) cache.valid = true; cache.autoconfig = true; cache.globalAddresses["2001:db8::1"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL); - Plugin::_instance->swapIpCache("eth0", "IPv6", cache); + Plugin::_instance->swapIpCache("eth0", "IPv6", std::move(cache)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv4\"}"), response)); EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); @@ -672,7 +673,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_cache_invalidated) Plugin::IpFamilyCache cache; cache.valid = false; cache.globalAddresses["192.168.1.5"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); - Plugin::_instance->swapIpCache("eth0", "IPv4", cache); + Plugin::_instance->swapIpCache("eth0", "IPv4", std::move(cache)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); @@ -686,7 +687,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_ipversion_case_insensitive) cache.valid = true; cache.autoconfig = true; cache.globalAddresses["2001:db8::99"] = Plugin::GlobalAddressInfo(128, Plugin::ADDR_GLOBAL); - Plugin::_instance->swapIpCache("eth0", "IPv6", cache); + Plugin::_instance->swapIpCache("eth0", "IPv6", std::move(cache)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"ipv6\"}"), response)); EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); @@ -704,7 +705,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_ipv6_ula_only) cache.autoconfig = true; cache.uniqueLocalAddresses.insert("fd00::1234:abcd"); cache.gateway = "fe80::1"; - Plugin::_instance->swapIpCache("eth0", "IPv6", cache); + Plugin::_instance->swapIpCache("eth0", "IPv6", std::move(cache)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv6\"}"), response)); EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); @@ -722,13 +723,13 @@ TEST_F(NetworkManagerTest, GetIPSettings_swapIpCache_returns_old_keys) cache1.valid = true; cache1.globalAddresses["192.168.1.10"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); cache1.globalAddresses["192.168.1.20"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); - Plugin::_instance->swapIpCache("eth0", "IPv4", cache1); + Plugin::_instance->swapIpCache("eth0", "IPv4", std::move(cache1)); /* Now swap with a new cache and check old keys are returned */ Plugin::IpFamilyCache cache2; cache2.valid = true; cache2.globalAddresses["10.0.0.1"] = Plugin::GlobalAddressInfo(8, Plugin::ADDR_GLOBAL); - std::set oldKeys = Plugin::_instance->swapIpCache("eth0", "IPv4", cache2); + std::set oldKeys = Plugin::_instance->swapIpCache("eth0", "IPv4", std::move(cache2)); EXPECT_EQ(oldKeys.size(), 2u); EXPECT_TRUE(oldKeys.count("192.168.1.10") == 1); @@ -746,14 +747,14 @@ TEST_F(NetworkManagerTest, GetIPSettings_separate_ipv4_ipv6_caches) cache4.valid = true; cache4.autoconfig = true; cache4.globalAddresses["192.168.1.50"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); - Plugin::_instance->swapIpCache("eth0", "IPv4", cache4); + Plugin::_instance->swapIpCache("eth0", "IPv4", std::move(cache4)); Plugin::IpFamilyCache cache6; cache6.valid = true; cache6.autoconfig = true; cache6.globalAddresses["2001:db8::50"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL); cache6.uniqueLocalAddresses.insert("fd12::50"); - Plugin::_instance->swapIpCache("eth0", "IPv6", cache6); + Plugin::_instance->swapIpCache("eth0", "IPv6", std::move(cache6)); /* Query IPv4 */ EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\", \"ipversion\":\"IPv4\"}"), response)); @@ -773,7 +774,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_cache_cleared) Plugin::IpFamilyCache cache; cache.valid = true; cache.globalAddresses["192.168.1.99"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); - Plugin::_instance->swapIpCache("eth0", "IPv4", cache); + Plugin::_instance->swapIpCache("eth0", "IPv4", std::move(cache)); /* Verify it's there */ EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); @@ -781,7 +782,7 @@ TEST_F(NetworkManagerTest, GetIPSettings_cache_cleared) /* Clear cache by swapping with default (valid=false) */ Plugin::IpFamilyCache empty; - Plugin::_instance->swapIpCache("eth0", "IPv4", empty); + Plugin::_instance->swapIpCache("eth0", "IPv4", std::move(empty)); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\"}"), response)); EXPECT_TRUE(response.find("\"success\":true") != std::string::npos); diff --git a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp index dfecf5fd6..e9eed28d1 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "FactoriesImplementation.h" #include "WrapsMock.h" @@ -555,7 +556,7 @@ TEST_F(NetworkManagerEventTest, disconnect_clears_ipv4_cache_eth0) cache.valid = true; cache.globalAddresses["192.168.1.50"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); cache.gateway = "192.168.1.1"; - Plugin::_instance->swapIpCache("eth0", "IPv4", cache); + Plugin::_instance->swapIpCache("eth0", "IPv4", std::move(cache)); /* Verify cache is populated */ EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"eth0\",\"ipversion\":\"IPv4\"}"), response)); @@ -586,7 +587,7 @@ TEST_F(NetworkManagerEventTest, disconnect_clears_ipv6_cache_wlan0) cache.valid = true; cache.globalAddresses["2001:db8::1"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL); cache.gateway = "fe80::1"; - Plugin::_instance->swapIpCache("wlan0", "IPv6", cache); + Plugin::_instance->swapIpCache("wlan0", "IPv6", std::move(cache)); /* Verify cache is populated */ EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("GetIPSettings"), _T("{\"interface\":\"wlan0\",\"ipversion\":\"IPv6\"}"), response)); @@ -615,12 +616,12 @@ TEST_F(NetworkManagerEventTest, disconnect_clears_both_ip_family_caches) Plugin::IpFamilyCache cache4; cache4.valid = true; cache4.globalAddresses["192.168.1.50"] = Plugin::GlobalAddressInfo(24, Plugin::ADDR_GLOBAL); - Plugin::_instance->swapIpCache("eth0", "IPv4", cache4); + Plugin::_instance->swapIpCache("eth0", "IPv4", std::move(cache4)); Plugin::IpFamilyCache cache6; cache6.valid = true; cache6.globalAddresses["2001:db8::99"] = Plugin::GlobalAddressInfo(64, Plugin::ADDR_GLOBAL); - Plugin::_instance->swapIpCache("eth0", "IPv6", cache6); + Plugin::_instance->swapIpCache("eth0", "IPv6", std::move(cache6)); /* Trigger disconnect — refreshIpFamilyCache is called for BOTH families */ NMDevice *DummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL));