Skip to content

Commit 2039e66

Browse files
ggli-googlecopybara-github
authored andcommitted
Support blocking socket in Wi-Fi hotspot medium
PiperOrigin-RevId: 713741103
1 parent 5bceb99 commit 2039e66

8 files changed

+1095
-646
lines changed

internal/platform/implementation/windows/wifi_hotspot.h

+22
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,11 @@
3636
#include "absl/synchronization/mutex.h"
3737
#include "internal/platform/byte_array.h"
3838
#include "internal/platform/cancellation_flag.h"
39+
#include "internal/platform/exception.h"
3940
#include "internal/platform/implementation/cancelable.h"
4041
#include "internal/platform/implementation/wifi_hotspot.h"
42+
#include "internal/platform/implementation/windows/nearby_client_socket.h"
43+
#include "internal/platform/implementation/windows/nearby_server_socket.h"
4144
#include "internal/platform/implementation/windows/scheduled_executor.h"
4245
#include "internal/platform/implementation/windows/submittable_executor.h"
4346
#include "internal/platform/implementation/windows/wifi_hotspot_native.h"
@@ -55,6 +58,8 @@
5558
#include "internal/platform/implementation/windows/generated/winrt/Windows.Security.Cryptography.h"
5659
#include "internal/platform/implementation/windows/generated/winrt/Windows.Storage.Streams.h"
5760
#include "internal/platform/implementation/windows/generated/winrt/base.h"
61+
#include "internal/platform/input_stream.h"
62+
#include "internal/platform/output_stream.h"
5863
#include "internal/platform/wifi_credential.h"
5964

6065
namespace nearby {
@@ -109,6 +114,8 @@ using ::winrt::Windows::Networking::Sockets::
109114
// remote WiFi Hotspot service, also will return a WifiHotspotSocket to caller.
110115
class WifiHotspotSocket : public api::WifiHotspotSocket {
111116
public:
117+
WifiHotspotSocket();
118+
explicit WifiHotspotSocket(std::unique_ptr<NearbyClientSocket> socket);
112119
explicit WifiHotspotSocket(StreamSocket socket);
113120
explicit WifiHotspotSocket(SOCKET socket);
114121
WifiHotspotSocket(const WifiHotspotSocket&) = default;
@@ -134,48 +141,59 @@ class WifiHotspotSocket : public api::WifiHotspotSocket {
134141
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
135142
Exception Close() override;
136143

144+
bool Connect(const std::string& ip_address, int port);
145+
137146
private:
138147
enum class SocketType { kWinRTSocket = 0, kWin32Socket };
139148
// A simple wrapper to handle input stream of socket
140149
class SocketInputStream : public InputStream {
141150
public:
142151
explicit SocketInputStream(IInputStream input_stream);
143152
explicit SocketInputStream(SOCKET socket);
153+
explicit SocketInputStream(NearbyClientSocket* client_socket);
144154
~SocketInputStream() override = default;
145155

146156
ExceptionOr<ByteArray> Read(std::int64_t size) override;
147157
ExceptionOr<size_t> Skip(size_t offset) override;
148158
Exception Close() override;
149159

150160
private:
161+
bool enable_blocking_socket_ = false;
151162
IInputStream input_stream_{nullptr};
152163
SOCKET socket_ = INVALID_SOCKET;
153164
SocketType socket_type_ = SocketType::kWinRTSocket;
154165
ByteArray read_buffer_;
166+
NearbyClientSocket* client_socket_{nullptr};
155167
};
156168

157169
// A simple wrapper to handle output stream of socket
158170
class SocketOutputStream : public OutputStream {
159171
public:
160172
explicit SocketOutputStream(IOutputStream output_stream);
161173
explicit SocketOutputStream(SOCKET socket);
174+
explicit SocketOutputStream(NearbyClientSocket* client_socket);
162175
~SocketOutputStream() override = default;
163176

164177
Exception Write(const ByteArray& data) override;
165178
Exception Flush() override;
166179
Exception Close() override;
167180

168181
private:
182+
bool enable_blocking_socket_ = false;
169183
IOutputStream output_stream_{nullptr};
170184
SOCKET socket_ = INVALID_SOCKET;
171185
SocketType socket_type_ = SocketType::kWinRTSocket;
186+
NearbyClientSocket* client_socket_{nullptr};
172187
};
173188

174189
// Internal properties
175190
SOCKET stream_soket_winsock_ = INVALID_SOCKET;
176191
StreamSocket stream_soket_{nullptr};
177192
SocketInputStream input_stream_{nullptr};
178193
SocketOutputStream output_stream_{nullptr};
194+
195+
bool enable_blocking_socket_ = false;
196+
std::unique_ptr<NearbyClientSocket> client_socket_;
179197
};
180198

181199
// WifiHotspotServerSocket provides the support to server socket, this server
@@ -216,6 +234,10 @@ class WifiHotspotServerSocket : public api::WifiHotspotServerSocket {
216234
// Binds to local port
217235
bool listen();
218236

237+
// Flag to enable blocking socket.
238+
bool enable_blocking_socket_ = false;
239+
NearbyServerSocket server_socket_;
240+
219241
private:
220242
static constexpr int kSocketEventsCount = 2;
221243
static constexpr int kSocketEventListen = 0;

internal/platform/implementation/windows/wifi_hotspot_medium.cc

+93-50
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "absl/strings/str_format.h"
2020
#include "absl/strings/string_view.h"
2121
#include "absl/synchronization/mutex.h"
22+
#include "absl/time/time.h"
2223
#include "internal/flags/nearby_flags.h"
2324
#include "internal/platform/byte_array.h"
2425
#include "internal/platform/cancellation_flag.h"
@@ -97,9 +98,6 @@ std::unique_ptr<api::WifiHotspotSocket> WifiHotspotMedium::ConnectToService(
9798
return nullptr;
9899
}
99100

100-
HostName host_name{winrt::to_hstring(ipv4_address)};
101-
winrt::hstring service_name{winrt::to_hstring(port)};
102-
103101
// Try connecting to the service up to wifi_hotspot_max_connection_retries,
104102
// because it may fail first time if DHCP procedure is not finished yet.
105103
int64_t wifi_hotspot_max_connection_retries =
@@ -120,14 +118,17 @@ std::unique_ptr<api::WifiHotspotSocket> WifiHotspotMedium::ConnectToService(
120118
<< ", connection interval=" << wifi_hotspot_retry_interval_millis
121119
<< "ms, connection timeout="
122120
<< wifi_hotspot_client_socket_connect_timeout_millis << "ms";
123-
for (int i = 0; i < wifi_hotspot_max_connection_retries; i++) {
124-
try {
125-
StreamSocket socket{};
126-
// Listener to connect cancellation.
127-
std::unique_ptr<CancellationFlagListener>
128-
connection_cancellation_listener = nullptr;
121+
122+
if (NearbyFlags::GetInstance().GetBoolFlag(
123+
nearby::platform::config_package_nearby::nearby_platform_feature::
124+
kEnableBlockingSocket)) {
125+
LOG(INFO) << "Connect to service " << ipv4_address << ":" << port;
126+
for (int i = 0; i < wifi_hotspot_max_connection_retries; ++i) {
127+
auto wifi_hotspot_socket = std::make_unique<WifiHotspotSocket>();
129128

130129
// setup cancel listener
130+
std::unique_ptr<CancellationFlagListener>
131+
connection_cancellation_listener = nullptr;
131132
if (cancellation_flag != nullptr) {
132133
if (cancellation_flag->Cancelled()) {
133134
LOG(INFO) << "connect has been cancelled to service " << ipv4_address
@@ -137,57 +138,100 @@ std::unique_ptr<api::WifiHotspotSocket> WifiHotspotMedium::ConnectToService(
137138

138139
connection_cancellation_listener =
139140
std::make_unique<nearby::CancellationFlagListener>(
140-
cancellation_flag, [socket]() {
141+
cancellation_flag, [socket = wifi_hotspot_socket.get()]() {
141142
LOG(WARNING) << "connect is closed due to it is cancelled.";
142-
socket.Close();
143+
socket->Close();
143144
});
144145
}
145146

146-
if (FeatureFlags::GetInstance().GetFlags().enable_connection_timeout) {
147-
connection_timeout_ = scheduled_executor_.Schedule(
148-
[socket]() {
149-
LOG(WARNING) << "connect is closed due to timeout.";
150-
socket.Close();
151-
},
152-
absl::Milliseconds(
153-
wifi_hotspot_client_socket_connect_timeout_millis));
147+
bool result = wifi_hotspot_socket->Connect(ipv4_address, port);
148+
if (!result) {
149+
LOG(WARNING) << "reconnect to service at " << (i + 1) << "th times";
150+
Sleep(wifi_hotspot_retry_interval_millis);
151+
continue;
154152
}
155153

156-
socket.ConnectAsync(host_name, service_name).get();
154+
LOG(INFO) << "connected to remote service " << ipv4_address << ":"
155+
<< port;
156+
return wifi_hotspot_socket;
157+
}
158+
159+
LOG(ERROR) << "Failed to connect to service " << ipv4_address << ":"
160+
<< port;
161+
return nullptr;
162+
} else {
163+
HostName host_name{winrt::to_hstring(ipv4_address)};
164+
winrt::hstring service_name{winrt::to_hstring(port)};
165+
166+
for (int i = 0; i < wifi_hotspot_max_connection_retries; i++) {
167+
try {
168+
StreamSocket socket{};
169+
// Listener to connect cancellation.
170+
std::unique_ptr<CancellationFlagListener>
171+
connection_cancellation_listener = nullptr;
172+
173+
// setup cancel listener
174+
if (cancellation_flag != nullptr) {
175+
if (cancellation_flag->Cancelled()) {
176+
LOG(INFO) << "connect has been cancelled to service "
177+
<< ipv4_address << ":" << port;
178+
return nullptr;
179+
}
180+
181+
connection_cancellation_listener =
182+
std::make_unique<nearby::CancellationFlagListener>(
183+
cancellation_flag, [socket]() {
184+
LOG(WARNING) << "connect is closed due to it is cancelled.";
185+
socket.Close();
186+
});
187+
}
188+
189+
if (FeatureFlags::GetInstance().GetFlags().enable_connection_timeout) {
190+
connection_timeout_ = scheduled_executor_.Schedule(
191+
[socket]() {
192+
LOG(WARNING) << "connect is closed due to timeout.";
193+
socket.Close();
194+
},
195+
absl::Milliseconds(
196+
wifi_hotspot_client_socket_connect_timeout_millis));
197+
}
198+
199+
socket.ConnectAsync(host_name, service_name).get();
200+
201+
if (connection_timeout_ != nullptr) {
202+
connection_timeout_->Cancel();
203+
connection_timeout_ = nullptr;
204+
}
205+
206+
auto wifi_hotspot_socket = std::make_unique<WifiHotspotSocket>(socket);
207+
208+
LOG(INFO) << "connected to remote service " << ipv4_address << ":"
209+
<< port;
210+
return wifi_hotspot_socket;
211+
} catch (std::exception exception) {
212+
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
213+
<< port << " for the " << i + 1
214+
<< " time. Exception: " << exception.what();
215+
} catch (const winrt::hresult_error& error) {
216+
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
217+
<< port << " for the " << i + 1
218+
<< " time. WinRT exception: " << error.code() << ": "
219+
<< winrt::to_string(error.message());
220+
} catch (...) {
221+
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
222+
<< port << " for the " << i + 1
223+
<< " time due to unknown reason.";
224+
}
157225

158226
if (connection_timeout_ != nullptr) {
159227
connection_timeout_->Cancel();
160228
connection_timeout_ = nullptr;
161229
}
162230

163-
auto wifi_hotspot_socket = std::make_unique<WifiHotspotSocket>(socket);
164-
165-
LOG(INFO) << "connected to remote service " << ipv4_address << ":"
166-
<< port;
167-
return wifi_hotspot_socket;
168-
} catch (std::exception exception) {
169-
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
170-
<< port << " for the " << i + 1
171-
<< " time. Exception: " << exception.what();
172-
} catch (const winrt::hresult_error& error) {
173-
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
174-
<< port << " for the " << i + 1
175-
<< " time. WinRT exception: " << error.code() << ": "
176-
<< winrt::to_string(error.message());
177-
} catch (...) {
178-
LOG(ERROR) << "failed to connect remote service " << ipv4_address << ":"
179-
<< port << " for the " << i + 1
180-
<< " time due to unknown reason.";
181-
}
182-
183-
if (connection_timeout_ != nullptr) {
184-
connection_timeout_->Cancel();
185-
connection_timeout_ = nullptr;
231+
Sleep(wifi_hotspot_retry_interval_millis);
186232
}
187-
188-
Sleep(wifi_hotspot_retry_interval_millis);
233+
return nullptr;
189234
}
190-
return nullptr;
191235
}
192236

193237
std::unique_ptr<api::WifiHotspotServerSocket>
@@ -401,10 +445,9 @@ fire_and_forget WifiHotspotMedium::OnConnectionRequested(
401445
// We found new connection request comes in during hotspot transfer. In this
402446
// case, we should create a new WiFiDirectDevice for it. It will cause
403447
// transfer failure if replace the old WiFiDirectDevice with it.
404-
auto wifi_direct_device =
405-
WiFiDirectDevice::FromIdAsync(
406-
connection_request.DeviceInformation().Id())
407-
.get();
448+
auto wifi_direct_device = WiFiDirectDevice::FromIdAsync(
449+
connection_request.DeviceInformation().Id())
450+
.get();
408451
wifi_direct_devices_.push_back(wifi_direct_device);
409452
LOG(INFO) << "Registered the device " << winrt::to_string(device_name)
410453
<< " in WLAN-AutoConfig";

0 commit comments

Comments
 (0)