Remove the fake Windows WifiDirect implementation files.

PiperOrigin-RevId: 828009506
This commit is contained in:
hai007
2025-11-04 09:33:18 -08:00
committed by Copybara-Service
parent d4dbee9493
commit 54a6836be0
5 changed files with 0 additions and 1433 deletions
@@ -220,12 +220,9 @@ cc_library(
"preferences_repository.cc",
"system_clock.cc",
"webrtc.cc",
"wifi_direct_medium.cc",
"wifi_direct_server_socket.cc",
"wifi_direct_service_medium.cc",
"wifi_direct_service_server_socket.cc",
"wifi_direct_service_socket.cc",
"wifi_direct_socket.cc",
"wifi_hotspot_medium.cc",
"wifi_hotspot_native.cc",
"wifi_hotspot_server_socket.cc",
@@ -258,7 +255,6 @@ cc_library(
"preferences_repository.h",
"webrtc.h",
"wifi.h",
"wifi_direct.h",
"wifi_direct_service.h",
"wifi_hotspot.h",
"wifi_hotspot_native.h",
@@ -1,321 +0,0 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_WINDOWS_WIFI_DIRECT_H_
#define PLATFORM_IMPL_WINDOWS_WIFI_DIRECT_H_
// Windows headers
#include <windows.h>
#include <wlanapi.h>
// Standard C/C++ headers
#include <deque>
#include <exception>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
// Nearby connections headers
#include "internal/platform/implementation/wifi_direct.h"
#include "internal/platform/implementation/windows/scheduled_executor.h"
// ABSL header
#include "absl/types/optional.h"
// WinRT headers
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.Enumeration.h"
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.WiFi.h"
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.WiFiDirect.h"
#include "internal/platform/implementation/windows/generated/winrt/Windows.Foundation.Collections.h"
#include "internal/platform/implementation/windows/generated/winrt/Windows.Foundation.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/generated/winrt/Windows.Security.Credentials.h"
#include "internal/platform/implementation/windows/generated/winrt/Windows.Security.Cryptography.h"
#include "internal/platform/implementation/windows/generated/winrt/Windows.Storage.Streams.h"
#include "internal/platform/implementation/windows/generated/winrt/base.h"
namespace nearby {
namespace windows {
using ::winrt::fire_and_forget;
using ::winrt::Windows::Devices::WiFiDirect::
WiFiDirectAdvertisementListenStateDiscoverability;
using ::winrt::Windows::Devices::WiFiDirect::WiFiDirectAdvertisementPublisher;
using ::winrt::Windows::Devices::WiFiDirect::
WiFiDirectAdvertisementPublisherStatus;
using ::winrt::Windows::Devices::WiFiDirect::
WiFiDirectAdvertisementPublisherStatusChangedEventArgs;
using ::winrt::Windows::Devices::WiFiDirect::WiFiDirectConnectionListener;
using ::winrt::Windows::Devices::WiFiDirect::WiFiDirectConnectionRequest;
using ::winrt::Windows::Devices::WiFiDirect::
WiFiDirectConnectionRequestedEventArgs;
using ::winrt::Windows::Devices::WiFiDirect::WiFiDirectConnectionStatus;
using ::winrt::Windows::Devices::WiFiDirect::WiFiDirectDevice;
using ::winrt::Windows::Devices::WiFi::WiFiAccessStatus;
using ::winrt::Windows::Devices::WiFi::WiFiAdapter;
using ::winrt::Windows::Devices::WiFi::WiFiAvailableNetwork;
using ::winrt::Windows::Devices::WiFi::WiFiConnectionStatus;
using ::winrt::Windows::Devices::WiFi::WiFiReconnectionKind;
using ::winrt::Windows::Devices::Enumeration::DeviceInformation;
using ::winrt::Windows::Devices::Enumeration::DeviceInformationPairing;
using ::winrt::Windows::Storage::Streams::Buffer;
using ::winrt::Windows::Storage::Streams::IInputStream;
using ::winrt::Windows::Storage::Streams::InputStreamOptions;
using ::winrt::Windows::Storage::Streams::IOutputStream;
using ::winrt::Windows::Security::Credentials::PasswordCredential;
using ::winrt::Windows::Security::Cryptography::CryptographicBuffer;
using ::winrt::Windows::Networking::HostName;
using ::winrt::Windows::Networking::HostNameType;
using ::winrt::Windows::Networking::Connectivity::ConnectionProfile;
using ::winrt::Windows::Networking::Connectivity::ConnectionProfileDeleteStatus;
using ::winrt::Windows::Networking::Connectivity::NetworkInformation;
using ::winrt::Windows::Networking::Sockets::StreamSocket;
using ::winrt::Windows::Networking::Sockets::StreamSocketListener;
using ::winrt::Windows::Networking::Sockets::
StreamSocketListenerConnectionReceivedEventArgs;
// WifiDirectSocket wraps the socket functions to read and write stream.
// In WifiDirect GO, A WifiDirectSocket will be passed to
// StartAcceptingConnections's call back when StreamSocketListener got connect.
// When call API to connect to remote WiFi Direct service, also will return a
// WifiDirectSocket to caller.
class WifiDirectSocket : public api::WifiDirectSocket {
public:
explicit WifiDirectSocket(StreamSocket socket);
WifiDirectSocket(const WifiDirectSocket&) = default;
WifiDirectSocket(WifiDirectSocket&&) = default;
~WifiDirectSocket() override;
WifiDirectSocket& operator=(const WifiDirectSocket&) = default;
WifiDirectSocket& operator=(WifiDirectSocket&&) = default;
// Returns the InputStream of the WifiDirectSocket.
// On error, returned stream will report Exception::kIo on any operation.
//
// The returned object is not owned by the caller, and can be invalidated once
// the WifiDirectSocket object is destroyed.
InputStream& GetInputStream() override;
// Returns the OutputStream of the WifiDirectSocket.
// On error, returned stream will report Exception::kIo on any operation.
//
// The returned object is not owned by the caller, and can be invalidated once
// the WifiDirectSocket object is destroyed.
OutputStream& GetOutputStream() override;
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
Exception Close() override;
private:
// A simple wrapper to handle input stream of socket
class SocketInputStream : public InputStream {
public:
explicit SocketInputStream(IInputStream input_stream);
~SocketInputStream() override = default;
ExceptionOr<ByteArray> Read(std::int64_t size) override;
ExceptionOr<size_t> Skip(size_t offset) override;
Exception Close() override;
private:
IInputStream input_stream_{nullptr};
};
// A simple wrapper to handle output stream of socket
class SocketOutputStream : public OutputStream {
public:
explicit SocketOutputStream(IOutputStream output_stream);
~SocketOutputStream() override = default;
Exception Write(const ByteArray& data) override;
Exception Flush() override;
Exception Close() override;
private:
IOutputStream output_stream_{nullptr};
};
// Internal properties
StreamSocket stream_soket_{nullptr};
SocketInputStream input_stream_{nullptr};
SocketOutputStream output_stream_{nullptr};
};
// WifiDirectServerSocket provides the support to server socket, this 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() override;
WifiDirectServerSocket& operator=(const WifiDirectServerSocket&) = default;
WifiDirectServerSocket& operator=(WifiDirectServerSocket&&) = default;
std::string GetIPAddress() const override;
int GetPort() const override;
void SetPort(int port) { port_ = port; }
StreamSocketListener GetSocketListener() const {
return stream_socket_listener_;
}
// Blocks until either:
// - at least one incoming connection request is available, or
// - ServerSocket is closed.
// On success, returns connected socket, ready to exchange data.
// Returns nullptr on error.
// Once error is reported, it is permanent, and ServerSocket has to be closed.
std::unique_ptr<api::WifiDirectSocket> Accept() override;
// 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);
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
Exception Close() override;
// Binds to local port
bool listen();
private:
// The listener is accepting incoming connections
fire_and_forget Listener_ConnectionReceived(
StreamSocketListener listener,
StreamSocketListenerConnectionReceivedEventArgs const& args);
// Retrieves IP addresses from local machine
std::vector<std::string> GetIpAddresses() const;
std::string GetDirectGOIpAddresses() const;
mutable absl::Mutex mutex_;
absl::CondVar cond_;
std::deque<StreamSocket> pending_sockets_ ABSL_GUARDED_BY(mutex_);
StreamSocketListener stream_socket_listener_{nullptr};
winrt::event_token listener_event_token_{};
// Close notifier
absl::AnyInvocable<void()> close_notifier_ = nullptr;
// IP addresses of the computer. mDNS uses them to advertise.
std::vector<std::string> ip_addresses_{};
// Cache socket not be picked by upper layer
std::string wifi_direct_go_ipaddr_ = {};
int port_ = 0;
bool closed_ = false;
};
// Container of operations that can be performed over the WifiDirect medium.
class WifiDirectMedium : public api::WifiDirectMedium {
public:
WifiDirectMedium() = default;
~WifiDirectMedium() override;
// If the WiFi Adaptor supports to start a WifiDirect interface.
bool IsInterfaceValid() const override;
// WifiDirect GC connects to server socket
std::unique_ptr<api::WifiDirectSocket> ConnectToService(
absl::string_view ip_address, int port,
CancellationFlag* cancellation_flag) override;
// WifiDirect GO starts to listen on server socket
std::unique_ptr<api::WifiDirectServerSocket> ListenForService(
int port) override;
// Start WifiDirect GO with specific Credentials.
bool StartWifiDirect(WifiDirectCredentials* wifi_direct_credentials) override;
// Stop the current WifiDirect GO
bool StopWifiDirect() override;
// WifiDirect GC connects to the GO
bool ConnectWifiDirect(
WifiDirectCredentials* wifi_direct_credentials) override;
// WifiDirect GC disconnects to the GO
bool DisconnectWifiDirect() override;
absl::optional<std::pair<std::int32_t, std::int32_t>> GetDynamicPortRange()
override {
return absl::nullopt;
}
private:
enum Value : char {
kMediumStatusIdle = 0,
kMediumStatusAccepting = (1 << 0),
kMediumStatusBeaconing = (1 << 1),
kMediumStatusConnected = (1 << 2),
};
// Implemented the internal disconnection to WifiDirect GO, and used to avoid
// deadlock.
bool InternalDisconnectWifiDirect();
bool IsIdle() { return medium_status_ == kMediumStatusIdle; }
// WifiDirect GO is accepting connection on server socket
bool IsAccepting() { return (medium_status_ & kMediumStatusAccepting) != 0; }
// WifiDirect GO is started and sending beacon
bool IsBeaconing() { return (medium_status_ & kMediumStatusBeaconing) != 0; }
// WifiDirect GC is connected with the GO
bool IsConnected() { return (medium_status_ & kMediumStatusConnected) != 0; }
void RestoreWifiConnection();
// Gets error message from exception pointer
std::string GetErrorMessage(std::exception_ptr eptr);
fire_and_forget OnStatusChanged(
WiFiDirectAdvertisementPublisher sender,
WiFiDirectAdvertisementPublisherStatusChangedEventArgs event);
fire_and_forget OnConnectionRequested(
WiFiDirectConnectionListener const& sender,
WiFiDirectConnectionRequestedEventArgs const& event);
// WINRT related data member
WiFiAdapter wifi_adapter_{nullptr};
WiFiAvailableNetwork wifi_connected_network_{nullptr};
WiFiDirectAdvertisementPublisher publisher_{nullptr};
WiFiDirectConnectionListener listener_{nullptr};
WiFiDirectDevice wifi_direct_device_{nullptr};
winrt::event_token publisher_status_changed_token_;
winrt::event_token connection_requested_token_;
// Protects to access some members
absl::Mutex mutex_;
// Medium Status
int medium_status_ = kMediumStatusIdle;
// Keep the server socket listener pointer
WifiDirectServerSocket* server_socket_ptr_ ABSL_GUARDED_BY(mutex_) = nullptr;
// Scheduler for timeout.
ScheduledExecutor scheduled_executor_;
// Scheduled task for connection timeout.
std::shared_ptr<api::Cancelable> connection_timeout_ = nullptr;
};
} // namespace windows
} // namespace nearby
#endif // PLATFORM_IMPL_WINDOWS_WIFI_DIRECT_H_
@@ -1,622 +0,0 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <exception>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "internal/base/masker.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/implementation/wifi_direct.h"
#include "internal/platform/implementation/wifi_utils.h"
#include "internal/platform/implementation/windows/wifi_direct.h"
// Nearby connections headers
#include "internal/platform/cancellation_flag_listener.h"
#include "internal/platform/implementation/windows/utils.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace windows {
namespace {
// The maximum scanning times for GC to find WifiDirect GO.
constexpr int kWifiDirectMaxScans = 2;
// The maximum connection times to remote WifiDirect GO server socket.
constexpr int kWifiDirectMaxConnectionRetries = 3;
// The interval between 2 connectin attempts.
constexpr absl::Duration kWifiDirectRetryIntervalMillis =
absl::Milliseconds(300);
// The connection timeout to remote WifiDirect GO server socket.
constexpr absl::Duration kWifiDirectClientSocketConnectTimeoutMillis =
absl::Milliseconds(10000);
// The maximum times to check IP address.
constexpr int kIpAddressMaxRetries = 3;
// The time interval to check IP address.
constexpr absl::Duration kIpAddressRetryIntervalMillis =
absl::Milliseconds(2000);
} // namespace
WifiDirectMedium::~WifiDirectMedium() {
StopWifiDirect();
DisconnectWifiDirect();
}
bool WifiDirectMedium::IsInterfaceValid() const {
HANDLE wifi_direct_handle = nullptr;
DWORD negotiated_version = 0;
DWORD result =
WFDOpenHandle(WFD_API_VERSION, &negotiated_version, &wifi_direct_handle);
if (result == ERROR_SUCCESS) {
LOG(INFO) << "WiFi can support WifiDirect";
WFDCloseHandle(wifi_direct_handle);
return true;
}
LOG(ERROR) << "WiFi can't support WifiDirect";
return false;
}
std::unique_ptr<api::WifiDirectSocket> WifiDirectMedium::ConnectToService(
absl::string_view ip_address, int port,
CancellationFlag* cancellation_flag) {
LOG(WARNING) << __func__ << " : Connect to remote service.";
if (ip_address.empty() || port == 0) {
LOG(ERROR) << "no valid service address and port to connect: "
<< "ip_address = " << ip_address << ", port = " << port;
return nullptr;
}
std::string ipv4_address;
if (ip_address.length() == 4) {
ipv4_address = ipaddr_4bytes_to_dotdecimal_string(ip_address);
} else {
ipv4_address = std::string(ip_address);
}
if (!WifiUtils::ValidateIPV4(ipv4_address)) {
LOG(ERROR) << "Invalid IP address parameter.";
return nullptr;
}
HostName host_name{winrt::to_hstring(ipv4_address)};
winrt::hstring service_name{winrt::to_hstring(port)};
// Try connecting to the service up to kWifiDirectMaxConnectionRetries,
// because it may fail first time if DHCP procedure is not finished yet.
for (int i = 0; i < kWifiDirectMaxConnectionRetries; i++) {
try {
StreamSocket socket{};
std::unique_ptr<nearby::CancellationFlagListener>
connection_cancellation_listener = nullptr;
// setup cancel listener
if (cancellation_flag != nullptr) {
if (cancellation_flag->Cancelled()) {
LOG(INFO) << "connect has been cancelled to service " << ipv4_address
<< ":" << port;
return nullptr;
}
connection_cancellation_listener =
std::make_unique<nearby::CancellationFlagListener>(
cancellation_flag, [socket]() {
LOG(WARNING) << "connect is closed due to it is cancelled.";
socket.Close();
});
}
connection_timeout_ = scheduled_executor_.Schedule(
[socket]() {
LOG(WARNING) << "connect is closed due to timeout.";
socket.Close();
},
kWifiDirectClientSocketConnectTimeoutMillis);
socket.ConnectAsync(host_name, service_name).get();
if (connection_timeout_ != nullptr) {
connection_timeout_->Cancel();
connection_timeout_ = nullptr;
}
auto client_socket = std::make_unique<WifiDirectSocket>(socket);
LOG(INFO) << "connected to remote service " << ipv4_address << ":"
<< port;
return client_socket;
} catch (...) {
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
<< port << " for the " << i + 1 << " time";
}
if (connection_timeout_ != nullptr) {
connection_timeout_->Cancel();
connection_timeout_ = nullptr;
}
Sleep(kWifiDirectRetryIntervalMillis / absl::Milliseconds(1));
}
return nullptr;
}
std::unique_ptr<api::WifiDirectServerSocket> WifiDirectMedium::ListenForService(
int port) {
absl::MutexLock lock(&mutex_);
// check current status
if (IsAccepting()) {
LOG(WARNING) << "accepting connections already started on port "
<< server_socket_ptr_->GetPort();
return nullptr;
}
auto server_socket = std::make_unique<WifiDirectServerSocket>(port);
server_socket_ptr_ = server_socket.get();
if (server_socket->listen()) {
medium_status_ |= kMediumStatusAccepting;
server_socket->SetCloseNotifier([this]() {
absl::MutexLock lock(&mutex_);
LOG(INFO) << "server socket was closed on port "
<< server_socket_ptr_->GetPort();
medium_status_ &= (~kMediumStatusAccepting);
server_socket_ptr_ = nullptr;
});
LOG(INFO) << "started to listen serive on port "
<< server_socket_ptr_->GetPort();
return server_socket;
}
LOG(ERROR) << "Failed to listen service on port " << port;
return nullptr;
}
bool WifiDirectMedium::StartWifiDirect(
WifiDirectCredentials* wifi_direct_credentials) {
absl::MutexLock lock(&mutex_);
if (IsBeaconing()) {
LOG(WARNING) << "cannot create SoftAP again when it is running.";
return true;
}
try {
publisher_ = WiFiDirectAdvertisementPublisher();
publisher_status_changed_token_ =
publisher_.StatusChanged({this, &WifiDirectMedium::OnStatusChanged});
listener_ = WiFiDirectConnectionListener();
connection_requested_token_ = listener_.ConnectionRequested(
{this, &WifiDirectMedium::OnConnectionRequested});
// Normal mode: The device is highly discoverable so long as the app is in
// the foreground.
publisher_.Advertisement().ListenStateDiscoverability(
WiFiDirectAdvertisementListenStateDiscoverability::Normal);
// Enable Autonomous GO mode
publisher_.Advertisement().IsAutonomousGroupOwnerEnabled(true);
// Using WIFIDirect legacy mode to create a softAP. AP means "access point".
// Windows WinRT WifiDirect class follows a full P2P protocol to establish a
// P2P connection. However the current Phone Nearby Connection uses a
// simplified protocol for P2P connection, which is just like a legacy
// AP/STA SSID/password mode. To accommodate with this, Windows side give up
// the formal P2P connection code suite, instead it uses Hotspot and legacy
// STA to fake a P2P connection. By this way, when Phone act as Group
// Client(GC), it can keep the connection with Router(AP) at the same time.
// But if phone act as Group Owner(GO), Windows side still can't keep its AP
// connection when connecting to phone as a GC because it is in normal STA
// mode.
Prng prng;
publisher_.Advertisement().LegacySettings().IsEnabled(true);
std::string password = absl::StrFormat("%08x", prng.NextUint32());
wifi_direct_credentials->SetPassword(password);
PasswordCredential creds;
creds.Password(winrt::to_hstring(password));
publisher_.Advertisement().LegacySettings().Passphrase(creds);
std::string ssid = "DIRECT-" + std::to_string(prng.NextUint32());
wifi_direct_credentials->SetSSID(ssid);
publisher_.Advertisement().LegacySettings().Ssid(winrt::to_hstring(ssid));
publisher_.Start();
if (publisher_.Status() ==
WiFiDirectAdvertisementPublisherStatus::Started) {
LOG(INFO) << "Windows WiFiDirect GO(SoftAP) started";
medium_status_ |= kMediumStatusBeaconing;
return true;
}
// Clean up when fail
LOG(ERROR) << "Windows WiFiDirect GO(SoftAP) fails to start";
publisher_.StatusChanged(publisher_status_changed_token_);
listener_.ConnectionRequested(connection_requested_token_);
listener_ = nullptr;
publisher_ = nullptr;
return false;
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Cannot start WiFiDirect GO. Exception: "
<< exception.what();
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << __func__ << ": Cannot start WiFiDirect GO. WinRT exception: "
<< error.code() << ": " << winrt::to_string(error.message());
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exception.";
}
return false;
}
bool WifiDirectMedium::StopWifiDirect() {
// Need to use Win32 API to deregister the Dnssd instance
absl::MutexLock lock(&mutex_);
if (!IsBeaconing()) {
LOG(WARNING)
<< "Cannot stop WiFiDirect GO(SoftAP) because no GO was started.";
return true;
}
try {
if (publisher_) {
publisher_.Stop();
listener_.ConnectionRequested(connection_requested_token_);
publisher_.StatusChanged(publisher_status_changed_token_);
wifi_direct_device_ = nullptr;
listener_ = nullptr;
publisher_ = nullptr;
LOG(INFO) << "succeeded to stop WiFiDirect GO(SoftAP)";
}
medium_status_ &= (~kMediumStatusBeaconing);
return true;
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Stop WiFiDirect GO failed. Exception: "
<< exception.what();
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << __func__ << ": Stop WiFiDirect GO failed. WinRT exception: "
<< error.code() << ": " << winrt::to_string(error.message());
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exception.";
}
return false;
}
fire_and_forget WifiDirectMedium::OnStatusChanged(
WiFiDirectAdvertisementPublisher sender,
WiFiDirectAdvertisementPublisherStatusChangedEventArgs event) {
if (event.Status() == WiFiDirectAdvertisementPublisherStatus::Started) {
if (sender.Advertisement().LegacySettings().IsEnabled()) {
LOG(INFO) << "WiFiDirect GO SSID: "
<< winrt::to_string(
publisher_.Advertisement().LegacySettings().Ssid());
LOG(INFO) << "WiFiDirect GO password: "
<< masker::Mask(winrt::to_string(publisher_.Advertisement()
.LegacySettings()
.Passphrase()
.Password()));
}
return winrt::fire_and_forget();
} else if (event.Status() ==
WiFiDirectAdvertisementPublisherStatus::Created) {
LOG(INFO) << "Receive WiFiDirect/SoftAP Created event.";
return winrt::fire_and_forget();
} else if (event.Status() ==
WiFiDirectAdvertisementPublisherStatus::Stopped) {
LOG(INFO) << "Receive WiFiDirect/SoftAP Stopped event.";
} else if (event.Status() ==
WiFiDirectAdvertisementPublisherStatus::Aborted) {
LOG(INFO) << "Receive WiFiDirect/SoftAP Aborted event.";
}
// Publisher is stopped. Need to clean up the publisher.
{
absl::MutexLock lock(&mutex_);
if (publisher_ != nullptr) {
LOG(ERROR) << "Windows WiFiDirect GO(SoftAP) cleanup.";
listener_.ConnectionRequested(connection_requested_token_);
publisher_.StatusChanged(publisher_status_changed_token_);
wifi_direct_device_ = nullptr;
listener_ = nullptr;
publisher_ = nullptr;
}
}
return winrt::fire_and_forget();
}
fire_and_forget WifiDirectMedium::OnConnectionRequested(
WiFiDirectConnectionListener const& sender,
WiFiDirectConnectionRequestedEventArgs const& event) {
WiFiDirectConnectionRequest connection_request = event.GetConnectionRequest();
winrt::hstring device_name = connection_request.DeviceInformation().Name();
LOG(INFO) << "Receive connection request from: "
<< winrt::to_string(device_name);
try {
// This is to solve b/236805122.
// Problem: [Microsoft-Windows-WLAN-AutoConfig] issues a disconnection to
// WifiDirect Client every 2 minutes and stopped WifiDirect GO eventually.
// Solution: Creating a WiFiDirectDevice for Clients connection request can
// solve the problem. Guess when this object is created,
// [Microsoft-Windows-WLAN-AutoConfig] will recognise it as a valid device
// and won't kick it away.
wifi_direct_device_ = WiFiDirectDevice::FromIdAsync(
connection_request.DeviceInformation().Id())
.get();
LOG(INFO) << "Registered the device in WLAN-AutoConfig";
} catch (...) {
LOG(ERROR) << "Failed to registered the device in WLAN-AutoConfig";
wifi_direct_device_ = nullptr;
connection_request.Close();
}
return winrt::fire_and_forget();
}
bool WifiDirectMedium::ConnectWifiDirect(
WifiDirectCredentials* wifi_direct_credentials) {
absl::MutexLock lock(&mutex_);
try {
if (IsConnected()) {
LOG(WARNING) << "Already connected to AP, disconnect first.";
InternalDisconnectWifiDirect();
}
auto access = WiFiAdapter::RequestAccessAsync().get();
if (access != WiFiAccessStatus::Allowed) {
LOG(WARNING) << "Access Denied with reason: " << static_cast<int>(access);
return false;
}
auto adapters = WiFiAdapter::FindAllAdaptersAsync().get();
if (adapters.Size() < 1) {
LOG(WARNING) << "No WiFi Adapter found.";
return false;
}
wifi_adapter_ = adapters.GetAt(0);
// Retrieve the current connected network's profile
ConnectionProfile profile =
wifi_adapter_.NetworkAdapter().GetConnectedProfileAsync().get();
std::string ssid;
if (profile != nullptr && profile.IsWlanConnectionProfile()) {
ssid = winrt::to_string(
profile.WlanConnectionProfileDetails().GetConnectedSsid());
}
// SoftAP is an abbreviation for "software enabled access point".
WiFiAvailableNetwork nearby_softap{nullptr};
LOG(INFO) << "Scanning for Nearby WifiDirect GO's SSID: "
<< wifi_direct_credentials->GetSSID();
// First time scan may not find our target GO, try 2 more times can
// almost guarantee to find the GO
wifi_adapter_.ScanAsync().get();
wifi_connected_network_ = nullptr;
for (int i = 0; i < kWifiDirectMaxScans; i++) {
for (const auto& network :
wifi_adapter_.NetworkReport().AvailableNetworks()) {
if (!wifi_connected_network_ && !ssid.empty() &&
(winrt::to_string(network.Ssid()) == ssid)) {
wifi_connected_network_ = network;
LOG(INFO) << "Save the current connected network: " << ssid;
} else if (!nearby_softap && winrt::to_string(network.Ssid()) ==
wifi_direct_credentials->GetSSID()) {
LOG(INFO) << "Found Nearby SSID: "
<< winrt::to_string(network.Ssid());
nearby_softap = network;
}
if (nearby_softap && wifi_connected_network_) break;
}
if (nearby_softap) break;
LOG(INFO) << "Scan ... ";
wifi_adapter_.ScanAsync().get();
}
if (!nearby_softap) {
LOG(INFO) << "WifiDirect GO is not found";
return false;
}
PasswordCredential creds;
creds.Password(winrt::to_hstring(wifi_direct_credentials->GetPassword()));
auto connect_result =
wifi_adapter_
.ConnectAsync(nearby_softap, WiFiReconnectionKind::Manual, creds)
.get();
if (connect_result == nullptr ||
connect_result.ConnectionStatus() != WiFiConnectionStatus::Success) {
LOG(INFO) << "Connecting failed with reason: "
<< static_cast<int>(connect_result.ConnectionStatus());
return false;
}
// Make sure IP address is ready.
std::string ip_address;
for (int i = 0; i < kIpAddressMaxRetries; i++) {
LOG(INFO) << "Check IP address at attempt " << i;
std::vector<std::string> ip_addresses = GetIpv4Addresses();
if (ip_addresses.empty()) {
Sleep(kIpAddressRetryIntervalMillis / absl::Milliseconds(1));
continue;
}
ip_address = ip_addresses[0];
break;
}
if (ip_address.empty()) {
LOG(INFO) << "Failed to get IP address from WifiDirect GO.";
return false;
}
LOG(INFO) << "Got IP: " << ip_address << " from WifiDirect GO.";
std::string last_ssid = wifi_direct_credentials->GetSSID();
medium_status_ |= kMediumStatusConnected;
LOG(INFO) << "Connected to WifiDirect GO: " << last_ssid;
return true;
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Cannot connet to WifiDirect GO. Exception: "
<< exception.what();
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << __func__
<< ": Cannot connet to WifiDirect GO. WinRT exception: "
<< error.code() << ": " << winrt::to_string(error.message());
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exception.";
}
return false;
}
void WifiDirectMedium::RestoreWifiConnection() {
if (!wifi_connected_network_ && wifi_adapter_) {
wifi_adapter_.Disconnect();
return;
}
if (wifi_adapter_) {
ConnectionProfile profile =
wifi_adapter_.NetworkAdapter().GetConnectedProfileAsync().get();
std::string ssid;
if (profile != nullptr && profile.IsWlanConnectionProfile()) {
ssid = winrt::to_string(
profile.WlanConnectionProfileDetails().GetConnectedSsid());
if (!ssid.empty() &&
(winrt::to_string(wifi_connected_network_.Ssid()) == ssid)) {
LOG(INFO) << "Already conneted to the previous WIFI network " << ssid
<< "! Skip restoration.";
return;
}
}
// Disconnect to the WiFi connection through the WiFi adapter.
wifi_adapter_.Disconnect();
LOG(INFO) << "Disconnected to current network.";
auto connect_result = wifi_adapter_
.ConnectAsync(wifi_connected_network_,
WiFiReconnectionKind::Automatic)
.get();
if (connect_result == nullptr ||
connect_result.ConnectionStatus() != WiFiConnectionStatus::Success) {
LOG(INFO) << "Connecting to previous network failed with reason: "
<< static_cast<int>(connect_result.ConnectionStatus());
} else {
LOG(INFO) << "Restored the previous WIFI connection: "
<< winrt::to_string(wifi_connected_network_.Ssid());
}
wifi_connected_network_ = nullptr;
}
}
bool WifiDirectMedium::DisconnectWifiDirect() {
absl::MutexLock lock(&mutex_);
try {
return InternalDisconnectWifiDirect();
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Disconnect WifiDirect GO failed. Exception: "
<< exception.what();
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << __func__
<< ": Disconnect WifiDirect GO failed. WinRT exception: "
<< error.code() << ": " << winrt::to_string(error.message());
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exception.";
}
return false;
}
bool WifiDirectMedium::InternalDisconnectWifiDirect() {
if (!IsConnected()) {
LOG(WARNING)
<< "Cannot disconnect WifiDirect GO because it is not connected.";
return true;
}
if (wifi_adapter_) {
// Gets connected WiFi profile.
auto profile =
wifi_adapter_.NetworkAdapter().GetConnectedProfileAsync().get();
// Disconnect to the WiFi connection through the WiFi adapter.
RestoreWifiConnection();
wifi_adapter_ = nullptr;
// Try to remove the WiFi profile
if (profile != nullptr && profile.CanDelete() &&
profile.IsWlanConnectionProfile()) {
std::string ssid = winrt::to_string(
profile.WlanConnectionProfileDetails().GetConnectedSsid());
auto profile_delete_status = profile.TryDeleteAsync().get();
switch (profile_delete_status) {
case ConnectionProfileDeleteStatus::Success:
LOG(INFO) << "WiFi profile with SSID:" << ssid << " is deleted.";
break;
case ConnectionProfileDeleteStatus::DeniedBySystem:
LOG(ERROR) << "Failed to delete WiFi profile with SSID:" << ssid
<< " due to denied by system.";
break;
case ConnectionProfileDeleteStatus::DeniedByUser:
LOG(ERROR) << "Failed to delete WiFi profile with SSID:" << ssid
<< " due to denied by user.";
break;
case ConnectionProfileDeleteStatus::UnknownError:
LOG(ERROR) << "Failed to delete WiFi profile with SSID:" << ssid
<< " due to unknonw error.";
break;
default:
break;
}
}
}
medium_status_ &= (~kMediumStatusConnected);
return true;
}
std::string WifiDirectMedium::GetErrorMessage(std::exception_ptr eptr) {
try {
if (eptr) {
std::rethrow_exception(eptr);
} else {
return "";
}
} catch (const std::exception& e) {
return e.what();
}
}
} // namespace windows
} // namespace nearby
@@ -1,282 +0,0 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <windows.h>
#include <exception>
#include <memory>
#include <string>
#include <vector>
// ABSL headers
#include "absl/functional/any_invocable.h"
#include "absl/strings/match.h"
// Nearby connections headers
#include "absl/synchronization/mutex.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/wifi_direct.h"
#include "internal/platform/implementation/windows/generated/winrt/Windows.Networking.Sockets.h"
#include "internal/platform/implementation/windows/utils.h"
#include "internal/platform/implementation/windows/wifi_direct.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace windows {
namespace {
using ::winrt::Windows::Networking::Sockets::SocketQualityOfService;
constexpr int kMaxRetries = 3;
constexpr int kRetryIntervalMilliSeconds = 300;
} // namespace
WifiDirectServerSocket::WifiDirectServerSocket(int port) : port_(port) {}
WifiDirectServerSocket::~WifiDirectServerSocket() { Close(); }
std::string WifiDirectServerSocket::GetIPAddress() const {
if (stream_socket_listener_ == nullptr) {
return {};
}
if (ip_addresses_.empty()) {
auto ip_addr = GetIpAddresses();
if (ip_addr.empty()) {
return {};
}
return ip_addr.front();
}
return ip_addresses_.front();
}
int WifiDirectServerSocket::GetPort() const {
if (stream_socket_listener_ == nullptr) {
return 0;
}
return std::stoi(stream_socket_listener_.Information().LocalPort().c_str());
}
std::unique_ptr<api::WifiDirectSocket> WifiDirectServerSocket::Accept() {
absl::MutexLock lock(&mutex_);
LOG(INFO) << __func__ << ": Accept is called.";
while (!closed_ && pending_sockets_.empty()) {
cond_.Wait(&mutex_);
}
if (closed_) return {};
StreamSocket wifi_direct_socket = pending_sockets_.front();
pending_sockets_.pop_front();
LOG(INFO) << __func__ << ": Accepted a remote connection.";
return std::make_unique<WifiDirectSocket>(wifi_direct_socket);
}
void WifiDirectServerSocket::SetCloseNotifier(
absl::AnyInvocable<void()> notifier) {
close_notifier_ = std::move(notifier);
}
Exception WifiDirectServerSocket::Close() {
try {
absl::MutexLock lock(&mutex_);
LOG(INFO) << __func__ << ": Close is called.";
if (closed_) {
return {Exception::kSuccess};
}
if (stream_socket_listener_ != nullptr) {
stream_socket_listener_.ConnectionReceived(listener_event_token_);
stream_socket_listener_.Close();
stream_socket_listener_ = nullptr;
for (const auto &pending_socket : pending_sockets_) {
pending_socket.Close();
}
pending_sockets_ = {};
}
closed_ = true;
cond_.SignalAll();
if (close_notifier_ != nullptr) {
close_notifier_();
}
LOG(INFO) << __func__ << ": Close completed succesfully.";
return {Exception::kSuccess};
} catch (std::exception exception) {
closed_ = true;
cond_.SignalAll();
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
return {Exception::kIo};
} catch (const winrt::hresult_error &error) {
closed_ = true;
cond_.SignalAll();
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
<< winrt::to_string(error.message());
return {Exception::kIo};
} catch (...) {
closed_ = true;
cond_.SignalAll();
LOG(ERROR) << __func__ << ": Unknown exeption.";
return {Exception::kIo};
}
}
bool WifiDirectServerSocket::listen() {
// Get current IP addresses of the device.
for (int i = 0; i < kMaxRetries; i++) {
wifi_direct_go_ipaddr_ = GetDirectGOIpAddresses();
if (wifi_direct_go_ipaddr_.empty()) {
LOG(WARNING) << "Failed to find WifiDirect GO's IP addr for the try: "
<< i + 1 << ". Wait " << kRetryIntervalMilliSeconds
<< "ms snd try again";
Sleep(kRetryIntervalMilliSeconds);
} else {
break;
}
}
if (wifi_direct_go_ipaddr_.empty()) {
LOG(WARNING) << "Failed to start accepting connection without IP "
"addresses configured on computer.";
return false;
}
// Setup stream socket listener.
stream_socket_listener_ = StreamSocketListener();
stream_socket_listener_.Control().QualityOfService(
SocketQualityOfService::LowLatency);
stream_socket_listener_.Control().KeepAlive(true);
// Setup socket event of ConnectionReceived.
listener_event_token_ = stream_socket_listener_.ConnectionReceived(
{this, &WifiDirectServerSocket::Listener_ConnectionReceived});
try {
HostName host_name{winrt::to_hstring(wifi_direct_go_ipaddr_)};
stream_socket_listener_
.BindEndpointAsync(host_name, winrt::to_hstring(port_))
.get();
if (port_ == 0) {
port_ =
std::stoi(stream_socket_listener_.Information().LocalPort().c_str());
}
return true;
} catch (std::exception exception) {
LOG(ERROR) << __func__
<< ": Cannot accept connection on preferred port. Exception: "
<< exception.what();
} catch (const winrt::hresult_error &error) {
LOG(ERROR)
<< __func__
<< ":Cannot accept connection on preferred port. WinRT exception: "
<< error.code() << ": " << winrt::to_string(error.message());
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
}
try {
stream_socket_listener_.BindServiceNameAsync({}).get();
// need to save the port information.
port_ =
std::stoi(stream_socket_listener_.Information().LocalPort().c_str());
LOG(INFO) << "Server Socket port: " << port_;
return true;
} catch (std::exception exception) {
LOG(ERROR) << __func__
<< ": Cannot bind to any port. Exception: " << exception.what();
} catch (const winrt::hresult_error &error) {
LOG(ERROR) << __func__
<< ": Cannot bind to any port. WinRT exception: " << error.code()
<< ": " << winrt::to_string(error.message());
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
}
return false;
}
fire_and_forget WifiDirectServerSocket::Listener_ConnectionReceived(
StreamSocketListener listener,
StreamSocketListenerConnectionReceivedEventArgs const &args) {
absl::MutexLock lock(&mutex_);
LOG(INFO) << __func__ << ": Received connection.";
if (closed_) {
return fire_and_forget{};
}
pending_sockets_.push_back(args.Socket());
cond_.SignalAll();
return fire_and_forget{};
}
std::vector<std::string> WifiDirectServerSocket::GetIpAddresses() const {
std::vector<std::string> result{};
auto host_names = NetworkInformation::GetHostNames();
for (auto host_name : host_names) {
if (host_name.IPInformation() != nullptr &&
host_name.IPInformation().NetworkAdapter() != nullptr &&
host_name.Type() == HostNameType::Ipv4) {
std::string ipv4_s = winrt::to_string(host_name.ToString());
if (absl::EndsWith(ipv4_s, ".1")) {
LOG(INFO) << "Found WifiDirect GO IP: " << ipv4_s;
result.push_back(ipv4_s);
}
}
}
return result;
}
std::string WifiDirectServerSocket::GetDirectGOIpAddresses() const {
try {
for (int i = 0; i < kMaxRetries; i++) {
auto host_names = NetworkInformation::GetHostNames();
for (auto host_name : host_names) {
if (host_name.IPInformation() != nullptr &&
host_name.IPInformation().NetworkAdapter() != nullptr &&
host_name.Type() == HostNameType::Ipv4) {
std::string ipv4_s = winrt::to_string(host_name.ToString());
if (absl::EndsWith(ipv4_s, ".1")) {
// TODO(b/228541380): replace when we find a better way to
// identifying the WifiDirect GO IP address
LOG(INFO) << "Found WifiDirect GO IP: " << ipv4_s;
return ipv4_s;
}
}
}
}
return {};
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
return {};
} catch (const winrt::hresult_error &error) {
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
<< winrt::to_string(error.message());
return {};
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
return {};
}
}
} // namespace windows
} // namespace nearby
@@ -1,204 +0,0 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cstdint>
#include <cstring>
#include <exception>
#include "internal/platform/byte_array.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/windows/wifi_direct.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/logging.h"
#include "internal/platform/output_stream.h"
namespace nearby {
namespace windows {
WifiDirectSocket::WifiDirectSocket(StreamSocket socket) {
stream_soket_ = socket;
input_stream_ = SocketInputStream(socket.InputStream());
output_stream_ = SocketOutputStream(socket.OutputStream());
}
WifiDirectSocket::~WifiDirectSocket() {
try {
if (stream_soket_ != nullptr) {
Close();
}
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
<< winrt::to_string(error.message());
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
}
}
InputStream& WifiDirectSocket::GetInputStream() { return input_stream_; }
OutputStream& WifiDirectSocket::GetOutputStream() { return output_stream_; }
Exception WifiDirectSocket::Close() {
try {
if (stream_soket_ != nullptr) {
stream_soket_.Close();
}
return {Exception::kSuccess};
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
return {Exception::kIo};
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
<< winrt::to_string(error.message());
return {Exception::kIo};
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
return {Exception::kIo};
}
}
WifiDirectSocket::SocketInputStream::SocketInputStream(
IInputStream input_stream) {
input_stream_ = input_stream;
}
ExceptionOr<ByteArray> WifiDirectSocket::SocketInputStream::Read(
std::int64_t size) {
try {
Buffer buffer = Buffer(size);
auto ibuffer =
input_stream_.ReadAsync(buffer, size, InputStreamOptions::None).get();
if (ibuffer.Length() != size) {
LOG(WARNING) << "Only got part of data of needed.";
}
ByteArray data((char*)ibuffer.data(), ibuffer.Length());
return ExceptionOr(data);
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
return {Exception::kIo};
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
<< winrt::to_string(error.message());
return {Exception::kIo};
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
return {Exception::kIo};
}
}
ExceptionOr<size_t> WifiDirectSocket::SocketInputStream::Skip(size_t offset) {
try {
Buffer buffer = Buffer(offset);
auto ibuffer =
input_stream_.ReadAsync(buffer, offset, InputStreamOptions::None).get();
return ExceptionOr((size_t)ibuffer.Length());
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
return {Exception::kIo};
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
<< winrt::to_string(error.message());
return {Exception::kIo};
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
return {Exception::kIo};
}
}
Exception WifiDirectSocket::SocketInputStream::Close() {
try {
input_stream_.Close();
return {Exception::kSuccess};
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
return {Exception::kIo};
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
<< winrt::to_string(error.message());
return {Exception::kIo};
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
return {Exception::kIo};
}
}
// SocketOutputStream
WifiDirectSocket::SocketOutputStream::SocketOutputStream(
IOutputStream output_stream) {
output_stream_ = output_stream;
}
Exception WifiDirectSocket::SocketOutputStream::Write(const ByteArray& data) {
try {
Buffer buffer = Buffer(data.size());
std::memcpy(buffer.data(), data.data(), data.size());
buffer.Length(data.size());
output_stream_.WriteAsync(buffer).get();
return {Exception::kSuccess};
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
return {Exception::kIo};
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
<< winrt::to_string(error.message());
return {Exception::kIo};
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
return {Exception::kIo};
}
}
Exception WifiDirectSocket::SocketOutputStream::Flush() {
try {
output_stream_.FlushAsync().get();
return {Exception::kSuccess};
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
return {Exception::kIo};
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
<< winrt::to_string(error.message());
return {Exception::kIo};
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
return {Exception::kIo};
}
}
Exception WifiDirectSocket::SocketOutputStream::Close() {
try {
output_stream_.Close();
return {Exception::kSuccess};
} catch (std::exception exception) {
LOG(ERROR) << __func__ << ": Exception: " << exception.what();
return {Exception::kIo};
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << __func__ << ": WinRT exception: " << error.code() << ": "
<< winrt::to_string(error.message());
return {Exception::kIo};
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
return {Exception::kIo};
}
}
} // namespace windows
} // namespace nearby