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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/media/router/discovery/discovery_network_list.h" 5 #include "chrome/browser/media/router/discovery/discovery_network_list.h"
6 6
7 // TODO(btolsch): Implement this for Windows. 7 #include <winsock2.h>
8 #include <ws2tcpip.h>
9
10 #include <iphlpapi.h> // NOLINT
11
12 #include <windot11.h> // NOLINT
13 #include <wlanapi.h> // NOLINT
14
15 #include <algorithm>
16 #include <utility>
17 #include <vector>
18
19 #include "base/memory/ptr_util.h"
20 #include "base/strings/string_number_conversions.h"
21
22 namespace {
23
24 void IfTable2Deleter(PMIB_IF_TABLE2 interface_table) {
25 if (interface_table) {
26 FreeMibTable(interface_table);
27 }
28 }
29
30 void WlanApiDeleter(void* p) {
31 if (p) {
32 WlanFreeMemory(p);
33 }
34 }
35
36 struct MAC {
37 MAC() : data{} {}
38 MAC(const uint8_t* src, ULONG length) : data{} { assign(src, length); }
39 void assign(const uint8_t* src, ULONG length) {
40 DCHECK_LE(length, 6UL);
41 memcpy(data, src, length);
42 }
43 bool operator==(const MAC& o) const { return memcmp(o.data, data, 6) == 0; }
44 uint8_t data[6];
45 };
46
47 std::vector<std::pair<GUID, MAC>> GetInterfaceGuidMap() {
48 PMIB_IF_TABLE2 interface_table_raw = nullptr;
49 auto result = GetIfTable2(&interface_table_raw);
50 if (result != ERROR_SUCCESS) {
51 DVLOG(2) << "GetIfTable2() failed";
52 return {};
53 }
54 auto interface_table =
55 std::unique_ptr<MIB_IF_TABLE2, decltype(&IfTable2Deleter)>(
56 interface_table_raw, IfTable2Deleter);
57
58 std::vector<std::pair<GUID, MAC>> guid_map;
59 guid_map.reserve(interface_table->NumEntries);
60 for (ULONG i = 0; i < interface_table->NumEntries; ++i) {
61 const auto* interface_row = &interface_table->Table[i];
62 guid_map.push_back(
63 std::make_pair(interface_row->InterfaceGuid,
64 MAC{interface_row->PhysicalAddress,
65 interface_row->PhysicalAddressLength}));
66 }
67
68 return guid_map;
69 }
70
71 std::vector<std::pair<MAC, std::string>> GetConnectionInfo() {
72 HANDLE client_handle = nullptr;
73 constexpr DWORD client_version = 2;
74 DWORD current_version = 0;
75
76 auto result =
77 WlanOpenHandle(client_version, nullptr, &current_version, &client_handle);
78 if (result != ERROR_SUCCESS) {
79 DVLOG(2) << "Failed to open Wlan client handle";
80 return {};
81 }
82
83 PWLAN_INTERFACE_INFO_LIST wlan_interface_list_raw = nullptr;
84 result = WlanEnumInterfaces(client_handle, nullptr, &wlan_interface_list_raw);
85 if (result != ERROR_SUCCESS) {
86 DVLOG(2) << "Failed to enumerate wireless interfaces";
87 return {};
88 }
89 auto wlan_interface_list =
90 std::unique_ptr<WLAN_INTERFACE_INFO_LIST, decltype(&WlanApiDeleter)>(
91 wlan_interface_list_raw, WlanApiDeleter);
92
93 auto guid_mac_map = GetInterfaceGuidMap();
94
95 std::vector<std::pair<MAC, std::string>> mac_ssid_map;
96 for (DWORD i = 0; i < wlan_interface_list->dwNumberOfItems; ++i) {
97 const auto* interface_info = &wlan_interface_list->InterfaceInfo[i];
98 MAC interface_mac;
99 bool found_mac = false;
100 for (const auto& guid_entry : guid_mac_map) {
101 if (guid_entry.first == interface_info->InterfaceGuid) {
102 interface_mac = guid_entry.second;
103 found_mac = true;
104 break;
105 }
106 }
107 if (!found_mac) {
108 continue;
109 }
110
111 WLAN_CONNECTION_ATTRIBUTES* connection_info = nullptr;
112 DWORD connection_info_size = 0;
113 result = WlanQueryInterface(
114 client_handle, &interface_info->InterfaceGuid,
115 wlan_intf_opcode_current_connection, nullptr, &connection_info_size,
116 reinterpret_cast<void**>(&connection_info), nullptr);
117 if (result != ERROR_SUCCESS) {
118 // We can't get the SSID for this interface so its network ID will
119 // fall back to its MAC address below.
120 DVLOG(2) << "Failed to get wireless connection info";
121 continue;
122 }
123 auto connection_attributes =
124 std::unique_ptr<WLAN_CONNECTION_ATTRIBUTES, decltype(&WlanApiDeleter)>(
125 connection_info, WlanApiDeleter);
126 const auto* ssid =
127 &connection_attributes->wlanAssociationAttributes.dot11Ssid;
128 mac_ssid_map.push_back(std::make_pair(
129 interface_mac,
130 std::string(reinterpret_cast<const char*>(&ssid->ucSSID[0]),
131 ssid->uSSIDLength)));
132 }
133 return mac_ssid_map;
134 }
135
136 } // namespace
137
8 std::vector<DiscoveryNetworkInfo> GetDiscoveryNetworkInfoList() { 138 std::vector<DiscoveryNetworkInfo> GetDiscoveryNetworkInfoList() {
9 return std::vector<DiscoveryNetworkInfo>(); 139 // Max number of times to retry GetAdaptersAddresses due to
10 } 140 // ERROR_BUFFER_OVERFLOW. If GetAdaptersAddresses returns this indefinitely
141 // due to an unforseen reason, we don't want to be stuck in an endless loop.
142 static constexpr int kMaxGetAdaptersAddressTries = 10;
143 // Use an initial buffer size of 15KB, as recommended by MSDN. See:
144 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915(v=vs.85). aspx
145 static constexpr int kInitialBufferSize = 15000;
146 constexpr ULONG address_flags = // TODO: include all interfaces flag?
147 GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
148 GAA_FLAG_SKIP_DNS_SERVER;
149 std::vector<DiscoveryNetworkInfo> network_ids;
150
151 ULONG addresses_buffer_size = kInitialBufferSize;
152 char initial_buf[kInitialBufferSize];
153 std::unique_ptr<char[]> addresses_buffer;
154
155 PIP_ADAPTER_ADDRESSES adapter_addresses =
156 reinterpret_cast<PIP_ADAPTER_ADDRESSES>(initial_buf);
157 auto result = GetAdaptersAddresses(AF_UNSPEC, address_flags, nullptr,
158 adapter_addresses, &addresses_buffer_size);
159
160 for (int i = 1;
161 result == ERROR_BUFFER_OVERFLOW && i < kMaxGetAdaptersAddressTries;
162 ++i) {
163 addresses_buffer.reset(new char[addresses_buffer_size]);
164 adapter_addresses =
165 reinterpret_cast<PIP_ADAPTER_ADDRESSES>(addresses_buffer.get());
166 result = GetAdaptersAddresses(AF_UNSPEC, address_flags, nullptr,
167 adapter_addresses, &addresses_buffer_size);
168 }
169
170 if (result != NO_ERROR) {
171 return std::vector<DiscoveryNetworkInfo>();
172 }
173
174 auto mac_ssid_map = GetConnectionInfo();
175 for (const IP_ADAPTER_ADDRESSES* current_adapter = adapter_addresses;
176 current_adapter != nullptr; current_adapter = current_adapter->Next) {
177 if (current_adapter->OperStatus != IfOperStatusUp ||
178 (current_adapter->IfType != IF_TYPE_ETHERNET_CSMACD &&
179 current_adapter->IfType != IF_TYPE_IEEE80211)) {
180 continue;
181 }
182 std::string name(current_adapter->AdapterName);
183 // We have to use a slightly roundabout way to get the SSID for each
184 // adapter:
185 // - Enumerate wifi devices to get list of interface GUIDs.
186 // - Enumerate interfaces to get interface GUID -> physical address map.
187 // - Map interface GUIDs to SSID.
188 // - Use GUID -> MAC map to do MAC -> interface GUID -> SSID.
189 // Although it's theoretically possible to have multiple interfaces per
190 // adapter, most wireless cards don't actually allow multiple
191 // managed-mode interfaces. However, in the event that there really
192 // are multiple interfaces per adapter, we will simply choose the first
193 // one in this list.
194 if (current_adapter->IfType == IF_TYPE_IEEE80211) {
195 MAC adapter_mac(current_adapter->PhysicalAddress,
196 current_adapter->PhysicalAddressLength);
197 bool found_ssid = false;
198 for (const auto& ssid_entry : mac_ssid_map) {
199 if (ssid_entry.first == adapter_mac) {
200 network_ids.push_back({name, ssid_entry.second});
201 found_ssid = true;
202 break;
203 }
204 }
205 if (found_ssid) {
206 continue;
207 }
208 }
209 network_ids.push_back(
210 {name, base::HexEncode(current_adapter->PhysicalAddress,
211 current_adapter->PhysicalAddressLength)});
212 }
213
214 StableSortDiscoveryNetworkInfo(network_ids.begin(), network_ids.end());
215
216 return network_ids;
217 }
OLDNEW
« 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