From 37b0c313195decd73953cdee69affd3997df5929 Mon Sep 17 00:00:00 2001 From: hai007 Date: Fri, 27 May 2022 15:19:14 -0700 Subject: [PATCH] Add Wifi Hotspot AP and Client validation check PiperOrigin-RevId: 451492039 --- connections/implementation/bwu_manager.cc | 2 +- .../implementation/mediums/wifi_hotspot.cc | 21 ++++++++++++++----- .../implementation/mediums/wifi_hotspot.h | 6 ++++-- .../mediums/wifi_hotspot_test.cc | 14 ++++++++----- .../p2p_point_to_point_pcp_handler.cc | 3 ++- .../implementation/p2p_star_pcp_handler.cc | 3 ++- .../implementation/g3/wifi_hotspot.cc | 6 ++++++ .../platform/implementation/g3/wifi_hotspot.h | 3 +++ .../platform/implementation/wifi_hotspot.h | 3 +++ .../implementation/windows/wifi_hotspot.h | 11 ++++++++++ .../windows/wifi_hotspot_medium.cc | 12 +++++++++++ internal/platform/wifi_hotspot.h | 5 +++++ internal/platform/wifi_hotspot_test.cc | 12 +++++++++-- 13 files changed, 84 insertions(+), 17 deletions(-) diff --git a/connections/implementation/bwu_manager.cc b/connections/implementation/bwu_manager.cc index 58ed0dbb..c1803b75 100644 --- a/connections/implementation/bwu_manager.cc +++ b/connections/implementation/bwu_manager.cc @@ -1180,7 +1180,7 @@ std::vector BwuManager::StripOutUnavailableMediums( bool available = false; switch (m) { case Medium::WIFI_HOTSPOT: - available = mediums_->GetWifiHotspot().IsAvailable(); + available = mediums_->GetWifiHotspot().IsAPAvailable(); break; case Medium::WIFI_LAN: available = mediums_->GetWifiLan().IsAvailable(); diff --git a/connections/implementation/mediums/wifi_hotspot.cc b/connections/implementation/mediums/wifi_hotspot.cc index d9ac9080..e5957a94 100644 --- a/connections/implementation/mediums/wifi_hotspot.cc +++ b/connections/implementation/mediums/wifi_hotspot.cc @@ -39,13 +39,24 @@ WifiHotspot::~WifiHotspot() { accept_loops_runner_.Shutdown(); } -bool WifiHotspot::IsAvailable() const { +bool WifiHotspot::IsAPAvailable() const { MutexLock lock(&mutex_); - return IsAvailableLocked(); + return IsAPAvailableLocked(); } -bool WifiHotspot::IsAvailableLocked() const { return medium_.IsValid(); } +bool WifiHotspot::IsAPAvailableLocked() const { + if (medium_.IsValid()) return medium_.IsInterfaceValid(); + return false; +} + +bool WifiHotspot::IsClientAvailable() const { + MutexLock lock(&mutex_); + + return IsClientAvailableLocked(); +} + +bool WifiHotspot::IsClientAvailableLocked() const { return medium_.IsValid(); } bool WifiHotspot::IsHotspotStarted() { MutexLock lock(&mutex_); @@ -135,7 +146,7 @@ bool WifiHotspot::StartAcceptingConnections( return false; } - if (!IsAvailableLocked()) { + if (!IsAPAvailableLocked()) { NEARBY_LOGS(INFO) << "Can't start accepting WifiHotspot connections [service_id=" << service_id << "]; WifiHotspot not available."; @@ -250,7 +261,7 @@ WifiHotspotSocket WifiHotspot::Connect(const std::string& service_id, return socket; } - if (!IsAvailableLocked()) { + if (!IsClientAvailableLocked()) { NEARBY_LOGS(INFO) << "Can't create client WifiHotspot socket [service_id=" << service_id << "]; WifiHotspot isn't available."; return socket; diff --git a/connections/implementation/mediums/wifi_hotspot.h b/connections/implementation/mediums/wifi_hotspot.h index 10b43d92..57629873 100644 --- a/connections/implementation/mediums/wifi_hotspot.h +++ b/connections/implementation/mediums/wifi_hotspot.h @@ -45,7 +45,8 @@ class WifiHotspot { // Returns true, if WifiHotspot communications are supported by a platform. - bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_); + bool IsAPAvailable() const ABSL_LOCKS_EXCLUDED(mutex_); + bool IsClientAvailable() const ABSL_LOCKS_EXCLUDED(mutex_); bool IsHotspotStarted() ABSL_LOCKS_EXCLUDED(mutex_); bool StartWifiHotspot() ABSL_LOCKS_EXCLUDED(mutex_); @@ -89,7 +90,8 @@ class WifiHotspot { static constexpr int kMaxConcurrentAcceptLoops = 5; // Same as IsAvailable(), but must be called with mutex_ held. - bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + bool IsAPAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + bool IsClientAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); // Same as IsAcceptingConnections(), but must be called with mutex_ held. bool IsAcceptingConnectionsLocked(const std::string& service_id) diff --git a/connections/implementation/mediums/wifi_hotspot_test.cc b/connections/implementation/mediums/wifi_hotspot_test.cc index beb3aaa6..3fdca3d1 100644 --- a/connections/implementation/mediums/wifi_hotspot_test.cc +++ b/connections/implementation/mediums/wifi_hotspot_test.cc @@ -65,17 +65,21 @@ TEST_F(WifiHotspotTest, ConstructorDestructorWorks) { auto wifi_hotspot_a = std::make_unique(); auto wifi_hotspot_b = std::make_unique(); - EXPECT_TRUE(wifi_hotspot_a->IsAvailable()); - EXPECT_TRUE(wifi_hotspot_b->IsAvailable()); + EXPECT_TRUE(wifi_hotspot_a->IsClientAvailable()); + EXPECT_TRUE(wifi_hotspot_b->IsClientAvailable()); } TEST_F(WifiHotspotTest, CanStartStopHotspot) { std::string service_id(kServiceID); auto wifi_hotspot_a = std::make_unique(); - EXPECT_TRUE(wifi_hotspot_a->StartWifiHotspot()); - EXPECT_TRUE(wifi_hotspot_a->StartAcceptingConnections(service_id, {})); - EXPECT_TRUE(wifi_hotspot_a->StopWifiHotspot()); + if (wifi_hotspot_a->IsAPAvailable()) { + EXPECT_TRUE(wifi_hotspot_a->StartWifiHotspot()); + EXPECT_TRUE(wifi_hotspot_a->StartAcceptingConnections(service_id, {})); + EXPECT_TRUE(wifi_hotspot_a->StopWifiHotspot()); + } else { + EXPECT_FALSE(wifi_hotspot_a->StartWifiHotspot()); + } } TEST_F(WifiHotspotTest, CanConnectDisconnectHotspot) { diff --git a/connections/implementation/p2p_point_to_point_pcp_handler.cc b/connections/implementation/p2p_point_to_point_pcp_handler.cc index 630d6e8c..e4035529 100644 --- a/connections/implementation/p2p_point_to_point_pcp_handler.cc +++ b/connections/implementation/p2p_point_to_point_pcp_handler.cc @@ -28,7 +28,8 @@ P2pPointToPointPcpHandler::P2pPointToPointPcpHandler( std::vector P2pPointToPointPcpHandler::GetConnectionMediumsByPriority() { std::vector mediums; - if (mediums_->GetWifiHotspot().IsAvailable()) { + if (mediums_->GetWifi().IsAvailable() && + mediums_->GetWifiHotspot().IsClientAvailable()) { mediums.push_back(proto::connections::WIFI_HOTSPOT); } if (mediums_->GetWifiLan().IsAvailable()) { diff --git a/connections/implementation/p2p_star_pcp_handler.cc b/connections/implementation/p2p_star_pcp_handler.cc index 0577bf9d..2d9d3476 100644 --- a/connections/implementation/p2p_star_pcp_handler.cc +++ b/connections/implementation/p2p_star_pcp_handler.cc @@ -33,7 +33,8 @@ P2pStarPcpHandler::P2pStarPcpHandler( std::vector P2pStarPcpHandler::GetConnectionMediumsByPriority() { std::vector mediums; - if (mediums_->GetWifiHotspot().IsAvailable()) { + if (mediums_->GetWifi().IsAvailable() && + mediums_->GetWifiHotspot().IsClientAvailable()) { mediums.push_back(proto::connections::WIFI_HOTSPOT); } if (mediums_->GetWifiLan().IsAvailable()) { diff --git a/internal/platform/implementation/g3/wifi_hotspot.cc b/internal/platform/implementation/g3/wifi_hotspot.cc index 93dfb417..b74115f4 100644 --- a/internal/platform/implementation/g3/wifi_hotspot.cc +++ b/internal/platform/implementation/g3/wifi_hotspot.cc @@ -187,6 +187,9 @@ bool WifiHotspotMedium::StartWifiHotspot( HotspotCredentials* hotspot_credentials) { absl::MutexLock lock(&mutex_); + if (!IsInterfaceValid()) + return false; + std::string ssid = absl::StrCat("DIRECT-", Prng().NextUint32()); hotspot_credentials->SetSSID(ssid); std::string password = absl::StrFormat("%08x", Prng().NextUint32()); @@ -206,6 +209,9 @@ bool WifiHotspotMedium::StopWifiHotspot() { absl::MutexLock lock(&mutex_); NEARBY_LOGS(INFO) << "G3 StopWifiHotspot"; + if (!IsInterfaceValid()) + return false; + auto& env = MediumEnvironment::Instance(); env.UpdateWifiHotspotMediumForStartOrConnect(*this, /*credentials*/nullptr, /*is_ap=*/true, diff --git a/internal/platform/implementation/g3/wifi_hotspot.h b/internal/platform/implementation/g3/wifi_hotspot.h index 811fb144..7cb0ed4d 100644 --- a/internal/platform/implementation/g3/wifi_hotspot.h +++ b/internal/platform/implementation/g3/wifi_hotspot.h @@ -184,6 +184,9 @@ class WifiHotspotMedium : public api::WifiHotspotMedium { WifiHotspotMedium& operator=(const WifiHotspotMedium&) = delete; WifiHotspotMedium& operator=(WifiHotspotMedium&&) = delete; + // If the WIFI Adaptor supports to start a Hotspot interface. + bool IsInterfaceValid() const override { return true;} + // Discoverer connects to server socket std::unique_ptr ConnectToService( absl::string_view ip_address, int port, diff --git a/internal/platform/implementation/wifi_hotspot.h b/internal/platform/implementation/wifi_hotspot.h index bcc1de6c..79be6fc7 100644 --- a/internal/platform/implementation/wifi_hotspot.h +++ b/internal/platform/implementation/wifi_hotspot.h @@ -74,6 +74,9 @@ class WifiHotspotMedium { public: virtual ~WifiHotspotMedium() = default; + // If the WIFI Adaptor supports to start a Hotspot interface. + virtual bool IsInterfaceValid() const = 0; + // Connects to a WifiHotspot service by ip address and port. // On success, returns a new WifiHotspotSocket. // On error, returns nullptr. diff --git a/internal/platform/implementation/windows/wifi_hotspot.h b/internal/platform/implementation/windows/wifi_hotspot.h index 137be682..62db606d 100644 --- a/internal/platform/implementation/windows/wifi_hotspot.h +++ b/internal/platform/implementation/windows/wifi_hotspot.h @@ -15,6 +15,10 @@ #ifndef PLATFORM_IMPL_WINDOWS_WIFI_HOTSPOT_H_ #define PLATFORM_IMPL_WINDOWS_WIFI_HOTSPOT_H_ +// Standard C/C++ headers +#include +#include + // Nearby connections headers #include "internal/platform/implementation/wifi_hotspot.h" @@ -209,8 +213,12 @@ class WifiHotspotServerSocket : public api::WifiHotspotServerSocket { // Container of operations that can be performed over the WifiHotspot medium. class WifiHotspotMedium : public api::WifiHotspotMedium { public: + WifiHotspotMedium(); ~WifiHotspotMedium() override; + // If the WIFI Adaptor supports to start a Hotspot interface. + bool IsInterfaceValid() const override; + // Discoverer connects to server socket std::unique_ptr ConnectToService( absl::string_view ip_address, int port, @@ -271,6 +279,9 @@ class WifiHotspotMedium : public api::WifiHotspotMedium { // Protects to access some members absl::Mutex mutex_; + // If the WiFi Adaptor supports to start a Hotspot interface. + bool hotspot_interface_valid_; + // Medium Status int medium_status_ = kMediumStatusIdle; diff --git a/internal/platform/implementation/windows/wifi_hotspot_medium.cc b/internal/platform/implementation/windows/wifi_hotspot_medium.cc index fd4d23a4..54070edb 100644 --- a/internal/platform/implementation/windows/wifi_hotspot_medium.cc +++ b/internal/platform/implementation/windows/wifi_hotspot_medium.cc @@ -29,11 +29,23 @@ namespace { constexpr int kMaxScans = 3; } // namespace +WifiHotspotMedium::WifiHotspotMedium() { + HotspotCredentials hotspot_credentials_; + hotspot_interface_valid_ = StartWifiHotspot(&hotspot_credentials_); + if (hotspot_interface_valid_) + StopWifiHotspot(); +} + WifiHotspotMedium::~WifiHotspotMedium() { StopWifiHotspot(); DisconnectWifiHotspot(); } +bool WifiHotspotMedium::IsInterfaceValid() const { + return hotspot_interface_valid_; +} + + std::unique_ptr WifiHotspotMedium::ConnectToService( absl::string_view ip_address, int port, CancellationFlag* cancellation_flag) { diff --git a/internal/platform/wifi_hotspot.h b/internal/platform/wifi_hotspot.h index 0890bc78..1f8767e3 100644 --- a/internal/platform/wifi_hotspot.h +++ b/internal/platform/wifi_hotspot.h @@ -194,6 +194,11 @@ class WifiHotspotMedium { return &hotspot_credentials_; } + bool IsInterfaceValid() const { + CHECK(impl_); + return impl_->IsInterfaceValid(); + } + bool IsValid() const { return impl_ != nullptr; } // since impl_ could be nullptr if platform hasn't implemented this Medium, diff --git a/internal/platform/wifi_hotspot_test.cc b/internal/platform/wifi_hotspot_test.cc index 399e22d3..5f160f36 100644 --- a/internal/platform/wifi_hotspot_test.cc +++ b/internal/platform/wifi_hotspot_test.cc @@ -85,8 +85,8 @@ TEST_F(WifiHotspotMediumTest, ConstructorDestructorWorks) { auto wifi_hotspot_b = std::make_unique(); // Make sure we can create functional mediums. - ASSERT_TRUE(wifi_hotspot_a->IsValid()); - ASSERT_TRUE(wifi_hotspot_b->IsValid()); + ASSERT_TRUE(wifi_hotspot_a->IsInterfaceValid()); + ASSERT_TRUE(wifi_hotspot_b->IsInterfaceValid()); // Make sure we can create 2 distinct mediums. EXPECT_NE(&wifi_hotspot_a->GetImpl(), &wifi_hotspot_b->GetImpl()); @@ -97,6 +97,7 @@ TEST_F(WifiHotspotMediumTest, ConstructorDestructorWorks) { TEST_F(WifiHotspotMediumTest, CanStartStopHotspot) { auto wifi_hotspot_a = std::make_unique(); + ASSERT_TRUE(wifi_hotspot_a->IsInterfaceValid()); EXPECT_TRUE(wifi_hotspot_a->StartWifiHotspot()); EXPECT_EQ(wifi_hotspot_a->GetDynamicPortRange(), std::nullopt); WifiHotspotServerSocket server_socket = wifi_hotspot_a->ListenForService(); @@ -111,6 +112,7 @@ TEST_F(WifiHotspotMediumTest, CanConnectDisconnectHotspot) { std::string ssid(kSsid); std::string password(kPassword); + ASSERT_TRUE(wifi_hotspot_a->IsInterfaceValid()); EXPECT_FALSE(wifi_hotspot_a->ConnectWifiHotspot(ssid, password)); EXPECT_TRUE(wifi_hotspot_a->DisconnectWifiHotspot()); wifi_hotspot_a.reset(); @@ -122,6 +124,8 @@ TEST_P(WifiHotspotMediumTest, CanStartHotspotThatOtherConnect) { auto wifi_hotspot_a = std::make_unique(); auto wifi_hotspot_b = std::make_unique(); + ASSERT_TRUE(wifi_hotspot_a->IsInterfaceValid()); + ASSERT_TRUE(wifi_hotspot_b->IsInterfaceValid()); EXPECT_TRUE(wifi_hotspot_a->StartWifiHotspot()); HotspotCredentials* hotspot_credentials = wifi_hotspot_a->GetCredential(); EXPECT_TRUE(wifi_hotspot_b->ConnectWifiHotspot( @@ -186,6 +190,8 @@ TEST_P(WifiHotspotMediumTest, CanStartHotspotThatOtherCanCancelConnect) { auto wifi_hotspot_a = std::make_unique(); auto wifi_hotspot_b = std::make_unique(); + ASSERT_TRUE(wifi_hotspot_a->IsInterfaceValid()); + ASSERT_TRUE(wifi_hotspot_b->IsInterfaceValid()); EXPECT_TRUE(wifi_hotspot_a->StartWifiHotspot()); HotspotCredentials* hotspot_credentials = wifi_hotspot_a->GetCredential(); EXPECT_TRUE(wifi_hotspot_b->ConnectWifiHotspot( @@ -242,6 +248,8 @@ TEST_F(WifiHotspotMediumTest, CanStartHotspotTheOtherFailConnect) { auto wifi_hotspot_a = std::make_unique(); auto wifi_hotspot_b = std::make_unique(); + ASSERT_TRUE(wifi_hotspot_a->IsInterfaceValid()); + ASSERT_TRUE(wifi_hotspot_b->IsInterfaceValid()); EXPECT_TRUE(wifi_hotspot_a->StartWifiHotspot()); std::string ssid(kSsid);