Wi-Fi Direct Service Implementation(7)

PiperOrigin-RevId: 834584965
This commit is contained in:
hai007
2025-11-19 21:45:43 -08:00
committed by Copybara-Service
parent 7bf001a8c9
commit ea2a651911
35 changed files with 559 additions and 339 deletions
+5 -1
View File
@@ -105,7 +105,11 @@ BwuManager::BwuManager(
}
if (config_.allow_upgrade_to.All(false)) {
config_.allow_upgrade_to.web_rtc = true;
config_.allow_upgrade_to.wifi_direct = true;
if (NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_connections_feature::
kEnableWifiDirect)) {
config_.allow_upgrade_to.wifi_direct = true;
}
config_.allow_upgrade_to.wifi_lan = true;
config_.allow_upgrade_to.wifi_hotspot = true;
if (NearbyFlags::GetInstance().GetBoolFlag(
@@ -84,6 +84,9 @@ CreateWifiHotspotCredentials() {
class BwuManagerTest : public ::testing::Test {
protected:
BwuManagerTest() {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kEnableWifiDirect,
true);
// 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);
@@ -202,6 +205,9 @@ class BwuManagerTest : public ::testing::Test {
};
TEST(BwuManagerBaseTest, AllowToUpgradeMedium) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kEnableWifiDirect,
true);
ClientProxy client;
EndpointChannelManager ecm;
EndpointManager em(&ecm);
@@ -915,9 +921,10 @@ TEST_F(BwuManagerTest, InitiateBwu_Revert_OnDisconnect_WifiDirect) {
CreateInitialEndpoint(&client_, kServiceIdA, kEndpointId1, Medium::BLUETOOTH);
ByteArray bytes = parser::ForBwuWifiDirectPathAvailable(
/*ssid=*/"Direct-12345678", /*password=*/"87654321", /*port=*/2143,
/*ssid=*/"", /*password=*/"", /*port=*/2143,
/*frequency=*/2412, /*supports_disabling_encryption=*/false,
/*gateway=*/"123.234.23.1");
/*gateway=*/"123.234.23.1", /*service_name=*/"NC-WifiDirectTest",
/*pin=*/"b592f7d3");
frame.ParseFromString(std::string(bytes));
::nearby::connections::V1Frame* v1_frame = frame.mutable_v1();
@@ -175,9 +175,10 @@ class FakeBwuHandler : public BaseBwuHandler {
}
case location::nearby::proto::connections::WIFI_DIRECT:
return parser::ForBwuWifiDirectPathAvailable(
/*ssid=*/"Direct-12345678", /*password=*/"87654321", /*port=*/2143,
/*ssid=*/"", /*password=*/"", /*port=*/2143,
/*frequency=*/2412, /*supports_disabling_encryption=*/false,
/*gateway=*/"123.234.23.1");
/*gateway=*/"123.234.23.1", /*service_name=*/"NC-WifiDirectTest",
/*pin=*/"b592f7d3");
case location::nearby::proto::connections::UNKNOWN_MEDIUM:
case location::nearby::proto::connections::MDNS:
case location::nearby::proto::connections::BLE:
@@ -103,6 +103,9 @@ constexpr auto kEnableScanningForInstantOnLost =
// Stop BLE_V2 scanning when upgrading to WIFI Hotspot or WFD.
constexpr auto kEnableStopBleScanningOnWifiUpgrade =
flags::Flag<bool>(kConfigPackage, "45687902", false);
// When true, enable Wi-Fi Direct in Nearby connections SDK.
constexpr auto kEnableWifiDirect =
flags::Flag<bool>(kConfigPackage, "45741157", false);
// by default, enable Wi-Fi Hotspot client.
constexpr auto kEnableWifiHotspotClient =
flags::Flag<bool>(kConfigPackage, "45648734", true);
@@ -120,7 +123,6 @@ constexpr auto kSafeToDisconnectVersion =
// When true, use stable endpoint ID.
constexpr auto kUseStableEndpointId =
flags::Flag<bool>(kConfigPackage, "45639298", false);
} // namespace nearby_connections_feature
} // namespace config_package_nearby
} // namespace connections
@@ -16,6 +16,13 @@
#include "connections/implementation/mediums/awdl.h"
#include "connections/implementation/mediums/ble.h"
#include "connections/implementation/mediums/bluetooth_classic.h"
#include "connections/implementation/mediums/bluetooth_radio.h"
#include "connections/implementation/mediums/webrtc.h"
#include "connections/implementation/mediums/wifi.h"
#include "connections/implementation/mediums/wifi_direct.h"
#include "connections/implementation/mediums/wifi_hotspot.h"
#include "connections/implementation/mediums/wifi_lan.h"
namespace nearby {
namespace connections {
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@
namespace nearby {
namespace connections {
namespace {
using ::location::nearby::proto::connections::OperationResultCode;
} // namespace
@@ -102,14 +101,14 @@ bool WifiDirect::IsConnectedToGO() {
return is_connected_to_go_;
}
bool WifiDirect::ConnectWifiDirect(const std::string& ssid,
const std::string& password) {
bool WifiDirect::ConnectWifiDirect(
const WifiDirectCredentials& wifi_direct_credentials) {
MutexLock lock(&mutex_);
if (is_connected_to_go_) {
LOG(INFO) << "No need to connect to GO because it is already connected.";
return true;
}
is_connected_to_go_ = medium_.ConnectWifiDirect(ssid, password);
is_connected_to_go_ = medium_.ConnectWifiDirect(wifi_direct_credentials);
return is_connected_to_go_;
}
@@ -135,10 +134,7 @@ WifiDirectCredentials* WifiDirect::GetCredentials(
<< ". Use default credentials";
return crendential;
}
crendential->SetGateway(it->second.GetIPAddress());
crendential->SetIPAddress(it->second.GetIPAddress());
crendential->SetPort(it->second.GetPort());
it->second.PopulateWifiDirectCredentials(*crendential);
return crendential;
}
@@ -168,7 +164,7 @@ bool WifiDirect::StartAcceptingConnections(
}
// "port=0" to let the platform to select an available port for the socket
WifiDirectServerSocket server_socket = medium_.ListenForService(/*port=*/0);
WifiDirectServerSocket server_socket = medium_.ListenForService();
if (!server_socket.IsValid()) {
LOG(INFO)
<< "Failed to start to listen on WifiDirect GO server for service_id="
@@ -258,8 +254,6 @@ ErrorOr<WifiDirectSocket> WifiDirect::Connect(
const std::string& service_id, const std::string& ip_address, int port,
CancellationFlag* cancellation_flag) {
MutexLock lock(&mutex_);
// Socket to return. To allow for NRVO to work, it has to be a single object.
WifiDirectSocket socket;
if (service_id.empty()) {
LOG(INFO) << "Refusing to create client WifiDirect socket because "
@@ -281,6 +275,8 @@ ErrorOr<WifiDirectSocket> WifiDirect::Connect(
CLIENT_CANCELLATION_CANCEL_WIFI_DIRECT_OUTGOING_CONNECTION)};
}
// Socket to return. To allow for NRVO to work, it has to be a single object.
WifiDirectSocket socket;
socket = medium_.ConnectToService(ip_address, port, cancellation_flag);
if (!socket.IsValid()) {
LOG(INFO) << "Failed to Connect via WifiDirect Server [service_id="
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/expected.h"
#include "internal/platform/multi_thread_executor.h"
@@ -51,7 +52,7 @@ class WifiDirect {
// If WifiDirect Group Owner started
bool IsGOStarted() ABSL_LOCKS_EXCLUDED(mutex_);
// Start WifiDirect Group Owner. Returns true if AutoGO is successfully
// Start WifiDirect Group Owner. Returns true if WifiDirect GO is successfully
// started.
bool StartWifiDirect() ABSL_LOCKS_EXCLUDED(mutex_);
// Stop WifiDirect Group Owner
@@ -60,7 +61,7 @@ class WifiDirect {
// If WifiDirect Group Client connects to Group Owner
bool IsConnectedToGO() ABSL_LOCKS_EXCLUDED(mutex_);
// WifiDirect Group Client request to connect to the Group Owner
bool ConnectWifiDirect(const std::string& ssid, const std::string& password)
bool ConnectWifiDirect(const WifiDirectCredentials& wifi_direct_credentials)
ABSL_LOCKS_EXCLUDED(mutex_);
// WifiDirect Group Client request to disconnect from the Group Owner
bool DisconnectWifiDirect() ABSL_LOCKS_EXCLUDED(mutex_);
@@ -118,7 +119,6 @@ class WifiDirect {
absl::flat_hash_map<std::string, WifiDirectServerSocket> server_sockets_
ABSL_GUARDED_BY(mutex_);
};
} // namespace connections
} // namespace nearby
@@ -1,5 +1,5 @@
// Copyright 2020 Google LLC
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
#include "absl/strings/string_view.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/expected.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/medium_environment.h"
#include "internal/platform/wifi_credential.h"
#include "internal/platform/wifi_direct.h"
@@ -42,8 +43,8 @@ constexpr FeatureFlags kTestCases[] = {
};
constexpr absl::string_view kServiceID{"com.google.location.nearby.apps.test"};
constexpr absl::string_view kSsid{"Direct-357a2d8c"};
constexpr absl::string_view kPassword{"12345678"};
constexpr absl::string_view kServiceName{"NC-WifiDirectTest"};
constexpr absl::string_view kPin{"12345678"};
constexpr absl::string_view kIp = "123.234.23.1";
constexpr const size_t kPort = 20;
@@ -85,11 +86,14 @@ TEST_F(WifiDirectTest, CanStartStopGO) {
}
TEST_F(WifiDirectTest, GCCanConnectDisconnectGO) {
std::string ssid(kSsid);
std::string password(kPassword);
WifiDirectCredentials wifi_direct_credentials;
std::string service_name(kServiceName);
std::string pin(kPin);
wifi_direct_credentials.SetServiceName(service_name);
wifi_direct_credentials.SetPin(pin);
WifiDirect wifi_direct_a;
EXPECT_FALSE(wifi_direct_a.ConnectWifiDirect(ssid, password));
EXPECT_FALSE(wifi_direct_a.ConnectWifiDirect(wifi_direct_credentials));
EXPECT_TRUE(wifi_direct_a.DisconnectWifiDirect());
}
@@ -110,9 +114,7 @@ TEST_P(WifiDirectTest, CanStartGOThatOtherConnect) {
WifiDirectCredentials* wifi_direct_credentials =
wifi_direct_a.GetCredentials(service_id);
EXPECT_TRUE(
wifi_direct_b.ConnectWifiDirect(wifi_direct_credentials->GetSSID(),
wifi_direct_credentials->GetPassword()));
EXPECT_TRUE(wifi_direct_b.ConnectWifiDirect(*wifi_direct_credentials));
EXPECT_TRUE(wifi_direct_b.IsConnectedToGO());
WifiDirectSocket socket_client;
@@ -150,9 +152,7 @@ TEST_P(WifiDirectTest, CanStartGOThatOtherCanCancelConnect) {
WifiDirectCredentials* wifi_direct_credentials =
wifi_direct_a.GetCredentials(service_id);
EXPECT_TRUE(
wifi_direct_b.ConnectWifiDirect(wifi_direct_credentials->GetSSID(),
wifi_direct_credentials->GetPassword()));
EXPECT_TRUE(wifi_direct_b.ConnectWifiDirect(*wifi_direct_credentials));
WifiDirectSocket socket_client;
EXPECT_FALSE(socket_client.IsValid());
@@ -180,10 +180,12 @@ TEST_F(WifiDirectTest, CanStartGOTheOtherFailConnect) {
EXPECT_TRUE(wifi_direct_a.StartWifiDirect());
std::string ssid(kSsid);
std::string password(kPassword);
EXPECT_FALSE(wifi_direct_b.ConnectWifiDirect(ssid, password));
WifiDirectCredentials wifi_direct_credentials;
std::string service_name(kServiceName);
std::string pin(kPin);
wifi_direct_credentials.SetServiceName(service_name);
wifi_direct_credentials.SetPin(pin);
EXPECT_FALSE(wifi_direct_b.ConnectWifiDirect(wifi_direct_credentials));
EXPECT_TRUE(wifi_direct_b.DisconnectWifiDirect());
EXPECT_TRUE(wifi_direct_a.StopWifiDirect());
}
+5 -1
View File
@@ -369,7 +369,9 @@ ByteArray ForBwuWifiDirectPathAvailable(const std::string& ssid,
std::int32_t port,
std::int32_t frequency,
bool supports_disabling_encryption,
const std::string& gateway) {
const std::string& gateway,
const std::string& service_name,
const std::string& pin) {
OfflineFrame frame;
frame.set_version(OfflineFrame::V1);
@@ -390,6 +392,8 @@ ByteArray ForBwuWifiDirectPathAvailable(const std::string& ssid,
wifi_direct_credentials->set_port(port);
wifi_direct_credentials->set_frequency(frequency);
wifi_direct_credentials->set_gateway(gateway);
wifi_direct_credentials->set_service_name(service_name);
wifi_direct_credentials->set_pin(pin);
return ToBytes(std::move(frame));
}
+3 -1
View File
@@ -94,7 +94,9 @@ ByteArray ForBwuWifiDirectPathAvailable(const std::string& ssid,
std::int32_t port,
std::int32_t frequency,
bool supports_disabling_encryption,
const std::string& gateway);
const std::string& gateway,
const std::string& service_name,
const std::string& pin);
ByteArray ForBwuBluetoothPathAvailable(const std::string& service_id,
MacAddress mac_address);
ByteArray ForBwuWebrtcPathAvailable(
@@ -536,11 +536,13 @@ TEST(OfflineFramesTest, CanGenerateBwuWifiDirectPathAvailable) {
upgrade_path_info: <
medium: WIFI_DIRECT
wifi_direct_credentials: <
ssid: "DIRECT-A0-0123456789AB"
password: "password"
ssid: ""
password: ""
port: 1000
frequency: 2412
gateway: "192.168.1.1"
service_name: "NC-WifiDirectTest"
pin: "b592f7d3"
>
supports_disabling_encryption: false
supports_client_introduction_ack: true
@@ -548,7 +550,8 @@ TEST(OfflineFramesTest, CanGenerateBwuWifiDirectPathAvailable) {
>
>)pb";
ByteArray bytes = ForBwuWifiDirectPathAvailable(
"DIRECT-A0-0123456789AB", "password", 1000, 2412, false, "192.168.1.1");
"", "", 1000, 2412, false, "192.168.1.1",
"NC-WifiDirectTest", "b592f7d3");
auto response = FromBytes(bytes);
ASSERT_TRUE(response.ok());
OfflineFrame message = response.result();
@@ -68,6 +68,8 @@ constexpr absl::string_view kWifiDirectSsidPatternString{
constexpr int kWifiDirectSsidMaxLength = 32;
constexpr int kWifiPasswordSsidMinLength = 8;
constexpr int kWifiPasswordSsidMaxLength = 64;
constexpr int kWifiDirectPinMinLength = 4;
constexpr int kWifiDirectPinMaxLength = 16;
inline bool WithinRange(int value, int min, int max) {
return value >= min && value < max;
@@ -282,25 +284,36 @@ Exception EnsureValidBandwidthUpgradeWifiAwarePathAvailableFrame(
Exception EnsureValidBandwidthUpgradeWifiDirectPathAvailableFrame(
const WifiDirectCredentials& wifi_direct_credentials) {
const std::regex ssid_pattern(
std::string(kWifiDirectSsidPatternString).c_str());
if (!wifi_direct_credentials.has_ssid() ||
!(wifi_direct_credentials.ssid().length() < kWifiDirectSsidMaxLength &&
std::regex_match(wifi_direct_credentials.ssid(), ssid_pattern)))
return {Exception::kInvalidProtocolBuffer};
if (!wifi_direct_credentials.has_password() ||
!WithinRange(wifi_direct_credentials.password().length(),
kWifiPasswordSsidMinLength, kWifiPasswordSsidMaxLength))
return {Exception::kInvalidProtocolBuffer};
if (!wifi_direct_credentials.has_frequency() ||
wifi_direct_credentials.frequency() < -1)
return {Exception::kInvalidProtocolBuffer};
const std::regex ssid_pattern(
std::string(kWifiDirectSsidPatternString).c_str());
bool ssid_valid =
wifi_direct_credentials.has_ssid() &&
wifi_direct_credentials.ssid().length() < kWifiDirectSsidMaxLength &&
std::regex_match(wifi_direct_credentials.ssid(), ssid_pattern);
bool password_valid =
wifi_direct_credentials.has_password() &&
WithinRange(wifi_direct_credentials.password().length(),
kWifiPasswordSsidMinLength, kWifiPasswordSsidMaxLength);
bool service_name_valid =
wifi_direct_credentials.has_service_name() &&
wifi_direct_credentials.service_name().length() <
kWifiDirectSsidMaxLength;
bool pin_valid =
wifi_direct_credentials.has_pin() &&
WithinRange(wifi_direct_credentials.pin().length(),
kWifiDirectPinMinLength, kWifiDirectPinMaxLength);
if ((ssid_valid && password_valid) || (service_name_valid && pin_valid))
return {Exception::kSuccess};
return {Exception::kInvalidProtocolBuffer};
// For backwards compatibility reasons, no other fields should be null-checked
// for this frame. Parameter checking (eg. must be within this range) is fine.
return {Exception::kSuccess};
}
Exception EnsureValidBandwidthUpgradeBluetoothPathAvailableFrame(
@@ -51,6 +51,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 absl::string_view kWifiDirectServiceName = "NC-WifiDirectTest";
constexpr absl::string_view kWifiDirectPin = "b592f7d3";
constexpr absl::string_view kGateway = "192.168.1.1";
constexpr int kWifiDirectFrequency = 2412;
constexpr int kPort = 1000;
@@ -726,8 +728,8 @@ TEST(OfflineFramesValidatorTest, ValidatesAsOkBandwidthUpgradeWifiDirect) {
ByteArray bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), std::string(kWifiDirectPassword), kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption,
std::string(kGateway));
kWifiDirectFrequency, kSupportsDisablingEncryption, std::string(kGateway),
std::string(kWifiDirectServiceName), std::string(kWifiDirectPin));
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
@@ -743,7 +745,8 @@ TEST(OfflineFramesValidatorTest,
// Anything less than -1 is invalid
ByteArray bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), std::string(kWifiDirectPassword), kPort, -2,
kSupportsDisablingEncryption, std::string(kGateway));
kSupportsDisablingEncryption, std::string(kGateway),
std::string(kWifiDirectServiceName), std::string(kWifiDirectPin));
offline_frame_1.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame_1);
@@ -753,7 +756,8 @@ TEST(OfflineFramesValidatorTest,
// But -1 itself is not invalid
bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), std::string(kWifiDirectPassword), kPort, -1,
kSupportsDisablingEncryption, std::string(kGateway));
kSupportsDisablingEncryption, std::string(kGateway),
std::string(kWifiDirectServiceName), std::string(kWifiDirectPin));
offline_frame_2.ParseFromString(std::string(bytes));
ret_value = EnsureValidOfflineFrame(offline_frame_2);
@@ -767,10 +771,12 @@ TEST(OfflineFramesValidatorTest,
OfflineFrame offline_frame_2;
std::string wifi_direct_ssid{"DIRECT-A*-0123456789AB"};
std::string wifi_direct_pin_wrong_length = "abc";
ByteArray bytes = ForBwuWifiDirectPathAvailable(
wifi_direct_ssid, std::string(kWifiDirectPassword), kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption,
std::string(kGateway));
std::string(kGateway), std::string(kWifiDirectServiceName),
wifi_direct_pin_wrong_length);
offline_frame_1.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame_1);
@@ -779,10 +785,14 @@ TEST(OfflineFramesValidatorTest,
std::string wifi_direct_ssid_wrong_length =
std::string{kWifiDirectSsid} + "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
std::string wifi_direct_service_name_wrong_length =
std::string{kWifiDirectServiceName} +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
bytes = ForBwuWifiDirectPathAvailable(
wifi_direct_ssid_wrong_length, std::string(kWifiDirectPassword), kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption,
std::string(kGateway));
std::string(kGateway), wifi_direct_service_name_wrong_length,
std::string(kWifiDirectPin));
offline_frame_2.ParseFromString(std::string(bytes));
ret_value = EnsureValidOfflineFrame(offline_frame_2);
@@ -796,10 +806,12 @@ TEST(OfflineFramesValidatorTest,
OfflineFrame offline_frame_2;
std::string short_wifi_direct_password{"Test"};
std::string short_wifi_direct_pin{"abc"};
ByteArray bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), short_wifi_direct_password, kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption,
std::string(kGateway));
std::string(kGateway), std::string(kWifiDirectServiceName),
short_wifi_direct_pin);
offline_frame_1.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame_1);
@@ -809,10 +821,14 @@ TEST(OfflineFramesValidatorTest,
std::string long_wifi_direct_password =
std::string{kWifiDirectSsid} +
"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789";
std::string long_wifi_direct_pin =
std::string{kWifiDirectPin} +
"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789";
bytes = ForBwuWifiDirectPathAvailable(
std::string(kWifiDirectSsid), long_wifi_direct_password, kPort,
kWifiDirectFrequency, kSupportsDisablingEncryption,
std::string(kGateway));
std::string(kGateway), std::string(kWifiDirectServiceName),
long_wifi_direct_pin);
offline_frame_2.ParseFromString(std::string(bytes));
ret_value = EnsureValidOfflineFrame(offline_frame_2);
@@ -49,9 +49,13 @@ P2pPointToPointPcpHandler::GetConnectionMediumsByPriority() {
if (mediums_->GetWifiLan().IsAvailable()) {
mediums.push_back(location::nearby::proto::connections::WIFI_LAN);
}
if (mediums_->GetWifi().IsAvailable() &&
mediums_->GetWifiDirect().IsGCAvailable()) {
mediums.push_back(location::nearby::proto::connections::WIFI_DIRECT);
if (NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_connections_feature::
kEnableWifiDirect)) {
if (mediums_->GetWifi().IsAvailable() &&
mediums_->GetWifiDirect().IsGCAvailable()) {
mediums.push_back(location::nearby::proto::connections::WIFI_DIRECT);
}
}
if (mediums_->GetWifi().IsAvailable() &&
mediums_->GetWifiHotspot().IsClientAvailable()) {
@@ -83,6 +83,12 @@ constexpr BooleanMediumSelector kTestCases[] = {
.wifi_lan = true,
.wifi_hotspot = true,
},
BooleanMediumSelector{
.bluetooth = true,
.ble = true,
.wifi_lan = true,
.wifi_direct = true,
},
BooleanMediumSelector{
.bluetooth = true,
.ble = true,
@@ -100,6 +106,9 @@ class P2pPointToPointPcpHandlerTest
LOG(INFO) << "SetUp: begin";
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kEnableAwdl, true);
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kEnableWifiDirect,
true);
if (advertising_options_.allowed.ble) {
LOG(INFO) << "SetUp: BLE enabled";
}
@@ -44,10 +44,6 @@ P2pStarPcpHandler::GetConnectionMediumsByPriority() {
if (mediums_->GetWifiLan().IsAvailable()) {
mediums.push_back(location::nearby::proto::connections::WIFI_LAN);
}
if (mediums_->GetWifi().IsAvailable() &&
mediums_->GetWifiDirect().IsGCAvailable()) {
mediums.push_back(location::nearby::proto::connections::WIFI_DIRECT);
}
if (mediums_->GetWifi().IsAvailable() &&
mediums_->GetWifiHotspot().IsClientAvailable()) {
mediums.push_back(location::nearby::proto::connections::WIFI_HOTSPOT);
@@ -329,10 +329,16 @@ message BandwidthUpgradeNegotiationFrame {
// Windows only supports WifiDirect with Service Discovey. Its
// credentials is the service_name/pin.
optional string service_name = 7;
// The pin is exactly 8 digits. The first 7 digits are the PIN. The last 1
// digit is a checksum calculated using a specific algorithm (CRC-8). The
// WifiDirect spec requires that pin is exactly 8 digits. The first 7
// digits are the PIN. The last 1 digit is a checksum calculated using a
// specific algorithm (CRC-8). However, the Windows WinRT
// WiFiDirectServiceAdvertiser::ConnectAsync() that we use does NOT
// enforce the CRC-8 checksum for a WPS PIN because: 1. The ConnectAsync
// PIN is NOT necessarily a WPS PIN. 2. WPS PIN validation is performed by
// the Wi-Fi driver/firmware. 3. WFDS connections often bypass or replace
// WPS PIN authentication
// pin is exchanged in the connection handshake stage, but we create and
// save it beforw starting GO, so we can send it to GC side for
// save it before starting GO, so we can send it to GC side for
// authentication.
optional string pin = 8;
}
@@ -1431,6 +1431,9 @@ TEST(ServiceControllerRouterCheckHpRealtekDeviceTest,
TEST(ServiceControllerRouterCheckHpRealtekDeviceTest,
notHPRealtekDevice_defaultBwuConfig) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::kEnableWifiDirect,
true);
ServiceControllerRouter router(
absl::AnyInvocable<bool()>{[]() { return false; }});
auto service_controller = router.GetServiceController();
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -41,12 +41,14 @@ namespace {
using ::location::nearby::connections::BandwidthUpgradeNegotiationFrame;
using ::location::nearby::proto::connections::OperationResultCode;
} // namespace
WifiDirectBwuHandler::WifiDirectBwuHandler(
Mediums& mediums, IncomingConnectionCallback incoming_connection_callback)
: BaseBwuHandler(std::move(incoming_connection_callback)),
mediums_(mediums) {}
// Called by BWU initiator. Set up WifiDirect upgraded medium for this
// endpoint, and returns an upgrade path info (ServiceName, Pin for Wifi WPS,
// Gateway used as IPAddress, Port) for remote party to perform connection.
ByteArray WifiDirectBwuHandler::HandleInitializeUpgradedMediumForEndpoint(
ClientProxy* client, const std::string& upgrade_service_id,
const std::string& endpoint_id) {
@@ -82,19 +84,29 @@ ByteArray WifiDirectBwuHandler::HandleInitializeUpgradedMediumForEndpoint(
wifi_direct_medium_.GetCredentials(upgrade_service_id);
std::string ssid = wifi_direct_crendential->GetSSID();
std::string password = wifi_direct_crendential->GetPassword();
std::string service_name = wifi_direct_crendential->GetServiceName();
std::string pin = wifi_direct_crendential->GetPin();
std::string gateway = wifi_direct_crendential->GetGateway();
int port = wifi_direct_crendential->GetPort();
int freq = wifi_direct_crendential->GetFrequency();
LOG(INFO) << "Start WifiDirect GO with SSID: " << ssid
<< ", Password: " << masker::Mask(password) << ", Port: " << port
<< ", Gateway: " << gateway << ", Frequency: " << freq;
if (ssid.empty()) {
LOG(INFO) << "Start WifiDirect GO with ServiceName: " << service_name
<< ", pin: " << masker::Mask(pin) << ", Port: " << port
<< ", Gateway: " << gateway << ", Frequency: " << freq;
} else {
LOG(INFO) << "Start WifiDirect GO with SSID: " << ssid
<< ", Password: " << masker::Mask(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);
/* supports_disabling_encryption */ disabling_encryption, gateway,
service_name, pin);
}
void WifiDirectBwuHandler::HandleRevertInitiatorStateForService(
@@ -124,14 +136,34 @@ WifiDirectBwuHandler::CreateUpgradedEndpointChannel(
const std::string& ssid = upgrade_path_info_credentials.ssid();
const std::string& password = upgrade_path_info_credentials.password();
const std::string& service_name =
upgrade_path_info_credentials.service_name();
const std::string& pin = upgrade_path_info_credentials.pin();
std::int32_t port = upgrade_path_info_credentials.port();
const std::string& gateway = upgrade_path_info_credentials.gateway();
std::int32_t freq = upgrade_path_info_credentials.frequency();
LOG(INFO) << "Received WifiDirect credential SSID: " << ssid
<< ", Password:" << masker::Mask(password) << ", Port:" << port
<< ", Gateway:" << gateway;
WifiDirectCredentials wifi_direct_credentials;
wifi_direct_credentials.SetSSID(ssid);
wifi_direct_credentials.SetPassword(password);
wifi_direct_credentials.SetServiceName(service_name);
wifi_direct_credentials.SetPin(pin);
wifi_direct_credentials.SetPort(port);
wifi_direct_credentials.SetGateway(gateway);
wifi_direct_credentials.SetFrequency(freq);
if (!wifi_direct_medium_.ConnectWifiDirect(ssid, password)) {
if (ssid.empty()) {
LOG(INFO) << "Received WifiDirect credential ServiceName: " << service_name
<< ", pin: " << masker::Mask(pin) << ", Port: " << port
<< ", Gateway: " << gateway << ", Frequency: " << freq;
} else {
LOG(INFO) << "Received WifiDirect credential SSID: " << ssid
<< ", Password: " << masker::Mask(password)
<< ", Port: " << port << ", Gateway: " << gateway
<< ", Frequency: " << freq;
}
if (!wifi_direct_medium_.ConnectWifiDirect(wifi_direct_credentials)) {
LOG(ERROR) << "Connect to WifiDiret GO failed";
return {Error(
OperationResultCode::CONNECTIVITY_WIFI_DIRECT_INVALID_CREDENTIAL)};
@@ -148,7 +180,7 @@ WifiDirectBwuHandler::CreateUpgradedEndpointChannel(
VLOG(1)
<< "WifiDirectBwuHandler successfully connected to WifiDirect service ("
<< port << ") while upgrading endpoint " << endpoint_id;
<< gateway << ":" << port << ") while upgrading endpoint " << endpoint_id;
// Create a new WifiDirectEndpointChannel.
return {std::make_unique<WifiDirectEndpointChannel>(
@@ -168,6 +200,5 @@ void WifiDirectBwuHandler::OnIncomingWifiDirectConnection(
});
NotifyOnIncomingConnection(client, std::move(connection));
}
} // namespace connections
} // namespace nearby
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -23,12 +23,10 @@
#include "connections/implementation/client_proxy.h"
#include "connections/implementation/endpoint_channel.h"
#include "connections/implementation/mediums/mediums.h"
#include "connections/implementation/mediums/wifi.h"
#include "connections/implementation/mediums/wifi_direct.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/expected.h"
#include "internal/platform/wifi_direct.h"
#include "utility"
namespace nearby {
namespace connections {
@@ -89,7 +87,6 @@ class WifiDirectBwuHandler : public BaseBwuHandler {
WifiDirectSocket socket);
Mediums& mediums_;
Wifi& wifi_medium_ = mediums_.GetWifi();
WifiDirect& wifi_direct_medium_ = mediums_.GetWifiDirect();
};
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -30,7 +30,6 @@
#include "internal/platform/count_down_latch.h"
#include "internal/platform/exception.h"
#include "internal/platform/expected.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/logging.h"
#include "internal/platform/medium_environment.h"
#include "internal/platform/single_thread_executor.h"
@@ -85,18 +84,12 @@ TEST_F(WifiDirectTest, WFDGOBWUInit_GCCreateEndpointChannel) {
mutable_connection) {
LOG(INFO) << "Server socket connection accept call back, Socket name: "
<< mutable_connection->socket->ToString();
std::shared_ptr<BwuHandler::IncomingSocketConnection> connection(
mutable_connection.release());
accept_latch.CountDown();
EXPECT_TRUE(end_latch.Await(kWaitDuration).result());
connection->channel->Close();
connection->socket->Close();
});
SingleThreadExecutor wfd_go_executor;
wfd_go_executor.Execute([&wfd_go_bwu_handler, &wifi_direct_go, &upgrade_frame,
&start_latch]() {
wfd_go_executor.Execute([&]() {
ByteArray upgrade_path_available_frame =
wfd_go_bwu_handler->InitializeUpgradedMediumForEndpoint(
&wifi_direct_go, std::string(kServiceID), std::string(kEndpointID));
+1
View File
@@ -118,6 +118,7 @@ class FeatureFlags {
std::uint32_t connection_max_frame_length = 1048576;
std::uint32_t blocking_queue_stream_queue_capacity = 10;
bool support_web_rtc_non_cellular_medium = false;
std::uint32_t wifi_direct_default_port = 63034;
};
static const FeatureFlags& GetInstance() {
@@ -19,12 +19,14 @@
#include <string>
#include <utility>
#include "absl/functional/any_invocable.h"
#include "absl/log/check.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/cancellation_flag_listener.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/wifi_direct.h"
#include "internal/platform/logging.h"
@@ -110,6 +112,14 @@ Exception WifiDirectServerSocket::DoClose() {
return {Exception::kSuccess};
}
void WifiDirectServerSocket::PopulateWifiDirectCredentials(
WifiDirectCredentials& wifi_direct_credentials) {
absl::MutexLock lock(mutex_);
wifi_direct_credentials.SetGateway(ip_address_);
wifi_direct_credentials.SetPort(port_);
}
// Code for WifiDirectMedium
WifiDirectMedium::WifiDirectMedium() {
auto& env = MediumEnvironment::Instance();
@@ -125,13 +135,13 @@ bool WifiDirectMedium::StartWifiDirect(
WifiDirectCredentials* wifi_direct_credentials) {
absl::MutexLock lock(mutex_);
std::string ssid = absl::StrCat("DIRECT-", Prng().NextUint32());
wifi_direct_credentials->SetSSID(ssid);
std::string password = absl::StrFormat("%08x", Prng().NextUint32());
wifi_direct_credentials->SetPassword(password);
std::string service_name = absl::StrCat("NC-", Prng().NextUint32());
wifi_direct_credentials->SetServiceName(service_name);
std::string pin = absl::StrFormat("%04x", Prng().NextUint32());
wifi_direct_credentials->SetPin(pin);
LOG(INFO) << "G3 StartWifiDirect GO: ssid=" << ssid
<< ", password:" << password;
LOG(INFO) << "G3 StartWifiDirect GO: service_name:" << service_name
<< ", pin:" << pin;
auto& env = MediumEnvironment::Instance();
env.UpdateWifiDirectMediumForStartOrConnect(*this, wifi_direct_credentials,
@@ -152,24 +162,24 @@ bool WifiDirectMedium::StopWifiDirect() {
}
bool WifiDirectMedium::ConnectWifiDirect(
WifiDirectCredentials* wifi_direct_credentials) {
const WifiDirectCredentials& wifi_direct_credentials) {
absl::MutexLock lock(mutex_);
LOG(INFO) << "G3 ConnectWifiDirect : ssid="
<< wifi_direct_credentials->GetSSID()
<< ", password:" << wifi_direct_credentials->GetPassword();
LOG(INFO) << "G3 ConnectWifiDirect : service_name:"
<< wifi_direct_credentials.GetServiceName()
<< ", pin:" << wifi_direct_credentials.GetPin();
auto& env = MediumEnvironment::Instance();
auto* remote_medium = static_cast<WifiDirectMedium*>(
env.GetWifiDirectMedium(wifi_direct_credentials->GetSSID(), {}));
env.GetWifiDirectMedium(wifi_direct_credentials.GetServiceName(), ""));
if (!remote_medium) {
env.UpdateWifiDirectMediumForStartOrConnect(*this, wifi_direct_credentials,
env.UpdateWifiDirectMediumForStartOrConnect(*this, &wifi_direct_credentials,
/*is_go=*/false,
/*enabled=*/false);
return false;
}
env.UpdateWifiDirectMediumForStartOrConnect(*this, wifi_direct_credentials,
env.UpdateWifiDirectMediumForStartOrConnect(*this, &wifi_direct_credentials,
/*is_go=*/false,
/*enabled=*/true);
return true;
@@ -198,7 +208,7 @@ std::unique_ptr<api::WifiDirectSocket> WifiDirectMedium::ConnectToService(
auto* remote_medium =
static_cast<WifiDirectMedium*>(env.GetWifiDirectMedium({}, ip_address));
if (remote_medium == nullptr) {
return nullptr;
return {};
}
WifiDirectServerSocket* server_socket = nullptr;
@@ -214,21 +224,32 @@ std::unique_ptr<api::WifiDirectSocket> WifiDirectMedium::ConnectToService(
LOG(ERROR) << "G3 WifiDirect Failed to find WifiDirect Server "
"socket: socket_name="
<< socket_name;
return nullptr;
return {};
}
}
if (cancellation_flag->Cancelled()) {
LOG(ERROR) << "G3 WifiDirect Connect: Has been cancelled: socket_name="
<< socket_name;
return nullptr;
return {};
}
CancellationFlagListener listener(cancellation_flag, [&server_socket]() {
LOG(INFO) << "G3 WifiDirect Cancel Connect.";
if (server_socket != nullptr) {
server_socket->Close();
}
});
auto socket = std::make_unique<WifiDirectSocket>();
// Finally, Request to connect to this socket.
server_socket->Connect(*socket);
LOG(INFO) << "G3 WifiDirect GC ConnectToService: connected: socket="
if (!server_socket->Connect(*socket)) {
LOG(ERROR) << "G3 WifiDirect Failed to connect to existing WifiDirect "
"Server socket: name="
<< socket_name;
return {};
}
LOG(INFO) << "G3 WifiDirect ConnectToService: connected: socket="
<< socket.get();
return socket;
}
@@ -247,9 +268,10 @@ std::unique_ptr<api::WifiDirectServerSocket> WifiDirectMedium::ListenForService(
dot_decimal_ip.pop_back();
server_socket->SetIPAddress(dot_decimal_ip);
server_socket->SetPort(port == 0 ? env.GetFakePort() : port);
std::string socket_name = WifiDirectServerSocket::GetName(
server_socket->GetIPAddress(), server_socket->GetPort());
int port_to_use = port == 0 ? env.GetFakePort() : port;
server_socket->SetPort(port_to_use);
std::string socket_name =
WifiDirectServerSocket::GetName(dot_decimal_ip, port_to_use);
server_socket->SetCloseNotifier([this, socket_name]() {
absl::MutexLock lock(mutex_);
server_sockets_.erase(socket_name);
@@ -15,17 +15,26 @@
#ifndef PLATFORM_IMPL_G3_WIFI_DIRECT_H_
#define PLATFORM_IMPL_G3_WIFI_DIRECT_H_
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/g3/multi_thread_executor.h"
#include "internal/platform/implementation/g3/socket_base.h"
#include "internal/platform/implementation/wifi_direct.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/wifi_credential.h"
namespace nearby {
namespace g3 {
@@ -112,6 +121,12 @@ class WifiDirectServerSocket : public api::WifiDirectServerSocket {
// Calls close_notifier if it was previously set, and marks socket as closed.
Exception Close() override ABSL_LOCKS_EXCLUDED(mutex_);
// Populates the provided `wifi_direct_credentials` with the IP address
// and port of this server socket.
void PopulateWifiDirectCredentials(
WifiDirectCredentials& wifi_direct_credentials) override
ABSL_LOCKS_EXCLUDED(mutex_);
private:
// Retrieves IP addresses from local machine
std::vector<std::string> GetIpAddresses() const;
@@ -158,7 +173,7 @@ class WifiDirectMedium : public api::WifiDirectMedium {
bool StopWifiDirect() override;
// Discoverer connects to the WiFiDirect GO
bool ConnectWifiDirect(
WifiDirectCredentials* wifi_direct_credentials) override;
const WifiDirectCredentials& wifi_direct_credentials) override;
// Discoverer disconnects from the WiFiDirect GO
bool DisconnectWifiDirect() override;
+10 -1
View File
@@ -15,11 +15,15 @@
#ifndef PLATFORM_API_WIFI_DIRECT_H_
#define PLATFORM_API_WIFI_DIRECT_H_
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/exception.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/wifi_credential.h"
@@ -67,6 +71,11 @@ class WifiDirectServerSocket {
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
virtual Exception Close() = 0;
// Populates the WifiDirect credentials with the server socket's service
// addresses and ports.
virtual void PopulateWifiDirectCredentials(
WifiDirectCredentials& wifi_direct_credentials) = 0;
};
// Container of operations that can be performed over the WifiLan medium.
@@ -104,7 +113,7 @@ class WifiDirectMedium {
// Client device connect to a softAP with specified credential.
virtual bool ConnectWifiDirect(
WifiDirectCredentials* wifi_direct_credentials) = 0;
const WifiDirectCredentials& wifi_direct_credentials) = 0;
virtual bool DisconnectWifiDirect() = 0;
// Returns the port range as a pair of min and max port.
@@ -74,8 +74,8 @@
#include "internal/platform/implementation/windows/string_utils.h"
#include "internal/platform/implementation/windows/submittable_executor.h"
#include "internal/platform/implementation/windows/timer.h"
#include "internal/platform/implementation/windows/utils.h"
#include "internal/platform/implementation/windows/wifi.h"
#include "internal/platform/implementation/windows/wifi_direct.h"
#include "internal/platform/implementation/windows/wifi_hotspot.h"
#include "internal/platform/implementation/windows/wifi_lan.h"
#include "internal/platform/logging.h"
@@ -284,7 +284,7 @@ ImplementationPlatform::CreateWifiHotspotMedium() {
std::unique_ptr<WifiDirectMedium>
ImplementationPlatform::CreateWifiDirectMedium() {
return nullptr;
return std::make_unique<windows::WifiDirectMedium>();
}
// TODO(b/261663238) replace with real implementation.
@@ -29,18 +29,20 @@
// Nearby connections headers
#include "absl/base/nullability.h"
#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/types/optional.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/wifi_direct.h"
#include "internal/platform/implementation/windows/nearby_client_socket.h"
#include "internal/platform/implementation/windows/nearby_server_socket.h"
#include "internal/platform/implementation/windows/socket_address.h"
#include "internal/platform/implementation/windows/submittable_executor.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/wifi_credential.h"
// WinRT headers
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.Enumeration.h"
@@ -78,10 +80,10 @@ using ::winrt::Windows::Foundation::AsyncStatus;
using ::winrt::Windows::Foundation::IInspectable;
// WifiDirectSocket wraps the socket functions to read and write stream.
// In WiFi HOTSPOT, A WifiDirectSocket will be passed to
// On WiFiDirect GO serverside, a WifiDirectSocket will be passed to
// StartAcceptingConnections's callback when Winsock Server Socket receives a
// new connection. When call API to connect to remote WiFi Hotspot service, also
// will return a WifiDirectSocket to caller.
// new connection. When client side call API to connect to remote WiFi
// WifiDirect GO service, it will return a WifiDirectServiceSocket to caller.
class WifiDirectSocket : public api::WifiDirectSocket {
public:
WifiDirectSocket();
@@ -113,42 +115,6 @@ class WifiDirectSocket : public api::WifiDirectSocket {
}
private:
// A simple wrapper to handle input stream of socket
class SocketInputStream : public InputStream {
public:
explicit SocketInputStream(NearbyClientSocket* absl_nonnull client_socket)
: client_socket_(client_socket) {}
~SocketInputStream() override = default;
ExceptionOr<ByteArray> Read(std::int64_t size) override {
return client_socket_->Read(size);
}
ExceptionOr<size_t> Skip(size_t offset) override {
return client_socket_->Skip(offset);
}
Exception Close() override { return client_socket_->Close(); }
private:
NearbyClientSocket* absl_nonnull const client_socket_;
};
// A simple wrapper to handle output stream of socket
class SocketOutputStream : public OutputStream {
public:
explicit SocketOutputStream(NearbyClientSocket* absl_nonnull client_socket)
: client_socket_(client_socket) {}
~SocketOutputStream() override = default;
Exception Write(const ByteArray& data) override {
return client_socket_->Write(data);
}
Exception Flush() override { return client_socket_->Flush(); }
Exception Close() override { return client_socket_->Close(); }
private:
NearbyClientSocket* absl_nonnull const client_socket_;
};
absl_nonnull std::unique_ptr<NearbyClientSocket> client_socket_;
SocketInputStream input_stream_;
SocketOutputStream output_stream_;
@@ -158,15 +124,14 @@ class WifiDirectSocket : public api::WifiDirectSocket {
// server socket accepts connection from clients.
class WifiDirectServerSocket : public api::WifiDirectServerSocket {
public:
explicit WifiDirectServerSocket(int port = 0);
WifiDirectServerSocket(const WifiDirectServerSocket&) = default;
WifiDirectServerSocket(WifiDirectServerSocket&&) = default;
WifiDirectServerSocket() = default;
~WifiDirectServerSocket() override;
WifiDirectServerSocket& operator=(const WifiDirectServerSocket&) = default;
WifiDirectServerSocket(WifiDirectServerSocket&&) = default;
WifiDirectServerSocket& operator=(WifiDirectServerSocket&&) = default;
std::string GetIPAddress() const override;
int GetPort() const override;
int GetPort() const override { return server_socket_.GetPort(); }
// Blocks until either:
// - at least one incoming connection request is available, or
@@ -179,83 +144,69 @@ class WifiDirectServerSocket : public api::WifiDirectServerSocket {
// Called by the server side of a connection before passing ownership of
// WifiDirectServerSocker to user, to track validity of a pointer to
// this server socket.
void SetCloseNotifier(absl::AnyInvocable<void()> notifier);
void SetCloseNotifier(absl::AnyInvocable<void()> notifier) {
server_socket_.SetCloseNotifier(std::move(notifier));
}
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
Exception Close() override;
// Binds to local port
bool Listen(bool dual_stack, std::string& ip_address);
// Populates the provided `wifi_direct_credentials` with the IP address
// and port of this server socket.
void PopulateWifiDirectCredentials(
WifiDirectCredentials& wifi_direct_credentials) override;
NearbyServerSocket server_socket_;
void SetIPAddress(std::string ip_address);
// Binds to local port
bool Listen(int port, bool dual_stack);
private:
// Retrieves hotspot IP address from local machine
// Retrieves WifiDirect GO IP address from local machine
std::string GetWifiDirectIpAddress() const;
const int port_;
mutable absl::Mutex mutex_;
// Close notifier
absl::AnyInvocable<void()> close_notifier_ = nullptr;
absl::CondVar is_listen_ready_;
bool is_listen_started_ ABSL_GUARDED_BY(mutex_) = false;
// IP addresses of the server socket.
std::string wifi_direct_ipaddr_ = {};
bool closed_ = false;
NearbyServerSocket server_socket_;
};
class WifiDirectDiscovered {
public:
explicit WifiDirectDiscovered(const DeviceInformation& device_info);
~WifiDirectDiscovered() = default;
WifiDirectDiscovered(WifiDirectDiscovered&&) = default;
WifiDirectDiscovered& operator=(WifiDirectDiscovered&&) = default;
std::string GetId() { return id_; }
DeviceInformation GetDeviceInformation() {
return windows_wifi_direct_device_;
}
private:
DeviceInformation windows_wifi_direct_device_;
// Once the device is lost, we can no longer access it's id.
std::string id_;
// Once the device is lost, we can no longer access it's mac address.
// std::string name_;
};
class WifiDirectMedium {
class WifiDirectMedium : public api::WifiDirectMedium {
public:
WifiDirectMedium();
~WifiDirectMedium();
~WifiDirectMedium() override;
// WifiDirectMedium is neither copyable nor movable.
WifiDirectMedium(const WifiDirectMedium&) = delete;
WifiDirectMedium& operator=(const WifiDirectMedium&) = delete;
// If the WiFi Adaptor supports to start WifiDirect Service GO.
bool IsInterfaceValid() const;
bool IsInterfaceValid() const override;
// Discoverer connects to server socket
std::unique_ptr<api::WifiDirectSocket> ConnectToService(
absl::string_view ip_address, int port,
CancellationFlag* cancellation_flag);
CancellationFlag* cancellation_flag) override;
// Advertiser starts to listen on server socket
std::unique_ptr<api::WifiDirectServerSocket> ListenForService(int port);
std::unique_ptr<api::WifiDirectServerSocket> ListenForService(
int port) override;
// Starts to advertising
bool StartWifiDirect();
// Stops to advertising
bool StopWifiDirect();
// Connects to a WifiDirect
bool ConnectWifiDirect();
// Disconnects from a WifiDirect
bool DisconnectWifiDirect();
// Advertiser start WiFiDirect GO with specific Credentials.
bool StartWifiDirect(WifiDirectCredentials* wifi_direct_credentials) override;
// Advertiser stop the current WiFiDirect GO.
bool StopWifiDirect() override;
// Discoverer connects to the WifiDirect GO as GC.
bool ConnectWifiDirect(
const WifiDirectCredentials& wifi_direct_credentials) override;
// Discoverer disconnects from the connected WifiDirect GO.
bool DisconnectWifiDirect() override;
absl::optional<std::pair<std::int32_t, std::int32_t>> GetDynamicPortRange() {
absl::optional<std::pair<std::int32_t, std::int32_t>> GetDynamicPortRange()
override {
return absl::nullopt;
}
@@ -263,7 +214,7 @@ class WifiDirectMedium {
enum Value : char {
kMediumStatusIdle = 0,
kMediumStatusAccepting = (1 << 0),
kMediumStatusServiceStarted = (1 << 1),
kMediumStatusGOStarted = (1 << 1),
kMediumStatusConnecting = (1 << 2),
kMediumStatusConnected = (1 << 3),
};
@@ -273,9 +224,9 @@ class WifiDirectMedium {
bool IsIdle() { return medium_status_ == kMediumStatusIdle; }
// Advertiser is accepting connection on server socket
bool IsAccepting() { return (medium_status_ & kMediumStatusAccepting) != 0; }
// Advertiser started WifiDirect
bool IsServiceStarted() {
return (medium_status_ & kMediumStatusServiceStarted) != 0;
// Advertiser started WifiDirect GO
bool IsGOStarted() {
return (medium_status_ & kMediumStatusGOStarted) != 0;
}
// Discoverer is connecting with the WifiDirect
bool IsConnecting() {
@@ -326,6 +277,9 @@ class WifiDirectMedium {
IInspectable inspectable);
fire_and_forget Watcher_DeviceStopped(DeviceWatcher sender,
IInspectable inspectable);
WifiDirectCredentials* credentials_go_ = nullptr;
WifiDirectCredentials credentials_gc_;
std::string ip_address_local_;
std::string ip_address_remote_;
@@ -334,12 +288,6 @@ class WifiDirectMedium {
// Keep the server socket listener pointer
WifiDirectServerSocket* server_socket_ptr_ ABSL_GUARDED_BY(mutex_) = nullptr;
SubmittableExecutor listener_executor_;
absl::flat_hash_map<winrt::hstring, std::unique_ptr<WifiDirectDiscovered>>
discovered_devices_by_id_;
absl::flat_hash_map<winrt::hstring, std::unique_ptr<WifiDirectDiscovered>>
connection_requested_devices_by_id_;
};
} // namespace nearby::windows
@@ -19,24 +19,25 @@
#include <string_view>
#include <utility>
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
#include "internal/flags/nearby_flags.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/cancellation_flag_listener.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/flags/nearby_platform_feature_flags.h"
#include "internal/platform/implementation/wifi_direct.h"
#include "internal/platform/implementation/windows/socket_address.h"
#include "internal/platform/implementation/windows/utils.h"
#include "internal/platform/implementation/windows/wifi_direct.h"
#include "internal/platform/logging.h"
#include "internal/platform/prng.h"
#include "internal/platform/wifi_credential.h"
namespace nearby {
namespace windows {
namespace {
constexpr std::wstring_view kServiceName = L"QuickShare";
constexpr std::wstring_view kPin = L"1234";
constexpr int kWaitingForConnectionTimeoutSeconds = 90; // seconds
} // namespace
@@ -193,11 +194,12 @@ std::unique_ptr<api::WifiDirectSocket> WifiDirectMedium::ConnectToService(
// Advertiser starts to listen on server socket
std::unique_ptr<api::WifiDirectServerSocket> WifiDirectMedium::ListenForService(
int port) {
LOG(INFO) << "WifiDirectMedium::ListenForService";
LOG(INFO) << __func__
<< " :Start to listen connection from WiFiDirect client.";
absl::MutexLock lock(mutex_);
if (!IsServiceStarted()) {
LOG(WARNING) << "WifiDirect service is not started, skip.";
if (!IsGOStarted()) {
LOG(WARNING) << "WifiDirect GO is not started, skip.";
return nullptr;
}
// check current status
@@ -207,14 +209,14 @@ std::unique_ptr<api::WifiDirectServerSocket> WifiDirectMedium::ListenForService(
return nullptr;
}
auto server_socket = std::make_unique<WifiDirectServerSocket>(port);
auto server_socket = std::make_unique<WifiDirectServerSocket>();
server_socket_ptr_ = server_socket.get();
// Start to listen on server socket in a separate thread. Before GC
// connects to GO, GO doesn't have IP address. BWU calls this API right away
// after it starts GO, we need to spin out the following logic to another
// thread to avoid blocking BWU sending out of band upgrade frame to GC.
listener_executor_.Execute([this]() mutable {
listener_executor_.Execute([this, port]() mutable {
absl::MutexLock lock(mutex_);
bool dual_stack = NearbyFlags::GetInstance().GetBoolFlag(
platform::config_package_nearby::nearby_platform_feature::
@@ -239,9 +241,12 @@ std::unique_ptr<api::WifiDirectServerSocket> WifiDirectMedium::ListenForService(
LOG(INFO) << "IP address is ready.";
}
}
server_socket_ptr_->SetIPAddress(ip_address_local_);
if (port == 0) {
port = FeatureFlags::GetInstance().GetFlags().wifi_direct_default_port;
}
if (server_socket_ptr_ &&
server_socket_ptr_->Listen(dual_stack, ip_address_local_)) {
server_socket_ptr_->Listen(port, dual_stack)) {
medium_status_ |= kMediumStatusAccepting;
// Setup close notifier after listen started.
@@ -267,17 +272,27 @@ std::unique_ptr<api::WifiDirectServerSocket> WifiDirectMedium::ListenForService(
return server_socket;
}
bool WifiDirectMedium::StartWifiDirect() {
bool WifiDirectMedium::StartWifiDirect(
WifiDirectCredentials* wifi_direct_credentials) {
LOG(INFO) << "WifiDirectMedium::StartWifiDirect";
absl::MutexLock lock(mutex_);
if (IsServiceStarted()) {
LOG(WARNING) << "Already started WifiDirect service, skip.";
if (IsGOStarted()) {
LOG(WARNING) << "Already started WifiDirect GO, skip.";
return true;
}
credentials_go_ = wifi_direct_credentials;
Prng prng;
std::string pin = absl::StrFormat("%04x", prng.NextUint32());
credentials_go_->SetPin(pin);
std::string service_name = "NC-" + std::to_string(prng.NextUint32());
credentials_go_->SetServiceName(service_name);
LOG(INFO) << "service_name:pin " << service_name << ":" << pin;
// Create Advertiser object
advertiser_ = WiFiDirectServiceAdvertiser(kServiceName);
advertiser_ = WiFiDirectServiceAdvertiser(winrt::to_hstring(service_name));
advertisement_status_changed_token_ = advertiser_.AdvertisementStatusChanged(
{this, &WifiDirectMedium::OnAdvertisementStatusChanged});
auto_accept_session_connected_token_ = advertiser_.AutoAcceptSessionConnected(
@@ -290,7 +305,7 @@ bool WifiDirectMedium::StartWifiDirect() {
advertiser_.ServiceStatus(WiFiDirectServiceStatus::Available);
// Config Methods
WiFiDirectServiceConfigurationMethod config_method;
if (kPin.empty()) {
if (pin.empty()) {
config_method = WiFiDirectServiceConfigurationMethod::Default; // NOLINT
} else {
config_method = WiFiDirectServiceConfigurationMethod::PinDisplay;
@@ -306,7 +321,7 @@ bool WifiDirectMedium::StartWifiDirect() {
WiFiDirectServiceAdvertisementStatus::Created) ||
(advertiser_.AdvertisementStatus() ==
WiFiDirectServiceAdvertisementStatus::Started)) {
medium_status_ |= kMediumStatusServiceStarted;
medium_status_ |= kMediumStatusGOStarted;
return true;
}
LOG(ERROR) << "Start WifiDirect GO failed.";
@@ -331,7 +346,7 @@ bool WifiDirectMedium::StartWifiDirect() {
bool WifiDirectMedium::StopWifiDirect() {
LOG(INFO) << "WifiDirectMedium::StopWifiDirect";
absl::MutexLock lock(mutex_);
if (!IsServiceStarted()) {
if (!IsGOStarted()) {
LOG(WARNING) << "Cannot stop Service because no Service is started.";
return true;
}
@@ -348,9 +363,11 @@ bool WifiDirectMedium::StopWifiDirect() {
device_info_ = nullptr;
session_ = nullptr;
}
medium_status_ &= (~kMediumStatusServiceStarted);
medium_status_ &= (~kMediumStatusGOStarted);
medium_status_ &= (~kMediumStatusConnected);
server_socket_ptr_ = nullptr;
ip_address_local_.clear();
ip_address_remote_.clear();
listener_executor_.Shutdown();
return true;
} catch (std::exception exception) {
@@ -465,10 +482,12 @@ fire_and_forget WifiDirectMedium::OnSessionRequested(
absl::MutexLock lock(mutex_);
WiFiDirectServiceSession session = nullptr;
if (kPin.empty()) {
auto pin = credentials_go_->GetPin();
if (pin.empty()) {
session = advertiser_.ConnectAsync(device_info_).get(); // NOLINT
} else {
session = advertiser_.ConnectAsync(device_info_, kPin).get();
session = advertiser_.ConnectAsync(device_info_, winrt::to_hstring(pin))
.get();
}
LOG(INFO) << "GO: TryEnqueue: Wait for ConnectAsync finish";
if (!session) {
@@ -519,7 +538,8 @@ fire_and_forget WifiDirectMedium::OnSessionRequested(
}
}
bool WifiDirectMedium::ConnectWifiDirect() {
bool WifiDirectMedium::ConnectWifiDirect(
const WifiDirectCredentials& credentials) {
LOG(INFO) << "WifiDirectMedium::ConnectWifiDirect";
absl::MutexLock lock(mutex_);
if (IsConnecting()) {
@@ -533,10 +553,9 @@ bool WifiDirectMedium::ConnectWifiDirect() {
return false;
}
discovered_devices_by_id_.clear();
connection_requested_devices_by_id_.clear();
winrt::hstring device_selector = WiFiDirectService::GetSelector(kServiceName);
credentials_gc_ = credentials;
winrt::hstring device_selector = WiFiDirectService::GetSelector(
winrt::to_hstring(credentials_gc_.GetServiceName()));
const winrt::param::iterable<winrt::hstring> requested_properties =
winrt::single_threaded_vector<winrt::hstring>({
winrt::to_hstring("System.Devices.WiFiDirectServices.ServiceAddress"),
@@ -590,7 +609,8 @@ fire_and_forget WifiDirectMedium::Watcher_DeviceAdded(
service_.PreferGroupOwnerMode(false);
WiFiDirectServiceSession session = nullptr;
if (kPin.empty()) {
auto pin = credentials_gc_.GetPin();
if (pin.empty()) {
session = service_.ConnectAsync().get(); // NOLINT
} else {
auto prov_info = co_await service_.GetProvisioningInfoAsync(
@@ -605,7 +625,7 @@ fire_and_forget WifiDirectMedium::Watcher_DeviceAdded(
<< ConfigMethodToString(
prov_info.SelectedConfigurationMethod());
session = service_.ConnectAsync(kPin).get();
session = service_.ConnectAsync(winrt::to_hstring(pin)).get();
}
if (!session) {
@@ -702,7 +722,9 @@ bool WifiDirectMedium::DisconnectWifiDirect() {
device_watcher_ = nullptr;
service_ = nullptr;
session_ = nullptr;
return true;
ip_address_local_.clear();
ip_address_remote_.clear();
return true;
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Stop WifiDirect GC failed. Exception: "
<< exception.what();
@@ -20,21 +20,20 @@
#include <utility>
// Nearby connections headers
#include "absl/functional/any_invocable.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
#include "internal/platform/exception.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/implementation/wifi_direct.h"
#include "internal/platform/implementation/windows/generated/winrt/Windows.Foundation.Collections.h"
#include "internal/platform/implementation/windows/generated/winrt/Windows.Networking.Connectivity.h"
#include "internal/platform/implementation/windows/generated/winrt/Windows.Networking.Sockets.h"
#include "internal/platform/implementation/windows/socket_address.h"
#include "internal/platform/implementation/windows/utils.h"
#include "internal/platform/implementation/windows/wifi_direct.h"
#include "internal/platform/logging.h"
#include "internal/platform/wifi_credential.h"
namespace nearby::windows {
WifiDirectServerSocket::WifiDirectServerSocket(int port) : port_(port) {}
namespace {
constexpr int kWaitingForServerSocketReadyTimeoutSeconds = 90; // seconds
} // namespace
WifiDirectServerSocket::~WifiDirectServerSocket() { Close(); }
@@ -42,9 +41,29 @@ std::string WifiDirectServerSocket::GetIPAddress() const {
return wifi_direct_ipaddr_;
}
int WifiDirectServerSocket::GetPort() const { return server_socket_.GetPort(); }
void WifiDirectServerSocket::SetIPAddress(std::string ip_address) {
absl::MutexLock lock(&mutex_);
if (ip_address.empty()) {
return;
}
wifi_direct_ipaddr_ = ip_address;
}
std::unique_ptr<api::WifiDirectSocket> WifiDirectServerSocket::Accept() {
absl::MutexLock lock(&mutex_);
if (!is_listen_started_) {
LOG(INFO) << __func__
<< ": Server socket is not started, wait for server socket is "
"ready.";
is_listen_ready_.WaitWithTimeout(
&mutex_, absl::Seconds(kWaitingForServerSocketReadyTimeoutSeconds));
if (!is_listen_started_) {
LOG(INFO) << __func__
<< ": Server socket failed to start within timeout.";
return nullptr;
}
}
auto client_socket = server_socket_.Accept();
if (client_socket == nullptr) {
return nullptr;
@@ -54,9 +73,16 @@ std::unique_ptr<api::WifiDirectSocket> WifiDirectServerSocket::Accept() {
return std::make_unique<WifiDirectSocket>(std::move(client_socket));
}
void WifiDirectServerSocket::SetCloseNotifier(
absl::AnyInvocable<void()> notifier) {
close_notifier_ = std::move(notifier);
void WifiDirectServerSocket::PopulateWifiDirectCredentials(
WifiDirectCredentials& wifi_direct_credentials) {
wifi_direct_credentials.SetGateway(wifi_direct_ipaddr_);
if (GetPort() != 0) {
wifi_direct_credentials.SetPort(GetPort());
} else {
wifi_direct_credentials.SetPort(FeatureFlags::GetInstance()
.GetFlags()
.wifi_direct_default_port);
}
}
Exception WifiDirectServerSocket::Close() {
@@ -64,35 +90,31 @@ Exception WifiDirectServerSocket::Close() {
if (closed_) {
return {Exception::kSuccess};
}
wifi_direct_ipaddr_.clear();
is_listen_started_ = false;
server_socket_.Close();
closed_ = true;
if (close_notifier_ != nullptr) {
close_notifier_();
}
LOG(INFO) << __func__ << ": Close completed succesfully.";
return {Exception::kSuccess};
}
bool WifiDirectServerSocket::Listen(bool dual_stack, std::string& ip_address) {
// Get current IP addresses of the device.
if (ip_address.empty()) {
return false;
}
wifi_direct_ipaddr_ = ip_address;
LOG(INFO) << "Listen wifi_direct on IP:port " << ip_address << ":" << port_;
bool WifiDirectServerSocket::Listen(int port, bool dual_stack) {
LOG(INFO) << "Listen wifi_direct on IP:port " << wifi_direct_ipaddr_ << ":"
<< port;
SocketAddress address(dual_stack);
if (!SocketAddress::FromString(address, ip_address, port_)) {
LOG(ERROR) << "Failed to parse wifi_direct IP address: " << ip_address
<< " and port: " << port_;
if (!SocketAddress::FromString(address, wifi_direct_ipaddr_, port)) {
LOG(ERROR) << "Failed to parse wifi_direct IP address.";
return false;
}
if (!server_socket_.Listen(address)) {
LOG(ERROR) << "Failed to listen socket.";
return false;
}
LOG(INFO) << "Notify the server socket is started.";
absl::MutexLock lock(&mutex_);
is_listen_started_ = true;
is_listen_ready_.SignalAll();
return true;
}
@@ -23,6 +23,7 @@
#include "absl/time/time.h"
#include "internal/platform/implementation/wifi_direct.h"
#include "internal/platform/logging.h"
#include "internal/platform/wifi_credential.h"
namespace nearby {
namespace windows {
@@ -35,9 +36,11 @@ TEST(WifiDirectMedium, DISABLED_StartWifiDirect) {
if (run_test) {
winrt::init_apartment();
WifiDirectCredentials credentials;
WifiDirectMedium wifi_direct_medium;
EXPECT_TRUE(wifi_direct_medium.StartWifiDirect());
EXPECT_TRUE(wifi_direct_medium.IsInterfaceValid());
EXPECT_TRUE(wifi_direct_medium.StartWifiDirect(&credentials));
while (true) {
LOG(INFO) << "Enter \"s\" to stop test:";
@@ -60,8 +63,19 @@ TEST(WifiDirectMedium, DISABLED_ConnectWifiDirect) {
std::cin >> run_test;
if (run_test) {
WifiDirectCredentials credentials;
WifiDirectMedium wifi_direct_medium;
EXPECT_TRUE(wifi_direct_medium.ConnectWifiDirect());
LOG(INFO) << "Enter WifiDirect Service Name to be connected: ";
std::string service_name;
std::cin >> service_name;
LOG(INFO) << "Enter pin: ";
std::string pin;
std::cin >> pin;
credentials.SetServiceName(service_name);
credentials.SetPin(pin);
EXPECT_TRUE(wifi_direct_medium.ConnectWifiDirect(credentials));
absl::SleepFor(absl::Seconds(2));
while (true) {
@@ -86,9 +100,12 @@ TEST(WifiDirectMedium, DISABLED_WifiDirectServerStartListen) {
if (run_test) {
winrt::init_apartment();
WifiDirectCredentials credentials;
WifiDirectMedium wifi_direct_medium;
EXPECT_TRUE(wifi_direct_medium.StartWifiDirect());
EXPECT_TRUE(wifi_direct_medium.IsInterfaceValid());
EXPECT_TRUE(wifi_direct_medium.StartWifiDirect(&credentials));
absl::SleepFor(absl::Seconds(1));
std::unique_ptr<api::WifiDirectServerSocket> server_socket =
wifi_direct_medium.ListenForService(/*port=*/1234);
@@ -121,9 +138,19 @@ TEST(WifiDirectMedium, DISABLED_WifiDirectConnectToServiceServer) {
if (run_test) {
winrt::init_apartment();
WifiDirectCredentials credentials;
WifiDirectMedium wifi_direct_medium;
EXPECT_TRUE(wifi_direct_medium.ConnectWifiDirect());
LOG(INFO) << "Enter WifiDirect Service Name to be connected: ";
std::string service_name;
std::cin >> service_name;
LOG(INFO) << "Enter pin: ";
std::string pin;
std::cin >> pin;
credentials.SetServiceName(service_name);
credentials.SetPin(pin);
EXPECT_TRUE(wifi_direct_medium.ConnectWifiDirect(credentials));
absl::SleepFor(absl::Seconds(1));
std::unique_ptr<api::WifiDirectSocket> client_socket =
wifi_direct_medium.ConnectToService(
+9 -6
View File
@@ -958,15 +958,15 @@ void MediumEnvironment::RegisterWifiDirectMedium(
}
api::WifiDirectMedium* MediumEnvironment::GetWifiDirectMedium(
absl::string_view ssid, absl::string_view ip_address) {
absl::string_view service_name, absl::string_view ip_address) {
MutexLock lock(&mutex_);
for (auto& medium_info : wifi_direct_mediums_) {
auto* medium_found = medium_info.first;
auto& info = medium_info.second;
if (info.is_go && info.is_active) {
if ((info.wifi_direct_credentials->GetSSID() == ssid) ||
if ((info.wifi_direct_credentials->GetServiceName() == service_name) ||
(!ip_address.empty() &&
(info.wifi_direct_credentials->GetIPAddress() == ip_address))) {
(info.wifi_direct_credentials->GetGateway() == ip_address))) {
LOG(INFO) << "Found Remote WifiDirect medium=" << medium_found;
return medium_found;
}
@@ -995,8 +995,9 @@ void MediumEnvironment::UpdateWifiDirectMediumForStartOrConnect(
if (wifi_direct_credentials) {
LOG(INFO) << "Update WifiDirect medium for GO: this=" << this
<< "; medium=" << &medium << role_status
<< "; ssid=" << wifi_direct_credentials->GetSSID()
<< "; password=" << wifi_direct_credentials->GetPassword();
<< "; service_name="
<< wifi_direct_credentials->GetServiceName()
<< "; pin=" << wifi_direct_credentials->GetPin();
} else {
LOG(INFO) << "Reset WifiDirect medium for GO: this=" << this
<< "; medium=" << &medium << role_status;
@@ -1031,7 +1032,8 @@ void MediumEnvironment::UnregisterWifiDirectMedium(
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium]() {
MutexLock lock(&mutex_);
wifi_direct_mediums_.extract(&medium);
auto item = wifi_direct_mediums_.extract(&medium);
if (item.empty()) return;
LOG(INFO) << "Unregistered WifiDirect medium:" << &medium;
});
}
@@ -1064,6 +1066,7 @@ api::WifiHotspotMedium* MediumEnvironment::GetWifiHotspotMedium(
}
}
LOG(INFO) << "Can't find WifiHotspot medium!";
return nullptr;
}
+1 -1
View File
@@ -295,7 +295,7 @@ class MediumEnvironment {
// Returns WifiDirect medium that matches ssid or IP address with the role of
// the Medium. Returns nullptr if not found.
api::WifiDirectMedium* GetWifiDirectMedium(absl::string_view ssid,
api::WifiDirectMedium* GetWifiDirectMedium(absl::string_view service_name,
absl::string_view ip_address);
// Updates credential and Medium role(GO or GC) to indicate the current
+17
View File
@@ -90,6 +90,16 @@ class WifiDirectCredentials {
std::string GetPassword() const { return password_; }
void SetPassword(const std::string& password) { password_ = password; }
// Get/Set Service Name.
std::string GetServiceName() const { return service_name_; }
void SetServiceName(const std::string& service_name) {
service_name_ = service_name;
}
// Get/Set Pin.
std::string GetPin() const { return pin_; }
void SetPin(const std::string& pin) { pin_ = pin; }
// Gets IP Address, which is in byte sequence, in network order. For example,
// for "192.168.1.1", it'll be byte(129)+byte(168)+byte(1)+byte(1). Now only
// ipv4 is supported.
@@ -121,8 +131,15 @@ class WifiDirectCredentials {
}
private:
// There are 2 types of WifiDirectAuthType.
// 1. Without Service Discovery: the credentials are ssid/password.
// 2. With Service Discovery: the credentials are service_name/pin.
// Android supports type 1 and 2 in the future, but Windows only supports the
// second type.
std::string ssid_;
std::string password_;
std::string service_name_;
std::string pin_;
std::string ip_address_;
std::string gateway_ = "0.0.0.0";
int port_ = 0;
+20 -16
View File
@@ -15,14 +15,24 @@
#ifndef PLATFORM_PUBLIC_WIFI_DIRECT_H_
#define PLATFORM_PUBLIC_WIFI_DIRECT_H_
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include "absl/base/thread_annotations.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/platform.h"
#include "internal/platform/implementation/wifi_direct.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/logging.h"
#include "internal/platform/mutex.h"
#include "internal/platform/mutex_lock.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/wifi_credential.h"
namespace nearby {
@@ -99,16 +109,11 @@ class WifiDirectServerSocket final {
std::unique_ptr<api::WifiDirectServerSocket> socket)
: impl_(std::move(socket)) {}
// Returns ip address.
std::string GetIPAddress() const {
CHECK(impl_);
return impl_->GetIPAddress();
}
// Returns port.
int GetPort() const {
CHECK(impl_);
return impl_->GetPort();
// Populates the WifiDirect credentials with the server socket's service
// addresses and ports.
void PopulateWifiDirectCredentials(
WifiDirectCredentials& wifi_direct_credentials) {
impl_->PopulateWifiDirectCredentials(wifi_direct_credentials);
}
// Blocks until either:
@@ -158,8 +163,8 @@ class WifiDirectMedium {
// Returns a new WifiDirectServerSocket.
// On Success, WifiDirectServerSocket::IsValid() returns true.
WifiDirectServerSocket ListenForService(int port = 0) {
return WifiDirectServerSocket(impl_->ListenForService(port));
WifiDirectServerSocket ListenForService() {
return WifiDirectServerSocket(impl_->ListenForService(/*port=*/0));
}
// Returns the port range as a pair of min and max port.
@@ -173,11 +178,10 @@ class WifiDirectMedium {
}
bool StopWifiDirect() { return impl_->StopWifiDirect(); }
bool ConnectWifiDirect(absl::string_view ssid, absl::string_view password) {
bool ConnectWifiDirect(const WifiDirectCredentials& wifi_direct_credentials) {
MutexLock lock(&mutex_);
wifi_direct_credentials_.SetSSID(std::string(ssid));
wifi_direct_credentials_.SetPassword(std::string(password));
return impl_->ConnectWifiDirect(&wifi_direct_credentials_);
wifi_direct_credentials_ = wifi_direct_credentials;
return impl_->ConnectWifiDirect(wifi_direct_credentials_);
}
bool DisconnectWifiDirect() { return impl_->DisconnectWifiDirect(); }
+65 -31
View File
@@ -14,12 +14,22 @@
#include "internal/platform/wifi_direct.h"
#include <memory>
#include <cstddef>
#include <optional>
#include <string>
#include "gtest/gtest.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/exception.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/medium_environment.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/single_thread_executor.h"
#include "internal/platform/wifi_credential.h"
namespace nearby {
namespace {
@@ -35,22 +45,37 @@ constexpr FeatureFlags kTestCases[] = {
},
};
constexpr absl::string_view kSsid = "Direct-357a2d8c";
constexpr absl::string_view kPassword = "b592f7d3";
constexpr absl::string_view kServiceName = "NC-WifiDirectTest";
constexpr absl::string_view kPin = "b592f7d3";
constexpr absl::string_view kIp = "123.234.23.1";
constexpr const size_t kPort = 20;
constexpr absl::string_view kData = "ABCD";
constexpr const size_t kChunkSize = 10;
constexpr absl::Duration kWaitDuration = absl::Milliseconds(100);
TEST(WifiDirectCredentialsTest, SetGetServiceName) {
std::string service_name(kServiceName);
WifiDirectCredentials wifi_direct_credentials;
wifi_direct_credentials.SetServiceName(service_name);
EXPECT_EQ(wifi_direct_credentials.GetServiceName(), kServiceName);
}
TEST(WifiDirectCredentialsTest, SetGetPin) {
std::string pin(kPin);
WifiDirectCredentials wifi_direct_credentials;
wifi_direct_credentials.SetPin(pin);
EXPECT_EQ(wifi_direct_credentials.GetPin(), kPin);
}
class WifiDirectMediumTest : public testing::TestWithParam<FeatureFlags> {
protected:
WifiDirectMediumTest() { env_.Start(); }
~WifiDirectMediumTest() override {
absl::SleepFor(kWaitDuration);
EXPECT_TRUE(env_.IsWifiDirectMediumsEmpty());
WifiDirectMediumTest() {
env_.Stop();
env_.Start();
}
~WifiDirectMediumTest() override { env_.Stop(); }
MediumEnvironment& env_{MediumEnvironment::Instance()};
};
@@ -70,7 +95,7 @@ TEST_F(WifiDirectMediumTest, ConstructorDestructorWorks) {
EXPECT_NE(&wifi_direct_a.GetImpl(), &wifi_direct_b.GetImpl());
}
TEST_F(WifiDirectMediumTest, CanStartStopDirect) {
TEST_F(WifiDirectMediumTest, CanStartStopWifiDirect) {
WifiDirectMedium wifi_direct_a;
ASSERT_TRUE(wifi_direct_a.IsInterfaceValid());
@@ -82,11 +107,14 @@ TEST_F(WifiDirectMediumTest, CanStartStopDirect) {
EXPECT_TRUE(wifi_direct_a.StopWifiDirect());
}
TEST_F(WifiDirectMediumTest, CanConnectDisconnectDirect) {
TEST_F(WifiDirectMediumTest, CanConnectDisconnectWifiDirect) {
WifiDirectMedium wifi_direct_a;
WifiDirectCredentials credentials;
credentials.SetServiceName(std::string(kServiceName));
credentials.SetPin(std::string(kPin));
ASSERT_TRUE(wifi_direct_a.IsInterfaceValid());
EXPECT_FALSE(wifi_direct_a.ConnectWifiDirect(kSsid, kPassword));
EXPECT_FALSE(wifi_direct_a.ConnectWifiDirect(credentials));
EXPECT_TRUE(wifi_direct_a.DisconnectWifiDirect());
}
@@ -102,17 +130,17 @@ TEST_P(WifiDirectMediumTest, CanStartDirectGOThatOtherCanConnect) {
WifiDirectCredentials* wifi_direct_credentials =
wifi_direct_a.GetCredential();
auto* medium_a =
env_.GetWifiDirectMedium(wifi_direct_credentials->GetSSID(), {});
env_.GetWifiDirectMedium(wifi_direct_credentials->GetServiceName(), {});
EXPECT_NE(medium_a, nullptr);
EXPECT_TRUE(
wifi_direct_b.ConnectWifiDirect(wifi_direct_credentials->GetSSID(),
wifi_direct_credentials->GetPassword()));
EXPECT_TRUE(wifi_direct_b.ConnectWifiDirect(*wifi_direct_credentials));
WifiDirectServerSocket server_socket = wifi_direct_a.ListenForService();
EXPECT_TRUE(server_socket.IsValid());
auto ip_addr = server_socket.GetIPAddress();
EXPECT_FALSE(absl::EndsWith(ip_addr, "."));
wifi_direct_credentials->SetIPAddress(ip_addr);
server_socket.PopulateWifiDirectCredentials(*wifi_direct_credentials);
std::string wifi_direct_a_ip_addr = wifi_direct_credentials->GetGateway();
EXPECT_FALSE(absl::EndsWith(wifi_direct_a_ip_addr, "."));
int wifi_direct_a_port = wifi_direct_credentials->GetPort();
EXPECT_NE(wifi_direct_a_port, 0);
WifiDirectSocket socket_a;
WifiDirectSocket socket_b;
@@ -124,14 +152,16 @@ TEST_P(WifiDirectMediumTest, CanStartDirectGOThatOtherCanConnect) {
SingleThreadExecutor server_executor;
SingleThreadExecutor client_executor;
client_executor.Execute(
[&wifi_direct_b, &socket_b, &server_socket, &flag]() {
[&wifi_direct_b, &socket_b, &server_socket, wifi_direct_a_ip_addr,
wifi_direct_a_port, &flag]() {
socket_b = wifi_direct_b.ConnectToService(kIp, kPort, &flag);
EXPECT_FALSE(socket_b.IsValid());
socket_b = wifi_direct_b.ConnectToService(
server_socket.GetIPAddress(), kPort, &flag);
wifi_direct_a_ip_addr, kPort, &flag);
EXPECT_FALSE(socket_b.IsValid());
socket_b = wifi_direct_b.ConnectToService(
server_socket.GetIPAddress(), server_socket.GetPort(), &flag);
wifi_direct_a_ip_addr, wifi_direct_a_port, &flag);
if (!socket_b.IsValid()) {
server_socket.Close();
}
@@ -163,7 +193,7 @@ TEST_P(WifiDirectMediumTest, CanStartDirectGOThatOtherCanConnect) {
EXPECT_TRUE(wifi_direct_b.DisconnectWifiDirect());
EXPECT_TRUE(wifi_direct_a.StopWifiDirect());
auto* medium_b =
env_.GetWifiDirectMedium(wifi_direct_credentials->GetSSID(), {});
env_.GetWifiDirectMedium(wifi_direct_credentials->GetServiceName(), {});
EXPECT_EQ(medium_b, nullptr);
}
@@ -178,13 +208,13 @@ TEST_P(WifiDirectMediumTest, CanStartDirectGOThatOtherCanCancelConnect) {
EXPECT_TRUE(wifi_direct_a.StartWifiDirect());
WifiDirectCredentials* wifi_direct_credentials =
wifi_direct_a.GetCredential();
EXPECT_TRUE(
wifi_direct_b.ConnectWifiDirect(wifi_direct_credentials->GetSSID(),
wifi_direct_credentials->GetPassword()));
EXPECT_TRUE(wifi_direct_b.ConnectWifiDirect(*wifi_direct_credentials));
WifiDirectServerSocket server_socket = wifi_direct_a.ListenForService();
EXPECT_TRUE(server_socket.IsValid());
wifi_direct_credentials->SetIPAddress(server_socket.GetIPAddress());
server_socket.PopulateWifiDirectCredentials(*wifi_direct_credentials);
std::string wifi_direct_a_ip_addr = wifi_direct_credentials->GetGateway();
int wifi_direct_a_port = wifi_direct_credentials->GetPort();
WifiDirectSocket socket_a;
WifiDirectSocket socket_b;
@@ -197,11 +227,12 @@ TEST_P(WifiDirectMediumTest, CanStartDirectGOThatOtherCanCancelConnect) {
SingleThreadExecutor server_executor;
SingleThreadExecutor client_executor;
client_executor.Execute(
[&wifi_direct_b, &socket_b, &server_socket, &flag]() {
[&wifi_direct_b, &socket_b, &server_socket, wifi_direct_a_ip_addr,
wifi_direct_a_port, &flag]() {
socket_b = wifi_direct_b.ConnectToService(kIp, kPort, &flag);
EXPECT_FALSE(socket_b.IsValid());
socket_b = wifi_direct_b.ConnectToService(
server_socket.GetIPAddress(), server_socket.GetPort(), &flag);
wifi_direct_a_ip_addr, wifi_direct_a_port, &flag);
if (!socket_b.IsValid()) {
server_socket.Close();
}
@@ -225,8 +256,8 @@ TEST_P(WifiDirectMediumTest, CanStartDirectGOThatOtherCanCancelConnect) {
server_socket.Close();
{
CancellationFlag flag(true);
socket_c = wifi_direct_b.ConnectToService(server_socket.GetIPAddress(),
server_socket.GetPort(), &flag);
socket_c = wifi_direct_b.ConnectToService(wifi_direct_a_ip_addr,
wifi_direct_a_port, &flag);
EXPECT_FALSE(socket_c.IsValid());
}
@@ -241,8 +272,11 @@ TEST_F(WifiDirectMediumTest, CanStartDirectGOThatOtherFailConnect) {
ASSERT_TRUE(wifi_direct_a.IsInterfaceValid());
ASSERT_TRUE(wifi_direct_b.IsInterfaceValid());
EXPECT_TRUE(wifi_direct_a.StartWifiDirect());
WifiDirectCredentials wifi_direct_credentials;
wifi_direct_credentials.SetServiceName(std::string(kServiceName));
wifi_direct_credentials.SetPin(std::string(kPin));
EXPECT_FALSE(wifi_direct_b.ConnectWifiDirect(kSsid, kPassword));
EXPECT_FALSE(wifi_direct_b.ConnectWifiDirect(wifi_direct_credentials));
EXPECT_TRUE(wifi_direct_b.DisconnectWifiDirect());
EXPECT_TRUE(wifi_direct_a.StopWifiDirect());