Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1781)

Unified Diff: chrome/browser/media/router/discovery/discovery_network_list_win.cc

Issue 2868213004: Add Windows and Mac network list implementation (Closed)
Patch Set: Rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/media/router/discovery/discovery_network_list_wifi_mac.mm ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/media/router/discovery/discovery_network_list_win.cc
diff --git a/chrome/browser/media/router/discovery/discovery_network_list_win.cc b/chrome/browser/media/router/discovery/discovery_network_list_win.cc
index a18dd909e08d0d4920ef55d19483baf6c4342ec6..fed47395a36d9726ab9266d7977316cf0935a73e 100644
--- a/chrome/browser/media/router/discovery/discovery_network_list_win.cc
+++ b/chrome/browser/media/router/discovery/discovery_network_list_win.cc
@@ -4,7 +4,214 @@
#include "chrome/browser/media/router/discovery/discovery_network_list.h"
-// TODO(btolsch): Implement this for Windows.
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+#include <iphlpapi.h> // NOLINT
+
+#include <windot11.h> // NOLINT
+#include <wlanapi.h> // NOLINT
+
+#include <algorithm>
+#include <utility>
+#include <vector>
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_number_conversions.h"
+
+namespace {
+
+void IfTable2Deleter(PMIB_IF_TABLE2 interface_table) {
+ if (interface_table) {
+ FreeMibTable(interface_table);
+ }
+}
+
+void WlanApiDeleter(void* p) {
+ if (p) {
+ WlanFreeMemory(p);
+ }
+}
+
+struct MAC {
+ MAC() : data{} {}
+ MAC(const uint8_t* src, ULONG length) : data{} { assign(src, length); }
+ void assign(const uint8_t* src, ULONG length) {
+ DCHECK_LE(length, 6UL);
+ memcpy(data, src, length);
+ }
+ bool operator==(const MAC& o) const { return memcmp(o.data, data, 6) == 0; }
+ uint8_t data[6];
+};
+
+std::vector<std::pair<GUID, MAC>> GetInterfaceGuidMap() {
+ PMIB_IF_TABLE2 interface_table_raw = nullptr;
+ auto result = GetIfTable2(&interface_table_raw);
+ if (result != ERROR_SUCCESS) {
+ DVLOG(2) << "GetIfTable2() failed";
+ return {};
+ }
+ auto interface_table =
+ std::unique_ptr<MIB_IF_TABLE2, decltype(&IfTable2Deleter)>(
+ interface_table_raw, IfTable2Deleter);
+
+ std::vector<std::pair<GUID, MAC>> guid_map;
+ guid_map.reserve(interface_table->NumEntries);
+ for (ULONG i = 0; i < interface_table->NumEntries; ++i) {
+ const auto* interface_row = &interface_table->Table[i];
+ guid_map.push_back(
+ std::make_pair(interface_row->InterfaceGuid,
+ MAC{interface_row->PhysicalAddress,
+ interface_row->PhysicalAddressLength}));
+ }
+
+ return guid_map;
+}
+
+std::vector<std::pair<MAC, std::string>> GetConnectionInfo() {
+ HANDLE client_handle = nullptr;
+ constexpr DWORD client_version = 2;
+ DWORD current_version = 0;
+
+ auto result =
+ WlanOpenHandle(client_version, nullptr, &current_version, &client_handle);
+ if (result != ERROR_SUCCESS) {
+ DVLOG(2) << "Failed to open Wlan client handle";
+ return {};
+ }
+
+ PWLAN_INTERFACE_INFO_LIST wlan_interface_list_raw = nullptr;
+ result = WlanEnumInterfaces(client_handle, nullptr, &wlan_interface_list_raw);
+ if (result != ERROR_SUCCESS) {
+ DVLOG(2) << "Failed to enumerate wireless interfaces";
+ return {};
+ }
+ auto wlan_interface_list =
+ std::unique_ptr<WLAN_INTERFACE_INFO_LIST, decltype(&WlanApiDeleter)>(
+ wlan_interface_list_raw, WlanApiDeleter);
+
+ auto guid_mac_map = GetInterfaceGuidMap();
+
+ std::vector<std::pair<MAC, std::string>> mac_ssid_map;
+ for (DWORD i = 0; i < wlan_interface_list->dwNumberOfItems; ++i) {
+ const auto* interface_info = &wlan_interface_list->InterfaceInfo[i];
+ MAC interface_mac;
+ bool found_mac = false;
+ for (const auto& guid_entry : guid_mac_map) {
+ if (guid_entry.first == interface_info->InterfaceGuid) {
+ interface_mac = guid_entry.second;
+ found_mac = true;
+ break;
+ }
+ }
+ if (!found_mac) {
+ continue;
+ }
+
+ WLAN_CONNECTION_ATTRIBUTES* connection_info = nullptr;
+ DWORD connection_info_size = 0;
+ result = WlanQueryInterface(
+ client_handle, &interface_info->InterfaceGuid,
+ wlan_intf_opcode_current_connection, nullptr, &connection_info_size,
+ reinterpret_cast<void**>(&connection_info), nullptr);
+ if (result != ERROR_SUCCESS) {
+ // We can't get the SSID for this interface so its network ID will
+ // fall back to its MAC address below.
+ DVLOG(2) << "Failed to get wireless connection info";
+ continue;
+ }
+ auto connection_attributes =
+ std::unique_ptr<WLAN_CONNECTION_ATTRIBUTES, decltype(&WlanApiDeleter)>(
+ connection_info, WlanApiDeleter);
+ const auto* ssid =
+ &connection_attributes->wlanAssociationAttributes.dot11Ssid;
+ mac_ssid_map.push_back(std::make_pair(
+ interface_mac,
+ std::string(reinterpret_cast<const char*>(&ssid->ucSSID[0]),
+ ssid->uSSIDLength)));
+ }
+ return mac_ssid_map;
+}
+
+} // namespace
+
std::vector<DiscoveryNetworkInfo> GetDiscoveryNetworkInfoList() {
- return std::vector<DiscoveryNetworkInfo>();
+ // Max number of times to retry GetAdaptersAddresses due to
+ // ERROR_BUFFER_OVERFLOW. If GetAdaptersAddresses returns this indefinitely
+ // due to an unforseen reason, we don't want to be stuck in an endless loop.
+ static constexpr int kMaxGetAdaptersAddressTries = 10;
+ // Use an initial buffer size of 15KB, as recommended by MSDN. See:
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915(v=vs.85).aspx
+ static constexpr int kInitialBufferSize = 15000;
+ constexpr ULONG address_flags = // TODO: include all interfaces flag?
+ GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
+ GAA_FLAG_SKIP_DNS_SERVER;
+ std::vector<DiscoveryNetworkInfo> network_ids;
+
+ ULONG addresses_buffer_size = kInitialBufferSize;
+ char initial_buf[kInitialBufferSize];
+ std::unique_ptr<char[]> addresses_buffer;
+
+ PIP_ADAPTER_ADDRESSES adapter_addresses =
+ reinterpret_cast<PIP_ADAPTER_ADDRESSES>(initial_buf);
+ auto result = GetAdaptersAddresses(AF_UNSPEC, address_flags, nullptr,
+ adapter_addresses, &addresses_buffer_size);
+
+ for (int i = 1;
+ result == ERROR_BUFFER_OVERFLOW && i < kMaxGetAdaptersAddressTries;
+ ++i) {
+ addresses_buffer.reset(new char[addresses_buffer_size]);
+ adapter_addresses =
+ reinterpret_cast<PIP_ADAPTER_ADDRESSES>(addresses_buffer.get());
+ result = GetAdaptersAddresses(AF_UNSPEC, address_flags, nullptr,
+ adapter_addresses, &addresses_buffer_size);
+ }
+
+ if (result != NO_ERROR) {
+ return std::vector<DiscoveryNetworkInfo>();
+ }
+
+ auto mac_ssid_map = GetConnectionInfo();
+ for (const IP_ADAPTER_ADDRESSES* current_adapter = adapter_addresses;
+ current_adapter != nullptr; current_adapter = current_adapter->Next) {
+ if (current_adapter->OperStatus != IfOperStatusUp ||
+ (current_adapter->IfType != IF_TYPE_ETHERNET_CSMACD &&
+ current_adapter->IfType != IF_TYPE_IEEE80211)) {
+ continue;
+ }
+ std::string name(current_adapter->AdapterName);
+ // We have to use a slightly roundabout way to get the SSID for each
+ // adapter:
+ // - Enumerate wifi devices to get list of interface GUIDs.
+ // - Enumerate interfaces to get interface GUID -> physical address map.
+ // - Map interface GUIDs to SSID.
+ // - Use GUID -> MAC map to do MAC -> interface GUID -> SSID.
+ // Although it's theoretically possible to have multiple interfaces per
+ // adapter, most wireless cards don't actually allow multiple
+ // managed-mode interfaces. However, in the event that there really
+ // are multiple interfaces per adapter, we will simply choose the first
+ // one in this list.
+ if (current_adapter->IfType == IF_TYPE_IEEE80211) {
+ MAC adapter_mac(current_adapter->PhysicalAddress,
+ current_adapter->PhysicalAddressLength);
+ bool found_ssid = false;
+ for (const auto& ssid_entry : mac_ssid_map) {
+ if (ssid_entry.first == adapter_mac) {
+ network_ids.push_back({name, ssid_entry.second});
+ found_ssid = true;
+ break;
+ }
+ }
+ if (found_ssid) {
+ continue;
+ }
+ }
+ network_ids.push_back(
+ {name, base::HexEncode(current_adapter->PhysicalAddress,
+ current_adapter->PhysicalAddressLength)});
+ }
+
+ StableSortDiscoveryNetworkInfo(network_ids.begin(), network_ids.end());
+
+ return network_ids;
}
« no previous file with comments | « chrome/browser/media/router/discovery/discovery_network_list_wifi_mac.mm ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698