Support blocking socket in Wi-Fi hotspot medium

PiperOrigin-RevId: 718006644
This commit is contained in:
Guogang Li
2025-01-21 11:42:56 -08:00
committed by Copybara-Service
parent d73d1d0515
commit b0be56bec8
4 changed files with 553 additions and 342 deletions
@@ -36,8 +36,11 @@
#include "absl/synchronization/mutex.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/cancelable.h"
#include "internal/platform/implementation/wifi_hotspot.h"
#include "internal/platform/implementation/windows/nearby_client_socket.h"
#include "internal/platform/implementation/windows/nearby_server_socket.h"
#include "internal/platform/implementation/windows/scheduled_executor.h"
#include "internal/platform/implementation/windows/submittable_executor.h"
#include "internal/platform/implementation/windows/wifi_hotspot_native.h"
@@ -55,6 +58,8 @@
#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"
#include "internal/platform/input_stream.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/wifi_credential.h"
namespace nearby {
@@ -109,6 +114,8 @@ using ::winrt::Windows::Networking::Sockets::
// remote WiFi Hotspot service, also will return a WifiHotspotSocket to caller.
class WifiHotspotSocket : public api::WifiHotspotSocket {
public:
WifiHotspotSocket();
explicit WifiHotspotSocket(std::unique_ptr<NearbyClientSocket> socket);
explicit WifiHotspotSocket(StreamSocket socket);
explicit WifiHotspotSocket(SOCKET socket);
WifiHotspotSocket(const WifiHotspotSocket&) = default;
@@ -134,6 +141,8 @@ class WifiHotspotSocket : public api::WifiHotspotSocket {
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
Exception Close() override;
bool Connect(const std::string& ip_address, int port);
private:
enum class SocketType { kWinRTSocket = 0, kWin32Socket };
// A simple wrapper to handle input stream of socket
@@ -141,6 +150,7 @@ class WifiHotspotSocket : public api::WifiHotspotSocket {
public:
explicit SocketInputStream(IInputStream input_stream);
explicit SocketInputStream(SOCKET socket);
explicit SocketInputStream(NearbyClientSocket* client_socket);
~SocketInputStream() override = default;
ExceptionOr<ByteArray> Read(std::int64_t size) override;
@@ -148,10 +158,12 @@ class WifiHotspotSocket : public api::WifiHotspotSocket {
Exception Close() override;
private:
bool enable_blocking_socket_ = false;
IInputStream input_stream_{nullptr};
SOCKET socket_ = INVALID_SOCKET;
SocketType socket_type_ = SocketType::kWinRTSocket;
ByteArray read_buffer_;
NearbyClientSocket* client_socket_{nullptr};
};
// A simple wrapper to handle output stream of socket
@@ -159,6 +171,7 @@ class WifiHotspotSocket : public api::WifiHotspotSocket {
public:
explicit SocketOutputStream(IOutputStream output_stream);
explicit SocketOutputStream(SOCKET socket);
explicit SocketOutputStream(NearbyClientSocket* client_socket);
~SocketOutputStream() override = default;
Exception Write(const ByteArray& data) override;
@@ -166,9 +179,11 @@ class WifiHotspotSocket : public api::WifiHotspotSocket {
Exception Close() override;
private:
bool enable_blocking_socket_ = false;
IOutputStream output_stream_{nullptr};
SOCKET socket_ = INVALID_SOCKET;
SocketType socket_type_ = SocketType::kWinRTSocket;
NearbyClientSocket* client_socket_{nullptr};
};
// Internal properties
@@ -176,6 +191,9 @@ class WifiHotspotSocket : public api::WifiHotspotSocket {
StreamSocket stream_soket_{nullptr};
SocketInputStream input_stream_{nullptr};
SocketOutputStream output_stream_{nullptr};
bool enable_blocking_socket_ = false;
std::unique_ptr<NearbyClientSocket> client_socket_;
};
// WifiHotspotServerSocket provides the support to server socket, this server
@@ -216,6 +234,10 @@ class WifiHotspotServerSocket : public api::WifiHotspotServerSocket {
// Binds to local port
bool listen();
// Flag to enable blocking socket.
bool enable_blocking_socket_ = false;
NearbyServerSocket server_socket_;
private:
static constexpr int kSocketEventsCount = 2;
static constexpr int kSocketEventListen = 0;
@@ -19,6 +19,7 @@
#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/byte_array.h"
#include "internal/platform/cancellation_flag.h"
@@ -97,9 +98,6 @@ std::unique_ptr<api::WifiHotspotSocket> WifiHotspotMedium::ConnectToService(
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 wifi_hotspot_max_connection_retries,
// because it may fail first time if DHCP procedure is not finished yet.
int64_t wifi_hotspot_max_connection_retries =
@@ -120,14 +118,17 @@ std::unique_ptr<api::WifiHotspotSocket> WifiHotspotMedium::ConnectToService(
<< ", connection interval=" << wifi_hotspot_retry_interval_millis
<< "ms, connection timeout="
<< wifi_hotspot_client_socket_connect_timeout_millis << "ms";
for (int i = 0; i < wifi_hotspot_max_connection_retries; i++) {
try {
StreamSocket socket{};
// Listener to connect cancellation.
std::unique_ptr<CancellationFlagListener>
connection_cancellation_listener = nullptr;
if (NearbyFlags::GetInstance().GetBoolFlag(
nearby::platform::config_package_nearby::nearby_platform_feature::
kEnableBlockingSocket)) {
LOG(INFO) << "Connect to service " << ipv4_address << ":" << port;
for (int i = 0; i < wifi_hotspot_max_connection_retries; ++i) {
auto wifi_hotspot_socket = std::make_unique<WifiHotspotSocket>();
// setup cancel listener
std::unique_ptr<CancellationFlagListener>
connection_cancellation_listener = nullptr;
if (cancellation_flag != nullptr) {
if (cancellation_flag->Cancelled()) {
LOG(INFO) << "connect has been cancelled to service " << ipv4_address
@@ -137,57 +138,100 @@ std::unique_ptr<api::WifiHotspotSocket> WifiHotspotMedium::ConnectToService(
connection_cancellation_listener =
std::make_unique<nearby::CancellationFlagListener>(
cancellation_flag, [socket]() {
cancellation_flag, [socket = wifi_hotspot_socket.get()]() {
LOG(WARNING) << "connect is closed due to it is cancelled.";
socket.Close();
socket->Close();
});
}
if (FeatureFlags::GetInstance().GetFlags().enable_connection_timeout) {
connection_timeout_ = scheduled_executor_.Schedule(
[socket]() {
LOG(WARNING) << "connect is closed due to timeout.";
socket.Close();
},
absl::Milliseconds(
wifi_hotspot_client_socket_connect_timeout_millis));
bool result = wifi_hotspot_socket->Connect(ipv4_address, port);
if (!result) {
LOG(WARNING) << "reconnect to service at " << (i + 1) << "th times";
Sleep(wifi_hotspot_retry_interval_millis);
continue;
}
socket.ConnectAsync(host_name, service_name).get();
LOG(INFO) << "connected to remote service " << ipv4_address << ":"
<< port;
return wifi_hotspot_socket;
}
LOG(ERROR) << "Failed to connect to service " << ipv4_address << ":"
<< port;
return nullptr;
} else {
HostName host_name{winrt::to_hstring(ipv4_address)};
winrt::hstring service_name{winrt::to_hstring(port)};
for (int i = 0; i < wifi_hotspot_max_connection_retries; i++) {
try {
StreamSocket socket{};
// Listener to connect cancellation.
std::unique_ptr<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();
});
}
if (FeatureFlags::GetInstance().GetFlags().enable_connection_timeout) {
connection_timeout_ = scheduled_executor_.Schedule(
[socket]() {
LOG(WARNING) << "connect is closed due to timeout.";
socket.Close();
},
absl::Milliseconds(
wifi_hotspot_client_socket_connect_timeout_millis));
}
socket.ConnectAsync(host_name, service_name).get();
if (connection_timeout_ != nullptr) {
connection_timeout_->Cancel();
connection_timeout_ = nullptr;
}
auto wifi_hotspot_socket = std::make_unique<WifiHotspotSocket>(socket);
LOG(INFO) << "connected to remote service " << ipv4_address << ":"
<< port;
return wifi_hotspot_socket;
} catch (std::exception exception) {
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
<< port << " for the " << i + 1
<< " time. Exception: " << exception.what();
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
<< port << " for the " << i + 1
<< " time. WinRT exception: " << error.code() << ": "
<< winrt::to_string(error.message());
} catch (...) {
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
<< port << " for the " << i + 1
<< " time due to unknown reason.";
}
if (connection_timeout_ != nullptr) {
connection_timeout_->Cancel();
connection_timeout_ = nullptr;
}
auto wifi_hotspot_socket = std::make_unique<WifiHotspotSocket>(socket);
LOG(INFO) << "connected to remote service " << ipv4_address << ":"
<< port;
return wifi_hotspot_socket;
} catch (std::exception exception) {
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
<< port << " for the " << i + 1
<< " time. Exception: " << exception.what();
} catch (const winrt::hresult_error& error) {
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
<< port << " for the " << i + 1
<< " time. WinRT exception: " << error.code() << ": "
<< winrt::to_string(error.message());
} catch (...) {
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
<< port << " for the " << i + 1
<< " time due to unknown reason.";
Sleep(wifi_hotspot_retry_interval_millis);
}
if (connection_timeout_ != nullptr) {
connection_timeout_->Cancel();
connection_timeout_ = nullptr;
}
Sleep(wifi_hotspot_retry_interval_millis);
return nullptr;
}
return nullptr;
}
std::unique_ptr<api::WifiHotspotServerSocket>
@@ -401,10 +445,9 @@ fire_and_forget WifiHotspotMedium::OnConnectionRequested(
// We found new connection request comes in during hotspot transfer. In this
// case, we should create a new WiFiDirectDevice for it. It will cause
// transfer failure if replace the old WiFiDirectDevice with it.
auto wifi_direct_device =
WiFiDirectDevice::FromIdAsync(
connection_request.DeviceInformation().Id())
.get();
auto wifi_direct_device = WiFiDirectDevice::FromIdAsync(
connection_request.DeviceInformation().Id())
.get();
wifi_direct_devices_.push_back(wifi_direct_device);
LOG(INFO) << "Registered the device " << winrt::to_string(device_name)
<< " in WLAN-AutoConfig";
@@ -14,17 +14,23 @@
#include <windows.h>
#include <cstdint>
#include <exception>
#include <memory>
#include <string>
#include <utility>
#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/flags/nearby_flags.h"
#include "internal/platform/exception.h"
#include "internal/platform/flags/nearby_platform_feature_flags.h"
#include "internal/platform/implementation/wifi_hotspot.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_hotspot.h"
@@ -37,78 +43,102 @@ using ::winrt::Windows::Networking::Sockets::SocketQualityOfService;
} // namespace
WifiHotspotServerSocket::WifiHotspotServerSocket(int port) : port_(port) {
for (auto &it : socket_events_) {
it = WSA_INVALID_EVENT;
enable_blocking_socket_ = NearbyFlags::GetInstance().GetBoolFlag(
nearby::platform::config_package_nearby::nearby_platform_feature::
kEnableBlockingSocket);
if (!enable_blocking_socket_) {
for (auto &it : socket_events_) {
it = WSA_INVALID_EVENT;
}
}
}
WifiHotspotServerSocket::~WifiHotspotServerSocket() { Close(); }
std::string WifiHotspotServerSocket::GetIPAddress() const {
if (NearbyFlags::GetInstance().GetBoolFlag(
platform::config_package_nearby::nearby_platform_feature::
kEnableHotspotWin32Socket)) {
if (listen_socket_ == INVALID_SOCKET) {
return {};
}
if (enable_blocking_socket_) {
return server_socket_.GetIPAddress();
} else {
if (stream_socket_listener_ == nullptr) {
return {};
if (NearbyFlags::GetInstance().GetBoolFlag(
platform::config_package_nearby::nearby_platform_feature::
kEnableHotspotWin32Socket)) {
if (listen_socket_ == INVALID_SOCKET) {
return {};
}
} else {
if (stream_socket_listener_ == nullptr) {
return {};
}
}
std::string hotspot_ip_address = GetHotspotIpAddress();
LOG(INFO) << __func__
<< ": Return hotspot IP address: " << hotspot_ip_address;
return hotspot_ip_address;
}
std::string hotspot_ip_address = GetHotspotIpAddress();
LOG(INFO) << __func__
<< ": Return hotspot IP address: " << hotspot_ip_address;
return hotspot_ip_address;
}
int WifiHotspotServerSocket::GetPort() const {
if (NearbyFlags::GetInstance().GetBoolFlag(
platform::config_package_nearby::nearby_platform_feature::
kEnableHotspotWin32Socket)) {
if (listen_socket_ == INVALID_SOCKET) {
LOG(WARNING) << __func__ << ": listen_socket_ is invalid.";
return 0;
}
return port_;
if (enable_blocking_socket_) {
return server_socket_.GetPort();
} else {
if (stream_socket_listener_ == nullptr) {
return 0;
if (NearbyFlags::GetInstance().GetBoolFlag(
platform::config_package_nearby::nearby_platform_feature::
kEnableHotspotWin32Socket)) {
if (listen_socket_ == INVALID_SOCKET) {
LOG(WARNING) << __func__ << ": listen_socket_ is invalid.";
return 0;
}
return port_;
} else {
if (stream_socket_listener_ == nullptr) {
return 0;
}
return std::stoi(
stream_socket_listener_.Information().LocalPort().c_str());
}
return std::stoi(stream_socket_listener_.Information().LocalPort().c_str());
}
}
std::unique_ptr<api::WifiHotspotSocket> WifiHotspotServerSocket::Accept() {
absl::MutexLock lock(&mutex_);
LOG(INFO) << __func__ << ": Accept is called.";
if (enable_blocking_socket_) {
auto client_socket = server_socket_.Accept();
if (client_socket == nullptr) {
return nullptr;
}
if (NearbyFlags::GetInstance().GetBoolFlag(
platform::config_package_nearby::nearby_platform_feature::
kEnableHotspotWin32Socket)) {
while (!closed_ && pending_client_sockets_.empty()) {
LOG(INFO) << __func__ << ": Accepted a remote connection.";
return std::make_unique<WifiHotspotSocket>(std::move(client_socket));
} else {
absl::MutexLock lock(&mutex_);
LOG(INFO) << __func__ << ": Accept is called.";
if (NearbyFlags::GetInstance().GetBoolFlag(
platform::config_package_nearby::nearby_platform_feature::
kEnableHotspotWin32Socket)) {
while (!closed_ && pending_client_sockets_.empty()) {
cond_.Wait(&mutex_);
}
if (closed_) return {};
SOCKET wifi_hotspot_socket = pending_client_sockets_.front();
pending_client_sockets_.pop_front();
LOG(INFO) << __func__ << ": Accepted a remote connection.";
return std::make_unique<WifiHotspotSocket>(wifi_hotspot_socket);
}
// Code when using WinRT API
while (!closed_ && pending_sockets_.empty()) {
cond_.Wait(&mutex_);
}
if (closed_) return {};
SOCKET wifi_hotspot_socket = pending_client_sockets_.front();
pending_client_sockets_.pop_front();
StreamSocket wifi_hotspot_socket = pending_sockets_.front();
pending_sockets_.pop_front();
LOG(INFO) << __func__ << ": Accepted a remote connection.";
return std::make_unique<WifiHotspotSocket>(wifi_hotspot_socket);
}
// Code when using WinRT API
while (!closed_ && pending_sockets_.empty()) {
cond_.Wait(&mutex_);
}
if (closed_) return {};
StreamSocket wifi_hotspot_socket = pending_sockets_.front();
pending_sockets_.pop_front();
LOG(INFO) << __func__ << ": Accepted a remote connection.";
return std::make_unique<WifiHotspotSocket>(wifi_hotspot_socket);
}
void WifiHotspotServerSocket::SetCloseNotifier(
@@ -119,55 +149,70 @@ void WifiHotspotServerSocket::SetCloseNotifier(
Exception WifiHotspotServerSocket::Close() {
try {
absl::MutexLock lock(&mutex_);
LOG(INFO) << __func__ << ": Close is called.";
if (closed_) {
return {Exception::kSuccess};
}
if (NearbyFlags::GetInstance().GetBoolFlag(
platform::config_package_nearby::nearby_platform_feature::
kEnableHotspotWin32Socket)) {
if (listen_socket_ != INVALID_SOCKET) {
LOG(INFO) << ": Close listen_socket_: " << listen_socket_;
// Trigger close event manually
WSASetEvent(socket_events_[kSocketEventClose]);
shutdown(listen_socket_, 2);
shutdown(client_socket_, 2);
closesocket(listen_socket_);
closesocket(client_socket_);
for (const auto &pending_socket : pending_client_sockets_) {
if (pending_socket != INVALID_SOCKET) closesocket(pending_socket);
}
submittable_executor_.Shutdown();
listen_socket_ = INVALID_SOCKET;
client_socket_ = INVALID_SOCKET;
for (auto &it : socket_events_) {
WSACloseEvent(it);
it = WSA_INVALID_EVENT;
}
WSACleanup();
pending_client_sockets_ = {};
if (enable_blocking_socket_) {
if (closed_) {
return {Exception::kSuccess};
}
server_socket_.Close();
closed_ = true;
if (close_notifier_ != nullptr) {
close_notifier_();
}
LOG(INFO) << __func__ << ": Close completed successfully.";
} else {
if (stream_socket_listener_ != nullptr) {
stream_socket_listener_.ConnectionReceived(listener_event_token_);
stream_socket_listener_.Close();
stream_socket_listener_ = nullptr;
LOG(INFO) << __func__ << ": Close is called.";
for (const auto &pending_socket : pending_sockets_) {
pending_socket.Close();
}
pending_sockets_ = {};
if (closed_) {
return {Exception::kSuccess};
}
}
closed_ = true;
cond_.SignalAll();
if (close_notifier_ != nullptr) {
close_notifier_();
if (NearbyFlags::GetInstance().GetBoolFlag(
platform::config_package_nearby::nearby_platform_feature::
kEnableHotspotWin32Socket)) {
if (listen_socket_ != INVALID_SOCKET) {
LOG(INFO) << ": Close listen_socket_: " << listen_socket_;
// Trigger close event manually
WSASetEvent(socket_events_[kSocketEventClose]);
shutdown(listen_socket_, 2);
shutdown(client_socket_, 2);
closesocket(listen_socket_);
closesocket(client_socket_);
for (const auto &pending_socket : pending_client_sockets_) {
if (pending_socket != INVALID_SOCKET) closesocket(pending_socket);
}
submittable_executor_.Shutdown();
listen_socket_ = INVALID_SOCKET;
client_socket_ = INVALID_SOCKET;
for (auto &it : socket_events_) {
WSACloseEvent(it);
it = WSA_INVALID_EVENT;
}
WSACleanup();
pending_client_sockets_ = {};
}
} else {
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.";
@@ -186,7 +231,7 @@ Exception WifiHotspotServerSocket::Close() {
} catch (...) {
closed_ = true;
cond_.SignalAll();
LOG(ERROR) << __func__ << ": Unknown exeption.";
LOG(ERROR) << __func__ << ": Unknown exception.";
return {Exception::kIo};
}
}
@@ -240,7 +285,7 @@ bool WifiHotspotServerSocket::SetupServerSocketWinRT() {
<< ":Cannot accept connection on preferred port. WinRT exception: "
<< error.code() << ": " << winrt::to_string(error.message());
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
LOG(ERROR) << __func__ << ": Unknown exception.";
}
try {
@@ -258,7 +303,7 @@ bool WifiHotspotServerSocket::SetupServerSocketWinRT() {
<< ": Cannot bind to any port. WinRT exception: " << error.code()
<< ": " << winrt::to_string(error.message());
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
LOG(ERROR) << __func__ << ": Unknown exception.";
}
return false;
@@ -436,12 +481,21 @@ bool WifiHotspotServerSocket::listen() {
return false;
}
if (NearbyFlags::GetInstance().GetBoolFlag(
platform::config_package_nearby::nearby_platform_feature::
kEnableHotspotWin32Socket)) {
return SetupServerSocketWinSock();
if (enable_blocking_socket_) {
if (!server_socket_.Listen(hotspot_ipaddr_, port_)) {
LOG(ERROR) << "Failed to listen socket.";
return false;
}
return true;
} else {
return SetupServerSocketWinRT();
if (NearbyFlags::GetInstance().GetBoolFlag(
platform::config_package_nearby::nearby_platform_feature::
kEnableHotspotWin32Socket)) {
return SetupServerSocketWinSock();
} else {
return SetupServerSocketWinRT();
}
}
}
@@ -489,7 +543,7 @@ std::string WifiHotspotServerSocket::GetHotspotIpAddress() const {
<< winrt::to_string(error.message());
return {};
} catch (...) {
LOG(ERROR) << __func__ << ": Unknown exeption.";
LOG(ERROR) << __func__ << ": Unknown exception.";
return {};
}
}
@@ -15,9 +15,15 @@
#include <cstdint>
#include <cstring>
#include <exception>
#include <memory>
#include <string>
#include <utility>
#include "internal/flags/nearby_flags.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/exception.h"
#include "internal/platform/flags/nearby_platform_feature_flags.h"
#include "internal/platform/implementation/windows/nearby_client_socket.h"
#include "internal/platform/implementation/windows/wifi_hotspot.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/logging.h"
@@ -79,6 +85,15 @@ int send_sync(SOCKET s, const char* buf, int len, int flags) {
} // namespace
WifiHotspotSocket::WifiHotspotSocket() {
enable_blocking_socket_ = NearbyFlags::GetInstance().GetBoolFlag(
nearby::platform::config_package_nearby::nearby_platform_feature::
kEnableBlockingSocket);
client_socket_ = std::make_unique<NearbyClientSocket>();
input_stream_ = SocketInputStream(client_socket_.get());
output_stream_ = SocketOutputStream(client_socket_.get());
}
WifiHotspotSocket::WifiHotspotSocket(StreamSocket socket) {
stream_soket_ = socket;
input_stream_ = SocketInputStream(socket.InputStream());
@@ -91,48 +106,57 @@ WifiHotspotSocket::WifiHotspotSocket(SOCKET socket) {
output_stream_ = SocketOutputStream(socket);
}
WifiHotspotSocket::~WifiHotspotSocket() {
try {
if (stream_soket_ != nullptr || stream_soket_winsock_ != INVALID_SOCKET) {
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.";
}
WifiHotspotSocket::WifiHotspotSocket(
std::unique_ptr<NearbyClientSocket> socket) {
enable_blocking_socket_ = NearbyFlags::GetInstance().GetBoolFlag(
nearby::platform::config_package_nearby::nearby_platform_feature::
kEnableBlockingSocket);
client_socket_ = std::move(socket);
input_stream_ = SocketInputStream(client_socket_.get());
output_stream_ = SocketOutputStream(client_socket_.get());
}
WifiHotspotSocket::~WifiHotspotSocket() { Close(); }
InputStream& WifiHotspotSocket::GetInputStream() { return input_stream_; }
OutputStream& WifiHotspotSocket::GetOutputStream() { return output_stream_; }
Exception WifiHotspotSocket::Close() {
try {
if (stream_soket_ != nullptr) {
stream_soket_.Close();
}
if (stream_soket_winsock_ != INVALID_SOCKET) {
closesocket(stream_soket_winsock_);
stream_soket_winsock_ = INVALID_SOCKET;
if (enable_blocking_socket_) {
if (client_socket_ != nullptr) {
return client_socket_->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};
} else {
try {
if (stream_soket_ != nullptr) {
stream_soket_.Close();
}
if (stream_soket_winsock_ != INVALID_SOCKET) {
closesocket(stream_soket_winsock_);
stream_soket_winsock_ = INVALID_SOCKET;
}
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 exception.";
return {Exception::kIo};
}
}
}
bool WifiHotspotSocket::Connect(const std::string& ip_address, int port) {
return client_socket_->Connect(ip_address, port);
}
WifiHotspotSocket::SocketInputStream::SocketInputStream(
IInputStream input_stream) {
input_stream_ = input_stream;
@@ -144,125 +168,160 @@ WifiHotspotSocket::SocketInputStream::SocketInputStream(SOCKET socket) {
socket_type_ = SocketType::kWin32Socket;
}
WifiHotspotSocket::SocketInputStream::SocketInputStream(
NearbyClientSocket* client_socket) {
enable_blocking_socket_ = NearbyFlags::GetInstance().GetBoolFlag(
nearby::platform::config_package_nearby::nearby_platform_feature::
kEnableBlockingSocket);
client_socket_ = client_socket;
}
ExceptionOr<ByteArray> WifiHotspotSocket::SocketInputStream::Read(
std::int64_t size) {
try {
if (socket_type_ == SocketType::kWinRTSocket) {
Buffer buffer = Buffer(size);
if (enable_blocking_socket_) {
if (client_socket_ == nullptr) {
LOG(ERROR) << "Failed to read data due to no client socket.";
return {Exception::kIo};
}
auto ibuffer =
input_stream_.ReadAsync(buffer, size, InputStreamOptions::None).get();
return client_socket_->Read(size);
} else {
try {
if (socket_type_ == SocketType::kWinRTSocket) {
Buffer buffer = Buffer(size);
if (ibuffer.Length() != size) {
LOG(WARNING) << "Only got part of data of needed.";
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<ByteArray>(data);
}
ByteArray data((char*)ibuffer.data(), ibuffer.Length());
int result;
int count = 0;
// When socket_type_ == SocketType::kWin32Socket
if (size > read_buffer_.size()) {
read_buffer_.resize(size);
}
while (count < size) {
result =
recv_sync(socket_, read_buffer_.data() + count, size - count, 0);
if (result == 0) {
LOG(WARNING) << "Connection closed.";
return {Exception::kIo};
} else if (result < 0) {
LOG(ERROR) << "recv failed with error: " << WSAGetLastError();
return {Exception::kIo};
} else {
count += result;
}
}
ByteArray data(read_buffer_.data(), size);
return ExceptionOr<ByteArray>(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 exception.";
return {Exception::kIo};
}
int result;
int count = 0;
// When socket_type_ == SocketType::kWin32Socket
if (size > read_buffer_.size()) {
read_buffer_.resize(size);
}
while (count < size) {
result = recv_sync(socket_, read_buffer_.data() + count, size - count, 0);
if (result == 0) {
LOG(WARNING) << "Connection closed.";
return {Exception::kIo};
} else if (result < 0) {
LOG(ERROR) << "recv failed with error: " << WSAGetLastError();
return {Exception::kIo};
} else {
count += result;
}
}
ByteArray data(read_buffer_.data(), size);
return ExceptionOr<ByteArray>(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> WifiHotspotSocket::SocketInputStream::Skip(size_t offset) {
try {
if (socket_type_ == SocketType::kWinRTSocket) {
Buffer buffer = Buffer(offset);
auto ibuffer =
input_stream_.ReadAsync(buffer, offset, InputStreamOptions::None)
.get();
return ExceptionOr<size_t>((size_t)ibuffer.Length());
}
// When socket_type_ == SocketType::kWin32Socket
int result;
int count = 0;
// When socket_type_ == SocketType::kWin32Socket
if (offset > read_buffer_.size()) {
read_buffer_.resize(offset);
if (enable_blocking_socket_) {
if (client_socket_ == nullptr) {
return {Exception::kIo};
}
while (count < offset) {
result =
recv_sync(socket_, read_buffer_.data() + count, offset - count, 0);
if (result == 0) {
LOG(WARNING) << "Connection closed.";
return {Exception::kIo};
} else if (result < 0) {
LOG(ERROR) << "recv failed with error: " << WSAGetLastError();
return {Exception::kIo};
} else {
count += result;
return client_socket_->Skip(offset);
} else {
try {
if (socket_type_ == SocketType::kWinRTSocket) {
Buffer buffer = Buffer(offset);
auto ibuffer =
input_stream_.ReadAsync(buffer, offset, InputStreamOptions::None)
.get();
return ExceptionOr<size_t>((size_t)ibuffer.Length());
}
}
// When socket_type_ == SocketType::kWin32Socket
int result;
int count = 0;
return ExceptionOr<size_t>(offset);
} 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};
// When socket_type_ == SocketType::kWin32Socket
if (offset > read_buffer_.size()) {
read_buffer_.resize(offset);
}
while (count < offset) {
result =
recv_sync(socket_, read_buffer_.data() + count, offset - count, 0);
if (result == 0) {
LOG(WARNING) << "Connection closed.";
return {Exception::kIo};
} else if (result < 0) {
LOG(ERROR) << "recv failed with error: " << WSAGetLastError();
return {Exception::kIo};
} else {
count += result;
}
}
return ExceptionOr<size_t>(offset);
} 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 exception.";
return {Exception::kIo};
}
}
}
Exception WifiHotspotSocket::SocketInputStream::Close() {
try {
if (socket_type_ == SocketType::kWinRTSocket) {
input_stream_.Close();
} else {
// When socket_type_ == SocketType::kWin32Socket
shutdown(socket_, SD_RECEIVE);
if (enable_blocking_socket_) {
if (client_socket_ == nullptr) {
return {Exception::kIo};
}
return client_socket_->Close();
} else {
try {
if (socket_type_ == SocketType::kWinRTSocket) {
input_stream_.Close();
} else {
// When socket_type_ == SocketType::kWin32Socket
shutdown(socket_, SD_RECEIVE);
}
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 exception.";
return {Exception::kIo};
}
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};
}
}
@@ -278,87 +337,120 @@ WifiHotspotSocket::SocketOutputStream::SocketOutputStream(SOCKET socket) {
socket_type_ = SocketType::kWin32Socket;
}
WifiHotspotSocket::SocketOutputStream::SocketOutputStream(
NearbyClientSocket* client_socket) {
enable_blocking_socket_ = NearbyFlags::GetInstance().GetBoolFlag(
nearby::platform::config_package_nearby::nearby_platform_feature::
kEnableBlockingSocket);
client_socket_ = client_socket;
}
Exception WifiHotspotSocket::SocketOutputStream::Write(const ByteArray& data) {
try {
if (socket_type_ == SocketType::kWinRTSocket) {
Buffer buffer = Buffer(data.size());
std::memcpy(buffer.data(), data.data(), data.size());
buffer.Length(data.size());
if (enable_blocking_socket_) {
if (client_socket_ == nullptr) {
return {Exception::kIo};
}
return client_socket_->Write(data);
} else {
try {
if (socket_type_ == SocketType::kWinRTSocket) {
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};
}
int result;
int count = 0;
while (count < data.size()) {
result =
send_sync(socket_, data.data() + count, data.size() - count, 0);
if (result == 0) {
LOG(WARNING) << "Connection closed.";
return {Exception::kIo};
} else if (result < 0) {
LOG(ERROR) << "Failed to send data with error: " << WSAGetLastError();
return {Exception::kIo};
} else {
count += result;
}
}
output_stream_.WriteAsync(buffer).get();
return {Exception::kSuccess};
}
int result;
int count = 0;
while (count < data.size()) {
result = send_sync(socket_, data.data() + count, data.size() - count, 0);
if (result == 0) {
LOG(WARNING) << "Connection closed.";
return {Exception::kIo};
} else if (result < 0) {
LOG(ERROR) << "Failed to send data with error: " << WSAGetLastError();
return {Exception::kIo};
} else {
count += result;
}
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 exception.";
return {Exception::kIo};
}
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 WifiHotspotSocket::SocketOutputStream::Flush() {
try {
if (socket_type_ == SocketType::kWinRTSocket) {
output_stream_.FlushAsync().get();
if (enable_blocking_socket_) {
if (client_socket_ == nullptr) {
return {Exception::kIo};
}
return client_socket_->Flush();
} else {
try {
if (socket_type_ == SocketType::kWinRTSocket) {
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 exception.";
return {Exception::kIo};
}
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 WifiHotspotSocket::SocketOutputStream::Close() {
try {
if (socket_type_ == SocketType::kWinRTSocket) {
output_stream_.Close();
} else {
// When socket_type_ == SocketType::kWin32Socket
shutdown(socket_, SD_SEND);
if (enable_blocking_socket_) {
if (client_socket_ == nullptr) {
return {Exception::kIo};
}
return client_socket_->Close();
} else {
try {
if (socket_type_ == SocketType::kWinRTSocket) {
output_stream_.Close();
} else {
// When socket_type_ == SocketType::kWin32Socket
shutdown(socket_, SD_SEND);
}
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 exception.";
return {Exception::kIo};
}
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};
}
}