diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index 0891f2cc..3dff5571 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 c00be066..a041f624 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 a4488dc5..15c739cf 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 11904b9d..d834861d 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 319476f9..6a101bdf 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 3ccc8ae0..8a0c33d0 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 b63a322c..22af0cdb 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 16bf3376..761c39fb 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 1103cee3..9e9fe13c 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{}; @@ -423,6 +422,7 @@ namespace WPEFramework return rc; } #endif + uint32_t NetworkManagerImplementation::SetInterfaceState(const string& interface/* @in */, const bool enabled /* @in */) { @@ -438,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; @@ -638,7 +732,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 +794,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 +865,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 +1004,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 +1024,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 c819e17b..7d97e5e8 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 c74944c8..e336ddc3 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 5dd09070..589cbb96 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) + { + NMLOG_DEBUG("SSID matched: %s", ssidstr.c_str()); + ssidMatch = true; + } + else { - 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 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,26 +639,82 @@ 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"); 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) @@ -630,14 +724,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 +748,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 +786,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 +904,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 +915,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 +1146,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 +1162,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 +1198,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 +1271,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 +1306,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 +1368,7 @@ namespace WPEFramework m_cancellable, wifiConnectTempCb, this); + g_variant_unref(connSettings); } if(m_connection) g_object_unref(m_connection); @@ -1211,6 +1470,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 +1484,9 @@ namespace WPEFramework NULL, addToKnownSSIDsUpdateCb, this); + g_variant_unref(connSettings); + g_object_unref(m_connection); + m_connection = NULL; } else { @@ -1231,6 +1495,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 +1507,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 +1753,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 +1761,8 @@ namespace WPEFramework } else NMLOG_INFO("WPS connection added/activated successfully"); + if(activeConnection) + g_object_unref(activeConnection); g_main_loop_quit(loop); } @@ -1592,6 +1863,8 @@ namespace WPEFramework if(!g_main_context_acquire(wpsContext)) { NMLOG_ERROR("acquire wpsContext failed !!"); + g_main_context_unref(wpsContext); + wpsContext = NULL; break; } @@ -1603,6 +1876,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 +1992,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 +2021,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 +2049,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 ca4d1d95..51164aa5 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(); @@ -66,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(); @@ -99,7 +101,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 f2a1e959..670b0a6f 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 9cb4de3c..bd633dd7 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 61ba95e1..c587688a 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 278dcbcb..d32f4615 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 c4a98390..27a8b287 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));