WIFI Direct implementation (3)

Part 3: BWU and client interface part

PiperOrigin-RevId: 498218241
This commit is contained in:
hai007
2022-12-28 11:22:48 -08:00
committed by Copybara-Service
parent 88e350e5d2
commit 499b2691f4
23 changed files with 714 additions and 66 deletions
+1
View File
@@ -432,6 +432,7 @@ let package = Package(
"connections/implementation/payload_manager_test.cc",
"connections/implementation/offline_frames_validator_test.cc",
"connections/implementation/service_controller_router_test.cc",
"connections/implementation/wifi_direct_bwu_test.cc",
"connections/implementation/wifi_hotspot_test.cc",
"connections/implementation/analytics/analytics_recorder_test.cc",
"connections/implementation/analytics/throughput_recorder_test.cc",
@@ -22,7 +22,7 @@ namespace location::nearby::windows {
extern "C" {
#define MAX_MEDIUMS 5
#define MAX_MEDIUMS 6
// Feature On/Off switch for mediums.
using BooleanMediumSelector = MediumSelectorW<bool>;
@@ -28,18 +28,19 @@ struct MediumSelectorW {
T web_rtc;
T wifi_lan;
T wifi_hotspot;
T wifi_direct;
constexpr MediumSelectorW() = default;
constexpr MediumSelectorW(const MediumSelectorW&) = default;
constexpr MediumSelectorW& operator=(const MediumSelectorW&) = default;
constexpr bool Any(const T& value) const {
return bluetooth == value || ble == value || web_rtc == value ||
wifi_lan == value || wifi_hotspot == value;
wifi_lan == value || wifi_hotspot == value || wifi_direct == value;
}
constexpr bool All(const T& value) const {
return bluetooth == value && ble == value && web_rtc == value &&
wifi_lan == value && wifi_hotspot == value;
wifi_lan == value && wifi_hotspot == value && wifi_direct == value;
}
constexpr int Count(const T& value) const {
@@ -48,6 +49,7 @@ struct MediumSelectorW {
if (ble == value) ++count;
if (wifi_lan == value) ++count;
if (wifi_hotspot == value) ++count;
if (wifi_direct == value) ++count;
if (web_rtc == value) ++count;
return count;
}
@@ -58,6 +60,7 @@ struct MediumSelectorW {
web_rtc = value;
wifi_lan = value;
wifi_hotspot = value;
wifi_direct = value;
return *this;
}
@@ -65,6 +68,7 @@ struct MediumSelectorW {
std::vector<MediumW> mediums;
// Mediums are sorted in order of decreasing preference.
if (wifi_lan == value) mediums.push_back(MediumW::WIFI_LAN);
if (wifi_direct == value) mediums.push_back(MediumW::WIFI_DIRECT);
if (wifi_hotspot == value) mediums.push_back(MediumW::WIFI_HOTSPOT);
if (web_rtc == value) mediums.push_back(MediumW::WEB_RTC);
if (bluetooth == value) mediums.push_back(MediumW::BLUETOOTH);
+5
View File
@@ -67,6 +67,8 @@ cc_library(
"pcp_manager.cc",
"service_controller_router.cc",
"webrtc_endpoint_channel.cc",
"wifi_direct_bwu_handler.cc",
"wifi_direct_endpoint_channel.cc",
"wifi_hotspot_bwu_handler.cc",
"wifi_hotspot_endpoint_channel.cc",
"wifi_lan_bwu_handler.cc",
@@ -114,6 +116,8 @@ cc_library(
"service_controller_router.h",
"service_id_constants.h",
"webrtc_endpoint_channel.h",
"wifi_direct_bwu_handler.h",
"wifi_direct_endpoint_channel.h",
"wifi_hotspot_bwu_handler.h",
"wifi_hotspot_endpoint_channel.h",
"wifi_lan_bwu_handler.h",
@@ -241,6 +245,7 @@ cc_test(
"payload_manager_test.cc",
"pcp_manager_test.cc",
"service_controller_router_test.cc",
"wifi_direct_bwu_test.cc",
"wifi_hotspot_test.cc",
"wifi_lan_service_info_test.cc",
],
@@ -179,6 +179,9 @@ void BasePcpHandler::OptionsAllowed(const BooleanMediumSelector& allowed,
if (allowed.wifi_hotspot) {
result << proto::connections::Medium_Name(Medium::WIFI_HOTSPOT) << " ";
}
if (allowed.wifi_direct) {
result << proto::connections::Medium_Name(Medium::WIFI_DIRECT) << " ";
}
result << "}";
}
@@ -234,6 +237,7 @@ BooleanMediumSelector BasePcpHandler::ComputeIntersectionOfSupportedMediums(
mediumSelector.web_rtc = intersection.contains(Medium::WEB_RTC);
mediumSelector.wifi_lan = intersection.contains(Medium::WIFI_LAN);
mediumSelector.wifi_hotspot = intersection.contains(Medium::WIFI_HOTSPOT);
mediumSelector.wifi_direct = intersection.contains(Medium::WIFI_DIRECT);
return mediumSelector;
}
+19 -2
View File
@@ -31,6 +31,7 @@
#else
#include "connections/implementation/webrtc_bwu_handler.h"
#endif
#include "connections/implementation/wifi_direct_bwu_handler.h"
#include "connections/implementation/wifi_hotspot_bwu_handler.h"
#include "connections/implementation/wifi_lan_bwu_handler.h"
#include "internal/platform/byte_array.h"
@@ -108,6 +109,11 @@ void BwuManager::InitBwuHandlers() {
Medium::WIFI_HOTSPOT,
std::make_unique<WifiHotspotBwuHandler>(*mediums_, notifications));
}
if (config_.allow_upgrade_to.wifi_direct) {
handlers_.emplace(
Medium::WIFI_DIRECT,
std::make_unique<WifiDirectBwuHandler>(*mediums_, notifications));
}
if (config_.allow_upgrade_to.wifi_lan) {
handlers_.emplace(Medium::WIFI_LAN, std::make_unique<WifiLanBwuHandler>(
*mediums_, notifications));
@@ -391,16 +397,24 @@ void BwuManager::RevertBwuMediumForEndpoint(const std::string& service_id,
// unless the BWU Medium is Hotspot. The client needs to disconnect from
// Hotspot, then it can restore the previous AP connection right away.
if (!IsInitiatorUpgradeServiceId(service_id)) {
if (medium == Medium::WIFI_HOTSPOT) {
if (medium == Medium::WIFI_HOTSPOT || medium == Medium::WIFI_DIRECT) {
handler->RevertResponderState(service_id);
}
return;
}
handler->RevertInitiatorState(service_id, endpoint_id);
}
bool BwuManager::IsUpgradeOngoing(const std::string& endpoint_id) {
CountDownLatch latch(1);
RunOnBwuManagerThread("is_upgrade_ongoing", [&latch]() {
latch.CountDown();
});
latch.Await();
return in_progress_upgrades_.contains(endpoint_id);
}
Medium BwuManager::GetBwuMediumForEndpoint(
const std::string& endpoint_id) const {
if (!FeatureFlags::GetInstance().GetFlags().support_multiple_bwu_mediums) {
@@ -1219,6 +1233,9 @@ std::vector<Medium> BwuManager::StripOutUnavailableMediums(
case Medium::WIFI_LAN:
available = mediums_->GetWifiLan().IsAvailable();
break;
case Medium::WIFI_DIRECT:
available = mediums_->GetWifiDirect().IsGOAvailable();
break;
case Medium::WIFI_HOTSPOT:
available = mediums_->GetWifiHotspot().IsAPAvailable();
break;
+3
View File
@@ -114,6 +114,9 @@ class BwuManager : public EndpointManager::FrameProcessor {
// ClientProxy objects are deleted.
void ShutdownExecutors();
// Check if BWU is on going for a specific Endpoint
bool IsUpgradeOngoing(const std::string& endpoint_id);
private:
static constexpr absl::Duration kReadClientIntroductionFrameTimeout =
absl::Seconds(5);
+134 -19
View File
@@ -42,6 +42,7 @@ constexpr absl::string_view kEndpointId1 = "Endpoint1";
constexpr absl::string_view kEndpointId2 = "Endpoint2";
constexpr absl::string_view kEndpointId3 = "Endpoint3";
constexpr absl::string_view kEndpointId4 = "Endpoint4";
constexpr absl::string_view kEndpointId5 = "Endpoint5";
class BwuManagerTest : public ::testing::Test {
protected:
@@ -49,20 +50,25 @@ class BwuManagerTest : public ::testing::Test {
// Set up fake BWU handlers for WebRTC and WifiLAN.
absl::flat_hash_map<Medium, std::unique_ptr<BwuHandler>> handlers;
auto fake_web_rtc = std::make_unique<FakeBwuHandler>(Medium::WEB_RTC);
auto fake_wifi_lan =
std::make_unique<FakeBwuHandler>(Medium::WIFI_LAN);
auto fake_wifi_lan = std::make_unique<FakeBwuHandler>(Medium::WIFI_LAN);
auto fake_wifi_direct =
std::make_unique<FakeBwuHandler>(Medium::WIFI_DIRECT);
auto fake_wifi_hotspot =
std::make_unique<FakeBwuHandler>(Medium::WIFI_HOTSPOT);
fake_web_rtc_bwu_handler_ = fake_web_rtc.get();
fake_wifi_lan_bwu_handler_ = fake_wifi_lan.get();
fake_wifi_direct_bwu_handler_ = fake_wifi_direct.get();
fake_wifi_hotspot_bwu_handler_ = fake_wifi_hotspot.get();
handlers.emplace(Medium::WEB_RTC, std::move(fake_web_rtc));
handlers.emplace(Medium::WIFI_LAN, std::move(fake_wifi_lan));
handlers.emplace(Medium::WIFI_DIRECT, std::move(fake_wifi_direct));
handlers.emplace(Medium::WIFI_HOTSPOT, std::move(fake_wifi_hotspot));
BwuManager::Config config;
config.allow_upgrade_to = BooleanMediumSelector{
.web_rtc = true, .wifi_lan = true, .wifi_hotspot = true};
config.allow_upgrade_to = BooleanMediumSelector{.web_rtc = true,
.wifi_lan = true,
.wifi_hotspot = true,
.wifi_direct = true};
bwu_manager_ = std::make_unique<BwuManager>(mediums_, em_, ecm_,
std::move(handlers), config);
@@ -101,6 +107,9 @@ class BwuManagerTest : public ::testing::Test {
case Medium::WIFI_LAN:
handler = fake_wifi_lan_bwu_handler_;
break;
case Medium::WIFI_DIRECT:
handler = fake_wifi_direct_bwu_handler_;
break;
case Medium::WIFI_HOTSPOT:
handler = fake_wifi_hotspot_bwu_handler_;
break;
@@ -138,11 +147,58 @@ class BwuManagerTest : public ::testing::Test {
Mediums mediums_;
FakeBwuHandler* fake_web_rtc_bwu_handler_ = nullptr;
FakeBwuHandler* fake_wifi_lan_bwu_handler_ = nullptr;
FakeBwuHandler* fake_wifi_direct_bwu_handler_ = nullptr;
FakeBwuHandler* fake_wifi_hotspot_bwu_handler_ = nullptr;
std::unique_ptr<BwuManager> bwu_manager_;
PacketMetaData packet_meta_data_;
};
TEST(BwuManagerBaseTest, AllowToUpgradeMedium) {
ClientProxy client;
EndpointChannelManager ecm;
EndpointManager em(&ecm);
Mediums mediums;
BwuManager::Config config;
config.allow_upgrade_to.SetAll(false);
absl::flat_hash_map<Medium, std::unique_ptr<BwuHandler>> handlers;
auto bwu_manager = std::make_unique<BwuManager>(mediums, em, ecm,
std::move(handlers), config);
auto channel1 = std::make_unique<FakeEndpointChannel>(
Medium::BLUETOOTH, std::string(kServiceIdA));
ecm.RegisterChannelForEndpoint(&client, std::string(kEndpointId1),
std::move(channel1));
bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId1),
Medium::WIFI_LAN);
EXPECT_TRUE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId1)));
auto channel2 = std::make_unique<FakeEndpointChannel>(
Medium::BLUETOOTH, std::string(kServiceIdA));
ecm.RegisterChannelForEndpoint(&client, std::string(kEndpointId2),
std::move(channel2));
bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId2),
Medium::WIFI_HOTSPOT);
EXPECT_TRUE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId2)));
auto channel3 = std::make_unique<FakeEndpointChannel>(
Medium::BLUETOOTH, std::string(kServiceIdA));
ecm.RegisterChannelForEndpoint(&client, std::string(kEndpointId3),
std::move(channel3));
bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId3),
Medium::WIFI_DIRECT);
EXPECT_FALSE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId3)));
auto channel4 = std::make_unique<FakeEndpointChannel>(
Medium::WEB_RTC, std::string(kServiceIdA));
ecm.RegisterChannelForEndpoint(&client, std::string(kEndpointId4),
std::move(channel4));
bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId4),
Medium::BLUETOOTH);
EXPECT_FALSE(bwu_manager->IsUpgradeOngoing(std::string(kEndpointId4)));
bwu_manager->Shutdown();
}
class BwuManagerTestParam : public BwuManagerTest,
public ::testing::WithParamInterface<bool> {
protected:
@@ -167,6 +223,7 @@ TEST_P(BwuManagerTestParam, InitiateBwu_Success) {
EXPECT_TRUE(fake_wifi_lan_bwu_handler_->handle_initialize_calls().empty());
EXPECT_TRUE(
fake_wifi_hotspot_bwu_handler_->handle_initialize_calls().empty());
EXPECT_TRUE(fake_wifi_direct_bwu_handler_->handle_initialize_calls().empty());
EXPECT_EQ(WrapInitiatorUpgradeServiceId(kServiceIdA),
fake_web_rtc_bwu_handler_->handle_initialize_calls()[0].service_id);
EXPECT_EQ(
@@ -237,9 +294,8 @@ TEST_P(BwuManagerTestParam,
fake_wifi_hotspot_bwu_handler_->handle_initialize_calls().empty());
}
TEST_P(BwuManagerTestParam, InitiateBwu_Error_NoMediumHandler) {
// Try to upgrade to a medium without a handler (WIFI_HOTSPOT is not support
// in these tests). Should just early return with no action.
TEST_P(BwuManagerTestParam, InitiateBwu_Error_NoInitialMedium) {
// Try to upgrade to a Medium without an initial Medium.
bwu_manager_->InitiateBwuForEndpoint(&client_, std::string(kEndpointId1),
Medium::WIFI_HOTSPOT);
@@ -248,6 +304,7 @@ TEST_P(BwuManagerTestParam, InitiateBwu_Error_NoMediumHandler) {
EXPECT_TRUE(fake_wifi_lan_bwu_handler_->handle_initialize_calls().empty());
EXPECT_TRUE(
fake_wifi_hotspot_bwu_handler_->handle_initialize_calls().empty());
EXPECT_TRUE(fake_wifi_direct_bwu_handler_->handle_initialize_calls().empty());
}
TEST_P(BwuManagerTestParam, InitiateBwu_Error_UpgradeAlreadyInProgress) {
@@ -265,6 +322,7 @@ TEST_P(BwuManagerTestParam, InitiateBwu_Error_UpgradeAlreadyInProgress) {
EXPECT_TRUE(fake_wifi_lan_bwu_handler_->handle_initialize_calls().empty());
EXPECT_TRUE(
fake_wifi_hotspot_bwu_handler_->handle_initialize_calls().empty());
EXPECT_TRUE(fake_wifi_direct_bwu_handler_->handle_initialize_calls().empty());
}
TEST_P(BwuManagerTestParam,
@@ -420,13 +478,12 @@ TEST_F(BwuManagerTest,
EXPECT_EQ(kEndpointId1,
fake_wifi_lan_bwu_handler_->disconnect_calls()[0].endpoint_id);
// With the support_multiple_bwu_mediums flag enabled, we have more
// granular per-service tracking. So, we can revert for each service when
// the last endpoint of that medium for the service goes down.
ASSERT_EQ(1u, fake_wifi_lan_bwu_handler_->handle_revert_calls().size());
EXPECT_EQ(
upgrade_service_id_A,
fake_wifi_lan_bwu_handler_->handle_revert_calls()[0].service_id);
// With the support_multiple_bwu_mediums flag enabled, we have more
// granular per-service tracking. So, we can revert for each service when
// the last endpoint of that medium for the service goes down.
ASSERT_EQ(1u, fake_wifi_lan_bwu_handler_->handle_revert_calls().size());
EXPECT_EQ(upgrade_service_id_A,
fake_wifi_lan_bwu_handler_->handle_revert_calls()[0].service_id);
}
{
CountDownLatch latch(1);
@@ -504,10 +561,13 @@ TEST_F(
CreateInitialEndpoint(kServiceIdA, kEndpointId2, Medium::BLUETOOTH);
CreateInitialEndpoint(kServiceIdB, kEndpointId3, Medium::BLUETOOTH);
CreateInitialEndpoint(kServiceIdB, kEndpointId4, Medium::BLUETOOTH);
CreateInitialEndpoint(kServiceIdB, kEndpointId5, Medium::BLUETOOTH);
FullyUpgradeEndpoint(kEndpointId1, /*initial_medium=*/Medium::BLUETOOTH,
/*upgrade_medium=*/Medium::WEB_RTC);
FullyUpgradeEndpoint(kEndpointId4, /*initial_medium=*/Medium::BLUETOOTH,
/*upgrade_medium=*/Medium::WIFI_HOTSPOT);
FullyUpgradeEndpoint(kEndpointId5, /*initial_medium=*/Medium::BLUETOOTH,
/*upgrade_medium=*/Medium::WIFI_DIRECT);
FullyUpgradeEndpoint(kEndpointId2, /*initial_medium=*/Medium::BLUETOOTH,
/*upgrade_medium=*/Medium::WIFI_LAN);
FullyUpgradeEndpoint(kEndpointId3, /*initial_medium=*/Medium::BLUETOOTH,
@@ -522,9 +582,11 @@ TEST_F(
EXPECT_TRUE(fake_web_rtc_bwu_handler_->disconnect_calls().empty());
EXPECT_TRUE(fake_wifi_lan_bwu_handler_->disconnect_calls().empty());
EXPECT_TRUE(fake_wifi_hotspot_bwu_handler_->disconnect_calls().empty());
EXPECT_TRUE(fake_wifi_direct_bwu_handler_->disconnect_calls().empty());
EXPECT_TRUE(fake_web_rtc_bwu_handler_->handle_revert_calls().empty());
EXPECT_TRUE(fake_wifi_lan_bwu_handler_->handle_revert_calls().empty());
EXPECT_TRUE(fake_wifi_hotspot_bwu_handler_->handle_revert_calls().empty());
EXPECT_TRUE(fake_wifi_direct_bwu_handler_->handle_revert_calls().empty());
{
CountDownLatch latch(1);
ecm_.UnregisterChannelForEndpoint(std::string(kEndpointId1));
@@ -544,6 +606,8 @@ TEST_F(
EXPECT_TRUE(fake_wifi_lan_bwu_handler_->handle_revert_calls().empty());
EXPECT_TRUE(fake_wifi_hotspot_bwu_handler_->disconnect_calls().empty());
EXPECT_TRUE(fake_wifi_hotspot_bwu_handler_->handle_revert_calls().empty());
EXPECT_TRUE(fake_wifi_direct_bwu_handler_->disconnect_calls().empty());
EXPECT_TRUE(fake_wifi_direct_bwu_handler_->handle_revert_calls().empty());
}
{
CountDownLatch latch(1);
@@ -601,6 +665,25 @@ TEST_F(
upgrade_service_id_B,
fake_wifi_hotspot_bwu_handler_->handle_revert_calls()[0].service_id);
}
{
CountDownLatch latch(1);
ecm_.UnregisterChannelForEndpoint(std::string(kEndpointId5));
bwu_manager_->OnEndpointDisconnect(&client_, upgrade_service_id_B,
std::string(kEndpointId5), latch);
// We reverted a WifiDirect channel; no additional WebRTC calls expected.
EXPECT_EQ(1u, fake_web_rtc_bwu_handler_->disconnect_calls().size());
EXPECT_EQ(1u, fake_web_rtc_bwu_handler_->handle_revert_calls().size());
// No more WifiDirect channels for service B; expect revert call.
ASSERT_EQ(1u, fake_wifi_direct_bwu_handler_->disconnect_calls().size());
EXPECT_EQ(kEndpointId5,
fake_wifi_direct_bwu_handler_->disconnect_calls()[0].endpoint_id);
ASSERT_EQ(1u, fake_wifi_direct_bwu_handler_->handle_revert_calls().size());
EXPECT_EQ(
upgrade_service_id_B,
fake_wifi_direct_bwu_handler_->handle_revert_calls()[0].service_id);
}
}
TEST_F(BwuManagerTest, InitiateBwu_Revert_OnUpgradeFailure_FlagEnabled) {
@@ -630,11 +713,11 @@ TEST_F(BwuManagerTest, InitiateBwu_Revert_OnUpgradeFailure_FlagEnabled) {
std::string(kEndpointId3), &client_,
Medium::WEB_RTC, packet_meta_data_);
// With the flag enabled, we can safely revert WebRTC just for service B
// because service B has no active WebRTC endpoints.
ASSERT_EQ(1u, fake_web_rtc_bwu_handler_->handle_revert_calls().size());
EXPECT_EQ(WrapInitiatorUpgradeServiceId(kServiceIdB),
fake_web_rtc_bwu_handler_->handle_revert_calls()[0].service_id);
// With the flag enabled, we can safely revert WebRTC just for service B
// because service B has no active WebRTC endpoints.
ASSERT_EQ(1u, fake_web_rtc_bwu_handler_->handle_revert_calls().size());
EXPECT_EQ(WrapInitiatorUpgradeServiceId(kServiceIdB),
fake_web_rtc_bwu_handler_->handle_revert_calls()[0].service_id);
}
TEST_F(BwuManagerTest, InitiateBwu_Revert_OnUpgradeFailure_FlagDisabled) {
@@ -671,6 +754,38 @@ TEST_F(BwuManagerTest, InitiateBwu_Revert_OnUpgradeFailure_FlagDisabled) {
EXPECT_TRUE(fake_web_rtc_bwu_handler_->handle_revert_calls().empty());
}
TEST_F(BwuManagerTest, InitiateBwu_Revert_OnDisconnect_WifiDirect) {
FeatureFlags::GetMutableFlagsForTesting().support_multiple_bwu_mediums = true;
OfflineFrame frame;
CreateInitialEndpoint(kServiceIdA, kEndpointId1, Medium::BLUETOOTH);
ByteArray bytes = parser::ForBwuWifiDirectPathAvailable(
/*ssid=*/"Direct-12345678", /*password=*/"87654321", /*port=*/2143,
/*frequency=*/2412, /*supports_disabling_encryption=*/false,
/*gateway=*/"123.234.23.1");
frame.ParseFromString(std::string(bytes));
::location::nearby::connections::V1Frame* v1_frame = frame.mutable_v1();
::location::nearby::connections::BandwidthUpgradeNegotiationFrame* sub_frame =
v1_frame->mutable_bandwidth_upgrade_negotiation();
::location::nearby::connections::
BandwidthUpgradeNegotiationFrame_UpgradePathInfo* upgrade_path_info =
sub_frame->mutable_upgrade_path_info();
upgrade_path_info->set_supports_client_introduction_ack(false);
bwu_manager_->OnIncomingFrame(frame, std::string(kEndpointId1), &client_,
Medium::BLUETOOTH, packet_meta_data_);
CountDownLatch latch(1);
bwu_manager_->OnEndpointDisconnect(&client_, (std::string)kServiceIdA,
std::string(kEndpointId1), latch);
ASSERT_EQ(fake_wifi_direct_bwu_handler_->disconnect_calls().size(), 1u);
EXPECT_EQ(kEndpointId1,
fake_wifi_direct_bwu_handler_->disconnect_calls()[0].endpoint_id);
// This is called by the RESPONDER--call RevertInitiatorState only when
// BWU Medium is Hotspot or WifiDirect.
ASSERT_EQ(fake_wifi_direct_bwu_handler_->handle_revert_calls().size(), 1u);
}
TEST_F(BwuManagerTest, InitiateBwu_Revert_OnDisconnect_Hotspot) {
FeatureFlags::GetMutableFlagsForTesting().support_multiple_bwu_mediums = true;
@@ -140,16 +140,20 @@ class FakeBwuHandler : public BaseBwuHandler {
case proto::connections::WEB_RTC:
return parser::ForBwuWebrtcPathAvailable(/*peer_id=*/"peer-id",
LocationHint{});
case proto::connections::UNKNOWN_MEDIUM:
case proto::connections::MDNS:
case proto::connections::WIFI_HOTSPOT:
return parser::ForBwuWifiHotspotPathAvailable(
/*ssid=*/"Direct-357a2d8c", /*password=*/"b592f7d3",
/*port=*/1234, /*gateway=*/"123.234.23.1", false);
case proto::connections::WIFI_DIRECT:
return parser::ForBwuWifiDirectPathAvailable(
/*ssid=*/"Direct-12345678", /*password=*/"87654321", /*port=*/2143,
/*frequency=*/2412, /*supports_disabling_encryption=*/false,
/*gateway=*/"123.234.23.1");
case proto::connections::UNKNOWN_MEDIUM:
case proto::connections::MDNS:
case proto::connections::BLE:
case proto::connections::WIFI_AWARE:
case proto::connections::NFC:
case proto::connections::WIFI_DIRECT:
case proto::connections::BLE_L2CAP:
case proto::connections::USB:
return ByteArray{};
+3 -1
View File
@@ -232,7 +232,8 @@ ByteArray ForBwuWifiDirectPathAvailable(const std::string& ssid,
const std::string& password,
std::int32_t port,
std::int32_t frequency,
bool supports_disabling_encryption) {
bool supports_disabling_encryption,
const std::string& gateway) {
OfflineFrame frame;
frame.set_version(OfflineFrame::V1);
@@ -252,6 +253,7 @@ ByteArray ForBwuWifiDirectPathAvailable(const std::string& ssid,
wifi_direct_credentials->set_password(password);
wifi_direct_credentials->set_port(port);
wifi_direct_credentials->set_frequency(frequency);
wifi_direct_credentials->set_gateway(gateway);
return ToBytes(std::move(frame));
}
+2 -1
View File
@@ -73,7 +73,8 @@ ByteArray ForBwuWifiDirectPathAvailable(const std::string& ssid,
const std::string& password,
std::int32_t port,
std::int32_t frequency,
bool supports_disabling_encryption);
bool supports_disabling_encryption,
const std::string& gateway);
ByteArray ForBwuBluetoothPathAvailable(const std::string& service_id,
const std::string& mac_address);
ByteArray ForBwuWebrtcPathAvailable(const std::string& peer_id,
@@ -294,7 +294,8 @@ TEST(OfflineFramesTest, CanGenerateBwuWifiDirectPathAvailable) {
ssid: "DIRECT-A0-0123456789AB"
password: "password"
port: 1000
frequency: 1000
frequency: 2412
gateway: "192.168.1.1"
>
supports_disabling_encryption: false
supports_client_introduction_ack: true
@@ -302,7 +303,7 @@ TEST(OfflineFramesTest, CanGenerateBwuWifiDirectPathAvailable) {
>
>)pb";
ByteArray bytes = ForBwuWifiDirectPathAvailable(
"DIRECT-A0-0123456789AB", "password", 1000, 1000, false);
"DIRECT-A0-0123456789AB", "password", 1000, 2412, false, "192.168.1.1");
auto response = FromBytes(bytes);
ASSERT_TRUE(response.ok());
OfflineFrame message = FromBytes(bytes).result();
@@ -14,14 +14,15 @@
#include "connections/implementation/offline_frames_validator.h"
#include <array>
#include <string>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/strings/string_view.h"
#include "connections/implementation/proto/offline_wire_formats.pb.h"
#include "connections/implementation/offline_frames.h"
#include "connections/implementation/proto/offline_wire_formats.pb.h"
#include "internal/platform/byte_array.h"
namespace location {
@@ -43,7 +44,8 @@ constexpr absl::string_view kPassword = "password";
constexpr absl::string_view kWifiHotspotGateway = "0.0.0.0";
constexpr absl::string_view kWifiDirectSsid = "DIRECT-A0-0123456789AB";
constexpr absl::string_view kWifiDirectPassword = "WIFIDIRECT123456";
constexpr int kWifiDirectFrequency = 1000;
constexpr absl::string_view kGateway = "192.168.1.1";
constexpr int kWifiDirectFrequency = 2412;
constexpr int kPort = 1000;
constexpr bool kSupportsDisablingEncryption = true;
constexpr std::array<Medium, 9> kMediums = {
@@ -54,19 +56,19 @@ constexpr std::array<Medium, 9> kMediums = {
constexpr int kKeepAliveIntervalMillis = 1000;
constexpr int kKeepAliveTimeoutMillis = 5000;
class OfflineFramesConnectionRequestTest : public testing::Test {
class OfflineFramesConnectionRequestTest : public testing::Test {
protected:
ConnectionInfo connection_info_{std::string(kEndpointId),
ByteArray{std::string(kEndpointName)},
kNonce,
kSupports5ghz,
std::string(kBssid),
kApFrequency,
std::string(kIp4Bytes),
std::vector<Medium, std::allocator<Medium>>(
kMediums.begin(), kMediums.end()),
kKeepAliveIntervalMillis,
kKeepAliveTimeoutMillis};
ByteArray{std::string(kEndpointName)},
kNonce,
kSupports5ghz,
std::string(kBssid),
kApFrequency,
std::string(kIp4Bytes),
std::vector<Medium, std::allocator<Medium>>(
kMediums.begin(), kMediums.end()),
kKeepAliveIntervalMillis,
kKeepAliveTimeoutMillis};
};
TEST_F(OfflineFramesConnectionRequestTest,
@@ -82,7 +84,7 @@ TEST_F(OfflineFramesConnectionRequestTest,
}
TEST_F(OfflineFramesConnectionRequestTest,
ValidatesAsFailWithNullConnectionRequestFrame) {
ValidatesAsFailWithNullConnectionRequestFrame) {
OfflineFrame offline_frame;
ByteArray bytes = ForConnectionRequest(connection_info_);
@@ -97,7 +99,7 @@ TEST_F(OfflineFramesConnectionRequestTest,
}
TEST_F(OfflineFramesConnectionRequestTest,
ValidatesAsFailWithNullEndpointIdInConnectionRequestFrame) {
ValidatesAsFailWithNullEndpointIdInConnectionRequestFrame) {
OfflineFrame offline_frame;
connection_info_.local_endpoint_id = "";
@@ -110,7 +112,7 @@ TEST_F(OfflineFramesConnectionRequestTest,
}
TEST_F(OfflineFramesConnectionRequestTest,
ValidatesAsFailWithNullEndpointInfoInConnectionRequestFrame) {
ValidatesAsFailWithNullEndpointInfoInConnectionRequestFrame) {
OfflineFrame offline_frame;
connection_info_.local_endpoint_info = ByteArray{""};
@@ -123,7 +125,7 @@ TEST_F(OfflineFramesConnectionRequestTest,
}
TEST_F(OfflineFramesConnectionRequestTest,
ValidatesAsOkWithNullBssidInConnectionRequestFrame) {
ValidatesAsOkWithNullBssidInConnectionRequestFrame) {
OfflineFrame offline_frame;
connection_info_.bssid = "";
@@ -136,7 +138,7 @@ TEST_F(OfflineFramesConnectionRequestTest,
}
TEST_F(OfflineFramesConnectionRequestTest,
ValidatesAsOkWithNullMediumsInConnectionRequestFrame) {
ValidatesAsOkWithNullMediumsInConnectionRequestFrame) {
OfflineFrame offline_frame;
connection_info_.supported_mediums = {};
@@ -595,7 +597,8 @@ TEST(OfflineFramesValidatorTest, ValidatesAsOkBandwidthUpgradeWifiDirect) {
ByteArray bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), std::string(kWifiDirectPassword), kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption);
kWifiDirectFrequency, kSupportsDisablingEncryption,
std::string(kGateway));
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
@@ -611,7 +614,7 @@ TEST(OfflineFramesValidatorTest,
// Anything less than -1 is invalid
ByteArray bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), std::string(kWifiDirectPassword), kPort, -2,
kSupportsDisablingEncryption);
kSupportsDisablingEncryption, std::string(kGateway));
offline_frame_1.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame_1);
@@ -619,9 +622,9 @@ TEST(OfflineFramesValidatorTest,
ASSERT_FALSE(ret_value.Ok());
// But -1 itself is not invalid
bytes = ForBwuWifiDirectPathAvailable(std::string(kWifiDirectSsid),
std::string(kWifiDirectPassword), kPort,
-1, kSupportsDisablingEncryption);
bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), std::string(kWifiDirectPassword), kPort, -1,
kSupportsDisablingEncryption, std::string(kGateway));
offline_frame_2.ParseFromString(std::string(bytes));
ret_value = EnsureValidOfflineFrame(offline_frame_2);
@@ -637,7 +640,8 @@ TEST(OfflineFramesValidatorTest,
std::string wifi_direct_ssid{"DIRECT-A*-0123456789AB"};
ByteArray bytes = ForBwuWifiDirectPathAvailable(
wifi_direct_ssid, std::string(kWifiDirectPassword), kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption);
kWifiDirectFrequency, kSupportsDisablingEncryption,
std::string(kGateway));
offline_frame_1.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame_1);
@@ -648,7 +652,8 @@ TEST(OfflineFramesValidatorTest,
std::string{kWifiDirectSsid} + "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
bytes = ForBwuWifiDirectPathAvailable(
wifi_direct_ssid_wrong_length, std::string(kWifiDirectPassword), kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption);
kWifiDirectFrequency, kSupportsDisablingEncryption,
std::string(kGateway));
offline_frame_2.ParseFromString(std::string(bytes));
ret_value = EnsureValidOfflineFrame(offline_frame_2);
@@ -664,7 +669,8 @@ TEST(OfflineFramesValidatorTest,
std::string short_wifi_direct_password{"Test"};
ByteArray bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), short_wifi_direct_password, kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption);
kWifiDirectFrequency, kSupportsDisablingEncryption,
std::string(kGateway));
offline_frame_1.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame_1);
@@ -676,7 +682,8 @@ TEST(OfflineFramesValidatorTest,
"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789";
bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), long_wifi_direct_password, kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption);
kWifiDirectFrequency, kSupportsDisablingEncryption,
std::string(kGateway));
offline_frame_2.ParseFromString(std::string(bytes));
ret_value = EnsureValidOfflineFrame(offline_frame_2);
@@ -27,9 +27,7 @@
#include "connections/implementation/bluetooth_endpoint_channel.h"
#include "connections/implementation/bwu_manager.h"
#include "connections/implementation/mediums/utils.h"
#include "connections/implementation/webrtc_endpoint_channel.h"
#include "connections/implementation/wifi_lan_endpoint_channel.h"
#include "internal/platform/crypto.h"
#include "internal/platform/nsd_service_info.h"
#include "internal/platform/types.h"
#include "proto/connections_enums.pb.h"
@@ -65,6 +63,7 @@ P2pClusterPcpHandler::P2pClusterPcpHandler(
ble_v2_medium_(mediums->GetBleV2()),
wifi_lan_medium_(mediums->GetWifiLan()),
wifi_hotspot_medium_(mediums->GetWifiHotspot()),
wifi_direct_medium_(mediums->GetWifiDirect()),
webrtc_medium_(mediums->GetWebRtc()),
injected_bluetooth_device_store_(injected_bluetooth_device_store) {}
@@ -34,14 +34,10 @@
#include "connections/implementation/mediums/webrtc_stub.h"
#else
#include "connections/implementation/mediums/webrtc.h"
#include "connections/implementation/mediums/webrtc_socket.h"
#endif
#include "connections/implementation/pcp.h"
#include "connections/implementation/wifi_lan_service_info.h"
#include "connections/strategy.h"
#include "internal/platform/bluetooth_classic.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/wifi_lan.h"
namespace location {
namespace nearby {
@@ -229,6 +225,7 @@ class P2pClusterPcpHandler : public BasePcpHandler {
BleV2& ble_v2_medium_;
WifiLan& wifi_lan_medium_;
WifiHotspot& wifi_hotspot_medium_;
WifiDirect& wifi_direct_medium_;
mediums::WebRtc& webrtc_medium_;
InjectedBluetoothDeviceStore& injected_bluetooth_device_store_;
std::int64_t bluetooth_classic_discoverer_client_id_{0};
@@ -33,6 +33,10 @@ P2pPointToPointPcpHandler::GetConnectionMediumsByPriority() {
if (mediums_->GetWifiLan().IsAvailable()) {
mediums.push_back(proto::connections::WIFI_LAN);
}
if (mediums_->GetWifi().IsAvailable() &&
mediums_->GetWifiDirect().IsGCAvailable()) {
mediums.push_back(proto::connections::WIFI_DIRECT);
}
if (mediums_->GetWifi().IsAvailable() &&
mediums_->GetWifiHotspot().IsClientAvailable()) {
mediums.push_back(proto::connections::WIFI_HOTSPOT);
@@ -36,6 +36,10 @@ P2pStarPcpHandler::GetConnectionMediumsByPriority() {
if (mediums_->GetWifiLan().IsAvailable()) {
mediums.push_back(proto::connections::WIFI_LAN);
}
if (mediums_->GetWifi().IsAvailable() &&
mediums_->GetWifiDirect().IsGCAvailable()) {
mediums.push_back(proto::connections::WIFI_DIRECT);
}
if (mediums_->GetWifi().IsAvailable() &&
mediums_->GetWifiHotspot().IsClientAvailable()) {
mediums.push_back(proto::connections::WIFI_HOTSPOT);
@@ -0,0 +1,158 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "connections/implementation/wifi_direct_bwu_handler.h"
#include <locale>
#include <memory>
#include <string>
#include <utility>
#include "absl/functional/bind_front.h"
#include "connections/implementation/client_proxy.h"
#include "connections/implementation/offline_frames.h"
#include "connections/implementation/wifi_direct_endpoint_channel.h"
#include "internal/platform/wifi_direct.h"
namespace location {
namespace nearby {
namespace connections {
WifiDirectBwuHandler::WifiDirectBwuHandler(Mediums& mediums,
BwuNotifications notifications)
: BaseBwuHandler(std::move(notifications)), mediums_(mediums) {}
ByteArray WifiDirectBwuHandler::HandleInitializeUpgradedMediumForEndpoint(
ClientProxy* client, const std::string& upgrade_service_id,
const std::string& endpoint_id) {
// Create WifiDirect GO
if (!wifi_direct_medium_.StartWifiDirect()) {
NEARBY_LOGS(INFO) << "Failed to start Wifi Direct!";
return {};
}
if (!wifi_direct_medium_.IsAcceptingConnections(upgrade_service_id)) {
if (!wifi_direct_medium_.StartAcceptingConnections(
upgrade_service_id,
{
.accepted_cb = absl::bind_front(
&WifiDirectBwuHandler::OnIncomingWifiDirectConnection, this,
client),
})) {
NEARBY_LOGS(ERROR)
<< "WifiDirectBwuHandler couldn't initiate WifiDirect upgrade for "
<< "service " << upgrade_service_id << " and endpoint " << endpoint_id
<< " because it failed to start listening for incoming WifiLan "
"connections.";
return {};
}
NEARBY_LOGS(INFO)
<< "WifiDirectBwuHandler successfully started listening for incoming "
"WifiDirect connections while upgrading endpoint "
<< endpoint_id;
}
// Note: Credentials are not generated until Medium StartWifiDirect() is
// called and the server socket is created. Be careful moving this codeblock
// around.
HotspotCredentials* wifi_direct_crendential =
wifi_direct_medium_.GetCredentials(upgrade_service_id);
std::string ssid = wifi_direct_crendential->GetSSID();
std::string password = wifi_direct_crendential->GetPassword();
std::string gateway = wifi_direct_crendential->GetGateway();
int port = wifi_direct_crendential->GetPort();
int freq = wifi_direct_crendential->GetFrequency();
NEARBY_LOGS(INFO) << "Start WifiDirect GO with SSID: " << ssid
<< ", Password: " << password << ", Port: " << port
<< ", Gateway: " << gateway << "Frequency: " << freq;
bool disabling_encryption =
(client->GetAdvertisingOptions().strategy == Strategy::kP2pPointToPoint);
return parser::ForBwuWifiDirectPathAvailable(
ssid, password, port, freq,
/* supports_disabling_encryption */ disabling_encryption, gateway);
}
void WifiDirectBwuHandler::HandleRevertInitiatorStateForService(
const std::string& upgrade_service_id) {
wifi_direct_medium_.StopAcceptingConnections(upgrade_service_id);
wifi_direct_medium_.StopWifiDirect();
wifi_direct_medium_.DisconnectWifiDirect();
NEARBY_LOGS(INFO)
<< "WifiDirectBwuHandler successfully reverted all states for "
<< "upgrade service ID " << upgrade_service_id;
}
std::unique_ptr<EndpointChannel>
WifiDirectBwuHandler::CreateUpgradedEndpointChannel(
ClientProxy* client, const std::string& service_id,
const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) {
if (!upgrade_path_info.has_wifi_direct_credentials()) {
NEARBY_LOGS(INFO) << "No WifiDirect Credential";
return nullptr;
}
const UpgradePathInfo::WifiDirectCredentials& upgrade_path_info_credentials =
upgrade_path_info.wifi_direct_credentials();
const std::string& ssid = upgrade_path_info_credentials.ssid();
const std::string& password = upgrade_path_info_credentials.password();
std::int32_t port = upgrade_path_info_credentials.port();
const std::string& gateway = upgrade_path_info_credentials.gateway();
NEARBY_LOGS(INFO) << "Received WifiDirect credential SSID: " << ssid
<< ", Password:" << password << ", Port:" << port
<< ", Gateway:" << gateway;
if (!wifi_direct_medium_.ConnectWifiDirect(ssid, password)) {
NEARBY_LOGS(ERROR) << "Connect to WifiDiret GO failed";
return nullptr;
}
WifiHotspotSocket socket = wifi_direct_medium_.Connect(
service_id, gateway, port, client->GetCancellationFlag(endpoint_id));
if (!socket.IsValid()) {
NEARBY_LOGS(ERROR)
<< "WifiDirectBwuHandler failed to connect to the WifiDirect service("
<< port << ") for endpoint " << endpoint_id;
return nullptr;
}
NEARBY_LOGS(VERBOSE)
<< "WifiDirectBwuHandler successfully connected to WifiDirect service ("
<< port << ") while upgrading endpoint " << endpoint_id;
// Create a new WifiDirectEndpointChannel.
return std::make_unique<WifiDirectEndpointChannel>(
service_id, /*channel_name=*/service_id, socket);
}
void WifiDirectBwuHandler::OnIncomingWifiDirectConnection(
ClientProxy* client, const std::string& upgrade_service_id,
WifiHotspotSocket socket) {
auto channel = std::make_unique<WifiDirectEndpointChannel>(
upgrade_service_id, /*channel_name=*/upgrade_service_id, socket);
std::unique_ptr<IncomingSocketConnection> connection(
new IncomingSocketConnection{
.socket = std::make_unique<WifiDirectIncomingSocket>(
upgrade_service_id, socket),
.channel = std::move(channel),
});
bwu_notifications_.incoming_connection_cb(client, std::move(connection));
}
} // namespace connections
} // namespace nearby
} // namespace location
@@ -0,0 +1,90 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CORE_INTERNAL_WIFI_DIRECT_BWU_HANDLER_H_
#define CORE_INTERNAL_WIFI_DIRECT_BWU_HANDLER_H_
#include <memory>
#include <string>
#include "connections/implementation/base_bwu_handler.h"
#include "connections/implementation/client_proxy.h"
#include "connections/implementation/mediums/mediums.h"
namespace location {
namespace nearby {
namespace connections {
// Defines the set of methods that need to be implemented to handle the
// per-Medium-specific operations needed to upgrade an EndpointChannel.
class WifiDirectBwuHandler : public BaseBwuHandler {
public:
explicit WifiDirectBwuHandler(Mediums& mediums,
BwuNotifications notifications);
private:
class WifiDirectIncomingSocket : public BwuHandler::IncomingSocket {
public:
// explicit WifiDirectIncomingSocket(const std::string& name,
explicit WifiDirectIncomingSocket(absl::string_view name,
WifiHotspotSocket socket)
: name_(name), socket_(socket) {}
std::string ToString() override { return name_; }
void Close() override { socket_.Close(); }
private:
std::string name_;
WifiHotspotSocket socket_;
};
// Called by BWU target. Retrieves a new medium info from incoming message,
// Windows doesn't support WIFIDirect as GC because phone side uses simplified
// WFD protocol to established connection while WINRT follow the standard WFD
// spec to achieve the connection. So return fail to stop the upgrade request
// from phone side.
std::unique_ptr<EndpointChannel> CreateUpgradedEndpointChannel(
ClientProxy* client, const std::string& service_id,
const std::string& endpoint_id,
const UpgradePathInfo& upgrade_path_info) final;
Medium GetUpgradeMedium() const final { return Medium::WIFI_DIRECT; }
void OnEndpointDisconnect(ClientProxy* client,
const std::string& endpoint_id) final {}
// Called by BWU initiator. Set up WifiDirect upgraded medium for this
// endpoint, and returns a upgrade path info (SSID, Password, Gateway used as
// IPAddress, Port) for remote party to perform connection.
ByteArray HandleInitializeUpgradedMediumForEndpoint(
ClientProxy* client, const std::string& upgrade_service_id,
const std::string& endpoint_id) final;
// Revert the upgrade when the procedure fails or disconnection is called.
void HandleRevertInitiatorStateForService(
const std::string& upgrade_service_id) final;
// Accept Connection Callback.
void OnIncomingWifiDirectConnection(ClientProxy* client,
const std::string& upgrade_service_id,
WifiHotspotSocket socket);
Mediums& mediums_;
Wifi& wifi_medium_ = mediums_.GetWifi();
WifiDirect& wifi_direct_medium_ = mediums_.GetWifiDirect();
};
} // namespace connections
} // namespace nearby
} // namespace location
#endif // CORE_INTERNAL_WIFI_DIRECT_BWU_HANDLER_H_
@@ -0,0 +1,126 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <memory>
#include <utility>
#include "gtest/gtest.h"
#include "connections/implementation/bwu_handler.h"
#include "connections/implementation/wifi_direct_bwu_handler.h"
#include "internal/platform/medium_environment.h"
namespace location {
namespace nearby {
namespace connections {
namespace {
constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000);
} // namespace
class WifiDirectTest : public testing::Test {
protected:
WifiDirectTest() { env_.Start(); }
~WifiDirectTest() override { env_.Stop(); }
MediumEnvironment& env_{MediumEnvironment::Instance()};
};
TEST_F(WifiDirectTest, CanCreateBwuHandler) {
BwuHandler::BwuNotifications notifications = {.incoming_connection_cb = {}};
ClientProxy client;
Mediums mediums;
auto handler = std::make_unique<WifiDirectBwuHandler>(mediums, notifications);
handler->InitializeUpgradedMediumForEndpoint(&client, /*service_id=*/"B",
/*endpoint_id=*/"2");
handler->RevertInitiatorState();
SUCCEED();
handler.reset();
}
TEST_F(WifiDirectTest, SoftAPBWUInit_STACreateEndpointChannel) {
CountDownLatch start_latch(1);
CountDownLatch accept_latch(1);
CountDownLatch end_latch(1);
BwuHandler::BwuNotifications notifications_1{
.incoming_connection_cb =
[&accept_latch, &end_latch](
ClientProxy* client,
std::unique_ptr<BwuHandler::IncomingSocketConnection>
mutable_connection) {
NEARBY_LOGS(WARNING) << "Server socket connection accept call back";
std::shared_ptr<BwuHandler::IncomingSocketConnection> connection(
mutable_connection.release());
accept_latch.CountDown();
EXPECT_TRUE(end_latch.Await(kWaitDuration).result());
NEARBY_LOGS(WARNING) << "Test is done. Close the socket";
connection->channel->Close();
connection->socket->Close();
},
};
BwuHandler::BwuNotifications notifications_2 = {.incoming_connection_cb = {}};
ClientProxy wifi_direct_go, wifi_direct_gc;
Mediums mediums_1, mediums_2;
ExceptionOr<OfflineFrame> upgrade_frame;
auto handler_1 =
std::make_unique<WifiDirectBwuHandler>(mediums_1, notifications_1);
SingleThreadExecutor server_executor;
server_executor.Execute(
[&handler_1, &wifi_direct_go, &upgrade_frame, &start_latch]() {
ByteArray upgrade_path_available_frame =
handler_1->InitializeUpgradedMediumForEndpoint(&wifi_direct_go,
/*service_id=*/"A",
/*endpoint_id=*/"1");
EXPECT_FALSE(upgrade_path_available_frame.Empty());
upgrade_frame = parser::FromBytes(upgrade_path_available_frame);
start_latch.CountDown();
});
SingleThreadExecutor client_executor;
// Wait till wifi_direct_go started and then connect to it
EXPECT_TRUE(start_latch.Await(kWaitDuration).result());
EXPECT_FALSE(mediums_2.GetWifiDirect().IsConnectedToGO());
std::unique_ptr<BwuHandler> handler_2 =
std::make_unique<WifiDirectBwuHandler>(mediums_2, notifications_2);
client_executor.Execute([&handler_2, &wifi_direct_gc, &upgrade_frame,
&accept_latch, &end_latch, &mediums_2]() {
auto bwu_frame =
upgrade_frame.result().v1().bandwidth_upgrade_negotiation();
std::unique_ptr<EndpointChannel> new_channel =
handler_2->CreateUpgradedEndpointChannel(
&wifi_direct_gc, /*service_id=*/"A",
/*endpoint_id=*/"1", bwu_frame.upgrade_path_info());
EXPECT_TRUE(accept_latch.Await(kWaitDuration).result());
EXPECT_EQ(new_channel->GetMedium(),
proto::connections::Medium::WIFI_DIRECT);
EXPECT_TRUE(mediums_2.GetWifiDirect().IsConnectedToGO());
handler_2->RevertResponderState(/*service_id=*/"A");
end_latch.CountDown();
});
EXPECT_TRUE(accept_latch.Await(kWaitDuration).result());
EXPECT_TRUE(end_latch.Await(kWaitDuration).result());
EXPECT_FALSE(mediums_2.GetWifiDirect().IsConnectedToGO());
}
} // namespace connections
} // namespace nearby
} // namespace location
@@ -0,0 +1,49 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "connections/implementation/wifi_direct_endpoint_channel.h"
#include <string>
#include <utility>
#include "internal/platform/logging.h"
#include "internal/platform/wifi_direct.h"
namespace location {
namespace nearby {
namespace connections {
WifiDirectEndpointChannel::WifiDirectEndpointChannel(
const std::string& service_id, const std::string& channel_name,
WifiHotspotSocket socket)
: BaseEndpointChannel(service_id, channel_name, &socket.GetInputStream(),
&socket.GetOutputStream()),
socket_(std::move(socket)) {}
proto::connections::Medium WifiDirectEndpointChannel::GetMedium() const {
return proto::connections::Medium::WIFI_DIRECT;
}
void WifiDirectEndpointChannel::CloseImpl() {
Exception status = socket_.Close();
if (!status.Ok()) {
NEARBY_LOGS(INFO)
<< "Failed to close underlying socket for WifiDirectEndpointChannel "
<< GetName() << " : exception = " << status.value;
}
}
} // namespace connections
} // namespace nearby
} // namespace location
@@ -0,0 +1,53 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CORE_INTERNAL_WIFI_DIRECT_ENDPOINT_CHANNEL_H_
#define CORE_INTERNAL_WIFI_DIRECT_ENDPOINT_CHANNEL_H_
#include <string>
#include "connections/implementation/base_endpoint_channel.h"
#include "internal/platform/wifi_hotspot.h"
namespace location {
namespace nearby {
namespace connections {
class WifiDirectEndpointChannel final : public BaseEndpointChannel {
public:
// Creates both outgoing and incoming WifiDirect channels.
WifiDirectEndpointChannel(const std::string& service_id,
const std::string& channel_name,
WifiHotspotSocket socket);
// Not copyable or movable
WifiDirectEndpointChannel(const WifiDirectEndpointChannel&) = delete;
WifiDirectEndpointChannel& operator=(const WifiDirectEndpointChannel&) =
delete;
WifiDirectEndpointChannel(WifiDirectEndpointChannel&&) = delete;
WifiDirectEndpointChannel& operator=(WifiDirectEndpointChannel&&) = delete;
proto::connections::Medium GetMedium() const override;
private:
void CloseImpl() override;
WifiHotspotSocket socket_;
};
} // namespace connections
} // namespace nearby
} // namespace location
#endif // CORE_INTERNAL_WIFI_DIRECT_ENDPOINT_CHANNEL_H_
+6 -2
View File
@@ -30,15 +30,16 @@ struct MediumSelector {
T web_rtc;
T wifi_lan;
T wifi_hotspot;
T wifi_direct;
constexpr bool Any(T value) const {
return bluetooth == value || ble == value || web_rtc == value ||
wifi_lan == value || wifi_hotspot == value;
wifi_lan == value || wifi_hotspot == value || wifi_direct == value;
}
constexpr bool All(T value) const {
return bluetooth == value && ble == value && web_rtc == value &&
wifi_lan == value && wifi_hotspot == value;
wifi_lan == value && wifi_hotspot == value && wifi_direct == value;
}
constexpr int Count(T value) const {
@@ -47,6 +48,7 @@ struct MediumSelector {
if (ble == value) count++;
if (wifi_lan == value) count++;
if (wifi_hotspot == value) count++;
if (wifi_direct == value) count++;
if (web_rtc == value) count++;
return count;
}
@@ -57,6 +59,7 @@ struct MediumSelector {
web_rtc = value;
wifi_lan = value;
wifi_hotspot = value;
wifi_direct = value;
return *this;
}
@@ -64,6 +67,7 @@ struct MediumSelector {
std::vector<Medium> mediums;
// Mediums are sorted in order of decreasing preference.
if (wifi_lan == value) mediums.push_back(Medium::WIFI_LAN);
if (wifi_direct == value) mediums.push_back(Medium::WIFI_DIRECT);
if (wifi_hotspot == value) mediums.push_back(Medium::WIFI_HOTSPOT);
if (web_rtc == value) mediums.push_back(Medium::WEB_RTC);
if (bluetooth == value) mediums.push_back(Medium::BLUETOOTH);