mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Renew DHCP lease on hotspot connection.
PiperOrigin-RevId: 817375675
This commit is contained in:
committed by
Copybara-Service
parent
346769d54f
commit
0d207bc95b
@@ -289,6 +289,7 @@ cc_library(
|
||||
deps = [
|
||||
":comm",
|
||||
":crypto", # build_cleaner: keep
|
||||
":network_info",
|
||||
":string_utils",
|
||||
":types",
|
||||
"//connections/implementation/flags:connections_flags",
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <combaseapi.h>
|
||||
// clang-format on
|
||||
|
||||
#include <algorithm>
|
||||
@@ -28,6 +27,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/windows/string_utils.h"
|
||||
#include "internal/platform/logging.h"
|
||||
@@ -53,22 +53,10 @@ void AddIpUnicastAddresses(IP_ADAPTER_UNICAST_ADDRESS* unicast_addresses,
|
||||
unicast_addresses = unicast_addresses->Next;
|
||||
}
|
||||
LOG(INFO) << "Added to interface: " << net_interface.index << ", "
|
||||
<< net_interface.ipv4_addresses.size()
|
||||
<< " v4 addresses, "
|
||||
<< net_interface.ipv4_addresses.size() << " v4 addresses, "
|
||||
<< net_interface.ipv6_addresses.size() << " v6 addresses.";
|
||||
}
|
||||
|
||||
std::string GuidToString(GUID guid) {
|
||||
std::wstring guid_str;
|
||||
guid_str.resize(39);
|
||||
int guid_size = StringFromGUID2(guid, guid_str.data(), guid_str.size());
|
||||
if (guid_size != 0) {
|
||||
guid_str.resize(guid_size - 1);
|
||||
return string_utils::WideStringToString(guid_str);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool NetworkInfo::Refresh() {
|
||||
@@ -112,9 +100,9 @@ bool NetworkInfo::Refresh() {
|
||||
continue;
|
||||
}
|
||||
auto it = result.insert(result.end(), InterfaceInfo{
|
||||
.index = next_address->IfIndex,
|
||||
.guid = next_address->NetworkGuid,
|
||||
});
|
||||
.index = next_address->IfIndex,
|
||||
.luid = next_address->Luid,
|
||||
});
|
||||
if (next_address->IfType == IF_TYPE_ETHERNET_CSMACD) {
|
||||
it->type = InterfaceType::kEthernet;
|
||||
VLOG(1) << "Found ethernet interface: " << next_address->AdapterName
|
||||
@@ -144,16 +132,16 @@ std::vector<NetworkInfo::InterfaceInfo> NetworkInfo::GetInterfaces() const {
|
||||
return interfaces_;
|
||||
}
|
||||
|
||||
bool NetworkInfo::RenewIpv4Address(GUID interface_guid) const {
|
||||
bool NetworkInfo::RenewIpv4Address(NET_LUID luid) const {
|
||||
uint64_t index = 0;
|
||||
{
|
||||
absl::MutexLock lock(mutex_);
|
||||
auto it = std::find_if(interfaces_.begin(), interfaces_.end(),
|
||||
[&interface_guid](const InterfaceInfo& intf) {
|
||||
return intf.guid == interface_guid;
|
||||
[luid](const InterfaceInfo& intf) {
|
||||
return intf.luid.Value == luid.Value;
|
||||
});
|
||||
if (it == interfaces_.end()) {
|
||||
LOG(ERROR) << "Interface not found: " << GuidToString(interface_guid);
|
||||
LOG(ERROR) << "Interface not found: " << absl::Hex(luid.Value);
|
||||
return false;
|
||||
}
|
||||
index = it->index;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
// clang-format off
|
||||
#include <winsock2.h>
|
||||
#include <ifdef.h>
|
||||
// clang-format on
|
||||
|
||||
#include <cstdint>
|
||||
@@ -35,14 +36,14 @@ enum InterfaceType {
|
||||
};
|
||||
|
||||
// Class to track network interfaces details. These include the interface type,
|
||||
// interface index, GUID and IP addresses.
|
||||
// interface index, NET_LUID and IP addresses.
|
||||
// This class is thread-safe.
|
||||
class NetworkInfo {
|
||||
public:
|
||||
struct InterfaceInfo {
|
||||
uint64_t index;
|
||||
InterfaceType type;
|
||||
GUID guid;
|
||||
NET_LUID luid;
|
||||
std::vector<sockaddr_storage> ipv4_addresses;
|
||||
std::vector<sockaddr_storage> ipv6_addresses;
|
||||
};
|
||||
@@ -54,7 +55,7 @@ class NetworkInfo {
|
||||
std::vector<InterfaceInfo> GetInterfaces() const;
|
||||
// Renews the IPv4 address for the given interface.
|
||||
// Returns true on success.
|
||||
bool RenewIpv4Address(GUID interface_guid) const;
|
||||
bool RenewIpv4Address(NET_LUID luid) const;
|
||||
|
||||
private:
|
||||
mutable absl::Mutex mutex_;
|
||||
|
||||
@@ -33,7 +33,7 @@ TEST(NetworkInfoTest, RenewIpv4Address) {
|
||||
if (net_interface.ipv4_addresses.empty()) {
|
||||
LOG(INFO) << "Ipv6 only interface";
|
||||
}
|
||||
EXPECT_TRUE(network_info.RenewIpv4Address(net_interface.guid));
|
||||
EXPECT_TRUE(network_info.RenewIpv4Address(net_interface.luid));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -434,7 +434,7 @@ bool WifiHotspotMedium::ConnectWifiHotspot(
|
||||
LOG(INFO) << "Connected to Hotspot successfully.";
|
||||
|
||||
// Make sure IP address is ready.
|
||||
std::string ip_address;
|
||||
bool has_address = false;
|
||||
int64_t ip_address_max_retries = NearbyFlags::GetInstance().GetInt64Flag(
|
||||
platform::config_package_nearby::nearby_platform_feature::
|
||||
kWifiHotspotCheckIpMaxRetries);
|
||||
@@ -447,32 +447,22 @@ bool WifiHotspotMedium::ConnectWifiHotspot(
|
||||
<< "ms";
|
||||
for (int i = 0; i < ip_address_max_retries; i++) {
|
||||
LOG(INFO) << "Check IP address at attempt " << i;
|
||||
std::vector<std::string> ip_addresses = GetWifiIpv4Addresses();
|
||||
|
||||
if (ip_addresses.empty()) {
|
||||
if (!wifi_hotspot_native_.HasAssignedAddress()) {
|
||||
// TODO: ftsui - Add flag to control this.
|
||||
wifi_hotspot_native_.RenewIpv4Address();
|
||||
Sleep(ip_address_retry_interval_millis);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Need to filter out the APIPA address("169.254.x.x").
|
||||
if (ip_addresses[0].starts_with("169.254.")) {
|
||||
LOG(WARNING) << "Got APIPA address " << ip_addresses[0];
|
||||
Sleep(ip_address_retry_interval_millis);
|
||||
continue;
|
||||
}
|
||||
|
||||
ip_address = ip_addresses[0];
|
||||
has_address = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ip_address.empty()) {
|
||||
if (!has_address) {
|
||||
LOG(INFO) << "Failed to get IP address from hotspot.";
|
||||
wifi_hotspot_native_.RestoreWifiProfile();
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Got IP address " << ip_address << " from hotspot.";
|
||||
|
||||
medium_status_ |= kMediumStatusConnected;
|
||||
LOG(INFO) << "Connected to hotspot: " << hotspot_credentials->GetSSID();
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <wlanapi.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <cguid.h>
|
||||
// clang-format on
|
||||
|
||||
@@ -70,6 +71,16 @@ constexpr char kProfileTemplate[] =
|
||||
</security>
|
||||
</MSM>
|
||||
</WLANProfile>)";
|
||||
|
||||
std::string ReasonCodeToString(DWORD reason_code) {
|
||||
std::wstring reason_str;
|
||||
reason_str.resize(100);
|
||||
WlanReasonCodeToString(reason_code, reason_str.size(), reason_str.data(),
|
||||
/*pReserved=*/nullptr);
|
||||
reason_str.resize(std::wcslen(reason_str.data()));
|
||||
return string_utils::WideStringToString(reason_str);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WifiHotspotNative::WifiHotspotNative() {
|
||||
@@ -104,7 +115,7 @@ bool WifiHotspotNative::ConnectToWifiNetwork(
|
||||
HotspotCredentials* hotspot_credentials) {
|
||||
GUID interface_guid = GetInterfaceGuid();
|
||||
if (interface_guid == GUID_NULL) {
|
||||
LOG(ERROR) << "No available WLAN Interface to use.";
|
||||
LOG(ERROR) << __func__ << ": No available WLAN Interface to use.";
|
||||
return false;
|
||||
}
|
||||
{
|
||||
@@ -128,7 +139,7 @@ bool WifiHotspotNative::ConnectToWifiNetwork(
|
||||
bool WifiHotspotNative::DisconnectWifiNetwork() {
|
||||
GUID interface_guid = GetInterfaceGuid();
|
||||
if (interface_guid == GUID_NULL) {
|
||||
LOG(ERROR) << "No available WLAN Interface to use.";
|
||||
LOG(ERROR) << __func__ << ": No available WLAN Interface to use.";
|
||||
return false;
|
||||
}
|
||||
absl::MutexLock lock(mutex_);
|
||||
@@ -146,7 +157,7 @@ bool WifiHotspotNative::DisconnectWifiNetwork() {
|
||||
bool WifiHotspotNative::Scan(absl::string_view ssid) {
|
||||
GUID interface_guid = GetInterfaceGuid();
|
||||
if (interface_guid == GUID_NULL) {
|
||||
LOG(ERROR) << "No available WLAN Interface to use.";
|
||||
LOG(ERROR) << __func__ << ": No available WLAN Interface to use.";
|
||||
return false;
|
||||
}
|
||||
WlanNotificationContext context = {
|
||||
@@ -204,7 +215,7 @@ void WifiHotspotNative::TriggerNetworkRefreshed() {
|
||||
|
||||
GUID interface_guid = GetInterfaceGuid();
|
||||
if (interface_guid == GUID_NULL) {
|
||||
LOG(ERROR) << "No available WLAN Interface to use.";
|
||||
LOG(ERROR) << __func__ << ": No available WLAN Interface to use.";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -368,18 +379,18 @@ bool WifiHotspotNative::ConnectToWifiNetworkInternal(
|
||||
ExceptionOr<bool> connect_result = connect_latch_->Await(kConnectTimeout);
|
||||
UnregisterWlanNotificationCallback();
|
||||
|
||||
backup_profile_name_ = std::move(context.original_profile_name);
|
||||
if (!connect_result.ok() || !connect_result.result()) {
|
||||
LOG(ERROR) << "Connect to Wifi hotspot timed out.";
|
||||
return false;
|
||||
}
|
||||
if (context.connection_code != WLAN_REASON_CODE_SUCCESS) {
|
||||
LOG(ERROR) << "Failed to connect to Wifi hotspot, code: "
|
||||
<< context.connection_code;
|
||||
<< ReasonCodeToString(context.connection_code);
|
||||
return false;
|
||||
}
|
||||
|
||||
connect_latch_ = nullptr;
|
||||
backup_profile_name_ = std::move(context.original_profile_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -472,7 +483,7 @@ bool WifiHotspotNative::RemoveWlanProfile(GUID interface_guid,
|
||||
bool WifiHotspotNative::RestoreWifiProfile() {
|
||||
GUID interface_guid = GetInterfaceGuid();
|
||||
if (interface_guid == GUID_NULL) {
|
||||
LOG(ERROR) << "No available WLAN Interface to use.";
|
||||
LOG(ERROR) << __func__ << ": No available WLAN Interface to use.";
|
||||
return false;
|
||||
}
|
||||
absl::MutexLock lock(mutex_);
|
||||
@@ -492,4 +503,44 @@ bool WifiHotspotNative::RestoreWifiProfile() {
|
||||
return ConnectToWifiNetworkInternal(interface_guid, backup_profile_name_);
|
||||
}
|
||||
|
||||
bool WifiHotspotNative::HasAssignedAddress() {
|
||||
if (!network_info_.Refresh()) {
|
||||
return false;
|
||||
}
|
||||
GUID interface_guid = GetInterfaceGuid();
|
||||
if (interface_guid == GUID_NULL) {
|
||||
LOG(ERROR) << __func__ << ": No available WLAN Interface to use.";
|
||||
return false;
|
||||
}
|
||||
NET_LUID luid;
|
||||
ConvertInterfaceGuidToLuid(&interface_guid, &luid);
|
||||
for (const auto& interface : network_info_.GetInterfaces()) {
|
||||
if (interface.luid.Value != luid.Value) {
|
||||
continue;
|
||||
}
|
||||
for (const auto& address : interface.ipv4_addresses) {
|
||||
DCHECK(address.ss_family == AF_INET);
|
||||
const sockaddr_in* ipv4_address =
|
||||
reinterpret_cast<const sockaddr_in*>(&address);
|
||||
// We ignore APIPA addresses since we won't be able to connect using that.
|
||||
if (ipv4_address->sin_addr.S_un.S_un_b.s_b1 != 169 ||
|
||||
ipv4_address->sin_addr.S_un.S_un_b.s_b2 != 254) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WifiHotspotNative::RenewIpv4Address() const {
|
||||
GUID interface_guid = GetInterfaceGuid();
|
||||
if (interface_guid == GUID_NULL) {
|
||||
LOG(ERROR) << __func__ << ": No available WLAN Interface to use.";
|
||||
return false;
|
||||
}
|
||||
NET_LUID luid;
|
||||
ConvertInterfaceGuidToLuid(&interface_guid, &luid);
|
||||
return network_info_.RenewIpv4Address(luid);
|
||||
}
|
||||
|
||||
} // namespace nearby::windows
|
||||
|
||||
@@ -25,16 +25,17 @@
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/implementation/windows/network_info.h"
|
||||
#include "internal/platform/wifi_credential.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
namespace nearby::windows {
|
||||
|
||||
class WifiHotspotNative {
|
||||
public:
|
||||
@@ -48,6 +49,10 @@ class WifiHotspotNative {
|
||||
|
||||
bool Scan(absl::string_view ssid) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Returns true if the interface has a non local scoped IPv4 address.
|
||||
bool HasAssignedAddress();
|
||||
bool RenewIpv4Address() const;
|
||||
|
||||
private:
|
||||
// Context for WLAN notification callback.
|
||||
struct WlanNotificationContext {
|
||||
@@ -92,9 +97,9 @@ class WifiHotspotNative {
|
||||
std::unique_ptr<CountDownLatch> connect_latch_;
|
||||
std::unique_ptr<CountDownLatch> scan_latch_;
|
||||
std::wstring backup_profile_name_;
|
||||
NetworkInfo network_info_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace nearby::windows
|
||||
|
||||
#endif // THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_WIFI_HOTSPOT_NATIVE_H_
|
||||
|
||||
Reference in New Issue
Block a user