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
@@ -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(