mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Wi-Fi Direct Service Implementation(9.3)
PiperOrigin-RevId: 859401498
This commit is contained in:
@@ -19,9 +19,12 @@
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <setupapi.h>
|
||||
#include <devguid.h>
|
||||
// clang-format on
|
||||
|
||||
// Standard C/C++ headers
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
@@ -351,4 +354,98 @@ std::optional<std::wstring> GetDnsHostName() {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool IsIntelWifiAdapter() {
|
||||
bool found_intel = false;
|
||||
LOG(INFO) << "Starting scan for Intel Wi-Fi adapters...";
|
||||
|
||||
// 1. Get a handle to all network adapters present in the system
|
||||
HDEVINFO h_dev_info =
|
||||
SetupDiGetClassDevsW(&GUID_DEVCLASS_NET, nullptr, nullptr, DIGCF_PRESENT);
|
||||
// SetupDiDestroyDeviceInfoList needs to be called in the end of this function
|
||||
if (h_dev_info == INVALID_HANDLE_VALUE) {
|
||||
LOG(ERROR) << "Failed to get Class Devs handle. Error: " << GetLastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
SP_DEVINFO_DATA dev_info_data;
|
||||
dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
|
||||
// 2. Enumerate through the devices
|
||||
for (DWORD i = 0; SetupDiEnumDeviceInfo(h_dev_info, i, &dev_info_data); i++) {
|
||||
// 3. Get the Hardware ID property (contains VEN_XXXX and DEV_XXXX)
|
||||
DWORD hardware_id_size = 0;
|
||||
if (!SetupDiGetDeviceRegistryPropertyW(h_dev_info, &dev_info_data,
|
||||
SPDRP_HARDWAREID, nullptr, nullptr,
|
||||
0, &hardware_id_size) &&
|
||||
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
LOG(ERROR) << "Failed to get Hardware ID size. Error: " << GetLastError();
|
||||
continue;
|
||||
}
|
||||
std::wstring hardware_id;
|
||||
hardware_id.resize((hardware_id_size + sizeof(wchar_t) - 1) /
|
||||
sizeof(wchar_t));
|
||||
if (SetupDiGetDeviceRegistryPropertyW(
|
||||
h_dev_info, &dev_info_data, SPDRP_HARDWAREID, nullptr,
|
||||
reinterpret_cast<BYTE*>(hardware_id.data()),
|
||||
hardware_id.size() * sizeof(wchar_t), nullptr)) {
|
||||
// REG_MULTI_SZ contains multiple null-terminated strings.
|
||||
// We search the whole buffer for the Intel Vendor ID (8086).
|
||||
// 4. Check for Intel Vendor ID: 8086
|
||||
// On you Windows computer, go to "Device Manager" --> "Network adapters"
|
||||
// --> Right click Wifi device
|
||||
// --> click "properties" --> click "Details" --> In "Property" dropdown
|
||||
// list, choose "Hardware ID", then you will see:
|
||||
// Hardware IDs look like: PCI\VEN_8086&DEV_2723...,
|
||||
// https://learn.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-pci-devices
|
||||
// https://learn.microsoft.com/en-us/windows-hardware/drivers/install/inf-models-section
|
||||
if (hardware_id.find(L"VEN_8086") != // NOLINT - ClangTidy asks to replace
|
||||
// find() with absl::StrContains(), but
|
||||
// this is not applicable to wide string
|
||||
// and will cause compile error.
|
||||
std::wstring::npos) {
|
||||
// 5. Ensure it's a Wi-Fi/Wireless device
|
||||
// We check the description to make sure we aren't flagging an Intel
|
||||
// Ethernet chip
|
||||
std::wstring to_log_hw_id = hardware_id;
|
||||
// Replace all null characters with spaces to avoid truncation.
|
||||
std::replace(to_log_hw_id.begin(), to_log_hw_id.end(), L'\0', L' ');
|
||||
LOG(INFO) << " - Hardware ID: "
|
||||
<< string_utils::WideStringToString(to_log_hw_id);
|
||||
|
||||
DWORD desc_buf_size = 0;
|
||||
if (!SetupDiGetDeviceRegistryPropertyW(h_dev_info, &dev_info_data,
|
||||
SPDRP_DEVICEDESC, nullptr,
|
||||
nullptr, 0, &desc_buf_size) &&
|
||||
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::wstring name;
|
||||
name.resize((desc_buf_size + sizeof(wchar_t) - 1) / sizeof(wchar_t));
|
||||
if (SetupDiGetDeviceRegistryPropertyW(
|
||||
h_dev_info, &dev_info_data, SPDRP_DEVICEDESC, nullptr,
|
||||
reinterpret_cast<BYTE*>(name.data()),
|
||||
name.size() * sizeof(wchar_t), nullptr)) {
|
||||
if (name.find(L"Wi-Fi") != // NOLINT - ClangTidy asks to replace
|
||||
// find() with absl::StrContains(), but
|
||||
// this is not applicable to wide string
|
||||
// and will cause compile error.
|
||||
std::wstring::npos ||
|
||||
name.find(L"Wireless") != // NOLINT
|
||||
std::wstring::npos ||
|
||||
name.find(L"Killer") != // NOLINT
|
||||
std::wstring::npos) {
|
||||
LOG(INFO) << "Found Intel Wi-Fi: " << name;
|
||||
found_intel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(h_dev_info);
|
||||
return found_intel;
|
||||
}
|
||||
|
||||
} // namespace nearby::windows
|
||||
|
||||
@@ -54,6 +54,9 @@ bool is_nearby_uuid_equal_to_winrt_guid(const Uuid& uuid,
|
||||
// Returns the DNS host name of the computer or std::nullopt if it fails.
|
||||
std::optional<std::wstring> GetDnsHostName();
|
||||
|
||||
// Returns true if the system has an Intel Wi-Fi adapter.
|
||||
bool IsIntelWifiAdapter();
|
||||
|
||||
namespace Constants {
|
||||
// The Id of the Service Name SDP attribute
|
||||
const uint16_t SdpServiceNameAttributeId = 0x100;
|
||||
|
||||
@@ -174,5 +174,10 @@ TEST(UtilsTests, GetDnsHostName) {
|
||||
<< nearby::windows::string_utils::WideStringToString(*host_name);
|
||||
}
|
||||
|
||||
TEST(UtilsTests, IsIntelWifiAdapter) {
|
||||
bool is_intel_wifi_adapter = IsIntelWifiAdapter();
|
||||
LOG(ERROR) << "is_intel_wifi_adapter: " << is_intel_wifi_adapter;
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "internal/platform/flags/nearby_platform_feature_flags.h"
|
||||
#include "internal/platform/implementation/wifi_direct.h"
|
||||
#include "internal/platform/implementation/windows/socket_address.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
#include "internal/platform/implementation/windows/wifi_direct.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/prng.h"
|
||||
@@ -73,6 +74,12 @@ WifiDirectMedium::~WifiDirectMedium() {
|
||||
}
|
||||
|
||||
bool WifiDirectMedium::IsWifiDirectServiceSupported() {
|
||||
if (!IsIntelWifiAdapter()) {
|
||||
LOG(INFO) << "Intel Wifi adapter is not found, WifiDirectService is not "
|
||||
"supported.";
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE wifi_direct_handle = nullptr;
|
||||
DWORD negotiated_version = 0;
|
||||
DWORD result = 0;
|
||||
@@ -85,63 +92,7 @@ bool WifiDirectMedium::IsWifiDirectServiceSupported() {
|
||||
}
|
||||
LOG(INFO) << "WiFi can support WifiDirect";
|
||||
WFDCloseHandle(wifi_direct_handle);
|
||||
|
||||
// Check if device support WinRT WiFiDirectService
|
||||
bool support_wifi_direct_service = false;
|
||||
std::string service_name = "NC-validation";
|
||||
|
||||
// Create Advertiser object
|
||||
WiFiDirectServiceAdvertiser advertiser =
|
||||
WiFiDirectServiceAdvertiser(winrt::to_hstring(service_name));
|
||||
if (advertiser == nullptr) {
|
||||
LOG(ERROR) << "Failed to create WiFiDirectServiceAdvertiser";
|
||||
return false;
|
||||
}
|
||||
|
||||
advertiser.AutoAcceptSession(true);
|
||||
advertiser.PreferGroupOwnerMode(true);
|
||||
advertiser.ServiceStatus(WiFiDirectServiceStatus::Available);
|
||||
// Config Methods
|
||||
WiFiDirectServiceConfigurationMethod config_method =
|
||||
WiFiDirectServiceConfigurationMethod::Default; // NOLINT
|
||||
|
||||
advertiser.PreferredConfigurationMethods().Clear();
|
||||
advertiser.PreferredConfigurationMethods().Append(config_method);
|
||||
|
||||
try {
|
||||
advertiser.Start();
|
||||
LOG(INFO) << "Start WifiDirect GO Status: "
|
||||
<< (int)advertiser.AdvertisementStatus();
|
||||
if (advertiser.AdvertisementStatus() ==
|
||||
WiFiDirectServiceAdvertisementStatus::Created) {
|
||||
LOG(INFO) << "WinRT WiFiDirectService is supported on this device.";
|
||||
support_wifi_direct_service = true;
|
||||
} else if (advertiser.AdvertisementStatus() ==
|
||||
WiFiDirectServiceAdvertisementStatus::Started) {
|
||||
LOG(INFO) << "WinRT WiFiDirectService is supported on this device.";
|
||||
advertiser.Stop();
|
||||
support_wifi_direct_service = true;
|
||||
} else {
|
||||
if (advertiser.AdvertisementStatus() ==
|
||||
WiFiDirectServiceAdvertisementStatus::Aborted) {
|
||||
LOG(INFO) << "Failed to start WifiDirect GO with error code: "
|
||||
<< (int)advertiser.ServiceError();
|
||||
}
|
||||
LOG(INFO) << "WinRT WiFiDirectService is not supported on this device.";
|
||||
support_wifi_direct_service = false;
|
||||
}
|
||||
} catch (std::exception exception) {
|
||||
LOG(ERROR) << __func__ << ": Start WifiDirect GO failed. Exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
LOG(ERROR) << __func__ << ": Start WifiDirect GO failed. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
LOG(ERROR) << __func__ << ": Unknown exeption.";
|
||||
}
|
||||
advertiser = nullptr;
|
||||
|
||||
return support_wifi_direct_service;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WifiDirectMedium::IsInterfaceValid() const {
|
||||
|
||||
Reference in New Issue
Block a user