diff options
Diffstat (limited to 'components/wifi/wifi_service_win.cc')
-rw-r--r-- | components/wifi/wifi_service_win.cc | 172 |
1 files changed, 151 insertions, 21 deletions
diff --git a/components/wifi/wifi_service_win.cc b/components/wifi/wifi_service_win.cc index 5f837fc..efaaa9b 100644 --- a/components/wifi/wifi_service_win.cc +++ b/components/wifi/wifi_service_win.cc @@ -42,6 +42,7 @@ const char kWlanGetAvailableNetworkList[] = "WlanGetAvailableNetworkList"; const char kWlanGetNetworkBssList[] = "WlanGetNetworkBssList"; const char kWlanGetProfile[] = "WlanGetProfile"; const char kWlanOpenHandle[] = "WlanOpenHandle"; +const char kWlanQueryInterface[] = "WlanQueryInterface"; const char kWlanRegisterNotification[] = "WlanRegisterNotification"; const char kWlanSaveTemporaryProfile[] = "WlanSaveTemporaryProfile"; const char kWlanScan[] = "WlanScan"; @@ -101,6 +102,15 @@ typedef DWORD (WINAPI* WlanOpenHandleFunction)( PDWORD pdwNegotiatedVersion, PHANDLE phClientHandle); +typedef DWORD (WINAPI* WlanQueryInterfaceFunction)( + HANDLE hClientHandle, + const GUID *pInterfaceGuid, + WLAN_INTF_OPCODE OpCode, + PVOID pReserved, + PDWORD pdwDataSize, + PVOID *ppData, + PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType); + typedef DWORD (WINAPI* WlanRegisterNotificationFunction)( HANDLE hClientHandle, DWORD dwNotifSource, @@ -293,12 +303,24 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { // Disconnect from currently connected network if any. DWORD Disconnect(); + // Get Frequency of currently connected network |network_guid|. If network is + // not connected, then return |kFrequencyUnknown|. + Frequency WiFiServiceImpl::GetConnectedFrequency( + const std::string& network_guid); + + // Get desired connection freqency if it was set using |SetProperties|. + // Default to |kFrequencyAny|. + Frequency GetFrequencyToConnect(const std::string& network_guid) const; + // Get DOT11_BSSID_LIST of desired BSSIDs to connect to |ssid| network on // given |frequency|. DWORD GetDesiredBssList(DOT11_SSID& ssid, Frequency frequency, scoped_ptr<DOT11_BSSID_LIST>* desired_list); + // Normalizes |frequency_in_mhz| into one of |Frequency| values. + Frequency GetNormalizedFrequency(int frequency_in_mhz) const; + // Save temporary wireless profile for |network_guid|. DWORD SaveTempProfile(const std::string& network_guid); @@ -331,6 +353,7 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { WlanGetNetworkBssListFunction WlanGetNetworkBssList_function_; WlanGetProfileFunction WlanGetProfile_function_; WlanOpenHandleFunction WlanOpenHandle_function_; + WlanQueryInterfaceFunction WlanQueryInterface_function_; WlanRegisterNotificationFunction WlanRegisterNotification_function_; WlanScanFunction WlanScan_function_; // WlanSaveTemporaryProfile function may not be avaiable on Windows XP. @@ -341,6 +364,9 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { // GUID of the currently connected interface, if any, otherwise the GUID of // one of the WLAN interfaces. GUID interface_guid_; + // Temporary storage of network properties indexed by |network_guid|. Persist + // only in memory. + DictionaryValue connect_properties_; // Preserved WLAN profile xml. std::map<std::string, std::string> saved_profiles_xml_; // Observer to get notified when network(s) have changed (e.g. connect). @@ -421,9 +447,16 @@ void WiFiServiceImpl::SetProperties( const std::string& network_guid, scoped_ptr<base::DictionaryValue> properties, std::string* error) { - // This method is not implemented in first version as it is not used by - // Google Cast extension. - CheckError(ERROR_CALL_NOT_IMPLEMENTED, kWiFiServiceError, error); + // Temporary preserve WiFi properties (desired frequency, wifi password) to + // use in StartConnect. + DCHECK(properties.get()); + if (!properties->HasKey(onc::network_type::kWiFi)) { + DVLOG(0) << "Missing WiFi properties:" << *properties; + *error = kWiFiServiceError; + return; + } + connect_properties_.SetWithoutPathExpansion(network_guid, + properties.release()); } void WiFiServiceImpl::GetVisibleNetworks(const std::string& network_type, @@ -465,9 +498,15 @@ void WiFiServiceImpl::StartConnect(const std::string& network_guid, std::string connected_network_guid; error_code = SaveCurrentConnectedNetwork(&connected_network_guid); if (error_code == ERROR_SUCCESS) { - Frequency frequency = kFrequencyAny; + // Check, if the network is already connected on desired frequency. + bool already_connected = (network_guid == connected_network_guid); + Frequency frequency = GetFrequencyToConnect(network_guid); + if (already_connected && frequency != kFrequencyAny) { + Frequency connected_frequency = GetConnectedFrequency(network_guid); + already_connected = (frequency == connected_frequency); + } // Connect only if network |network_guid| is not connected already. - if (network_guid != connected_network_guid) + if (!already_connected) error_code = Connect(network_guid, frequency); if (error_code == ERROR_SUCCESS) { // Notify that previously connected network has changed. @@ -680,6 +719,9 @@ DWORD WiFiServiceImpl::LoadWlanLibrary() { WlanOpenHandle_function_ = reinterpret_cast<WlanOpenHandleFunction>( ::GetProcAddress(wlan_api_library_, kWlanOpenHandle)); + WlanQueryInterface_function_ = + reinterpret_cast<WlanQueryInterfaceFunction>( + ::GetProcAddress(wlan_api_library_, kWlanQueryInterface)); WlanRegisterNotification_function_ = reinterpret_cast<WlanRegisterNotificationFunction>( ::GetProcAddress(wlan_api_library_, kWlanRegisterNotification)); @@ -698,6 +740,7 @@ DWORD WiFiServiceImpl::LoadWlanLibrary() { !WlanGetAvailableNetworkList_function_ || !WlanGetProfile_function_ || !WlanOpenHandle_function_ || + !WlanQueryInterface_function_ || !WlanRegisterNotification_function_ || !WlanScan_function_) { DLOG(ERROR) << "Unable to find required WlanApi function."; @@ -753,7 +796,7 @@ DWORD WiFiServiceImpl::OpenClientHandle() { error = ERROR_NOINTERFACE; } } - // Clean up. + // Clean up.. if (interface_list != NULL) WlanFreeMemory_function_(interface_list); } @@ -936,10 +979,8 @@ void WiFiServiceImpl::NetworkPropertiesFromAvailableNetwork( 0 == memcmp(bss_entry.dot11Ssid.ucSSID, wlan.dot11Ssid.ucSSID, bss_entry.dot11Ssid.uSSIDLength)) { - if (bss_entry.ulChCenterFrequency < 3000000) - properties->frequency = kFrequency2400; - else - properties->frequency = kFrequency5000; + properties->frequency = GetNormalizedFrequency( + bss_entry.ulChCenterFrequency / 1000); properties->frequency_list.push_back(properties->frequency); properties->bssid = NetworkProperties::MacAddressAsString( bss_entry.dot11Bssid); @@ -1012,7 +1053,7 @@ DWORD WiFiServiceImpl::GetVisibleNetworkList(NetworkList* network_list) { } } - // clean up + // Clean up. if (available_network_list != NULL) { WlanFreeMemory_function_(available_network_list); } @@ -1045,7 +1086,7 @@ DWORD WiFiServiceImpl::FindConnectedNetwork( } } - // clean up + // Clean up. if (available_network_list != NULL) { WlanFreeMemory_function_(available_network_list); } @@ -1053,6 +1094,90 @@ DWORD WiFiServiceImpl::FindConnectedNetwork( return error; } +WiFiService::Frequency WiFiServiceImpl::GetConnectedFrequency( + const std::string& network_guid) { + if (client_ == NULL) { + NOTREACHED(); + return kFrequencyUnknown; + } + + // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is + // needed, then different method of getting BSS (e.g. OID query) will have + // to be used. + if (WlanGetNetworkBssList_function_ == NULL) + return kFrequencyUnknown; + + Frequency frequency = kFrequencyUnknown; + DWORD error = ERROR_SUCCESS; + DWORD data_size = 0; + PWLAN_CONNECTION_ATTRIBUTES wlan_connection_attributes = NULL; + PWLAN_BSS_LIST bss_list = NULL; + error = WlanQueryInterface_function_( + client_, + &interface_guid_, + wlan_intf_opcode_current_connection, + NULL, + &data_size, + reinterpret_cast<PVOID*>(&wlan_connection_attributes), + NULL); + if (error == ERROR_SUCCESS && + wlan_connection_attributes != NULL && + wlan_connection_attributes->isState == wlan_interface_state_connected) { + WLAN_ASSOCIATION_ATTRIBUTES& connected_wlan = + wlan_connection_attributes->wlanAssociationAttributes; + // Try to find connected frequency based on bss. + if (GUIDFromSSID(connected_wlan.dot11Ssid) == network_guid && + WlanGetNetworkBssList_function_ != NULL) { + error = WlanGetNetworkBssList_function_(client_, + &interface_guid_, + &connected_wlan.dot11Ssid, + connected_wlan.dot11BssType, + FALSE, + NULL, + &bss_list); + if (error == ERROR_SUCCESS && NULL != bss_list) { + // Go through bss_list and find matching BSSID. + for (size_t bss = 0; bss < bss_list->dwNumberOfItems; ++bss) { + const WLAN_BSS_ENTRY& bss_entry(bss_list->wlanBssEntries[bss]); + if (0 == memcmp(bss_entry.dot11Bssid, + connected_wlan.dot11Bssid, + sizeof(bss_entry.dot11Bssid))) { + frequency = GetNormalizedFrequency( + bss_entry.ulChCenterFrequency / 1000); + break; + } + } + } + } + } + + // Clean up. + if (wlan_connection_attributes != NULL) { + WlanFreeMemory_function_(wlan_connection_attributes); + } + + if (bss_list != NULL) { + WlanFreeMemory_function_(bss_list); + } + + return frequency; +} + +WiFiService::Frequency WiFiServiceImpl::GetFrequencyToConnect( + const std::string& network_guid) const { + // Check whether desired frequency is set in |connect_properties_|. + const DictionaryValue* properties; + const DictionaryValue* wifi; + int frequency; + if (connect_properties_.GetDictionaryWithoutPathExpansion( + network_guid, &properties) && + properties->GetDictionary(onc::network_type::kWiFi, &wifi) && + wifi->GetInteger(onc::wifi::kFrequency, &frequency)) { + return GetNormalizedFrequency(frequency); + } + return kFrequencyAny; +} + DWORD WiFiServiceImpl::GetDesiredBssList( DOT11_SSID& ssid, Frequency frequency, @@ -1078,8 +1203,8 @@ DWORD WiFiServiceImpl::GetDesiredBssList( error = WlanGetNetworkBssList_function_(client_, &interface_guid_, - NULL, - dot11_BSS_type_any, + &ssid, + dot11_BSS_type_infrastructure, FALSE, NULL, &bss_list); @@ -1097,11 +1222,8 @@ DWORD WiFiServiceImpl::GetDesiredBssList( bss_entry.dot11Ssid.uSSIDLength)) continue; - if (bss_entry.ulChCenterFrequency < 3000000) - bss_frequency = kFrequency2400; - else - bss_frequency = kFrequency5000; - + bss_frequency = GetNormalizedFrequency( + bss_entry.ulChCenterFrequency / 1000); if (bss_frequency == frequency && bss_entry.uLinkQuality > best_quality) { best_quality = bss_entry.uLinkQuality; @@ -1130,13 +1252,21 @@ DWORD WiFiServiceImpl::GetDesiredBssList( } } - // clean up + // Clean up. if (bss_list != NULL) { WlanFreeMemory_function_(bss_list); } return error; } +WiFiService::Frequency WiFiServiceImpl::GetNormalizedFrequency( + int frequency_in_mhz) const { + if (frequency_in_mhz == 0) + return kFrequencyAny; + if (frequency_in_mhz < 3000) + return kFrequency2400; + return kFrequency5000; +} DWORD WiFiServiceImpl::Connect(const std::string& network_guid, Frequency frequency) { @@ -1237,7 +1367,7 @@ DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid, if (error == ERROR_SUCCESS && str_profile_xml != NULL) { *profile_xml = base::UTF16ToUTF8(str_profile_xml); } - // clean up + // Clean up. if (str_profile_xml != NULL) { WlanFreeMemory_function_(str_profile_xml); } |