From 438b503f0b77572c22f778e9f8278d1af5ef3eb1 Mon Sep 17 00:00:00 2001 From: Francis Tsui Date: Mon, 10 Nov 2025 15:42:58 -0800 Subject: [PATCH] Add flag for sending hotspot address candidates. PiperOrigin-RevId: 830628854 --- .../flags/nearby_platform_feature_flags.h | 4 ++ .../windows/wifi_hotspot_medium.cc | 10 +++- .../windows/wifi_hotspot_native.cc | 7 ++- .../windows/wifi_hotspot_native.h | 6 +- .../windows/wifi_hotspot_server_socket.cc | 58 +++++++++++++++---- 5 files changed, 70 insertions(+), 15 deletions(-) diff --git a/internal/platform/flags/nearby_platform_feature_flags.h b/internal/platform/flags/nearby_platform_feature_flags.h index 688143bb..a91c2f32 100644 --- a/internal/platform/flags/nearby_platform_feature_flags.h +++ b/internal/platform/flags/nearby_platform_feature_flags.h @@ -53,6 +53,10 @@ constexpr auto kWifiHotspotConnectionIntervalMillis = constexpr auto kWifiHotspotConnectionTimeoutMillis = flags::Flag(kConfigPackage, "45415888", 10000); +// Enable/Disable use of address candidates for hotspot upgrade in Windows. +constexpr auto kEnableHotspotAddressCandidates = + flags::Flag(kConfigPackage, "45739567", false); + // Enable/Disable DHCP renewal when connecting to hotspot. constexpr auto kEnableHotspotDhcpRenew = flags::Flag(kConfigPackage, "45731858", false); diff --git a/internal/platform/implementation/windows/wifi_hotspot_medium.cc b/internal/platform/implementation/windows/wifi_hotspot_medium.cc index 73c2a10f..e81d77af 100644 --- a/internal/platform/implementation/windows/wifi_hotspot_medium.cc +++ b/internal/platform/implementation/windows/wifi_hotspot_medium.cc @@ -409,6 +409,14 @@ bool WifiHotspotMedium::ConnectWifiHotspot( // Make sure IP address is ready. bool has_address = false; + bool has_ipv6_candidates = false; + for (const auto& address_candidate : + hotspot_credentials.GetAddressCandidates()) { + if (address_candidate.address.size() == 16) { + has_ipv6_candidates = true; + break; + } + } int64_t ip_address_max_retries = NearbyFlags::GetInstance().GetInt64Flag( platform::config_package_nearby::nearby_platform_feature:: kWifiHotspotCheckIpMaxRetries); @@ -425,7 +433,7 @@ bool WifiHotspotMedium::ConnectWifiHotspot( for (int i = 0; i < ip_address_max_retries; i++) { LOG(INFO) << "Check IP address at attempt " << i; - if (wifi_hotspot_native_.HasAssignedAddress()) { + if (wifi_hotspot_native_.HasAssignedAddress(has_ipv6_candidates)) { has_address = true; break; } diff --git a/internal/platform/implementation/windows/wifi_hotspot_native.cc b/internal/platform/implementation/windows/wifi_hotspot_native.cc index 89ffc081..82e1340e 100644 --- a/internal/platform/implementation/windows/wifi_hotspot_native.cc +++ b/internal/platform/implementation/windows/wifi_hotspot_native.cc @@ -393,7 +393,7 @@ bool WifiHotspotNative::RestoreWifiProfile() { return ConnectToWifiNetworkInternal(interface_guid, backup_profile_name_); } -bool WifiHotspotNative::HasAssignedAddress() { +bool WifiHotspotNative::HasAssignedAddress(bool include_ipv6) { if (!network_info_.Refresh()) { return false; } @@ -408,6 +408,11 @@ bool WifiHotspotNative::HasAssignedAddress() { if (interface.luid.Value != luid.Value) { continue; } + if (include_ipv6) { + if (!interface.ipv6_addresses.empty()) { + return true; + } + } for (const auto& address : interface.ipv4_addresses) { DCHECK(address.ss_family == AF_INET); const sockaddr_in* ipv4_address = diff --git a/internal/platform/implementation/windows/wifi_hotspot_native.h b/internal/platform/implementation/windows/wifi_hotspot_native.h index 6cc64aa4..0c0c8041 100644 --- a/internal/platform/implementation/windows/wifi_hotspot_native.h +++ b/internal/platform/implementation/windows/wifi_hotspot_native.h @@ -47,8 +47,10 @@ class WifiHotspotNative { bool RestoreWifiProfile() ABSL_LOCKS_EXCLUDED(mutex_); - // Returns true if the interface has a non local scoped IPv4 address. - bool HasAssignedAddress(); + // Returns true if the interface has required IP address assigned. + // If `include_ipv6` is false, check for non local scoped IPv4 address only. + // Otherwise, check for any IPv6 address or non local scoped IPv4 address. + bool HasAssignedAddress(bool include_ipv6); bool RenewIpv4Address() const; // Return the interface index of the wifi interface used to connect to the // hotspot. diff --git a/internal/platform/implementation/windows/wifi_hotspot_server_socket.cc b/internal/platform/implementation/windows/wifi_hotspot_server_socket.cc index e03f67f7..3cdd3f23 100644 --- a/internal/platform/implementation/windows/wifi_hotspot_server_socket.cc +++ b/internal/platform/implementation/windows/wifi_hotspot_server_socket.cc @@ -34,6 +34,7 @@ #include "internal/platform/implementation/windows/generated/winrt/Windows.Foundation.Collections.h" #include "internal/platform/implementation/windows/generated/winrt/Windows.Networking.Connectivity.h" #include "internal/platform/implementation/windows/generated/winrt/Windows.Networking.Sockets.h" +#include "internal/platform/implementation/windows/network_info.h" #include "internal/platform/implementation/windows/socket_address.h" #include "internal/platform/implementation/windows/utils.h" #include "internal/platform/implementation/windows/wifi_hotspot_server_socket.h" @@ -87,18 +88,53 @@ void WifiHotspotServerSocket::PopulateHotspotCredentials( "addresses configured on computer."; return; } - std::vector hotspot_ipaddr_bytes; - uint32_t address_int = inet_addr(hotspot_ipaddr.c_str()); - if (address_int != INADDR_NONE) { - hotspot_ipaddr_bytes.resize(4); - std::memcpy(hotspot_ipaddr_bytes.data(), - reinterpret_cast(&address_int), 4); + bool use_address_candidates = NearbyFlags::GetInstance().GetBoolFlag( + platform::config_package_nearby::nearby_platform_feature:: + kEnableHotspotAddressCandidates); + + if (!use_address_candidates) { + std::vector hotspot_ipaddr_bytes; + uint32_t address_int = inet_addr(hotspot_ipaddr.c_str()); + if (address_int != INADDR_NONE) { + hotspot_ipaddr_bytes.resize(4); + std::memcpy(hotspot_ipaddr_bytes.data(), + reinterpret_cast(&address_int), 4); + } + ServiceAddress service_address = { + .address = hotspot_ipaddr_bytes, + .port = static_cast(GetPort()), + }; + hotspot_credentials.SetAddressCandidates({service_address}); + return; } - ServiceAddress service_address = { - .address = hotspot_ipaddr_bytes, - .port = static_cast(GetPort()), - }; - hotspot_credentials.SetAddressCandidates({service_address}); + std::vector service_addresses; + for (const auto& interface : NetworkInfo::GetNetworkInfo().GetInterfaces()) { + if (interface.type == InterfaceType::kWifiHotspot) { + LOG(INFO) << "Found Wifi Hotspot interface, index: " << interface.index; + for (const auto& ipaddress : interface.ipv6_addresses) { + const sockaddr_in6* ipv6_address = + reinterpret_cast(&ipaddress); + service_addresses.push_back(ServiceAddress{ + .address = std::vector(ipv6_address->sin6_addr.u.Byte, + ipv6_address->sin6_addr.u.Byte + 16), + .port = static_cast(GetPort()), + }); + } + for (const auto& ipaddress : interface.ipv4_addresses) { + const sockaddr_in* ipv4_address = + reinterpret_cast(&ipaddress); + service_addresses.push_back(ServiceAddress{ + .address = {ipv4_address->sin_addr.S_un.S_un_b.s_b1, + ipv4_address->sin_addr.S_un.S_un_b.s_b2, + ipv4_address->sin_addr.S_un.S_un_b.s_b3, + ipv4_address->sin_addr.S_un.S_un_b.s_b4}, + .port = static_cast(GetPort()), + }); + } + break; + } + } + hotspot_credentials.SetAddressCandidates(std::move(service_addresses)); } bool WifiHotspotServerSocket::Listen(int port, bool dual_stack) {