diff --git a/NetworkManagerGnomeWIFI.cpp b/NetworkManagerGnomeWIFI.cpp index 4d665b91..8fb62a70 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 74704015..eada5a8a 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;