mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
WIFI Direct implementation (5)
Part 5: Add WifiDirect Server/Client Socket and Credential PiperOrigin-RevId: 499401159
This commit is contained in:
@@ -23,9 +23,7 @@
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/g3/wifi_hotspot.h"
|
||||
#include "internal/platform/implementation/wifi_direct.h"
|
||||
#include "internal/platform/implementation/wifi_hotspot.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
|
||||
@@ -33,6 +31,142 @@ namespace location {
|
||||
namespace nearby {
|
||||
namespace g3 {
|
||||
|
||||
|
||||
// Code for WifiDirectSocket
|
||||
WifiDirectSocket::~WifiDirectSocket() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
DoClose();
|
||||
}
|
||||
|
||||
void WifiDirectSocket::Connect(WifiDirectSocket& other) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
remote_socket_ = &other;
|
||||
input_ = other.output_;
|
||||
}
|
||||
|
||||
InputStream& WifiDirectSocket::GetInputStream() {
|
||||
auto* remote_socket = GetRemoteSocket();
|
||||
CHECK(remote_socket != nullptr);
|
||||
return remote_socket->GetLocalInputStream();
|
||||
}
|
||||
|
||||
OutputStream& WifiDirectSocket::GetOutputStream() {
|
||||
return GetLocalOutputStream();
|
||||
}
|
||||
|
||||
WifiDirectSocket* WifiDirectSocket::GetRemoteSocket() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
return remote_socket_;
|
||||
}
|
||||
|
||||
bool WifiDirectSocket::IsConnected() const {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
return IsConnectedLocked();
|
||||
}
|
||||
|
||||
Exception WifiDirectSocket::Close() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
DoClose();
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
void WifiDirectSocket::DoClose() {
|
||||
if (!closed_) {
|
||||
remote_socket_ = nullptr;
|
||||
output_->GetOutputStream().Close();
|
||||
output_->GetInputStream().Close();
|
||||
input_->GetOutputStream().Close();
|
||||
input_->GetInputStream().Close();
|
||||
closed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool WifiDirectSocket::IsConnectedLocked() const { return input_ != nullptr; }
|
||||
|
||||
InputStream& WifiDirectSocket::GetLocalInputStream() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
return output_->GetInputStream();
|
||||
}
|
||||
|
||||
OutputStream& WifiDirectSocket::GetLocalOutputStream() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
return output_->GetOutputStream();
|
||||
}
|
||||
|
||||
// Code for WifiDirectServerSocket
|
||||
std::string WifiDirectServerSocket::GetName(absl::string_view ip_address,
|
||||
int port) {
|
||||
return absl::StrCat(ip_address, ":", port);
|
||||
}
|
||||
|
||||
std::unique_ptr<api::WifiDirectSocket> WifiDirectServerSocket::Accept() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
while (!closed_ && pending_sockets_.empty()) {
|
||||
cond_.Wait(&mutex_);
|
||||
}
|
||||
// whether or not we were running in the wait loop, return early if closed.
|
||||
if (closed_) return {};
|
||||
auto* remote_socket =
|
||||
pending_sockets_.extract(pending_sockets_.begin()).value();
|
||||
CHECK(remote_socket);
|
||||
|
||||
auto local_socket = std::make_unique<WifiDirectSocket>();
|
||||
local_socket->Connect(*remote_socket);
|
||||
remote_socket->Connect(*local_socket);
|
||||
cond_.SignalAll();
|
||||
return local_socket;
|
||||
}
|
||||
|
||||
bool WifiDirectServerSocket::Connect(WifiDirectSocket& socket) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (closed_) return false;
|
||||
if (socket.IsConnected()) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to connect to WifiDirect server socket: already connected";
|
||||
return true; // already connected.
|
||||
}
|
||||
// add client socket to the pending list
|
||||
pending_sockets_.insert(&socket);
|
||||
cond_.SignalAll();
|
||||
while (!socket.IsConnected()) {
|
||||
cond_.Wait(&mutex_);
|
||||
if (closed_) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WifiDirectServerSocket::SetCloseNotifier(std::function<void()> notifier) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
close_notifier_ = std::move(notifier);
|
||||
}
|
||||
|
||||
WifiDirectServerSocket::~WifiDirectServerSocket() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
DoClose();
|
||||
}
|
||||
|
||||
Exception WifiDirectServerSocket::Close() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
return DoClose();
|
||||
}
|
||||
|
||||
Exception WifiDirectServerSocket::DoClose() {
|
||||
bool should_notify = !closed_;
|
||||
closed_ = true;
|
||||
if (should_notify) {
|
||||
cond_.SignalAll();
|
||||
if (close_notifier_) {
|
||||
auto notifier = std::move(close_notifier_);
|
||||
mutex_.Unlock();
|
||||
// Notifier may contain calls to public API, and may cause deadlock, if
|
||||
// mutex_ is held during the call.
|
||||
notifier();
|
||||
mutex_.Lock();
|
||||
}
|
||||
}
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
// Code for WifiDirectMedium
|
||||
WifiDirectMedium::WifiDirectMedium() {
|
||||
auto& env = MediumEnvironment::Instance();
|
||||
@@ -45,7 +179,7 @@ WifiDirectMedium::~WifiDirectMedium() {
|
||||
}
|
||||
|
||||
bool WifiDirectMedium::StartWifiDirect(
|
||||
HotspotCredentials* wifi_direct_credentials) {
|
||||
WifiDirectCredentials* wifi_direct_credentials) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
std::string ssid = absl::StrCat("DIRECT-", Prng().NextUint32());
|
||||
@@ -75,7 +209,7 @@ bool WifiDirectMedium::StopWifiDirect() {
|
||||
}
|
||||
|
||||
bool WifiDirectMedium::ConnectWifiDirect(
|
||||
HotspotCredentials* wifi_direct_credentials) {
|
||||
WifiDirectCredentials* wifi_direct_credentials) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
NEARBY_LOGS(INFO) << "G3 ConnectWifiDirect : ssid="
|
||||
@@ -110,10 +244,10 @@ bool WifiDirectMedium::DisconnectWifiDirect() {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<api::WifiHotspotSocket> WifiDirectMedium::ConnectToService(
|
||||
std::unique_ptr<api::WifiDirectSocket> WifiDirectMedium::ConnectToService(
|
||||
absl::string_view ip_address, int port,
|
||||
CancellationFlag* cancellation_flag) {
|
||||
std::string socket_name = WifiHotspotServerSocket::GetName(ip_address, port);
|
||||
std::string socket_name = WifiDirectServerSocket::GetName(ip_address, port);
|
||||
NEARBY_LOGS(INFO) << "G3 WifiDirect ConnectToService [self]: medium=" << this
|
||||
<< ", ip address + port=" << socket_name;
|
||||
// First, find an instance of remote medium, that exposed this service.
|
||||
@@ -124,7 +258,7 @@ std::unique_ptr<api::WifiHotspotSocket> WifiDirectMedium::ConnectToService(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WifiHotspotServerSocket* server_socket = nullptr;
|
||||
WifiDirectServerSocket* server_socket = nullptr;
|
||||
NEARBY_LOGS(INFO) << "G3 WifiDirect ConnectToService [peer]: medium="
|
||||
<< remote_medium
|
||||
<< ", remote ip address + port=" << socket_name;
|
||||
@@ -148,19 +282,19 @@ std::unique_ptr<api::WifiHotspotSocket> WifiDirectMedium::ConnectToService(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto socket = std::make_unique<WifiHotspotSocket>();
|
||||
auto socket = std::make_unique<WifiDirectSocket>();
|
||||
// Finally, Request to connect to this socket.
|
||||
|
||||
server_socket->Connect(*socket);
|
||||
NEARBY_LOGS(INFO) << "G3 WifiHotspot GC ConnectToService: connected: socket="
|
||||
NEARBY_LOGS(INFO) << "G3 WifiDirect GC ConnectToService: connected: socket="
|
||||
<< socket.get();
|
||||
return socket;
|
||||
}
|
||||
|
||||
std::unique_ptr<api::WifiHotspotServerSocket>
|
||||
std::unique_ptr<api::WifiDirectServerSocket>
|
||||
WifiDirectMedium::ListenForService(int port) {
|
||||
auto& env = MediumEnvironment::Instance();
|
||||
auto server_socket = std::make_unique<WifiHotspotServerSocket>();
|
||||
auto server_socket = std::make_unique<WifiDirectServerSocket>();
|
||||
|
||||
std::string dot_decimal_ip;
|
||||
std::string ip_address = env.GetFakeIPAddress();
|
||||
@@ -172,7 +306,7 @@ WifiDirectMedium::ListenForService(int port) {
|
||||
|
||||
server_socket->SetIPAddress(dot_decimal_ip);
|
||||
server_socket->SetPort(port == 0 ? env.GetFakePort() : port);
|
||||
std::string socket_name = WifiHotspotServerSocket::GetName(
|
||||
std::string socket_name = WifiDirectServerSocket::GetName(
|
||||
server_socket->GetIPAddress(), server_socket->GetPort());
|
||||
server_socket->SetCloseNotifier([this, socket_name]() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
@@ -22,12 +22,9 @@
|
||||
#include <utility>
|
||||
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/g3/multi_thread_executor.h"
|
||||
#include "internal/platform/implementation/g3/pipe.h"
|
||||
#include "internal/platform/implementation/g3/wifi_hotspot.h"
|
||||
#include "internal/platform/implementation/wifi_direct.h"
|
||||
#include "internal/platform/implementation/wifi_hotspot.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
|
||||
@@ -37,6 +34,141 @@ namespace g3 {
|
||||
|
||||
class WifiDirectMedium;
|
||||
|
||||
class WifiDirectSocket : public api::WifiDirectSocket {
|
||||
public:
|
||||
WifiDirectSocket() = default;
|
||||
~WifiDirectSocket() override;
|
||||
WifiDirectSocket(const WifiDirectSocket&) = default;
|
||||
WifiDirectSocket(WifiDirectSocket&&) = default;
|
||||
WifiDirectSocket& operator=(const WifiDirectSocket&) = default;
|
||||
WifiDirectSocket& operator=(WifiDirectSocket&&) = default;
|
||||
|
||||
// Connect to another WifiDirectSocket, to form a functional low-level
|
||||
// channel. from this point on, and until Close is called, connection exists.
|
||||
void Connect(WifiDirectSocket& other) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// 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 ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// 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 ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Returns address of a remote WifiDirectSocket or nullptr.
|
||||
WifiDirectSocket* GetRemoteSocket() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Returns true if connection exists to the (possibly closed) remote socket.
|
||||
bool IsConnected() const ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
Exception Close() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
private:
|
||||
void DoClose() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Returns true if connection exists to the (possibly closed) remote socket.
|
||||
bool IsConnectedLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Returns InputStream of our side of a connection.
|
||||
// This is what the remote side is supposed to read from.
|
||||
// This is a helper for GetInputStream() method.
|
||||
InputStream& GetLocalInputStream() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Returns OutputStream of our side of a connection.
|
||||
// This is what the local size is supposed to write to.
|
||||
// This is a helper for GetOutputStream() method.
|
||||
OutputStream& GetLocalOutputStream() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Output pipe is initialized by constructor, it remains always valid, until
|
||||
// it is closed. it represents output part of a local socket. Input part of a
|
||||
// local socket comes from the peer socket, after connection.
|
||||
std::shared_ptr<Pipe> output_{new Pipe};
|
||||
std::shared_ptr<Pipe> input_;
|
||||
mutable absl::Mutex mutex_;
|
||||
WifiDirectSocket* remote_socket_ ABSL_GUARDED_BY(mutex_) = nullptr;
|
||||
bool closed_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
};
|
||||
|
||||
// WifiDirectServerSocket provides the support to server socket, this server
|
||||
// socket accepts connection from clients.
|
||||
class WifiDirectServerSocket : public api::WifiDirectServerSocket {
|
||||
public:
|
||||
~WifiDirectServerSocket() override;
|
||||
|
||||
static std::string GetName(absl::string_view ip_address, int port);
|
||||
|
||||
std::string GetIPAddress() const override ABSL_LOCKS_EXCLUDED(mutex_) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
return ip_address_;
|
||||
}
|
||||
|
||||
void SetIPAddress(const std::string& ip_address) ABSL_LOCKS_EXCLUDED(mutex_) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
ip_address_ = ip_address;
|
||||
}
|
||||
|
||||
int GetPort() const override ABSL_LOCKS_EXCLUDED(mutex_) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
return port_;
|
||||
}
|
||||
|
||||
void SetPort(int port) ABSL_LOCKS_EXCLUDED(mutex_) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
port_ = port;
|
||||
}
|
||||
|
||||
// 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
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Blocks until either:
|
||||
// - connection is available, or
|
||||
// - server socket is closed, or
|
||||
// - error happens.
|
||||
//
|
||||
// Called by the client side of a connection.
|
||||
// Returns true, if socket is successfully connected.
|
||||
bool Connect(WifiDirectSocket& socket) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// 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(std::function<void()> notifier)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
// Calls close_notifier if it was previously set, and marks socket as closed.
|
||||
Exception Close() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
private:
|
||||
// Retrieves IP addresses from local machine
|
||||
std::vector<std::string> GetIpAddresses() const;
|
||||
std::string GetDirectGOIpAddresses() const;
|
||||
|
||||
Exception DoClose() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
mutable absl::Mutex mutex_;
|
||||
std::string ip_address_ ABSL_GUARDED_BY(mutex_);
|
||||
int port_ ABSL_GUARDED_BY(mutex_);
|
||||
absl::CondVar cond_;
|
||||
absl::flat_hash_set<WifiDirectSocket*> pending_sockets_
|
||||
ABSL_GUARDED_BY(mutex_);
|
||||
std::function<void()> close_notifier_ ABSL_GUARDED_BY(mutex_);
|
||||
bool closed_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
};
|
||||
|
||||
// Container of operations that can be performed over the WifiDirect medium.
|
||||
class WifiDirectMedium : public api::WifiDirectMedium {
|
||||
public:
|
||||
@@ -52,20 +184,21 @@ class WifiDirectMedium : public api::WifiDirectMedium {
|
||||
bool IsInterfaceValid() const override { return true; }
|
||||
|
||||
// Discoverer connects to server socket
|
||||
std::unique_ptr<api::WifiHotspotSocket> ConnectToService(
|
||||
std::unique_ptr<api::WifiDirectSocket> ConnectToService(
|
||||
absl::string_view ip_address, int port,
|
||||
CancellationFlag* cancellation_flag) override;
|
||||
|
||||
// Advertiser starts to listen on server socket
|
||||
std::unique_ptr<api::WifiHotspotServerSocket> ListenForService(
|
||||
std::unique_ptr<api::WifiDirectServerSocket> ListenForService(
|
||||
int port) override;
|
||||
|
||||
// Advertiser start WiFiDirect GO with specific Crendentials
|
||||
bool StartWifiDirect(HotspotCredentials* wifi_direct_credentials) override;
|
||||
bool StartWifiDirect(WifiDirectCredentials* wifi_direct_credentials) override;
|
||||
// Advertiser stop the current WiFiDirect GO
|
||||
bool StopWifiDirect() override;
|
||||
// Discoverer connects to the WiFiDirect GO
|
||||
bool ConnectWifiDirect(HotspotCredentials* wifi_direct_credentials) override;
|
||||
bool ConnectWifiDirect(
|
||||
WifiDirectCredentials* wifi_direct_credentials) override;
|
||||
// Discoverer disconnects from the WiFiDirect GO
|
||||
bool DisconnectWifiDirect() override;
|
||||
|
||||
@@ -77,7 +210,7 @@ class WifiDirectMedium : public api::WifiDirectMedium {
|
||||
private:
|
||||
absl::Mutex mutex_;
|
||||
|
||||
absl::flat_hash_map<std::string, WifiHotspotServerSocket*> server_sockets_
|
||||
absl::flat_hash_map<std::string, WifiDirectServerSocket*> server_sockets_
|
||||
ABSL_GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
|
||||
@@ -20,13 +20,56 @@
|
||||
#include <utility>
|
||||
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/implementation/wifi_hotspot.h"
|
||||
#include "internal/platform/input_stream.h"
|
||||
#include "internal/platform/output_stream.h"
|
||||
#include "internal/platform/wifi_hotspot_credential.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace api {
|
||||
|
||||
class WifiDirectSocket {
|
||||
public:
|
||||
virtual ~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.
|
||||
virtual InputStream& GetInputStream() = 0;
|
||||
|
||||
// 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.
|
||||
virtual OutputStream& GetOutputStream() = 0;
|
||||
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
virtual Exception Close() = 0;
|
||||
};
|
||||
|
||||
class WifiDirectServerSocket {
|
||||
public:
|
||||
virtual ~WifiDirectServerSocket() = default;
|
||||
|
||||
virtual std::string GetIPAddress() const = 0;
|
||||
|
||||
virtual int GetPort() const = 0;
|
||||
|
||||
// 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.
|
||||
virtual std::unique_ptr<WifiDirectSocket> Accept() = 0;
|
||||
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
virtual Exception Close() = 0;
|
||||
};
|
||||
|
||||
// Container of operations that can be performed over the WifiLan medium.
|
||||
class WifiDirectMedium {
|
||||
public:
|
||||
@@ -38,7 +81,7 @@ class WifiDirectMedium {
|
||||
// Connects to a WifiDirect service by port.
|
||||
// On success, returns a new WifiDirectSocket.
|
||||
// On error, returns nullptr.
|
||||
virtual std::unique_ptr<WifiHotspotSocket> ConnectToService(
|
||||
virtual std::unique_ptr<WifiDirectSocket> ConnectToService(
|
||||
absl::string_view ip_address, int port,
|
||||
CancellationFlag* cancellation_flag) = 0;
|
||||
|
||||
@@ -49,19 +92,20 @@ class WifiDirectMedium {
|
||||
// 1~65536 : open a server socket on that exact port.
|
||||
// On success, returns a new WifiDirectServerSocket.
|
||||
// On error, returns nullptr.
|
||||
virtual std::unique_ptr<WifiHotspotServerSocket> ListenForService(
|
||||
virtual std::unique_ptr<WifiDirectServerSocket> ListenForService(
|
||||
int port) = 0;
|
||||
|
||||
// Start a WifiDirect GO with platform dependent APIs and set the
|
||||
// SSID/password pair back to the credentials. BWU module will retrieve these
|
||||
// credentials and send to the client device through established channel and
|
||||
// then client may connect to this WifiDirect GO with these credentials.
|
||||
virtual bool StartWifiDirect(HotspotCredentials* wifi_direct_credentials) = 0;
|
||||
virtual bool StartWifiDirect(
|
||||
WifiDirectCredentials* wifi_direct_credentials) = 0;
|
||||
virtual bool StopWifiDirect() = 0;
|
||||
|
||||
// Client device connect to a softAP with specified credential.
|
||||
virtual bool ConnectWifiDirect(
|
||||
HotspotCredentials* wifi_direct_credentials) = 0;
|
||||
WifiDirectCredentials* wifi_direct_credentials) = 0;
|
||||
virtual bool DisconnectWifiDirect() = 0;
|
||||
|
||||
// Returns the port range as a pair of min and max port.
|
||||
|
||||
@@ -141,6 +141,8 @@ cc_library(
|
||||
"thread_pool.cc",
|
||||
"utils.cc",
|
||||
"wifi_direct_medium.cc",
|
||||
"wifi_direct_server_socket.cc",
|
||||
"wifi_direct_socket.cc",
|
||||
"wifi_hotspot_medium.cc",
|
||||
"wifi_hotspot_server_socket.cc",
|
||||
"wifi_hotspot_socket.cc",
|
||||
|
||||
@@ -20,21 +20,24 @@
|
||||
#include <wlanapi.h>
|
||||
|
||||
// Standard C/C++ headers
|
||||
#include <deque>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// Nearby connections headers
|
||||
#include "internal/platform/cancellation_flag_listener.h"
|
||||
#include "internal/platform/implementation/wifi_direct.h"
|
||||
#include "internal/platform/implementation/wifi_hotspot.h"
|
||||
#include "internal/platform/implementation/windows/scheduled_executor.h"
|
||||
#include "internal/platform/implementation/windows/wifi_hotspot.h"
|
||||
|
||||
// ABSL header
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
// WinRT headers
|
||||
#include "absl/types/optional.h"
|
||||
#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"
|
||||
@@ -93,6 +96,139 @@ 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(std::function<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
|
||||
std::function<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:
|
||||
@@ -103,21 +239,22 @@ class WifiDirectMedium : public api::WifiDirectMedium {
|
||||
bool IsInterfaceValid() const override;
|
||||
|
||||
// WifiDirect GC connects to server socket
|
||||
std::unique_ptr<api::WifiHotspotSocket> ConnectToService(
|
||||
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::WifiHotspotServerSocket> ListenForService(
|
||||
std::unique_ptr<api::WifiDirectServerSocket> ListenForService(
|
||||
int port) override;
|
||||
|
||||
// Start WifiDirect GO with specific Credentials.
|
||||
bool StartWifiDirect(HotspotCredentials* wifi_direct_credentials) override;
|
||||
bool StartWifiDirect(WifiDirectCredentials* wifi_direct_credentials) override;
|
||||
// Stop the current WifiDirect GO
|
||||
bool StopWifiDirect() override;
|
||||
|
||||
// WifiDirect GC connects to the GO
|
||||
bool ConnectWifiDirect(HotspotCredentials* wifi_direct_credentials) override;
|
||||
bool ConnectWifiDirect(
|
||||
WifiDirectCredentials* wifi_direct_credentials) override;
|
||||
// WifiDirect GC disconnects to the GO
|
||||
bool DisconnectWifiDirect() override;
|
||||
|
||||
@@ -172,7 +309,7 @@ class WifiDirectMedium : public api::WifiDirectMedium {
|
||||
int medium_status_ = kMediumStatusIdle;
|
||||
|
||||
// Keep the server socket listener pointer
|
||||
WifiHotspotServerSocket* server_socket_ptr_ ABSL_GUARDED_BY(mutex_) = nullptr;
|
||||
WifiDirectServerSocket* server_socket_ptr_ ABSL_GUARDED_BY(mutex_) = nullptr;
|
||||
|
||||
// Scheduler for timeout.
|
||||
ScheduledExecutor scheduled_executor_;
|
||||
|
||||
@@ -76,7 +76,7 @@ bool WifiDirectMedium::IsInterfaceValid() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<api::WifiHotspotSocket> WifiDirectMedium::ConnectToService(
|
||||
std::unique_ptr<api::WifiDirectSocket> WifiDirectMedium::ConnectToService(
|
||||
absl::string_view ip_address, int port,
|
||||
CancellationFlag* cancellation_flag) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << " : Connect to remote service.";
|
||||
@@ -142,11 +142,11 @@ std::unique_ptr<api::WifiHotspotSocket> WifiDirectMedium::ConnectToService(
|
||||
connection_timeout_ = nullptr;
|
||||
}
|
||||
|
||||
auto wifi_hotspot_socket = std::make_unique<WifiHotspotSocket>(socket);
|
||||
auto client_socket = std::make_unique<WifiDirectSocket>(socket);
|
||||
|
||||
NEARBY_LOGS(INFO) << "connected to remote service " << ipv4_address << ":"
|
||||
<< port;
|
||||
return wifi_hotspot_socket;
|
||||
return client_socket;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << "failed to connect remote service " << ipv4_address
|
||||
<< ":" << port << " for the " << i + 1 << " time";
|
||||
@@ -166,7 +166,7 @@ std::unique_ptr<api::WifiHotspotSocket> WifiDirectMedium::ConnectToService(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<api::WifiHotspotServerSocket>
|
||||
std::unique_ptr<api::WifiDirectServerSocket>
|
||||
WifiDirectMedium::ListenForService(int port) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
@@ -177,7 +177,7 @@ WifiDirectMedium::ListenForService(int port) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto server_socket = std::make_unique<WifiHotspotServerSocket>(port);
|
||||
auto server_socket = std::make_unique<WifiDirectServerSocket>(port);
|
||||
server_socket_ptr_ = server_socket.get();
|
||||
|
||||
server_socket->SetCloseNotifier([this]() {
|
||||
@@ -201,7 +201,7 @@ WifiDirectMedium::ListenForService(int port) {
|
||||
}
|
||||
|
||||
bool WifiDirectMedium::StartWifiDirect(
|
||||
HotspotCredentials* wifi_direct_credentials) {
|
||||
WifiDirectCredentials* wifi_direct_credentials) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
if (IsBeaconing()) {
|
||||
@@ -387,7 +387,7 @@ fire_and_forget WifiDirectMedium::OnConnectionRequested(
|
||||
}
|
||||
|
||||
bool WifiDirectMedium::ConnectWifiDirect(
|
||||
HotspotCredentials* wifi_direct_credentials) {
|
||||
WifiDirectCredentials* wifi_direct_credentials) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
// 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 <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// ABSL headers
|
||||
#include "absl/strings/match.h"
|
||||
|
||||
// Nearby connections headers
|
||||
#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 location {
|
||||
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_);
|
||||
NEARBY_LOGS(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();
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Accepted a remote connection.";
|
||||
return std::make_unique<WifiDirectSocket>(wifi_direct_socket);
|
||||
}
|
||||
|
||||
void WifiDirectServerSocket::SetCloseNotifier(std::function<void()> notifier) {
|
||||
close_notifier_ = std::move(notifier);
|
||||
}
|
||||
|
||||
Exception WifiDirectServerSocket::Close() {
|
||||
try {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
NEARBY_LOGS(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_();
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Close completed succesfully.";
|
||||
return {Exception::kSuccess};
|
||||
} catch (std::exception exception) {
|
||||
closed_ = true;
|
||||
cond_.SignalAll();
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error &error) {
|
||||
closed_ = true;
|
||||
cond_.SignalAll();
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
closed_ = true;
|
||||
cond_.SignalAll();
|
||||
NEARBY_LOGS(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()) {
|
||||
NEARBY_LOGS(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()) {
|
||||
NEARBY_LOGS(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) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Cannot accept connection on preferred port. Exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error &error) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ":Cannot accept connection on preferred port. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(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());
|
||||
NEARBY_LOGS(INFO) << "Server Socket port: " << port_;
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Cannot bind to any port. Exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error &error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Cannot bind to any port. WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
fire_and_forget WifiDirectServerSocket::Listener_ConnectionReceived(
|
||||
StreamSocketListener listener,
|
||||
StreamSocketListenerConnectionReceivedEventArgs const &args) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
NEARBY_LOGS(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")) {
|
||||
NEARBY_LOGS(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
|
||||
NEARBY_LOGS(INFO) << "Found WifiDirect GO IP: " << ipv4_s;
|
||||
return ipv4_s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {};
|
||||
} catch (const winrt::hresult_error &error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
return {};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,202 @@
|
||||
// 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 <cstring>
|
||||
#include <exception>
|
||||
|
||||
#include "internal/platform/implementation/windows/wifi_direct.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace location {
|
||||
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) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(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) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(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) {
|
||||
NEARBY_LOGS(WARNING) << "Only got part of data of needed.";
|
||||
}
|
||||
|
||||
ByteArray data((char*)ibuffer.data(), ibuffer.Length());
|
||||
|
||||
return ExceptionOr(data);
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(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) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
|
||||
Exception WifiDirectSocket::SocketInputStream::Close() {
|
||||
try {
|
||||
input_stream_.Close();
|
||||
return {Exception::kSuccess};
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(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) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
|
||||
Exception WifiDirectSocket::SocketOutputStream::Flush() {
|
||||
try {
|
||||
output_stream_.FlushAsync().get();
|
||||
return {Exception::kSuccess};
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
|
||||
Exception WifiDirectSocket::SocketOutputStream::Close() {
|
||||
try {
|
||||
output_stream_.Close();
|
||||
return {Exception::kSuccess};
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception: " << exception.what();
|
||||
return {Exception::kIo};
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WinRT exception: " << error.code()
|
||||
<< ": " << winrt::to_string(error.message());
|
||||
return {Exception::kIo};
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Unknown exeption.";
|
||||
return {Exception::kIo};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -20,6 +20,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// ABSL headers
|
||||
#include "absl/strings/match.h"
|
||||
|
||||
// Nearby connections headers
|
||||
#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"
|
||||
@@ -223,15 +227,6 @@ fire_and_forget WifiHotspotServerSocket::Listener_ConnectionReceived(
|
||||
return fire_and_forget{};
|
||||
}
|
||||
|
||||
bool HasEnding(std::string const &full_string, std::string const &ending) {
|
||||
if (full_string.length() >= ending.length()) {
|
||||
return (0 == full_string.compare(full_string.length() - ending.length(),
|
||||
ending.length(), ending));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> WifiHotspotServerSocket::GetIpAddresses() const {
|
||||
std::vector<std::string> result{};
|
||||
auto host_names = NetworkInformation::GetHostNames();
|
||||
@@ -241,7 +236,7 @@ std::vector<std::string> WifiHotspotServerSocket::GetIpAddresses() const {
|
||||
host_name.Type() == HostNameType::Ipv4) {
|
||||
std::string ipv4_s = winrt::to_string(host_name.ToString());
|
||||
|
||||
if (HasEnding(ipv4_s, ".1")) {
|
||||
if (absl::EndsWith(ipv4_s, ".1")) {
|
||||
NEARBY_LOGS(INFO) << "Found Hotspot IP: " << ipv4_s;
|
||||
result.push_back(ipv4_s);
|
||||
}
|
||||
@@ -259,7 +254,7 @@ std::string WifiHotspotServerSocket::GetHotspotIpAddresses() const {
|
||||
host_name.IPInformation().NetworkAdapter() != nullptr &&
|
||||
host_name.Type() == HostNameType::Ipv4) {
|
||||
std::string ipv4_s = winrt::to_string(host_name.ToString());
|
||||
if (HasEnding(ipv4_s, ".1")) {
|
||||
if (absl::EndsWith(ipv4_s, ".1")) {
|
||||
// TODO(b/228541380): replace when we find a better way to
|
||||
// identifying the hotspot address
|
||||
NEARBY_LOGS(INFO) << "Found Hotspot IP: " << ipv4_s;
|
||||
|
||||
Reference in New Issue
Block a user