diff --git a/internal/platform/implementation/g3/BUILD b/internal/platform/implementation/g3/BUILD index 5dd64cc6..02f45c6c 100644 --- a/internal/platform/implementation/g3/BUILD +++ b/internal/platform/implementation/g3/BUILD @@ -85,6 +85,7 @@ cc_library( "bluetooth_adapter.h", "bluetooth_classic.h", "credential_storage_impl.h", + "socket_base.h", "webrtc.h", "wifi.h", "wifi_direct.h", diff --git a/internal/platform/implementation/g3/ble.cc b/internal/platform/implementation/g3/ble.cc index 95bbfe47..310d19be 100644 --- a/internal/platform/implementation/g3/ble.cc +++ b/internal/platform/implementation/g3/ble.cc @@ -28,76 +28,11 @@ namespace nearby { namespace g3 { -BleSocket::~BleSocket() { - absl::MutexLock lock(&mutex_); - DoClose(); -} - -void BleSocket::Connect(BleSocket& other) { - absl::MutexLock lock(&mutex_); - remote_socket_ = &other; - input_ = other.output_; -} - -InputStream& BleSocket::GetInputStream() { - auto* remote_socket = GetRemoteSocket(); - CHECK(remote_socket != nullptr); - return remote_socket->GetLocalInputStream(); -} - -OutputStream& BleSocket::GetOutputStream() { return GetLocalOutputStream(); } - -BleSocket* BleSocket::GetRemoteSocket() { - absl::MutexLock lock(&mutex_); - return remote_socket_; -} - -bool BleSocket::IsConnected() const { - absl::MutexLock lock(&mutex_); - return IsConnectedLocked(); -} - -bool BleSocket::IsClosed() const { - absl::MutexLock lock(&mutex_); - return closed_; -} - -Exception BleSocket::Close() { - absl::MutexLock lock(&mutex_); - DoClose(); - return {Exception::kSuccess}; -} - BlePeripheral* BleSocket::GetRemotePeripheral() { absl::MutexLock lock(&mutex_); return peripheral_; } -void BleSocket::DoClose() { - if (!closed_) { - remote_socket_ = nullptr; - output_->GetOutputStream().Close(); - output_->GetInputStream().Close(); - if (IsConnectedLocked()) { - input_->GetOutputStream().Close(); - input_->GetInputStream().Close(); - } - closed_ = true; - } -} - -bool BleSocket::IsConnectedLocked() const { return input_ != nullptr; } - -InputStream& BleSocket::GetLocalInputStream() { - absl::MutexLock lock(&mutex_); - return output_->GetInputStream(); -} - -OutputStream& BleSocket::GetLocalOutputStream() { - absl::MutexLock lock(&mutex_); - return output_->GetOutputStream(); -} - std::unique_ptr BleServerSocket::Accept( BlePeripheral* peripheral) { absl::MutexLock lock(&mutex_); diff --git a/internal/platform/implementation/g3/ble.h b/internal/platform/implementation/g3/ble.h index 2c8fd4c0..78736ef8 100644 --- a/internal/platform/implementation/g3/ble.h +++ b/internal/platform/implementation/g3/ble.h @@ -28,6 +28,7 @@ #include "internal/platform/implementation/g3/bluetooth_classic.h" #include "internal/platform/implementation/g3/multi_thread_executor.h" #include "internal/platform/implementation/g3/pipe.h" +#include "internal/platform/implementation/g3/socket_base.h" #include "internal/platform/input_stream.h" #include "internal/platform/output_stream.h" @@ -36,64 +37,36 @@ namespace g3 { class BleMedium; -class BleSocket : public api::BleSocket { +class BleSocket : public api::BleSocket, public SocketBase { public: BleSocket() = default; explicit BleSocket(BlePeripheral* peripheral) : peripheral_(peripheral) {} - ~BleSocket() override; - - // Connect to another BleSocket, to form a functional low-level channel. - // from this point on, and until Close is called, connection exists. - void Connect(BleSocket& other) ABSL_LOCKS_EXCLUDED(mutex_); // Returns the InputStream of this connected BleSocket. - InputStream& GetInputStream() override ABSL_LOCKS_EXCLUDED(mutex_); + InputStream& GetInputStream() override { + return SocketBase::GetInputStream(); + } // Returns the OutputStream of this connected BleSocket. // This stream is for local side to write. - OutputStream& GetOutputStream() override ABSL_LOCKS_EXCLUDED(mutex_); + OutputStream& GetOutputStream() override { + return SocketBase::GetOutputStream(); + } // Returns address of a remote BleSocket or nullptr. - BleSocket* GetRemoteSocket() ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true if connection exists to the (possibly closed) remote socket. - bool IsConnected() const ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true if socket is closed. - bool IsClosed() const ABSL_LOCKS_EXCLUDED(mutex_); + BleSocket* GetRemoteSocket() { + return static_cast(SocketBase::GetRemoteSocket()); + } // Returns Exception::kIo on error, Exception::kSuccess otherwise. - Exception Close() override ABSL_LOCKS_EXCLUDED(mutex_); + Exception Close() override { return SocketBase::Close(); } // Returns valid BlePeripheral pointer if there is a connection, and // nullptr otherwise. BlePeripheral* GetRemotePeripheral() 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 output_{new Pipe}; - std::shared_ptr input_; - mutable absl::Mutex mutex_; BlePeripheral* peripheral_; - BleSocket* remote_socket_ ABSL_GUARDED_BY(mutex_) = nullptr; - bool closed_ ABSL_GUARDED_BY(mutex_) = false; }; class BleServerSocket { diff --git a/internal/platform/implementation/g3/ble_v2.cc b/internal/platform/implementation/g3/ble_v2.cc index 78886b95..f0fcf339 100644 --- a/internal/platform/implementation/g3/ble_v2.cc +++ b/internal/platform/implementation/g3/ble_v2.cc @@ -69,82 +69,14 @@ api::ble_v2::BlePeripheral::UniqueId BleV2Peripheral::GetUniqueId() const { return adapter_.GetUniqueId(); } -BleV2Socket::~BleV2Socket() { - absl::MutexLock lock(&mutex_); - DoClose(); -} - -void BleV2Socket::Connect(BleV2Socket& other) { - absl::MutexLock lock(&mutex_); - remote_socket_ = &other; - input_ = other.output_; -} - -InputStream& BleV2Socket::GetInputStream() { - auto* remote_socket = GetRemoteSocket(); - CHECK(remote_socket != nullptr); - return remote_socket->GetLocalInputStream(); -} - -OutputStream& BleV2Socket::GetOutputStream() { return GetLocalOutputStream(); } - -BleV2Socket* BleV2Socket::GetRemoteSocket() { - absl::MutexLock lock(&mutex_); - return remote_socket_; -} - -bool BleV2Socket::IsConnected() const { - absl::MutexLock lock(&mutex_); - return IsConnectedLocked(); -} - -bool BleV2Socket::IsClosed() const { - absl::MutexLock lock(&mutex_); - return closed_; -} - -Exception BleV2Socket::Close() { - absl::MutexLock lock(&mutex_); - DoClose(); - return {Exception::kSuccess}; -} - BleV2Peripheral* BleV2Socket::GetRemotePeripheral() { - BluetoothAdapter* remote_adapter = nullptr; - { - absl::MutexLock lock(&mutex_); - if (remote_socket_ == nullptr || remote_socket_->adapter_ == nullptr) { - return nullptr; - } - remote_adapter = remote_socket_->adapter_; - } - if (remote_adapter == nullptr || remote_adapter->GetBleV2Medium() == nullptr) + BleV2Socket* remote_socket = GetRemoteSocket(); + if (remote_socket == nullptr || remote_socket->adapter_ == nullptr || + remote_socket->adapter_->GetBleV2Medium() == nullptr) { return nullptr; - return &(static_cast(remote_adapter->GetBleV2Medium()) - ->GetPeripheral()); -} - -void BleV2Socket::DoClose() { - if (!closed_) { - remote_socket_ = nullptr; - output_->GetOutputStream().Close(); - output_->GetInputStream().Close(); - input_->GetOutputStream().Close(); - input_->GetInputStream().Close(); - closed_ = true; } -} - -bool BleV2Socket::IsConnectedLocked() const { return input_ != nullptr; } - -InputStream& BleV2Socket::GetLocalInputStream() { - absl::MutexLock lock(&mutex_); - return output_->GetInputStream(); -} - -OutputStream& BleV2Socket::GetLocalOutputStream() { - absl::MutexLock lock(&mutex_); - return output_->GetOutputStream(); + return &(static_cast(remote_socket->adapter_->GetBleV2Medium()) + ->GetPeripheral()); } std::unique_ptr BleV2ServerSocket::Accept() { diff --git a/internal/platform/implementation/g3/ble_v2.h b/internal/platform/implementation/g3/ble_v2.h index 9b993086..4b273a46 100644 --- a/internal/platform/implementation/g3/ble_v2.h +++ b/internal/platform/implementation/g3/ble_v2.h @@ -30,6 +30,7 @@ #include "internal/platform/implementation/ble_v2.h" #include "internal/platform/implementation/g3/bluetooth_adapter.h" #include "internal/platform/implementation/g3/pipe.h" +#include "internal/platform/implementation/g3/socket_base.h" #include "internal/platform/medium_environment.h" #include "internal/platform/prng.h" #include "internal/platform/uuid.h" @@ -50,67 +51,35 @@ class BleV2Peripheral : public api::ble_v2::BlePeripheral { BluetoothAdapter& adapter_; }; -class BleV2Socket : public api::ble_v2::BleSocket { +class BleV2Socket : public api::ble_v2::BleSocket, public SocketBase { public: explicit BleV2Socket(BluetoothAdapter* adapter) : adapter_(adapter) {} - BleV2Socket(const BleV2Socket&) = default; - BleV2Socket& operator=(const BleV2Socket&) = default; - BleV2Socket(BleV2Socket&&) = default; - BleV2Socket& operator=(BleV2Socket&&) = default; - ~BleV2Socket() override; - - // Connect to another BleSocket, to form a functional low-level channel. - // from this point on, and until Close is called, connection exists. - void Connect(BleV2Socket& other) ABSL_LOCKS_EXCLUDED(mutex_); // Returns the InputStream of this connected BleSocket. - InputStream& GetInputStream() override ABSL_LOCKS_EXCLUDED(mutex_); + InputStream& GetInputStream() override { + return SocketBase::GetInputStream(); + } // Returns the OutputStream of this connected BleSocket. // This stream is for local side to write. - OutputStream& GetOutputStream() override ABSL_LOCKS_EXCLUDED(mutex_); + OutputStream& GetOutputStream() override { + return SocketBase::GetOutputStream(); + } // Returns address of a remote BleSocket or nullptr. - BleV2Socket* GetRemoteSocket() ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true if connection exists to the (possibly closed) remote socket. - bool IsConnected() const ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true if socket is closed. - bool IsClosed() const ABSL_LOCKS_EXCLUDED(mutex_); + BleV2Socket* GetRemoteSocket() { + return static_cast(SocketBase::GetRemoteSocket()); + } // Returns Exception::kIo on error, Exception::kSuccess otherwise. - Exception Close() override ABSL_LOCKS_EXCLUDED(mutex_); + Exception Close() override { return SocketBase::Close(); } // Returns valid BlePeripheral pointer if there is a connection, and // nullptr otherwise. BleV2Peripheral* GetRemotePeripheral() 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 output_{new Pipe}; - std::shared_ptr input_; - mutable absl::Mutex mutex_; BluetoothAdapter* adapter_ = nullptr; // Our Adapter. Read only. - BleV2Socket* remote_socket_ ABSL_GUARDED_BY(mutex_) = nullptr; - bool closed_ ABSL_GUARDED_BY(mutex_) = false; }; class BleV2ServerSocket : public api::ble_v2::BleServerSocket { diff --git a/internal/platform/implementation/g3/bluetooth_classic.cc b/internal/platform/implementation/g3/bluetooth_classic.cc index 58f2b7f0..d7a1a832 100644 --- a/internal/platform/implementation/g3/bluetooth_classic.cc +++ b/internal/platform/implementation/g3/bluetooth_classic.cc @@ -29,80 +29,13 @@ namespace nearby { namespace g3 { -BluetoothSocket::~BluetoothSocket() { - absl::MutexLock lock(&mutex_); - DoClose(); -} - -void BluetoothSocket::Connect(BluetoothSocket& other) { - absl::MutexLock lock(&mutex_); - remote_socket_ = &other; - input_ = other.output_; -} - -bool BluetoothSocket::IsConnected() const { - absl::MutexLock lock(&mutex_); - return IsConnectedLocked(); -} - -bool BluetoothSocket::IsClosed() const { - absl::MutexLock lock(&mutex_); - return closed_; -} - -bool BluetoothSocket::IsConnectedLocked() const { return input_ != nullptr; } - -InputStream& BluetoothSocket::GetInputStream() { - absl::MutexLock lock(&mutex_); - if (IsConnectedLocked()) { - return input_->GetInputStream(); - } else { - return invalid_input_stream_; - } -} - -OutputStream& BluetoothSocket::GetOutputStream() { - return GetLocalOutputStream(); -} - -InputStream& BluetoothSocket::GetLocalInputStream() { - absl::MutexLock lock(&mutex_); - return output_->GetInputStream(); -} - -OutputStream& BluetoothSocket::GetLocalOutputStream() { - absl::MutexLock lock(&mutex_); - return output_->GetOutputStream(); -} - -Exception BluetoothSocket::Close() { - absl::MutexLock lock(&mutex_); - DoClose(); - return {Exception::kSuccess}; -} - -void BluetoothSocket::DoClose() { - if (!closed_) { - remote_socket_ = nullptr; - output_->GetOutputStream().Close(); - output_->GetInputStream().Close(); - input_->GetOutputStream().Close(); - input_->GetInputStream().Close(); - input_.reset(); - closed_ = true; - } -} - BluetoothDevice* BluetoothSocket::GetRemoteDevice() { - BluetoothAdapter* remote_adapter = nullptr; - { - absl::MutexLock lock(&mutex_); - if (remote_socket_ == nullptr || remote_socket_->adapter_ == nullptr) { - return nullptr; - } - remote_adapter = remote_socket_->adapter_; + BluetoothSocket* remote_socket = + static_cast(GetRemoteSocket()); + if (remote_socket == nullptr || remote_socket->adapter_ == nullptr) { + return nullptr; } - return remote_adapter ? &remote_adapter->GetDevice() : nullptr; + return &remote_socket->adapter_->GetDevice(); } std::unique_ptr BluetoothServerSocket::Accept() { diff --git a/internal/platform/implementation/g3/bluetooth_classic.h b/internal/platform/implementation/g3/bluetooth_classic.h index 140bdc12..6bae1fa3 100644 --- a/internal/platform/implementation/g3/bluetooth_classic.h +++ b/internal/platform/implementation/g3/bluetooth_classic.h @@ -27,6 +27,7 @@ #include "internal/platform/implementation/bluetooth_classic.h" #include "internal/platform/implementation/g3/bluetooth_adapter.h" #include "internal/platform/implementation/g3/pipe.h" +#include "internal/platform/implementation/g3/socket_base.h" #include "internal/platform/input_stream.h" #include "internal/platform/listeners.h" #include "internal/platform/output_stream.h" @@ -35,83 +36,34 @@ namespace nearby { namespace g3 { // https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html. -class BluetoothSocket : public api::BluetoothSocket { +class BluetoothSocket : public api::BluetoothSocket, public SocketBase { public: BluetoothSocket() = default; explicit BluetoothSocket(BluetoothAdapter* adapter) : adapter_(adapter) {} - ~BluetoothSocket() override; - - // Connects to another BluetoothSocket, to form a functional low-level - // channel. From this point on, and until Close is called, connection exists. - void Connect(BluetoothSocket& other); - - // NOTE: - // It is an undefined behavior if GetInputStream() or GetOutputStream() is - // called for a not-connected BluetoothSocket, i.e. any object that is not - // returned by BluetoothClassicMedium::ConnectToService() for client side or - // BluetoothServerSocket::Accept() for server side of connection. // Returns the InputStream of this connected BluetoothSocket. - InputStream& GetInputStream() override; + InputStream& GetInputStream() override { + return SocketBase::GetInputStream(); + } // Returns the OutputStream of this connected BluetoothSocket. // This stream is for local side to write. - OutputStream& GetOutputStream() override; - - // Returns true if connection exists to the (possibly closed) remote socket. - bool IsConnected() const ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true if socket is closed. - bool IsClosed() const ABSL_LOCKS_EXCLUDED(mutex_); + OutputStream& GetOutputStream() override { + return SocketBase::GetOutputStream(); + } // Closes both input and output streams, marks Socket as closed. // After this call object should be treated as not connected. // Returns Exception::kIo on error, Exception::kSuccess otherwise. - Exception Close() override ABSL_LOCKS_EXCLUDED(mutex_); + Exception Close() override { return SocketBase::Close(); } // https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#getRemoteDevice() // Returns valid BluetoothDevice pointer if there is a connection, and // nullptr otherwise. - BluetoothDevice* GetRemoteDevice() override ABSL_LOCKS_EXCLUDED(mutex_); + BluetoothDevice* GetRemoteDevice() override; 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_); - - class InvalidInputStream : public InputStream { - public: - ExceptionOr Read(std::int64_t size) override { - return ExceptionOr(Exception::kIo); - } - ExceptionOr Skip(size_t offset) override { - return ExceptionOr(Exception::kIo); - } - Exception Close() override { return {Exception::kIo}; } - }; - // Returned to the caller if the remote socket is destroyed. - InvalidInputStream invalid_input_stream_; - - // 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 output_{new Pipe}; - std::shared_ptr input_; - mutable absl::Mutex mutex_; BluetoothAdapter* adapter_ = nullptr; // Our Adapter. Read only. - BluetoothSocket* remote_socket_ ABSL_GUARDED_BY(mutex_) = nullptr; - bool closed_ ABSL_GUARDED_BY(mutex_) = false; }; // https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html. diff --git a/internal/platform/implementation/g3/socket_base.h b/internal/platform/implementation/g3/socket_base.h new file mode 100644 index 00000000..4da305b9 --- /dev/null +++ b/internal/platform/implementation/g3/socket_base.h @@ -0,0 +1,139 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_G3_SOCKET_BASE_H_ +#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_G3_SOCKET_BASE_H_ + +#include +#include +#include + +#include "absl/base/thread_annotations.h" +#include "absl/synchronization/mutex.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/exception.h" +#include "internal/platform/implementation/g3/pipe.h" +#include "internal/platform/input_stream.h" +#include "internal/platform/output_stream.h" + +namespace nearby { +namespace g3 { + +// Common base for BT, BLE and Wifi socket implementations. +class SocketBase { + public: + virtual ~SocketBase() { + absl::MutexLock lock(&mutex_); + DoClose(); + } + + // Connects to another Socket, to form a functional low-level + // channel. From this point on, and until Close is called, connection exists. + void Connect(SocketBase& other) ABSL_LOCKS_EXCLUDED(mutex_) { + absl::MutexLock lock(&mutex_); + remote_socket_ = &other; + input_ = other.output_; + } + + // Returns the InputStream of this connected socket. + InputStream& GetInputStream() ABSL_LOCKS_EXCLUDED(mutex_) { + absl::MutexLock lock(&mutex_); + if (IsConnectedLocked()) { + return input_->GetInputStream(); + } + return invalid_input_stream_; + } + + // Returns the OutputStream of this connected socket. + // This stream is for local side to write. + OutputStream& GetOutputStream() ABSL_LOCKS_EXCLUDED(mutex_) { + absl::MutexLock lock(&mutex_); + return output_->GetOutputStream(); + } + + // Returns true if connection exists to the (possibly closed) remote socket. + bool IsConnected() const ABSL_LOCKS_EXCLUDED(mutex_) { + absl::MutexLock lock(&mutex_); + return IsConnectedLocked(); + } + + // Returns true if socket is closed. + bool IsClosed() const ABSL_LOCKS_EXCLUDED(mutex_) { + absl::MutexLock lock(&mutex_); + return closed_; + } + + // Closes both input and output streams, marks Socket as closed. + // After this call object should be treated as not connected. + // Returns Exception::kIo on error, Exception::kSuccess otherwise. + Exception Close() ABSL_LOCKS_EXCLUDED(mutex_) { + absl::MutexLock lock(&mutex_); + DoClose(); + return {Exception::kSuccess}; + } + + SocketBase* GetRemoteSocket() ABSL_LOCKS_EXCLUDED(mutex_) { + absl::MutexLock lock(&mutex_); + return remote_socket_; + } + + protected: + mutable absl::Mutex mutex_; + + private: + void DoClose() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_) { + if (!closed_) { + remote_socket_ = nullptr; + output_->GetOutputStream().Close(); + output_->GetInputStream().Close(); + if (IsConnectedLocked()) { + input_->GetOutputStream().Close(); + input_->GetInputStream().Close(); + input_.reset(); + } + closed_ = true; + } + } + + // Returns true if connection exists to the (possibly closed) remote socket. + bool IsConnectedLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_) { + return input_ != nullptr; + } + + class InvalidInputStream : public InputStream { + public: + ExceptionOr Read(std::int64_t size) override { + return ExceptionOr(Exception::kIo); + } + ExceptionOr Skip(size_t offset) override { + return ExceptionOr(Exception::kIo); + } + Exception Close() override { return {Exception::kIo}; } + }; + // Returned to the caller if the remote socket is destroyed. + InvalidInputStream invalid_input_stream_; + + // 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 output_{new Pipe}; + std::shared_ptr input_; + SocketBase* remote_socket_ ABSL_GUARDED_BY(mutex_) = nullptr; + bool closed_ ABSL_GUARDED_BY(mutex_) = false; +}; + +} // namespace g3 +} // namespace nearby + +#endif // THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_G3_SOCKET_BASE_H_ diff --git a/internal/platform/implementation/g3/wifi_direct.cc b/internal/platform/implementation/g3/wifi_direct.cc index e0d2cdbe..d4d97261 100644 --- a/internal/platform/implementation/g3/wifi_direct.cc +++ b/internal/platform/implementation/g3/wifi_direct.cc @@ -29,67 +29,6 @@ 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) { diff --git a/internal/platform/implementation/g3/wifi_direct.h b/internal/platform/implementation/g3/wifi_direct.h index bab8ef25..fba77915 100644 --- a/internal/platform/implementation/g3/wifi_direct.h +++ b/internal/platform/implementation/g3/wifi_direct.h @@ -23,6 +23,7 @@ #include "absl/synchronization/mutex.h" #include "internal/platform/implementation/g3/multi_thread_executor.h" #include "internal/platform/implementation/g3/pipe.h" +#include "internal/platform/implementation/g3/socket_base.h" #include "internal/platform/implementation/wifi_direct.h" #include "internal/platform/input_stream.h" #include "internal/platform/output_stream.h" @@ -32,66 +33,28 @@ namespace g3 { class WifiDirectMedium; -class WifiDirectSocket : public api::WifiDirectSocket { +class WifiDirectSocket : public api::WifiDirectSocket, public SocketBase { 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_); + InputStream& GetInputStream() override { + return SocketBase::GetInputStream(); + } // 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_); + OutputStream& GetOutputStream() override { + return SocketBase::GetOutputStream(); + } // 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 output_{new Pipe}; - std::shared_ptr input_; - mutable absl::Mutex mutex_; - WifiDirectSocket* remote_socket_ ABSL_GUARDED_BY(mutex_) = nullptr; - bool closed_ ABSL_GUARDED_BY(mutex_) = false; + Exception Close() override { return SocketBase::Close(); } }; // WifiDirectServerSocket provides the support to server socket, this server diff --git a/internal/platform/implementation/g3/wifi_hotspot.cc b/internal/platform/implementation/g3/wifi_hotspot.cc index 49875714..d4ab753d 100644 --- a/internal/platform/implementation/g3/wifi_hotspot.cc +++ b/internal/platform/implementation/g3/wifi_hotspot.cc @@ -30,72 +30,6 @@ namespace nearby { namespace g3 { -// Code for WifiHotspotSocket -WifiHotspotSocket::~WifiHotspotSocket() { - absl::MutexLock lock(&mutex_); - DoClose(); -} - -void WifiHotspotSocket::Connect(WifiHotspotSocket& other) { - absl::MutexLock lock(&mutex_); - remote_socket_ = &other; - input_ = other.output_; -} - -InputStream& WifiHotspotSocket::GetInputStream() { - auto* remote_socket = GetRemoteSocket(); - CHECK(remote_socket != nullptr); - return remote_socket->GetLocalInputStream(); -} - -OutputStream& WifiHotspotSocket::GetOutputStream() { - return GetLocalOutputStream(); -} - -WifiHotspotSocket* WifiHotspotSocket::GetRemoteSocket() { - absl::MutexLock lock(&mutex_); - return remote_socket_; -} - -bool WifiHotspotSocket::IsConnected() const { - absl::MutexLock lock(&mutex_); - return IsConnectedLocked(); -} - -bool WifiHotspotSocket::IsClosed() const { - absl::MutexLock lock(&mutex_); - return closed_; -} - -Exception WifiHotspotSocket::Close() { - absl::MutexLock lock(&mutex_); - DoClose(); - return {Exception::kSuccess}; -} - -void WifiHotspotSocket::DoClose() { - if (!closed_) { - remote_socket_ = nullptr; - output_->GetOutputStream().Close(); - output_->GetInputStream().Close(); - input_->GetOutputStream().Close(); - input_->GetInputStream().Close(); - closed_ = true; - } -} - -bool WifiHotspotSocket::IsConnectedLocked() const { return input_ != nullptr; } - -InputStream& WifiHotspotSocket::GetLocalInputStream() { - absl::MutexLock lock(&mutex_); - return output_->GetInputStream(); -} - -OutputStream& WifiHotspotSocket::GetLocalOutputStream() { - absl::MutexLock lock(&mutex_); - return output_->GetOutputStream(); -} - // Code for WifiHotspotServerSocket std::string WifiHotspotServerSocket::GetName(absl::string_view ip_address, int port) { diff --git a/internal/platform/implementation/g3/wifi_hotspot.h b/internal/platform/implementation/g3/wifi_hotspot.h index d4682621..6c248dfd 100644 --- a/internal/platform/implementation/g3/wifi_hotspot.h +++ b/internal/platform/implementation/g3/wifi_hotspot.h @@ -24,6 +24,7 @@ #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/socket_base.h" #include "internal/platform/implementation/wifi_hotspot.h" #include "internal/platform/input_stream.h" #include "internal/platform/output_stream.h" @@ -33,69 +34,28 @@ namespace g3 { class WifiHotspotMedium; -class WifiHotspotSocket : public api::WifiHotspotSocket { +class WifiHotspotSocket : public api::WifiHotspotSocket, public SocketBase { public: - WifiHotspotSocket() = default; - ~WifiHotspotSocket() override; - WifiHotspotSocket(const WifiHotspotSocket&) = default; - WifiHotspotSocket(WifiHotspotSocket&&) = default; - WifiHotspotSocket& operator=(const WifiHotspotSocket&) = default; - WifiHotspotSocket& operator=(WifiHotspotSocket&&) = default; - - // Connect to another WifiHotspotSocket, to form a functional low-level - // channel. from this point on, and until Close is called, connection exists. - void Connect(WifiHotspotSocket& other) ABSL_LOCKS_EXCLUDED(mutex_); - // Returns the InputStream of the WifiHotspotSocket. // 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 WifiHotspotSocket object is destroyed. - InputStream& GetInputStream() override ABSL_LOCKS_EXCLUDED(mutex_); + InputStream& GetInputStream() override { + return SocketBase::GetInputStream(); + } // Returns the OutputStream of the WifiHotspotSocket. // 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 WifiHotspotSocket object is destroyed. - OutputStream& GetOutputStream() override ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns address of a remote WifiHotspotSocket or nullptr. - WifiHotspotSocket* GetRemoteSocket() ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true if connection exists to the (possibly closed) remote socket. - bool IsConnected() const ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true if socket is closed. - bool IsClosed() const ABSL_LOCKS_EXCLUDED(mutex_); + OutputStream& GetOutputStream() override { + return SocketBase::GetOutputStream(); + } // 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 output_{new Pipe}; - std::shared_ptr input_; - mutable absl::Mutex mutex_; - WifiHotspotSocket* remote_socket_ ABSL_GUARDED_BY(mutex_) = nullptr; - bool closed_ ABSL_GUARDED_BY(mutex_) = false; + Exception Close() override { return SocketBase::Close(); } }; // WifiHotspotServerSocket provides the support to server socket, this server diff --git a/internal/platform/implementation/g3/wifi_lan.cc b/internal/platform/implementation/g3/wifi_lan.cc index 043f921f..078c67b3 100644 --- a/internal/platform/implementation/g3/wifi_lan.cc +++ b/internal/platform/implementation/g3/wifi_lan.cc @@ -31,71 +31,6 @@ namespace nearby { namespace g3 { -WifiLanSocket::~WifiLanSocket() { - absl::MutexLock lock(&mutex_); - DoClose(); -} - -void WifiLanSocket::Connect(WifiLanSocket& other) { - absl::MutexLock lock(&mutex_); - remote_socket_ = &other; - input_ = other.output_; -} - -InputStream& WifiLanSocket::GetInputStream() { - auto* remote_socket = GetRemoteSocket(); - CHECK(remote_socket != nullptr); - return remote_socket->GetLocalInputStream(); -} - -OutputStream& WifiLanSocket::GetOutputStream() { - return GetLocalOutputStream(); -} - -WifiLanSocket* WifiLanSocket::GetRemoteSocket() { - absl::MutexLock lock(&mutex_); - return remote_socket_; -} - -bool WifiLanSocket::IsConnected() const { - absl::MutexLock lock(&mutex_); - return IsConnectedLocked(); -} - -bool WifiLanSocket::IsClosed() const { - absl::MutexLock lock(&mutex_); - return closed_; -} - -Exception WifiLanSocket::Close() { - absl::MutexLock lock(&mutex_); - DoClose(); - return {Exception::kSuccess}; -} - -void WifiLanSocket::DoClose() { - if (!closed_) { - remote_socket_ = nullptr; - output_->GetOutputStream().Close(); - output_->GetInputStream().Close(); - input_->GetOutputStream().Close(); - input_->GetInputStream().Close(); - closed_ = true; - } -} - -bool WifiLanSocket::IsConnectedLocked() const { return input_ != nullptr; } - -InputStream& WifiLanSocket::GetLocalInputStream() { - absl::MutexLock lock(&mutex_); - return output_->GetInputStream(); -} - -OutputStream& WifiLanSocket::GetLocalOutputStream() { - absl::MutexLock lock(&mutex_); - return output_->GetOutputStream(); -} - std::string WifiLanServerSocket::GetName(const std::string& ip_address, int port) { std::string dot_delimited_string; diff --git a/internal/platform/implementation/g3/wifi_lan.h b/internal/platform/implementation/g3/wifi_lan.h index 398f2c51..19cb18d3 100644 --- a/internal/platform/implementation/g3/wifi_lan.h +++ b/internal/platform/implementation/g3/wifi_lan.h @@ -25,6 +25,7 @@ #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/socket_base.h" #include "internal/platform/implementation/wifi_lan.h" #include "internal/platform/input_stream.h" #include "internal/platform/nsd_service_info.h" @@ -35,58 +36,26 @@ namespace g3 { class WifiLanMedium; -class WifiLanSocket : public api::WifiLanSocket { +class WifiLanSocket : public api::WifiLanSocket, public SocketBase { public: - WifiLanSocket() = default; - ~WifiLanSocket() override; - - // Connect to another WifiLanSocket, to form a functional low-level channel. - // from this point on, and until Close is called, connection exists. - void Connect(WifiLanSocket& other) ABSL_LOCKS_EXCLUDED(mutex_); - // Returns the InputStream of this connected WifiLanSocket. - InputStream& GetInputStream() override ABSL_LOCKS_EXCLUDED(mutex_); + InputStream& GetInputStream() override { + return SocketBase::GetInputStream(); + } // Returns the OutputStream of this connected WifiLanSocket. // This stream is for local side to write. - OutputStream& GetOutputStream() override ABSL_LOCKS_EXCLUDED(mutex_); + OutputStream& GetOutputStream() override { + return SocketBase::GetOutputStream(); + } // Returns address of a remote WifiLanSocket or nullptr. - WifiLanSocket* GetRemoteSocket() ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true if connection exists to the (possibly closed) remote socket. - bool IsConnected() const ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true if socket is closed. - bool IsClosed() const ABSL_LOCKS_EXCLUDED(mutex_); + WifiLanSocket* GetRemoteSocket() { + return static_cast(SocketBase::GetRemoteSocket()); + } // 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 output_{new Pipe}; - std::shared_ptr input_; - mutable absl::Mutex mutex_; - WifiLanSocket* remote_socket_ ABSL_GUARDED_BY(mutex_) = nullptr; - bool closed_ ABSL_GUARDED_BY(mutex_) = false; + Exception Close() override { return SocketBase::Close(); } }; class WifiLanServerSocket : public api::WifiLanServerSocket {