mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
WIFI Direct implementation (3)
Part 3: BWU and client interface part PiperOrigin-RevId: 498218241
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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{};
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user