diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-05-12 15:59:20 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-05-25 06:57:22 +0000 |
commit | f7eaed5286974984ba5f9e3189d8f49d03e99f81 (patch) | |
tree | caed19b2af2024f35449fb0b781d0a25e09d4f8f /chromium/third_party/nearby/src/cpp/core/internal | |
parent | 9729c4479fe23554eae6e6dd1f30ff488f470c84 (diff) | |
download | qtwebengine-chromium-f7eaed5286974984ba5f9e3189d8f49d03e99f81.tar.gz |
BASELINE: Update Chromium to 100.0.4896.167
Change-Id: I98cbeb5d7543d966ffe04d8cefded0c493a11333
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/nearby/src/cpp/core/internal')
152 files changed, 0 insertions, 33301 deletions
diff --git a/chromium/third_party/nearby/src/cpp/core/internal/BUILD b/chromium/third_party/nearby/src/cpp/core/internal/BUILD deleted file mode 100644 index 9247f02e790..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/BUILD +++ /dev/null @@ -1,214 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -licenses(["notice"]) - -cc_library( - name = "internal", - srcs = [ - "base_endpoint_channel.cc", - "base_pcp_handler.cc", - "ble_advertisement.cc", - "ble_endpoint_channel.cc", - "bluetooth_bwu_handler.cc", - "bluetooth_device_name.cc", - "bluetooth_endpoint_channel.cc", - "bwu_manager.cc", - "client_proxy.cc", - "encryption_runner.cc", - "endpoint_channel_manager.cc", - "endpoint_manager.cc", - "injected_bluetooth_device_store.cc", - "internal_payload.cc", - "internal_payload_factory.cc", - "offline_frames.cc", - "offline_frames_validator.cc", - "offline_service_controller.cc", - "p2p_cluster_pcp_handler.cc", - "p2p_point_to_point_pcp_handler.cc", - "p2p_star_pcp_handler.cc", - "payload_manager.cc", - "pcp_manager.cc", - "service_controller_router.cc", - "webrtc_bwu_handler.cc", - "webrtc_endpoint_channel.cc", - "wifi_lan_bwu_handler.cc", - "wifi_lan_endpoint_channel.cc", - "wifi_lan_service_info.cc", - ], - hdrs = [ - "base_bwu_handler.h", - "base_endpoint_channel.h", - "base_pcp_handler.h", - "ble_advertisement.h", - "ble_endpoint_channel.h", - "bluetooth_bwu_handler.h", - "bluetooth_device_name.h", - "bluetooth_endpoint_channel.h", - "bwu_handler.h", - "bwu_manager.h", - "client_proxy.h", - "encryption_runner.h", - "endpoint_channel.h", - "endpoint_channel_manager.h", - "endpoint_manager.h", - "injected_bluetooth_device_store.h", - "internal_payload.h", - "internal_payload_factory.h", - "offline_frames.h", - "offline_frames_validator.h", - "offline_service_controller.h", - "p2p_cluster_pcp_handler.h", - "p2p_point_to_point_pcp_handler.h", - "p2p_star_pcp_handler.h", - "payload_manager.h", - "pcp.h", - "pcp_handler.h", - "pcp_manager.h", - "service_controller.h", - "service_controller_router.h", - "webrtc_bwu_handler.h", - "webrtc_endpoint_channel.h", - "wifi_lan_bwu_handler.h", - "wifi_lan_endpoint_channel.h", - "wifi_lan_service_info.h", - ], - compatible_with = ["//buildenv/target:non_prod"], - copts = ["-DCORE_ADAPTER_DLL"], - visibility = [ - "//core:__pkg__", - "//core/internal/fuzzers:__pkg__", - ], - deps = [ - ":message_lite", - "//absl/base:core_headers", - "//absl/container:btree", - "//absl/container:flat_hash_map", - "//absl/container:flat_hash_set", - "//absl/functional:bind_front", - "//absl/memory", - "//absl/strings", - "//absl/time", - "//absl/types:span", - "//analytics", - "//core:core_types", - "//core/internal/mediums", - "//core/internal/mediums:utils", - "//core/internal/mediums/webrtc", - "//platform/api:comm", - "//platform/base", - "//platform/base:cancellation_flag", - "//platform/base:error_code_recorder", - "//platform/base:util", - "//platform/public:comm", - "//platform/public:logging", - "//platform/public:types", - "//proto:connections_enums_portable_proto", - "//proto/connections:offline_wire_formats_portable_proto", - "//securegcm:ukey2", - ], -) - -cc_library( - name = "message_lite", - hdrs = [ - "message_lite.h", - ], - compatible_with = ["//buildenv/target:non_prod"], - visibility = [ - "//core:__subpackages__", - ], - deps = [ - "//net/proto2/compat/public:proto2_lite", - ], -) - -cc_library( - name = "internal_test", - testonly = True, - srcs = [ - "offline_simulation_user.cc", - "simulation_user.cc", - ], - hdrs = [ - "mock_service_controller.h", - "mock_service_controller_router.h", - "offline_simulation_user.h", - "simulation_user.h", - ], - visibility = [ - "//core:__subpackages__", - ], - deps = [ - ":internal", - "//testing/base/public:gunit_for_library_testonly", - "//absl/functional:bind_front", - "//absl/strings", - "//core:core_types", - "//platform/base", - "//platform/base:test_util", - "//platform/public:types", - ], -) - -cc_test( - name = "core_internal_test", - size = "small", - timeout = "moderate", - srcs = [ - "base_endpoint_channel_test.cc", - "base_pcp_handler_test.cc", - "ble_advertisement_test.cc", - "bluetooth_device_name_test.cc", - "bwu_manager_test.cc", - "client_proxy_test.cc", - "encryption_runner_test.cc", - "endpoint_channel_manager_test.cc", - "endpoint_manager_test.cc", - "injected_bluetooth_device_store_test.cc", - "internal_payload_factory_test.cc", - "offline_frames_test.cc", - "offline_frames_validator_test.cc", - "offline_service_controller_test.cc", - "p2p_cluster_pcp_handler_test.cc", - "payload_manager_test.cc", - "pcp_manager_test.cc", - "service_controller_router_test.cc", - "wifi_lan_service_info_test.cc", - ], - shard_count = 16, - deps = [ - ":internal", - ":internal_test", - "//testing/base/public:gunit", - "//testing/base/public:gunit_main", - "//absl/container:flat_hash_set", - "//absl/strings", - "//absl/synchronization", - "//absl/time", - "//absl/types:span", - "//analytics", - "//core:core_types", - "//core/internal/mediums", - "//core/internal/mediums:utils", - "//platform/base", - "//platform/base:test_util", - "//platform/impl/g3", # build_cleaner: keep - "//platform/public:comm", - "//platform/public:logging", - "//platform/public:types", - "//proto:connections_enums_portable_proto", - "//proto/connections:offline_wire_formats_portable_proto", - "//securegcm:ukey2", - ], -) diff --git a/chromium/third_party/nearby/src/cpp/core/internal/base_bwu_handler.h b/chromium/third_party/nearby/src/cpp/core/internal/base_bwu_handler.h deleted file mode 100644 index e26ca7b7450..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/base_bwu_handler.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_BASE_BWU_HANDLER_H_ -#define CORE_INTERNAL_BASE_BWU_HANDLER_H_ - -#include <cstdint> -#include <memory> -#include <string> - -#include "absl/container/flat_hash_map.h" -#include "absl/time/clock.h" -#include "core/internal/bwu_handler.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel_manager.h" -#include "platform/public/cancelable_alarm.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/scheduled_executor.h" -#include "platform/public/single_thread_executor.h" - -namespace location { -namespace nearby { -namespace connections { - -class BaseBwuHandler : public BwuHandler { - public: - using ClientIntroduction = BwuNegotiationFrame::ClientIntroduction; - - BaseBwuHandler(EndpointChannelManager& channel_manager, - BwuNotifications bwu_notifications) - : channel_manager_(&channel_manager), - bwu_notifications_(std::move(bwu_notifications)) {} - ~BaseBwuHandler() override = default; - - protected: - // Represents the incoming Socket the Initiator has gotten after initializing - // its upgraded bandwidth medium. - EndpointChannelManager* GetEndpointChannelManager(); - EndpointChannelManager* channel_manager_; - BwuNotifications bwu_notifications_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_BASE_BWU_HANDLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/base_endpoint_channel.cc b/chromium/third_party/nearby/src/cpp/core/internal/base_endpoint_channel.cc deleted file mode 100644 index bdc0d743ffe..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/base_endpoint_channel.cc +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/base_endpoint_channel.h" - -#include <cassert> - -#include "absl/strings/escaping.h" -#include "absl/strings/str_cat.h" -#include "core/internal/offline_frames.h" -#include "platform/base/byte_array.h" -#include "platform/base/exception.h" -#include "platform/public/logging.h" -#include "platform/public/mutex.h" -#include "platform/public/mutex_lock.h" -#include "proto/connections_enums.pb.h" - -namespace location { -namespace nearby { -namespace connections { - -namespace { - -std::int32_t BytesToInt(const ByteArray& bytes) { - const char* int_bytes = bytes.data(); - - std::int32_t result = 0; - result |= (static_cast<std::int32_t>(int_bytes[0]) & 0x0FF) << 24; - result |= (static_cast<std::int32_t>(int_bytes[1]) & 0x0FF) << 16; - result |= (static_cast<std::int32_t>(int_bytes[2]) & 0x0FF) << 8; - result |= (static_cast<std::int32_t>(int_bytes[3]) & 0x0FF); - - return result; -} - -ByteArray IntToBytes(std::int32_t value) { - char int_bytes[sizeof(std::int32_t)]; - int_bytes[0] = static_cast<char>((value >> 24) & 0x0FF); - int_bytes[1] = static_cast<char>((value >> 16) & 0x0FF); - int_bytes[2] = static_cast<char>((value >> 8) & 0x0FF); - int_bytes[3] = static_cast<char>((value)&0x0FF); - - return ByteArray(int_bytes, sizeof(int_bytes)); -} - -ExceptionOr<ByteArray> ReadExactly(InputStream* reader, std::int64_t size) { - ByteArray buffer(size); - std::int64_t current_pos = 0; - - while (current_pos < size) { - ExceptionOr<ByteArray> read_bytes = reader->Read(size - current_pos); - if (!read_bytes.ok()) { - return read_bytes; - } - ByteArray result = read_bytes.result(); - - if (result.Empty()) { - NEARBY_LOGS(WARNING) << __func__ << ": Empty result when reading bytes."; - return ExceptionOr<ByteArray>(Exception::kIo); - } - - buffer.CopyAt(current_pos, result); - current_pos += result.size(); - } - - return ExceptionOr<ByteArray>(std::move(buffer)); -} - -ExceptionOr<std::int32_t> ReadInt(InputStream* reader) { - ExceptionOr<ByteArray> read_bytes = ReadExactly(reader, sizeof(std::int32_t)); - if (!read_bytes.ok()) { - return ExceptionOr<std::int32_t>(read_bytes.exception()); - } - return ExceptionOr<std::int32_t>(BytesToInt(std::move(read_bytes.result()))); -} - -Exception WriteInt(OutputStream* writer, std::int32_t value) { - return writer->Write(IntToBytes(value)); -} - -} // namespace - -BaseEndpointChannel::BaseEndpointChannel(const std::string& channel_name, - InputStream* reader, - OutputStream* writer) - : channel_name_(channel_name), reader_(reader), writer_(writer) {} - -ExceptionOr<ByteArray> BaseEndpointChannel::Read() { - ByteArray result; - { - MutexLock lock(&reader_mutex_); - - ExceptionOr<std::int32_t> read_int = ReadInt(reader_); - if (!read_int.ok()) { - return ExceptionOr<ByteArray>(read_int.exception()); - } - - if (read_int.result() < 0 || read_int.result() > kMaxAllowedReadBytes) { - NEARBY_LOGS(WARNING) << __func__ << ": Read an invalid number of bytes: " - << read_int.result(); - return ExceptionOr<ByteArray>(Exception::kIo); - } - - ExceptionOr<ByteArray> read_bytes = ReadExactly(reader_, read_int.result()); - if (!read_bytes.ok()) { - return read_bytes; - } - result = std::move(read_bytes.result()); - } - - { - MutexLock crypto_lock(&crypto_mutex_); - if (IsEncryptionEnabledLocked()) { - // If encryption is enabled, decode the message. - std::string input(std::move(result)); - std::unique_ptr<std::string> decrypted_data = - crypto_context_->DecodeMessageFromPeer(input); - if (decrypted_data) { - result = ByteArray(std::move(*decrypted_data)); - } else { - // It could be a protocol race, where remote party sends a KEEP_ALIVE - // before encryption is setup on their side, and we receive it after - // we switched to encryption mode. - // In this case, we verify that message is indeed a valid KEEP_ALIVE, - // and let it through if it is, otherwise message is erased. - // TODO(apolyudov): verify this happens at most once per session. - result = {}; - auto parsed = parser::FromBytes(ByteArray(input)); - if (parsed.ok()) { - if (parser::GetFrameType(parsed.result()) == V1Frame::KEEP_ALIVE) { - NEARBY_LOGS(INFO) - << __func__ - << ": Read unencrypted KEEP_ALIVE on encrypted channel."; - result = ByteArray(input); - } else { - NEARBY_LOGS(WARNING) - << __func__ << ": Read unexpected unencrypted frame of type " - << parser::GetFrameType(parsed.result()); - } - } else { - NEARBY_LOGS(WARNING) - << __func__ << ": Unable to parse data as unencrypted message."; - } - } - if (result.Empty()) { - NEARBY_LOGS(WARNING) << __func__ << ": Unable to parse read result."; - return ExceptionOr<ByteArray>(Exception::kInvalidProtocolBuffer); - } - } - } - - { - MutexLock lock(&last_read_mutex_); - last_read_timestamp_ = SystemClock::ElapsedRealtime(); - } - return ExceptionOr<ByteArray>(result); -} - -Exception BaseEndpointChannel::Write(const ByteArray& data) { - { - MutexLock pause_lock(&is_paused_mutex_); - if (is_paused_) { - BlockUntilUnpaused(); - } - } - - ByteArray encrypted_data; - const ByteArray* data_to_write = &data; - { - // Holding both mutexes is necessary to prevent the keep alive and payload - // threads from writing encrypted messages out of order which causes a - // failure to decrypt on the reader side. However we need to release the - // crypto lock after encrypting to ensure read decryption is not blocked. - MutexLock lock(&writer_mutex_); - { - MutexLock crypto_lock(&crypto_mutex_); - if (IsEncryptionEnabledLocked()) { - // If encryption is enabled, encode the message. - std::unique_ptr<std::string> encrypted = - crypto_context_->EncodeMessageToPeer(std::string(data)); - if (!encrypted) { - NEARBY_LOGS(WARNING) << __func__ << ": Failed to encrypt data."; - return {Exception::kIo}; - } - encrypted_data = ByteArray(std::move(*encrypted)); - data_to_write = &encrypted_data; - } - } - - Exception write_exception = - WriteInt(writer_, static_cast<std::int32_t>(data_to_write->size())); - if (write_exception.Raised()) { - NEARBY_LOGS(WARNING) << __func__ << ": Failed to write header: " - << write_exception.value; - return write_exception; - } - write_exception = writer_->Write(*data_to_write); - if (write_exception.Raised()) { - NEARBY_LOGS(WARNING) << __func__ << ": Failed to write data: " - << write_exception.value; - return write_exception; - } - Exception flush_exception = writer_->Flush(); - if (flush_exception.Raised()) { - NEARBY_LOGS(WARNING) << __func__ << ": Failed to flush writer: " - << flush_exception.value; - return flush_exception; - } - } - - { - MutexLock lock(&last_write_mutex_); - last_write_timestamp_ = SystemClock::ElapsedRealtime(); - } - return {Exception::kSuccess}; -} - -void BaseEndpointChannel::Close() { - { - // In case channel is paused, resume it first thing. - MutexLock lock(&is_paused_mutex_); - UnblockPausedWriter(); - } - CloseIo(); - CloseImpl(); -} - -void BaseEndpointChannel::CloseIo() { - // Keep this method dedicated to reader and writer handling an nothing else. - { - // Do not take reader_mutex_ here: read may be in progress, and it will - // deadlock. Calling Close() with Read() in progress will terminate the - // IO and Read() will proceed normally (with Exception::kIo). - Exception exception = reader_->Close(); - if (!exception.Ok()) { - NEARBY_LOGS(WARNING) << __func__ - << ": Exception closing reader: " << exception.value; - } - } - { - // Do not take writer_mutex_ here: write may be in progress, and it will - // deadlock. Calling Close() with Write() in progress will terminate the - // IO and Write() will proceed normally (with Exception::kIo). - Exception exception = writer_->Close(); - if (!exception.Ok()) { - NEARBY_LOGS(WARNING) << __func__ - << ": Exception closing writer: " << exception.value; - } - } -} - -void BaseEndpointChannel::SetAnalyticsRecorder( - analytics::AnalyticsRecorder* analytics_recorder, - const std::string& endpoint_id) { - analytics_recorder_ = analytics_recorder; - endpoint_id_ = endpoint_id; -} - -void BaseEndpointChannel::Close( - proto::connections::DisconnectionReason reason) { - NEARBY_LOGS(INFO) << __func__ - << ": Closing endpoint channel, reason: " << reason; - Close(); - - if (analytics_recorder_ != nullptr && !endpoint_id_.empty()) { - analytics_recorder_->OnConnectionClosed(endpoint_id_, GetMedium(), reason); - } -} - -std::string BaseEndpointChannel::GetType() const { - MutexLock crypto_lock(&crypto_mutex_); - std::string subtype = IsEncryptionEnabledLocked() ? "ENCRYPTED_" : ""; - std::string medium = proto::connections::Medium_Name( - proto::connections::Medium::UNKNOWN_MEDIUM); - - if (GetMedium() != proto::connections::Medium::UNKNOWN_MEDIUM) { - medium = - absl::StrCat(subtype, proto::connections::Medium_Name(GetMedium())); - } - return medium; -} - -std::string BaseEndpointChannel::GetName() const { return channel_name_; } - -int BaseEndpointChannel::GetMaxTransmitPacketSize() const { - // Return default value if the medium never define it's chunk size. - return kDefaultMaxTransmitPacketSize; -} - -void BaseEndpointChannel::EnableEncryption( - std::shared_ptr<EncryptionContext> context) { - MutexLock crypto_lock(&crypto_mutex_); - crypto_context_ = context; -} - -void BaseEndpointChannel::DisableEncryption() { - MutexLock crypto_lock(&crypto_mutex_); - crypto_context_.reset(); -} - -bool BaseEndpointChannel::IsPaused() const { - MutexLock lock(&is_paused_mutex_); - return is_paused_; -} - -void BaseEndpointChannel::Pause() { - MutexLock lock(&is_paused_mutex_); - is_paused_ = true; -} - -void BaseEndpointChannel::Resume() { - MutexLock lock(&is_paused_mutex_); - is_paused_ = false; - is_paused_cond_.Notify(); -} - -absl::Time BaseEndpointChannel::GetLastReadTimestamp() const { - MutexLock lock(&last_read_mutex_); - return last_read_timestamp_; -} - -absl::Time BaseEndpointChannel::GetLastWriteTimestamp() const { - MutexLock lock(&last_write_mutex_); - return last_write_timestamp_; -} - -bool BaseEndpointChannel::IsEncryptionEnabledLocked() const { - return crypto_context_ != nullptr; -} - -void BaseEndpointChannel::BlockUntilUnpaused() { - // For more on how this works, see - // https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html - while (is_paused_) { - Exception wait_succeeded = is_paused_cond_.Wait(); - if (!wait_succeeded.Ok()) { - NEARBY_LOGS(WARNING) << __func__ << ": Failure waiting to unpause: " - << wait_succeeded.value; - return; - } - } -} - -void BaseEndpointChannel::UnblockPausedWriter() { - // For more on how this works, see - // https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html - is_paused_ = false; - is_paused_cond_.Notify(); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/base_endpoint_channel.h b/chromium/third_party/nearby/src/cpp/core/internal/base_endpoint_channel.h deleted file mode 100644 index 94518bda306..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/base_endpoint_channel.h +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_BASE_ENDPOINT_CHANNEL_H_ -#define CORE_INTERNAL_BASE_ENDPOINT_CHANNEL_H_ - -#include <cstdint> -#include <memory> -#include <string> - -#include "securegcm/d2d_connection_context_v1.h" -#include "absl/base/thread_annotations.h" -#include "analytics/analytics_recorder.h" -#include "core/internal/endpoint_channel.h" -#include "platform/base/byte_array.h" -#include "platform/base/input_stream.h" -#include "platform/base/output_stream.h" -#include "platform/public/atomic_reference.h" -#include "platform/public/condition_variable.h" -#include "platform/public/mutex.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { - -class BaseEndpointChannel : public EndpointChannel { - public: - BaseEndpointChannel(const std::string& channel_name, InputStream* reader, - OutputStream* writer); - ~BaseEndpointChannel() override = default; - - ExceptionOr<ByteArray> Read() - ABSL_LOCKS_EXCLUDED(reader_mutex_, crypto_mutex_, - last_read_mutex_) override; - - Exception Write(const ByteArray& data) - ABSL_LOCKS_EXCLUDED(writer_mutex_, crypto_mutex_) override; - - // Closes this EndpointChannel, without tracking the closure in analytics. - void Close() ABSL_LOCKS_EXCLUDED(is_paused_mutex_) override; - - // Closes this EndpointChannel and records the closure with the given reason. - void Close(proto::connections::DisconnectionReason reason) override; - - // Returns a one-word type descriptor for the concrete EndpointChannel - // implementation that can be used in log messages; eg: BLUETOOTH, BLE, - // WIFI. - std::string GetType() const override; - - // Returns the name of the EndpointChannel. - std::string GetName() const override; - - // Returns the maximum supported transmit packet size(MTU) for the underlying - // transport. - int GetMaxTransmitPacketSize() const override; - - // Enables encryption on the EndpointChannel. - // Should be called after connection is accepted by both parties, and - // before entering data phase, where Payloads may be exchanged. - void EnableEncryption(std::shared_ptr<EncryptionContext> context) override; - - // Disables encryption on the EndpointChannel. - void DisableEncryption() override; - - // True if the EndpointChannel is currently pausing all writes. - bool IsPaused() const ABSL_LOCKS_EXCLUDED(is_paused_mutex_) override; - - // Pauses all writes on this EndpointChannel until resume() is called. - void Pause() ABSL_LOCKS_EXCLUDED(is_paused_mutex_) override; - - // Resumes any writes on this EndpointChannel that were suspended when pause() - // was called. - void Resume() ABSL_LOCKS_EXCLUDED(is_paused_mutex_) override; - - // Returns the timestamp (returned by ElapsedRealtime) of the last read from - // this endpoint, or -1 if no reads have occurred. - absl::Time GetLastReadTimestamp() const - ABSL_LOCKS_EXCLUDED(last_read_mutex_) override; - - // Returns the timestamp (returned by ElapsedRealtime) of the last write to - // this endpoint, or -1 if no writes have occurred. - absl::Time GetLastWriteTimestamp() const - ABSL_LOCKS_EXCLUDED(last_write_mutex_) override; - - void SetAnalyticsRecorder(analytics::AnalyticsRecorder* analytics_recorder, - const std::string& endpoint_id) override; - - protected: - virtual void CloseImpl() = 0; - - private: - // Used to sanity check that our frame sizes are reasonable. - static constexpr std::int32_t kMaxAllowedReadBytes = 1048576; // 1MB - - // The default maximum transmit unit/packet size. - static constexpr int kDefaultMaxTransmitPacketSize = 65536; // 64 KB - - bool IsEncryptionEnabledLocked() const - ABSL_EXCLUSIVE_LOCKS_REQUIRED(crypto_mutex_); - void UnblockPausedWriter() ABSL_EXCLUSIVE_LOCKS_REQUIRED(is_paused_mutex_); - void BlockUntilUnpaused() ABSL_EXCLUSIVE_LOCKS_REQUIRED(is_paused_mutex_); - void CloseIo() ABSL_NO_THREAD_SAFETY_ANALYSIS; - - // We need a separate mutex to protect read timestamp, because if a read - // blocks on IO, we don't want timestamp read access to block too. - mutable Mutex last_read_mutex_; - absl::Time last_read_timestamp_ ABSL_GUARDED_BY(last_read_mutex_) = - absl::InfinitePast(); - - // We need a separate mutex to protect write timestamp, because if a write - // blocks on IO, we don't want timestamp write access to block too. - mutable Mutex last_write_mutex_; - absl::Time last_write_timestamp_ ABSL_GUARDED_BY(last_write_mutex_) = - absl::InfinitePast(); - - const std::string channel_name_; - - // The reader and writer are synchronized independently since we can't have - // writes waiting on reads that might potentially block forever. - Mutex reader_mutex_; - InputStream* reader_ ABSL_PT_GUARDED_BY(reader_mutex_); - - Mutex writer_mutex_; - OutputStream* writer_ ABSL_PT_GUARDED_BY(writer_mutex_); - - // An encryptor/decryptor. May be null. - mutable Mutex crypto_mutex_; - std::shared_ptr<EncryptionContext> crypto_context_ - ABSL_GUARDED_BY(crypto_mutex_) ABSL_PT_GUARDED_BY(crypto_mutex_); - - mutable Mutex is_paused_mutex_; - ConditionVariable is_paused_cond_{&is_paused_mutex_}; - // If true, writes should block until this has been set to false. - bool is_paused_ ABSL_GUARDED_BY(is_paused_mutex_) = false; - - analytics::AnalyticsRecorder* analytics_recorder_ = nullptr; - std::string endpoint_id_ = ""; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_BASE_ENDPOINT_CHANNEL_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/base_endpoint_channel_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/base_endpoint_channel_test.cc deleted file mode 100644 index 9d8ebc7e569..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/base_endpoint_channel_test.cc +++ /dev/null @@ -1,409 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/base_endpoint_channel.h" - -#include <functional> -#include <string> -#include <utility> - -#include "securegcm/d2d_connection_context_v1.h" -#include "securegcm/ukey2_handshake.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/synchronization/mutex.h" -#include "absl/time/time.h" -#include "core/internal/encryption_runner.h" -#include "core/internal/offline_frames.h" -#include "platform/base/byte_array.h" -#include "platform/base/exception.h" -#include "platform/base/input_stream.h" -#include "platform/base/output_stream.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/logging.h" -#include "platform/public/multi_thread_executor.h" -#include "platform/public/pipe.h" -#include "platform/public/single_thread_executor.h" -#include "proto/connections_enums.pb.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -using ::location::nearby::proto::connections::DisconnectionReason; -using ::location::nearby::proto::connections::Medium; -using EncryptionContext = BaseEndpointChannel::EncryptionContext; - -class TestEndpointChannel : public BaseEndpointChannel { - public: - explicit TestEndpointChannel(InputStream* input, OutputStream* output) - : BaseEndpointChannel("channel", input, output) {} - - MOCK_METHOD(Medium, GetMedium, (), (const override)); - MOCK_METHOD(void, CloseImpl, (), (override)); -}; - -std::function<void()> MakeDataPump( - std::string label, InputStream* input, OutputStream* output, - std::function<void(const ByteArray&)> monitor = nullptr) { - return [label, input, output, monitor]() { - NEARBY_LOGS(INFO) << "streaming data through '" << label << "'"; - while (true) { - auto read_response = input->Read(Pipe::kChunkSize); - if (!read_response.ok()) { - NEARBY_LOGS(INFO) << "Peer reader closed on '" << label << "'"; - output->Close(); - break; - } - if (monitor) { - monitor(read_response.result()); - } - auto write_response = output->Write(read_response.result()); - if (write_response.Raised()) { - NEARBY_LOGS(INFO) << "Peer writer closed on '" << label << "'"; - input->Close(); - break; - } - } - NEARBY_LOGS(INFO) << "streaming terminated on '" << label << "'"; - }; -} - -std::function<void(const ByteArray&)> MakeDataMonitor(const std::string& label, - std::string* capture, - absl::Mutex* mutex) { - return [label, capture, mutex](const ByteArray& input) mutable { - std::string s = std::string(input); - { - absl::MutexLock lock(mutex); - *capture += s; - } - NEARBY_LOGS(INFO) << "source='" << label << "'" - << "; message='" << s << "'"; - }; -} - -std::pair<std::shared_ptr<EncryptionContext>, - std::shared_ptr<EncryptionContext>> -DoDhKeyExchange(BaseEndpointChannel* channel_a, - BaseEndpointChannel* channel_b) { - std::shared_ptr<EncryptionContext> context_a; - std::shared_ptr<EncryptionContext> context_b; - EncryptionRunner crypto_a; - EncryptionRunner crypto_b; - ClientProxy proxy_a; - ClientProxy proxy_b; - CountDownLatch latch(2); - crypto_a.StartClient( - &proxy_a, "endpoint_id", channel_a, - { - .on_success_cb = - [&latch, &context_a]( - const std::string& endpoint_id, - std::unique_ptr<securegcm::UKey2Handshake> ukey2, - const std::string& auth_token, - const ByteArray& raw_auth_token) { - NEARBY_LOGS(INFO) << "client-A side key negotiation done"; - EXPECT_TRUE(ukey2->VerifyHandshake()); - auto context = ukey2->ToConnectionContext(); - EXPECT_NE(context, nullptr); - context_a = std::move(context); - latch.CountDown(); - }, - .on_failure_cb = - [&latch](const std::string& endpoint_id, - EndpointChannel* channel) { - NEARBY_LOGS(INFO) << "client-A side key negotiation failed"; - latch.CountDown(); - }, - }); - crypto_b.StartServer( - &proxy_b, "endpoint_id", channel_b, - { - .on_success_cb = - [&latch, &context_b]( - const std::string& endpoint_id, - std::unique_ptr<securegcm::UKey2Handshake> ukey2, - const std::string& auth_token, - const ByteArray& raw_auth_token) { - NEARBY_LOGS(INFO) << "client-B side key negotiation done"; - EXPECT_TRUE(ukey2->VerifyHandshake()); - auto context = ukey2->ToConnectionContext(); - EXPECT_NE(context, nullptr); - context_b = std::move(context); - latch.CountDown(); - }, - .on_failure_cb = - [&latch](const std::string& endpoint_id, - EndpointChannel* channel) { - NEARBY_LOGS(INFO) << "client-B side key negotiation failed"; - latch.CountDown(); - }, - }); - EXPECT_TRUE(latch.Await(absl::Milliseconds(5000)).result()); - return std::make_pair(std::move(context_a), std::move(context_b)); -} - -TEST(BaseEndpointChannelTest, ConstructorDestructorWorks) { - Pipe pipe; - InputStream& input_stream = pipe.GetInputStream(); - OutputStream& output_stream = pipe.GetOutputStream(); - - TestEndpointChannel test_channel(&input_stream, &output_stream); -} - -TEST(BaseEndpointChannelTest, ReadWrite) { - // Direct not-encrypted IO. - Pipe pipe_a; // channel_a writes to pipe_a, reads from pipe_b. - Pipe pipe_b; // channel_b writes to pipe_b, reads from pipe_a. - TestEndpointChannel channel_a(&pipe_b.GetInputStream(), - &pipe_a.GetOutputStream()); - TestEndpointChannel channel_b(&pipe_a.GetInputStream(), - &pipe_b.GetOutputStream()); - ByteArray tx_message{"data message"}; - channel_a.Write(tx_message); - ByteArray rx_message = std::move(channel_b.Read().result()); - EXPECT_EQ(rx_message, tx_message); -} - -TEST(BaseEndpointChannelTest, NotEncryptedReadWriteCanBeIntercepted) { - // Not encrypted IO; MITM scenario. - - // Setup test communication environment. - absl::Mutex mutex; - std::string capture_a; - std::string capture_b; - Pipe client_a; // Channel "a" writes to client "a", reads from server "a". - Pipe client_b; // Channel "b" writes to client "b", reads from server "b". - Pipe server_a; // Data pump "a" reads from client "a", writes to server "b". - Pipe server_b; // Data pump "b" reads from client "b", writes to server "a". - TestEndpointChannel channel_a(&server_a.GetInputStream(), - &client_a.GetOutputStream()); - TestEndpointChannel channel_b(&server_b.GetInputStream(), - &client_b.GetOutputStream()); - - ON_CALL(channel_a, GetMedium).WillByDefault([]() { return Medium::BLE; }); - ON_CALL(channel_b, GetMedium).WillByDefault([]() { return Medium::BLE; }); - - MultiThreadExecutor executor(2); - executor.Execute(MakeDataPump( - "pump_a", &client_a.GetInputStream(), &server_b.GetOutputStream(), - MakeDataMonitor("monitor_a", &capture_a, &mutex))); - executor.Execute(MakeDataPump( - "pump_b", &client_b.GetInputStream(), &server_a.GetOutputStream(), - MakeDataMonitor("monitor_b", &capture_b, &mutex))); - - EXPECT_EQ(channel_a.GetType(), "BLE"); - EXPECT_EQ(channel_b.GetType(), "BLE"); - - // Start data transfer - ByteArray tx_message{"data message"}; - channel_a.Write(tx_message); - ByteArray rx_message = std::move(channel_b.Read().result()); - - // Verify expectations. - EXPECT_EQ(rx_message, tx_message); - { - absl::MutexLock lock(&mutex); - std::string message{tx_message}; - EXPECT_TRUE(capture_a.find(message) != std::string::npos || - capture_b.find(message) != std::string::npos); - } - - // Shutdown test environment. - channel_a.Close(DisconnectionReason::LOCAL_DISCONNECTION); - channel_b.Close(DisconnectionReason::REMOTE_DISCONNECTION); -} - -TEST(BaseEndpointChannelTest, EncryptedReadWriteCanNotBeIntercepted) { - // Encrypted IO; MITM scenario. - - // Setup test communication environment. - absl::Mutex mutex; - std::string capture_a; - std::string capture_b; - Pipe client_a; // Channel "a" writes to client "a", reads from server "a". - Pipe client_b; // Channel "b" writes to client "b", reads from server "b". - Pipe server_a; // Data pump "a" reads from client "a", writes to server "b". - Pipe server_b; // Data pump "b" reads from client "b", writes to server "a". - TestEndpointChannel channel_a(&server_a.GetInputStream(), - &client_a.GetOutputStream()); - TestEndpointChannel channel_b(&server_b.GetInputStream(), - &client_b.GetOutputStream()); - - ON_CALL(channel_a, GetMedium).WillByDefault([]() { - return Medium::BLUETOOTH; - }); - ON_CALL(channel_b, GetMedium).WillByDefault([]() { - return Medium::BLUETOOTH; - }); - - MultiThreadExecutor executor(2); - executor.Execute(MakeDataPump( - "pump_a", &client_a.GetInputStream(), &server_b.GetOutputStream(), - MakeDataMonitor("monitor_a", &capture_a, &mutex))); - executor.Execute(MakeDataPump( - "pump_b", &client_b.GetInputStream(), &server_a.GetOutputStream(), - MakeDataMonitor("monitor_b", &capture_b, &mutex))); - - // Run DH key exchange; setup encryption contexts for channels. - auto [context_a, context_b] = DoDhKeyExchange(&channel_a, &channel_b); - ASSERT_NE(context_a, nullptr); - ASSERT_NE(context_b, nullptr); - channel_a.EnableEncryption(context_a); - channel_b.EnableEncryption(context_b); - - EXPECT_EQ(channel_a.GetType(), "ENCRYPTED_BLUETOOTH"); - EXPECT_EQ(channel_b.GetType(), "ENCRYPTED_BLUETOOTH"); - - // Start data transfer - ByteArray tx_message{"data message"}; - channel_a.Write(tx_message); - ByteArray rx_message = std::move(channel_b.Read().result()); - - // Verify expectations. - EXPECT_EQ(rx_message, tx_message); - { - absl::MutexLock lock(&mutex); - std::string message{tx_message}; - EXPECT_TRUE(capture_a.find(message) == std::string::npos && - capture_b.find(message) == std::string::npos); - } - - // Shutdown test environment. - channel_a.Close(DisconnectionReason::LOCAL_DISCONNECTION); - channel_b.Close(DisconnectionReason::REMOTE_DISCONNECTION); -} - -TEST(BaseEndpointChannelTest, CanBesuspendedAndResumed) { - // Setup test communication environment. - Pipe pipe_a; // channel_a writes to pipe_a, reads from pipe_b. - Pipe pipe_b; // channel_b writes to pipe_b, reads from pipe_a. - TestEndpointChannel channel_a(&pipe_b.GetInputStream(), - &pipe_a.GetOutputStream()); - TestEndpointChannel channel_b(&pipe_a.GetInputStream(), - &pipe_b.GetOutputStream()); - - ON_CALL(channel_a, GetMedium).WillByDefault([]() { - return Medium::WIFI_LAN; - }); - ON_CALL(channel_b, GetMedium).WillByDefault([]() { - return Medium::WIFI_LAN; - }); - - EXPECT_EQ(channel_a.GetType(), "WIFI_LAN"); - EXPECT_EQ(channel_b.GetType(), "WIFI_LAN"); - - // Start data transfer - ByteArray tx_message{"data message"}; - ByteArray more_message{"more data"}; - channel_a.Write(tx_message); - ByteArray rx_message = std::move(channel_b.Read().result()); - - // Pause and make sure reader blocks. - MultiThreadExecutor pause_resume_executor(2); - channel_a.Pause(); - pause_resume_executor.Execute([&channel_a, &more_message]() { - // Write will block until channel is resumed, or closed. - EXPECT_TRUE(channel_a.Write(more_message).Ok()); - }); - CountDownLatch latch(1); - ByteArray read_more; - pause_resume_executor.Execute([&channel_b, &read_more, &latch]() { - // Read will block until channel is resumed, or closed. - auto response = channel_b.Read(); - EXPECT_TRUE(response.ok()); - read_more = std::move(response.result()); - latch.CountDown(); - }); - absl::SleepFor(absl::Milliseconds(500)); - EXPECT_TRUE(read_more.Empty()); - - // Resume; verify that data transfer comepleted. - channel_a.Resume(); - EXPECT_TRUE(latch.Await(absl::Milliseconds(1000)).result()); - EXPECT_EQ(read_more, more_message); - - // Shutdown test environment. - channel_a.Close(DisconnectionReason::LOCAL_DISCONNECTION); - channel_b.Close(DisconnectionReason::REMOTE_DISCONNECTION); -} - -TEST(BaseEndpointChannelTest, ReadAfterInputStreamClosed) { - Pipe pipe; - InputStream& input_stream = pipe.GetInputStream(); - OutputStream& output_stream = pipe.GetOutputStream(); - - TestEndpointChannel test_channel(&input_stream, &output_stream); - - // Close the output stream before trying to read from the input. - output_stream.Close(); - - // Trying to read should fail gracefully with an IO error. - ExceptionOr<ByteArray> read_data = test_channel.Read(); - - ASSERT_FALSE(read_data.ok()); - ASSERT_TRUE(read_data.GetException().Raised(Exception::kIo)); -} - -TEST(BaseEndpointChannelTest, ReadUnencryptedFrameOnEncryptedChannel) { - // Setup test communication environment. - Pipe pipe_a; // channel_a writes to pipe_a, reads from pipe_b. - Pipe pipe_b; // channel_b writes to pipe_b, reads from pipe_a. - TestEndpointChannel channel_a(&pipe_b.GetInputStream(), - &pipe_a.GetOutputStream()); - TestEndpointChannel channel_b(&pipe_a.GetInputStream(), - &pipe_b.GetOutputStream()); - - ON_CALL(channel_a, GetMedium).WillByDefault([]() { - return Medium::BLUETOOTH; - }); - ON_CALL(channel_b, GetMedium).WillByDefault([]() { - return Medium::BLUETOOTH; - }); - - // Run DH key exchange; setup encryption contexts for channels. But only - // encrypt |channel_b|. - auto [context_a, context_b] = DoDhKeyExchange(&channel_a, &channel_b); - ASSERT_NE(context_a, nullptr); - ASSERT_NE(context_b, nullptr); - channel_b.EnableEncryption(context_b); - - EXPECT_EQ(channel_a.GetType(), "BLUETOOTH"); - EXPECT_EQ(channel_b.GetType(), "ENCRYPTED_BLUETOOTH"); - - // An unencrypted KeepAlive should succeed. - ByteArray keep_alive_message = parser::ForKeepAlive(); - channel_a.Write(keep_alive_message); - ExceptionOr<ByteArray> result = channel_b.Read(); - EXPECT_TRUE(result.ok()); - EXPECT_EQ(result.result(), keep_alive_message); - - // An unencrypted data frame should fail. - ByteArray tx_message{"data message"}; - channel_a.Write(tx_message); - result = channel_b.Read(); - EXPECT_FALSE(result.ok()); - EXPECT_EQ(result.exception(), Exception::kInvalidProtocolBuffer); - - // Shutdown test environment. - channel_a.Close(DisconnectionReason::LOCAL_DISCONNECTION); - channel_b.Close(DisconnectionReason::REMOTE_DISCONNECTION); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/base_pcp_handler.cc b/chromium/third_party/nearby/src/cpp/core/internal/base_pcp_handler.cc deleted file mode 100644 index 8e3bf3e9455..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/base_pcp_handler.cc +++ /dev/null @@ -1,1533 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/base_pcp_handler.h" - -#include <cassert> -#include <cinttypes> -#include <cstdlib> -#include <limits> -#include <memory> - -#include "securegcm/d2d_connection_context_v1.h" -#include "securegcm/ukey2_handshake.h" -#include "absl/container/flat_hash_set.h" -#include "absl/strings/escaping.h" -#include "absl/types/span.h" -#include "core/internal/mediums/utils.h" -#include "core/internal/offline_frames.h" -#include "core/internal/pcp_handler.h" -#include "core/options.h" -#include "platform/base/base64_utils.h" -#include "platform/base/bluetooth_utils.h" -#include "platform/public/logging.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { - -using ::location::nearby::proto::connections::Medium; -using ::securegcm::UKey2Handshake; - -constexpr absl::Duration BasePcpHandler::kConnectionRequestReadTimeout; -constexpr absl::Duration BasePcpHandler::kRejectedConnectionCloseDelay; - -BasePcpHandler::BasePcpHandler(Mediums* mediums, - EndpointManager* endpoint_manager, - EndpointChannelManager* channel_manager, - BwuManager* bwu_manager, Pcp pcp) - : mediums_(mediums), - endpoint_manager_(endpoint_manager), - channel_manager_(channel_manager), - pcp_(pcp), - bwu_manager_(bwu_manager) {} - -BasePcpHandler::~BasePcpHandler() { - NEARBY_LOGS(INFO) << "Initiating shutdown of BasePcpHandler(" - << strategy_.GetName() << ")"; - DisconnectFromEndpointManager(); - // Stop all the ongoing Runnables (as gracefully as possible). - NEARBY_LOGS(INFO) << "BasePcpHandler(" << strategy_.GetName() - << ") is bringing down executors."; - serial_executor_.Shutdown(); - alarm_executor_.Shutdown(); - NEARBY_LOGS(INFO) << "BasePcpHandler(" << strategy_.GetName() - << ") has shut down."; -} - -void BasePcpHandler::DisconnectFromEndpointManager() { - if (stop_.Set(true)) return; - NEARBY_LOGS(INFO) << "BasePcpHandler(" << strategy_.GetName() - << ") unregister from EPM."; - // Unregister ourselves from EPM message dispatcher. - endpoint_manager_->UnregisterFrameProcessor(V1Frame::CONNECTION_RESPONSE, - this); -} - -Status BasePcpHandler::StartAdvertising(ClientProxy* client, - const std::string& service_id, - const ConnectionOptions& options, - const ConnectionRequestInfo& info) { - Future<Status> response; - NEARBY_LOGS(INFO) << "StartAdvertising with supported mediums: " - << GetStringValueOfSupportedMediums(options); - ConnectionOptions advertising_options = options.CompatibleOptions(); - RunOnPcpHandlerThread( - "start-advertising", - [this, client, &service_id, &info, &advertising_options, &response]() - RUN_ON_PCP_HANDLER_THREAD() { - // The endpoint id inside of the advertisement is different to high - // visibility and low visibility mode. In order to decide if client - // should grab the high visibility or low visibility id, it needs to - // tell client which one right now, before - // client#StartedAdvertising. - if (ShouldEnterHighVisibilityMode(advertising_options)) { - client->EnterHighVisibilityMode(); - } - - auto result = StartAdvertisingImpl( - client, service_id, client->GetLocalEndpointId(), - info.endpoint_info, advertising_options); - if (!result.status.Ok()) { - client->ExitHighVisibilityMode(); - response.Set(result.status); - return; - } - - // Now that we've succeeded, mark the client as advertising. - // Save the advertising options for local reference in later process - // like upgrading bandwidth. - advertising_listener_ = info.listener; - client->StartedAdvertising(service_id, GetStrategy(), info.listener, - absl::MakeSpan(result.mediums), - advertising_options); - response.Set({Status::kSuccess}); - }); - return WaitForResult(absl::StrCat("StartAdvertising(", service_id, ")"), - client->GetClientId(), &response); -} - -void BasePcpHandler::StopAdvertising(ClientProxy* client) { - NEARBY_LOGS(INFO) << "StopAdvertising local_endpoint_id=" - << client->GetLocalEndpointId(); - CountDownLatch latch(1); - RunOnPcpHandlerThread("stop-advertising", - [this, client, &latch]() RUN_ON_PCP_HANDLER_THREAD() { - StopAdvertisingImpl(client); - client->StoppedAdvertising(); - latch.CountDown(); - }); - WaitForLatch("StopAdvertising", &latch); -} - -std::string BasePcpHandler::GetStringValueOfSupportedMediums( - const ConnectionOptions& options) const { - std::ostringstream result; - result << "{ "; - if (options.allowed.bluetooth) { - result << proto::connections::Medium_Name(Medium::BLUETOOTH) << " "; - } - if (options.allowed.ble) { - result << proto::connections::Medium_Name(Medium::BLE) << " "; - } - if (options.allowed.web_rtc) { - result << proto::connections::Medium_Name(Medium::WEB_RTC) << " "; - } - if (options.allowed.wifi_lan) { - result << proto::connections::Medium_Name(Medium::WIFI_LAN) << " "; - } - result << "}"; - return result.str(); -} - -bool BasePcpHandler::ShouldEnterHighVisibilityMode( - const ConnectionOptions& options) { - return !options.low_power && options.allowed.bluetooth; -} - -BooleanMediumSelector BasePcpHandler::ComputeIntersectionOfSupportedMediums( - const PendingConnectionInfo& connection_info) { - absl::flat_hash_set<Medium> intersection; - auto their_mediums = connection_info.supported_mediums; - - // If no supported mediums were set, use the default upgrade medium. - if (their_mediums.empty()) { - their_mediums.push_back(GetDefaultUpgradeMedium()); - } - - for (Medium my_medium : GetConnectionMediumsByPriority()) { - if (std::find(their_mediums.begin(), their_mediums.end(), my_medium) != - their_mediums.end()) { - // We use advertising options as a proxy to whether or not the local - // client does want to enable a WebRTC upgrade. - if (my_medium == location::nearby::proto::connections::Medium::WEB_RTC) { - ConnectionOptions advertising_options = - connection_info.client->GetAdvertisingOptions(); - - if (!advertising_options.enable_webrtc_listening && - !advertising_options.allowed.web_rtc) { - // The local client does not allow WebRTC for listening or upgrades, - // ignore. - continue; - } - } - - intersection.emplace(my_medium); - } - } - - // Not using designated initializers here since the VS C++ compiler errors - // out indicating that MediumSelector<bool> is not an aggregate - MediumSelector<bool> mediumSelector{}; - mediumSelector.bluetooth = intersection.contains(Medium::BLUETOOTH); - mediumSelector.ble = intersection.contains(Medium::BLE); - mediumSelector.web_rtc = intersection.contains(Medium::WEB_RTC); - mediumSelector.wifi_lan = intersection.contains(Medium::WIFI_LAN); - return mediumSelector; -} - -Status BasePcpHandler::StartDiscovery(ClientProxy* client, - const std::string& service_id, - const ConnectionOptions& options, - const DiscoveryListener& listener) { - Future<Status> response; - ConnectionOptions discovery_options = options.CompatibleOptions(); - - NEARBY_LOGS(INFO) << "StartDiscovery with supported mediums:" - << GetStringValueOfSupportedMediums(options); - RunOnPcpHandlerThread( - "start-discovery", [this, client, service_id, discovery_options, - &listener, &response]() RUN_ON_PCP_HANDLER_THREAD() { - // Ask the implementation to attempt to start discovery. - auto result = StartDiscoveryImpl(client, service_id, discovery_options); - if (!result.status.Ok()) { - response.Set(result.status); - return; - } - - // Now that we've succeeded, mark the client as discovering and clear - // out any old endpoints we had discovered. - discovered_endpoints_.clear(); - client->StartedDiscovery(service_id, GetStrategy(), listener, - absl::MakeSpan(result.mediums), - discovery_options); - response.Set({Status::kSuccess}); - }); - return WaitForResult(absl::StrCat("StartDiscovery(", service_id, ")"), - client->GetClientId(), &response); -} - -void BasePcpHandler::StopDiscovery(ClientProxy* client) { - CountDownLatch latch(1); - RunOnPcpHandlerThread("stop-discovery", - [this, client, &latch]() RUN_ON_PCP_HANDLER_THREAD() { - StopDiscoveryImpl(client); - client->StoppedDiscovery(); - latch.CountDown(); - }); - - WaitForLatch("StopDiscovery", &latch); -} - -void BasePcpHandler::InjectEndpoint( - ClientProxy* client, const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) { - CountDownLatch latch(1); - RunOnPcpHandlerThread("inject-endpoint", - [this, client, service_id, metadata, &latch]() - RUN_ON_PCP_HANDLER_THREAD() { - InjectEndpointImpl(client, service_id, metadata); - latch.CountDown(); - }); - - WaitForLatch(absl::StrCat("InjectEndpoint(", service_id, ")"), &latch); -} - -void BasePcpHandler::WaitForLatch(const std::string& method_name, - CountDownLatch* latch) { - Exception await_exception = latch->Await(); - if (!await_exception.Ok()) { - if (await_exception.Raised(Exception::kTimeout)) { - NEARBY_LOGS(INFO) << "Blocked in " << method_name; - } - } -} - -Status BasePcpHandler::WaitForResult(const std::string& method_name, - std::int64_t client_id, - Future<Status>* future) { - if (!future) { - NEARBY_LOGS(INFO) << "No future to wait for; return with error"; - return {Status::kError}; - } - NEARBY_LOGS(INFO) << "Waiting for future to complete: " << method_name; - ExceptionOr<Status> result = future->Get(); - if (!result.ok()) { - NEARBY_LOGS(INFO) << "Future:[" << method_name - << "] completed with exception:" << result.exception(); - return {Status::kError}; - } - NEARBY_LOGS(INFO) << "Future:[" << method_name - << "] completed with status:" << result.result().value; - return result.result(); -} - -void BasePcpHandler::RunOnPcpHandlerThread(const std::string& name, - Runnable runnable) { - serial_executor_.Execute(name, std::move(runnable)); -} - -EncryptionRunner::ResultListener BasePcpHandler::GetResultListener() { - return { - .on_success_cb = - [this](const std::string& endpoint_id, - std::unique_ptr<UKey2Handshake> ukey2, - const std::string& auth_token, - const ByteArray& raw_auth_token) { - RunOnPcpHandlerThread( - "encryption-success", - [this, endpoint_id, raw_ukey2 = ukey2.release(), auth_token, - raw_auth_token]() RUN_ON_PCP_HANDLER_THREAD() mutable { - OnEncryptionSuccessRunnable( - endpoint_id, std::unique_ptr<UKey2Handshake>(raw_ukey2), - auth_token, raw_auth_token); - }); - }, - .on_failure_cb = - [this](const std::string& endpoint_id, EndpointChannel* channel) { - RunOnPcpHandlerThread( - "encryption-failure", - [this, endpoint_id, channel]() RUN_ON_PCP_HANDLER_THREAD() { - NEARBY_LOGS(ERROR) - << "Encryption failed for endpoint_id=" << endpoint_id - << " on medium=" - << proto::connections::Medium_Name(channel->GetMedium()); - OnEncryptionFailureRunnable(endpoint_id, channel); - }); - }, - }; -} - -void BasePcpHandler::OnEncryptionSuccessRunnable( - const std::string& endpoint_id, std::unique_ptr<UKey2Handshake> ukey2, - const std::string& auth_token, const ByteArray& raw_auth_token) { - // Quick fail if we've been removed from pending connections while we were - // busy running UKEY2. - auto it = pending_connections_.find(endpoint_id); - if (it == pending_connections_.end()) { - NEARBY_LOGS(INFO) - << "Connection not found on UKEY negotination complete; endpoint_id=" - << endpoint_id; - return; - } - - BasePcpHandler::PendingConnectionInfo& connection_info = it->second; - Medium medium = connection_info.channel->GetMedium(); - - if (!ukey2) { - // Fail early, if there is no crypto context. - ProcessPreConnectionInitiationFailure( - connection_info.client, medium, endpoint_id, - connection_info.channel.get(), connection_info.is_incoming, - connection_info.start_time, {Status::kEndpointIoError}, - connection_info.result.lock().get()); - return; - } - - connection_info.SetCryptoContext(std::move(ukey2)); - connection_info.connection_token = GetHashedConnectionToken(raw_auth_token); - NEARBY_LOGS(INFO) - << "Register encrypted connection; wait for response; endpoint_id=" - << endpoint_id; - - // Set ourselves up so that we receive all acceptance/rejection messages - endpoint_manager_->RegisterFrameProcessor(V1Frame::CONNECTION_RESPONSE, this); - - // Now we register our endpoint so that we can listen for both sides to - // accept. - endpoint_manager_->RegisterEndpoint( - connection_info.client, endpoint_id, - { - .remote_endpoint_info = connection_info.remote_endpoint_info, - .authentication_token = auth_token, - .raw_authentication_token = raw_auth_token, - .is_incoming_connection = connection_info.is_incoming, - }, - { - .strategy = connection_info.options.strategy, - .allowed = ComputeIntersectionOfSupportedMediums(connection_info), - .auto_upgrade_bandwidth = - connection_info.options.auto_upgrade_bandwidth, - .enforce_topology_constraints = - connection_info.options.enforce_topology_constraints, - .low_power = connection_info.options.low_power, - .enable_bluetooth_listening = - connection_info.options.enable_bluetooth_listening, - .enable_webrtc_listening = - connection_info.options.enable_webrtc_listening, - .is_out_of_band_connection = - connection_info.options.is_out_of_band_connection, - .remote_bluetooth_mac_address = - connection_info.options.remote_bluetooth_mac_address, - .fast_advertisement_service_uuid = - connection_info.options.fast_advertisement_service_uuid, - .keep_alive_interval_millis = - connection_info.options.keep_alive_interval_millis, - .keep_alive_timeout_millis = - connection_info.options.keep_alive_timeout_millis, - }, - std::move(connection_info.channel), connection_info.listener, - connection_info.connection_token); - - if (connection_info.is_incoming) { - connection_info.client->GetAnalyticsRecorder().OnIncomingConnectionAttempt( - proto::connections::INITIAL, medium, proto::connections::RESULT_SUCCESS, - SystemClock::ElapsedRealtime() - connection_info.start_time, - connection_info.connection_token); - } else { - connection_info.client->GetAnalyticsRecorder().OnOutgoingConnectionAttempt( - endpoint_id, proto::connections::INITIAL, medium, - proto::connections::RESULT_SUCCESS, - SystemClock::ElapsedRealtime() - connection_info.start_time, - connection_info.connection_token); - } - - if (auto future_status = connection_info.result.lock()) { - NEARBY_LOGS(INFO) << "Connection established; Finalising future OK."; - future_status->Set({Status::kSuccess}); - connection_info.result.reset(); - } -} - -void BasePcpHandler::OnEncryptionFailureRunnable( - const std::string& endpoint_id, EndpointChannel* endpoint_channel) { - auto it = pending_connections_.find(endpoint_id); - if (it == pending_connections_.end()) { - NEARBY_LOGS(INFO) - << "Connection not found on UKEY negotination complete; endpoint_id=" - << endpoint_id; - return; - } - - BasePcpHandler::PendingConnectionInfo& info = it->second; - // We had a bug here, caused by a race with EncryptionRunner. We now verify - // the EndpointChannel to avoid it. In a simultaneous connection, we clean - // up one of the two EndpointChannels and then update our pendingConnections - // with the winning channel's state. Closing a channel that was in the - // middle of EncryptionRunner would trigger onEncryptionFailed, and, since - // the map had already updated with the winning EndpointChannel, we closed - // it too by accident. - if (*endpoint_channel != *info.channel) { - NEARBY_LOGS(INFO) << "Not destroying channel [mismatch]: passed=" - << endpoint_channel->GetName() - << "; expected=" << info.channel->GetName(); - return; - } - - ProcessPreConnectionInitiationFailure( - info.client, info.channel->GetMedium(), endpoint_id, info.channel.get(), - info.is_incoming, info.start_time, {Status::kEndpointIoError}, - info.result.lock().get()); -} - -Status BasePcpHandler::RequestConnection(ClientProxy* client, - const std::string& endpoint_id, - const ConnectionRequestInfo& info, - const ConnectionOptions& options) { - auto result = std::make_shared<Future<Status>>(); - RunOnPcpHandlerThread( - "request-connection", [this, client, &info, options, endpoint_id, - result]() RUN_ON_PCP_HANDLER_THREAD() { - absl::Time start_time = SystemClock::ElapsedRealtime(); - - // If we already have a pending connection, then we shouldn't allow any - // more outgoing connections to this endpoint. - if (pending_connections_.count(endpoint_id)) { - NEARBY_LOGS(INFO) - << "In requestConnection(), connection requested with " - "endpoint(id=" - << endpoint_id - << "), but we already have a pending connection with them."; - result->Set({Status::kAlreadyConnectedToEndpoint}); - return; - } - - // If our child class says we can't send any more outgoing connections, - // listen to them. - if (ShouldEnforceTopologyConstraints(client->GetAdvertisingOptions()) && - !CanSendOutgoingConnection(client)) { - NEARBY_LOGS(INFO) - << "In requestConnection(), client=" << client->GetClientId() - << " attempted a connection with endpoint(id=" << endpoint_id - << "), but outgoing connections are disallowed"; - result->Set({Status::kOutOfOrderApiCall}); - return; - } - - DiscoveredEndpoint* endpoint = GetDiscoveredEndpoint(endpoint_id); - if (endpoint == nullptr) { - NEARBY_LOGS(INFO) - << "Discovered endpoint not found: endpoint_id=" << endpoint_id; - result->Set({Status::kEndpointUnknown}); - return; - } - - auto remote_bluetooth_mac_address = - BluetoothUtils::ToString(options.remote_bluetooth_mac_address); - if (!remote_bluetooth_mac_address.empty()) { - if (AppendRemoteBluetoothMacAddressEndpoint( - endpoint_id, remote_bluetooth_mac_address, - client->GetDiscoveryOptions())) - NEARBY_LOGS(INFO) - << "Appended remote Bluetooth MAC Address endpoint [" - << remote_bluetooth_mac_address << "]"; - } - - if (AppendWebRTCEndpoint(endpoint_id, client->GetDiscoveryOptions())) - NEARBY_LOGS(INFO) << "Appended Web RTC endpoint."; - - auto discovered_endpoints = GetDiscoveredEndpoints(endpoint_id); - std::unique_ptr<EndpointChannel> channel; - ConnectImplResult connect_impl_result; - - for (auto connect_endpoint : discovered_endpoints) { - absl::Time connect_start_time = SystemClock::ElapsedRealtime(); - if (!MediumSupportedByClientOptions(connect_endpoint->medium, - options)) - continue; - connect_impl_result = ConnectImpl(client, connect_endpoint); - if (connect_impl_result.status.Ok()) { - channel = std::move(connect_impl_result.endpoint_channel); - break; - } else { - LogConnectionAttempt(client, connect_endpoint->medium, - connect_endpoint->endpoint_id, - /* is_incoming = */ false, connect_start_time); - } - } - - Medium channel_medium = - channel ? channel->GetMedium() : Medium::UNKNOWN_MEDIUM; - if (channel == nullptr) { - NEARBY_LOGS(INFO) - << "Endpoint channel not available: endpoint_id=" << endpoint_id; - ProcessPreConnectionInitiationFailure( - client, channel_medium, endpoint_id, channel.get(), - /* is_incoming = */ false, start_time, connect_impl_result.status, - result.get()); - return; - } - - NEARBY_LOGS(INFO) - << "In requestConnection(), wrote ConnectionRequestFrame " - "to endpoint_id=" - << endpoint_id; - // Generate the nonce to use for this connection. - std::int32_t nonce = prng_.NextInt32(); - - // The first message we have to send, after connecting, is to tell the - // endpoint about ourselves. - Exception write_exception = WriteConnectionRequestFrame( - channel.get(), client->GetLocalEndpointId(), info.endpoint_info, - nonce, GetSupportedConnectionMediumsByPriority(options), - options.keep_alive_interval_millis, - options.keep_alive_timeout_millis); - if (!write_exception.Ok()) { - NEARBY_LOGS(INFO) << "Failed to send connection request: endpoint_id=" - << endpoint_id; - ProcessPreConnectionInitiationFailure( - client, channel_medium, endpoint_id, channel.get(), - /* is_incoming = */ false, start_time, {Status::kEndpointIoError}, - result.get()); - return; - } - - NEARBY_LOGS(INFO) << "Adding connection to pending set: endpoint_id=" - << endpoint_id; - - // We've successfully connected to the device, and are now about to jump - // on to the EncryptionRunner thread to start running our encryption - // protocol. We'll mark ourselves as pending in case we get another call - // to RequestConnection or OnIncomingConnection, so that we can cancel - // the connection if needed. - // Not using designated initializers here since the VS C++ compiler - // errors out indicating that MediumSelector<bool> is not an aggregate - PendingConnectionInfo pendingConnectionInfo{}; - pendingConnectionInfo.client = client; - pendingConnectionInfo.remote_endpoint_info = endpoint->endpoint_info; - pendingConnectionInfo.nonce = nonce; - pendingConnectionInfo.is_incoming = false; - pendingConnectionInfo.start_time = start_time; - pendingConnectionInfo.listener = info.listener; - pendingConnectionInfo.options = options; - pendingConnectionInfo.result = result; - pendingConnectionInfo.channel = std::move(channel); - - EndpointChannel* endpoint_channel = - pending_connections_ - .emplace(endpoint_id, std::move(pendingConnectionInfo)) - .first->second.channel.get(); - - NEARBY_LOGS(INFO) << "Initiating secure connection: endpoint_id=" - << endpoint_id; - // Next, we'll set up encryption. When it's done, our future will return - // and RequestConnection() will finish. - encryption_runner_.StartClient(client, endpoint_id, endpoint_channel, - GetResultListener()); - }); - NEARBY_LOGS(INFO) << "Waiting for connection to complete: endpoint_id=" - << endpoint_id; - auto status = - WaitForResult(absl::StrCat("RequestConnection(", endpoint_id, ")"), - client->GetClientId(), result.get()); - NEARBY_LOGS(INFO) << "Wait is complete: endpoint_id=" << endpoint_id - << "; status=" << status.value; - return status; -} - -bool BasePcpHandler::MediumSupportedByClientOptions( - const proto::connections::Medium& medium, - const ConnectionOptions& client_options) const { - for (auto supported_medium : client_options.GetMediums()) { - if (medium == supported_medium) { - return true; - } - } - return false; -} - -// Get ordered supported connection medium based on local advertising/discovery -// option. -std::vector<proto::connections::Medium> -BasePcpHandler::GetSupportedConnectionMediumsByPriority( - const ConnectionOptions& local_option) { - std::vector<proto::connections::Medium> supported_mediums_by_priority; - for (auto medium_by_priority : GetConnectionMediumsByPriority()) { - if (MediumSupportedByClientOptions(medium_by_priority, local_option)) { - supported_mediums_by_priority.push_back(medium_by_priority); - } - } - return supported_mediums_by_priority; -} - -// Get any single discovered endpoint for a given endpoint_id. -BasePcpHandler::DiscoveredEndpoint* BasePcpHandler::GetDiscoveredEndpoint( - const std::string& endpoint_id) { - auto it = discovered_endpoints_.find(endpoint_id); - if (it == discovered_endpoints_.end()) { - return nullptr; - } - return it->second.get(); -} - -std::vector<BasePcpHandler::DiscoveredEndpoint*> -BasePcpHandler::GetDiscoveredEndpoints(const std::string& endpoint_id) { - std::vector<BasePcpHandler::DiscoveredEndpoint*> result; - auto it = discovered_endpoints_.equal_range(endpoint_id); - for (auto item = it.first; item != it.second; item++) { - result.push_back(item->second.get()); - } - std::sort(result.begin(), result.end(), - [this](DiscoveredEndpoint* a, DiscoveredEndpoint* b) -> bool { - return IsPreferred(*a, *b); - }); - - return result; -} - -std::vector<BasePcpHandler::DiscoveredEndpoint*> -BasePcpHandler::GetDiscoveredEndpoints( - const proto::connections::Medium medium) { - std::vector<BasePcpHandler::DiscoveredEndpoint*> result; - for (const auto& item : discovered_endpoints_) { - if (item.second->medium == medium) { - result.push_back(item.second.get()); - } - } - return result; -} - -mediums::WebrtcPeerId BasePcpHandler::CreatePeerIdFromAdvertisement( - const std::string& service_id, const std::string& endpoint_id, - const ByteArray& endpoint_info) { - std::string seed = - absl::StrCat(service_id, endpoint_id, std::string(endpoint_info)); - return mediums::WebrtcPeerId::FromSeed(ByteArray(std::move(seed))); -} - -bool BasePcpHandler::HasOutgoingConnections(ClientProxy* client) const { - for (const auto& item : pending_connections_) { - auto& connection = item.second; - if (!connection.is_incoming) { - return true; - } - } - return client->GetNumOutgoingConnections() > 0; -} - -bool BasePcpHandler::HasIncomingConnections(ClientProxy* client) const { - for (const auto& item : pending_connections_) { - auto& connection = item.second; - if (connection.is_incoming) { - return true; - } - } - return client->GetNumIncomingConnections() > 0; -} - -bool BasePcpHandler::CanSendOutgoingConnection(ClientProxy* client) const { - return true; -} - -bool BasePcpHandler::CanReceiveIncomingConnection(ClientProxy* client) const { - return true; -} - -Exception BasePcpHandler::WriteConnectionRequestFrame( - EndpointChannel* endpoint_channel, const std::string& local_endpoint_id, - const ByteArray& local_endpoint_info, std::int32_t nonce, - const std::vector<proto::connections::Medium>& supported_mediums, - std::int32_t keep_alive_interval_millis, - std::int32_t keep_alive_timeout_millis) { - return endpoint_channel->Write(parser::ForConnectionRequest( - local_endpoint_id, local_endpoint_info, nonce, /*supports_5_ghz =*/false, - /*bssid=*/std::string{}, supported_mediums, keep_alive_interval_millis, - keep_alive_timeout_millis)); -} - -void BasePcpHandler::ProcessPreConnectionInitiationFailure( - ClientProxy* client, Medium medium, const std::string& endpoint_id, - EndpointChannel* channel, bool is_incoming, absl::Time start_time, - Status status, Future<Status>* result) { - if (channel != nullptr) { - channel->Close(); - } - - if (result != nullptr) { - NEARBY_LOGS(INFO) << "Connection failed; aborting future"; - result->Set(status); - } - - LogConnectionAttempt(client, medium, endpoint_id, is_incoming, start_time); - // result is hold inside a swapper, and saved in PendingConnectionInfo. - // PendingConnectionInfo destructor will clear the memory of SettableFuture - // shared_ptr for result. - pending_connections_.erase(endpoint_id); -} - -void BasePcpHandler::ProcessPreConnectionResultFailure( - ClientProxy* client, const std::string& endpoint_id) { - auto item = pending_connections_.extract(endpoint_id); - endpoint_manager_->DiscardEndpoint(client, endpoint_id); - client->OnConnectionRejected(endpoint_id, {Status::kError}); -} - -bool BasePcpHandler::ShouldEnforceTopologyConstraints( - const ConnectionOptions& local_advertising_options) const { - // Topology constraints only matter for the advertiser. - // For discoverers, we'll always enforce them. - if (local_advertising_options.strategy.IsNone()) { - return true; - } - - return local_advertising_options.enforce_topology_constraints; -} - -bool BasePcpHandler::AutoUpgradeBandwidth( - const ConnectionOptions& local_advertising_options) const { - if (local_advertising_options.strategy.IsNone()) { - return true; - } - - return local_advertising_options.auto_upgrade_bandwidth; -} - -Status BasePcpHandler::AcceptConnection( - ClientProxy* client, const std::string& endpoint_id, - const PayloadListener& payload_listener) { - Future<Status> response; - RunOnPcpHandlerThread( - "accept-connection", [this, client, endpoint_id, payload_listener, - &response]() RUN_ON_PCP_HANDLER_THREAD() { - NEARBY_LOGS(INFO) << "AcceptConnection: endpoint_id=" << endpoint_id; - if (!pending_connections_.count(endpoint_id)) { - NEARBY_LOGS(INFO) - << "AcceptConnection: no pending connection for endpoint_id=" - << endpoint_id; - - response.Set({Status::kEndpointUnknown}); - return; - } - auto& connection_info = pending_connections_[endpoint_id]; - - // By this point in the flow, connection_info.channel has been - // nulled out because ownership of that EndpointChannel was passed on to - // EndpointChannelManager via a call to - // EndpointManager::registerEndpoint(), so we now need to get access to - // the EndpointChannel from the authoritative owner. - std::shared_ptr<EndpointChannel> channel = - channel_manager_->GetChannelForEndpoint(endpoint_id); - if (channel == nullptr) { - NEARBY_LOGS(ERROR) << "Channel destroyed before Accept; bring down " - "connection: endpoint_id=" - << endpoint_id; - ProcessPreConnectionResultFailure(client, endpoint_id); - response.Set({Status::kEndpointUnknown}); - return; - } - - Exception write_exception = - channel->Write(parser::ForConnectionResponse(Status::kSuccess)); - if (!write_exception.Ok()) { - NEARBY_LOGS(INFO) - << "AcceptConnection: failed to send response: endpoint_id=" - << endpoint_id; - ProcessPreConnectionResultFailure(client, endpoint_id); - response.Set({Status::kEndpointIoError}); - return; - } - - NEARBY_LOGS(INFO) << "AcceptConnection: accepting locally: endpoint_id=" - << endpoint_id; - connection_info.LocalEndpointAcceptedConnection(endpoint_id, - payload_listener); - EvaluateConnectionResult(client, endpoint_id, - false /* can_close_immediately */); - response.Set({Status::kSuccess}); - }); - - return WaitForResult(absl::StrCat("AcceptConnection(", endpoint_id, ")"), - client->GetClientId(), &response); -} - -Status BasePcpHandler::RejectConnection(ClientProxy* client, - const std::string& endpoint_id) { - Future<Status> response; - RunOnPcpHandlerThread( - "reject-connection", - [this, client, endpoint_id, &response]() RUN_ON_PCP_HANDLER_THREAD() { - NEARBY_LOG(INFO, "RejectConnection: id=%s", endpoint_id.c_str()); - if (!pending_connections_.count(endpoint_id)) { - NEARBY_LOGS(INFO) - << "RejectConnection: no pending connection for endpoint_id=" - << endpoint_id; - response.Set({Status::kEndpointUnknown}); - return; - } - auto& connection_info = pending_connections_[endpoint_id]; - - // By this point in the flow, connection_info->endpoint_channel_ has - // been nulled out because ownership of that EndpointChannel was passed - // on to EndpointChannelManager via a call to - // EndpointManager::registerEndpoint(), so we now need to get access to - // the EndpointChannel from the authoritative owner. - std::shared_ptr<EndpointChannel> channel = - channel_manager_->GetChannelForEndpoint(endpoint_id); - if (channel == nullptr) { - NEARBY_LOGS(ERROR) - << "Channel destroyed before Reject; bring down connection: " - "endpoint_id=" - << endpoint_id; - ProcessPreConnectionResultFailure(client, endpoint_id); - response.Set({Status::kEndpointUnknown}); - return; - } - - Exception write_exception = channel->Write( - parser::ForConnectionResponse(Status::kConnectionRejected)); - if (!write_exception.Ok()) { - NEARBY_LOGS(INFO) - << "RejectConnection: failed to send response: endpoint_id=" - << endpoint_id; - ProcessPreConnectionResultFailure(client, endpoint_id); - response.Set({Status::kEndpointIoError}); - return; - } - - NEARBY_LOGS(INFO) << "RejectConnection: rejecting locally: endpoint_id=" - << endpoint_id; - connection_info.LocalEndpointRejectedConnection(endpoint_id); - EvaluateConnectionResult(client, endpoint_id, - false /* can_close_immediately */); - response.Set({Status::kSuccess}); - }); - - return WaitForResult(absl::StrCat("RejectConnection(", endpoint_id, ")"), - client->GetClientId(), &response); -} - -void BasePcpHandler::OnIncomingFrame(OfflineFrame& frame, - const std::string& endpoint_id, - ClientProxy* client, - proto::connections::Medium medium) { - CountDownLatch latch(1); - RunOnPcpHandlerThread( - "incoming-frame", - [this, client, endpoint_id, frame, &latch]() RUN_ON_PCP_HANDLER_THREAD() { - NEARBY_LOGS(INFO) << "OnConnectionResponse: endpoint_id=" - << endpoint_id; - - if (client->HasRemoteEndpointResponded(endpoint_id)) { - NEARBY_LOGS(INFO) - << "OnConnectionResponse: already handled; endpoint_id=" - << endpoint_id; - return; - } - - const ConnectionResponseFrame& connection_response = - frame.v1().connection_response(); - - // For backward compatible, here still check both status and - // response parameters until the response feature is roll out in all - // supported devices. - bool accepted = false; - if (connection_response.has_response()) { - accepted = - connection_response.response() == ConnectionResponseFrame::ACCEPT; - } else { - accepted = connection_response.status() == Status::kSuccess; - } - if (accepted) { - NEARBY_LOGS(INFO) - << "OnConnectionResponse: remote accepted; endpoint_id=" - << endpoint_id; - client->RemoteEndpointAcceptedConnection(endpoint_id); - } else { - NEARBY_LOGS(INFO) - << "OnConnectionResponse: remote rejected; endpoint_id=" - << endpoint_id << "; status=" << connection_response.status(); - client->RemoteEndpointRejectedConnection(endpoint_id); - } - - EvaluateConnectionResult(client, endpoint_id, - /* can_close_immediately= */ true); - - latch.CountDown(); - }); - WaitForLatch("OnIncomingFrame()", &latch); -} - -void BasePcpHandler::OnEndpointDisconnect(ClientProxy* client, - const std::string& endpoint_id, - CountDownLatch barrier) { - if (stop_.Get()) { - barrier.CountDown(); - return; - } - RunOnPcpHandlerThread("on-endpoint-disconnect", - [this, client, endpoint_id, barrier]() - RUN_ON_PCP_HANDLER_THREAD() mutable { - auto item = pending_alarms_.find(endpoint_id); - if (item != pending_alarms_.end()) { - auto& alarm = item->second; - alarm.Cancel(); - pending_alarms_.erase(item); - } - ProcessPreConnectionResultFailure(client, - endpoint_id); - barrier.CountDown(); - }); -} - -BluetoothDevice BasePcpHandler::GetRemoteBluetoothDevice( - const std::string& remote_bluetooth_mac_address) { - return mediums_->GetBluetoothClassic().GetRemoteDevice( - remote_bluetooth_mac_address); -} - -void BasePcpHandler::OnEndpointFound( - ClientProxy* client, std::shared_ptr<DiscoveredEndpoint> endpoint) { - // Check if we've seen this endpoint ID before. - std::string& endpoint_id = endpoint->endpoint_id; - NEARBY_LOGS(INFO) << "OnEndpointFound: id=" << endpoint_id << " [enter]"; - - auto range = discovered_endpoints_.equal_range(endpoint->endpoint_id); - - DiscoveredEndpoint* owned_endpoint = nullptr; - for (auto& item = range.first; item != range.second; ++item) { - auto& discovered_endpoint = item->second; - if (discovered_endpoint->medium != endpoint->medium) continue; - // Check if there was a info change. If there was, report the previous - // endpoint as lost. - if (discovered_endpoint->endpoint_info != endpoint->endpoint_info) { - OnEndpointLost(client, *discovered_endpoint); - discovered_endpoint = endpoint; // Replace endpoint. - OnEndpointFound(client, std::move(endpoint)); - return; - } else { - owned_endpoint = endpoint.get(); - break; - } - } - - if (!owned_endpoint) { - owned_endpoint = - discovered_endpoints_.emplace(endpoint_id, std::move(endpoint)) - ->second.get(); - } - - // Range is empty: this is the first endpoint we discovered so far. - // Report this endpoint_id to client. - if (range.first == range.second) { - NEARBY_LOGS(INFO) << "Adding new endpoint: endpoint_id=" << endpoint_id; - // And, as it's the first time, report it to the client. - client->OnEndpointFound( - owned_endpoint->service_id, owned_endpoint->endpoint_id, - owned_endpoint->endpoint_info, owned_endpoint->medium); - } else { - NEARBY_LOGS(INFO) << "Adding new medium for endpoint: endpoint_id=" - << endpoint_id << "; medium=" << owned_endpoint->medium; - } -} - -void BasePcpHandler::OnEndpointLost( - ClientProxy* client, const BasePcpHandler::DiscoveredEndpoint& endpoint) { - // Look up the DiscoveredEndpoint we have in our cache. - const auto* discovered_endpoint = GetDiscoveredEndpoint(endpoint.endpoint_id); - if (discovered_endpoint == nullptr) { - NEARBY_LOGS(INFO) << "No previous endpoint (nothing to lose): endpoint_id=" - << endpoint.endpoint_id; - return; - } - - // Validate that the cached endpoint has the same info as the one reported as - // onLost. If the info differs, then no-op. This likely means that the remote - // device changed their info. We reported onFound for the new info and are - // just now figuring out that we lost the old info. - if (discovered_endpoint->endpoint_info != endpoint.endpoint_info) { - NEARBY_LOGS(INFO) << "Previous endpoint name mismatch; passed=" - << absl::BytesToHexString(endpoint.endpoint_info.data()) - << "; expected=" - << absl::BytesToHexString( - discovered_endpoint->endpoint_info.data()); - return; - } - - auto item = discovered_endpoints_.extract(endpoint.endpoint_id); - if (!discovered_endpoints_.count(endpoint.endpoint_id)) { - client->OnEndpointLost(endpoint.service_id, endpoint.endpoint_id); - } -} - -bool BasePcpHandler::IsPreferred( - const BasePcpHandler::DiscoveredEndpoint& new_endpoint, - const BasePcpHandler::DiscoveredEndpoint& old_endpoint) { - std::vector<proto::connections::Medium> mediums = - GetConnectionMediumsByPriority(); - // As we iterate through the list of mediums, we see if we run into the new - // endpoint's medium or the old endpoint's medium first. - for (const auto& medium : mediums) { - if (medium == new_endpoint.medium) { - // The new endpoint's medium came first. It's preferred! - return true; - } - - if (medium == old_endpoint.medium) { - // The old endpoint's medium came first. Stick with the old endpoint! - return false; - } - } - std::string medium_string; - for (const auto& medium : mediums) { - absl::StrAppend(&medium_string, medium, "; "); - } - NEARBY_LOGS(ERROR) << "Failed to find either " << new_endpoint.medium - << " or " << old_endpoint.medium - << " in the list of locally supported mediums despite " - "expecting to find both, when deciding which medium " - << medium_string << " is preferred."; - return false; -} - -Exception BasePcpHandler::OnIncomingConnection( - ClientProxy* client, const ByteArray& remote_endpoint_info, - std::unique_ptr<EndpointChannel> channel, - proto::connections::Medium medium) { - absl::Time start_time = SystemClock::ElapsedRealtime(); - - // Fixes an NPE in ClientProxy.OnConnectionAccepted. The crash happened when - // the client stopped advertising and we nulled out state, followed by an - // incoming connection where we attempted to check that state. - if (!client->IsAdvertising()) { - NEARBY_LOGS(WARNING) << "Ignoring incoming connection on medium " - << proto::connections::Medium_Name( - channel->GetMedium()) - << " because client=" << client->GetClientId() - << " is no longer advertising."; - return {Exception::kIo}; - } - - // Endpoints connecting to us will always tell us about themselves first. - ExceptionOr<OfflineFrame> wrapped_frame = - ReadConnectionRequestFrame(channel.get()); - - if (!wrapped_frame.ok()) { - if (wrapped_frame.exception()) { - NEARBY_LOGS(ERROR) - << "Failed to parse incoming connection request; client=" - << client->GetClientId() - << "; device=" << absl::BytesToHexString(remote_endpoint_info.data()); - ProcessPreConnectionInitiationFailure(client, medium, "", channel.get(), - /* is_incoming= */ false, - start_time, {Status::kError}, - nullptr); - return {Exception::kSuccess}; - } - return wrapped_frame.GetException(); - } - - OfflineFrame& frame = wrapped_frame.result(); - const ConnectionRequestFrame& connection_request = - frame.v1().connection_request(); - NEARBY_LOGS(INFO) << "In onIncomingConnection(" - << proto::connections::Medium_Name(channel->GetMedium()) - << ") for client=" << client->GetClientId() - << ", read ConnectionRequestFrame from endpoint(id=" - << connection_request.endpoint_id() << ")"; - if (client->IsConnectedToEndpoint(connection_request.endpoint_id())) { - NEARBY_LOGS(ERROR) << "Incoming connection on medium " - << proto::connections::Medium_Name(channel->GetMedium()) - << " was denied because we're " - "already connected to endpoint(id=" - << connection_request.endpoint_id() << ")."; - return {Exception::kIo}; - } - - // If we've already sent out a connection request to this endpoint, then this - // is where we need to decide which connection to break. - if (BreakTie(client, connection_request.endpoint_id(), - connection_request.nonce(), channel.get())) { - return {Exception::kSuccess}; - } - - // If our child class says we can't accept any more incoming connections, - // listen to them. - if (ShouldEnforceTopologyConstraints(client->GetAdvertisingOptions()) && - !CanReceiveIncomingConnection(client)) { - NEARBY_LOGS(ERROR) << "Incoming connections are currently disallowed."; - return {Exception::kIo}; - } - - // The ConnectionRequest frame has two fields that both contain the - // EndpointInfo. The legacy field stores it as a string while the newer field - // stores it as a byte array. We'll attempt to grab from the newer field, but - // will accept the older string if it's all that exists. - const ByteArray endpoint_info{connection_request.has_endpoint_info() - ? connection_request.endpoint_info() - : connection_request.endpoint_name()}; - - // Retrieve the keep-alive frame interval and timeout fields. If the frame - // doesn't have those fields, we need to get them as default from feature - // flags to prevent 0-values causing thread ill. - ConnectionOptions options = {.keep_alive_interval_millis = 0, - .keep_alive_timeout_millis = 0}; - if (connection_request.has_keep_alive_interval_millis() && - connection_request.has_keep_alive_timeout_millis()) { - options.keep_alive_interval_millis = - connection_request.keep_alive_interval_millis(); - options.keep_alive_timeout_millis = - connection_request.keep_alive_timeout_millis(); - } - if (options.keep_alive_interval_millis == 0 || - options.keep_alive_timeout_millis == 0 || - options.keep_alive_interval_millis >= options.keep_alive_timeout_millis) { - NEARBY_LOGS(WARNING) - << "Incoming connection has wrong keep-alive frame interval=" - << options.keep_alive_interval_millis - << ", timeout=" << options.keep_alive_timeout_millis - << " values; correct them as default.", - options.keep_alive_interval_millis = - FeatureFlags::GetInstance().GetFlags().keep_alive_interval_millis; - options.keep_alive_timeout_millis = - FeatureFlags::GetInstance().GetFlags().keep_alive_timeout_millis; - } - - // We've successfully connected to the device, and are now about to jump on to - // the EncryptionRunner thread to start running our encryption protocol. We'll - // mark ourselves as pending in case we get another call to RequestConnection - // or OnIncomingConnection, so that we can cancel the connection if needed. - // Not using designated initializers here since the VS C++ compiler errors - // out indicating that MediumSelector<bool> is not an aggregate - PendingConnectionInfo pendingConnectionInfo{}; - pendingConnectionInfo.client = client; - pendingConnectionInfo.remote_endpoint_info = endpoint_info; - pendingConnectionInfo.nonce = connection_request.nonce(); - pendingConnectionInfo.is_incoming = true; - pendingConnectionInfo.start_time = start_time; - pendingConnectionInfo.listener = advertising_listener_; - pendingConnectionInfo.options = options; - pendingConnectionInfo.supported_mediums = - parser::ConnectionRequestMediumsToMediums(connection_request); - pendingConnectionInfo.channel = std::move(channel); - - auto* owned_channel = pending_connections_ - .emplace(connection_request.endpoint_id(), - std::move(pendingConnectionInfo)) - .first->second.channel.get(); - - // Next, we'll set up encryption. - encryption_runner_.StartServer(client, connection_request.endpoint_id(), - owned_channel, GetResultListener()); - return {Exception::kSuccess}; -} - -bool BasePcpHandler::BreakTie(ClientProxy* client, - const std::string& endpoint_id, - std::int32_t incoming_nonce, - EndpointChannel* endpoint_channel) { - auto it = pending_connections_.find(endpoint_id); - if (it != pending_connections_.end()) { - BasePcpHandler::PendingConnectionInfo& info = it->second; - - NEARBY_LOGS(INFO) - << "In onIncomingConnection(" - << proto::connections::Medium_Name(endpoint_channel->GetMedium()) - << ") for client=" << client->GetClientId() - << ", found a collision with endpoint " << endpoint_id - << ". We've already sent a connection request to them with nonce " - << info.nonce - << ", but they're also trying to connect to us with nonce " - << incoming_nonce; - // Break the lowest connection. In the (extremely) rare case of a tie, break - // both. - if (info.nonce > incoming_nonce) { - // Our connection won! Clean up their connection. - endpoint_channel->Close(); - - NEARBY_LOGS(INFO) << "In onIncomingConnection(" - << proto::connections::Medium_Name( - endpoint_channel->GetMedium()) - << ") for client=" << client->GetClientId() - << ", cleaned up the collision with endpoint " - << endpoint_id << " by closing their channel."; - return true; - } else if (info.nonce < incoming_nonce) { - // Aw, we lost. Clean up our connection, and then we'll let their - // connection continue on. - ProcessTieBreakLoss(client, endpoint_id, &info); - NEARBY_LOGS(INFO) - << "In onIncomingConnection(" - << proto::connections::Medium_Name(endpoint_channel->GetMedium()) - << ") for client=" << client->GetClientId() - << ", cleaned up the collision with endpoint " << endpoint_id - << " by closing our channel and notifying our client of the failure."; - } else { - // Oh. Huh. We both lost. Well, that's awkward. We'll clean up both and - // just force the devices to retry. - endpoint_channel->Close(); - - ProcessTieBreakLoss(client, endpoint_id, &info); - - NEARBY_LOGS(INFO) - << "In onIncomingConnection(" - << proto::connections::Medium_Name(endpoint_channel->GetMedium()) - << ") for client=" << client->GetClientId() - << ", cleaned up the collision with endpoint " << endpoint_id - << " by closing both channels. Our nonces were identical, so we " - "couldn't decide which channel to use."; - return true; - } - } - - return false; -} - -void BasePcpHandler::ProcessTieBreakLoss( - ClientProxy* client, const std::string& endpoint_id, - BasePcpHandler::PendingConnectionInfo* info) { - ProcessPreConnectionInitiationFailure( - client, info->channel->GetMedium(), endpoint_id, info->channel.get(), - info->is_incoming, info->start_time, {Status::kEndpointIoError}, - info->result.lock().get()); - ProcessPreConnectionResultFailure(client, endpoint_id); -} - -bool BasePcpHandler::AppendRemoteBluetoothMacAddressEndpoint( - const std::string& endpoint_id, - const std::string& remote_bluetooth_mac_address, - const ConnectionOptions& local_discovery_options) { - if (!local_discovery_options.allowed.bluetooth) { - return false; - } - - auto it = discovered_endpoints_.equal_range(endpoint_id); - if (it.first == it.second) { - return false; - } - auto endpoint = it.first->second.get(); - for (auto item = it.first; item != it.second; item++) { - if (item->second->medium == proto::connections::Medium::BLUETOOTH) { - NEARBY_LOGS(INFO) - << "Cannot append remote Bluetooth MAC Address endpoint, because " - "the endpoint has already been found over Bluetooth [" - << remote_bluetooth_mac_address << "]"; - return false; - } - } - - auto remote_bluetooth_device = - GetRemoteBluetoothDevice(remote_bluetooth_mac_address); - if (!remote_bluetooth_device.IsValid()) { - NEARBY_LOGS(INFO) - << "Cannot append remote Bluetooth MAC Address endpoint, because a " - "valid Bluetooth device could not be derived [" - << remote_bluetooth_mac_address << "]"; - return false; - } - - auto bluetooth_endpoint = - std::make_shared<BluetoothEndpoint>(BluetoothEndpoint{ - {endpoint_id, endpoint->endpoint_info, endpoint->service_id, - proto::connections::Medium::BLUETOOTH, WebRtcState::kUnconnectable}, - remote_bluetooth_device, - }); - - discovered_endpoints_.emplace(endpoint_id, std::move(bluetooth_endpoint)); - return true; -} - -bool BasePcpHandler::AppendWebRTCEndpoint( - const std::string& endpoint_id, - const ConnectionOptions& local_discovery_options) { - if (!local_discovery_options.allowed.web_rtc) { - return false; - } - - bool should_connect_web_rtc = false; - auto it = discovered_endpoints_.equal_range(endpoint_id); - if (it.first == it.second) return false; - auto endpoint = it.first->second.get(); - for (auto item = it.first; item != it.second; item++) { - if (item->second->web_rtc_state != WebRtcState::kUnconnectable) { - should_connect_web_rtc = true; - break; - } - } - if (!should_connect_web_rtc) return false; - - auto webrtc_endpoint = std::make_shared<WebRtcEndpoint>(WebRtcEndpoint{ - {endpoint_id, endpoint->endpoint_info, endpoint->service_id, - proto::connections::Medium::WEB_RTC, WebRtcState::kConnectable}, - CreatePeerIdFromAdvertisement(endpoint->service_id, endpoint->endpoint_id, - endpoint->endpoint_info), - }); - - discovered_endpoints_.emplace(endpoint_id, std::move(webrtc_endpoint)); - return true; -} - -void BasePcpHandler::EvaluateConnectionResult(ClientProxy* client, - const std::string& endpoint_id, - bool can_close_immediately) { - // Short-circuit immediately if we're not in an actionable state yet. We will - // be called again once the other side has made their decision. - if (!client->IsConnectionAccepted(endpoint_id) && - !client->IsConnectionRejected(endpoint_id)) { - if (!client->HasLocalEndpointResponded(endpoint_id)) { - NEARBY_LOGS(INFO) - << "ConnectionResult: local client did not respond; endpoint_id=" - << endpoint_id; - } else if (!client->HasRemoteEndpointResponded(endpoint_id)) { - NEARBY_LOGS(INFO) - << "ConnectionResult: remote client did not respond; endpoint_id=" - << endpoint_id; - } - return; - } - - // Clean up the endpoint channel from our list of 'pending' connections. It's - // no longer pending. - auto it = pending_connections_.find(endpoint_id); - if (it == pending_connections_.end()) { - NEARBY_LOGS(INFO) << "No pending connection to evaluate; endpoint_id=" - << endpoint_id; - return; - } - - auto pair = pending_connections_.extract(it); - BasePcpHandler::PendingConnectionInfo& connection_info = pair.mapped(); - bool is_connection_accepted = client->IsConnectionAccepted(endpoint_id); - - Status response_code; - if (is_connection_accepted) { - NEARBY_LOGS(INFO) << "Pending connection accepted; endpoint_id=" - << endpoint_id; - response_code = {Status::kSuccess}; - - // Both sides have accepted, so we can now start talking over encrypted - // channels - // Now, after both parties accepted connection (presumably after verifying & - // matching security tokens), we are allowed to extract the shared key. - auto ukey2 = std::move(connection_info.ukey2); - bool succeeded = ukey2->VerifyHandshake(); - CHECK(succeeded); // If this fails, it's a UKEY2 protocol bug. - auto context = ukey2->ToConnectionContext(); - CHECK(context); // there is no way how this can fail, if Verify succeeded. - // If it did, it's a UKEY2 protocol bug. - - channel_manager_->EncryptChannelForEndpoint(endpoint_id, - std::move(context)); - - client->GetAnalyticsRecorder().OnConnectionEstablished( - endpoint_id, - channel_manager_->GetChannelForEndpoint(endpoint_id)->GetMedium(), - connection_info.connection_token); - } else { - NEARBY_LOGS(INFO) << "Pending connection rejected; endpoint_id=" - << endpoint_id; - response_code = {Status::kConnectionRejected}; - } - - // Invoke the client callback to let it know of the connection result. - if (response_code.Ok()) { - client->OnConnectionAccepted(endpoint_id); - } else { - client->OnConnectionRejected(endpoint_id, response_code); - } - - // If the connection failed, clean everything up and short circuit. - if (!is_connection_accepted) { - // Clean up the channel in EndpointManager if it's no longer required. - if (can_close_immediately) { - endpoint_manager_->DiscardEndpoint(client, endpoint_id); - } else { - pending_alarms_.emplace( - endpoint_id, - CancelableAlarm( - "BasePcpHandler.evaluateConnectionResult() delayed close", - [this, client, endpoint_id]() { - endpoint_manager_->DiscardEndpoint(client, endpoint_id); - }, - kRejectedConnectionCloseDelay, &alarm_executor_)); - } - - return; - } - - // Kick off the bandwidth upgrade for incoming connections. - if (connection_info.is_incoming && - AutoUpgradeBandwidth(client->GetAdvertisingOptions())) { - bwu_manager_->InitiateBwuForEndpoint(client, endpoint_id); - } -} - -ExceptionOr<OfflineFrame> BasePcpHandler::ReadConnectionRequestFrame( - EndpointChannel* endpoint_channel) { - if (endpoint_channel == nullptr) { - return ExceptionOr<OfflineFrame>(Exception::kIo); - } - - // To avoid a device connecting but never sending their introductory frame, we - // time out the connection after a certain amount of time. - CancelableAlarm timeout_alarm( - absl::StrCat("PcpHandler(", this->GetStrategy().GetName(), - ")::ReadConnectionRequestFrame"), - [endpoint_channel]() { endpoint_channel->Close(); }, - kConnectionRequestReadTimeout, &alarm_executor_); - // Do a blocking read to try and find the ConnectionRequestFrame - ExceptionOr<ByteArray> wrapped_bytes = endpoint_channel->Read(); - timeout_alarm.Cancel(); - - if (!wrapped_bytes.ok()) { - return ExceptionOr<OfflineFrame>(wrapped_bytes.exception()); - } - - ByteArray bytes = std::move(wrapped_bytes.result()); - ExceptionOr<OfflineFrame> wrapped_frame = parser::FromBytes(bytes); - if (wrapped_frame.GetException().Raised(Exception::kInvalidProtocolBuffer)) { - return ExceptionOr<OfflineFrame>(Exception::kIo); - } - - OfflineFrame& frame = wrapped_frame.result(); - if (V1Frame::CONNECTION_REQUEST != parser::GetFrameType(frame)) { - return ExceptionOr<OfflineFrame>(Exception::kIo); - } - - return wrapped_frame; -} - -std::string BasePcpHandler::GetHashedConnectionToken( - const ByteArray& token_bytes) { - auto token = std::string(token_bytes); - return location::nearby::Base64Utils::Encode( - Utils::Sha256Hash(token, token.size())) - .substr(0, kConnectionTokenLength); -} - -void BasePcpHandler::LogConnectionAttempt(ClientProxy* client, Medium medium, - const std::string& endpoint_id, - bool is_incoming, - absl::Time start_time) { - proto::connections::ConnectionAttemptResult result = - Cancelled(client, endpoint_id) ? proto::connections::RESULT_CANCELLED - : proto::connections::RESULT_ERROR; - if (is_incoming) { - client->GetAnalyticsRecorder().OnIncomingConnectionAttempt( - proto::connections::INITIAL, medium, result, - SystemClock::ElapsedRealtime() - start_time, - /* connection_token= */ ""); - } else { - client->GetAnalyticsRecorder().OnOutgoingConnectionAttempt( - endpoint_id, proto::connections::INITIAL, medium, result, - SystemClock::ElapsedRealtime() - start_time, - /* connection_token= */ ""); - } -} - -bool BasePcpHandler::Cancelled(ClientProxy* client, - const std::string& endpoint_id) { - if (endpoint_id.empty()) { - return false; - } - - return client->GetCancellationFlag(endpoint_id)->Cancelled(); -} - -///////////////////// BasePcpHandler::PendingConnectionInfo /////////////////// - -void BasePcpHandler::PendingConnectionInfo::SetCryptoContext( - std::unique_ptr<UKey2Handshake> ukey2) { - this->ukey2 = std::move(ukey2); -} - -BasePcpHandler::PendingConnectionInfo::~PendingConnectionInfo() { - auto future_status = result.lock(); - if (future_status && !future_status->IsSet()) { - NEARBY_LOG(INFO, "Future was not set; destroying info"); - future_status->Set({Status::kError}); - } - - if (channel != nullptr) { - channel->Close(proto::connections::DisconnectionReason::SHUTDOWN); - } - - // Destroy crypto context now; for some reason, crypto context destructor - // segfaults if it is not destroyed here. - this->ukey2.reset(); -} - -void BasePcpHandler::PendingConnectionInfo::LocalEndpointAcceptedConnection( - const std::string& endpoint_id, const PayloadListener& payload_listener) { - client->LocalEndpointAcceptedConnection(endpoint_id, payload_listener); -} - -void BasePcpHandler::PendingConnectionInfo::LocalEndpointRejectedConnection( - const std::string& endpoint_id) { - client->LocalEndpointRejectedConnection(endpoint_id); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/base_pcp_handler.h b/chromium/third_party/nearby/src/cpp/core/internal/base_pcp_handler.h deleted file mode 100644 index 896d03c4bb2..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/base_pcp_handler.h +++ /dev/null @@ -1,524 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_BASE_PCP_HANDLER_H_ -#define CORE_INTERNAL_BASE_PCP_HANDLER_H_ - -#include <cstdint> -#include <memory> -#include <string> -#include <vector> - -#include "securegcm/d2d_connection_context_v1.h" -#include "securegcm/ukey2_handshake.h" -#include "absl/container/btree_map.h" -#include "absl/container/flat_hash_map.h" -#include "absl/time/time.h" -#include "core/internal/bwu_manager.h" -#include "core/internal/client_proxy.h" -#include "core/internal/encryption_runner.h" -#include "core/internal/endpoint_channel_manager.h" -#include "core/internal/endpoint_manager.h" -#include "core/internal/mediums/mediums.h" -#include "core/internal/mediums/webrtc.h" -#include "core/internal/pcp.h" -#include "core/internal/pcp_handler.h" -#include "core/listeners.h" -#include "core/options.h" -#include "core/status.h" -#include "platform/base/byte_array.h" -#include "platform/base/prng.h" -#include "platform/public/atomic_boolean.h" -#include "platform/public/atomic_reference.h" -#include "platform/public/cancelable_alarm.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/future.h" -#include "platform/public/scheduled_executor.h" -#include "platform/public/single_thread_executor.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { - -// Represents the WebRtc state that mediums are connectable or not. -enum class WebRtcState { - kUndefined = 0, - kConnectable = 1, - kUnconnectable = 2, -}; - -// Annotations for methods that need to run on PCP handler thread. -// Use only in BasePcpHandler and derived classes. -#define RUN_ON_PCP_HANDLER_THREAD() \ - ABSL_EXCLUSIVE_LOCKS_REQUIRED(GetPcpHandlerThread()) - -// A base implementation of the PcpHandler interface that takes care of all -// bookkeeping and handshake protocols that are common across all PcpHandler -// implementations -- thus, every concrete PcpHandler implementation must extend -// this class, so that they can focus exclusively on the medium-specific -// operations. -class BasePcpHandler : public PcpHandler, - public EndpointManager::FrameProcessor { - public: - using FrameProcessor = EndpointManager::FrameProcessor; - - // TODO(apolyudov): Add SecureRandom. - BasePcpHandler(Mediums* mediums, EndpointManager* endpoint_manager, - EndpointChannelManager* channel_manager, - BwuManager* bwu_manager, Pcp pcp); - ~BasePcpHandler() override; - BasePcpHandler(BasePcpHandler&&) = delete; - BasePcpHandler& operator=(BasePcpHandler&&) = delete; - - // Starts advertising. Once successfully started, changes ClientProxy's state. - // Notifies ConnectionListener (info.listener) in case of any event. - // See - // cpp/core/listeners.h - Status StartAdvertising(ClientProxy* client, const std::string& service_id, - const ConnectionOptions& options, - const ConnectionRequestInfo& info) override; - - // Stops Advertising is active, and changes CLientProxy state, - // otherwise does nothing. - void StopAdvertising(ClientProxy* client) override; - - // Starts discovery of endpoints that may be advertising. - // Updates ClientProxy state once discovery started. - // DiscoveryListener will get called in case of any event. - Status StartDiscovery(ClientProxy* client, const std::string& service_id, - const ConnectionOptions& options, - const DiscoveryListener& listener) override; - - // Stops Discovery if it is active, and changes CLientProxy state, - // otherwise does nothing. - void StopDiscovery(ClientProxy* client) override; - - void InjectEndpoint(ClientProxy* client, const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) override; - - // Requests a newly discovered remote endpoint it to form a connection. - // Updates state on ClientProxy. - Status RequestConnection(ClientProxy* client, const std::string& endpoint_id, - const ConnectionRequestInfo& info, - const ConnectionOptions& options) override; - - // Called by either party to accept connection on their part. - // Until both parties call it, connection will not reach a data phase. - // Updates state in ClientProxy. - Status AcceptConnection(ClientProxy* client, const std::string& endpoint_id, - const PayloadListener& payload_listener) override; - - // Called by either party to reject connection on their part. - // If either party does call it, connection will terminate. - // Updates state in ClientProxy. - Status RejectConnection(ClientProxy* client, - const std::string& endpoint_id) override; - - // @EndpointManagerReaderThread - void OnIncomingFrame(OfflineFrame& frame, const std::string& endpoint_id, - ClientProxy* client, - proto::connections::Medium medium) override; - - // Called when an endpoint disconnects while we're waiting for both sides to - // approve/reject the connection. - // @EndpointManagerThread - void OnEndpointDisconnect(ClientProxy* client, const std::string& endpoint_id, - CountDownLatch barrier) override; - - Pcp GetPcp() const override { return pcp_; } - Strategy GetStrategy() const override { return strategy_; } - void DisconnectFromEndpointManager(); - - protected: - // The result of a call to startAdvertisingImpl() or startDiscoveryImpl(). - struct StartOperationResult { - Status status; - // If success, the mediums on which we are now advertising/discovering, for - // analytics. - std::vector<proto::connections::Medium> mediums; - }; - - // Represents an endpoint that we've discovered. Typically, the implementation - // will know how to connect to this endpoint if asked. (eg. It holds on to a - // BluetoothDevice) - // - // NOTE(DiscoveredEndpoint): - // Specific protocol is expected to derive from it, as follows: - // struct ProtocolEndpoint : public DiscoveredEndpoint { - // ProtocolContext context; - // }; - // Protocol then allocates instance with std::make_shared<ProtocolEndpoint>(), - // and passes this instance to OnEndpointFound() method. - // When calling OnEndpointLost(), protocol does not need to pass the same - // instance (but it can if implementation desires to do so). - // BasePcpHandler will hold on to the shared_ptr<DiscoveredEndpoint>. - struct DiscoveredEndpoint { - DiscoveredEndpoint(std::string endpoint_id, ByteArray endpoint_info, - std::string service_id, - proto::connections::Medium medium, - WebRtcState web_rtc_state) - : endpoint_id(std::move(endpoint_id)), - endpoint_info(std::move(endpoint_info)), - service_id(std::move(service_id)), - medium(medium), - web_rtc_state(web_rtc_state) {} - virtual ~DiscoveredEndpoint() = default; - - std::string endpoint_id; - ByteArray endpoint_info; - std::string service_id; - proto::connections::Medium medium; - WebRtcState web_rtc_state; - }; - - struct BluetoothEndpoint : public DiscoveredEndpoint { - BluetoothEndpoint(DiscoveredEndpoint endpoint, BluetoothDevice device) - : DiscoveredEndpoint(std::move(endpoint)), - bluetooth_device(std::move(device)) {} - - BluetoothDevice bluetooth_device; - }; - - struct BleEndpoint : public BasePcpHandler::DiscoveredEndpoint { - BleEndpoint(DiscoveredEndpoint endpoint, BlePeripheral peripheral) - : DiscoveredEndpoint(std::move(endpoint)), - ble_peripheral(std::move(peripheral)) {} - BlePeripheral ble_peripheral; - }; - - struct WifiLanEndpoint : public DiscoveredEndpoint { - WifiLanEndpoint(DiscoveredEndpoint endpoint, - const NsdServiceInfo& service_info) - : DiscoveredEndpoint(std::move(endpoint)), service_info(service_info) {} - - NsdServiceInfo service_info; - }; - - struct WebRtcEndpoint : public DiscoveredEndpoint { - WebRtcEndpoint(DiscoveredEndpoint endpoint, mediums::WebrtcPeerId peer_id) - : DiscoveredEndpoint(std::move(endpoint)), - peer_id(std::move(peer_id)) {} - - mediums::WebrtcPeerId peer_id; - }; - - struct ConnectImplResult { - proto::connections::Medium medium = - proto::connections::Medium::UNKNOWN_MEDIUM; - Status status = {Status::kError}; - std::unique_ptr<EndpointChannel> endpoint_channel; - }; - - void RunOnPcpHandlerThread(const std::string& name, Runnable runnable); - - BluetoothDevice GetRemoteBluetoothDevice( - const std::string& remote_bluetooth_mac_address); - - ConnectionOptions GetConnectionOptions() const; - ConnectionOptions GetDiscoveryOptions() const; - - void OnEndpointFound(ClientProxy* client, - std::shared_ptr<DiscoveredEndpoint> endpoint) - RUN_ON_PCP_HANDLER_THREAD(); - - void OnEndpointLost(ClientProxy* client, const DiscoveredEndpoint& endpoint) - RUN_ON_PCP_HANDLER_THREAD(); - - Exception OnIncomingConnection( - ClientProxy* client, const ByteArray& remote_endpoint_info, - std::unique_ptr<EndpointChannel> endpoint_channel, - proto::connections::Medium medium); // throws Exception::IO - - virtual bool HasOutgoingConnections(ClientProxy* client) const; - virtual bool HasIncomingConnections(ClientProxy* client) const; - - virtual bool CanSendOutgoingConnection(ClientProxy* client) const; - virtual bool CanReceiveIncomingConnection(ClientProxy* client) const; - - virtual StartOperationResult StartAdvertisingImpl( - ClientProxy* client, const std::string& service_id, - const std::string& local_endpoint_id, - const ByteArray& local_endpoint_info, const ConnectionOptions& options) - RUN_ON_PCP_HANDLER_THREAD() = 0; - - virtual Status StopAdvertisingImpl(ClientProxy* client) - RUN_ON_PCP_HANDLER_THREAD() = 0; - - virtual StartOperationResult StartDiscoveryImpl( - ClientProxy* client, const std::string& service_id, - const ConnectionOptions& options) RUN_ON_PCP_HANDLER_THREAD() = 0; - - virtual Status StopDiscoveryImpl(ClientProxy* client) - RUN_ON_PCP_HANDLER_THREAD() = 0; - - virtual Status InjectEndpointImpl(ClientProxy* client, - const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) - RUN_ON_PCP_HANDLER_THREAD() = 0; - - virtual ConnectImplResult ConnectImpl(ClientProxy* client, - DiscoveredEndpoint* endpoint) - RUN_ON_PCP_HANDLER_THREAD() = 0; - - virtual std::vector<proto::connections::Medium> - GetConnectionMediumsByPriority() = 0; - virtual proto::connections::Medium GetDefaultUpgradeMedium() = 0; - - // Returns the first discovered endpoint for the given endpoint_id. - DiscoveredEndpoint* GetDiscoveredEndpoint(const std::string& endpoint_id); - - // Returns a vector of discovered endpoints, sorted in order of decreasing - // preference. - std::vector<BasePcpHandler::DiscoveredEndpoint*> GetDiscoveredEndpoints( - const std::string& endpoint_id); - - // Returns a vector of discovered endpoints that share a given Medium. - std::vector<BasePcpHandler::DiscoveredEndpoint*> GetDiscoveredEndpoints( - const proto::connections::Medium medium); - - mediums::WebrtcPeerId CreatePeerIdFromAdvertisement( - const string& service_id, const string& endpoint_id, - const ByteArray& endpoint_info); - - SingleThreadExecutor* GetPcpHandlerThread() - ABSL_LOCK_RETURNED(serial_executor_) { - return &serial_executor_; - } - - Mediums* mediums_; - EndpointManager* endpoint_manager_; - EndpointChannelManager* channel_manager_; - - private: - struct PendingConnectionInfo { - PendingConnectionInfo() = default; - PendingConnectionInfo(PendingConnectionInfo&& other) = default; - PendingConnectionInfo& operator=(PendingConnectionInfo&&) = default; - ~PendingConnectionInfo(); - - // Passes crypto context that we acquired in DH session for temporary - // ownership here. - void SetCryptoContext(std::unique_ptr<securegcm::UKey2Handshake> ukey2); - - // Pass Accept notification to client. - void LocalEndpointAcceptedConnection( - const std::string& endpoint_id, - const PayloadListener& payload_listener); - - // Pass Reject notification to client. - void LocalEndpointRejectedConnection(const std::string& endpoint_id); - - // Client state tracker to report events to. Never changes. Always valid. - ClientProxy* client = nullptr; - // Peer endpoint info, or empty, if not discovered yet. May change. - ByteArray remote_endpoint_info; - std::int32_t nonce = 0; - bool is_incoming = false; - absl::Time start_time{absl::InfinitePast()}; - // Client callbacks. Always valid. - ConnectionListener listener; - ConnectionOptions options; - - // Only set for outgoing connections. If set, we must call - // result->Set() when connection is established, or rejected. - std::weak_ptr<Future<Status>> result; - - // Only (possibly) vector for incoming connections. - std::vector<proto::connections::Medium> supported_mediums; - - // Keep track of a channel before we pass it to EndpointChannelManager. - std::unique_ptr<EndpointChannel> channel; - - // Crypto context; initially empty; established first thing after channel - // creation by running UKey2 session. While it is in progress, we keep track - // of channel ourselves. Once it is done, we pass channel over to - // EndpointChannelManager. We keep crypto context until connection is - // accepted. Crypto context is passed over to channel_manager_ before - // switching to connected state, where Payload may be exchanged. - std::unique_ptr<securegcm::UKey2Handshake> ukey2; - - // Used in AnalyticsRecorder for devices connection tracking. - std::string connection_token; - }; - - // @EncryptionRunnerThread - // Called internally when DH session has negotiated a key successfully. - void OnEncryptionSuccessImpl(const std::string& endpoint_id, - std::unique_ptr<securegcm::UKey2Handshake> ukey2, - const std::string& auth_token, - const ByteArray& raw_auth_token); - - // @EncryptionRunnerThread - // Called internally when DH session was not able to negotiate a key. - void OnEncryptionFailureImpl(const std::string& endpoint_id, - EndpointChannel* channel); - - EncryptionRunner::ResultListener GetResultListener(); - - void OnEncryptionSuccessRunnable( - const std::string& endpoint_id, - std::unique_ptr<securegcm::UKey2Handshake> ukey2, - const std::string& auth_token, const ByteArray& raw_auth_token); - void OnEncryptionFailureRunnable(const std::string& endpoint_id, - EndpointChannel* endpoint_channel); - - static Exception WriteConnectionRequestFrame( - EndpointChannel* endpoint_channel, const std::string& local_endpoint_id, - const ByteArray& local_endpoint_info, std::int32_t nonce, - const std::vector<proto::connections::Medium>& supported_mediums, - std::int32_t keep_alive_interval_millis, - std::int32_t keep_alive_timeout_millis); - - static constexpr absl::Duration kConnectionRequestReadTimeout = - absl::Seconds(2); - static constexpr absl::Duration kRejectedConnectionCloseDelay = - absl::Seconds(2); - static constexpr int kConnectionTokenLength = 8; - - void OnConnectionResponse(ClientProxy* client, const std::string& endpoint_id, - const OfflineFrame& frame); - - // Returns true if the new endpoint is preferred over the old endpoint. - bool IsPreferred(const BasePcpHandler::DiscoveredEndpoint& new_endpoint, - const BasePcpHandler::DiscoveredEndpoint& old_endpoint); - - // Returns true, if connection party should respect the specified topology. - bool ShouldEnforceTopologyConstraints( - const ConnectionOptions& local_advertising_options) const; - - // Returns true, if connection party should attempt to upgrade itself to - // use a higher bandwidth medium, if it is available. - bool AutoUpgradeBandwidth( - const ConnectionOptions& local_advertising_options) const; - - // Returns true if the incoming connection should be killed. This only - // happens when an incoming connection arrives while we have an outgoing - // connection to the same endpoint and we need to stop one connection. - bool BreakTie(ClientProxy* client, const std::string& endpoint_id, - std::int32_t incoming_nonce, EndpointChannel* channel); - // We're not sure how far our outgoing connection has gotten. We may (or may - // not) have called ClientProxy::OnConnectionInitiated. Therefore, we'll - // call both preInit and preResult failures. - void ProcessTieBreakLoss(ClientProxy* client, const std::string& endpoint_id, - PendingConnectionInfo* info); - - // Returns true if the bluetooth endpoint based on remote bluetooth mac - // address is created and appended into discovered_endpoints_ with key - // endpoint_id. - bool AppendRemoteBluetoothMacAddressEndpoint( - const std::string& endpoint_id, - const std::string& remote_bluetooth_mac_address, - const ConnectionOptions& local_discovery_options); - - // Returns true if the webrtc endpoint is created and appended into - // discovered_endpoints_ with key endpoint_id. - bool AppendWebRTCEndpoint(const std::string& endpoint_id, - const ConnectionOptions& local_discovery_options); - - void ProcessPreConnectionInitiationFailure( - ClientProxy* client, Medium medium, const std::string& endpoint_id, - EndpointChannel* channel, bool is_incoming, absl::Time start_time, - Status status, Future<Status>* result); - void ProcessPreConnectionResultFailure(ClientProxy* client, - const std::string& endpoint_id); - - // Called when either side accepts/rejects the connection, but only takes - // effect after both have accepted or one side has rejected. - // - // NOTE: We also take in a 'can_close_immediately' variable. This is because - // any writes in transit are dropped when we close. To avoid having a reject - // write being dropped (which causes the other side to report - // onResult(DISCONNECTED) instead of onResult(REJECTED)), we delay our - // close. If the other side behaves properly, we shouldn't even see the - // delay (because they will also close the connection). - void EvaluateConnectionResult(ClientProxy* client, - const std::string& endpoint_id, - bool can_close_immediately); - - ExceptionOr<OfflineFrame> ReadConnectionRequestFrame( - EndpointChannel* channel); - - // Returns an 8 characters length hashed string generated via a token byte - // array. - std::string GetHashedConnectionToken(const ByteArray& token_bytes); - - static void LogConnectionAttempt(ClientProxy* client, Medium medium, - const std::string& endpoint_id, - bool is_incoming, absl::Time start_time); - - // Returns true if the client cancels the operation in progress through the - // endpoint id. This is done by CancellationFlag. - static bool Cancelled(ClientProxy* client, const std::string& endpoint_id); - - void WaitForLatch(const std::string& method_name, CountDownLatch* latch); - Status WaitForResult(const std::string& method_name, std::int64_t client_id, - Future<Status>* future); - bool MediumSupportedByClientOptions( - const proto::connections::Medium& medium, - const ConnectionOptions& client_options) const; - std::vector<proto::connections::Medium> - GetSupportedConnectionMediumsByPriority( - const ConnectionOptions& local_option); - std::string GetStringValueOfSupportedMediums( - const ConnectionOptions& options) const; - - // The endpoint id in high visibility mode is stable for 30 seconds, while in - // low visibility mode it always rotates. We assume a client is trying to - // rotate endpoint id when the options is "low power" (3P) or "disable - // Bluetooth classic" (1P). - bool ShouldEnterHighVisibilityMode(const ConnectionOptions& options); - - // Returns the intersection of supported mediums based on the mediums reported - // by the remote client and the local client's advertising options. - BooleanMediumSelector ComputeIntersectionOfSupportedMediums( - const PendingConnectionInfo& connection_info); - - ScheduledExecutor alarm_executor_; - SingleThreadExecutor serial_executor_; - - // A map of endpoint id -> PendingConnectionInfo. Entries in this map imply - // that there is an active connection to the endpoint and we're waiting for - // both sides to accept before allowing payloads through. Once the fate of - // the connection is decided (either accepted or rejected), it should be - // removed from this map. - absl::flat_hash_map<std::string, PendingConnectionInfo> pending_connections_; - // A map of endpoint id -> DiscoveredEndpoint. - absl::btree_multimap<std::string, std::shared_ptr<DiscoveredEndpoint>> - discovered_endpoints_; - // A map of endpoint id -> alarm. These alarms delay closing the - // EndpointChannel to give the other side enough time to read the rejection - // message. It's expected that the other side will close the connection - // after reading the message (in which case, this alarm should be cancelled - // as it's no longer needed), but this alarm is the fallback in case that - // doesn't happen. - absl::flat_hash_map<std::string, CancelableAlarm> pending_alarms_; - - // The active ClientProxy's connection lifecycle listener. Non-null while - // advertising. - ConnectionListener advertising_listener_; - - AtomicBoolean stop_{false}; - Pcp pcp_; - Strategy strategy_{PcpToStrategy(pcp_)}; - Prng prng_; - EncryptionRunner encryption_runner_; - BwuManager* bwu_manager_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_BASE_PCP_HANDLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/base_pcp_handler_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/base_pcp_handler_test.cc deleted file mode 100644 index b916cbf39b7..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/base_pcp_handler_test.cc +++ /dev/null @@ -1,785 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/base_pcp_handler.h" - -#include <array> -#include <atomic> -#include <memory> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/time/time.h" -#include "core/internal/base_endpoint_channel.h" -#include "core/internal/bwu_manager.h" -#include "core/internal/client_proxy.h" -#include "core/internal/encryption_runner.h" -#include "core/internal/offline_frames.h" -#include "core/listeners.h" -#include "core/options.h" -#include "core/params.h" -#include "platform/base/byte_array.h" -#include "platform/base/exception.h" -#include "platform/base/medium_environment.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/pipe.h" -#include "proto/connections/offline_wire_formats.pb.h" -#include "proto/connections_enums.pb.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -using ::location::nearby::proto::connections::Medium; -using ::testing::_; -using ::testing::AtLeast; -using ::testing::Invoke; -using ::testing::MockFunction; -using ::testing::Return; -using ::testing::StrictMock; - -constexpr std::array<char, 6> kFakeMacAddress = {'a', 'b', 'c', 'd', 'e', 'f'}; - -constexpr BooleanMediumSelector kTestCases[] = { - BooleanMediumSelector{}, - BooleanMediumSelector{ - .bluetooth = true, - }, - BooleanMediumSelector{ - .wifi_lan = true, - }, - BooleanMediumSelector{ - .bluetooth = true, - .wifi_lan = true, - }, -}; - -class MockEndpointChannel : public BaseEndpointChannel { - public: - explicit MockEndpointChannel(Pipe* reader, Pipe* writer) - : BaseEndpointChannel("channel", &reader->GetInputStream(), - &writer->GetOutputStream()) {} - - ExceptionOr<ByteArray> DoRead() { return BaseEndpointChannel::Read(); } - Exception DoWrite(const ByteArray& data) { - if (broken_write_) { - return {Exception::kFailed}; - } - return BaseEndpointChannel::Write(data); - } - absl::Time DoGetLastReadTimestamp() { - return BaseEndpointChannel::GetLastReadTimestamp(); - } - - MOCK_METHOD(ExceptionOr<ByteArray>, Read, (), (override)); - MOCK_METHOD(Exception, Write, (const ByteArray& data), (override)); - MOCK_METHOD(void, CloseImpl, (), (override)); - MOCK_METHOD(proto::connections::Medium, GetMedium, (), (const override)); - MOCK_METHOD(std::string, GetType, (), (const override)); - MOCK_METHOD(std::string, GetName, (), (const override)); - MOCK_METHOD(bool, IsPaused, (), (const override)); - MOCK_METHOD(void, Pause, (), (override)); - MOCK_METHOD(void, Resume, (), (override)); - MOCK_METHOD(absl::Time, GetLastReadTimestamp, (), (const override)); - - bool broken_write_{false}; -}; - -class MockPcpHandler : public BasePcpHandler { - public: - using DiscoveredEndpoint = BasePcpHandler::DiscoveredEndpoint; - - MockPcpHandler(Mediums* m, EndpointManager* em, EndpointChannelManager* ecm, - BwuManager* bwu) - : BasePcpHandler(m, em, ecm, bwu, Pcp::kP2pCluster) {} - - // Expose protected inner types of a base type for mocking. - using BasePcpHandler::ConnectImplResult; - using BasePcpHandler::DiscoveredEndpoint; - using BasePcpHandler::StartOperationResult; - - MOCK_METHOD(Strategy, GetStrategy, (), (const override)); - MOCK_METHOD(Pcp, GetPcp, (), (const override)); - - MOCK_METHOD(bool, HasOutgoingConnections, (ClientProxy * client), - (const, override)); - MOCK_METHOD(bool, HasIncomingConnections, (ClientProxy * client), - (const, override)); - - MOCK_METHOD(bool, CanSendOutgoingConnection, (ClientProxy * client), - (const, override)); - MOCK_METHOD(bool, CanReceiveIncomingConnection, (ClientProxy * client), - (const, override)); - - MOCK_METHOD(StartOperationResult, StartAdvertisingImpl, - (ClientProxy * client, const std::string& service_id, - const std::string& local_endpoint_id, - const ByteArray& local_endpoint_info, - const ConnectionOptions& options), - (override)); - MOCK_METHOD(Status, StopAdvertisingImpl, (ClientProxy * client), (override)); - MOCK_METHOD(StartOperationResult, StartDiscoveryImpl, - (ClientProxy * client, const std::string& service_id, - const ConnectionOptions& options), - (override)); - MOCK_METHOD(Status, StopDiscoveryImpl, (ClientProxy * client), (override)); - MOCK_METHOD(Status, InjectEndpointImpl, - (ClientProxy * client, const std::string& service_id, - const OutOfBandConnectionMetadata& metadata), - (override)); - MOCK_METHOD(ConnectImplResult, ConnectImpl, - (ClientProxy * client, DiscoveredEndpoint* endpoint), (override)); - MOCK_METHOD(proto::connections::Medium, GetDefaultUpgradeMedium, (), - (override)); - - std::vector<proto::connections::Medium> GetConnectionMediumsByPriority() - override { - return std::vector<proto::connections::Medium>{ - proto::connections::WIFI_LAN, proto::connections::WEB_RTC, - proto::connections::BLUETOOTH, proto::connections::BLE}; - } - - // Mock adapters for protected non-virtual methods of a base class. - void OnEndpointFound(ClientProxy* client, - std::shared_ptr<DiscoveredEndpoint> endpoint) - ABSL_NO_THREAD_SAFETY_ANALYSIS { - BasePcpHandler::OnEndpointFound(client, std::move(endpoint)); - } - void OnEndpointLost(ClientProxy* client, const DiscoveredEndpoint& endpoint) - ABSL_NO_THREAD_SAFETY_ANALYSIS { - BasePcpHandler::OnEndpointLost(client, endpoint); - } - std::vector<BasePcpHandler::DiscoveredEndpoint*> GetDiscoveredEndpoints( - const std::string& endpoint_id) { - return BasePcpHandler::GetDiscoveredEndpoints(endpoint_id); - } - - std::vector<proto::connections::Medium> GetDiscoveryMediums( - ClientProxy* client) { - auto allowed = client->GetDiscoveryOptions().CompatibleOptions().allowed; - return GetMediumsFromSelector(allowed); - } - - std::vector<proto::connections::Medium> GetMediumsFromSelector( - BooleanMediumSelector allowed) { - return allowed.GetMediums(true); - } -}; - -class MockContext { - public: - explicit MockContext(std::atomic_int* destroyed = nullptr) - : destroyed_{destroyed} {} - MockContext(MockContext&& other) { *this = std::move(other); } - MockContext& operator=(MockContext&& other) { - destroyed_ = other.destroyed_; - other.destroyed_ = nullptr; - return *this; - } - - ~MockContext() { - if (destroyed_) (*destroyed_)++; - } - - private: - std::atomic_int* destroyed_; -}; - -struct MockDiscoveredEndpoint : public MockPcpHandler::DiscoveredEndpoint { - MockDiscoveredEndpoint(DiscoveredEndpoint endpoint, MockContext context) - : DiscoveredEndpoint(std::move(endpoint)), context(std::move(context)) {} - - MockContext context; -}; - -class BasePcpHandlerTest - : public ::testing::TestWithParam<BooleanMediumSelector> { - protected: - struct MockConnectionListener { - StrictMock<MockFunction<void(const std::string& endpoint_id, - const ConnectionResponseInfo& info)>> - initiated_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id)>> accepted_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id, - const Status& status)>> - rejected_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id)>> - disconnected_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id, - std::int32_t quality)>> - bandwidth_changed_cb; - }; - struct MockDiscoveryListener { - StrictMock<MockFunction<void(const std::string& endpoint_id, - const ByteArray& endpoint_info, - const std::string& service_id)>> - endpoint_found_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id)>> - endpoint_lost_cb; - StrictMock< - MockFunction<void(const std::string& endpoint_id, DistanceInfo info)>> - endpoint_distance_changed_cb; - }; - - void StartAdvertising(ClientProxy* client, MockPcpHandler* pcp_handler, - BooleanMediumSelector allowed = GetParam()) { - std::string service_id{"service"}; - ConnectionOptions options{ - .strategy = Strategy::kP2pCluster, - .allowed = allowed, - .auto_upgrade_bandwidth = true, - .enforce_topology_constraints = true, - }; - ConnectionRequestInfo info{ - .endpoint_info = ByteArray{"remote_endpoint_name"}, - .listener = connection_listener_, - }; - EXPECT_CALL(*pcp_handler, StartAdvertisingImpl(client, service_id, _, - info.endpoint_info, _)) - .WillOnce(Return(MockPcpHandler::StartOperationResult{ - .status = {Status::kSuccess}, - .mediums = pcp_handler->GetMediumsFromSelector(allowed), - })); - EXPECT_EQ(pcp_handler->StartAdvertising(client, service_id, options, info), - Status{Status::kSuccess}); - EXPECT_TRUE(client->IsAdvertising()); - } - - void StartDiscovery(ClientProxy* client, MockPcpHandler* pcp_handler, - BooleanMediumSelector allowed = GetParam()) { - std::string service_id{"service"}; - ConnectionOptions options{ - .strategy = Strategy::kP2pCluster, - .allowed = allowed, - .auto_upgrade_bandwidth = true, - .enforce_topology_constraints = true, - .keep_alive_interval_millis = 5000, - .keep_alive_timeout_millis = 3000, - }; - EXPECT_CALL(*pcp_handler, StartDiscoveryImpl(client, service_id, _)) - .WillOnce(Return(MockPcpHandler::StartOperationResult{ - .status = {Status::kSuccess}, - .mediums = pcp_handler->GetMediumsFromSelector(allowed), - })); - EXPECT_EQ(pcp_handler->StartDiscovery(client, service_id, options, - discovery_listener_), - Status{Status::kSuccess}); - EXPECT_TRUE(client->IsDiscovering()); - } - - std::pair<std::unique_ptr<MockEndpointChannel>, - std::unique_ptr<MockEndpointChannel>> - SetupConnection(Pipe& pipe_a, Pipe& pipe_b, - proto::connections::Medium medium) { // NOLINT - auto channel_a = std::make_unique<MockEndpointChannel>(&pipe_b, &pipe_a); - auto channel_b = std::make_unique<MockEndpointChannel>(&pipe_a, &pipe_b); - // On initiator (A) side, we drop the first write, since this is a - // connection establishment packet, and we don't have the peer entity, just - // the peer channel. The rest of the exchange must happen for the benefit of - // DH key exchange. - EXPECT_CALL(*channel_a, Read()) - .WillRepeatedly(Invoke( - [channel = channel_a.get()]() { return channel->DoRead(); })); - EXPECT_CALL(*channel_a, Write(_)) - .WillOnce(Return(Exception{Exception::kSuccess})) - .WillRepeatedly( - Invoke([channel = channel_a.get()](const ByteArray& data) { - return channel->DoWrite(data); - })); - EXPECT_CALL(*channel_a, GetMedium).WillRepeatedly(Return(medium)); - EXPECT_CALL(*channel_a, GetLastReadTimestamp) - .WillRepeatedly(Return(absl::Now())); - EXPECT_CALL(*channel_a, IsPaused).WillRepeatedly(Return(false)); - EXPECT_CALL(*channel_b, Read()) - .WillRepeatedly(Invoke( - [channel = channel_b.get()]() { return channel->DoRead(); })); - EXPECT_CALL(*channel_b, Write(_)) - .WillRepeatedly( - Invoke([channel = channel_b.get()](const ByteArray& data) { - return channel->DoWrite(data); - })); - EXPECT_CALL(*channel_b, GetMedium).WillRepeatedly(Return(medium)); - EXPECT_CALL(*channel_b, GetLastReadTimestamp) - .WillRepeatedly(Return(absl::Now())); - EXPECT_CALL(*channel_b, IsPaused).WillRepeatedly(Return(false)); - return std::make_pair(std::move(channel_a), std::move(channel_b)); - } - - void RequestConnection(const std::string& endpoint_id, - std::unique_ptr<MockEndpointChannel> channel_a, - MockEndpointChannel* channel_b, ClientProxy* client, - MockPcpHandler* pcp_handler, - proto::connections::Medium connect_medium, - std::atomic_int* flag = nullptr, - Status expected_result = {Status::kSuccess}) { - ConnectionRequestInfo info{ - .endpoint_info = ByteArray{"ABCD"}, - .listener = connection_listener_, - }; - ConnectionOptions options{ - .remote_bluetooth_mac_address = - ByteArray{std::string("\x12\x34\x56\x78\x9a\xbc")}, - .keep_alive_interval_millis = - FeatureFlags::GetInstance().GetFlags().keep_alive_interval_millis, - .keep_alive_timeout_millis = - FeatureFlags::GetInstance().GetFlags().keep_alive_timeout_millis, - }; - EXPECT_CALL(mock_discovery_listener_.endpoint_found_cb, Call); - EXPECT_CALL(*pcp_handler, CanSendOutgoingConnection) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*pcp_handler, GetStrategy) - .WillRepeatedly(Return(Strategy::kP2pCluster)); - if (expected_result == Status{Status::kSuccess}) { - EXPECT_CALL(mock_connection_listener_.initiated_cb, Call).Times(1); - } - // Simulate successful discovery. - auto encryption_runner = std::make_unique<EncryptionRunner>(); - auto allowed_mediums = pcp_handler->GetDiscoveryMediums(client); - - EXPECT_CALL(*pcp_handler, ConnectImpl) - .WillOnce(Invoke([&channel_a, connect_medium]( - ClientProxy* client, - MockPcpHandler::DiscoveredEndpoint* endpoint) { - return MockPcpHandler::ConnectImplResult{ - .medium = connect_medium, - .status = {Status::kSuccess}, - .endpoint_channel = std::move(channel_a), - }; - })); - - for (const auto& discovered_medium : allowed_mediums) { - pcp_handler->OnEndpointFound( - client, - std::make_shared<MockDiscoveredEndpoint>(MockDiscoveredEndpoint{ - { - endpoint_id, - info.endpoint_info, - "service", - discovered_medium, - WebRtcState::kUndefined, - }, - MockContext{flag}, - })); - } - auto other_client = std::make_unique<ClientProxy>(); - - // Run peer crypto in advance, if channel_b is provided. - // Otherwise stay in not-encrypted state. - if (channel_b != nullptr) { - encryption_runner->StartServer(other_client.get(), endpoint_id, channel_b, - {}); - } - EXPECT_EQ( - pcp_handler->RequestConnection(client, endpoint_id, info, options), - expected_result); - NEARBY_LOG(INFO, "Stopping Encryption Runner"); - } - - Pipe pipe_a_; - Pipe pipe_b_; - MockConnectionListener mock_connection_listener_; - MockDiscoveryListener mock_discovery_listener_; - ConnectionListener connection_listener_{ - .initiated_cb = mock_connection_listener_.initiated_cb.AsStdFunction(), - .accepted_cb = mock_connection_listener_.accepted_cb.AsStdFunction(), - .rejected_cb = mock_connection_listener_.rejected_cb.AsStdFunction(), - .disconnected_cb = - mock_connection_listener_.disconnected_cb.AsStdFunction(), - .bandwidth_changed_cb = - mock_connection_listener_.bandwidth_changed_cb.AsStdFunction(), - }; - DiscoveryListener discovery_listener_{ - .endpoint_found_cb = - mock_discovery_listener_.endpoint_found_cb.AsStdFunction(), - .endpoint_lost_cb = - mock_discovery_listener_.endpoint_lost_cb.AsStdFunction(), - .endpoint_distance_changed_cb = - mock_discovery_listener_.endpoint_distance_changed_cb.AsStdFunction(), - }; - MediumEnvironment& env_ = MediumEnvironment::Instance(); -}; - -TEST_P(BasePcpHandlerTest, ConstructorDestructorWorks) { - env_.Start(); - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - SUCCEED(); - bwu.Shutdown(); - env_.Stop(); -} - -TEST_P(BasePcpHandlerTest, StartAdvertisingChangesState) { - env_.Start(); - ClientProxy client; - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - StartAdvertising(&client, &pcp_handler); - bwu.Shutdown(); - env_.Stop(); -} - -TEST_P(BasePcpHandlerTest, StopAdvertisingChangesState) { - env_.Start(); - ClientProxy client; - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - StartAdvertising(&client, &pcp_handler); - EXPECT_CALL(pcp_handler, StopAdvertisingImpl(&client)).Times(1); - EXPECT_TRUE(client.IsAdvertising()); - pcp_handler.StopAdvertising(&client); - EXPECT_FALSE(client.IsAdvertising()); - bwu.Shutdown(); - env_.Stop(); -} - -TEST_P(BasePcpHandlerTest, StartDiscoveryChangesState) { - env_.Start(); - ClientProxy client; - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - StartDiscovery(&client, &pcp_handler); - bwu.Shutdown(); - env_.Stop(); -} - -TEST_P(BasePcpHandlerTest, StopDiscoveryChangesState) { - env_.Start(); - ClientProxy client; - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - StartDiscovery(&client, &pcp_handler); - EXPECT_CALL(pcp_handler, StopDiscoveryImpl(&client)).Times(1); - EXPECT_TRUE(client.IsDiscovering()); - pcp_handler.StopDiscovery(&client); - EXPECT_FALSE(client.IsDiscovering()); - bwu.Shutdown(); - env_.Stop(); -} - -TEST_P(BasePcpHandlerTest, RequestConnectionChangesState) { - env_.Start(); - std::string endpoint_id{"1234"}; - ClientProxy client; - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - StartDiscovery(&client, &pcp_handler); - auto mediums = pcp_handler.GetDiscoveryMediums(&client); - auto connect_medium = mediums[mediums.size() - 1]; - auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium); - auto& channel_a = channel_pair.first; - auto& channel_b = channel_pair.second; - EXPECT_CALL(*channel_a, CloseImpl).Times(1); - EXPECT_CALL(*channel_b, CloseImpl).Times(1); - EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0)); - RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), &client, - &pcp_handler, connect_medium); - NEARBY_LOG(INFO, "RequestConnection complete"); - channel_b->Close(); - bwu.Shutdown(); - pcp_handler.DisconnectFromEndpointManager(); - env_.Stop(); -} - -TEST_P(BasePcpHandlerTest, IoError_RequestConnectionFails) { - env_.Start(); - std::string endpoint_id{"1234"}; - ClientProxy client; - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - StartDiscovery(&client, &pcp_handler); - auto mediums = pcp_handler.GetDiscoveryMediums(&client); - auto connect_medium = mediums[mediums.size() - 1]; - auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium); - auto& channel_a = channel_pair.first; - auto& channel_b = channel_pair.second; - EXPECT_CALL(*channel_a, CloseImpl).Times(AtLeast(1)); - EXPECT_CALL(*channel_b, CloseImpl).Times(AtLeast(1)); - channel_b->broken_write_ = true; - EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0)); - RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), &client, - &pcp_handler, connect_medium, nullptr, - {Status::kEndpointIoError}); - NEARBY_LOG(INFO, "RequestConnection complete"); - channel_b->Close(); - bwu.Shutdown(); - pcp_handler.DisconnectFromEndpointManager(); - env_.Stop(); -} - -TEST_P(BasePcpHandlerTest, AcceptConnectionChangesState) { - env_.Start(); - std::string endpoint_id{"1234"}; - ClientProxy client; - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - StartDiscovery(&client, &pcp_handler); - auto mediums = pcp_handler.GetDiscoveryMediums(&client); - auto connect_medium = mediums[mediums.size() - 1]; - auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium); - auto& channel_a = channel_pair.first; - auto& channel_b = channel_pair.second; - EXPECT_CALL(*channel_a, CloseImpl).Times(1); - EXPECT_CALL(*channel_b, CloseImpl).Times(1); - RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), &client, - &pcp_handler, connect_medium); - NEARBY_LOG(INFO, "Attempting to accept connection: id=%s", - endpoint_id.c_str()); - EXPECT_EQ(pcp_handler.AcceptConnection(&client, endpoint_id, {}), - Status{Status::kSuccess}); - EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0)); - NEARBY_LOGS(INFO) << "Closing connection: id=" << endpoint_id; - channel_b->Close(); - bwu.Shutdown(); - pcp_handler.DisconnectFromEndpointManager(); - env_.Stop(); -} - -TEST_P(BasePcpHandlerTest, RejectConnectionChangesState) { - env_.Start(); - std::string endpoint_id{"1234"}; - ClientProxy client; - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - StartDiscovery(&client, &pcp_handler); - auto mediums = pcp_handler.GetDiscoveryMediums(&client); - auto connect_medium = mediums[mediums.size() - 1]; - auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium); - auto& channel_b = channel_pair.second; - EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(1); - RequestConnection(endpoint_id, std::move(channel_pair.first), channel_b.get(), - &client, &pcp_handler, connect_medium); - NEARBY_LOGS(INFO) << "Attempting to reject connection: id=" << endpoint_id; - EXPECT_EQ(pcp_handler.RejectConnection(&client, endpoint_id), - Status{Status::kSuccess}); - NEARBY_LOGS(INFO) << "Closing connection: id=" << endpoint_id; - channel_b->Close(); - bwu.Shutdown(); - pcp_handler.DisconnectFromEndpointManager(); - env_.Stop(); -} - -TEST_P(BasePcpHandlerTest, OnIncomingFrameChangesState) { - env_.Start(); - std::string endpoint_id{"1234"}; - ClientProxy client; - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - StartDiscovery(&client, &pcp_handler); - auto mediums = pcp_handler.GetDiscoveryMediums(&client); - auto connect_medium = mediums[mediums.size() - 1]; - auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium); - auto& channel_a = channel_pair.first; - auto& channel_b = channel_pair.second; - EXPECT_CALL(*channel_a, CloseImpl).Times(1); - EXPECT_CALL(*channel_b, CloseImpl).Times(1); - RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), &client, - &pcp_handler, connect_medium); - NEARBY_LOGS(INFO) << "Attempting to accept connection: id=" << endpoint_id; - EXPECT_CALL(mock_connection_listener_.accepted_cb, Call).Times(1); - EXPECT_CALL(mock_connection_listener_.disconnected_cb, Call) - .Times(AtLeast(0)); - EXPECT_EQ(pcp_handler.AcceptConnection(&client, endpoint_id, {}), - Status{Status::kSuccess}); - NEARBY_LOG(INFO, "Simulating remote accept: id=%s", endpoint_id.c_str()); - auto frame = - parser::FromBytes(parser::ForConnectionResponse(Status::kSuccess)); - pcp_handler.OnIncomingFrame(frame.result(), endpoint_id, &client, - connect_medium); - NEARBY_LOGS(INFO) << "Closing connection: id=" << endpoint_id; - channel_b->Close(); - bwu.Shutdown(); - pcp_handler.DisconnectFromEndpointManager(); - env_.Stop(); -} - -TEST_P(BasePcpHandlerTest, DestructorIsCalledOnProtocolEndpoint) { - env_.Start(); - std::atomic_int destroyed_flag = 0; - int mediums_count = 0; - { - std::string endpoint_id{"1234"}; - ClientProxy client; - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - StartDiscovery(&client, &pcp_handler); - auto mediums = pcp_handler.GetDiscoveryMediums(&client); - auto connect_medium = mediums[mediums.size() - 1]; - auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium); - auto& channel_a = channel_pair.first; - auto& channel_b = channel_pair.second; - EXPECT_CALL(*channel_a, CloseImpl).Times(1); - EXPECT_CALL(*channel_b, CloseImpl).Times(1); - RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), - &client, &pcp_handler, connect_medium, &destroyed_flag); - mediums_count = mediums.size(); - NEARBY_LOG(INFO, "Attempting to accept connection: id=%s", - endpoint_id.c_str()); - EXPECT_EQ(pcp_handler.AcceptConnection(&client, endpoint_id, {}), - Status{Status::kSuccess}); - EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0)); - NEARBY_LOG(INFO, "Closing connection: id=%s", endpoint_id.c_str()); - channel_b->Close(); - bwu.Shutdown(); - pcp_handler.DisconnectFromEndpointManager(); - } - EXPECT_EQ(destroyed_flag.load(), mediums_count); - env_.Stop(); -} - -TEST_P(BasePcpHandlerTest, MultipleMediumsProduceSingleEndpointLostEvent) { - env_.Start(); - BooleanMediumSelector allowed = GetParam(); - if (allowed.Count(true) < 2) { - // Ignore single-medium test cases, and implicit "all mediums" case. - SUCCEED(); - return; - } - std::atomic_int destroyed_flag = 0; - int mediums_count = 0; - { - std::string endpoint_id{"1234"}; - ClientProxy client; - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - StartDiscovery(&client, &pcp_handler); - auto mediums = pcp_handler.GetDiscoveryMediums(&client); - auto connect_medium = mediums[mediums.size() - 1]; - auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium); - auto& channel_a = channel_pair.first; - auto& channel_b = channel_pair.second; - EXPECT_CALL(*channel_a, CloseImpl).Times(1); - EXPECT_CALL(*channel_b, CloseImpl).Times(1); - EXPECT_CALL(mock_discovery_listener_.endpoint_lost_cb, Call).Times(1); - RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), - &client, &pcp_handler, connect_medium, &destroyed_flag); - auto allowed_mediums = pcp_handler.GetDiscoveryMediums(&client); - mediums_count = allowed_mediums.size(); - NEARBY_LOG(INFO, "Attempting to accept connection: id=%s", - endpoint_id.c_str()); - EXPECT_EQ(pcp_handler.AcceptConnection(&client, endpoint_id, {}), - Status{Status::kSuccess}); - EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0)); - for (const auto* endpoint : - pcp_handler.GetDiscoveredEndpoints(endpoint_id)) { - pcp_handler.OnEndpointLost(&client, *endpoint); - } - NEARBY_LOG(INFO, "Closing connection: id=%s", endpoint_id.c_str()); - channel_b->Close(); - bwu.Shutdown(); - pcp_handler.DisconnectFromEndpointManager(); - } - EXPECT_EQ(destroyed_flag.load(), mediums_count); - env_.Stop(); -} - -INSTANTIATE_TEST_SUITE_P(ParameterizedBasePcpHandlerTest, BasePcpHandlerTest, - ::testing::ValuesIn(kTestCases)); - -TEST_F(BasePcpHandlerTest, InjectEndpoint) { - env_.Start(); - std::string service_id{"service"}; - std::string endpoint_id{"ABCD"}; - ClientProxy client; - Mediums m; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(m, em, ecm, {}, {}); - MockPcpHandler pcp_handler(&m, &em, &ecm, &bwu); - BooleanMediumSelector allowed{ - .bluetooth = true, - }; - ConnectionOptions options{ - .allowed = allowed, - .is_out_of_band_connection = true, - }; - EXPECT_CALL(mock_discovery_listener_.endpoint_found_cb, Call); - EXPECT_CALL(pcp_handler, StartDiscoveryImpl(&client, service_id, _)) - .WillOnce(Return(MockPcpHandler::StartOperationResult{ - .status = {Status::kSuccess}, - .mediums = allowed.GetMediums(true), - })); - EXPECT_EQ(pcp_handler.StartDiscovery(&client, service_id, options, - discovery_listener_), - Status{Status::kSuccess}); - EXPECT_TRUE(client.IsDiscovering()); - - EXPECT_CALL(pcp_handler, InjectEndpointImpl(&client, service_id, _)) - .WillOnce(Invoke([&pcp_handler, &endpoint_id]( - ClientProxy* client, const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) { - pcp_handler.OnEndpointFound( - client, - std::make_shared<MockDiscoveredEndpoint>(MockDiscoveredEndpoint{ - { - endpoint_id, - /*endpoint_info=*/ByteArray{"ABCD"}, - service_id, - Medium::BLUETOOTH, - WebRtcState::kUndefined, - }, - MockContext{nullptr}, - })); - return Status{Status::kSuccess}; - })); - pcp_handler.InjectEndpoint( - &client, service_id, - OutOfBandConnectionMetadata{ - .medium = Medium::BLUETOOTH, - .remote_bluetooth_mac_address = ByteArray(kFakeMacAddress), - }); - bwu.Shutdown(); - env_.Stop(); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/ble_advertisement.cc b/chromium/third_party/nearby/src/cpp/core/internal/ble_advertisement.cc deleted file mode 100644 index ba856d8eee8..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/ble_advertisement.cc +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/ble_advertisement.h" - -#include <inttypes.h> - -#include "absl/strings/escaping.h" -#include "core/internal/base_pcp_handler.h" -#include "platform/base/base_input_stream.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { - -BleAdvertisement::BleAdvertisement(Version version, Pcp pcp, - const ByteArray& service_id_hash, - const std::string& endpoint_id, - const ByteArray& endpoint_info, - const std::string& bluetooth_mac_address, - const ByteArray& uwb_address, - WebRtcState web_rtc_state) { - DoInitialize(/*fast_advertisement=*/false, version, pcp, service_id_hash, - endpoint_id, endpoint_info, bluetooth_mac_address, uwb_address, - web_rtc_state); -} - -BleAdvertisement::BleAdvertisement(Version version, Pcp pcp, - const std::string& endpoint_id, - const ByteArray& endpoint_info, - const ByteArray& uwb_address) { - DoInitialize(/*fast_advertisement=*/true, version, pcp, {}, endpoint_id, - endpoint_info, {}, uwb_address, WebRtcState::kUndefined); -} - -void BleAdvertisement::DoInitialize(bool fast_advertisement, Version version, - Pcp pcp, const ByteArray& service_id_hash, - const std::string& endpoint_id, - const ByteArray& endpoint_info, - const std::string& bluetooth_mac_address, - const ByteArray& uwb_address, - WebRtcState web_rtc_state) { - fast_advertisement_ = fast_advertisement; - if (!fast_advertisement_) { - if (service_id_hash.size() != kServiceIdHashLength) return; - } - int max_endpoint_info_length = - fast_advertisement_ ? kMaxFastEndpointInfoLength : kMaxEndpointInfoLength; - if (version != Version::kV1 || endpoint_id.empty() || - endpoint_id.length() != kEndpointIdLength || - endpoint_info.size() > max_endpoint_info_length) { - return; - } - - switch (pcp) { - case Pcp::kP2pCluster: // Fall through - case Pcp::kP2pStar: // Fall through - case Pcp::kP2pPointToPoint: - break; - default: - return; - } - - version_ = version; - pcp_ = pcp; - service_id_hash_ = service_id_hash; - endpoint_id_ = endpoint_id; - endpoint_info_ = endpoint_info; - uwb_address_ = uwb_address; - if (!fast_advertisement_) { - if (!BluetoothUtils::FromString(bluetooth_mac_address).Empty()) { - bluetooth_mac_address_ = bluetooth_mac_address; - } - - web_rtc_state_ = web_rtc_state; - } -} - -BleAdvertisement::BleAdvertisement(bool fast_advertisement, - const ByteArray& ble_advertisement_bytes) { - fast_advertisement_ = fast_advertisement; - - if (ble_advertisement_bytes.Empty()) { - NEARBY_LOG(ERROR, - "Cannot deserialize BleAdvertisement: null bytes passed in."); - return; - } - - int min_advertisement_length = fast_advertisement_ - ? kMinFastAdvertisementLength - : kMinAdvertisementLength; - - if (ble_advertisement_bytes.size() < min_advertisement_length) { - NEARBY_LOG(ERROR, - "Cannot deserialize BleAdvertisement: expecting min %d raw " - "bytes, got %" PRIu64, - kMinAdvertisementLength, ble_advertisement_bytes.size()); - return; - } - - ByteArray advertisement_bytes{ble_advertisement_bytes}; - BaseInputStream base_input_stream{advertisement_bytes}; - // The first 1 byte is supposed to be the version and pcp. - auto version_and_pcp_byte = static_cast<char>(base_input_stream.ReadUint8()); - // The upper 3 bits are supposed to be the version. - version_ = - static_cast<Version>((version_and_pcp_byte & kVersionBitmask) >> 5); - if (version_ != Version::kV1) { - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement: unsupported Version %d", - version_); - return; - } - // The lower 5 bits are supposed to be the Pcp. - pcp_ = static_cast<Pcp>(version_and_pcp_byte & kPcpBitmask); - switch (pcp_) { - case Pcp::kP2pCluster: // Fall through - case Pcp::kP2pStar: // Fall through - case Pcp::kP2pPointToPoint: - break; - default: - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement: uunsupported V1 PCP %d", - pcp_); - } - - // The next 3 bytes are supposed to be the service_id_hash if not fast - // advertisment. - if (!fast_advertisement_) - service_id_hash_ = base_input_stream.ReadBytes(kServiceIdHashLength); - - // The next 4 bytes are supposed to be the endpoint_id. - endpoint_id_ = std::string{base_input_stream.ReadBytes(kEndpointIdLength)}; - - // The next 1 byte is supposed to be the length of the endpoint_info. - std::uint32_t expected_endpoint_info_length = base_input_stream.ReadUint8(); - - // The next x bytes are the endpoint info. (Max length is 131 bytes or 17 - // bytes as fast_advertisement being true). - endpoint_info_ = base_input_stream.ReadBytes(expected_endpoint_info_length); - const int max_endpoint_info_length = - fast_advertisement_ ? kMaxFastEndpointInfoLength : kMaxEndpointInfoLength; - if (endpoint_info_.Empty() || - endpoint_info_.size() != expected_endpoint_info_length || - endpoint_info_.size() > max_endpoint_info_length) { - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement(fast advertisement=%d): " - "expected endpointInfo to be %d bytes, got %" PRIu64, - fast_advertisement_, expected_endpoint_info_length, - endpoint_info_.size()); - - // Clear enpoint_id for validity. - endpoint_id_.clear(); - return; - } - - // The next 6 bytes are the bluetooth mac address if not fast advertisment. - if (!fast_advertisement_) { - auto bluetooth_mac_address_bytes = - base_input_stream.ReadBytes(BluetoothUtils::kBluetoothMacAddressLength); - bluetooth_mac_address_ = - BluetoothUtils::ToString(bluetooth_mac_address_bytes); - } - - // The next 1 byte is supposed to be the length of the uwb_address. If the - // next byte is not available then it should be a fast advertisement and skip - // it for remaining bytes. - if (base_input_stream.IsAvailable(1)) { - std::uint32_t expected_uwb_address_length = base_input_stream.ReadUint8(); - // If the length of uwb_address is not zero, then retrieve it. - if (expected_uwb_address_length != 0) { - uwb_address_ = base_input_stream.ReadBytes(expected_uwb_address_length); - if (uwb_address_.Empty() || - uwb_address_.size() != expected_uwb_address_length) { - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement: " - "expected uwbAddress size to be %d bytes, got %" PRIu64, - expected_uwb_address_length, uwb_address_.size()); - - // Clear enpoint_id for validity. - endpoint_id_.clear(); - return; - } - } - - // The next 1 byte is extra field. - if (!fast_advertisement_) { - if (base_input_stream.IsAvailable(kExtraFieldLength)) { - auto extra_field = static_cast<char>(base_input_stream.ReadUint8()); - web_rtc_state_ = (extra_field & kWebRtcConnectableFlagBitmask) == 1 - ? WebRtcState::kConnectable - : WebRtcState::kUnconnectable; - } - } - } - - base_input_stream.Close(); -} - -BleAdvertisement::operator ByteArray() const { - if (!IsValid()) { - return ByteArray(); - } - - // The first 3 bits are the Version. - char version_and_pcp_byte = - (static_cast<char>(version_) << 5) & kVersionBitmask; - // The next 5 bits are the Pcp. - version_and_pcp_byte |= static_cast<char>(pcp_) & kPcpBitmask; - - std::string out; - if (fast_advertisement_) { - // clang-format off - out = absl::StrCat(std::string(1, version_and_pcp_byte), - endpoint_id_, - std::string(1, endpoint_info_.size()), - std::string(endpoint_info_)); - // clang-format on - } else { - // clang-format off - out = absl::StrCat(std::string(1, version_and_pcp_byte), - std::string(service_id_hash_), - endpoint_id_, - std::string(1, endpoint_info_.size()), - std::string(endpoint_info_)); - // clang-format on - - // The next 6 bytes are the bluetooth mac address. If bluetooth_mac_address - // is invalid or empty, we get back an empty byte array. - auto bluetooth_mac_address_bytes{ - BluetoothUtils::FromString(bluetooth_mac_address_)}; - if (!bluetooth_mac_address_bytes.Empty()) { - absl::StrAppend(&out, std::string(bluetooth_mac_address_bytes)); - } else { - // If bluetooth MAC address is invalid, then reserve the bytes. - auto fake_bt_mac_address_bytes = - ByteArray(BluetoothUtils::kBluetoothMacAddressLength); - absl::StrAppend(&out, std::string(fake_bt_mac_address_bytes)); - } - } - - // The next bytes are UWB address field. - if (!uwb_address_.Empty()) { - absl::StrAppend(&out, std::string(1, uwb_address_.size())); - absl::StrAppend(&out, std::string(uwb_address_)); - } else if (!fast_advertisement_) { - // Write UWB address with length 0 to be able to read the next field when - // decode. - absl::StrAppend(&out, std::string(1, uwb_address_.size())); - } - - // The next 1 byte is extra field. - if (!fast_advertisement_) { - int web_rtc_connectable_flag = - (web_rtc_state_ == WebRtcState::kConnectable) ? 1 : 0; - char extra_field_byte = static_cast<char>(web_rtc_connectable_flag) & - kWebRtcConnectableFlagBitmask; - absl::StrAppend(&out, std::string(1, extra_field_byte)); - } - - return ByteArray(std::move(out)); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/ble_advertisement.h b/chromium/third_party/nearby/src/cpp/core/internal/ble_advertisement.h deleted file mode 100644 index a47bbbd8bd2..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/ble_advertisement.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_BLE_ADVERTISEMENT_H_ -#define CORE_INTERNAL_BLE_ADVERTISEMENT_H_ - -#include "core/internal/base_pcp_handler.h" -#include "core/internal/pcp.h" -#include "platform/base/bluetooth_utils.h" -#include "platform/base/byte_array.h" - -namespace location { -namespace nearby { -namespace connections { - -// Represents the format of the Connections Ble Advertisement used in -// Advertising + Discovery. -// -// <p>[VERSION][PCP][SERVICE_ID_HASH][ENDPOINT_ID][ENDPOINT_INFO_SIZE] -// [ENDPOINT_INFO][BLUETOOTH_MAC][UWB_ADDRESS_SIZE][UWB_ADDRESS][EXTRA_FIELD] -// -// <p>The fast version of this advertisement simply omits SERVICE_ID_HASH and -// the Bluetooth MAC address. -// -// <p>See go/connections-ble-advertisement for more information. -class BleAdvertisement { - public: - // Versions of the BleAdvertisement. - enum class Version { - kUndefined = 0, - kV1 = 1, - // Version is only allocated 3 bits in the BleAdvertisement, so this - // can never go beyond V7. - }; - - static constexpr int kVersionAndPcpLength = 1; - static constexpr int kVersionBitmask = 0x0E0; - static constexpr int kPcpBitmask = 0x01F; - static constexpr int kServiceIdHashLength = 3; - static constexpr int kEndpointIdLength = 4; - static constexpr int kEndpointInfoSizeLength = 1; - static constexpr int kBluetoothMacAddressLength = - BluetoothUtils::kBluetoothMacAddressLength; - static constexpr int kUwbAddressSizeLength = 1; - static constexpr int kExtraFieldLength = 1; - static constexpr int kEndpointInfoLengthBitmask = 0x0FF; - static constexpr int kWebRtcConnectableFlagBitmask = 0x01; - static constexpr int kMinAdvertisementLength = - kVersionAndPcpLength + kServiceIdHashLength + kEndpointIdLength + - kEndpointInfoSizeLength + kBluetoothMacAddressLength; - - // The difference between normal and fast advertisements is that the fast one - // omits the SERVICE_ID_HASH and Bluetooth MAC address. This is done to save - // space. - static constexpr int kMinFastAdvertisementLength = kMinAdvertisementLength - - kServiceIdHashLength - - kBluetoothMacAddressLength; - static constexpr int kMaxEndpointInfoLength = 131; - static constexpr int kMaxFastEndpointInfoLength = 17; - - BleAdvertisement() = default; - BleAdvertisement(Version version, Pcp pcp, const std::string& endpoint_id, - const ByteArray& endpoint_info, - const ByteArray& uwb_address); - BleAdvertisement(Version version, Pcp pcp, const ByteArray& service_id_hash, - const std::string& endpoint_id, - const ByteArray& endpoint_info, - const std::string& bluetooth_mac_address, - const ByteArray& uwb_address, WebRtcState web_rtc_state); - BleAdvertisement(bool fast_advertisement, - const ByteArray& ble_advertisement_bytes); - BleAdvertisement(const BleAdvertisement&) = default; - BleAdvertisement& operator=(const BleAdvertisement&) = default; - BleAdvertisement(BleAdvertisement&&) = default; - BleAdvertisement& operator=(BleAdvertisement&&) = default; - ~BleAdvertisement() = default; - - explicit operator ByteArray() const; - - bool IsValid() const { return !endpoint_id_.empty(); } - bool IsFastAdvertisement() const { return fast_advertisement_; } - Version GetVersion() const { return version_; } - Pcp GetPcp() const { return pcp_; } - ByteArray GetServiceIdHash() const { return service_id_hash_; } - std::string GetEndpointId() const { return endpoint_id_; } - ByteArray GetEndpointInfo() const { return endpoint_info_; } - std::string GetBluetoothMacAddress() const { return bluetooth_mac_address_; } - ByteArray GetUwbAddress() const { return uwb_address_; } - WebRtcState GetWebRtcState() const { return web_rtc_state_; } - - private: - void DoInitialize(bool fast_advertisement, Version version, Pcp pcp, - const ByteArray& service_id_hash, - const std::string& endpoint_id, - const ByteArray& endpoint_info, - const std::string& bluetooth_mac_address, - const ByteArray& uwb_address, WebRtcState web_rtc_state); - - bool fast_advertisement_ = false; - Version version_{Version::kUndefined}; - Pcp pcp_{Pcp::kUnknown}; - ByteArray service_id_hash_; - std::string endpoint_id_; - ByteArray endpoint_info_; - std::string bluetooth_mac_address_; - // TODO(b/169550050): Define UWB address field. - ByteArray uwb_address_; - WebRtcState web_rtc_state_{WebRtcState::kUndefined}; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_BLE_ADVERTISEMENT_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/ble_advertisement_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/ble_advertisement_test.cc deleted file mode 100644 index 61871d536f9..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/ble_advertisement_test.cc +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/ble_advertisement.h" - -#include "gtest/gtest.h" -#include "core/internal/base_pcp_handler.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -constexpr BleAdvertisement::Version kVersion = BleAdvertisement::Version::kV1; -constexpr Pcp kPcp = Pcp::kP2pCluster; -constexpr absl::string_view kServiceIdHashBytes{"\x0a\x0b\x0c"}; -constexpr absl::string_view kEndpointId{"AB12"}; -constexpr absl::string_view kEndpointName{ - "How much wood can a woodchuck chuck if a wood chuck would chuck wood?"}; -constexpr absl::string_view kFastAdvertisementEndpointName{"Fast Advertise"}; -constexpr absl::string_view kBluetoothMacAddress{"00:00:E6:88:64:13"}; -constexpr WebRtcState kWebRtcState = WebRtcState::kConnectable; - -// TODO(b/169550050): Implement UWBAddress. -TEST(BleAdvertisementTest, ConstructionWorks) { - ByteArray service_id_hash{std::string(kServiceIdHashBytes)}; - ByteArray endpoint_info{std::string(kEndpointName)}; - BleAdvertisement ble_advertisement{ - kVersion, kPcp, - service_id_hash, std::string(kEndpointId), - endpoint_info, std::string(kBluetoothMacAddress), - ByteArray{}, kWebRtcState}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_FALSE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kPcp, ble_advertisement.GetPcp()); - EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(kEndpointId, ble_advertisement.GetEndpointId()); - EXPECT_EQ(endpoint_info, ble_advertisement.GetEndpointInfo()); - EXPECT_EQ(kBluetoothMacAddress, ble_advertisement.GetBluetoothMacAddress()); - EXPECT_EQ(kWebRtcState, ble_advertisement.GetWebRtcState()); -} - -TEST(BleAdvertisementTest, ConstructionWorksForFastAdvertisement) { - ByteArray fast_endpoint_info{std::string(kFastAdvertisementEndpointName)}; - BleAdvertisement ble_advertisement{kVersion, kPcp, std::string(kEndpointId), - fast_endpoint_info, ByteArray{}}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_TRUE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kPcp, ble_advertisement.GetPcp()); - EXPECT_EQ(kEndpointId, ble_advertisement.GetEndpointId()); - EXPECT_EQ(fast_endpoint_info, ble_advertisement.GetEndpointInfo()); - EXPECT_EQ(WebRtcState::kUndefined, ble_advertisement.GetWebRtcState()); -} - -TEST(BleAdvertisementTest, ConstructionWorksWithEmptyEndpointInfo) { - ByteArray empty_endpoint_info; - - ByteArray service_id_hash{std::string(kServiceIdHashBytes)}; - BleAdvertisement ble_advertisement{kVersion, - kPcp, - service_id_hash, - std::string(kEndpointId), - empty_endpoint_info, - std::string(kBluetoothMacAddress), - ByteArray{}, - kWebRtcState}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_FALSE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kPcp, ble_advertisement.GetPcp()); - EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(kEndpointId, ble_advertisement.GetEndpointId()); - EXPECT_EQ(empty_endpoint_info, ble_advertisement.GetEndpointInfo()); - EXPECT_EQ(kBluetoothMacAddress, ble_advertisement.GetBluetoothMacAddress()); - EXPECT_EQ(kWebRtcState, ble_advertisement.GetWebRtcState()); -} - -TEST(BleAdvertisementTest, - ConstructionWorksWithEmptyEndpointInfoForFastAdvertisement) { - ByteArray empty_endpoint_info; - - BleAdvertisement ble_advertisement{kVersion, kPcp, std::string(kEndpointId), - empty_endpoint_info, ByteArray{}}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_TRUE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kPcp, ble_advertisement.GetPcp()); - EXPECT_EQ(kEndpointId, ble_advertisement.GetEndpointId()); - EXPECT_EQ(empty_endpoint_info, ble_advertisement.GetEndpointInfo()); - EXPECT_EQ(WebRtcState::kUndefined, ble_advertisement.GetWebRtcState()); -} - -TEST(BleAdvertisementTest, ConstructionWorksWithEmojiEndpointInfo) { - ByteArray emoji_endpoint_info{std::string("\u0001F450 \u0001F450")}; - - ByteArray service_id_hash{std::string(kServiceIdHashBytes)}; - BleAdvertisement ble_advertisement{kVersion, - kPcp, - service_id_hash, - std::string(kEndpointId), - emoji_endpoint_info, - std::string(kBluetoothMacAddress), - ByteArray{}, - kWebRtcState}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_FALSE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kPcp, ble_advertisement.GetPcp()); - EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(kEndpointId, ble_advertisement.GetEndpointId()); - EXPECT_EQ(emoji_endpoint_info, ble_advertisement.GetEndpointInfo()); - EXPECT_EQ(kBluetoothMacAddress, ble_advertisement.GetBluetoothMacAddress()); - EXPECT_EQ(kWebRtcState, ble_advertisement.GetWebRtcState()); -} - -TEST(BleAdvertisementTest, - ConstructionWorksWithEmojiEndpointInfoForFastAdvertisement) { - ByteArray emoji_endpoint_info{std::string("\u0001F450 \u0001F450")}; - - BleAdvertisement ble_advertisement{kVersion, kPcp, std::string(kEndpointId), - emoji_endpoint_info, ByteArray{}}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_TRUE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kPcp, ble_advertisement.GetPcp()); - EXPECT_EQ(kEndpointId, ble_advertisement.GetEndpointId()); - EXPECT_EQ(emoji_endpoint_info, ble_advertisement.GetEndpointInfo()); - EXPECT_EQ(WebRtcState::kUndefined, ble_advertisement.GetWebRtcState()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithLongEndpointInfo) { - std::string long_endpoint_name(BleAdvertisement::kMaxEndpointInfoLength + 1, - 'x'); - ByteArray long_endpoint_info{long_endpoint_name}; - - ByteArray service_id_hash{std::string(kServiceIdHashBytes)}; - BleAdvertisement ble_advertisement{ - kVersion, kPcp, - service_id_hash, std::string(kEndpointId), - long_endpoint_info, std::string(kBluetoothMacAddress), - ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, - ConstructionFailsWithLongEndpointInfoForFastAdvertisement) { - std::string long_endpoint_name( - BleAdvertisement::kMaxFastEndpointInfoLength + 1, 'x'); - ByteArray long_endpoint_info{long_endpoint_name}; - - BleAdvertisement ble_advertisement{kVersion, kPcp, std::string(kEndpointId), - long_endpoint_info, ByteArray{}}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithBadVersion) { - auto bad_version = static_cast<BleAdvertisement::Version>(666); - - ByteArray service_id_hash{std::string(kServiceIdHashBytes)}; - ByteArray endpoint_info{std::string(kEndpointName)}; - BleAdvertisement ble_advertisement{ - bad_version, kPcp, - service_id_hash, std::string(kEndpointId), - endpoint_info, std::string(kBluetoothMacAddress), - ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, - ConstructionFailsWithBadVersionForFastAdvertisement) { - auto bad_version = static_cast<BleAdvertisement::Version>(666); - - ByteArray fast_endpoint_info{std::string(kFastAdvertisementEndpointName)}; - BleAdvertisement ble_advertisement{bad_version, kPcp, - std::string(kEndpointId), - fast_endpoint_info, ByteArray{}}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithBadPCP) { - auto bad_pcp = static_cast<Pcp>(666); - - ByteArray service_id_hash{std::string(kServiceIdHashBytes)}; - ByteArray endpoint_info{std::string(kEndpointName)}; - BleAdvertisement ble_advertisement{ - kVersion, bad_pcp, - service_id_hash, std::string(kEndpointId), - endpoint_info, std::string(kBluetoothMacAddress), - ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithBadPCPForFastAdvertisement) { - auto bad_pcp = static_cast<Pcp>(666); - - ByteArray fast_endpoint_info{std::string(kFastAdvertisementEndpointName)}; - BleAdvertisement ble_advertisement{kVersion, bad_pcp, - std::string(kEndpointId), - fast_endpoint_info, ByteArray{}}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionSucceedsWithEmptyBluetoothMacAddress) { - std::string empty_bluetooth_mac_address = ""; - - ByteArray service_id_hash{std::string(kServiceIdHashBytes)}; - ByteArray endpoint_info{std::string(kEndpointName)}; - BleAdvertisement ble_advertisement{ - kVersion, kPcp, - service_id_hash, std::string(kEndpointId), - endpoint_info, empty_bluetooth_mac_address, - ByteArray{}, kWebRtcState}; - - EXPECT_TRUE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionSucceedsWithInvalidBluetoothMacAddress) { - std::string bad_bluetooth_mac_address = "022:00"; - - ByteArray service_id_hash{std::string(kServiceIdHashBytes)}; - ByteArray endpoint_info{std::string(kEndpointName)}; - BleAdvertisement ble_advertisement{kVersion, kPcp, - service_id_hash, std::string(kEndpointId), - endpoint_info, bad_bluetooth_mac_address, - ByteArray{}, kWebRtcState}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kPcp, ble_advertisement.GetPcp()); - EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(kEndpointId, ble_advertisement.GetEndpointId()); - EXPECT_EQ(endpoint_info, ble_advertisement.GetEndpointInfo()); - EXPECT_TRUE(ble_advertisement.GetBluetoothMacAddress().empty()); - EXPECT_EQ(kWebRtcState, ble_advertisement.GetWebRtcState()); -} - -TEST(BleAdvertisementTest, ConstructionFromBytesWorks) { - // Serialize good data into a good Ble Advertisement. - ByteArray service_id_hash{std::string(kServiceIdHashBytes)}; - ByteArray endpoint_info{std::string(kEndpointName)}; - BleAdvertisement org_ble_advertisement{ - kVersion, kPcp, - service_id_hash, std::string(kEndpointId), - endpoint_info, std::string(kBluetoothMacAddress), - ByteArray{}, kWebRtcState}; - ByteArray ble_advertisement_bytes(org_ble_advertisement); - - BleAdvertisement ble_advertisement{false, ble_advertisement_bytes}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_FALSE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kPcp, ble_advertisement.GetPcp()); - EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(kEndpointId, ble_advertisement.GetEndpointId()); - EXPECT_EQ(endpoint_info, ble_advertisement.GetEndpointInfo()); - EXPECT_EQ(kBluetoothMacAddress, ble_advertisement.GetBluetoothMacAddress()); - EXPECT_EQ(kWebRtcState, ble_advertisement.GetWebRtcState()); -} - -TEST(BleAdvertisementTest, ConstructionFromBytesWorksForFastAdvertisement) { - // Serialize good data into a good Ble Advertisement. - ByteArray fast_endpoint_info{std::string(kFastAdvertisementEndpointName)}; - BleAdvertisement org_ble_advertisement{kVersion, kPcp, - std::string(kEndpointId), - fast_endpoint_info, ByteArray{}}; - ByteArray ble_advertisement_bytes(org_ble_advertisement); - - BleAdvertisement ble_advertisement{true, ble_advertisement_bytes}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_TRUE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kPcp, ble_advertisement.GetPcp()); - EXPECT_EQ(kEndpointId, ble_advertisement.GetEndpointId()); - EXPECT_EQ(fast_endpoint_info, ble_advertisement.GetEndpointInfo()); - EXPECT_EQ(WebRtcState::kUndefined, ble_advertisement.GetWebRtcState()); -} - -// Bytes at the end should be ignored so that they can be used as reserve bytes -// in the future. -TEST(BleAdvertisementTest, ConstructionFromLongLengthBytesWorks) { - // Serialize good data into a good Ble Advertisement. - ByteArray service_id_hash{std::string(kServiceIdHashBytes)}; - ByteArray endpoint_info{std::string(kEndpointName)}; - BleAdvertisement ble_advertisement{ - kVersion, kPcp, - service_id_hash, std::string(kEndpointId), - endpoint_info, std::string(kBluetoothMacAddress), - ByteArray{}, kWebRtcState}; - ByteArray ble_advertisement_bytes(ble_advertisement); - - // Add bytes to the end of the valid Ble advertisement. - ByteArray long_ble_advertisement_bytes( - BleAdvertisement::kMinAdvertisementLength + 1000); - ASSERT_LE(ble_advertisement_bytes.size(), - long_ble_advertisement_bytes.size()); - memcpy(long_ble_advertisement_bytes.data(), ble_advertisement_bytes.data(), - ble_advertisement_bytes.size()); - - BleAdvertisement long_ble_advertisement{false, long_ble_advertisement_bytes}; - - EXPECT_TRUE(long_ble_advertisement.IsValid()); - EXPECT_EQ(kVersion, long_ble_advertisement.GetVersion()); - EXPECT_EQ(kPcp, long_ble_advertisement.GetPcp()); - EXPECT_EQ(service_id_hash, long_ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(kEndpointId, long_ble_advertisement.GetEndpointId()); - EXPECT_EQ(endpoint_info, long_ble_advertisement.GetEndpointInfo()); - EXPECT_EQ(kBluetoothMacAddress, - long_ble_advertisement.GetBluetoothMacAddress()); - EXPECT_EQ(kWebRtcState, ble_advertisement.GetWebRtcState()); -} - -TEST(BleAdvertisementTest, ConstructionFromNullBytesFails) { - BleAdvertisement ble_advertisement{false, ByteArray{}}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFromNullBytesFailsForFastAdvertisement) { - BleAdvertisement ble_advertisement{true, ByteArray{}}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFromShortLengthBytesFails) { - // Serialize good data into a good Ble Advertisement. - ByteArray service_id_hash{std::string(kServiceIdHashBytes)}; - ByteArray endpoint_info{std::string(kEndpointName)}; - BleAdvertisement ble_advertisement{ - kVersion, kPcp, - service_id_hash, std::string(kEndpointId), - endpoint_info, std::string(kBluetoothMacAddress), - ByteArray{}, kWebRtcState}; - ByteArray ble_advertisement_bytes(ble_advertisement); - - // Shorten the valid Ble Advertisement. - ByteArray short_ble_advertisement_bytes{ - ble_advertisement_bytes.data(), - BleAdvertisement::kMinAdvertisementLength - 1}; - - BleAdvertisement short_ble_advertisement{false, - short_ble_advertisement_bytes}; - - EXPECT_FALSE(short_ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, - ConstructionFromShortLengthBytesFailsForFastAdvertisement) { - // Serialize good data into a good Ble Advertisement. - ByteArray fast_endpoint_info{std::string(kFastAdvertisementEndpointName)}; - BleAdvertisement ble_advertisement{kVersion, kPcp, std::string(kEndpointId), - fast_endpoint_info, ByteArray{}}; - ByteArray ble_advertisement_bytes(ble_advertisement); - - // Shorten the valid Ble Advertisement. - ByteArray short_ble_advertisement_bytes{ - ble_advertisement_bytes.data(), - BleAdvertisement::kMinAdvertisementLength - 1}; - - BleAdvertisement short_ble_advertisement{true, short_ble_advertisement_bytes}; - - EXPECT_FALSE(short_ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, - ConstructionFromByesWithWrongEndpointInfoLengthFails) { - // Serialize good data into a good Ble Advertisement. - ByteArray service_id_hash{std::string(kServiceIdHashBytes)}; - ByteArray endpoint_info{std::string(kEndpointName)}; - BleAdvertisement ble_advertisement{ - kVersion, kPcp, - service_id_hash, std::string(kEndpointId), - endpoint_info, std::string(kBluetoothMacAddress), - ByteArray{}, kWebRtcState}; - ByteArray ble_advertisement_bytes(ble_advertisement); - - // Corrupt the EndpointNameLength bits. - std::string corrupt_ble_advertisement_string(ble_advertisement_bytes); - corrupt_ble_advertisement_string[8] ^= 0x0FF; - ByteArray corrupt_ble_advertisement_bytes(corrupt_ble_advertisement_string); - - BleAdvertisement corrupt_ble_advertisement{false, - corrupt_ble_advertisement_bytes}; - - EXPECT_FALSE(corrupt_ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, - ConstructionFromByesWithWrongEndpointInfoLengthFailsForFastAdvertisement) { - // Serialize good data into a good Ble Advertisement. - ByteArray fast_endpoint_info{std::string(kFastAdvertisementEndpointName)}; - BleAdvertisement ble_advertisement{kVersion, kPcp, std::string(kEndpointId), - fast_endpoint_info, ByteArray{}}; - ByteArray ble_advertisement_bytes = ByteArray(ble_advertisement); - - // Corrupt the EndpointInfoLength bits. - std::string corrupt_ble_advertisement_string(ble_advertisement_bytes); - corrupt_ble_advertisement_string[5] ^= 0x0FF; - ByteArray corrupt_ble_advertisement_bytes(corrupt_ble_advertisement_string); - - BleAdvertisement corrupt_ble_advertisement{true, - corrupt_ble_advertisement_bytes}; - - EXPECT_FALSE(corrupt_ble_advertisement.IsValid()); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/ble_endpoint_channel.cc b/chromium/third_party/nearby/src/cpp/core/internal/ble_endpoint_channel.cc deleted file mode 100644 index 5cf3bc2bef0..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/ble_endpoint_channel.cc +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/ble_endpoint_channel.h" - -#include <string> - -#include "platform/public/ble.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { - -namespace { - -OutputStream* GetOutputStreamOrNull(BleSocket& socket) { - if (socket.GetRemotePeripheral().IsValid()) return &socket.GetOutputStream(); - return nullptr; -} - -InputStream* GetInputStreamOrNull(BleSocket& socket) { - if (socket.GetRemotePeripheral().IsValid()) return &socket.GetInputStream(); - return nullptr; -} - -} // namespace - -BleEndpointChannel::BleEndpointChannel(const std::string& channel_name, - BleSocket socket) - : BaseEndpointChannel(channel_name, GetInputStreamOrNull(socket), - GetOutputStreamOrNull(socket)), - ble_socket_(std::move(socket)) {} - -proto::connections::Medium BleEndpointChannel::GetMedium() const { - return proto::connections::Medium::BLE; -} - -int BleEndpointChannel::GetMaxTransmitPacketSize() const { - return kDefaultBleMaxTransmitPacketSize; -} - -void BleEndpointChannel::CloseImpl() { - auto status = ble_socket_.Close(); - if (!status.Ok()) { - NEARBY_LOGS(INFO) - << "Failed to close underlying socket for BleEndpointChannel " - << GetName() << ": exception=" << status.value; - } -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/ble_endpoint_channel.h b/chromium/third_party/nearby/src/cpp/core/internal/ble_endpoint_channel.h deleted file mode 100644 index 18c6954e4d9..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/ble_endpoint_channel.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_BLE_ENDPOINT_CHANNEL_H_ -#define CORE_INTERNAL_BLE_ENDPOINT_CHANNEL_H_ - -#include "core/internal/base_endpoint_channel.h" -#include "platform/public/ble.h" - -namespace location { -namespace nearby { -namespace connections { - -class BleEndpointChannel final : public BaseEndpointChannel { - public: - // Creates both outgoing and incoming Ble channels. - BleEndpointChannel(const std::string& channel_name, BleSocket socket); - - proto::connections::Medium GetMedium() const override; - - int GetMaxTransmitPacketSize() const override; - - private: - static constexpr int kDefaultBleMaxTransmitPacketSize = 512; // 512 bytes - - void CloseImpl() override; - - BleSocket ble_socket_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_BLE_ENDPOINT_CHANNEL_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_bwu_handler.cc b/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_bwu_handler.cc deleted file mode 100644 index 24186c2dcfd..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_bwu_handler.cc +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/bluetooth_bwu_handler.h" - -#include "absl/functional/bind_front.h" -#include "core/internal/bluetooth_endpoint_channel.h" -#include "core/internal/client_proxy.h" -#include "core/internal/offline_frames.h" - -// Manages the Bluetooth-specific methods needed to upgrade an {@link -// EndpointChannel}. - -namespace location { -namespace nearby { -namespace connections { - -BluetoothBwuHandler::BluetoothBwuHandler( - Mediums& mediums, EndpointChannelManager& channel_manager, - BwuNotifications notifications) - : BaseBwuHandler(channel_manager, std::move(notifications)), - mediums_(mediums) {} - -void BluetoothBwuHandler::Revert() { - for (const std::string& service_id : active_service_ids_) { - bluetooth_medium_.StopAcceptingConnections(service_id); - } - active_service_ids_.clear(); - NEARBY_LOG(INFO, - "BluetoothBwuHandler successfully reverted all Bluetooth state."); -} - -// Accept Connection Callback. -// Notifies that the remote party called BluetoothClassic::Connect() -// for this socket. -void BluetoothBwuHandler::OnIncomingBluetoothConnection( - ClientProxy* client, const std::string& service_id, - BluetoothSocket socket) { - auto channel = - absl::make_unique<BluetoothEndpointChannel>(service_id, socket); - std::unique_ptr<IncomingSocketConnection> connection{ - new IncomingSocketConnection{ - .socket = - std::make_unique<BluetoothIncomingSocket>(service_id, socket), - .channel = std::move(channel), - }}; - bwu_notifications_.incoming_connection_cb(client, std::move(connection)); -} - -// Called by BWU initiator. BT Medium is set up, and BWU request is prepared, -// with necessary info (service_id, MAC address) for remote party to perform -// discovery. -ByteArray BluetoothBwuHandler::InitializeUpgradedMediumForEndpoint( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id) { - std::string upgrade_service_id = Utils::WrapUpgradeServiceId(service_id); - - std::string mac_address = bluetooth_medium_.GetMacAddress(); - if (mac_address.empty()) { - return {}; - } - - if (!bluetooth_medium_.IsAcceptingConnections(upgrade_service_id)) { - if (!bluetooth_medium_.StartAcceptingConnections( - upgrade_service_id, - { - .accepted_cb = absl::bind_front( - &BluetoothBwuHandler::OnIncomingBluetoothConnection, this, - client, service_id), - })) { - NEARBY_LOGS(ERROR) << "BluetoothBwuHandler couldn't initiate the " - "BLUETOOTH upgrade for endpoint " - << endpoint_id - << " because it failed to start listening for " - "incoming Bluetooth connections."; - - return {}; - } - NEARBY_LOGS(VERBOSE) - << "BluetoothBwuHandler successfully started listening for incoming " - "Bluetooth connections on serviceid=" - << upgrade_service_id << " while upgrading endpoint " << endpoint_id; - } - // cache service ID to revert - active_service_ids_.emplace(upgrade_service_id); - - return parser::ForBwuBluetoothPathAvailable(upgrade_service_id, mac_address); -} - -// Called by BWU target. Retrieves a new medium info from incoming message, -// and establishes connection over BT using this info. -// Returns a channel ready to exchange data or nullptr on error. -std::unique_ptr<EndpointChannel> -BluetoothBwuHandler::CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) { - const UpgradePathInfo::BluetoothCredentials& bluetooth_credentials = - upgrade_path_info.bluetooth_credentials(); - if (!bluetooth_credentials.has_service_name() || - !bluetooth_credentials.has_mac_address()) { - NEARBY_LOG(ERROR, "BluetoothBwuHandler failed to parse UpgradePathInfo."); - return nullptr; - } - - const std::string& service_name = bluetooth_credentials.service_name(); - const std::string& mac_address = bluetooth_credentials.mac_address(); - - NEARBY_LOGS(VERBOSE) << "BluetoothBwuHandler is attempting to connect to " - "available Bluetooth device " - << service_name << ", " << mac_address - << ") for endpoint " << endpoint_id; - - BluetoothDevice device = bluetooth_medium_.GetRemoteDevice(mac_address); - if (!device.IsValid()) { - NEARBY_LOGS(ERROR) - << "BluetoothBwuHandler failed to derive a valid Bluetooth device " - "from the MAC address (" - << mac_address << ") for endpoint " << endpoint_id; - return nullptr; - } - - BluetoothSocket socket = bluetooth_medium_.Connect( - device, service_name, client->GetCancellationFlag(endpoint_id)); - if (!socket.IsValid()) { - NEARBY_LOGS(ERROR) - << "BluetoothBwuHandler failed to connect to the Bluetooth device (" - << service_name << ", " << mac_address << ") for endpoint " - << endpoint_id; - return nullptr; - } - - NEARBY_LOGS(VERBOSE) - << "BluetoothBwuHandler successfully connected to Bluetooth device (" - << service_name << ", " << mac_address << ") while upgrading endpoint " - << endpoint_id; - - auto channel = - std::make_unique<BluetoothEndpointChannel>(service_name, socket); - if (channel == nullptr) { - NEARBY_LOGS(ERROR) - << "BluetoothBwuHandler failed to create Bluetooth endpoint " - "channel to the Bluetooth device (" - << service_name << ", " << mac_address << ") for endpoint " - << endpoint_id; - socket.Close(); - return nullptr; - } - - return channel; -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_bwu_handler.h b/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_bwu_handler.h deleted file mode 100644 index d39aa55df30..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_bwu_handler.h +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_BLUETOOTH_BWU_HANDLER_H_ -#define CORE_INTERNAL_BLUETOOTH_BWU_HANDLER_H_ - -#include <string> - -#include "core/internal/base_bwu_handler.h" -#include "core/internal/client_proxy.h" -#include "core/internal/mediums/mediums.h" -#include "core/internal/mediums/utils.h" -#include "platform/public/bluetooth_classic.h" -#include "platform/public/count_down_latch.h" - -namespace location { -namespace nearby { -namespace connections { - -// Defines the set of methods that need to be implemented to handle the -// per-Medium-specific operations needed to upgrade an EndpointChannel. -class BluetoothBwuHandler : public BaseBwuHandler { - public: - BluetoothBwuHandler(Mediums& mediums, EndpointChannelManager& channel_manager, - BwuNotifications notifications); - ~BluetoothBwuHandler() override = default; - - private: - constexpr static const int kServiceIdLength = 10; - - // Implements BaseBwuHandler: - // Reverts any changes made to the device in the process of upgrading - // endpoints. - void Revert() override; - - // Cleans up in-progress upgrades after endpoint disconnection. - void OnEndpointDisconnect(ClientProxy* client, - const std::string& endpoint_id) override {} - - void OnIncomingBluetoothConnection(ClientProxy* client, - const std::string& service_id, - BluetoothSocket socket); - - class BluetoothIncomingSocket : public IncomingSocket { - public: - explicit BluetoothIncomingSocket(const std::string& name, - BluetoothSocket socket) - : name_(name), socket_(socket) {} - ~BluetoothIncomingSocket() override = default; - std::string ToString() override { return name_; } - void Close() override { socket_.Close(); } - - private: - std::string name_; - BluetoothSocket socket_; - }; - - // First part of InitiateBwuForEndpoint implementation; - // returns a BWU request to remote party as byte array. - ByteArray InitializeUpgradedMediumForEndpoint( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id) override; - - // Invoked from OnBwuNegotiationFrame. - std::unique_ptr<EndpointChannel> CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) override; - - // Returns the upgrade medium of the BwuHandler. - // @BwuHandlerThread - Medium GetUpgradeMedium() const override { return Medium::BLUETOOTH; } - - Mediums& mediums_; - absl::flat_hash_set<std::string> active_service_ids_; - BluetoothRadio& bluetooth_radio_{mediums_.GetBluetoothRadio()}; - BluetoothClassic& bluetooth_medium_{mediums_.GetBluetoothClassic()}; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_BLUETOOTH_BWU_HANDLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_device_name.cc b/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_device_name.cc deleted file mode 100644 index 45f5a6cabd4..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_device_name.cc +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/bluetooth_device_name.h" - -#include <inttypes.h> - -#include <cstring> -#include <utility> - -#include "absl/strings/escaping.h" -#include "absl/strings/str_cat.h" -#include "platform/base/base64_utils.h" -#include "platform/base/base_input_stream.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { - -BluetoothDeviceName::BluetoothDeviceName(Version version, Pcp pcp, - absl::string_view endpoint_id, - const ByteArray& service_id_hash, - const ByteArray& endpoint_info, - const ByteArray& uwb_address, - WebRtcState web_rtc_state) { - if (version != Version::kV1 || endpoint_id.empty() || - endpoint_id.length() != kEndpointIdLength || - service_id_hash.size() != kServiceIdHashLength) { - return; - } - switch (pcp) { - case Pcp::kP2pCluster: // Fall through - case Pcp::kP2pStar: // Fall through - case Pcp::kP2pPointToPoint: - break; - default: - return; - } - - version_ = version; - pcp_ = pcp; - endpoint_id_ = std::string(endpoint_id); - service_id_hash_ = service_id_hash; - endpoint_info_ = endpoint_info; - uwb_address_ = uwb_address; - web_rtc_state_ = web_rtc_state; -} - -BluetoothDeviceName::BluetoothDeviceName( - absl::string_view bluetooth_device_name_string) { - ByteArray bluetooth_device_name_bytes = - Base64Utils::Decode(bluetooth_device_name_string); - if (bluetooth_device_name_bytes.Empty()) { - return; - } - - if (bluetooth_device_name_bytes.size() < kMinBluetoothDeviceNameLength) { - NEARBY_LOG(INFO, - "Cannot deserialize BluetoothDeviceName: expecting min %d raw " - "bytes, got %" PRIu64, - kMinBluetoothDeviceNameLength, - bluetooth_device_name_bytes.size()); - return; - } - - BaseInputStream base_input_stream{bluetooth_device_name_bytes}; - // The first 1 byte is supposed to be the version and pcp. - auto version_and_pcp_byte = static_cast<char>(base_input_stream.ReadUint8()); - // The upper 3 bits are supposed to be the version. - version_ = - static_cast<Version>((version_and_pcp_byte & kVersionBitmask) >> 5); - if (version_ != Version::kV1) { - NEARBY_LOG(INFO, - "Cannot deserialize BluetoothDeviceName: unsupported version=%d", - version_); - return; - } - // The lower 5 bits are supposed to be the Pcp. - pcp_ = static_cast<Pcp>(version_and_pcp_byte & kPcpBitmask); - switch (pcp_) { - case Pcp::kP2pCluster: // Fall through - case Pcp::kP2pStar: // Fall through - case Pcp::kP2pPointToPoint: - break; - default: - NEARBY_LOG( - INFO, "Cannot deserialize BluetoothDeviceName: unsupported V1 PCP %d", - pcp_); - return; - } - - // The next 4 bytes are supposed to be the endpoint_id. - endpoint_id_ = std::string{base_input_stream.ReadBytes(kEndpointIdLength)}; - - // The next 3 bytes are supposed to be the service_id_hash. - service_id_hash_ = base_input_stream.ReadBytes(kServiceIdHashLength); - - // The next 1 byte is field containning WebRtc state. - auto field_byte = static_cast<char>(base_input_stream.ReadUint8()); - web_rtc_state_ = (field_byte & kWebRtcConnectableFlagBitmask) == 1 - ? WebRtcState::kConnectable - : WebRtcState::kUnconnectable; - - // The next 6 bytes are supposed to be reserved, and can be left - // untouched. - base_input_stream.ReadBytes(kReservedLength); - - // The next 1 byte is supposed to be the length of the endpoint_info. - std::uint32_t expected_endpoint_info_length = base_input_stream.ReadUint8(); - - // The rest bytes are supposed to be the endpoint_info - endpoint_info_ = base_input_stream.ReadBytes(expected_endpoint_info_length); - if (endpoint_info_.Empty() || - endpoint_info_.size() != expected_endpoint_info_length) { - NEARBY_LOG(INFO, - "Cannot deserialize BluetoothDeviceName: expected " - "endpoint info to be %d bytes, got %" PRIu64, - expected_endpoint_info_length, endpoint_info_.size()); - - // Clear enpoint_id for validadity. - endpoint_id_.clear(); - return; - } - - // If the input stream has extra bytes, it's for UWB address. The first byte - // is the address length. It can be 2-byte short address or 8-byte extended - // address. - if (base_input_stream.IsAvailable(1)) { - // The next 1 byte is supposed to be the length of the uwb_address. - std::uint32_t expected_uwb_address_length = base_input_stream.ReadUint8(); - // If the length of usb_address is not zero, then retrieve it. - if (expected_uwb_address_length != 0) { - uwb_address_ = base_input_stream.ReadBytes(expected_uwb_address_length); - if (uwb_address_.Empty() || - uwb_address_.size() != expected_uwb_address_length) { - NEARBY_LOG(INFO, - "Cannot deserialize BluetoothDeviceName: " - "expected uwbAddress size to be %d bytes, got %" PRIu64, - expected_uwb_address_length, uwb_address_.size()); - - // Clear enpoint_id for validadity. - endpoint_id_.clear(); - return; - } - } - } -} - -BluetoothDeviceName::operator std::string() const { - if (!IsValid()) { - return ""; - } - - // The upper 3 bits are the Version. - auto version_and_pcp_byte = static_cast<char>( - (static_cast<uint32_t>(Version::kV1) << 5) & kVersionBitmask); - // The lower 5 bits are the PCP. - version_and_pcp_byte |= - static_cast<char>(static_cast<uint32_t>(pcp_) & kPcpBitmask); - - // A byte contains WebRtcState state. - int web_rtc_connectable_flag = - (web_rtc_state_ == WebRtcState::kConnectable) ? 1 : 0; - char field_byte = static_cast<char>(web_rtc_connectable_flag) & - kWebRtcConnectableFlagBitmask; - - ByteArray reserved_bytes{kReservedLength}; - - ByteArray usable_endpoint_info(endpoint_info_); - if (endpoint_info_.size() > kMaxEndpointInfoLength) { - NEARBY_LOG(INFO, - "While serializing Advertisement, truncating Endpoint Name %s " - "(%lu bytes) down to %d bytes", - absl::BytesToHexString(endpoint_info_.data()).c_str(), - endpoint_info_.size(), kMaxEndpointInfoLength); - usable_endpoint_info.SetData(endpoint_info_.data(), kMaxEndpointInfoLength); - } - - // clang-format off - std::string out = absl::StrCat(std::string(1, version_and_pcp_byte), - endpoint_id_, - std::string(service_id_hash_), - std::string(1, field_byte), - std::string(reserved_bytes), - std::string(1, usable_endpoint_info.size()), - std::string(usable_endpoint_info)); - // clang-format on - - // If UWB address is available, attach it at the end. - if (!uwb_address_.Empty()) { - absl::StrAppend(&out, std::string(1, uwb_address_.size())); - absl::StrAppend(&out, std::string(uwb_address_)); - } - - return Base64Utils::Encode(ByteArray{std::move(out)}); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_device_name.h b/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_device_name.h deleted file mode 100644 index 44e3c07d1cb..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_device_name.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_BLUETOOTH_DEVICE_NAME_H_ -#define CORE_INTERNAL_BLUETOOTH_DEVICE_NAME_H_ - -#include <cstdint> - -#include "absl/strings/string_view.h" -#include "core/internal/base_pcp_handler.h" -#include "core/internal/pcp.h" -#include "platform/base/byte_array.h" - -namespace location { -namespace nearby { -namespace connections { - -// Represents the format of the Bluetooth device name used in Advertising + -// Discovery. -// -// <p>See go/nearby-offline-data-interchange-formats for the specification. -class BluetoothDeviceName { - public: - // Versions of the BluetoothDeviceName. - enum class Version { - kUndefined = 0, - kV1 = 1, - // Version is only allocated 3 bits in the BluetoothDeviceName, so this - // can never go beyond V7. - }; - - static constexpr int kServiceIdHashLength = 3; - - BluetoothDeviceName() = default; - BluetoothDeviceName(Version version, Pcp pcp, absl::string_view endpoint_id, - const ByteArray& service_id_hash, - const ByteArray& endpoint_info, - const ByteArray& uwb_address, WebRtcState web_rtc_state); - explicit BluetoothDeviceName(absl::string_view bluetooth_device_name_string); - BluetoothDeviceName(const BluetoothDeviceName&) = default; - BluetoothDeviceName& operator=(const BluetoothDeviceName&) = default; - BluetoothDeviceName(BluetoothDeviceName&&) = default; - BluetoothDeviceName& operator=(BluetoothDeviceName&&) = default; - ~BluetoothDeviceName() = default; - - explicit operator std::string() const; - - bool IsValid() const { return !endpoint_id_.empty(); } - Version GetVersion() const { return version_; } - Pcp GetPcp() const { return pcp_; } - std::string GetEndpointId() const { return endpoint_id_; } - ByteArray GetServiceIdHash() const { return service_id_hash_; } - ByteArray GetEndpointInfo() const { return endpoint_info_; } - ByteArray GetUwbAddress() const { return uwb_address_; } - WebRtcState GetWebRtcState() const { return web_rtc_state_; } - - private: - static constexpr int kEndpointIdLength = 4; - static constexpr int kReservedLength = 6; - static constexpr int kMaxEndpointInfoLength = 131; - static constexpr int kMinBluetoothDeviceNameLength = 16; - - static constexpr int kVersionBitmask = 0x0E0; - static constexpr int kPcpBitmask = 0x01F; - static constexpr int kEndpointNameLengthBitmask = 0x0FF; - static constexpr int kWebRtcConnectableFlagBitmask = 0x01; - - Version version_{Version::kUndefined}; - Pcp pcp_{Pcp::kUnknown}; - std::string endpoint_id_; - ByteArray service_id_hash_; - ByteArray endpoint_info_; - // TODO(b/169550050): Define UWB address field. - ByteArray uwb_address_; - WebRtcState web_rtc_state_{WebRtcState::kUndefined}; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_BLUETOOTH_DEVICE_NAME_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_device_name_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_device_name_test.cc deleted file mode 100644 index f4b82b8891e..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_device_name_test.cc +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/bluetooth_device_name.h" - -#include <cstring> -#include <memory> - -#include "gtest/gtest.h" -#include "platform/base/base64_utils.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -constexpr BluetoothDeviceName::Version kVersion = - BluetoothDeviceName::Version::kV1; -constexpr Pcp kPcp = Pcp::kP2pCluster; -constexpr absl::string_view kEndPointID{"AB12"}; -constexpr absl::string_view kServiceIDHashBytes{"\x0a\x0b\x0c"}; -constexpr absl::string_view kEndPointName{"RAWK + ROWL!"}; -constexpr WebRtcState kWebRtcState = WebRtcState::kConnectable; - -// TODO(b/169550050): Implement UWBAddress. -TEST(BluetoothDeviceNameTest, ConstructionWorks) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - BluetoothDeviceName bluetooth_device_name{ - kVersion, kPcp, kEndPointID, service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_TRUE(bluetooth_device_name.IsValid()); - EXPECT_EQ(kVersion, bluetooth_device_name.GetVersion()); - EXPECT_EQ(kPcp, bluetooth_device_name.GetPcp()); - EXPECT_EQ(kEndPointID, bluetooth_device_name.GetEndpointId()); - EXPECT_EQ(service_id_hash, bluetooth_device_name.GetServiceIdHash()); - EXPECT_EQ(endpoint_info, bluetooth_device_name.GetEndpointInfo()); - EXPECT_EQ(kWebRtcState, bluetooth_device_name.GetWebRtcState()); -} - -TEST(BluetoothDeviceNameTest, ConstructionWorksWithEmptyEndpointName) { - ByteArray empty_endpoint_info; - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - BluetoothDeviceName bluetooth_device_name{kVersion, - kPcp, - kEndPointID, - service_id_hash, - empty_endpoint_info, - ByteArray{}, - kWebRtcState}; - - EXPECT_TRUE(bluetooth_device_name.IsValid()); - EXPECT_EQ(kVersion, bluetooth_device_name.GetVersion()); - EXPECT_EQ(kPcp, bluetooth_device_name.GetPcp()); - EXPECT_EQ(kEndPointID, bluetooth_device_name.GetEndpointId()); - EXPECT_EQ(service_id_hash, bluetooth_device_name.GetServiceIdHash()); - EXPECT_EQ(empty_endpoint_info, bluetooth_device_name.GetEndpointInfo()); - EXPECT_EQ(kWebRtcState, bluetooth_device_name.GetWebRtcState()); -} - -TEST(BluetoothDeviceNameTest, ConstructionFailsWithBadVersion) { - auto bad_version = static_cast<BluetoothDeviceName::Version>(666); - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - BluetoothDeviceName bluetooth_device_name{ - bad_version, kPcp, kEndPointID, service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(bluetooth_device_name.IsValid()); -} - -TEST(BluetoothDeviceNameTest, ConstructionFailsWithBadPcp) { - auto bad_pcp = static_cast<Pcp>(666); - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - BluetoothDeviceName bluetooth_device_name{ - kVersion, bad_pcp, kEndPointID, service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(bluetooth_device_name.IsValid()); -} - -TEST(BluetoothDeviceNameTest, ConstructionFailsWithShortEndpointId) { - std::string short_endpoint_id("AB1"); - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - BluetoothDeviceName bluetooth_device_name{ - kVersion, kPcp, short_endpoint_id, service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(bluetooth_device_name.IsValid()); -} - -TEST(BluetoothDeviceNameTest, ConstructionFailsWithLongEndpointId) { - std::string long_endpoint_id("AB12X"); - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - BluetoothDeviceName bluetooth_device_name{ - kVersion, kPcp, long_endpoint_id, service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(bluetooth_device_name.IsValid()); -} - -TEST(BluetoothDeviceNameTest, ConstructionFailsWithShortServiceIdHash) { - char short_service_id_hash_bytes[] = "\x0a\x0b"; - - ByteArray short_service_id_hash{short_service_id_hash_bytes}; - ByteArray endpoint_info{std::string(kEndPointName)}; - BluetoothDeviceName bluetooth_device_name{ - kVersion, kPcp, kEndPointID, short_service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(bluetooth_device_name.IsValid()); -} - -TEST(BluetoothDeviceNameTest, ConstructionFailsWithLongServiceIdHash) { - char long_service_id_hash_bytes[] = "\x0a\x0b\x0c\x0d"; - - ByteArray long_service_id_hash{long_service_id_hash_bytes}; - ByteArray endpoint_info{std::string(kEndPointName)}; - BluetoothDeviceName bluetooth_device_name{ - kVersion, kPcp, kEndPointID, long_service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(bluetooth_device_name.IsValid()); -} - -TEST(BluetoothDeviceNameTest, ConstructionFailsWithShortStringLength) { - char bluetooth_device_name_string[] = "X"; - - ByteArray bluetooth_device_name_bytes{bluetooth_device_name_string}; - BluetoothDeviceName bluetooth_device_name{ - Base64Utils::Encode(bluetooth_device_name_bytes)}; - - EXPECT_FALSE(bluetooth_device_name.IsValid()); -} - -TEST(BluetoothDeviceNameTest, ConstructionFailsWithWrongEndpointNameLength) { - // Serialize good data into a good Bluetooth Device Name. - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - BluetoothDeviceName bluetooth_device_name{ - kVersion, kPcp, kEndPointID, service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - auto bluetooth_device_name_string = std::string(bluetooth_device_name); - - // Base64-decode the good Bluetooth Device Name. - ByteArray bluetooth_device_name_bytes = - Base64Utils::Decode(bluetooth_device_name_string); - // Corrupt the EndpointNameLength bits (120-127) by reversing all of them. - std::string corrupt_string(bluetooth_device_name_bytes.data(), - bluetooth_device_name_bytes.size()); - corrupt_string[15] ^= 0x0FF; - // Base64-encode the corrupted bytes into a corrupt Bluetooth Device Name. - ByteArray corrupt_bluetooth_device_name_bytes{corrupt_string.data(), - corrupt_string.size()}; - std::string corrupt_bluetooth_device_name_string( - Base64Utils::Encode(corrupt_bluetooth_device_name_bytes)); - - // And deserialize the corrupt Bluetooth Device Name. - BluetoothDeviceName corrupt_bluetooth_device_name( - corrupt_bluetooth_device_name_string); - - EXPECT_FALSE(corrupt_bluetooth_device_name.IsValid()); -} - -TEST(BluetoothDeviceNameTest, CanParseGeneratedName) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - // Build name1 from scratch. - BluetoothDeviceName name1{kVersion, kPcp, kEndPointID, - service_id_hash, endpoint_info, ByteArray{}, - kWebRtcState}; - // Build name2 from string composed from name1. - BluetoothDeviceName name2{std::string(name1)}; - EXPECT_TRUE(name1.IsValid()); - EXPECT_TRUE(name2.IsValid()); - EXPECT_EQ(name1.GetVersion(), name2.GetVersion()); - EXPECT_EQ(name1.GetPcp(), name2.GetPcp()); - EXPECT_EQ(name1.GetEndpointId(), name2.GetEndpointId()); - EXPECT_EQ(name1.GetServiceIdHash(), name2.GetServiceIdHash()); - EXPECT_EQ(name1.GetEndpointInfo(), name2.GetEndpointInfo()); - EXPECT_EQ(name1.GetWebRtcState(), name2.GetWebRtcState()); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_endpoint_channel.cc b/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_endpoint_channel.cc deleted file mode 100644 index 7e38e648f8d..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_endpoint_channel.cc +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/bluetooth_endpoint_channel.h" - -#include <string> - -#include "platform/public/bluetooth_classic.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { - -namespace { - -OutputStream* GetOutputStreamOrNull(BluetoothSocket& socket) { - if (socket.GetRemoteDevice().IsValid()) return &socket.GetOutputStream(); - return nullptr; -} - -InputStream* GetInputStreamOrNull(BluetoothSocket& socket) { - if (socket.GetRemoteDevice().IsValid()) return &socket.GetInputStream(); - return nullptr; -} - -} // namespace - -BluetoothEndpointChannel::BluetoothEndpointChannel( - const std::string& channel_name, BluetoothSocket socket) - : BaseEndpointChannel(channel_name, GetInputStreamOrNull(socket), - GetOutputStreamOrNull(socket)), - bluetooth_socket_(std::move(socket)) {} - -proto::connections::Medium BluetoothEndpointChannel::GetMedium() const { - return proto::connections::Medium::BLUETOOTH; -} - -int BluetoothEndpointChannel::GetMaxTransmitPacketSize() const { - return kDefaultBTMaxTransmitPacketSize; -} - -void BluetoothEndpointChannel::CloseImpl() { - auto status = bluetooth_socket_.Close(); - if (!status.Ok()) { - NEARBY_LOGS(INFO) - << "Failed to close underlying socket for BluetoothEndpointChannel " - << GetName() << ": exception=" << status.value; - } -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_endpoint_channel.h b/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_endpoint_channel.h deleted file mode 100644 index f9059348056..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/bluetooth_endpoint_channel.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_BLUETOOTH_ENDPOINT_CHANNEL_H_ -#define CORE_INTERNAL_BLUETOOTH_ENDPOINT_CHANNEL_H_ - -#include <string> - -#include "core/internal/base_endpoint_channel.h" -#include "platform/public/bluetooth_classic.h" - -namespace location { -namespace nearby { -namespace connections { - -class BluetoothEndpointChannel final : public BaseEndpointChannel { - public: - // Creates both outgoing and incoming BT channels. - BluetoothEndpointChannel(const std::string& channel_name, - BluetoothSocket bluetooth_socket); - - proto::connections::Medium GetMedium() const override; - - int GetMaxTransmitPacketSize() const override; - - private: - static constexpr int kDefaultBTMaxTransmitPacketSize = 1980; // 990 * 2 Bytes - - void CloseImpl() override; - - BluetoothSocket bluetooth_socket_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_BLUETOOTH_ENDPOINT_CHANNEL_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/bwu_handler.h b/chromium/third_party/nearby/src/cpp/core/internal/bwu_handler.h deleted file mode 100644 index c31fa731529..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/bwu_handler.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_BWU_HANDLER_H_ -#define CORE_INTERNAL_BWU_HANDLER_H_ - -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel.h" -#include "core/internal/offline_frames.h" -#include "platform/public/count_down_latch.h" - -namespace location { -namespace nearby { -namespace connections { - -using BwuNegotiationFrame = BandwidthUpgradeNegotiationFrame; - -// Defines the set of methods that need to be implemented to handle the -// per-Medium-specific operations needed to upgrade an EndpointChannel. -class BwuHandler { - public: - using UpgradePathInfo = parser::UpgradePathInfo; - - virtual ~BwuHandler() = default; - - // Called by the Initiator to setup the upgraded medium for this endpoint (if - // that hasn't already been done), and returns a serialized UpgradePathInfo - // that can be sent to the Responder. - // @BwuHandlerThread - virtual ByteArray InitializeUpgradedMediumForEndpoint( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id) = 0; - - // Called to revert any state changed by the Initiator to setup the upgraded - // medium for an endpoint. - // @BwuHandlerThread - virtual void Revert() = 0; - - // Called by the Responder to setup the upgraded medium for this endpoint (if - // that hasn't already been done) using the UpgradePathInfo sent by the - // Initiator, and returns a new EndpointChannel for the upgraded medium. - // @BwuHandlerThread - virtual std::unique_ptr<EndpointChannel> CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) = 0; - - // Returns the upgrade medium of the BwuHandler. - // @BwuHandlerThread - virtual Medium GetUpgradeMedium() const = 0; - virtual void OnEndpointDisconnect(ClientProxy* client, - const std::string& endpoint_id) = 0; - - class IncomingSocket { - public: - virtual ~IncomingSocket() = default; - - virtual std::string ToString() = 0; - virtual void Close() = 0; - }; - - struct IncomingSocketConnection { - std::unique_ptr<IncomingSocket> socket; - std::unique_ptr<EndpointChannel> channel; - }; - - struct BwuNotifications { - std::function<void(ClientProxy* client, - std::unique_ptr<IncomingSocketConnection> connection)> - incoming_connection_cb; - }; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_BWU_HANDLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager.cc b/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager.cc deleted file mode 100644 index f73980fe2b9..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager.cc +++ /dev/null @@ -1,1201 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/bwu_manager.h" - -#include <algorithm> -#include <memory> - -#include "absl/functional/bind_front.h" -#include "absl/time/time.h" -#include "core/internal/bluetooth_bwu_handler.h" -#include "core/internal/bwu_handler.h" -#include "core/internal/offline_frames.h" -#include "core/internal/webrtc_bwu_handler.h" -#include "core/internal/wifi_lan_bwu_handler.h" -#include "platform/base/byte_array.h" -#include "platform/base/feature_flags.h" -#include "platform/public/count_down_latch.h" -#include "proto/connections_enums.pb.h" - -namespace location { -namespace nearby { -namespace connections { - -using ::location::nearby::proto::connections::DisconnectionReason; - -// Required for C++ 14 support in Chrome -constexpr absl::Duration BwuManager::kReadClientIntroductionFrameTimeout; - -BwuManager::BwuManager( - Mediums& mediums, EndpointManager& endpoint_manager, - EndpointChannelManager& channel_manager, - absl::flat_hash_map<Medium, std::unique_ptr<BwuHandler>> handlers, - Config config) - : config_(config), - mediums_(&mediums), - endpoint_manager_(&endpoint_manager), - channel_manager_(&channel_manager) { - if (config_.bandwidth_upgrade_retry_delay == absl::ZeroDuration()) { - if (FeatureFlags::GetInstance().GetFlags().use_exp_backoff_in_bwu_retry) { - config_.bandwidth_upgrade_retry_delay = - FeatureFlags::GetInstance() - .GetFlags() - .bwu_retry_exp_backoff_initial_delay; - } else { - config_.bandwidth_upgrade_retry_delay = absl::Seconds(5); - } - } - if (config_.bandwidth_upgrade_retry_max_delay == absl::ZeroDuration()) { - if (FeatureFlags::GetInstance().GetFlags().use_exp_backoff_in_bwu_retry) { - config_.bandwidth_upgrade_retry_max_delay = - FeatureFlags::GetInstance() - .GetFlags() - .bwu_retry_exp_backoff_maximum_delay; - } else { - config_.bandwidth_upgrade_retry_max_delay = absl::Seconds(10); - } - } - if (config_.allow_upgrade_to.All(false)) { - config_.allow_upgrade_to.web_rtc = true; - } - if (!handlers.empty()) { - handlers_ = std::move(handlers); - } else { - InitBwuHandlers(); - } - - // Register the offline frame processor. - endpoint_manager_->RegisterFrameProcessor( - V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION, this); -} - -BwuManager::~BwuManager() { - NEARBY_LOGS(INFO) << "BwuManager going down"; - Shutdown(); -} - -void BwuManager::InitBwuHandlers() { - // Register the supported concrete BwuMedium implementations. - BwuHandler::BwuNotifications notifications{ - .incoming_connection_cb = - absl::bind_front(&BwuManager::OnIncomingConnection, this), - }; - if (config_.allow_upgrade_to.wifi_lan) { - handlers_.emplace(Medium::WIFI_LAN, - std::make_unique<WifiLanBwuHandler>( - *mediums_, *channel_manager_, notifications)); - } - if (config_.allow_upgrade_to.web_rtc) { - handlers_.emplace(Medium::WEB_RTC, - std::make_unique<WebrtcBwuHandler>( - *mediums_, *channel_manager_, notifications)); - } - if (config_.allow_upgrade_to.bluetooth) { - handlers_.emplace(Medium::BLUETOOTH, - std::make_unique<BluetoothBwuHandler>( - *mediums_, *channel_manager_, notifications)); - } -} - -void BwuManager::Shutdown() { - NEARBY_LOGS(INFO) << "Initiating shutdown of BwuManager."; - - endpoint_manager_->UnregisterFrameProcessor( - V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION, this); - - // Stop all the ongoing Runnables (as gracefully as possible). - alarm_executor_.Shutdown(); - serial_executor_.Shutdown(); - - // After worker threads are down we became exclusive owners of data and - // may access it from current thread. - for (auto& item : previous_endpoint_channels_) { - EndpointChannel* channel = item.second.get(); - if (!channel) continue; - channel->Close(DisconnectionReason::SHUTDOWN); - } - - CancelAllRetryUpgradeAlarms(); - medium_ = Medium::UNKNOWN_MEDIUM; - for (auto& item : handlers_) { - BwuHandler& handler = *item.second; - handler.Revert(); - } - handlers_.clear(); - - NEARBY_LOGS(INFO) << "BwuHandler has shut down."; -} - -// This is the point on the Initiator side where the -// medium_ is set. -void BwuManager::InitiateBwuForEndpoint(ClientProxy* client, - const std::string& endpoint_id, - Medium new_medium) { - NEARBY_LOGS(INFO) << "InitiateBwuForEndpoint for endpoint " << endpoint_id - << " with medium " << new_medium; - RunOnBwuManagerThread("bwu-init", [this, client, endpoint_id, new_medium]() { - Medium proposed_medium = ChooseBestUpgradeMedium( - client->GetUpgradeMediums(endpoint_id).GetMediums(true)); - if (new_medium != Medium::UNKNOWN_MEDIUM) { - proposed_medium = new_medium; - } - auto* handler = SetCurrentBwuHandler(proposed_medium); - if (!handler) { - NEARBY_LOGS(ERROR) - << "BwuManager cannot initiate bandwidth upgrade for endpoint " - << endpoint_id - << " because the current BandwidthUpgradeMedium cannot be deduced."; - return; - } - - if (in_progress_upgrades_.contains(endpoint_id)) { - NEARBY_LOGS(INFO) - << "BwuManager is ignoring bandwidth upgrade for endpoint " - << endpoint_id - << " because we're already upgrading bandwidth for that endpoint."; - - return; - } - CancelRetryUpgradeAlarm(endpoint_id); - - auto channel = channel_manager_->GetChannelForEndpoint(endpoint_id); - Medium channel_medium = - channel ? channel->GetMedium() : Medium::UNKNOWN_MEDIUM; - client->GetAnalyticsRecorder().OnBandwidthUpgradeStarted( - endpoint_id, channel_medium, medium_, proto::connections::INCOMING, - client->GetConnectionToken(endpoint_id)); - if (channel == nullptr) { - NEARBY_LOGS(INFO) - << "BwuManager couldn't complete the upgrade for endpoint " - << endpoint_id - << " because it couldn't find an existing EndpointChannel for it."; - client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, proto::connections::CHANNEL_ERROR, - proto::connections::NETWORK_AVAILABLE); - return; - } - - // Ignore requests where the medium we're upgrading to is the medium we're - // already connected over. This can happen now that Bluetooth is both an - // advertising medium and a potential bandwidth upgrade, and will continue - // to be possible as we add other new advertising mediums like mDNS (WiFi - // LAN). Very specifically, this happens now when a device uses P2P_CLUSTER, - // connects over Bluetooth, and is not connected to LAN. Bluetooth is the - // best medium, and we attempt to upgrade from Bluetooth to Bluetooth. - // if (medium_ == channel->GetMedium()) { - NEARBY_LOGS(INFO) << "BwuManager ignoring the upgrade for endpoint " - << endpoint_id - << " because it is already connected over medium " - << proto::connections::Medium_Name(medium_); - if (medium_ == channel->GetMedium()) { - return; - } - - std::string service_id = client->GetServiceId(); - ByteArray bytes = handler->InitializeUpgradedMediumForEndpoint( - client, service_id, endpoint_id); - - // Because we grab the endpointChannel first thing, it is possible the - // endpointChannel is stale by the time we attempt to write over it. - if (bytes.Empty()) { - NEARBY_LOGS(ERROR) - << "BwuManager couldn't complete the upgrade for endpoint " - << endpoint_id << " to medium " - << proto::connections::Medium_Name(medium_) - << " because it failed to initialize the " - "BWU_NEGOTIATION.UPGRADE_PATH_AVAILABLE OfflineFrame."; - UpgradePathInfo info; - info.set_medium(parser::MediumToUpgradePathInfoMedium(medium_)); - - ProcessUpgradeFailureEvent(client, endpoint_id, info); - client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, proto::connections::RESULT_IO_ERROR, - proto::connections::NETWORK_AVAILABLE); - return; - } - if (!channel->Write(bytes).Ok()) { - NEARBY_LOGS(ERROR) - << "BwuManager couldn't complete the upgrade for endpoint " - << endpoint_id << " to medium " - << proto::connections::Medium_Name(medium_) - << " because it failed to write the " - "BWU_NEGOTIATION.UPGRADE_PATH_AVAILABLE OfflineFrame."; - return; - } - - NEARBY_LOGS(INFO) - << "BwuManager successfully wrote the " - "BWU_NEGOTIATION.UPGRADE_PATH_AVAILABLE OfflineFrame while " - "upgrading endpoint " - << endpoint_id << " to medium" - << proto::connections::Medium_Name(medium_); - in_progress_upgrades_.emplace(endpoint_id, client); - }); -} - -void BwuManager::OnIncomingFrame(OfflineFrame& frame, - const std::string& endpoint_id, - ClientProxy* client, Medium medium) { - NEARBY_LOGS(INFO) << "OnIncomingFrame for endpoint " << endpoint_id - << " with medium " - << proto::connections::Medium_Name(medium); - if (parser::GetFrameType(frame) != V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION) - return; - auto bwu_frame = frame.v1().bandwidth_upgrade_negotiation(); - if (FeatureFlags::GetInstance().GetFlags().enable_async_bandwidth_upgrade) { - RunOnBwuManagerThread( - "bwu-on-incoming-frame", [this, client, endpoint_id, bwu_frame]() { - OnBwuNegotiationFrame(client, bwu_frame, endpoint_id); - }); - } else { - CountDownLatch latch(1); - RunOnBwuManagerThread("bwu-on-incoming-frame", [this, client, endpoint_id, - bwu_frame, &latch]() { - OnBwuNegotiationFrame(client, bwu_frame, endpoint_id); - latch.CountDown(); - }); - latch.Await(); - } -} - -void BwuManager::OnEndpointDisconnect(ClientProxy* client, - const std::string& endpoint_id, - CountDownLatch barrier) { - NEARBY_LOGS(INFO) - << "BwuManager has processed endpoint disconnection for endpoint " - << endpoint_id; - RunOnBwuManagerThread( - "bwu-on-endpoint-disconnect", - [this, client, endpoint_id, barrier]() mutable { - if (medium_ == Medium::UNKNOWN_MEDIUM) { - NEARBY_LOGS(INFO) - << "BwuManager has processed endpoint disconnection for endpoint " - << endpoint_id - << " because there is no current BandwidthUpgradeMedium."; - barrier.CountDown(); - return; - } - - if (handler_) { - handler_->OnEndpointDisconnect(client, endpoint_id); - } - - auto item = previous_endpoint_channels_.extract(endpoint_id); - - if (!item.empty()) { - auto old_channel = item.mapped(); - if (old_channel != nullptr) { - old_channel->Close(DisconnectionReason::SHUTDOWN); - } - } - in_progress_upgrades_.erase(endpoint_id); - retry_delays_.erase(endpoint_id); - CancelRetryUpgradeAlarm(endpoint_id); - - successfully_upgraded_endpoints_.erase(endpoint_id); - - // If this was our very last endpoint: - // - // a) revert all the changes for currentBwuMedium. - // b) reset currentBwuMedium. - if (channel_manager_->GetConnectedEndpointsCount() <= 1) { - Revert(); - } - barrier.CountDown(); - }); -} - -BwuHandler* BwuManager::SetCurrentBwuHandler(Medium medium) { - NEARBY_LOGS(INFO) << "SetCurrentBwuHandler to medium " - << proto::connections::Medium_Name(medium); - handler_ = nullptr; - medium_ = medium; - if (medium != Medium::UNKNOWN_MEDIUM) { - auto item = handlers_.find(medium); - if (item != handlers_.end()) { - handler_ = item->second.get(); - } - } - return handler_; -} - -void BwuManager::Revert() { - NEARBY_LOGS(INFO) << "Revert reseting medium " - << proto::connections::Medium_Name(medium_); - if (handler_) { - handler_->Revert(); - handler_ = nullptr; - } - medium_ = Medium::UNKNOWN_MEDIUM; -} - -void BwuManager::OnBwuNegotiationFrame(ClientProxy* client, - const BwuNegotiationFrame frame, - const string& endpoint_id) { - NEARBY_LOGS(INFO) << "BwuManager process incoming OfflineFrame for endpoint " - << endpoint_id; - switch (frame.event_type()) { - case BwuNegotiationFrame::UPGRADE_PATH_AVAILABLE: - ProcessBwuPathAvailableEvent(client, endpoint_id, - frame.upgrade_path_info()); - break; - case BwuNegotiationFrame::UPGRADE_FAILURE: - ProcessUpgradeFailureEvent(client, endpoint_id, - frame.upgrade_path_info()); - break; - case BwuNegotiationFrame::LAST_WRITE_TO_PRIOR_CHANNEL: - ProcessLastWriteToPriorChannelEvent(client, endpoint_id); - break; - case BwuNegotiationFrame::SAFE_TO_CLOSE_PRIOR_CHANNEL: - ProcessSafeToClosePriorChannelEvent(client, endpoint_id); - break; - default: - NEARBY_LOGS(WARNING) - << "BwuManager can't process unknown incoming OfflineFrame of type " - << frame.event_type() << ", ignoring it."; - break; - } -} - -void BwuManager::OnIncomingConnection( - ClientProxy* client, - std::unique_ptr<BwuHandler::IncomingSocketConnection> mutable_connection) { - NEARBY_LOGS(INFO) << "BwuManager process incoming connection service_id=" - << client->GetServiceId(); - std::shared_ptr<BwuHandler::IncomingSocketConnection> connection( - mutable_connection.release()); - RunOnBwuManagerThread( - "bwu-on-incoming-connection", [this, client, connection]() { - absl::Time connection_attempt_start_time = - SystemClock::ElapsedRealtime(); - EndpointChannel* channel = connection->channel.get(); - if (channel == nullptr) { - NEARBY_LOGS(ERROR) - << "BwuManager failed to create new EndpointChannel for incoming " - "socket."; - connection->socket->Close(); - AttemptToRecordBandwidthUpgradeErrorForUnknownEndpoint( - proto::connections::MEDIUM_ERROR, - proto::connections::SOCKET_CREATION); - return; - } - - NEARBY_LOGS(VERBOSE) - << "BwuManager successfully created new EndpointChannel for " - "incoming socket"; - - ClientIntroduction introduction; - if (!ReadClientIntroductionFrame(channel, introduction)) { - // This was never a fully EstablishedConnection, no need to provide a - // closure reason. - channel->Close(); - NEARBY_LOGS(ERROR) - << "BwuManager failed to read " - "BWU_NEGOTIATION.CLIENT_INTRODUCTION OfflineFrame from " - "newly-created EndpointChannel " - << channel->GetName() - << ", so the EndpointChannel was discarded."; - return; - } - - if (!WriteClientIntroductionAckFrame(channel)) { - // This was never a fully EstablishedConnection, no need to provide a - // closure reason. - channel->Close(); - return; - } - - NEARBY_LOGS(VERBOSE) << "BwuManager successfully received " - "BWU_NEGOTIATION.CLIENT_INTRODUCTION " - "OfflineFrame on EndpointChannel " - << channel->GetName(); - - const std::string& endpoint_id = introduction.endpoint_id(); - ClientProxy* mapped_client; - const auto item = in_progress_upgrades_.find(endpoint_id); - if (item == in_progress_upgrades_.end()) return; - mapped_client = item->second; - CancelRetryUpgradeAlarm(endpoint_id); - if (mapped_client == nullptr) { - // This was never a fully EstablishedConnection, no need to provide a - // closure reason. - channel->Close(); - return; - } - - CHECK(client == mapped_client); - - // The ConnectionAttempt has now succeeded, so record it as such. - client->GetAnalyticsRecorder().OnIncomingConnectionAttempt( - proto::connections::UPGRADE, channel->GetMedium(), - proto::connections::RESULT_SUCCESS, - SystemClock::ElapsedRealtime() - connection_attempt_start_time, - client->GetConnectionToken(endpoint_id)); - - // Use the introductory client information sent over to run the upgrade - // protocol. - RunUpgradeProtocol(mapped_client, endpoint_id, - std::move(connection->channel)); - }); -} - -void BwuManager::RunOnBwuManagerThread(const std::string& name, - Runnable runnable) { - serial_executor_.Execute(name, std::move(runnable)); -} - -void BwuManager::RunUpgradeProtocol( - ClientProxy* client, const std::string& endpoint_id, - std::unique_ptr<EndpointChannel> new_channel) { - NEARBY_LOGS(INFO) << "RunUpgradeProtocol new channel @" << new_channel.get() - << " name: " << new_channel->GetName() - << ", medium: " << new_channel->GetMedium(); - // First, register this new EndpointChannel as *the* EndpointChannel to use - // for this endpoint here onwards. NOTE: We pause this new EndpointChannel - // until we've completely drained the old EndpointChannel to avoid out of - // order reads on the other side. This is a consequence of using the same - // UKEY2 context for both the previous and new EndpointChannels. UKEY2 uses - // sequence numbers for writes and reads, and simultaneously sending Payloads - // on the new channel and control messages on the old channel cause the other - // side to read messages out of sequence - new_channel->Pause(); - auto old_channel = channel_manager_->GetChannelForEndpoint(endpoint_id); - if (!old_channel) { - NEARBY_LOGS(INFO) - << "BwuManager didn't find a previous EndpointChannel for " - << endpoint_id - << " when registering the new EndpointChannel, short-circuiting the " - "upgrade protocol."; - client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, proto::connections::CHANNEL_ERROR, - proto::connections::PRIOR_ENDPOINT_CHANNEL); - return; - } - channel_manager_->ReplaceChannelForEndpoint(client, endpoint_id, - std::move(new_channel)); - - // Next, initiate a clean shutdown for the previous EndpointChannel used for - // this endpoint by telling the remote device that it will not receive any - // more writes over that EndpointChannel. - if (!old_channel->Write(parser::ForBwuLastWrite()).Ok()) { - NEARBY_LOGS(ERROR) - << "BwuManager failed to write " - "BWU_NEGOTIATION.LAST_WRITE_TO_PRIOR_CHANNEL OfflineFrame to " - "endpoint " - << endpoint_id << ", short-circuiting the upgrade protocol."; - client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, proto::connections::RESULT_IO_ERROR, - proto::connections::LAST_WRITE_TO_PRIOR_CHANNEL); - return; - } - NEARBY_LOGS(VERBOSE) << "BwuManager successfully wrote " - "BWU_NEGOTIATION.LAST_WRITE_TO_PRIOR_CHANNEL " - "OfflineFrame while upgrading endpoint " - << endpoint_id; - - // The remainder of this clean shutdown for the previous EndpointChannel will - // continue when we receive a corresponding - // BANDWIDTH_UPGRADE_NEGOTIATION.LAST_WRITE_TO_PRIOR_CHANNEL OfflineFrame from - // the remote device, so for now, just store that previous EndpointChannel. - previous_endpoint_channels_.emplace(endpoint_id, old_channel); - - // If we already read LAST_WRITE on the old endpoint channel, then we can - // safely close it now. - auto item = successfully_upgraded_endpoints_.extract(endpoint_id); - if (!item.empty()) { - ProcessLastWriteToPriorChannelEvent(client, endpoint_id); - } -} - -// Outgoing BWU session. -void BwuManager::ProcessBwuPathAvailableEvent( - ClientProxy* client, const string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) { - NEARBY_LOGS(INFO) << "ProcessBwuPathAvailableEvent for endpoint " - << endpoint_id << " medium " - << parser::UpgradePathInfoMediumToMedium( - upgrade_path_info.medium()); - if (in_progress_upgrades_.contains(endpoint_id)) { - NEARBY_LOGS(ERROR) - << "BwuManager received a duplicate bandwidth upgrade for endpoint " - << endpoint_id - << ". We're out of sync with the remote device and cannot recover; " - "closing all channels."; - - auto item = previous_endpoint_channels_.extract(endpoint_id); - if (!item.empty()) { - std::shared_ptr<EndpointChannel> previous_endpoint_channel = - item.mapped(); - if (previous_endpoint_channel) { - previous_endpoint_channel->Close(DisconnectionReason::UNFINISHED); - } - } - std::shared_ptr<EndpointChannel> new_channel = - channel_manager_->GetChannelForEndpoint(endpoint_id); - if (new_channel) { - // The upgraded channel never finished upgrading, and therefore is still - // paused. - new_channel->Resume(); - new_channel->Close(DisconnectionReason::UNFINISHED); - } - - return; - } - Medium medium = - parser::UpgradePathInfoMediumToMedium(upgrade_path_info.medium()); - if (medium_ == Medium::UNKNOWN_MEDIUM) { - SetCurrentBwuHandler(medium); - } - // Check for the correct medium so we don't process an incorrect OfflineFrame. - if (medium != medium_) { - NEARBY_LOGS(INFO) << "Medium not matching"; - RunUpgradeFailedProtocol(client, endpoint_id, upgrade_path_info); - return; - } - - client->GetAnalyticsRecorder().OnBandwidthUpgradeStarted( - endpoint_id, medium, medium_, proto::connections::OUTGOING, - client->GetConnectionToken(endpoint_id)); - - absl::Time connection_attempt_start_time = SystemClock::ElapsedRealtime(); - auto channel = ProcessBwuPathAvailableEventInternal(client, endpoint_id, - upgrade_path_info); - proto::connections::ConnectionAttemptResult connection_attempt_result; - if (channel != nullptr) { - connection_attempt_result = proto::connections::RESULT_SUCCESS; - } else if (client->GetCancellationFlag(endpoint_id)->Cancelled()) { - connection_attempt_result = proto::connections::RESULT_CANCELLED; - client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, proto::connections::RESULT_REMOTE_ERROR, - proto::connections::UPGRADE_CANCEL); - } else { - connection_attempt_result = proto::connections::RESULT_ERROR; - } - - client->GetAnalyticsRecorder().OnOutgoingConnectionAttempt( - endpoint_id, proto::connections::UPGRADE, medium_, - connection_attempt_result, - SystemClock::ElapsedRealtime() - connection_attempt_start_time, - client->GetConnectionToken(endpoint_id)); - - if (channel == nullptr) { - NEARBY_LOGS(INFO) << "Failed to get new channel."; - RunUpgradeFailedProtocol(client, endpoint_id, upgrade_path_info); - return; - } - - in_progress_upgrades_.emplace(endpoint_id, client); - RunUpgradeProtocol(client, endpoint_id, std::move(channel)); -} - -std::unique_ptr<EndpointChannel> -BwuManager::ProcessBwuPathAvailableEventInternal( - ClientProxy* client, const string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) { - NEARBY_LOGS(INFO) << "ProcessBwuPathAvailableEventInternal for endpoint " - << endpoint_id << " medium " - << parser::UpgradePathInfoMediumToMedium( - upgrade_path_info.medium()); - std::unique_ptr<EndpointChannel> channel = - handler_->CreateUpgradedEndpointChannel(client, client->GetServiceId(), - endpoint_id, upgrade_path_info); - if (!channel) { - NEARBY_LOGS(ERROR) - << "BwuManager failed to create an endpoint channel to endpoint" - << endpoint_id << ", aborting upgrade."; - client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, proto::connections::RESULT_IO_ERROR, - proto::connections::SOCKET_CREATION); - return nullptr; - } - - // Write the requisite BANDWIDTH_UPGRADE_NEGOTIATION.CLIENT_INTRODUCTION as - // the first OfflineFrame on this new EndpointChannel. - if (!channel->Write(parser::ForBwuIntroduction(client->GetLocalEndpointId())) - .Ok()) { - // This was never a fully EstablishedConnection, no need to provide a - // closure reason. - channel->Close(); - - NEARBY_LOGS(ERROR) - << "BwuManager failed to write BWU_NEGOTIATION.CLIENT_INTRODUCTION " - "OfflineFrame to newly-created EndpointChannel " - << channel->GetName() << ", aborting upgrade."; - client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, proto::connections::RESULT_IO_ERROR, - proto::connections::CLIENT_INTRODUCTION); - return {}; - } - - if (upgrade_path_info.supports_client_introduction_ack()) { - if (!ReadClientIntroductionAckFrame(channel.get())) { - // This was never a fully EstablishedConnection, no need to provide a - // closure reason. - channel->Close(); - - NEARBY_LOGS(ERROR) << "BwuManager failed to read " - "BWU_NEGOTIATION.CLIENT_INTRODUCTION_ACK " - "OfflineFrame to newly-created EndpointChannel " - << channel->GetName() << ", aborting upgrade."; - - return {}; - } - } - - NEARBY_LOGS(INFO) << "BwuManager successfully wrote " - "BWU_NEGOTIATION.CLIENT_INTRODUCTION OfflineFrame to " - "newly-created EndpointChannel " - << channel->GetName() << " while upgrading endpoint " - << endpoint_id; - - // Set the AnalyticsRecorder so that the future closure of this - // EndpointChannel will be recorded. - return channel; -} - -void BwuManager::RunUpgradeFailedProtocol( - ClientProxy* client, const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) { - NEARBY_LOGS(INFO) << "RunUpgradeFailedProtocol for endpoint " << endpoint_id - << " medium " - << parser::UpgradePathInfoMediumToMedium( - upgrade_path_info.medium()); - // We attempted to connect to the new medium that the remote device has set up - // for us but we failed. We need to let the remote device know so that they - // can pick another medium for us to try. - std::shared_ptr<EndpointChannel> channel = - channel_manager_->GetChannelForEndpoint(endpoint_id); - if (!channel) { - NEARBY_LOGS(ERROR) - << "BwuManager didn't find a previous EndpointChannel for " - << endpoint_id - << " when sending an upgrade failure frame, short-circuiting the " - "upgrade protocol."; - client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, proto::connections::CHANNEL_ERROR, - proto::connections::NETWORK_AVAILABLE); - return; - } - - // Report UPGRADE_FAILURE to the remote device. - if (!channel->Write(parser::ForBwuFailure(upgrade_path_info)).Ok()) { - channel->Close(DisconnectionReason::IO_ERROR); - - NEARBY_LOGS(ERROR) - << "BwuManager failed to write BWU_NEGOTIATION.UPGRADE_FAILURE " - "OfflineFrame to endpoint " - << endpoint_id << ", short-circuiting the upgrade protocol."; - client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, proto::connections::RESULT_IO_ERROR, - proto::connections::NETWORK_AVAILABLE); - return; - } - - // And lastly, clean up our currentBwuMedium since we failed to - // utilize it anyways. - if (medium_ != Medium::UNKNOWN_MEDIUM) { - Revert(); - } - in_progress_upgrades_.erase(endpoint_id); - NEARBY_LOGS(INFO) << "BwuManager has informed endpoint " << endpoint_id - << " that the bandwidth upgrade failed."; -} - -bool BwuManager::ReadClientIntroductionFrame(EndpointChannel* channel, - ClientIntroduction& introduction) { - NEARBY_LOGS(INFO) << "ReadClientIntroductionFrame with channel name: " - << channel->GetName() - << ", medium: " << channel->GetMedium(); - CancelableAlarm timeout_alarm( - "BwuManager::ReadClientIntroductionFrame", - [channel]() { - NEARBY_LOGS(ERROR) << "In BwuManager, failed to read the " - "ClientIntroductionFrame after " - << absl::FormatDuration( - kReadClientIntroductionFrameTimeout) - << ". Timing out and closing EndpointChannel " - << channel->GetType(); - channel->Close(); - }, - kReadClientIntroductionFrameTimeout, &alarm_executor_); - auto data = channel->Read(); - timeout_alarm.Cancel(); - if (!data.ok()) return false; - auto transfer(parser::FromBytes(data.result())); - if (!transfer.ok()) { - NEARBY_LOGS(ERROR) << "In ReadClientIntroductionFrame, attempted to read a " - "ClientIntroductionFrame from EndpointChannel " - << channel->GetType() - << " but was unable to obtain any OfflineFrame."; - return false; - } - OfflineFrame frame = transfer.result(); - if (!frame.has_v1() || !frame.v1().has_bandwidth_upgrade_negotiation()) { - NEARBY_LOGS(ERROR) - << "In ReadClientIntroductionFrame, expected a " - "BANDWIDTH_UPGRADE_NEGOTIATION v1 OfflineFrame but got a " - << parser::GetFrameType(frame) << " frame instead."; - return false; - } - if (frame.v1().bandwidth_upgrade_negotiation().event_type() != - BandwidthUpgradeNegotiationFrame::CLIENT_INTRODUCTION) { - NEARBY_LOGS(ERROR) - << "In ReadClientIntroductionFrame, expected a CLIENT_INTRODUCTION " - "v1 OfflineFrame but got a BANDWIDTH_UPGRADE_NEGOTIATION frame " - "with eventType " - << frame.v1().bandwidth_upgrade_negotiation().event_type() - << " instead."; - return false; - } - const auto& frame_intro = - frame.v1().bandwidth_upgrade_negotiation().client_introduction(); - introduction = frame_intro; - return true; -} - -bool BwuManager::ReadClientIntroductionAckFrame(EndpointChannel* channel) { - NEARBY_LOGS(INFO) << "ReadClientIntroductionAckFrame with channel name: " - << channel->GetName() << ", medium: " - << proto::connections::Medium_Name(channel->GetMedium()); - CancelableAlarm timeout_alarm( - "BwuManager::ReadClientIntroductionAckFrame", - [channel]() { - NEARBY_LOGS(ERROR) - << "In BwuManager, failed to read the ClientIntroductionAckFrame " - "after " - << absl::FormatDuration(kReadClientIntroductionFrameTimeout) - << ". Timing out and closing EndpointChannel " - << channel->GetType(); - channel->Close(); - }, - kReadClientIntroductionFrameTimeout, &alarm_executor_); - auto data = channel->Read(); - timeout_alarm.Cancel(); - if (!data.ok()) return false; - auto transfer(parser::FromBytes(data.result())); - if (!transfer.ok()) return false; - OfflineFrame frame = transfer.result(); - if (!frame.has_v1() || !frame.v1().has_bandwidth_upgrade_negotiation()) - return false; - if (frame.v1().bandwidth_upgrade_negotiation().event_type() != - BandwidthUpgradeNegotiationFrame::CLIENT_INTRODUCTION_ACK) - return false; - return true; -} - -bool BwuManager::WriteClientIntroductionAckFrame(EndpointChannel* channel) { - NEARBY_LOGS(INFO) << "WriteClientIntroductionAckFrame channel name: " - << channel->GetName() - << ", medium: " << channel->GetMedium(); - return channel->Write(parser::ForBwuIntroductionAck()).Ok(); -} - -void BwuManager::ProcessLastWriteToPriorChannelEvent( - ClientProxy* client, const std::string& endpoint_id) { - NEARBY_LOGS(INFO) << "ProcessLastWriteToPriorChannelEvent for endpoint " - << endpoint_id; - // By this point in the upgrade protocol, there is the guarantee that both - // involved endpoints have registered a new EndpointChannel with the - // EndpointChannelManager as the official channel for communication; given - // the way communication is structured in the EndpointManager, this means - // that all new writes are happening over that new EndpointChannel, but - // reads are still happening over this prior EndpointChannel (to avoid data - // loss). But now that we've received this definitive final write over that - // prior EndpointChannel, we can let the remote device that they can safely - // close their end of this now-dormant EndpointChannel. - EndpointChannel* previous_endpoint_channel = - previous_endpoint_channels_[endpoint_id].get(); - if (!previous_endpoint_channel) { - NEARBY_LOGS(ERROR) - << "BwuManager received a BWU_NEGOTIATION.LAST_WRITE_TO_PRIOR_CHANNEL " - "OfflineFrame for unknown endpoint " - << endpoint_id << ", can't complete the upgrade protocol."; - successfully_upgraded_endpoints_.emplace(endpoint_id); - return; - } - - if (!previous_endpoint_channel->Write(parser::ForBwuSafeToClose()).Ok()) { - previous_endpoint_channel->Close(DisconnectionReason::IO_ERROR); - // Remove this prior EndpointChannel from previous_endpoint_channels to - // avoid leaks. - previous_endpoint_channels_.erase(endpoint_id); - - NEARBY_LOGS(ERROR) << "BwuManager failed to write " - "BWU_NEGOTIATION.SAFE_TO_CLOSE_PRIOR_CHANNEL " - "OfflineFrame to endpoint " - << endpoint_id - << ", short-circuiting the upgrade protocol."; - client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, proto::connections::RESULT_IO_ERROR, - proto::connections::SAFE_TO_CLOSE_PRIOR_CHANNEL); - return; - } - NEARBY_LOGS(VERBOSE) << "BwuManager successfully wrote " - "BWU_NEGOTIATION.SAFE_TO_CLOSE_PRIOR_CHANNEL " - "OfflineFrame while trying to upgrade endpoint " - << endpoint_id; - - // The upgrade protocol's clean shutdown of the prior EndpointChannel will - // conclude when we receive a corresponding - // BANDWIDTH_UPGRADE_NEGOTIATION.SAFE_TO_CLOSE_PRIOR_CHANNEL OfflineFrame - // from the remote device. -} - -void BwuManager::ProcessSafeToClosePriorChannelEvent( - ClientProxy* client, const std::string& endpoint_id) { - NEARBY_LOGS(INFO) << "ProcessSafeToClosePriorChannelEvent for endpoint " - << endpoint_id; - // By this point in the upgrade protocol, there's no more writes happening - // over the prior EndpointChannel, and the remote device has given us the - // go-ahead to close this EndpointChannel [1], so we can safely close it - // (and depend on the EndpointManager querying the EndpointChannelManager to - // start reading from the new EndpointChannel). - // - // [1] Which also implies that they've received our - // BANDWIDTH_UPGRADE_NEGOTIATION.LAST_WRITE_TO_PRIOR_CHANNEL OfflineFrame), - // so there can be no data loss, regardless of whether the EndpointChannel - // allows reads of queued, unread data after the EndpointChannel has been - // closed from the other end (as is the case with conventional TCP sockets) - // or not (as is the case with Android's Bluetooth sockets, where closing - // instantly throws an IOException on the remote device). - auto item = previous_endpoint_channels_.extract(endpoint_id); - auto& previous_endpoint_channel = item.mapped(); - if (previous_endpoint_channel == nullptr) { - NEARBY_LOGS(ERROR) - << "BwuManager received a BWU_NEGOTIATION.SAFE_TO_CLOSE_PRIOR_CHANNEL " - "OfflineFrame for unknown endpoint " - << endpoint_id << ", can't complete the upgrade protocol."; - return; - } - NEARBY_LOGS(INFO) - << "BwuManager successfully received a " - << "BWU_NEGOTIATION.SAFE_TO_CLOSE_PRIOR_CHANNEL OfflineFrame while " - << "trying to upgrade endpoint " << endpoint_id; - - // Each encrypted message includes the key to decrypt the next message. The - // disconnect message is optional and may not be received under normal - // circumstances so it is necessary to send it unencrypted. This way the - // serial crypto context does not increment here. - previous_endpoint_channel->DisableEncryption(); - previous_endpoint_channel->Write(parser::ForDisconnection()); - - // Attempt to read the disconnect message from the previous channel. We don't - // care whether we successfully read it or whether we get an exception here. - // The idea is just to make sure the other side has had a chance to receive - // the full SAFE_TO_CLOSE_PRIOR_CHANNEL message before we actually close the - // channel. See b/172380349 for more context. - previous_endpoint_channel->Read(); - previous_endpoint_channel->Close(DisconnectionReason::UPGRADED); - - NEARBY_LOGS(VERBOSE) - << "BwuManager cleanly shut down prior " - << previous_endpoint_channel->GetType() - << " EndpointChannel to conclude upgrade protocol for endpoint " - << endpoint_id; - - // Now the upgrade protocol has completed, record analytics for this new - // upgraded bandwidth connection... - client->GetAnalyticsRecorder().OnConnectionEstablished( - endpoint_id, medium_, client->GetConnectionToken(endpoint_id)); - // ...and the success of the upgrade itself. - client->GetAnalyticsRecorder().OnBandwidthUpgradeSuccess(endpoint_id); - - // Now that the old channel has been drained, we can unpause the new channel - std::shared_ptr<EndpointChannel> channel = - channel_manager_->GetChannelForEndpoint(endpoint_id); - - if (!channel) { - NEARBY_LOGS(ERROR) << "BwuManager attempted to resume the current " - "EndpointChannel with endpoint " - << endpoint_id << ", but none was found."; - return; - } - - channel->Resume(); - - // Report the success to the client - client->OnBandwidthChanged(endpoint_id, channel->GetMedium()); - in_progress_upgrades_.erase(endpoint_id); -} - -void BwuManager::ProcessUpgradeFailureEvent( - ClientProxy* client, const std::string& endpoint_id, - const UpgradePathInfo& upgrade_info) { - NEARBY_LOGS(INFO) << "ProcessUpgradeFailureEvent for endpoint " << endpoint_id - << " from medium: " - << parser::UpgradePathInfoMediumToMedium( - upgrade_info.medium()); - // The remote device failed to upgrade to the new medium we set up for them. - // That's alright! We'll just try the next available medium (if there is - // one). - in_progress_upgrades_.erase(endpoint_id); - - // The first thing we have to do is to replace our - // currentBwuMedium with the next best upgrade medium we share - // with the remote device. The catch is that we can only do this if we only - // have one connected endpoint. Otherwise, we'll end up disrupting our other - // connected peers. - if (channel_manager_->GetConnectedEndpointsCount() > 1) { - // We can't change the currentBwuMedium, so there are no more - // upgrade attempts for this endpoint. Sorry. - NEARBY_LOGS(ERROR) - << "BwuManager failed to attempt a new bandwidth upgrade for endpoint " - << endpoint_id - << " because we have other connected endpoints and can't try a new " - "upgrade medium."; - client->GetAnalyticsRecorder().OnBandwidthUpgradeError( - endpoint_id, proto::connections::CHANNEL_ERROR, - proto::connections::NETWORK_AVAILABLE); - return; - } - - // Revert the existing upgrade medium for now. - if (medium_ != Medium::UNKNOWN_MEDIUM) { - Revert(); - } - - // Loop through the ordered list of upgrade mediums. One by one, remove the - // top element until we get to the medium we last attempted to upgrade to. - // The remainder of the list will contain the mediums we haven't attempted - // yet. - Medium last = parser::UpgradePathInfoMediumToMedium(upgrade_info.medium()); - std::vector<Medium> all_possible_mediums = - client->GetUpgradeMediums(endpoint_id).GetMediums(true); - std::vector<Medium> untried_mediums(all_possible_mediums); - for (Medium medium : all_possible_mediums) { - untried_mediums.erase(untried_mediums.begin()); - if (medium == last) { - break; - } - } - - RetryUpgradeMediums(client, endpoint_id, untried_mediums); -} - -void BwuManager::RetryUpgradeMediums(ClientProxy* client, - const std::string& endpoint_id, - std::vector<Medium> upgrade_mediums) { - Medium next_medium = ChooseBestUpgradeMedium(upgrade_mediums); - NEARBY_LOGS(INFO) << "RetryUpgradeMediums for endpoint " << endpoint_id - << " after ChooseBestUpgradeMedium: " << next_medium; - - // If current medium is not WiFi and we have not succeeded with upgrading - // yet, retry upgrade. - Medium current_medium = GetEndpointMedium(endpoint_id); - if (current_medium != Medium::WIFI_LAN && - (next_medium == current_medium || next_medium == Medium::UNKNOWN_MEDIUM || - upgrade_mediums.empty())) { - RetryUpgradesAfterDelay(client, endpoint_id); - return; - } - - // Attempt to set the new upgrade medium. - if (!SetCurrentBwuHandler(next_medium)) { - NEARBY_LOGS(INFO) - << "BwuManager failed to attempt a new bandwidth upgrade for endpoint " - << endpoint_id - << " because we couldn't set a new bandwidth upgrade medium."; - return; - } - - // Now that we've successfully picked a new upgrade medium to try, - // re-initiate the bandwidth upgrade. - NEARBY_LOGS(INFO) << "BwuManager is attempting to upgrade endpoint " - << endpoint_id - << " again with a new bandwidth upgrade medium."; - InitiateBwuForEndpoint(client, endpoint_id, next_medium); -} - -std::vector<Medium> BwuManager::StripOutUnavailableMediums( - const std::vector<Medium>& mediums) { - std::vector<Medium> available_mediums; - for (Medium m : mediums) { - bool available = false; - switch (m) { - case Medium::WIFI_LAN: - available = mediums_->GetWifiLan().IsAvailable(); - break; - case Medium::WEB_RTC: - available = mediums_->GetWebRtc().IsAvailable(); - break; - case Medium::BLUETOOTH: - available = mediums_->GetBluetoothClassic().IsAvailable(); - break; - default: - break; - } - if (available) { - available_mediums.push_back(m); - } - } - return available_mediums; -} - -// Returns the optimal medium supported by both devices. -// Each medium in the passed in list is checked for its availability with the -// medium_manager_ to ensure that the chosen upgrade medium is supported and -// available locally before continuing the upgrade. Once we pick a medium, all -// future connections will use it too. eg. If we chose Wifi LAN, we'll attempt -// to upgrade the 2nd, 3rd, etc remote endpoints with Wifi LAN even if they're -// on a different network (or had a better medium). This is a quick and easy -// way to prevent mediums, like Wifi Hotspot, from interfering with active -// connections (although it's suboptimal for bandwidth throughput). When all -// endpoints disconnect, we reset the bandwidth upgrade medium. -Medium BwuManager::ChooseBestUpgradeMedium(const std::vector<Medium>& mediums) { - auto available_mediums = StripOutUnavailableMediums(mediums); - if (medium_ == Medium::UNKNOWN_MEDIUM) { - if (!available_mediums.empty()) { - // Case 1: This is our first time upgrading, and we have at least one - // supported medium to choose from. Return the first medium in the list, - // since they are ordered by preference. - return available_mediums[0]; - } - // Case 2: This is our first time upgrading, but there are no available - // upgrade mediums. Fall through to returning UNKNOWN_MEDIUM at the - // bottom. - NEARBY_LOGS(INFO) - << "Current upgrade medium is unset, but there are no common supported " - "upgrade mediums."; - } else { - // Case 3: We have already upgraded, and there is a list of supported - // mediums to check against. Return the current upgrade medium if it's in - // the supported list. - if (std::find(available_mediums.begin(), available_mediums.end(), - medium_) != available_mediums.end()) { - return medium_; - } - // Case 4: We have already upgraded, but the current medium is not - // supported by the remote endpoint (it's not in the list, or the list is - // empty). Fall through and return Medium.UNKNOWN_MEDIUM because we cannot - // continue with the current upgrade medium, and we are not allowed to - // switch. - std::string mediums_string; - for (const auto& medium : available_mediums) { - absl::StrAppend(&mediums_string, proto::connections::Medium_Name(medium), - "; "); - } - NEARBY_LOGS(INFO) - << "Current upgrade medium " << proto::connections::Medium_Name(medium_) - << " is not supported by the remote endpoint (supported mediums: " - << mediums_string << ")"; - } - - return Medium::UNKNOWN_MEDIUM; -} - -void BwuManager::RetryUpgradesAfterDelay(ClientProxy* client, - const std::string& endpoint_id) { - absl::Duration delay = CalculateNextRetryDelay(endpoint_id); - CancelRetryUpgradeAlarm(endpoint_id); - CancelableAlarm alarm( - "BWU alarm", - [this, client, endpoint_id]() { - RunOnBwuManagerThread( - "bwu-retry-upgrade", [this, client, endpoint_id]() { - if (!client->IsConnectedToEndpoint(endpoint_id)) { - return; - } - RetryUpgradeMediums( - client, endpoint_id, - client->GetUpgradeMediums(endpoint_id).GetMediums(true)); - }); - }, - delay, &alarm_executor_); - - retry_upgrade_alarms_.emplace(endpoint_id, - std::make_pair(std::move(alarm), delay)); - retry_delays_[endpoint_id] = delay; - NEARBY_LOGS(INFO) << "Retry bandwidth upgrade after " - << absl::FormatDuration(delay); -} - -void BwuManager::AttemptToRecordBandwidthUpgradeErrorForUnknownEndpoint( - proto::connections::BandwidthUpgradeResult result, - proto::connections::BandwidthUpgradeErrorStage error_stage) { - if (in_progress_upgrades_.size() == 1) { - auto it = in_progress_upgrades_.begin(); - std::string endpoint_id = it->first; - ClientProxy* client = it->second; - // Note: Even though we know this is an error, we cannot clear state yet. - // We've sent the remote device the credentials they need and it's up to - // them if they want to repeatedly attempt to connect or if they want to - // give up and have us try a different medium. This isn't a decision we can - // make for them. - client->GetAnalyticsRecorder().OnBandwidthUpgradeError(endpoint_id, result, - error_stage); - NEARBY_LOGS(INFO) << "BwuManager got error " - << proto::connections::BandwidthUpgradeResult_Name(result) - << " at stage " - << proto::connections::BandwidthUpgradeErrorStage_Name( - error_stage) - << " when upgrading endpoint " << endpoint_id; - } - // Otherwise, we have no way of knowing which endpoint was trying to connect - // to us :( - NEARBY_LOGS(INFO) << "BwuManager got error " - << proto::connections::BandwidthUpgradeResult_Name(result) - << " at stage " - << proto::connections::BandwidthUpgradeErrorStage_Name( - error_stage) - << ", but we don't know which endpoint was trying to " - "connect to us, so skipping analytics for his error."; -} - -absl::Duration BwuManager::CalculateNextRetryDelay( - const std::string& endpoint_id) { - auto item = retry_delays_.find(endpoint_id); - auto initial_delay = config_.bandwidth_upgrade_retry_delay; - if (item == retry_delays_.end()) return initial_delay; - /* - * Without use_exp_backoff_in_bwu_retry, bwu retry intervals for the same - * endpoint_id in seconds will be like: 5, 10, 10, 10... - * With use_exp_backoff_in_bwu_retry enabled, bwu retry intervals in seconds - * would be like: 3, 6, 12, 24, ... 300, 300, ... - */ - auto delay = - FeatureFlags::GetInstance().GetFlags().use_exp_backoff_in_bwu_retry - ? item->second * 2 - : item->second + initial_delay; - return std::min(delay, config_.bandwidth_upgrade_retry_max_delay); -} - -void BwuManager::CancelRetryUpgradeAlarm(const std::string& endpoint_id) { - NEARBY_LOGS(INFO) << "CancelRetryUpgradeAlarm for endpoint " << endpoint_id; - auto item = retry_upgrade_alarms_.extract(endpoint_id); - if (item.empty()) return; - auto& pair = item.mapped(); - pair.first.Cancel(); -} - -void BwuManager::CancelAllRetryUpgradeAlarms() { - NEARBY_LOGS(INFO) << "CancelAllRetryUpgradeAlarms invoked"; - for (auto& item : retry_upgrade_alarms_) { - const std::string& endpoint_id = item.first; - CancelableAlarm& cancellable_alarm = item.second.first; - NEARBY_LOGS(INFO) << "CancelRetryUpgradeAlarm for endpoint " << endpoint_id; - cancellable_alarm.Cancel(); - } - retry_upgrade_alarms_.clear(); - retry_delays_.clear(); -} - -Medium BwuManager::GetEndpointMedium(const std::string& endpoint_id) { - auto channel = channel_manager_->GetChannelForEndpoint(endpoint_id); - return channel == nullptr ? Medium::UNKNOWN_MEDIUM : channel->GetMedium(); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager.h b/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager.h deleted file mode 100644 index b304a49a587..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager.h +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_BWU_MANAGER_H_ -#define CORE_INTERNAL_BWU_MANAGER_H_ - -#include <memory> -#include <string> -#include <vector> - -#include "absl/container/flat_hash_map.h" -#include "absl/container/flat_hash_set.h" -#include "absl/time/time.h" -#include "core/internal/bwu_handler.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_manager.h" -#include "core/internal/mediums/mediums.h" -#include "core/options.h" -#include "platform/base/byte_array.h" -#include "platform/public/scheduled_executor.h" - -namespace location { -namespace nearby { -namespace connections { - -// Base class for managing the upgrade of endpoints to a different medium for -// communication (from whatever they were previously using). -// -// The sequencing of the upgrade protocol is as follows: -// - Initiator sets up an upgrade path, sends -// BANDWIDTH_UPGRADE_NEGOTIATION.UPGRADE_PATH_AVAILABLE to Responder over -// the prior EndpointChannel. -// - Responder joins the upgrade path, sends (possibly without encryption) -// BANDWIDTH_UPGRADE_NEGOTIATION.CLIENT_INTRODUCTION over the new -// EndpointChannel, and sends -// BANDWIDTH_UPGRADE_NEGOTIATION.LAST_WRITE_TO_PRIOR_CHANNEL over the -// prior EndpointChannel. -// - Initiator receives BANDWIDTH_UPGRADE_NEGOTIATION.CLIENT_INTRODUCTION -// over the newly-established EndpointChannel, and sends -// BANDWIDTH_UPGRADE_NEGOTIATION.LAST_WRITE_TO_PRIOR_CHANNEL over the -// prior EndpointChannel. -// - Both wait to receive -// BANDWIDTH_UPGRADE_NEGOTIATION.LAST_WRITE_TO_PRIOR_CHANNEL from the -// other, and upon doing so, send -// BANDWIDTH_UPGRADE_NEGOTIATION.SAFE_TO_CLOSE_PRIOR_CHANNEL to each other -// - Both then wait to receive -// BANDWIDTH_UPGRADE_NEGOTIATION.SAFE_TO_CLOSE_PRIOR_CHANNEL from the -// other, and upon doing so, close the prior EndpointChannel. -class BwuManager : public EndpointManager::FrameProcessor { - public: - using UpgradePathInfo = BwuHandler::UpgradePathInfo; - - struct Config { - BooleanMediumSelector allow_upgrade_to; - absl::Duration bandwidth_upgrade_retry_delay; - absl::Duration bandwidth_upgrade_retry_max_delay; - }; - - BwuManager(Mediums& mediums, EndpointManager& endpoint_manager, - EndpointChannelManager& channel_manager, - absl::flat_hash_map<Medium, std::unique_ptr<BwuHandler>> handlers, - Config config); - - ~BwuManager() override; - - // This is the point on the outbound BWU protocol where the handler_ is set. - // Function initiates the bandwidth upgrade and sends an - // UPGRADE_PATH_AVAILABLE OfflineFrame. - void InitiateBwuForEndpoint(ClientProxy* client_proxy, - const std::string& endpoint_id, - Medium new_medium = Medium::UNKNOWN_MEDIUM); - - // == EndpointManager::FrameProcessor interface ==. - // This is the point on the inbound BWU protocol where the handler_ is set. - // This is also an entry point for handling messages for both outbound and - // inbound BWU protocol. - // @EndpointManagerReaderThread - void OnIncomingFrame(OfflineFrame& frame, const std::string& endpoint_id, - ClientProxy* client, Medium medium) override; - - // Cleans up in-progress upgrades after endpoint disconnection. - // @EndpointManagerReaderThread - void OnEndpointDisconnect(ClientProxy* client_proxy, - const std::string& endpoint_id, - CountDownLatch barrier) override; - void Shutdown(); - - private: - static constexpr absl::Duration kReadClientIntroductionFrameTimeout = - absl::Seconds(5); - BwuHandler* SetCurrentBwuHandler(Medium medium); - void InitBwuHandlers(); - void RunOnBwuManagerThread(const std::string& name, - std::function<void()> runnable); - std::vector<Medium> StripOutUnavailableMediums( - const std::vector<Medium>& mediums); - Medium ChooseBestUpgradeMedium(const std::vector<Medium>& mediums); - - // BaseBwuHandler - using ClientIntroduction = BwuNegotiationFrame::ClientIntroduction; - - // Processes the BwuNegotiationFrames that come over the - // EndpointChannel on both initiator and responder side of the upgrade. - void OnBwuNegotiationFrame(ClientProxy* client, - const BwuNegotiationFrame frame, - const string& endpoint_id); - - // Called to revert any state changed by the Initiator or Responder in the - // course of setting up the upgraded medium for an endpoint. - void Revert(); - - // Common functionality to take an incoming connection and go through the - // upgrade process. This is a callback, invoked by concrete handlers, once - // connection is available. - void OnIncomingConnection( - ClientProxy* client, - std::unique_ptr<BwuHandler::IncomingSocketConnection> mutable_connection); - - void RunUpgradeProtocol(ClientProxy* client, const std::string& endpoint_id, - std::unique_ptr<EndpointChannel> new_channel); - void RunUpgradeFailedProtocol(ClientProxy* client, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info); - void ProcessBwuPathAvailableEvent(ClientProxy* client, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info); - std::unique_ptr<EndpointChannel> ProcessBwuPathAvailableEventInternal( - ClientProxy* client, const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info); - void ProcessLastWriteToPriorChannelEvent(ClientProxy* client, - const std::string& endpoint_id); - void ProcessSafeToClosePriorChannelEvent(ClientProxy* client, - const std::string& endpoint_id); - bool ReadClientIntroductionFrame(EndpointChannel* endpoint_channel, - ClientIntroduction& introduction); - bool ReadClientIntroductionAckFrame(EndpointChannel* endpoint_channel); - bool WriteClientIntroductionAckFrame(EndpointChannel* endpoint_channel); - void ProcessEndpointDisconnection(ClientProxy* client, - const std::string& endpoint_id, - CountDownLatch* barrier); - void ProcessUpgradeFailureEvent(ClientProxy* client, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_info); - void CancelRetryUpgradeAlarm(const std::string& endpoint_id); - void CancelAllRetryUpgradeAlarms(); - void RetryUpgradeMediums(ClientProxy* client, const std::string& endpoint_id, - std::vector<Medium> upgrade_mediums); - Medium GetEndpointMedium(const std::string& endpoint_id); - absl::Duration CalculateNextRetryDelay(const std::string& endpoint_id); - void RetryUpgradesAfterDelay(ClientProxy* client, - const std::string& endpoint_id); - void AttemptToRecordBandwidthUpgradeErrorForUnknownEndpoint( - proto::connections::BandwidthUpgradeResult result, - proto::connections::BandwidthUpgradeErrorStage error_stage); - - Config config_; - - Medium medium_ = Medium::UNKNOWN_MEDIUM; - BwuHandler* handler_ = nullptr; - Mediums* mediums_; - absl::flat_hash_map<Medium, std::unique_ptr<BwuHandler>> handlers_; - - EndpointManager* endpoint_manager_; - EndpointChannelManager* channel_manager_; - ScheduledExecutor alarm_executor_; - SingleThreadExecutor serial_executor_; - // Stores each upgraded endpoint's previous EndpointChannel (that was - // displaced in favor of a new EndpointChannel) temporarily, until it can - // safely be shut down for good in processLastWriteToPriorChannelEvent(). - absl::flat_hash_map<std::string, std::shared_ptr<EndpointChannel>> - previous_endpoint_channels_; - absl::flat_hash_set<std::string> successfully_upgraded_endpoints_; - // Maps endpointId -> ClientProxy for which - // initiateBwuForEndpoint() has been called but which have not - // yet completed the upgrade via onIncomingConnection(). - absl::flat_hash_map<std::string, ClientProxy*> in_progress_upgrades_; - // Maps endpointId -> timestamp of when the SAFE_TO_CLOSE message was written. - absl::flat_hash_map<std::string, absl::Time> safe_to_close_write_timestamps_; - absl::flat_hash_map<std::string, std::pair<CancelableAlarm, absl::Duration>> - retry_upgrade_alarms_; - // Maps endpointId -> duration of delay before bwu retry. - // When bwu failed, retry_upgrade_alarms_ will clear the entry before the - // retry happen, then we can not find the last delay used in the alarm. Thus - // using a different map to keep track of the delays per endpoint. - absl::flat_hash_map<std::string, absl::Duration> retry_delays_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_BWU_MANAGER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager_test.cc deleted file mode 100644 index 050a4563cd1..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager_test.cc +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/bwu_manager.h" - -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/time/time.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel_manager.h" -#include "core/internal/endpoint_manager.h" -#include "core/internal/mediums/mediums.h" -#include "core/internal/mediums/utils.h" -#include "core/internal/offline_frames.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -TEST(BwuManagerTest, CanCreateInstance) { - Mediums mediums; - EndpointChannelManager ecm; - EndpointManager em{&ecm}; - BwuManager bwu_manager{mediums, em, ecm, {}, {}}; - - SystemClock::Sleep(absl::Seconds(3)); - - bwu_manager.Shutdown(); -} - -TEST(BwuManagerTest, CanInitiateBwu) { - ClientProxy client; - std::string endpoint_id("EP_A"); - Mediums mediums; - EndpointChannelManager ecm; - EndpointManager em{&ecm}; - BwuManager bwu_manager{mediums, em, ecm, {}, {}}; - - // Method returns void, so we just verify we did not SEGFAULT while calling. - bwu_manager.InitiateBwuForEndpoint(&client, endpoint_id); - SystemClock::Sleep(absl::Seconds(3)); - - bwu_manager.Shutdown(); -} - -TEST(BwuManagerTest, CanProcessBandwidthUpgradeFrames) { - ClientProxy client; - std::string endpoint_id("EP_A"); - LocationHint location_hint = Utils::BuildLocationHint("US"); - Mediums mediums; - EndpointChannelManager ecm; - EndpointManager em{&ecm}; - BwuManager bwu_manager{mediums, em, ecm, {}, {}}; - - ExceptionOr<OfflineFrame> path_available_frame = parser::FromBytes( - parser::ForBwuWebrtcPathAvailable("my_id", location_hint)); - bwu_manager.OnIncomingFrame(path_available_frame.result(), endpoint_id, - &client, Medium::WEB_RTC); - - ExceptionOr<OfflineFrame> last_write_frame = - parser::FromBytes(parser::ForBwuLastWrite()); - bwu_manager.OnIncomingFrame(last_write_frame.result(), endpoint_id, &client, - Medium::WEB_RTC); - - ExceptionOr<OfflineFrame> safe_to_close_frame = - parser::FromBytes(parser::ForBwuSafeToClose()); - bwu_manager.OnIncomingFrame(safe_to_close_frame.result(), endpoint_id, - &client, Medium::WEB_RTC); - - bwu_manager.Shutdown(); -} - -TEST(BwuManagerTest, InitiateBwu_UpgradeFails_NoCrash) { - ClientProxy client; - std::string endpoint_id("EP_A"); - Mediums mediums; - EndpointChannelManager ecm; - EndpointManager em{&ecm}; - BwuManager bwu_manager{mediums, em, ecm, {}, {}}; - parser::UpgradePathInfo upgrade_path_info; - upgrade_path_info.set_medium(parser::UpgradePathInfo::WEB_RTC); - - bwu_manager.InitiateBwuForEndpoint(&client, endpoint_id); - ExceptionOr<OfflineFrame> bwu_failed_frame = - parser::FromBytes(parser::ForBwuFailure(upgrade_path_info)); - bwu_manager.OnIncomingFrame(bwu_failed_frame.result(), endpoint_id, &client, - Medium::WEB_RTC); - - bwu_manager.Shutdown(); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/client_proxy.cc b/chromium/third_party/nearby/src/cpp/core/internal/client_proxy.cc deleted file mode 100644 index 031832cbad7..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/client_proxy.cc +++ /dev/null @@ -1,774 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/client_proxy.h" - -#include <cstdlib> -#include <functional> -#include <limits> -#include <string> -#include <utility> - -#include "absl/container/flat_hash_map.h" -#include "absl/container/flat_hash_set.h" -#include "absl/strings/escaping.h" -#include "absl/strings/str_cat.h" -#include "platform/base/error_code_recorder.h" -#include "platform/base/feature_flags.h" -#include "platform/base/prng.h" -#include "platform/public/logging.h" -#include "platform/public/mutex_lock.h" -#include "proto/connections_enums.pb.h" - -namespace location { -namespace nearby { -namespace connections { - -// The definition is necessary before C++17. -constexpr absl::Duration - ClientProxy::kHighPowerAdvertisementEndpointIdCacheTimeout; - -constexpr char kEndpointIdChars[] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}; - -ClientProxy::ClientProxy(analytics::EventLogger* event_logger) - : client_id_(Prng().NextInt64()) { - NEARBY_LOGS(INFO) << "ClientProxy ctor event_logger=" << event_logger; - analytics_recorder_ = - std::make_unique<analytics::AnalyticsRecorder>(event_logger); - error_code_recorder_ = std::make_unique<ErrorCodeRecorder>( - [this](const ErrorCodeParams& params) { - analytics_recorder_->OnErrorCode(params); - }); -} - -ClientProxy::~ClientProxy() { Reset(); } - -std::int64_t ClientProxy::GetClientId() const { return client_id_; } - -std::string ClientProxy::GetLocalEndpointId() { - MutexLock lock(&mutex_); - if (local_endpoint_id_.empty()) { - local_endpoint_id_ = GenerateLocalEndpointId(); - NEARBY_LOGS(INFO) << "ClientProxy [Local Endpoint Generated]: client=" - << GetClientId() - << "; endpoint_id=" << local_endpoint_id_; - } - return local_endpoint_id_; -} - -std::string ClientProxy::GetConnectionToken(const std::string& endpoint_id) { - Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - return item->connection_token; - } - return {}; -} - -std::string ClientProxy::GenerateLocalEndpointId() { - if (high_vis_mode_) { - if (!local_high_vis_mode_cache_endpoint_id_.empty()) { - NEARBY_LOGS(INFO) - << "ClientProxy [Local Endpoint Re-using cached endpoint id]: client=" - << GetClientId() << "; local_high_vis_mode_cache_endpoint_id_=" - << local_high_vis_mode_cache_endpoint_id_; - return local_high_vis_mode_cache_endpoint_id_; - } - } - std::string id; - for (int i = 0; i < kEndpointIdLength; i++) { - id += kEndpointIdChars[prng_.NextUint32() % sizeof(kEndpointIdChars)]; - } - return id; -} - -void ClientProxy::Reset() { - MutexLock lock(&mutex_); - - StoppedAdvertising(); - StoppedDiscovery(); - RemoveAllEndpoints(); - ExitHighVisibilityMode(); - analytics_recorder_->LogSession(); -} - -void ClientProxy::StartedAdvertising( - const std::string& service_id, Strategy strategy, - const ConnectionListener& listener, - absl::Span<proto::connections::Medium> mediums, - const ConnectionOptions& advertising_options) { - MutexLock lock(&mutex_); - NEARBY_LOGS(INFO) << "ClientProxy [StartedAdvertising]: client=" - << GetClientId(); - - if (high_vis_mode_) { - local_high_vis_mode_cache_endpoint_id_ = local_endpoint_id_; - NEARBY_LOGS(INFO) - << "ClientProxy [High Visibility Mode Adv, Cache EndpointId]: client=" - << GetClientId() << "; local_high_vis_mode_cache_endpoint_id_=" - << local_high_vis_mode_cache_endpoint_id_; - CancelClearLocalHighVisModeCacheEndpointIdAlarm(); - } - - advertising_info_ = {service_id, listener}; - advertising_options_ = advertising_options; - - const std::vector<proto::connections::Medium> medium_vector(mediums.begin(), - mediums.end()); - analytics_recorder_->OnStartAdvertising(strategy, medium_vector); -} - -void ClientProxy::StoppedAdvertising() { - MutexLock lock(&mutex_); - NEARBY_LOGS(INFO) << "ClientProxy [StoppedAdvertising]: client=" - << GetClientId(); - - if (IsAdvertising()) { - advertising_info_.Clear(); - analytics_recorder_->OnStopAdvertising(); - } - // advertising_options_ is purposefully not cleared here. - ResetLocalEndpointIdIfNeeded(); - - ExitHighVisibilityMode(); -} - -bool ClientProxy::IsAdvertising() const { - MutexLock lock(&mutex_); - - return !advertising_info_.IsEmpty(); -} - -std::string ClientProxy::GetAdvertisingServiceId() const { - MutexLock lock(&mutex_); - return advertising_info_.service_id; -} - -std::string ClientProxy::GetServiceId() const { - MutexLock lock(&mutex_); - if (IsAdvertising()) return advertising_info_.service_id; - if (IsDiscovering()) return discovery_info_.service_id; - return "idle_service_id"; -} - -void ClientProxy::StartedDiscovery( - const std::string& service_id, Strategy strategy, - const DiscoveryListener& listener, - absl::Span<proto::connections::Medium> mediums, - const ConnectionOptions& discovery_options) { - MutexLock lock(&mutex_); - discovery_info_ = DiscoveryInfo{service_id, listener}; - discovery_options_ = discovery_options; - - const std::vector<proto::connections::Medium> medium_vector(mediums.begin(), - mediums.end()); - analytics_recorder_->OnStartDiscovery(strategy, medium_vector); -} - -void ClientProxy::StoppedDiscovery() { - MutexLock lock(&mutex_); - - if (IsDiscovering()) { - discovered_endpoint_ids_.clear(); - discovery_info_.Clear(); - analytics_recorder_->OnStopDiscovery(); - } - // discovery_options_ is purposefully not cleared here. - ResetLocalEndpointIdIfNeeded(); -} - -bool ClientProxy::IsDiscoveringServiceId(const std::string& service_id) const { - MutexLock lock(&mutex_); - - return IsDiscovering() && service_id == discovery_info_.service_id; -} - -bool ClientProxy::IsDiscovering() const { - MutexLock lock(&mutex_); - - return !discovery_info_.IsEmpty(); -} - -std::string ClientProxy::GetDiscoveryServiceId() const { - MutexLock lock(&mutex_); - - return discovery_info_.service_id; -} - -void ClientProxy::OnEndpointFound(const std::string& service_id, - const std::string& endpoint_id, - const ByteArray& endpoint_info, - proto::connections::Medium medium) { - MutexLock lock(&mutex_); - - NEARBY_LOGS(INFO) << "ClientProxy [Endpoint Found]: [enter] id=" - << endpoint_id << "; service=" << service_id << "; info=" - << absl::BytesToHexString(endpoint_info.data()); - if (!IsDiscoveringServiceId(service_id)) { - NEARBY_LOGS(INFO) << "ClientProxy [Endpoint Found]: Ignoring event for id=" - << endpoint_id - << " because this client is not discovering."; - return; - } - - if (discovered_endpoint_ids_.count(endpoint_id)) { - NEARBY_LOGS(WARNING) - << "ClientProxy [Endpoint Found]: Ignoring event for id=" << endpoint_id - << " because this client has already reported this endpoint as found."; - return; - } - - discovered_endpoint_ids_.insert(endpoint_id); - discovery_info_.listener.endpoint_found_cb(endpoint_id, endpoint_info, - service_id); - analytics_recorder_->OnEndpointFound(medium); -} - -void ClientProxy::OnEndpointLost(const std::string& service_id, - const std::string& endpoint_id) { - MutexLock lock(&mutex_); - - NEARBY_LOGS(INFO) << "ClientProxy [Endpoint Lost]: [enter] id=" << endpoint_id - << "; service=" << service_id; - if (!IsDiscoveringServiceId(service_id)) { - NEARBY_LOG(INFO, - "ClientProxy [Endpoint Lost]: Ignoring event for id=%s because " - "this client is not discovering", - endpoint_id.c_str()); - return; - } - - const auto it = discovered_endpoint_ids_.find(endpoint_id); - if (it == discovered_endpoint_ids_.end()) { - NEARBY_LOGS(WARNING) - << "ClientProxy [Endpoint Lost]: Ignoring event for id=" << endpoint_id - << " because this client has not yet reported this endpoint as found"; - return; - } - - discovered_endpoint_ids_.erase(it); - discovery_info_.listener.endpoint_lost_cb(endpoint_id); -} - -void ClientProxy::OnConnectionInitiated(const std::string& endpoint_id, - const ConnectionResponseInfo& info, - const ConnectionOptions& options, - const ConnectionListener& listener, - const std::string& connection_token) { - MutexLock lock(&mutex_); - - // Whether this is incoming or outgoing, the local and remote endpoints both - // still need to accept this connection, so set its establishment status to - // PENDING. - auto result = connections_.emplace( - endpoint_id, Connection{ - .is_incoming = info.is_incoming_connection, - .connection_listener = listener, - .connection_options = options, - .connection_token = connection_token, - }); - // Instead of using structured binding which is nice, but banned - // (can not use c++17 features, until chromium does) we unpack manually. - auto& pair_iter = result.first; - bool inserted = result.second; - NEARBY_LOGS(INFO) - << "ClientProxy [Connection Initiated]: add Connection: client=" - << GetClientId() << "; endpoint_id=" << endpoint_id - << "; inserted=" << inserted; - DCHECK(inserted); - const Connection& item = pair_iter->second; - // Notify the client. - // - // Note: we allow devices to connect to an advertiser even after it stops - // advertising, so no need to check IsAdvertising() here. - item.connection_listener.initiated_cb(endpoint_id, info); - - if (info.is_incoming_connection) { - // Add CancellationFlag for advertisers once encryption succeeds. - AddCancellationFlag(endpoint_id); - analytics_recorder_->OnConnectionRequestReceived(endpoint_id); - } else { - analytics_recorder_->OnConnectionRequestSent(endpoint_id); - } -} - -void ClientProxy::OnConnectionAccepted(const std::string& endpoint_id) { - MutexLock lock(&mutex_); - - if (!HasPendingConnectionToEndpoint(endpoint_id)) { - NEARBY_LOGS(INFO) << "ClientProxy [Connection Accepted]: no pending " - "connection; endpoint_id=" - << endpoint_id; - return; - } - - // Notify the client. - Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - item->connection_listener.accepted_cb(endpoint_id); - item->status = Connection::kConnected; - } -} - -void ClientProxy::OnConnectionRejected(const std::string& endpoint_id, - const Status& status) { - MutexLock lock(&mutex_); - - if (!HasPendingConnectionToEndpoint(endpoint_id)) { - NEARBY_LOGS(INFO) << "ClientProxy [Connection Rejected]: no pending " - "connection; endpoint_id=" - << endpoint_id; - return; - } - - // Notify the client. - const Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - item->connection_listener.rejected_cb(endpoint_id, status); - OnDisconnected(endpoint_id, false /* notify */); - } -} - -void ClientProxy::OnBandwidthChanged(const std::string& endpoint_id, - Medium new_medium) { - MutexLock lock(&mutex_); - - const Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - item->connection_listener.bandwidth_changed_cb(endpoint_id, new_medium); - NEARBY_LOGS(INFO) << "ClientProxy [reporting onBandwidthChanged]: client=" - << GetClientId() << "; endpoint_id=" << endpoint_id; - } -} - -void ClientProxy::OnDisconnected(const std::string& endpoint_id, bool notify) { - MutexLock lock(&mutex_); - - const Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - if (notify) { - item->connection_listener.disconnected_cb({endpoint_id}); - } - connections_.erase(endpoint_id); - ResetLocalEndpointIdIfNeeded(); - } - - CancelEndpoint(endpoint_id); -} - -bool ClientProxy::ConnectionStatusMatches(const std::string& endpoint_id, - Connection::Status status) const { - MutexLock lock(&mutex_); - - const Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - return item->status == status; - } - return false; -} - -BooleanMediumSelector ClientProxy::GetUpgradeMediums( - const std::string& endpoint_id) const { - MutexLock lock(&mutex_); - - const Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - return item->connection_options.allowed; - } - return {}; -} - -bool ClientProxy::IsConnectedToEndpoint(const std::string& endpoint_id) const { - return ConnectionStatusMatches(endpoint_id, Connection::kConnected); -} - -std::vector<std::string> ClientProxy::GetMatchingEndpoints( - std::function<bool(const Connection&)> pred) const { - MutexLock lock(&mutex_); - - std::vector<std::string> connected_endpoints; - - for (const auto& pair : connections_) { - const auto& endpoint_id = pair.first; - const auto& connection = pair.second; - if (pred(connection)) { - connected_endpoints.push_back(endpoint_id); - } - } - return connected_endpoints; -} - -std::vector<std::string> ClientProxy::GetPendingConnectedEndpoints() const { - return GetMatchingEndpoints([](const Connection& connection) { - return connection.status != Connection::kConnected; - }); -} - -std::vector<std::string> ClientProxy::GetConnectedEndpoints() const { - return GetMatchingEndpoints([](const Connection& connection) { - return connection.status == Connection::kConnected; - }); -} - -std::int32_t ClientProxy::GetNumOutgoingConnections() const { - return GetMatchingEndpoints([](const Connection& connection) { - return connection.status == Connection::kConnected && - !connection.is_incoming; - }) - .size(); -} - -std::int32_t ClientProxy::GetNumIncomingConnections() const { - return GetMatchingEndpoints([](const Connection& connection) { - return connection.status == Connection::kConnected && - connection.is_incoming; - }) - .size(); -} - -bool ClientProxy::HasPendingConnectionToEndpoint( - const std::string& endpoint_id) const { - MutexLock lock(&mutex_); - - const Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - return item->status != Connection::kConnected; - } - return false; -} - -bool ClientProxy::HasLocalEndpointResponded( - const std::string& endpoint_id) const { - MutexLock lock(&mutex_); - - return ConnectionStatusesContains( - endpoint_id, - static_cast<Connection::Status>(Connection::kLocalEndpointAccepted | - Connection::kLocalEndpointRejected)); -} - -bool ClientProxy::HasRemoteEndpointResponded( - const std::string& endpoint_id) const { - MutexLock lock(&mutex_); - - return ConnectionStatusesContains( - endpoint_id, - static_cast<Connection::Status>(Connection::kRemoteEndpointAccepted | - Connection::kRemoteEndpointRejected)); -} - -void ClientProxy::LocalEndpointAcceptedConnection( - const std::string& endpoint_id, const PayloadListener& listener) { - MutexLock lock(&mutex_); - - if (HasLocalEndpointResponded(endpoint_id)) { - NEARBY_LOGS(INFO) - << "ClientProxy [Local Accepted]: local endpoint has responded; id=" - << endpoint_id; - return; - } - - AppendConnectionStatus(endpoint_id, Connection::kLocalEndpointAccepted); - Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - item->payload_listener = listener; - } - analytics_recorder_->OnLocalEndpointAccepted(endpoint_id); -} - -void ClientProxy::LocalEndpointRejectedConnection( - const std::string& endpoint_id) { - MutexLock lock(&mutex_); - - if (HasLocalEndpointResponded(endpoint_id)) { - NEARBY_LOGS(INFO) - << "ClientProxy [Local Rejected]: local endpoint has responded; id=" - << endpoint_id; - return; - } - - AppendConnectionStatus(endpoint_id, Connection::kLocalEndpointRejected); - analytics_recorder_->OnLocalEndpointRejected(endpoint_id); -} - -void ClientProxy::RemoteEndpointAcceptedConnection( - const std::string& endpoint_id) { - MutexLock lock(&mutex_); - - if (HasRemoteEndpointResponded(endpoint_id)) { - NEARBY_LOGS(INFO) - << "ClientProxy [Remote Accepted]: remote endpoint has responded; id=" - << endpoint_id; - return; - } - - AppendConnectionStatus(endpoint_id, Connection::kRemoteEndpointAccepted); - analytics_recorder_->OnRemoteEndpointAccepted(endpoint_id); -} - -void ClientProxy::RemoteEndpointRejectedConnection( - const std::string& endpoint_id) { - MutexLock lock(&mutex_); - - if (HasRemoteEndpointResponded(endpoint_id)) { - NEARBY_LOGS(INFO) - << "ClientProxy [Remote Rejected]: remote endpoint has responded; id=" - << endpoint_id; - return; - } - - AppendConnectionStatus(endpoint_id, Connection::kRemoteEndpointRejected); - analytics_recorder_->OnRemoteEndpointRejected(endpoint_id); -} - -bool ClientProxy::IsConnectionAccepted(const std::string& endpoint_id) const { - MutexLock lock(&mutex_); - - return ConnectionStatusesContains(endpoint_id, - Connection::kLocalEndpointAccepted) && - ConnectionStatusesContains(endpoint_id, - Connection::kRemoteEndpointAccepted); -} - -bool ClientProxy::IsConnectionRejected(const std::string& endpoint_id) const { - MutexLock lock(&mutex_); - - return ConnectionStatusesContains( - endpoint_id, - static_cast<Connection::Status>(Connection::kLocalEndpointRejected | - Connection::kRemoteEndpointRejected)); -} - -bool ClientProxy::LocalConnectionIsAccepted(std::string endpoint_id) const { - return ConnectionStatusesContains( - endpoint_id, ClientProxy::Connection::kLocalEndpointAccepted); -} - -bool ClientProxy::RemoteConnectionIsAccepted(std::string endpoint_id) const { - return ConnectionStatusesContains( - endpoint_id, ClientProxy::Connection::kRemoteEndpointAccepted); -} - -void ClientProxy::AddCancellationFlag(const std::string& endpoint_id) { - // Don't insert the CancellationFlag to the map if feature flag is disabled. - if (!FeatureFlags::GetInstance().GetFlags().enable_cancellation_flag) { - return; - } - - auto item = cancellation_flags_.find(endpoint_id); - if (item != cancellation_flags_.end()) { - return; - } - cancellation_flags_.emplace(endpoint_id, - std::make_unique<CancellationFlag>()); -} - -CancellationFlag* ClientProxy::GetCancellationFlag( - const std::string& endpoint_id) { - const auto item = cancellation_flags_.find(endpoint_id); - if (item == cancellation_flags_.end()) { - return default_cancellation_flag_.get(); - } - return item->second.get(); -} - -void ClientProxy::CancelEndpoint(const std::string& endpoint_id) { - const auto item = cancellation_flags_.find(endpoint_id); - if (item == cancellation_flags_.end()) return; - item->second->Cancel(); - cancellation_flags_.erase(item); -} - -void ClientProxy::CancelAllEndpoints() { - for (const auto& item : cancellation_flags_) { - CancellationFlag* cancellation_flag = item.second.get(); - if (cancellation_flag->Cancelled()) { - continue; - } - cancellation_flag->Cancel(); - } - cancellation_flags_.clear(); -} - -void ClientProxy::OnPayload(const std::string& endpoint_id, Payload payload) { - MutexLock lock(&mutex_); - - if (IsConnectedToEndpoint(endpoint_id)) { - const Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - NEARBY_LOGS(INFO) << "ClientProxy [reporting onPayloadReceived]: client=" - << GetClientId() << "; endpoint_id=" << endpoint_id - << " ; payload_id=" << payload.GetId(); - item->payload_listener.payload_cb(endpoint_id, std::move(payload)); - } - } -} - -const ClientProxy::Connection* ClientProxy::LookupConnection( - const std::string& endpoint_id) const { - auto item = connections_.find(endpoint_id); - return item != connections_.end() ? &item->second : nullptr; -} - -ClientProxy::Connection* ClientProxy::LookupConnection( - const std::string& endpoint_id) { - auto item = connections_.find(endpoint_id); - return item != connections_.end() ? &item->second : nullptr; -} - -void ClientProxy::OnPayloadProgress(const std::string& endpoint_id, - const PayloadProgressInfo& info) { - MutexLock lock(&mutex_); - - if (IsConnectedToEndpoint(endpoint_id)) { - Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - item->payload_listener.payload_progress_cb(endpoint_id, info); - - if (info.status == PayloadProgressInfo::Status::kInProgress) { - NEARBY_LOGS(VERBOSE) - << "ClientProxy [reporting onPayloadProgress]: client=" - << GetClientId() << "; endpoint_id=" << endpoint_id - << "; payload_id=" << info.payload_id - << ", payload_status=" << ToString(info.status); - } else { - NEARBY_LOGS(INFO) - << "ClientProxy [reporting onPayloadProgress]: client=" - << GetClientId() << "; endpoint_id=" << endpoint_id - << "; payload_id=" << info.payload_id - << ", payload_status=" << ToString(info.status); - } - } - } -} - -void ClientProxy::RemoveAllEndpoints() { - MutexLock lock(&mutex_); - - // Note: we may want to notify the client of onDisconnected() for each - // endpoint, in the case when this is called from stopAllEndpoints(). For now, - // just remove without notifying. - connections_.clear(); - cancellation_flags_.clear(); - local_endpoint_id_.clear(); -} - -void ClientProxy::ResetLocalEndpointIdIfNeeded() { - MutexLock lock(&mutex_); - if (connections_.empty() && !IsAdvertising() && !IsDiscovering()) { - local_endpoint_id_.clear(); - } -} - -bool ClientProxy::ConnectionStatusesContains( - const std::string& endpoint_id, Connection::Status status_to_match) const { - const Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - return (item->status & status_to_match) != 0; - } - return false; -} - -void ClientProxy::AppendConnectionStatus(const std::string& endpoint_id, - Connection::Status status_to_append) { - Connection* item = LookupConnection(endpoint_id); - if (item != nullptr) { - item->status = - static_cast<Connection::Status>(item->status | status_to_append); - } -} - -ConnectionOptions ClientProxy::GetAdvertisingOptions() const { - return advertising_options_; -} - -ConnectionOptions ClientProxy::GetDiscoveryOptions() const { - return discovery_options_; -} - -void ClientProxy::EnterHighVisibilityMode() { - MutexLock lock(&mutex_); - NEARBY_LOGS(INFO) << "ClientProxy [EnterHighVisibilityMode]: client=" - << GetClientId(); - - high_vis_mode_ = true; -} - -void ClientProxy::ExitHighVisibilityMode() { - MutexLock lock(&mutex_); - NEARBY_LOGS(INFO) << "ClientProxy [ExitHighVisibilityMode]: client=" - << GetClientId(); - - high_vis_mode_ = false; - ScheduleClearLocalHighVisModeCacheEndpointIdAlarm(); -} - -void ClientProxy::ScheduleClearLocalHighVisModeCacheEndpointIdAlarm() { - CancelClearLocalHighVisModeCacheEndpointIdAlarm(); - - if (local_high_vis_mode_cache_endpoint_id_.empty()) { - NEARBY_LOGS(VERBOSE) << "ClientProxy [There is no cached local high power " - "advertising endpoint Id]: client=" - << GetClientId(); - return; - } - - // Schedule to clear cache high visibility mode advertisement endpoint id in - // 30s. - NEARBY_LOGS(INFO) << "ClientProxy [High Visibility Mode Adv, Schedule to " - "Clear Cache EndpointId]: client=" - << GetClientId() - << "; local_high_vis_mode_cache_endpoint_id_=" - << local_high_vis_mode_cache_endpoint_id_; - clear_local_high_vis_mode_cache_endpoint_id_alarm_ = - CancelableAlarm( - "clear_high_power_endpoint_id_cache", - [this]() { - MutexLock lock(&mutex_); - NEARBY_LOGS(INFO) - << "ClientProxy [Cleared cached local high power advertising " - "endpoint Id.]: client=" - << GetClientId() << "; local_high_vis_mode_cache_endpoint_id_=" - << local_high_vis_mode_cache_endpoint_id_; - local_high_vis_mode_cache_endpoint_id_.clear(); - }, - kHighPowerAdvertisementEndpointIdCacheTimeout, - &single_thread_executor_); -} - -void ClientProxy::CancelClearLocalHighVisModeCacheEndpointIdAlarm() { - if (clear_local_high_vis_mode_cache_endpoint_id_alarm_.IsValid()) { - clear_local_high_vis_mode_cache_endpoint_id_alarm_.Cancel(); - clear_local_high_vis_mode_cache_endpoint_id_alarm_ = CancelableAlarm(); - } -} - -std::string ClientProxy::ToString(PayloadProgressInfo::Status status) const { - switch (status) { - case PayloadProgressInfo::Status::kSuccess: - return std::string("Success"); - case PayloadProgressInfo::Status::kFailure: - return std::string("Failure"); - case PayloadProgressInfo::Status::kInProgress: - return std::string("In Progress"); - case PayloadProgressInfo::Status::kCanceled: - return std::string("Cancelled"); - } -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/client_proxy.h b/chromium/third_party/nearby/src/cpp/core/internal/client_proxy.h deleted file mode 100644 index 8bf210f16a6..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/client_proxy.h +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_CLIENT_PROXY_H_ -#define CORE_INTERNAL_CLIENT_PROXY_H_ - -#include <cstdint> -#include <functional> -#include <string> -#include <vector> - -#include "analytics/analytics_recorder.h" -#include "core/listeners.h" -#include "core/options.h" -#include "core/status.h" -#include "core/strategy.h" -#include "platform/base/byte_array.h" -#include "platform/base/cancellation_flag.h" -#include "platform/base/error_code_recorder.h" -#include "platform/base/prng.h" -#include "platform/public/cancelable_alarm.h" -#include "platform/public/mutex.h" -// Prefer using absl:: versions of a set and a map; they tend to be more -// efficient: implementation is using open-addressing hash tables. -#include "absl/container/flat_hash_map.h" -#include "absl/container/flat_hash_set.h" -#include "absl/types/span.h" - -namespace location { -namespace nearby { -namespace connections { - -// CLientProxy is tracking state of client's connection, and serves as -// a proxy for notifications sent to this client. -class ClientProxy final { - public: - static constexpr int kEndpointIdLength = 4; - static constexpr absl::Duration - kHighPowerAdvertisementEndpointIdCacheTimeout = absl::Seconds(30); - - explicit ClientProxy(analytics::EventLogger* event_logger = nullptr); - ~ClientProxy(); - ClientProxy(ClientProxy&&) = default; - ClientProxy& operator=(ClientProxy&&) = default; - - std::int64_t GetClientId() const; - - std::string GetLocalEndpointId(); - - analytics::AnalyticsRecorder& GetAnalyticsRecorder() const { - return *analytics_recorder_; - } - - std::string GetConnectionToken(const std::string& endpoint_id); - - // Clears all the runtime state of this client. - void Reset(); - - // Marks this client as advertising with the given callbacks. - void StartedAdvertising( - const std::string& service_id, Strategy strategy, - const ConnectionListener& connection_lifecycle_listener, - absl::Span<proto::connections::Medium> mediums, - const ConnectionOptions& advertising_options = ConnectionOptions{}); - // Marks this client as not advertising. - void StoppedAdvertising(); - bool IsAdvertising() const; - std::string GetAdvertisingServiceId() const; - - // Get service ID of a surrently active link (either advertising, or - // discovering). - std::string GetServiceId() const; - - // Marks this client as discovering with the given callback. - void StartedDiscovery( - const std::string& service_id, Strategy strategy, - const DiscoveryListener& discovery_listener, - absl::Span<proto::connections::Medium> mediums, - const ConnectionOptions& discovery_options = ConnectionOptions{}); - // Marks this client as not discovering at all. - void StoppedDiscovery(); - bool IsDiscoveringServiceId(const std::string& service_id) const; - bool IsDiscovering() const; - std::string GetDiscoveryServiceId() const; - - // Proxies to the client's DiscoveryListener::OnEndpointFound() callback. - void OnEndpointFound(const std::string& service_id, - const std::string& endpoint_id, - const ByteArray& endpoint_info, - proto::connections::Medium medium); - // Proxies to the client's DiscoveryListener::OnEndpointLost() callback. - void OnEndpointLost(const std::string& service_id, - const std::string& endpoint_id); - - // Proxies to the client's ConnectionListener::OnInitiated() callback. - void OnConnectionInitiated(const std::string& endpoint_id, - const ConnectionResponseInfo& info, - const ConnectionOptions& options, - const ConnectionListener& listener, - const std::string& connection_token); - - // Proxies to the client's ConnectionListener::OnAccepted() callback. - void OnConnectionAccepted(const std::string& endpoint_id); - // Proxies to the client's ConnectionListener::OnRejected() callback. - void OnConnectionRejected(const std::string& endpoint_id, - const Status& status); - - void OnBandwidthChanged(const std::string& endpoint_id, Medium new_medium); - - // Removes the endpoint from this client's list of connected endpoints. If - // notify is true, also calls the client's - // ConnectionListener.disconnected_cb() callback. - void OnDisconnected(const std::string& endpoint_id, bool notify); - - // Returns all mediums eligible for upgrade. - BooleanMediumSelector GetUpgradeMediums(const std::string& endpoint_id) const; - // Returns true if it's safe to send payloads to this endpoint. - bool IsConnectedToEndpoint(const std::string& endpoint_id) const; - // Returns all endpoints that can safely be sent payloads. - std::vector<std::string> GetConnectedEndpoints() const; - // Returns all endpoints that are still awaiting acceptance. - std::vector<std::string> GetPendingConnectedEndpoints() const; - // Returns the number of endpoints that are connected and outgoing. - std::int32_t GetNumOutgoingConnections() const; - // Returns the number of endpoints that are connected and incoming. - std::int32_t GetNumIncomingConnections() const; - // If true, then we're in the process of approving (or rejecting) a - // connection. No payloads should be sent until isConnectedToEndpoint() - // returns true. - bool HasPendingConnectionToEndpoint(const std::string& endpoint_id) const; - // Returns true if the local endpoint has already marked itself as - // accepted/rejected. - bool HasLocalEndpointResponded(const std::string& endpoint_id) const; - // Returns true if the remote endpoint has already marked themselves as - // accepted/rejected. - bool HasRemoteEndpointResponded(const std::string& endpoint_id) const; - // Marks the local endpoint as having accepted the connection. - void LocalEndpointAcceptedConnection(const std::string& endpoint_id, - const PayloadListener& listener); - // Marks the local endpoint as having rejected the connection. - void LocalEndpointRejectedConnection(const std::string& endpoint_id); - // Marks the remote endpoint as having accepted the connection. - void RemoteEndpointAcceptedConnection(const std::string& endpoint_id); - // Marks the remote endpoint as having rejected the connection. - void RemoteEndpointRejectedConnection(const std::string& endpoint_id); - // Returns true if both the local endpoint and the remote endpoint have - // accepted the connection. - bool IsConnectionAccepted(const std::string& endpoint_id) const; - // Returns true if either the local endpoint or the remote endpoint has - // rejected the connection. - bool IsConnectionRejected(const std::string& endpoint_id) const; - - // Proxies to the client's PayloadListener::OnPayload() callback. - void OnPayload(const std::string& endpoint_id, Payload payload); - // Proxies to the client's PayloadListener::OnPayloadProgress() callback. - void OnPayloadProgress(const std::string& endpoint_id, - const PayloadProgressInfo& info); - bool LocalConnectionIsAccepted(std::string endpoint_id) const; - bool RemoteConnectionIsAccepted(std::string endpoint_id) const; - - // Adds a CancellationFlag for endpoint id. - void AddCancellationFlag(const std::string& endpoint_id); - // Returns the CancellationFlag for endpoint id, - CancellationFlag* GetCancellationFlag(const std::string& endpoint_id); - // Sets the CancellationFlag to true for endpoint id. - void CancelEndpoint(const std::string& endpoint_id); - // Cancels all CancellationFlags. - void CancelAllEndpoints(); - ConnectionOptions GetAdvertisingOptions() const; - ConnectionOptions GetDiscoveryOptions() const; - - // The endpoint id will be stable for 30 seconds after high visibility mode - // (high power and Bluetooth Classic) advertisement stops. - // If client re-enters high visibility mode within 30 seconds, he is going to - // have the same endpoint id. - void EnterHighVisibilityMode(); - // Cleans up any modifications in high visibility mode. The endpoint id always - // rotates. - void ExitHighVisibilityMode(); - - private: - struct Connection { - // Status: may be either: - // Connection::PENDING, or combination of - // Connection::LOCAL_ENDPOINT_ACCEPTED: - // Connection::LOCAL_ENDPOINT_REJECTED and - // Connection::REMOTE_ENDPOINT_ACCEPTED: - // Connection::REMOTE_ENDPOINT_REJECTED, or - // Connection::CONNECTED. - // Only when this is set to CONNECTED should you allow payload transfers. - // - // We want this enum to be implicitly convertible to int, because - // we perform bit operations on it. - enum Status : uint8_t { - kPending = 0, - kLocalEndpointAccepted = 1 << 0, - kLocalEndpointRejected = 1 << 1, - kRemoteEndpointAccepted = 1 << 2, - kRemoteEndpointRejected = 1 << 3, - kConnected = 1 << 4, - }; - bool is_incoming{false}; - Status status{kPending}; - ConnectionListener connection_listener; - PayloadListener payload_listener; - ConnectionOptions connection_options; - std::string connection_token; - }; - - struct AdvertisingInfo { - std::string service_id; - ConnectionListener listener; - void Clear() { service_id.clear(); } - bool IsEmpty() const { return service_id.empty(); } - }; - - struct DiscoveryInfo { - std::string service_id; - DiscoveryListener listener; - void Clear() { service_id.clear(); } - bool IsEmpty() const { return service_id.empty(); } - }; - - void RemoveAllEndpoints(); - void ResetLocalEndpointIdIfNeeded(); - bool ConnectionStatusesContains(const std::string& endpoint_id, - Connection::Status status_to_match) const; - void AppendConnectionStatus(const std::string& endpoint_id, - Connection::Status status_to_append); - - const Connection* LookupConnection(const std::string& endpoint_id) const; - Connection* LookupConnection(const std::string& endpoint_id); - bool ConnectionStatusMatches(const std::string& endpoint_id, - Connection::Status status) const; - std::vector<std::string> GetMatchingEndpoints( - std::function<bool(const Connection&)> pred) const; - std::string GenerateLocalEndpointId(); - - void ScheduleClearLocalHighVisModeCacheEndpointIdAlarm(); - void CancelClearLocalHighVisModeCacheEndpointIdAlarm(); - - std::string ToString(PayloadProgressInfo::Status status) const; - - mutable RecursiveMutex mutex_; - Prng prng_; - std::int64_t client_id_; - std::string local_endpoint_id_; - // If currently is advertising in high visibility mode is true: high power and - // Bluetooth Classic enabled. When high_visibility_mode_ is true, the endpoint - // id is stable for 30s. When high_visibility_mode_ is false, the endpoint id - // always rotates. - bool high_vis_mode_{false}; - // Caches the endpoint id when it is in high visibility mode advertisement for - // 30s. Currently, Nearby Connections keeps rotating endpoint id. The client - // (Nearby Share) treats different endpoints as different receivers, duplicate - // share targets for same devices occur on share sheet in this case. - // Therefore, we remember the high visibility mode advertisement endpoint id - // here. empty if 1) There is no high power advertisement before 2) The - // endpoint id cached here in previous high visibility mode advertisement - // expires. - std::string local_high_vis_mode_cache_endpoint_id_; - ScheduledExecutor single_thread_executor_; - CancelableAlarm clear_local_high_vis_mode_cache_endpoint_id_alarm_; - - // If not empty, we are currently advertising and accepting connection - // requests for the given service_id. - AdvertisingInfo advertising_info_; - - // If not empty, we are currently discovering for the given service_id. - DiscoveryInfo discovery_info_; - - // The active ClientProxy's advertising constraints. Empty() - // returns true if the client hasn't started advertising false otherwise. - // Note: this is not cleared when the client stops advertising because it - // might still be useful downstream of advertising (eg: establishing - // connections, performing bandwidth upgrades, etc.) - ConnectionOptions advertising_options_; - - // The active ClientProxy's discovery constraints. Null if the client - // hasn't started discovering. Note: this is not cleared when the client - // stops discovering because it might still be useful downstream of - // discovery (eg: connection speed, etc.) - ConnectionOptions discovery_options_; - - // Maps endpoint_id to endpoint connection state. - absl::flat_hash_map<std::string, Connection> connections_; - - // A cache of endpoint ids that we've already notified the discoverer of. We - // check this cache before calling onEndpointFound() so that we don't notify - // the client multiple times for the same endpoint. This would otherwise - // happen because some mediums (like Bluetooth) repeatedly give us the same - // endpoints after each scan. - absl::flat_hash_set<std::string> discovered_endpoint_ids_; - - // Maps endpoint_id to CancellationFlag. - absl::flat_hash_map<std::string, std::unique_ptr<CancellationFlag>> - cancellation_flags_; - // A default cancellation flag with isCancelled set be true. - std::unique_ptr<CancellationFlag> default_cancellation_flag_ = - std::make_unique<CancellationFlag>(true); - - // An analytics logger with |EventLogger| provided by client, which is default - // nullptr as no-op. - std::unique_ptr<analytics::AnalyticsRecorder> analytics_recorder_; - std::unique_ptr<ErrorCodeRecorder> error_code_recorder_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_CLIENT_PROXY_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/client_proxy_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/client_proxy_test.cc deleted file mode 100644 index 61038279636..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/client_proxy_test.cc +++ /dev/null @@ -1,622 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/client_proxy.h" - -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/flat_hash_set.h" -#include "absl/time/clock.h" -#include "absl/time/time.h" -#include "absl/types/span.h" -#include "core/listeners.h" -#include "core/options.h" -#include "core/strategy.h" -#include "platform/base/byte_array.h" -#include "platform/base/feature_flags.h" -#include "platform/base/medium_environment.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -using FeatureFlags = FeatureFlags::Flags; -using ::testing::MockFunction; -using ::testing::StrictMock; - -constexpr FeatureFlags kTestCases[] = { - FeatureFlags{ - .enable_cancellation_flag = true, - }, - FeatureFlags{ - .enable_cancellation_flag = false, - }, -}; - -class ClientProxyTest : public ::testing::TestWithParam<FeatureFlags> { - protected: - struct MockDiscoveryListener { - StrictMock<MockFunction<void(const std::string& endpoint_id, - const ByteArray& endpoint_info, - const std::string& service_id)>> - endpoint_found_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id)>> - endpoint_lost_cb; - }; - struct MockConnectionListener { - StrictMock<MockFunction<void(const std::string& endpoint_id, - const ConnectionResponseInfo& info)>> - initiated_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id)>> accepted_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id, - const Status& status)>> - rejected_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id)>> - disconnected_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id, - std::int32_t quality)>> - bandwidth_changed_cb; - }; - struct MockPayloadListener { - StrictMock< - MockFunction<void(const std::string& endpoint_id, Payload payload)>> - payload_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id, - const PayloadProgressInfo& info)>> - payload_progress_cb; - }; - - struct Endpoint { - ByteArray info; - std::string id; - }; - - bool ShouldEnterHighVisibilityMode(const ConnectionOptions& options) { - return !options.low_power && options.allowed.bluetooth; - } - - Endpoint StartAdvertising( - ClientProxy* client, ConnectionListener listener, - ConnectionOptions advertising_options = ConnectionOptions{}) { - if (ShouldEnterHighVisibilityMode(advertising_options)) { - client->EnterHighVisibilityMode(); - } - Endpoint endpoint{ - .info = ByteArray{"advertising endpoint name"}, - .id = client->GetLocalEndpointId(), - }; - client->StartedAdvertising(service_id_, strategy_, listener, - absl::MakeSpan(mediums_), advertising_options); - return endpoint; - } - - void StopAdvertising(ClientProxy* client) { client->StoppedAdvertising(); } - - Endpoint StartDiscovery(ClientProxy* client, DiscoveryListener listener) { - Endpoint endpoint{ - .info = ByteArray{"discovery endpoint name"}, - .id = client->GetLocalEndpointId(), - }; - client->StartedDiscovery(service_id_, strategy_, listener, - absl::MakeSpan(mediums_)); - return endpoint; - } - - void OnDiscoveryEndpointFound(ClientProxy* client, const Endpoint& endpoint) { - EXPECT_CALL(mock_discovery_.endpoint_found_cb, Call).Times(1); - client->OnEndpointFound(service_id_, endpoint.id, endpoint.info, medium_); - } - - void OnDiscoveryEndpointLost(ClientProxy* client, const Endpoint& endpoint) { - EXPECT_CALL(mock_discovery_.endpoint_lost_cb, Call).Times(1); - client->OnEndpointLost(service_id_, endpoint.id); - } - - void OnDiscoveryConnectionInitiated(ClientProxy* client, - const Endpoint& endpoint) { - EXPECT_CALL(mock_discovery_connection_.initiated_cb, Call).Times(1); - const std::string auth_token{"auth_token"}; - const ByteArray raw_auth_token{auth_token}; - const std::string connection_token{"conntokn"}; - advertising_connection_info_.remote_endpoint_info = endpoint.info; - client->OnConnectionInitiated( - endpoint.id, advertising_connection_info_, connection_options_, - discovery_connection_listener_, connection_token); - EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint.id)); - } - - void OnDiscoveryConnectionLocalAccepted(ClientProxy* client, - const Endpoint& endpoint) { - EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint.id)); - EXPECT_FALSE(client->HasLocalEndpointResponded(endpoint.id)); - client->LocalEndpointAcceptedConnection(endpoint.id, payload_listener_); - EXPECT_TRUE(client->HasLocalEndpointResponded(endpoint.id)); - EXPECT_TRUE(client->LocalConnectionIsAccepted(endpoint.id)); - } - - void OnDiscoveryConnectionRemoteAccepted(ClientProxy* client, - const Endpoint& endpoint) { - EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint.id)); - EXPECT_FALSE(client->HasRemoteEndpointResponded(endpoint.id)); - client->RemoteEndpointAcceptedConnection(endpoint.id); - EXPECT_TRUE(client->HasRemoteEndpointResponded(endpoint.id)); - EXPECT_TRUE(client->RemoteConnectionIsAccepted(endpoint.id)); - } - - void OnDiscoveryConnectionLocalRejected(ClientProxy* client, - const Endpoint& endpoint) { - EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint.id)); - EXPECT_FALSE(client->HasLocalEndpointResponded(endpoint.id)); - client->LocalEndpointRejectedConnection(endpoint.id); - EXPECT_TRUE(client->HasLocalEndpointResponded(endpoint.id)); - EXPECT_FALSE(client->LocalConnectionIsAccepted(endpoint.id)); - } - - void OnDiscoveryConnectionRemoteRejected(ClientProxy* client, - const Endpoint& endpoint) { - EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint.id)); - EXPECT_FALSE(client->HasRemoteEndpointResponded(endpoint.id)); - client->RemoteEndpointRejectedConnection(endpoint.id); - EXPECT_TRUE(client->HasRemoteEndpointResponded(endpoint.id)); - EXPECT_FALSE(client->RemoteConnectionIsAccepted(endpoint.id)); - } - - void OnDiscoveryConnectionAccepted(ClientProxy* client, - const Endpoint& endpoint) { - EXPECT_CALL(mock_discovery_connection_.accepted_cb, Call).Times(1); - EXPECT_TRUE(client->IsConnectionAccepted(endpoint.id)); - client->OnConnectionAccepted(endpoint.id); - } - - void OnDiscoveryConnectionRejected(ClientProxy* client, - const Endpoint& endpoint) { - EXPECT_CALL(mock_discovery_connection_.rejected_cb, Call).Times(1); - EXPECT_TRUE(client->IsConnectionRejected(endpoint.id)); - client->OnConnectionRejected(endpoint.id, {Status::kConnectionRejected}); - } - - void OnDiscoveryBandwidthChanged(ClientProxy* client, - const Endpoint& endpoint) { - EXPECT_CALL(mock_discovery_connection_.bandwidth_changed_cb, Call).Times(1); - client->OnBandwidthChanged(endpoint.id, Medium::WIFI_LAN); - } - - void OnDiscoveryConnectionDisconnected(ClientProxy* client, - const Endpoint& endpoint) { - EXPECT_CALL(mock_discovery_connection_.disconnected_cb, Call).Times(1); - client->OnDisconnected(endpoint.id, true); - } - - void OnPayload(ClientProxy* client, const Endpoint& endpoint) { - EXPECT_CALL(mock_discovery_payload_.payload_cb, Call).Times(1); - client->OnPayload(endpoint.id, Payload(payload_bytes_)); - } - - void OnPayloadProgress(ClientProxy* client, const Endpoint& endpoint) { - EXPECT_CALL(mock_discovery_payload_.payload_progress_cb, Call).Times(1); - client->OnPayloadProgress(endpoint.id, {}); - } - - MockDiscoveryListener mock_discovery_; - MockConnectionListener mock_discovery_connection_; - MockPayloadListener mock_discovery_payload_; - - proto::connections::Medium medium_{proto::connections::Medium::BLUETOOTH}; - std::vector<proto::connections::Medium> mediums_{ - proto::connections::Medium::BLUETOOTH, - }; - Strategy strategy_{Strategy::kP2pPointToPoint}; - const std::string service_id_{"service"}; - ClientProxy client1_; - ClientProxy client2_; - std::string auth_token_ = "auth_token"; - ByteArray raw_auth_token_ = ByteArray(auth_token_); - ByteArray payload_bytes_{"bytes"}; - ConnectionResponseInfo advertising_connection_info_{ - .authentication_token = auth_token_, - .raw_authentication_token = raw_auth_token_, - .is_incoming_connection = true, - }; - ConnectionListener advertising_connection_listener_; - ConnectionListener discovery_connection_listener_{ - .initiated_cb = mock_discovery_connection_.initiated_cb.AsStdFunction(), - .accepted_cb = mock_discovery_connection_.accepted_cb.AsStdFunction(), - .rejected_cb = mock_discovery_connection_.rejected_cb.AsStdFunction(), - .disconnected_cb = - mock_discovery_connection_.disconnected_cb.AsStdFunction(), - .bandwidth_changed_cb = - mock_discovery_connection_.bandwidth_changed_cb.AsStdFunction(), - }; - DiscoveryListener discovery_listener_{ - .endpoint_found_cb = mock_discovery_.endpoint_found_cb.AsStdFunction(), - .endpoint_lost_cb = mock_discovery_.endpoint_lost_cb.AsStdFunction(), - }; - PayloadListener payload_listener_{ - .payload_cb = mock_discovery_payload_.payload_cb.AsStdFunction(), - .payload_progress_cb = - mock_discovery_payload_.payload_progress_cb.AsStdFunction(), - }; - ConnectionOptions connection_options_; -}; - -TEST_P(ClientProxyTest, CanCancelEndpoint) { - FeatureFlags feature_flags = GetParam(); - MediumEnvironment::Instance().SetFeatureFlags(feature_flags); - - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); - OnDiscoveryConnectionInitiated(&client2_, advertising_endpoint); - - EXPECT_FALSE( - client2_.GetCancellationFlag(advertising_endpoint.id)->Cancelled()); - - client2_.CancelEndpoint(advertising_endpoint.id); - - // If FeatureFlag is disabled, Cancelled is false as no-op. - if (!feature_flags.enable_cancellation_flag) { - EXPECT_FALSE( - client2_.GetCancellationFlag(advertising_endpoint.id)->Cancelled()); - } else { - // The Cancelled is always true as the default flag being returned. - EXPECT_TRUE( - client2_.GetCancellationFlag(advertising_endpoint.id)->Cancelled()); - } -} - -TEST_P(ClientProxyTest, CanCancelAllEndpoints) { - FeatureFlags feature_flags = GetParam(); - MediumEnvironment::Instance().SetFeatureFlags(feature_flags); - - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); - OnDiscoveryConnectionInitiated(&client2_, advertising_endpoint); - - EXPECT_FALSE( - client2_.GetCancellationFlag(advertising_endpoint.id)->Cancelled()); - - client2_.CancelAllEndpoints(); - - // If FeatureFlag is disabled, Cancelled is false as no-op. - if (!feature_flags.enable_cancellation_flag) { - EXPECT_FALSE( - client2_.GetCancellationFlag(advertising_endpoint.id)->Cancelled()); - } else { - // The Cancelled is always true as the default flag being returned. - EXPECT_TRUE( - client2_.GetCancellationFlag(advertising_endpoint.id)->Cancelled()); - } -} - -TEST_P(ClientProxyTest, CanCancelAllEndpointsWithDifferentEndpoint) { - FeatureFlags feature_flags = GetParam(); - MediumEnvironment::Instance().SetFeatureFlags(feature_flags); - - ConnectionListener advertising_connection_listener_2; - ConnectionListener advertising_connection_listener_3; - ClientProxy client3; - - StartDiscovery(&client1_, discovery_listener_); - Endpoint advertising_endpoint_2 = - StartAdvertising(&client2_, advertising_connection_listener_2); - Endpoint advertising_endpoint_3 = - StartAdvertising(&client3, advertising_connection_listener_3); - OnDiscoveryEndpointFound(&client1_, advertising_endpoint_2); - OnDiscoveryConnectionInitiated(&client1_, advertising_endpoint_2); - OnDiscoveryEndpointFound(&client1_, advertising_endpoint_3); - OnDiscoveryConnectionInitiated(&client1_, advertising_endpoint_3); - - // The CancellationFlag of endpoint_2 and endpoint_3 have been added. Default - // Cancelled is false. - EXPECT_FALSE( - client1_.GetCancellationFlag(advertising_endpoint_2.id)->Cancelled()); - EXPECT_FALSE( - client1_.GetCancellationFlag(advertising_endpoint_3.id)->Cancelled()); - - client1_.CancelAllEndpoints(); - - if (!feature_flags.enable_cancellation_flag) { - // The CancellationFlag of endpoint_2 and endpoint_3 will not be removed - // since it is not added. The default flag returned as Cancelled being true, - // but Cancelled requested is false since the FeatureFlag is off. - EXPECT_FALSE( - client1_.GetCancellationFlag(advertising_endpoint_2.id)->Cancelled()); - EXPECT_FALSE( - client1_.GetCancellationFlag(advertising_endpoint_3.id)->Cancelled()); - } else { - // Expect the CancellationFlag of endpoint_2 and endpoint_3 has been - // removed. The Cancelled is always true as the default flag being returned. - EXPECT_TRUE( - client1_.GetCancellationFlag(advertising_endpoint_2.id)->Cancelled()); - EXPECT_TRUE( - client1_.GetCancellationFlag(advertising_endpoint_3.id)->Cancelled()); - } -} - -INSTANTIATE_TEST_SUITE_P(ParametrisedClientProxyTest, ClientProxyTest, - ::testing::ValuesIn(kTestCases)); - -TEST_F(ClientProxyTest, ConstructorDestructorWorks) { SUCCEED(); } - -TEST_F(ClientProxyTest, ClientIdIsUnique) { - EXPECT_NE(client1_.GetClientId(), client2_.GetClientId()); -} - -TEST_F(ClientProxyTest, GeneratedEndpointIdIsUnique) { - EXPECT_NE(client1_.GetLocalEndpointId(), client2_.GetLocalEndpointId()); -} - -TEST_F(ClientProxyTest, ResetClearsState) { - client1_.Reset(); - EXPECT_FALSE(client1_.IsAdvertising()); - EXPECT_FALSE(client1_.IsDiscovering()); - EXPECT_TRUE(client1_.GetAdvertisingServiceId().empty()); - EXPECT_TRUE(client1_.GetDiscoveryServiceId().empty()); -} - -TEST_F(ClientProxyTest, StartedAdvertisingChangesStateFromIdle) { - client1_.StartedAdvertising(service_id_, strategy_, {}, {}); - - EXPECT_TRUE(client1_.IsAdvertising()); - EXPECT_FALSE(client1_.IsDiscovering()); - EXPECT_EQ(client1_.GetAdvertisingServiceId(), service_id_); - EXPECT_TRUE(client1_.GetDiscoveryServiceId().empty()); -} - -TEST_F(ClientProxyTest, StartedDiscoveryChangesStateFromIdle) { - client1_.StartedDiscovery(service_id_, strategy_, {}, {}); - - EXPECT_FALSE(client1_.IsAdvertising()); - EXPECT_TRUE(client1_.IsDiscovering()); - EXPECT_TRUE(client1_.GetAdvertisingServiceId().empty()); - EXPECT_EQ(client1_.GetDiscoveryServiceId(), service_id_); -} - -TEST_F(ClientProxyTest, OnEndpointFoundFiresNotificationInDiscovery) { - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); -} - -TEST_F(ClientProxyTest, OnEndpointLostFiresNotificationInDiscovery) { - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); - OnDiscoveryEndpointLost(&client2_, advertising_endpoint); -} - -TEST_F(ClientProxyTest, OnConnectionInitiatedFiresNotificationInDiscovery) { - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); - OnDiscoveryConnectionInitiated(&client2_, advertising_endpoint); -} - -TEST_F(ClientProxyTest, OnBandwidthChangedFiresNotificationInDiscovery) { - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); - OnDiscoveryConnectionInitiated(&client2_, advertising_endpoint); - OnDiscoveryConnectionLocalAccepted(&client2_, advertising_endpoint); - OnDiscoveryConnectionRemoteAccepted(&client2_, advertising_endpoint); - OnDiscoveryConnectionAccepted(&client2_, advertising_endpoint); - OnDiscoveryBandwidthChanged(&client2_, advertising_endpoint); -} - -TEST_F(ClientProxyTest, OnDisconnectedFiresNotificationInDiscovery) { - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); - OnDiscoveryConnectionInitiated(&client2_, advertising_endpoint); - OnDiscoveryConnectionDisconnected(&client2_, advertising_endpoint); -} - -TEST_F(ClientProxyTest, LocalEndpointAcceptedConnectionChangesState) { - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); - OnDiscoveryConnectionInitiated(&client2_, advertising_endpoint); - OnDiscoveryConnectionLocalAccepted(&client2_, advertising_endpoint); -} - -TEST_F(ClientProxyTest, LocalEndpointRejectedConnectionChangesState) { - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); - OnDiscoveryConnectionInitiated(&client2_, advertising_endpoint); - OnDiscoveryConnectionLocalRejected(&client2_, advertising_endpoint); -} - -TEST_F(ClientProxyTest, RemoteEndpointAcceptedConnectionChangesState) { - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); - OnDiscoveryConnectionInitiated(&client2_, advertising_endpoint); - OnDiscoveryConnectionRemoteAccepted(&client2_, advertising_endpoint); -} - -TEST_F(ClientProxyTest, RemoteEndpointRejectedConnectionChangesState) { - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); - OnDiscoveryConnectionInitiated(&client2_, advertising_endpoint); - OnDiscoveryConnectionRemoteRejected(&client2_, advertising_endpoint); -} - -TEST_F(ClientProxyTest, OnPayloadChangesState) { - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); - OnDiscoveryConnectionInitiated(&client2_, advertising_endpoint); - OnDiscoveryConnectionLocalAccepted(&client2_, advertising_endpoint); - OnDiscoveryConnectionRemoteAccepted(&client2_, advertising_endpoint); - OnDiscoveryConnectionAccepted(&client2_, advertising_endpoint); - OnPayload(&client2_, advertising_endpoint); -} - -TEST_F(ClientProxyTest, OnPayloadProgressChangesState) { - Endpoint advertising_endpoint = - StartAdvertising(&client1_, advertising_connection_listener_); - StartDiscovery(&client2_, discovery_listener_); - OnDiscoveryEndpointFound(&client2_, advertising_endpoint); - OnDiscoveryConnectionInitiated(&client2_, advertising_endpoint); - OnDiscoveryConnectionLocalAccepted(&client2_, advertising_endpoint); - OnDiscoveryConnectionRemoteAccepted(&client2_, advertising_endpoint); - OnDiscoveryConnectionAccepted(&client2_, advertising_endpoint); - OnPayloadProgress(&client2_, advertising_endpoint); -} - -TEST_F(ClientProxyTest, - EndpointIdCacheWhenHighVizAdvertisementAgainImmediately) { - ConnectionOptions advertising_options{.strategy = strategy_, - .allowed = - { - .bluetooth = true, - }, - .low_power = false}; - - Endpoint advertising_endpoint_1 = StartAdvertising( - &client1_, advertising_connection_listener_, advertising_options); - - StopAdvertising(&client1_); - - // Advertise immediately. - Endpoint advertising_endpoint_2 = StartAdvertising( - &client1_, advertising_connection_listener_, advertising_options); - - EXPECT_EQ(advertising_endpoint_1.id, advertising_endpoint_2.id); -} - -TEST_F(ClientProxyTest, - EndpointIdRotateWhenHighVizAdvertisementAgainForAWhile) { - ConnectionOptions advertising_options{.strategy = strategy_, - .allowed = - { - .bluetooth = true, - }, - .low_power = false}; - - Endpoint advertising_endpoint_1 = StartAdvertising( - &client1_, advertising_connection_listener_, advertising_options); - - StopAdvertising(&client1_); - - // Wait to expire and then advertise. - absl::SleepFor(ClientProxy::kHighPowerAdvertisementEndpointIdCacheTimeout + - absl::Milliseconds(100)); - Endpoint advertising_endpoint_2 = StartAdvertising( - &client1_, advertising_connection_listener_, advertising_options); - - EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id); -} - -TEST_F(ClientProxyTest, - EndpointIdRotateWhenLowVizAdvertisementAfterHighVizAdvertisement) { - ConnectionOptions high_viz_advertising_options{.strategy = strategy_, - .allowed = - { - .bluetooth = true, - }, - .low_power = false}; - Endpoint advertising_endpoint_1 = - StartAdvertising(&client1_, advertising_connection_listener_, - high_viz_advertising_options); - - StopAdvertising(&client1_); - - ConnectionOptions low_viz_advertising_options{.strategy = strategy_, - .low_power = true}; - - Endpoint advertising_endpoint_2 = StartAdvertising( - &client1_, advertising_connection_listener_, low_viz_advertising_options); - - EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id); -} - -// Tests endpoint_id rotates when discover. -TEST_F(ClientProxyTest, EndpointIdRotateWhenStartDiscovery) { - ConnectionOptions advertising_options{.strategy = strategy_, - .allowed = - { - .bluetooth = true, - }, - .low_power = false}; - - Endpoint advertising_endpoint_1 = StartAdvertising( - &client1_, advertising_connection_listener_, advertising_options); - - StopAdvertising(&client1_); - StartDiscovery(&client1_, discovery_listener_); - - Endpoint advertising_endpoint_2 = StartAdvertising( - &client1_, advertising_connection_listener_, advertising_options); - - EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id); -} - -// Tests the low visibility mode with bluetooth disabled advertisment. -TEST_F(ClientProxyTest, - EndpointIdRotateWhenLowVizAdvertisementWithBluetoothDisabled) { - ConnectionOptions advertising_options{.strategy = strategy_, - .allowed = { - .bluetooth = false, - }}; - - Endpoint advertising_endpoint_1 = StartAdvertising( - &client1_, advertising_connection_listener_, advertising_options); - - StopAdvertising(&client1_); - - Endpoint advertising_endpoint_2 = StartAdvertising( - &client1_, advertising_connection_listener_, advertising_options); - - EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id); -} - -// Tests the low visibility mode with low power advertisment. -TEST_F(ClientProxyTest, EndpointIdRotateWhenLowVizAdvertisementWithLowPower) { - ConnectionOptions advertising_options{.strategy = strategy_, - .low_power = true}; - - Endpoint advertising_endpoint_1 = StartAdvertising( - &client1_, advertising_connection_listener_, advertising_options); - - StopAdvertising(&client1_); - - Endpoint advertising_endpoint_2 = StartAdvertising( - &client1_, advertising_connection_listener_, advertising_options); - - EXPECT_NE(advertising_endpoint_1.id, advertising_endpoint_2.id); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/encryption_runner.cc b/chromium/third_party/nearby/src/cpp/core/internal/encryption_runner.cc deleted file mode 100644 index e81f6065791..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/encryption_runner.cc +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/encryption_runner.h" - -#include <cinttypes> -#include <cstdint> -#include <memory> - -#include "securegcm/ukey2_handshake.h" -#include "absl/strings/ascii.h" -#include "absl/time/clock.h" -#include "absl/time/time.h" -#include "platform/base/base64_utils.h" -#include "platform/base/byte_array.h" -#include "platform/base/exception.h" -#include "platform/public/cancelable_alarm.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -constexpr absl::Duration kTimeout = absl::Seconds(15); -constexpr std::int32_t kMaxUkey2VerificationStringLength = 32; -constexpr std::int32_t kTokenLength = 5; -constexpr securegcm::UKey2Handshake::HandshakeCipher kCipher = - securegcm::UKey2Handshake::HandshakeCipher::P256_SHA512; - -// Transforms a raw UKEY2 token (which is a random ByteArray that's -// kMaxUkey2VerificationStringLength long) into a kTokenLength string that only -// uses [A-Z], [0-9], '_', '-' for each character. -std::string ToHumanReadableString(const ByteArray& token) { - std::string result = Base64Utils::Encode(token).substr(0, kTokenLength); - absl::AsciiStrToUpper(&result); - return result; -} - -bool HandleEncryptionSuccess(const std::string& endpoint_id, - std::unique_ptr<securegcm::UKey2Handshake> ukey2, - const EncryptionRunner::ResultListener& listener) { - std::unique_ptr<std::string> verification_string = - ukey2->GetVerificationString(kMaxUkey2VerificationStringLength); - if (verification_string == nullptr) { - return false; - } - - ByteArray raw_authentication_token(*verification_string); - - listener.on_success_cb(endpoint_id, std::move(ukey2), - ToHumanReadableString(raw_authentication_token), - raw_authentication_token); - - return true; -} - -void CancelableAlarmRunnable(ClientProxy* client, - const std::string& endpoint_id, - EndpointChannel* endpoint_channel) { - NEARBY_LOGS(INFO) << "Timing out encryption for client " - << client->GetClientId() - << " to endpoint_id=" << endpoint_id << " after " - << absl::FormatDuration(kTimeout); - endpoint_channel->Close(); -} - -class ServerRunnable final { - public: - ServerRunnable(ClientProxy* client, ScheduledExecutor* alarm_executor, - const std::string& endpoint_id, EndpointChannel* channel, - EncryptionRunner::ResultListener&& listener) - : client_(client), - alarm_executor_(alarm_executor), - endpoint_id_(endpoint_id), - channel_(channel), - listener_(std::move(listener)) {} - - void operator()() const { - CancelableAlarm timeout_alarm( - "EncryptionRunner.StartServer() timeout", - [this]() { CancelableAlarmRunnable(client_, endpoint_id_, channel_); }, - kTimeout, alarm_executor_); - - std::unique_ptr<securegcm::UKey2Handshake> server = - securegcm::UKey2Handshake::ForResponder(kCipher); - if (server == nullptr) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - // Message 1 (Client Init) - ExceptionOr<ByteArray> client_init = channel_->Read(); - if (!client_init.ok()) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - securegcm::UKey2Handshake::ParseResult parse_result = - server->ParseHandshakeMessage(std::string(client_init.result())); - - // Java code throws a HandshakeException / AlertException. - if (!parse_result.success) { - LogException(); - if (parse_result.alert_to_send != nullptr) { - HandleAlertException(parse_result); - } - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - NEARBY_LOGS(INFO) - << "In StartServer(), read UKEY2 Message 1 from endpoint(id=" - << endpoint_id_ << ")."; - - // Message 2 (Server Init) - std::unique_ptr<std::string> server_init = - server->GetNextHandshakeMessage(); - - // Java code throws a HandshakeException. - if (server_init == nullptr) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - Exception write_exception = - channel_->Write(ByteArray(std::move(*server_init))); - if (!write_exception.Ok()) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - NEARBY_LOGS(INFO) - << "In StartServer(), wrote UKEY2 Message 2 to endpoint(id=" - << endpoint_id_ << ")."; - - // Message 3 (Client Finish) - ExceptionOr<ByteArray> client_finish = channel_->Read(); - - if (!client_finish.ok()) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - parse_result = - server->ParseHandshakeMessage(std::string(client_finish.result())); - - // Java code throws an AlertException or a HandshakeException. - if (!parse_result.success) { - LogException(); - if (parse_result.alert_to_send != nullptr) { - HandleAlertException(parse_result); - } - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - NEARBY_LOGS(INFO) - << "In StartServer(), read UKEY2 Message 3 from endpoint(id=" - << endpoint_id_ << ")."; - - timeout_alarm.Cancel(); - - if (!HandleEncryptionSuccess(endpoint_id_, std::move(server), listener_)) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - } - - private: - void LogException() const { - NEARBY_LOGS(ERROR) << "In StartServer(), UKEY2 failed with endpoint(id=" - << endpoint_id_ << ")."; - } - - void HandleHandshakeOrIoException(CancelableAlarm* timeout_alarm) const { - timeout_alarm->Cancel(); - listener_.on_failure_cb(endpoint_id_, channel_); - } - - void HandleAlertException( - const securegcm::UKey2Handshake::ParseResult& parse_result) const { - Exception write_exception = - channel_->Write(ByteArray(*parse_result.alert_to_send)); - if (!write_exception.Ok()) { - NEARBY_LOGS(WARNING) - << "In StartServer(), client " << client_->GetClientId() - << " failed to pass the alert error message to endpoint(id=" - << endpoint_id_ << ")."; - } - } - - ClientProxy* client_; - ScheduledExecutor* alarm_executor_; - const std::string endpoint_id_; - EndpointChannel* channel_; - EncryptionRunner::ResultListener listener_; -}; - -class ClientRunnable final { - public: - ClientRunnable(ClientProxy* client, ScheduledExecutor* alarm_executor, - const std::string& endpoint_id, EndpointChannel* channel, - EncryptionRunner::ResultListener&& listener) - : client_(client), - alarm_executor_(alarm_executor), - endpoint_id_(endpoint_id), - channel_(channel), - listener_(std::move(listener)) {} - - void operator()() const { - CancelableAlarm timeout_alarm( - "EncryptionRunner.StartClient() timeout", - [this]() { CancelableAlarmRunnable(client_, endpoint_id_, channel_); }, - kTimeout, alarm_executor_); - - std::unique_ptr<securegcm::UKey2Handshake> crypto = - securegcm::UKey2Handshake::ForInitiator(kCipher); - - // Java code throws a HandshakeException. - if (crypto == nullptr) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - // Message 1 (Client Init) - std::unique_ptr<std::string> client_init = - crypto->GetNextHandshakeMessage(); - - // Java code throws a HandshakeException. - if (client_init == nullptr) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - Exception write_init_exception = channel_->Write(ByteArray(*client_init)); - if (!write_init_exception.Ok()) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - NEARBY_LOGS(INFO) - << "In StartClient(), wrote UKEY2 Message 1 to endpoint(id=" - << endpoint_id_ << ")."; - - // Message 2 (Server Init) - ExceptionOr<ByteArray> server_init = channel_->Read(); - - if (!server_init.ok()) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - securegcm::UKey2Handshake::ParseResult parse_result = - crypto->ParseHandshakeMessage(std::string(server_init.result())); - - // Java code throws an AlertException or a HandshakeException. - if (!parse_result.success) { - LogException(); - if (parse_result.alert_to_send != nullptr) { - HandleAlertException(parse_result); - } - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - NEARBY_LOGS(INFO) - << "In StartClient(), read UKEY2 Message 2 from endpoint(id=" - << endpoint_id_ << ")."; - - // Message 3 (Client Finish) - std::unique_ptr<std::string> client_finish = - crypto->GetNextHandshakeMessage(); - - // Java code throws a HandshakeException. - if (client_finish == nullptr) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - Exception write_finish_exception = - channel_->Write(ByteArray(*client_finish)); - if (!write_finish_exception.Ok()) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - - NEARBY_LOGS(INFO) - << "In StartClient(), wrote UKEY2 Message 3 to endpoint(id=" - << endpoint_id_ << ")."; - - timeout_alarm.Cancel(); - - if (!HandleEncryptionSuccess(endpoint_id_, std::move(crypto), listener_)) { - LogException(); - HandleHandshakeOrIoException(&timeout_alarm); - return; - } - } - - private: - void LogException() const { - NEARBY_LOGS(ERROR) << "In StartClient(), UKEY2 failed with endpoint(id=" - << endpoint_id_ << ")."; - } - - void HandleHandshakeOrIoException(CancelableAlarm* timeout_alarm) const { - timeout_alarm->Cancel(); - listener_.on_failure_cb(endpoint_id_, channel_); - } - - void HandleAlertException( - const securegcm::UKey2Handshake::ParseResult& parse_result) const { - Exception write_exception = - channel_->Write(ByteArray(*parse_result.alert_to_send)); - if (!write_exception.Ok()) { - NEARBY_LOGS(WARNING) - << "In StartClient(), client " << client_->GetClientId() - << " failed to pass the alert error message to endpoint(id=" - << endpoint_id_ << ")."; - } - } - - ClientProxy* client_; - ScheduledExecutor* alarm_executor_; - const std::string endpoint_id_; - EndpointChannel* channel_; - EncryptionRunner::ResultListener listener_; -}; - -} // namespace - -EncryptionRunner::~EncryptionRunner() { - // Stop all the ongoing Runnables (as gracefully as possible). - client_executor_.Shutdown(); - server_executor_.Shutdown(); - alarm_executor_.Shutdown(); -} - -void EncryptionRunner::StartServer( - ClientProxy* client, const std::string& endpoint_id, - EndpointChannel* endpoint_channel, - EncryptionRunner::ResultListener&& listener) { - server_executor_.Execute( - "encryption-server", - [runnable{ServerRunnable(client, &alarm_executor_, endpoint_id, - endpoint_channel, std::move(listener))}]() { - runnable(); - }); -} - -void EncryptionRunner::StartClient( - ClientProxy* client, const std::string& endpoint_id, - EndpointChannel* endpoint_channel, - EncryptionRunner::ResultListener&& listener) { - client_executor_.Execute( - "encryption-client", - [runnable{ClientRunnable(client, &alarm_executor_, endpoint_id, - endpoint_channel, std::move(listener))}]() { - runnable(); - }); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/encryption_runner.h b/chromium/third_party/nearby/src/cpp/core/internal/encryption_runner.h deleted file mode 100644 index 452fa627fec..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/encryption_runner.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_ENCRYPTION_RUNNER_H_ -#define CORE_INTERNAL_ENCRYPTION_RUNNER_H_ - -#include <string> - -#include "securegcm/ukey2_handshake.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel.h" -#include "core/listeners.h" -#include "platform/base/byte_array.h" -#include "platform/public/scheduled_executor.h" -#include "platform/public/single_thread_executor.h" - -namespace location { -namespace nearby { -namespace connections { - -// Encrypts a connection over UKEY2. -// -// NOTE: Stalled EndpointChannels will be disconnected after kTimeout. -// This is to prevent unverified endpoints from maintaining an -// indefinite connection to us. -class EncryptionRunner { - public: - EncryptionRunner() = default; - ~EncryptionRunner(); - - struct ResultListener { - // @EncryptionRunnerThread - std::function<void(const std::string& endpoint_id, - std::unique_ptr<securegcm::UKey2Handshake> ukey2, - const std::string& auth_token, - const ByteArray& raw_auth_token)> - on_success_cb = - DefaultCallback<const std::string&, - std::unique_ptr<securegcm::UKey2Handshake>, - const std::string&, const ByteArray&>(); - - // Encryption has failed. The remote_endpoint_id and channel are given so - // that any pending state can be cleaned up. - // - // We return the EndpointChannel because, at this stage, simultaneous - // connections are a possibility. Use this channel to verify that the state - // you're cleaning up is for this EndpointChannel, and not state for another - // channel to the same endpoint. - // - // @EncryptionRunnerThread - std::function<void(const std::string& endpoint_id, - EndpointChannel* channel)> - on_failure_cb = DefaultCallback<const std::string&, EndpointChannel*>(); - }; - - // @AnyThread - void StartServer(ClientProxy* client, const std::string& endpoint_id, - EndpointChannel* endpoint_channel, - ResultListener&& result_listener); - // @AnyThread - void StartClient(ClientProxy* client, const std::string& endpoint_id, - EndpointChannel* endpoint_channel, - ResultListener&& result_listener); - - private: - ScheduledExecutor alarm_executor_; - SingleThreadExecutor server_executor_; - SingleThreadExecutor client_executor_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_ENCRYPTION_RUNNER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/encryption_runner_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/encryption_runner_test.cc deleted file mode 100644 index 06720e3385e..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/encryption_runner_test.cc +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/encryption_runner.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/time/clock.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel.h" -#include "platform/base/byte_array.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/pipe.h" -#include "platform/public/system_clock.h" -#include "proto/connections_enums.pb.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -using ::location::nearby::proto::connections::Medium; - -class FakeEndpointChannel : public EndpointChannel { - public: - FakeEndpointChannel(InputStream* in, OutputStream* out) - : in_(in), out_(out) {} - ExceptionOr<ByteArray> Read() override { - read_timestamp_ = SystemClock::ElapsedRealtime(); - return in_ ? in_->Read(Pipe::kChunkSize) - : ExceptionOr<ByteArray>{Exception::kIo}; - } - Exception Write(const ByteArray& data) override { - write_timestamp_ = SystemClock::ElapsedRealtime(); - return out_ ? out_->Write(data) : Exception{Exception::kIo}; - } - void Close() override { - if (in_) in_->Close(); - if (out_) out_->Close(); - } - void Close(proto::connections::DisconnectionReason reason) override { - Close(); - } - std::string GetType() const override { return "fake-channel-type"; } - std::string GetName() const override { return "fake-channel"; } - Medium GetMedium() const override { return Medium::BLE; } - int GetMaxTransmitPacketSize() const override { return 512; } - void EnableEncryption(std::shared_ptr<EncryptionContext> context) override {} - void DisableEncryption() override {} - bool IsPaused() const override { return false; } - void Pause() override {} - void Resume() override {} - absl::Time GetLastReadTimestamp() const override { return read_timestamp_; } - absl::Time GetLastWriteTimestamp() const override { return write_timestamp_; } - void SetAnalyticsRecorder(analytics::AnalyticsRecorder* analytics_recorder, - const std::string& endpoint_id) override {} - - private: - InputStream* in_ = nullptr; - OutputStream* out_ = nullptr; - absl::Time read_timestamp_ = absl::InfinitePast(); - absl::Time write_timestamp_ = absl::InfinitePast(); -}; - -struct User { - User(Pipe* reader, Pipe* writer) - : channel(&reader->GetInputStream(), &writer->GetOutputStream()) {} - - FakeEndpointChannel channel; - EncryptionRunner crypto; - ClientProxy client; -}; - -struct Response { - enum class Status { - kUnknown = 0, - kDone = 1, - kFailed = 2, - }; - - CountDownLatch latch{2}; - Status server_status = Status::kUnknown; - Status client_status = Status::kUnknown; -}; - -TEST(EncryptionRunnerTest, ConstructorDestructorWorks) { EncryptionRunner enc; } - -TEST(EncryptionRunnerTest, ReadWrite) { - Pipe from_a_to_b; - Pipe from_b_to_a; - User user_a(/*reader=*/&from_b_to_a, /*writer=*/&from_a_to_b); - User user_b(/*reader=*/&from_a_to_b, /*writer=*/&from_b_to_a); - Response response; - - user_a.crypto.StartServer( - &user_a.client, "endpoint_id", &user_a.channel, - { - .on_success_cb = - [&response](const std::string& endpoint_id, - std::unique_ptr<securegcm::UKey2Handshake> ukey2, - const std::string& auth_token, - const ByteArray& raw_auth_token) { - response.server_status = Response::Status::kDone; - response.latch.CountDown(); - }, - .on_failure_cb = - [&response](const std::string& endpoint_id, - EndpointChannel* channel) { - response.server_status = Response::Status::kFailed; - response.latch.CountDown(); - }, - }); - user_b.crypto.StartClient( - &user_b.client, "endpoint_id", &user_b.channel, - { - .on_success_cb = - [&response](const std::string& endpoint_id, - std::unique_ptr<securegcm::UKey2Handshake> ukey2, - const std::string& auth_token, - const ByteArray& raw_auth_token) { - response.client_status = Response::Status::kDone; - response.latch.CountDown(); - }, - .on_failure_cb = - [&response](const std::string& endpoint_id, - EndpointChannel* channel) { - response.client_status = Response::Status::kFailed; - response.latch.CountDown(); - }, - }); - EXPECT_TRUE(response.latch.Await(absl::Milliseconds(5000)).result()); - EXPECT_EQ(response.server_status, Response::Status::kDone); - EXPECT_EQ(response.client_status, Response::Status::kDone); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_channel.h b/chromium/third_party/nearby/src/cpp/core/internal/endpoint_channel.h deleted file mode 100644 index 4d9bef3948a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_channel.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_ENDPOINT_CHANNEL_H_ -#define CORE_INTERNAL_ENDPOINT_CHANNEL_H_ - -#include <cstdint> -#include <string> - -#include "securegcm/d2d_connection_context_v1.h" -#include "absl/time/clock.h" -#include "analytics/analytics_recorder.h" -#include "platform/base/byte_array.h" -#include "platform/base/exception.h" -#include "platform/public/mutex.h" -#include "proto/connections_enums.pb.h" - -namespace location { -namespace nearby { -namespace connections { - -class EndpointChannel { - public: - virtual ~EndpointChannel() = default; - - using EncryptionContext = ::securegcm::D2DConnectionContextV1; - - virtual ExceptionOr<ByteArray> - Read() = 0; // throws Exception::IO, Exception::INTERRUPTED - - virtual Exception Write(const ByteArray& data) = 0; // throws Exception::IO - - // Closes this EndpointChannel, without tracking the closure in analytics. - virtual void Close() = 0; - - // Closes this EndpointChannel and records the closure with the given reason. - virtual void Close(proto::connections::DisconnectionReason reason) = 0; - - // Returns a one-word type descriptor for the concrete EndpointChannel - // implementation that can be used in log messages; eg: BLUETOOTH, BLE, WIFI. - virtual std::string GetType() const = 0; - - // Returns the name of the EndpointChannel. - virtual std::string GetName() const = 0; - - // Returns the analytics enum representing the medium of this EndpointChannel. - virtual proto::connections::Medium GetMedium() const = 0; - - // Returns the maximum supported transmit packet size(MTU) for the underlying - // transport. - virtual int GetMaxTransmitPacketSize() const = 0; - - // Enables encryption on the EndpointChannel. - virtual void EnableEncryption(std::shared_ptr<EncryptionContext> context) = 0; - - // Disables encryption on the EndpointChannel. - virtual void DisableEncryption() = 0; - - // True if the EndpointChannel is currently pausing all writes. - virtual bool IsPaused() const = 0; - - // Pauses all writes on this EndpointChannel until resume() is called. - virtual void Pause() = 0; - - // Resumes any writes on this EndpointChannel that were suspended when pause() - // was called. - virtual void Resume() = 0; - - // Returns the timestamp of the last read from this endpoint, or -1 if no - // reads have occurred. - virtual absl::Time GetLastReadTimestamp() const = 0; - - // Returns the timestamp of the last write to this endpoint, or -1 if no - // writes have occurred. - virtual absl::Time GetLastWriteTimestamp() const = 0; - - // Sets the AnalyticsRecorder instance for analytics. - virtual void SetAnalyticsRecorder( - analytics::AnalyticsRecorder* analytics_recorder, - const std::string& endpoint_id) = 0; -}; - -inline bool operator==(const EndpointChannel& lhs, const EndpointChannel& rhs) { - return (lhs.GetType() == rhs.GetType()) && (lhs.GetName() == rhs.GetName()) && - (lhs.GetMedium() == rhs.GetMedium()); -} - -inline bool operator!=(const EndpointChannel& lhs, const EndpointChannel& rhs) { - return !(lhs == rhs); -} - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_ENDPOINT_CHANNEL_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_channel_manager.cc b/chromium/third_party/nearby/src/cpp/core/internal/endpoint_channel_manager.cc deleted file mode 100644 index 55cead7e84f..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_channel_manager.cc +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/endpoint_channel_manager.h" - -#include <memory> -#include <string> -#include <utility> - -#include "absl/time/time.h" -#include "core/internal/offline_frames.h" -#include "platform/base/feature_flags.h" -#include "platform/public/logging.h" -#include "platform/public/mutex.h" -#include "platform/public/mutex_lock.h" -#include "platform/public/system_clock.h" -#include "proto/connections/offline_wire_formats.pb.h" - -namespace location { -namespace nearby { -namespace connections { - -namespace { -const absl::Duration kDataTransferDelay = absl::Milliseconds(500); -} - -EndpointChannelManager::~EndpointChannelManager() { - NEARBY_LOG(INFO, "Initiating shutdown of EndpointChannelManager."); - MutexLock lock(&mutex_); - channel_state_.DestroyAll(); - NEARBY_LOG(INFO, "EndpointChannelManager has shut down."); -} - -void EndpointChannelManager::RegisterChannelForEndpoint( - ClientProxy* client, const std::string& endpoint_id, - std::unique_ptr<EndpointChannel> channel) { - MutexLock lock(&mutex_); - - NEARBY_LOGS(INFO) << "EndpointChannelManager registered channel of type " - << channel->GetType() << " to endpoint " << endpoint_id; - SetActiveEndpointChannel(client, endpoint_id, std::move(channel)); - - NEARBY_LOG(INFO, "Registered channel: id=%s", endpoint_id.c_str()); -} - -void EndpointChannelManager::ReplaceChannelForEndpoint( - ClientProxy* client, const std::string& endpoint_id, - std::unique_ptr<EndpointChannel> channel) { - MutexLock lock(&mutex_); - - auto* endpoint = channel_state_.LookupEndpointData(endpoint_id); - if (endpoint != nullptr && endpoint->channel == nullptr) { - NEARBY_LOGS(INFO) << "EndpointChannelManager is missing channel while " - "trying to update: endpoint " - << endpoint_id; - } - - SetActiveEndpointChannel(client, endpoint_id, std::move(channel)); -} - -bool EndpointChannelManager::EncryptChannelForEndpoint( - const std::string& endpoint_id, - std::unique_ptr<EncryptionContext> context) { - MutexLock lock(&mutex_); - - channel_state_.UpdateEncryptionContextForEndpoint(endpoint_id, - std::move(context)); - auto* endpoint = channel_state_.LookupEndpointData(endpoint_id); - return channel_state_.EncryptChannel(endpoint); -} - -std::shared_ptr<EndpointChannel> EndpointChannelManager::GetChannelForEndpoint( - const std::string& endpoint_id) { - MutexLock lock(&mutex_); - - auto* endpoint = channel_state_.LookupEndpointData(endpoint_id); - if (endpoint == nullptr) { - NEARBY_LOGS(INFO) << "No channel info for endpoint " << endpoint_id; - return {}; - } - - return endpoint->channel; -} - -void EndpointChannelManager::SetActiveEndpointChannel( - ClientProxy* client, const std::string& endpoint_id, - std::unique_ptr<EndpointChannel> channel) { - // Update the channel first, then encrypt this new channel, if - // crypto context is present. - channel->SetAnalyticsRecorder(&client->GetAnalyticsRecorder(), endpoint_id); - channel_state_.UpdateChannelForEndpoint(endpoint_id, std::move(channel)); - - auto* endpoint = channel_state_.LookupEndpointData(endpoint_id); - if (endpoint->IsEncrypted()) channel_state_.EncryptChannel(endpoint); -} - -int EndpointChannelManager::GetConnectedEndpointsCount() const { - MutexLock lock(&mutex_); - return channel_state_.GetConnectedEndpointsCount(); -} - -///////////////////////////////// ChannelState ///////////////////////////////// - -// endpoint - channel endpoint to encrypt -bool EndpointChannelManager::ChannelState::EncryptChannel( - EndpointChannelManager::ChannelState::EndpointData* endpoint) { - if (endpoint != nullptr && endpoint->channel != nullptr && - endpoint->context != nullptr) { - endpoint->channel->EnableEncryption(endpoint->context); - return true; - } - return false; -} - -EndpointChannelManager::ChannelState::EndpointData* -EndpointChannelManager::ChannelState::LookupEndpointData( - const std::string& endpoint_id) { - auto item = endpoints_.find(endpoint_id); - return item != endpoints_.end() ? &item->second : nullptr; -} - -void EndpointChannelManager::ChannelState::UpdateChannelForEndpoint( - const std::string& endpoint_id, std::unique_ptr<EndpointChannel> channel) { - // Create EndpointData instance, if necessary, and populate channel. - endpoints_[endpoint_id].channel = std::move(channel); -} - -void EndpointChannelManager::ChannelState::UpdateEncryptionContextForEndpoint( - const std::string& endpoint_id, - std::unique_ptr<EncryptionContext> context) { - // Create EndpointData instance, if necessary, and populate crypto context. - endpoints_[endpoint_id].context = std::move(context); -} - -bool EndpointChannelManager::ChannelState::RemoveEndpoint( - const std::string& endpoint_id, - proto::connections::DisconnectionReason reason) { - auto item = endpoints_.find(endpoint_id); - if (item == endpoints_.end()) return false; - item->second.disconnect_reason = reason; - auto channel = item->second.channel; - if (channel) { - // If the channel was paused (i.e. during a bandwidth upgrade negotiation) - // we resume to ensure the thread won't hang when trying to write to it. - channel->Resume(); - - channel->Write(parser::ForDisconnection()); - NEARBY_LOGS(INFO) - << "EndpointChannelManager reported the disconnection to endpoint " - << endpoint_id; - SystemClock::Sleep(kDataTransferDelay); - } - endpoints_.erase(item); - return true; -} - -bool EndpointChannelManager::UnregisterChannelForEndpoint( - const std::string& endpoint_id) { - MutexLock lock(&mutex_); - - if (!channel_state_.RemoveEndpoint( - endpoint_id, - proto::connections::DisconnectionReason::LOCAL_DISCONNECTION)) { - return false; - } - - NEARBY_LOGS(INFO) - << "EndpointChannelManager unregistered channel for endpoint " - << endpoint_id; - - return true; -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_channel_manager.h b/chromium/third_party/nearby/src/cpp/core/internal/endpoint_channel_manager.h deleted file mode 100644 index 7ec1e1a1954..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_channel_manager.h +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_ENDPOINT_CHANNEL_MANAGER_H_ -#define CORE_INTERNAL_ENDPOINT_CHANNEL_MANAGER_H_ - -#include <memory> -#include <string> - -#include "securegcm/d2d_connection_context_v1.h" -#include "absl/container/flat_hash_map.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel.h" -#include "platform/public/logging.h" -#include "platform/public/mutex.h" - -namespace location { -namespace nearby { -namespace connections { - -// NOTE(std::string): -// All the strings in internal class public interfaces should be exchanged as -// const std::string& if they are immutable, and as std::string if they are -// mutable. -// This is to keep all the internal classes compatible with each other, -// and minimize resources spent on the type conversion. -// Project-wide, strings are either passed around as reference (which has -// zero maintenance costs, and sizeof(void*) memory usage => passed around in a -// CPU register), and whenever lifetime etension is required, it must be copied -// to std::string instance (which will again propagate as a const reference -// within it's lifetime domain). - -// Manages the communication channels to all the remote endpoints with which we -// are interacting. -class EndpointChannelManager final { - public: - using EncryptionContext = EndpointChannel::EncryptionContext; - - ~EndpointChannelManager(); - - // Registers the initial EndpointChannel to be associated with an endpoint; - // if there already exists a previously-associated EndpointChannel, that will - // be closed before continuing the registration. - void RegisterChannelForEndpoint(ClientProxy* client, - const std::string& endpoint_id, - std::unique_ptr<EndpointChannel> channel) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Replaces the EndpointChannel to be associated with an endpoint from here on - // in, transferring the encryption context from the previous EndpointChannel - // to the newly-provided EndpointChannel. - void ReplaceChannelForEndpoint(ClientProxy* client, - const std::string& endpoint_id, - std::unique_ptr<EndpointChannel> channel) - ABSL_LOCKS_EXCLUDED(mutex_); - - bool EncryptChannelForEndpoint(const std::string& endpoint_id, - std::unique_ptr<EncryptionContext> context) - ABSL_LOCKS_EXCLUDED(mutex_); - - // NOTE(shared_ptr<> usage): - // - // EndpointChannelManager is holding an EndpointChannel instance; - // GetChannelForEndpoint() is passing ownership over to a worker thread. - // It is not a pointer passing but an ownership passing, to guarantee that - // channel instance will not disappear underneath the feet of a worker thread - // inside EndpointManager [ EndpointManager::EndpointChannelLoopRunnable() ]. - // If it is just a pointer, Channel will get destroyed while in use by a - // worker thread. shared_ptr is a simple and reliable tool to avoid that. - // - // The reason why it can not be std::unique_ptr<> is: there are other code - // paths that expect to be able to read the pointer value multiple times, from - // multiple places (each of them needs "ownership" for the duration of their - // use). EndpointManager::SendTransferFrameBytes() is another such place. - // If EndpointChannelManager replaces the current channel, and any (or both) - // EndpointManager methods that use a channel are running, it is better to - // have a shared ownership. - std::shared_ptr<EndpointChannel> GetChannelForEndpoint( - const std::string& endpoint_id) ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true if 'endpoint_id' actually had a registered EndpointChannel. - // IOW, a return of false signifies a no-op. - bool UnregisterChannelForEndpoint(const std::string& endpoint_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - int GetConnectedEndpointsCount() const ABSL_LOCKS_EXCLUDED(mutex_); - - private: - // Tracks channel state for all endpoints. This includes what EndpointChannel - // the endpoint is currently using and whether or not the EndpointChannel has - // been encrypted yet. - class ChannelState { - public: - struct EndpointData { - EndpointData() = default; - EndpointData(EndpointData&&) = default; - EndpointData& operator=(EndpointData&&) = default; - ~EndpointData() { - if (channel != nullptr) { - channel->Close(disconnect_reason); - } - } - - // True if we have a 'context' for the endpoint. - bool IsEncrypted() const { return context != nullptr; } - - std::shared_ptr<EndpointChannel> channel; - std::shared_ptr<EncryptionContext> context; - proto::connections::DisconnectionReason disconnect_reason = - proto::connections::DisconnectionReason::UNKNOWN_DISCONNECTION_REASON; - }; - - ChannelState() = default; - ~ChannelState() { DestroyAll(); } - ChannelState(ChannelState&&) = default; - ChannelState& operator=(ChannelState&&) = default; - - // Provides a way to destroy contents of a container, while holding a lock. - void DestroyAll() { endpoints_.clear(); } - // Return pointer to endpoint data, or nullptr, it not found. - EndpointData* LookupEndpointData(const std::string& endpoint_id); - - // Stores a new EndpointChannel for the endpoint. - // Prevoius one is destroyed, if it existed. - void UpdateChannelForEndpoint(const std::string& endpoint_id, - std::unique_ptr<EndpointChannel> channel); - - // Stores a new EncryptionContext for the endpoint. - // Prevoius one is destroyed, if it existed. - void UpdateEncryptionContextForEndpoint( - const std::string& endpoint_id, - std::unique_ptr<EncryptionContext> context); - - // Removes all knowledge of this endpoint, cleaning up as necessary. - // Returns false if the endpoint was not found. - bool RemoveEndpoint(const std::string& endpoint_id, - proto::connections::DisconnectionReason reason); - - bool EncryptChannel(EndpointData* endpoint); - int GetConnectedEndpointsCount() const { return endpoints_.size(); } - - private: - // Endpoint ID -> EndpointData. Contains everything we know about the - // endpoint. - absl::flat_hash_map<std::string, EndpointData> endpoints_; - }; - - void SetActiveEndpointChannel(ClientProxy* client, - const std::string& endpoint_id, - std::unique_ptr<EndpointChannel> channel) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - mutable Mutex mutex_; - ChannelState channel_state_ ABSL_GUARDED_BY(mutex_); -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_ENDPOINT_CHANNEL_MANAGER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_channel_manager_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/endpoint_channel_manager_test.cc deleted file mode 100644 index f278a1d26b9..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_channel_manager_test.cc +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/endpoint_channel_manager.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -namespace location { -namespace nearby { -namespace connections { - -TEST(EndpointChannelManagerTest, ConstructorDestructorWorks) { - EndpointChannelManager mgr; - SUCCEED(); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager.cc b/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager.cc deleted file mode 100644 index e050b9f45b1..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager.cc +++ /dev/null @@ -1,675 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/endpoint_manager.h" - -#include <memory> -#include <utility> - -#include "core/internal/endpoint_channel.h" -#include "core/internal/offline_frames.h" -#include "platform/base/exception.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/logging.h" -#include "platform/public/mutex_lock.h" -#include "proto/connections/offline_wire_formats.pb.h" - -namespace location { -namespace nearby { -namespace connections { - -using ::location::nearby::proto::connections::Medium; - -constexpr absl::Duration EndpointManager::kProcessEndpointDisconnectionTimeout; -constexpr absl::Time EndpointManager::kInvalidTimestamp; - -class EndpointManager::LockedFrameProcessor { - public: - explicit LockedFrameProcessor(FrameProcessorWithMutex* fp) - : lock_{std::make_unique<MutexLock>(&fp->mutex_)}, - frame_processor_with_mutex_{fp} {} - - // Constructor of a no-op object. - LockedFrameProcessor() {} - - explicit operator bool() const { return get() != nullptr; } - - FrameProcessor* operator->() const { return get(); } - - void set(FrameProcessor* frame_processor) { - if (frame_processor_with_mutex_) - frame_processor_with_mutex_->frame_processor_ = frame_processor; - } - - FrameProcessor* get() const { - return frame_processor_with_mutex_ - ? frame_processor_with_mutex_->frame_processor_ - : nullptr; - } - - void reset() { - if (frame_processor_with_mutex_) - frame_processor_with_mutex_->frame_processor_ = nullptr; - } - - private: - std::unique_ptr<MutexLock> lock_; - FrameProcessorWithMutex* frame_processor_with_mutex_ = nullptr; -}; - -// A Runnable that continuously grabs the most recent EndpointChannel available -// for an endpoint. -// -// handler - Called whenever an EndpointChannel is available for endpointId. -// Implementations are expected to read/write freely to the -// EndpointChannel until an Exception::IO is thrown. Once an -// Exception::IO occurs, a check will be performed to see if another -// EndpointChannel is available for the given endpoint and, if so, -// handler(EndpointChannel) will be called again. -void EndpointManager::EndpointChannelLoopRunnable( - const std::string& runnable_name, ClientProxy* client, - const std::string& endpoint_id, - std::function<ExceptionOr<bool>(EndpointChannel*)> handler) { - // EndpointChannelManager will not let multiple channels exist simultaneously - // for the same endpoint_id; it will be closing "old" channels as new ones - // come. - // Closed channel will return Exception::kIo for any Read, and loop (below) - // will retry and attempt to pick another channel. - // If channel is deleted (no mapping), or it is still the same channel - // (same Medium) on which we got the Exception::kIo, we terminate the loop. - NEARBY_LOG(INFO, "Started worker loop name=%s, endpoint=%s", - runnable_name.c_str(), endpoint_id.c_str()); - Medium last_failed_medium = Medium::UNKNOWN_MEDIUM; - while (true) { - // It's important to keep re-fetching the EndpointChannel for an endpoint - // because it can be changed out from under us (for example, when we - // upgrade from Bluetooth to Wifi). - std::shared_ptr<EndpointChannel> channel = - channel_manager_->GetChannelForEndpoint(endpoint_id); - if (channel == nullptr) { - NEARBY_LOG(INFO, "Endpoint channel is nullptr, bail out."); - break; - } - - // If we're looping back around after a failure, and there's not a new - // EndpointChannel for this endpoint, there's nothing more to do here. - if ((last_failed_medium != Medium::UNKNOWN_MEDIUM) && - (channel->GetMedium() == last_failed_medium)) { - NEARBY_LOG( - INFO, "No new endpoint channel is found after a failure, exit loop."); - break; - } - - ExceptionOr<bool> keep_using_channel = handler(channel.get()); - - if (!keep_using_channel.ok()) { - Exception exception = keep_using_channel.GetException(); - // An "invalid proto" may be a final payload on a channel we're about to - // close, so we'll loop back around once. We set |last_failed_medium| to - // ensure we don't loop indefinitely. See crbug.com/1182031 for more - // detail. - if (exception.Raised(Exception::kInvalidProtocolBuffer)) { - last_failed_medium = channel->GetMedium(); - NEARBY_LOGS(INFO) - << "Received invalid protobuf message, re-fetching endpoint " - "channel; last_failed_medium=" - << proto::connections::Medium_Name(last_failed_medium); - continue; - } - if (exception.Raised(Exception::kIo)) { - last_failed_medium = channel->GetMedium(); - NEARBY_LOGS(INFO) - << "Endpoint channel IO exception; last_failed_medium=" - << proto::connections::Medium_Name(last_failed_medium); - continue; - } - if (exception.Raised(Exception::kInterrupted)) { - break; - } - } - - if (!keep_using_channel.result()) { - NEARBY_LOGS(INFO) << "Dropping current channel: last medium=" - << proto::connections::Medium_Name(last_failed_medium); - break; - } - } - // Indicate we're out of the loop and it is ok to schedule another instance - // if needed. - NEARBY_LOGS(INFO) << "Worker going down; worker name=" << runnable_name - << "; endpoint_id=" << endpoint_id; - // Always clear out all state related to this endpoint before terminating - // this thread. - DiscardEndpoint(client, endpoint_id); - NEARBY_LOGS(INFO) << "Worker done; worker name=" << runnable_name - << "; endpoint_id=" << endpoint_id; -} - -ExceptionOr<bool> EndpointManager::HandleData( - const std::string& endpoint_id, ClientProxy* client, - EndpointChannel* endpoint_channel) { - // Read as much as we can from the healthy EndpointChannel - when it is no - // longer in good shape (i.e. our read from it throws an Exception), our - // super class will loop back around and try our luck in case there's been - // a replacement for this endpoint since we last checked with the - // EndpointChannelManager. - while (true) { - ExceptionOr<ByteArray> bytes = endpoint_channel->Read(); - if (!bytes.ok()) { - NEARBY_LOG(INFO, "Stop reading on read-time exception: %d", - bytes.exception()); - return ExceptionOr<bool>(bytes.exception()); - } - ExceptionOr<OfflineFrame> wrapped_frame = parser::FromBytes(bytes.result()); - if (!wrapped_frame.ok()) { - if (wrapped_frame.GetException().Raised( - Exception::kInvalidProtocolBuffer)) { - NEARBY_LOG(INFO, "Failed to decode; endpoint=%s; channel=%s; skip", - endpoint_id.c_str(), endpoint_channel->GetType().c_str()); - continue; - } else { - NEARBY_LOG(INFO, "Stop reading on parse-time exception: %d", - wrapped_frame.exception()); - return ExceptionOr<bool>(wrapped_frame.exception()); - } - } - OfflineFrame& frame = wrapped_frame.result(); - - // Route the incoming offlineFrame to its registered processor. - V1Frame::FrameType frame_type = parser::GetFrameType(frame); - LockedFrameProcessor frame_processor = GetFrameProcessor(frame_type); - if (!frame_processor) { - // report messages without handlers, except KEEP_ALIVE, which has - // no explicit handler. - if (frame_type == V1Frame::KEEP_ALIVE) { - NEARBY_LOG(INFO, "KeepAlive message for endpoint %s", - endpoint_id.c_str()); - } else if (frame_type == V1Frame::DISCONNECTION) { - NEARBY_LOG(INFO, "Disconnect message for endpoint %s", - endpoint_id.c_str()); - endpoint_channel->Close(); - } else { - NEARBY_LOGS(ERROR) << "Unhandled message: endpoint_id=" << endpoint_id - << ", frame type=" - << V1Frame::FrameType_Name(frame_type); - } - continue; - } - - frame_processor->OnIncomingFrame(frame, endpoint_id, client, - endpoint_channel->GetMedium()); - } -} - -ExceptionOr<bool> EndpointManager::HandleKeepAlive( - EndpointChannel* endpoint_channel, absl::Duration keep_alive_interval, - absl::Duration keep_alive_timeout, Mutex* keep_alive_waiter_mutex, - ConditionVariable* keep_alive_waiter) { - // Check if it has been too long since we received a frame from our endpoint. - absl::Time last_read_time = endpoint_channel->GetLastReadTimestamp(); - absl::Duration duration_until_timeout = - last_read_time == kInvalidTimestamp - ? keep_alive_timeout - : last_read_time + keep_alive_timeout - - SystemClock::ElapsedRealtime(); - if (duration_until_timeout <= absl::ZeroDuration()) { - return ExceptionOr<bool>(false); - } - - // If we haven't written anything to the endpoint for a while, attempt to send - // the KeepAlive frame over the endpoint channel. If the write fails, our - // super class will loop back around and try our luck again in case there's - // been a replacement for this endpoint. - absl::Time last_write_time = endpoint_channel->GetLastWriteTimestamp(); - absl::Duration duration_until_write_keep_alive = - last_write_time == kInvalidTimestamp - ? keep_alive_interval - : last_write_time + keep_alive_interval - - SystemClock::ElapsedRealtime(); - if (duration_until_write_keep_alive <= absl::ZeroDuration()) { - Exception write_exception = endpoint_channel->Write(parser::ForKeepAlive()); - if (!write_exception.Ok()) { - return ExceptionOr<bool>(write_exception); - } - duration_until_write_keep_alive = keep_alive_interval; - } - - absl::Duration wait_for = - std::min(duration_until_timeout, duration_until_write_keep_alive); - { - MutexLock lock(keep_alive_waiter_mutex); - Exception wait_exception = keep_alive_waiter->Wait(wait_for); - if (!wait_exception.Ok()) { - return ExceptionOr<bool>(wait_exception); - } - } - - return ExceptionOr<bool>(true); -} - -bool operator==(const EndpointManager::FrameProcessor& lhs, - const EndpointManager::FrameProcessor& rhs) { - // We're comparing addresses because these objects are callbacks which need to - // be matched by exact instances. - return &lhs == &rhs; -} - -bool operator<(const EndpointManager::FrameProcessor& lhs, - const EndpointManager::FrameProcessor& rhs) { - // We're comparing addresses because these objects are callbacks which need to - // be matched by exact instances. - return &lhs < &rhs; -} - -EndpointManager::EndpointManager(EndpointChannelManager* manager) - : channel_manager_(manager) {} - -EndpointManager::~EndpointManager() { - NEARBY_LOG(INFO, "Initiating shutdown of EndpointManager."); - CountDownLatch latch(1); - RunOnEndpointManagerThread("bring-down-endpoints", [this, &latch]() { - NEARBY_LOG(INFO, "Bringing down endpoints"); - endpoints_.clear(); - latch.CountDown(); - }); - latch.Await(); - - NEARBY_LOG(INFO, "Bringing down control thread"); - serial_executor_.Shutdown(); - NEARBY_LOG(INFO, "EndpointManager is down"); -} - -void EndpointManager::RegisterFrameProcessor( - V1Frame::FrameType frame_type, EndpointManager::FrameProcessor* processor) { - if (auto frame_processor = GetFrameProcessor(frame_type)) { - NEARBY_LOGS(INFO) << "EndpointManager received request to update " - "registration of frame processor " - << processor << " for frame type " - << V1Frame::FrameType_Name(frame_type) << ", self" - << this; - frame_processor.set(processor); - } else { - MutexLock lock(&frame_processors_lock_); - NEARBY_LOGS(INFO) << "EndpointManager received request to add registration " - "of frame processor " - << processor << " for frame type " - << V1Frame::FrameType_Name(frame_type) - << ", self=" << this; - frame_processors_.emplace(frame_type, processor); - } -} - -void EndpointManager::UnregisterFrameProcessor( - V1Frame::FrameType frame_type, - const EndpointManager::FrameProcessor* processor) { - NEARBY_LOGS(INFO) << "UnregisterFrameProcessor [enter]: processor =" - << processor; - if (processor == nullptr) return; - if (auto frame_processor = GetFrameProcessor(frame_type)) { - if (frame_processor.get() == processor) { - frame_processor.reset(); - NEARBY_LOGS(INFO) << "EndpointManager unregister frame processor " - << processor << " for frame type " - << V1Frame::FrameType_Name(frame_type) - << ", self=" << this; - } else { - NEARBY_LOGS(INFO) << "EndpointManager cannot unregister frame processor " - << processor - << " because it is not registered for frame type " - << V1Frame::FrameType_Name(frame_type) - << ", expected=" << frame_processor.get(); - } - } else { - NEARBY_LOGS(INFO) << "UnregisterFrameProcessor [not found]: processor=" - << processor; - } -} - -EndpointManager::LockedFrameProcessor EndpointManager::GetFrameProcessor( - V1Frame::FrameType frame_type) { - MutexLock lock(&frame_processors_lock_); - auto it = frame_processors_.find(frame_type); - if (it != frame_processors_.end()) { - return LockedFrameProcessor(&it->second); - } - return LockedFrameProcessor(); -} - -void EndpointManager::RemoveEndpointState(const std::string& endpoint_id) { - NEARBY_LOGS(VERBOSE) << "EnsureWorkersTerminated for endpoint " - << endpoint_id; - auto item = endpoints_.find(endpoint_id); - if (item != endpoints_.end()) { - NEARBY_LOGS(INFO) << "EndpointState found for endpoint " << endpoint_id; - // If another instance of data and keep-alive handlers is running, it will - // terminate soon. Removing EndpointState waits for workers to complete. - endpoints_.erase(item); - NEARBY_LOGS(VERBOSE) << "Workers terminated for endpoint " << endpoint_id; - } else { - NEARBY_LOGS(INFO) << "EndpointState not found for endpoint " << endpoint_id; - } -} - -void EndpointManager::RegisterEndpoint(ClientProxy* client, - const std::string& endpoint_id, - const ConnectionResponseInfo& info, - const ConnectionOptions& options, - std::unique_ptr<EndpointChannel> channel, - const ConnectionListener& listener, - const std::string& connection_token) { - CountDownLatch latch(1); - - // NOTE (unique_ptr<> capture): - // std::unique_ptr<> is not copyable, so we can not pass it to - // lambda capture, because lambda eventually is converted to std::function<>. - // Instead, we release() a pointer, and pass a raw pointer, which is copyalbe. - // We ignore the risk of job not scheduled (and an associated risk of memory - // leak), because this may only happen during service shutdown. - RunOnEndpointManagerThread("register-endpoint", [this, client, - channel = channel.release(), - &endpoint_id, &info, - &options, &listener, - &connection_token, - &latch]() { - if (endpoints_.contains(endpoint_id)) { - NEARBY_LOGS(WARNING) << "Registering duplicate endpoint " << endpoint_id; - // We must remove old endpoint state before registering a new one for the - // same endpoint_id. - RemoveEndpointState(endpoint_id); - } - - absl::Duration keep_alive_interval = - absl::Milliseconds(options.keep_alive_interval_millis); - absl::Duration keep_alive_timeout = - absl::Milliseconds(options.keep_alive_timeout_millis); - NEARBY_LOGS(INFO) << "Registering endpoint " << endpoint_id - << " for client " << client->GetClientId() - << " with keep-alive frame as interval=" - << absl::FormatDuration(keep_alive_interval) - << ", timeout=" - << absl::FormatDuration(keep_alive_timeout); - - // Pass ownership of channel to EndpointChannelManager - NEARBY_LOGS(INFO) << "Registering endpoint with channel manager: endpoint " - << endpoint_id; - channel_manager_->RegisterChannelForEndpoint( - client, endpoint_id, std::unique_ptr<EndpointChannel>(channel)); - - EndpointState& endpoint_state = - endpoints_ - .emplace(endpoint_id, EndpointState(endpoint_id, channel_manager_)) - .first->second; - - NEARBY_LOGS(INFO) << "Starting workers: endpoint " << endpoint_id; - // For every endpoint, there's normally only one Read handler instance - // running on a dedicated thread. This instance reads data from the - // endpoint and delegates incoming frames to various FrameProcessors. - // Once the frame has been properly handled, it starts reading again for - // the next frame. If the handler fails its read and no other - // EndpointChannels are available for this endpoint, a disconnection - // will be initiated. - endpoint_state.StartEndpointReader([this, client, endpoint_id]() { - EndpointChannelLoopRunnable( - "Read", client, endpoint_id, - [this, client, endpoint_id](EndpointChannel* channel) { - return HandleData(endpoint_id, client, channel); - }); - }); - - // For every endpoint, there's only one KeepAliveManager instance running on - // a dedicated thread. This instance will periodically send out a ping* to - // the endpoint while listening for an incoming pong**. If it fails to send - // the ping, or if no pong is heard within keep_alive_timeout, it initiates - // a disconnection. - // - // (*) Bluetooth requires a constant outgoing stream of messages. If - // there's silence, Android will break the socket. This is why we ping. - // (**) Wifi Hotspots can fail to notice a connection has been lost, and - // they will happily keep writing to /dev/null. This is why we listen - // for the pong. - NEARBY_LOGS(VERBOSE) << "EndpointManager enabling KeepAlive for endpoint " - << endpoint_id; - endpoint_state.StartEndpointKeepAliveManager( - [this, client, endpoint_id, keep_alive_interval, keep_alive_timeout]( - Mutex* keep_alive_waiter_mutex, - ConditionVariable* keep_alive_waiter) { - EndpointChannelLoopRunnable( - "KeepAliveManager", client, endpoint_id, - [this, keep_alive_interval, keep_alive_timeout, - keep_alive_waiter_mutex, - keep_alive_waiter](EndpointChannel* channel) { - return HandleKeepAlive( - channel, keep_alive_interval, keep_alive_timeout, - keep_alive_waiter_mutex, keep_alive_waiter); - }); - }); - NEARBY_LOGS(INFO) << "Registering endpoint " << endpoint_id - << ", workers started and notifying client."; - - // It's now time to let the client know of this new connection so that - // they can accept or reject it. - client->OnConnectionInitiated(endpoint_id, info, options, listener, - connection_token); - latch.CountDown(); - }); - latch.Await(); -} - -void EndpointManager::UnregisterEndpoint(ClientProxy* client, - const std::string& endpoint_id) { - NEARBY_LOGS(INFO) << "UnregisterEndpoint for endpoint " << endpoint_id; - CountDownLatch latch(1); - RunOnEndpointManagerThread( - "unregister-endpoint", [this, client, endpoint_id, &latch]() { - RemoveEndpoint(client, endpoint_id, - /*notify=*/client->IsConnectedToEndpoint(endpoint_id)); - latch.CountDown(); - }); - latch.Await(); -} - -int EndpointManager::GetMaxTransmitPacketSize(const std::string& endpoint_id) { - std::shared_ptr<EndpointChannel> channel = - channel_manager_->GetChannelForEndpoint(endpoint_id); - if (channel == nullptr) { - return 0; - } - - return channel->GetMaxTransmitPacketSize(); -} - -std::vector<std::string> EndpointManager::SendPayloadChunk( - const PayloadTransferFrame::PayloadHeader& payload_header, - const PayloadTransferFrame::PayloadChunk& payload_chunk, - const std::vector<std::string>& endpoint_ids) { - ByteArray bytes = - parser::ForDataPayloadTransfer(payload_header, payload_chunk); - - return SendTransferFrameBytes( - endpoint_ids, bytes, payload_header.id(), - /*offset=*/payload_chunk.offset(), - /*packet_type=*/ - PayloadTransferFrame::PacketType_Name(PayloadTransferFrame::DATA)); -} - -// Designed to run asynchronously. It is called from IO thread pools, and -// jobs in these pools may be waited for from the EndpointManager thread. If we -// allow synchronous behavior here it will cause a live lock. -void EndpointManager::DiscardEndpoint(ClientProxy* client, - const std::string& endpoint_id) { - NEARBY_LOGS(VERBOSE) << "DiscardEndpoint for endpoint " << endpoint_id; - RunOnEndpointManagerThread("discard-endpoint", [this, client, endpoint_id]() { - RemoveEndpoint(client, endpoint_id, - /*notify=*/client->IsConnectedToEndpoint(endpoint_id)); - }); -} - -std::vector<std::string> EndpointManager::SendControlMessage( - const PayloadTransferFrame::PayloadHeader& header, - const PayloadTransferFrame::ControlMessage& control, - const std::vector<std::string>& endpoint_ids) { - ByteArray bytes = parser::ForControlPayloadTransfer(header, control); - - return SendTransferFrameBytes( - endpoint_ids, bytes, header.id(), - /*offset=*/control.offset(), - /*packet_type=*/ - PayloadTransferFrame::PacketType_Name(PayloadTransferFrame::CONTROL)); -} - -// @EndpointManagerThread -void EndpointManager::RemoveEndpoint(ClientProxy* client, - const std::string& endpoint_id, - bool notify) { - NEARBY_LOGS(INFO) << "RemoveEndpoint for endpoint " << endpoint_id; - // Unregistering from channel_manager_ will also serve to terminate - // the dedicated handler and KeepAlive threads we started when we registered - // this endpoint. - if (channel_manager_->UnregisterChannelForEndpoint(endpoint_id)) { - // Notify all frame processors of the disconnection immediately and wait - // for them to clean up state. Only once all processors are done cleaning - // up, we can remove the endpoint from ClientProxy after which there - // should be no further interactions with the endpoint. - // (See b/37352254 for history) - WaitForEndpointDisconnectionProcessing(client, endpoint_id); - - client->OnDisconnected(endpoint_id, notify); - NEARBY_LOGS(INFO) << "Removed endpoint for endpoint " << endpoint_id; - } - RemoveEndpointState(endpoint_id); -} - -// @EndpointManagerThread -void EndpointManager::WaitForEndpointDisconnectionProcessing( - ClientProxy* client, const std::string& endpoint_id) { - NEARBY_LOGS(INFO) << "Wait: client=" << client - << "; endpoint_id=" << endpoint_id; - CountDownLatch barrier = - NotifyFrameProcessorsOnEndpointDisconnect(client, endpoint_id); - - NEARBY_LOGS(INFO) - << "Waiting for frame processors to disconnect from endpoint " - << endpoint_id; - if (!barrier.Await(kProcessEndpointDisconnectionTimeout).result()) { - NEARBY_LOGS(INFO) << "Failed to disconnect frame processors from endpoint " - << endpoint_id; - } else { - NEARBY_LOGS(INFO) - << "Finished waiting for frame processors to disconnect from endpoint " - << endpoint_id; - } -} - -CountDownLatch EndpointManager::NotifyFrameProcessorsOnEndpointDisconnect( - ClientProxy* client, const std::string& endpoint_id) { - NEARBY_LOGS(INFO) << "NotifyFrameProcessorsOnEndpointDisconnect: client=" - << client << "; endpoint_id=" << endpoint_id; - MutexLock lock(&frame_processors_lock_); - auto total_size = frame_processors_.size(); - NEARBY_LOGS(INFO) << "Total frame processors: " << total_size; - CountDownLatch barrier(total_size); - - int valid = 0; - for (auto& item : frame_processors_) { - LockedFrameProcessor processor(&item.second); - NEARBY_LOGS(INFO) << "processor=" << processor.get() - << "; frame type=" << V1Frame::FrameType_Name(item.first); - if (processor) { - valid++; - processor->OnEndpointDisconnect(client, endpoint_id, barrier); - } else { - barrier.CountDown(); - } - } - - if (!valid) { - NEARBY_LOGS(INFO) << "No valid frame processors."; - } else { - NEARBY_LOGS(INFO) << "Valid frame processors: " << valid; - } - return barrier; -} - -std::vector<std::string> EndpointManager::SendTransferFrameBytes( - const std::vector<std::string>& endpoint_ids, const ByteArray& bytes, - std::int64_t payload_id, std::int64_t offset, - const std::string& packet_type) { - std::vector<std::string> failed_endpoint_ids; - for (const std::string& endpoint_id : endpoint_ids) { - std::shared_ptr<EndpointChannel> channel = - channel_manager_->GetChannelForEndpoint(endpoint_id); - - if (channel == nullptr) { - // We no longer know about this endpoint (it was either explicitly - // unregistered, or a read/write error made us unregister it internally). - NEARBY_LOGS(ERROR) << "EndpointManager failed to find EndpointChannel " - "over which to write " - << packet_type << " at offset " << offset - << " of Payload " << payload_id << " to endpoint " - << endpoint_id; - - failed_endpoint_ids.push_back(endpoint_id); - continue; - } - - Exception write_exception = channel->Write(bytes); - if (!write_exception.Ok()) { - failed_endpoint_ids.push_back(endpoint_id); - NEARBY_LOGS(INFO) << "Failed to send packet; endpoint_id=" << endpoint_id; - continue; - } - } - - return failed_endpoint_ids; -} - -EndpointManager::EndpointState::~EndpointState() { - // We must unregister the endpoint first to signal the runnables that they - // should exit their loops. SingleThreadExecutor destructors will wait for the - // workers to finish. |channel_manager_| is null after moved from this object - // (in move constructor) which prevents unregistering the channel prematurely. - if (channel_manager_) { - NEARBY_LOG(VERBOSE, "EndpointState destructor %s", endpoint_id_.c_str()); - channel_manager_->UnregisterChannelForEndpoint(endpoint_id_); - } - - // Make sure the KeepAlive thread isn't blocking shutdown. - if (keep_alive_waiter_mutex_ && keep_alive_waiter_) { - MutexLock lock(keep_alive_waiter_mutex_.get()); - keep_alive_waiter_->Notify(); - } -} - -void EndpointManager::EndpointState::StartEndpointReader(Runnable&& runnable) { - reader_thread_.Execute("reader", std::move(runnable)); -} - -void EndpointManager::EndpointState::StartEndpointKeepAliveManager( - std::function<void(Mutex*, ConditionVariable*)> runnable) { - keep_alive_thread_.Execute( - "keep-alive", - [runnable, keep_alive_waiter_mutex = keep_alive_waiter_mutex_.get(), - keep_alive_waiter = keep_alive_waiter_.get()]() { - runnable(keep_alive_waiter_mutex, keep_alive_waiter); - }); -} - -void EndpointManager::RunOnEndpointManagerThread(const std::string& name, - Runnable runnable) { - serial_executor_.Execute(name, std::move(runnable)); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager.h b/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager.h deleted file mode 100644 index ec1a16197f5..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager.h +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_ENDPOINT_MANAGER_H_ -#define CORE_INTERNAL_ENDPOINT_MANAGER_H_ - -#include <cstdint> -#include <memory> - -#include "absl/base/thread_annotations.h" -#include "absl/container/flat_hash_map.h" -#include "absl/container/flat_hash_set.h" -#include "absl/time/time.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel.h" -#include "core/internal/endpoint_channel_manager.h" -#include "core/listeners.h" -#include "platform/base/byte_array.h" -#include "platform/base/runnable.h" -#include "platform/public/condition_variable.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/multi_thread_executor.h" -#include "platform/public/single_thread_executor.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { - -// Manages all operations related to the remote endpoints with which we are -// interacting. -// -// All processing of incoming and outgoing payloads is spread across this and -// the PayloadManager as described below. -// -// The sending of outgoing payloads originates in -// PayloadManager::SendPayload() before control is transferred over to -// EndpointManager::SendPayloadChunk(). This work happens on one of three -// dedicated writer threads belonging to the PayloadManager. The writer thread -// that is used depends on the Payload::Type. -// -// The EndpointManager has one dedicated reader thread for each registered -// endpoint, and the receiving of every incoming payload (and its subsequent -// chunks) originates on one of those threads before control is transferred over -// to PayloadManager::ProcessFrame() (still running on that -// same dedicated reader thread). - -class EndpointManager { - public: - class FrameProcessor { - public: - virtual ~FrameProcessor() = default; - - // @EndpointManagerReaderThread - // Called for every incoming frame of registered type. - // NOTE(OfflineFrame& frame): - // For large payload in data phase, resources may be saved if data is moved, - // rather than copied (if passing data by reference is not an option). - // To achieve that, OfflineFrame needs to be either mutabe lvalue reference, - // or rvalue reference. Rvalue references are discouraged by go/cstyle, - // and that leaves us with mutable lvalue reference. - virtual void OnIncomingFrame(OfflineFrame& offline_frame, - const std::string& from_endpoint_id, - ClientProxy* to_client, - proto::connections::Medium current_medium) = 0; - - // Implementations must call barrier.CountDown() once - // they're done. This parallelizes the disconnection event across all frame - // processors. - // - // @EndpointManagerThread - virtual void OnEndpointDisconnect(ClientProxy* client, - const std::string& endpoint_id, - CountDownLatch barrier) = 0; - }; - - explicit EndpointManager(EndpointChannelManager* manager); - ~EndpointManager(); - - // Invoked from the constructors of the various *Manager components that make - // up the OfflineServiceController implementation. - // FrameProcessor* instances are of dynamic duration and survive all sessions. - // Blocks until registration is complete. - void RegisterFrameProcessor(V1Frame::FrameType frame_type, - FrameProcessor* processor); - void UnregisterFrameProcessor(V1Frame::FrameType frame_type, - const FrameProcessor* processor); - - // Invoked from the different PcpHandler implementations (of which there can - // be only one at a time). - // Blocks until registration is complete. - void RegisterEndpoint(ClientProxy* client, const std::string& endpoint_id, - const ConnectionResponseInfo& info, - const ConnectionOptions& options, - std::unique_ptr<EndpointChannel> channel, - const ConnectionListener& listener, - const std::string& connection_token); - // Called when a client explicitly asks to disconnect from this endpoint. In - // this case, we do not notify the client of onDisconnected(). - void UnregisterEndpoint(ClientProxy* client, const std::string& endpoint_id); - - // Returns the maximum supported transmit packet size(MTU) for the underlying - // transport. - int GetMaxTransmitPacketSize(const std::string& endpoint_id); - - // Returns the list of endpoints to which sending this chunk failed. - // - // Invoked from the PayloadManager's sendPayload() method. - std::vector<std::string> SendPayloadChunk( - const PayloadTransferFrame::PayloadHeader& payload_header, - const PayloadTransferFrame::PayloadChunk& payload_chunk, - const std::vector<std::string>& endpoint_ids); - std::vector<std::string> SendControlMessage( - const PayloadTransferFrame::PayloadHeader& payload_header, - const PayloadTransferFrame::ControlMessage& control_message, - const std::vector<std::string>& endpoint_ids); - - // Called when we internally want to get rid of the endpoint, without the - // client directly telling us to. For example... - // a) We failed to read from the endpoint in its dedicated reader thread. - // b) We failed to write to the endpoint in PayloadManager. - // c) The connection was rejected in PCPHandler. - // d) The dedicated KeepAlive thread exceeded its period of inactivity. - // Or in the numerous other cases where a failure occurred and we no longer - // believe the endpoint is in a healthy state. - // - // Note: This must not block. Otherwise we can get into a deadlock where we - // ask everyone who's registered an FrameProcessor to - // processEndpointDisconnection() while the caller of DiscardEndpoint() is - // blocked here. - void DiscardEndpoint(ClientProxy* client, const std::string& endpoint_id); - - private: - class EndpointState { - public: - EndpointState(const std::string& endpoint_id, - EndpointChannelManager* channel_manager) - : endpoint_id_{endpoint_id}, - channel_manager_{channel_manager}, - keep_alive_waiter_mutex_{std::make_unique<Mutex>()}, - keep_alive_waiter_{std::make_unique<ConditionVariable>( - keep_alive_waiter_mutex_.get())} {} - - EndpointState(const EndpointState&) = delete; - // The default move constructor would not reset |channel_manager_|, for - // example. This needs to be nullified so the destructor shutdown logic is - // bypassed when objects are moved. - EndpointState(EndpointState&& other) - : endpoint_id_{std::move(other.endpoint_id_)}, - channel_manager_{std::exchange(other.channel_manager_, nullptr)}, - reader_thread_{std::move(other.reader_thread_)}, - keep_alive_waiter_mutex_{ - std::exchange(other.keep_alive_waiter_mutex_, nullptr)}, - keep_alive_waiter_{std::exchange(other.keep_alive_waiter_, nullptr)}, - keep_alive_thread_{std::move(other.keep_alive_thread_)} {} - EndpointState& operator=(const EndpointState&) = delete; - EndpointState&& operator=(EndpointState&&) = delete; - ~EndpointState(); - - void StartEndpointReader(Runnable&& runnable); - void StartEndpointKeepAliveManager( - std::function<void(Mutex*, ConditionVariable*)> runnable); - - private: - const std::string endpoint_id_; - EndpointChannelManager* channel_manager_; - SingleThreadExecutor reader_thread_; - - // Use a condition variable so we can wait on the thread but still be able - // to wake it up before shutting down. We don't want to just sleep and risk - // blocking shutdown. Note: Create the mutex/condition variable on the heap - // so raw pointers sent to HandleKeepAlive() aren't invalidated during - // std::move operations. - mutable std::unique_ptr<Mutex> keep_alive_waiter_mutex_; - std::unique_ptr<ConditionVariable> keep_alive_waiter_; - SingleThreadExecutor keep_alive_thread_; - }; - - // RAII accessor for FrameProcessor - class LockedFrameProcessor; - - // Provides a mutex per FrameProcessor to prevent unregistering (and - // destroying) a FrameProcessor when it's in use. - class FrameProcessorWithMutex { - public: - explicit FrameProcessorWithMutex(FrameProcessor* frame_processor = nullptr) - : frame_processor_{frame_processor} {} - - private: - FrameProcessor* frame_processor_; - Mutex mutex_; - friend class LockedFrameProcessor; - }; - - LockedFrameProcessor GetFrameProcessor(V1Frame::FrameType frame_type); - - ExceptionOr<bool> HandleData(const std::string& endpoint_id, - ClientProxy* client_proxy, - EndpointChannel* endpoint_channel); - - ExceptionOr<bool> HandleKeepAlive(EndpointChannel* endpoint_channel, - absl::Duration keep_alive_interval, - absl::Duration keep_alive_timeout, - Mutex* keep_alive_waiter_mutex, - ConditionVariable* keep_alive_waiter); - - // Waits for a given endpoint EndpointChannelLoopRunnable() workers to - // terminate. - // Is called from RegisterEndpoint to avoid races; also called from - // RemoveEndpoint as part of proper endpoint shutdown sequence. - // @EndpointManagerThread - void RemoveEndpointState(const std::string& endpoint_id); - - void EndpointChannelLoopRunnable( - const std::string& runnable_name, ClientProxy* client_proxy, - const std::string& endpoint_id, - std::function<ExceptionOr<bool>(EndpointChannel*)> handler); - - static void WaitForLatch(const std::string& method_name, - CountDownLatch* latch); - static void WaitForLatch(const std::string& method_name, - CountDownLatch* latch, std::int32_t timeout_millis); - - static constexpr absl::Duration kProcessEndpointDisconnectionTimeout = - absl::Milliseconds(2000); - static constexpr absl::Time kInvalidTimestamp = absl::InfinitePast(); - - // It should be noted that this method may be called multiple times (because - // invoking this method closes the endpoint channel, which causes the - // dedicated reader and KeepAlive threads to terminate, which in turn leads to - // this method being called), but that's alright because the implementation of - // this method is idempotent. - // @EndpointManagerThread - void RemoveEndpoint(ClientProxy* client, const std::string& endpoint_id, - bool notify); - - void WaitForEndpointDisconnectionProcessing(ClientProxy* client, - const std::string& endpoint_id); - - CountDownLatch NotifyFrameProcessorsOnEndpointDisconnect( - ClientProxy* client, const std::string& endpoint_id); - - std::vector<std::string> SendTransferFrameBytes( - const std::vector<std::string>& endpoint_ids, - const ByteArray& payload_transfer_frame_bytes, std::int64_t payload_id, - std::int64_t offset, const std::string& packet_type); - - // Executes all jobs sequentially, on a serial_executor_. - void RunOnEndpointManagerThread(const std::string& name, Runnable runnable); - - EndpointChannelManager* channel_manager_; - - RecursiveMutex frame_processors_lock_; - absl::flat_hash_map<V1Frame::FrameType, FrameProcessorWithMutex> - frame_processors_ ABSL_GUARDED_BY(frame_processors_lock_); - - // We keep track of all registered channel endpoints here. - absl::flat_hash_map<std::string, EndpointState> endpoints_; - - SingleThreadExecutor serial_executor_; -}; - -// Operator overloads when comparing FrameProcessor*. -bool operator==(const EndpointManager::FrameProcessor& lhs, - const EndpointManager::FrameProcessor& rhs); -bool operator<(const EndpointManager::FrameProcessor& lhs, - const EndpointManager::FrameProcessor& rhs); - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_ENDPOINT_MANAGER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager_test.cc deleted file mode 100644 index dae1057b411..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager_test.cc +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/endpoint_manager.h" - -#include <atomic> -#include <memory> -#include <string> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/synchronization/mutex.h" -#include "absl/time/clock.h" -#include "absl/time/time.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel_manager.h" -#include "core/internal/offline_frames.h" -#include "core/options.h" -#include "platform/base/byte_array.h" -#include "platform/base/exception.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/logging.h" -#include "platform/public/pipe.h" -#include "proto/connections_enums.pb.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -using ::location::nearby::proto::connections::DisconnectionReason; -using ::location::nearby::proto::connections::Medium; -using ::testing::_; -using ::testing::MockFunction; -using ::testing::Return; -using ::testing::StrictMock; - -class MockEndpointChannel : public EndpointChannel { - public: - MOCK_METHOD(ExceptionOr<ByteArray>, Read, (), (override)); - MOCK_METHOD(Exception, Write, (const ByteArray& data), (override)); - MOCK_METHOD(void, Close, (), (override)); - MOCK_METHOD(void, Close, (DisconnectionReason reason), (override)); - MOCK_METHOD(std::string, GetType, (), (const override)); - MOCK_METHOD(std::string, GetName, (), (const override)); - MOCK_METHOD(Medium, GetMedium, (), (const override)); - MOCK_METHOD(int, GetMaxTransmitPacketSize, (), (const override)); - MOCK_METHOD(void, EnableEncryption, - (std::shared_ptr<EncryptionContext> context), (override)); - MOCK_METHOD(void, DisableEncryption, (), (override)); - MOCK_METHOD(bool, IsPaused, (), (const override)); - MOCK_METHOD(void, Pause, (), (override)); - MOCK_METHOD(void, Resume, (), (override)); - MOCK_METHOD(absl::Time, GetLastReadTimestamp, (), (const override)); - MOCK_METHOD(absl::Time, GetLastWriteTimestamp, (), (const override)); - MOCK_METHOD(void, SetAnalyticsRecorder, - (analytics::AnalyticsRecorder*, const std::string&), (override)); - - bool IsClosed() const { - absl::MutexLock lock(&mutex_); - return closed_; - } - void DoClose() { - absl::MutexLock lock(&mutex_); - closed_ = true; - } - - private: - mutable absl::Mutex mutex_; - bool closed_ = false; -}; - -class MockFrameProcessor : public EndpointManager::FrameProcessor { - public: - MOCK_METHOD(void, OnIncomingFrame, - (OfflineFrame & offline_frame, - const std::string& from_endpoint_id, ClientProxy* to_client, - Medium current_medium), - (override)); - - MOCK_METHOD(void, OnEndpointDisconnect, - (ClientProxy * client, const std::string& endpoint_id, - CountDownLatch barrier), - (override)); -}; - -class EndpointManagerTest : public ::testing::Test { - protected: - void RegisterEndpoint(std::unique_ptr<MockEndpointChannel> channel, - bool should_close = true) { - CountDownLatch done(1); - if (should_close) { - ON_CALL(*channel, Close(_)) - .WillByDefault( - [&done](DisconnectionReason reason) { done.CountDown(); }); - } - EXPECT_CALL(*channel, GetMedium()).WillRepeatedly(Return(Medium::BLE)); - EXPECT_CALL(*channel, GetLastReadTimestamp()) - .WillRepeatedly(Return(start_time_)); - EXPECT_CALL(*channel, GetLastWriteTimestamp()) - .WillRepeatedly(Return(start_time_)); - EXPECT_CALL(mock_listener_.initiated_cb, Call).Times(1); - em_.RegisterEndpoint(&client_, endpoint_id_, info_, options_, - std::move(channel), listener_, connection_token); - if (should_close) { - EXPECT_TRUE(done.Await(absl::Milliseconds(1000)).result()); - } - } - - ClientProxy client_; - ConnectionOptions options_{ - .keep_alive_interval_millis = 5000, - .keep_alive_timeout_millis = 30000, - }; - std::vector<std::unique_ptr<EndpointManager::FrameProcessor>> processors_; - EndpointChannelManager ecm_; - EndpointManager em_{&ecm_}; - std::string endpoint_id_ = "endpoint_id"; - ConnectionResponseInfo info_ = { - .remote_endpoint_info = ByteArray{"info"}, - .authentication_token = "auth_token", - .raw_authentication_token = ByteArray{"auth_token"}, - .is_incoming_connection = true, - }; - struct MockConnectionListener { - StrictMock<MockFunction<void(const std::string& endpoint_id, - const ConnectionResponseInfo& info)>> - initiated_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id)>> accepted_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id, - const Status& status)>> - rejected_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id)>> - disconnected_cb; - StrictMock<MockFunction<void(const std::string& endpoint_id, - std::int32_t quality)>> - bandwidth_changed_cb; - } mock_listener_; - ConnectionListener listener_{ - .initiated_cb = mock_listener_.initiated_cb.AsStdFunction(), - .accepted_cb = mock_listener_.accepted_cb.AsStdFunction(), - .rejected_cb = mock_listener_.rejected_cb.AsStdFunction(), - .disconnected_cb = mock_listener_.disconnected_cb.AsStdFunction(), - .bandwidth_changed_cb = - mock_listener_.bandwidth_changed_cb.AsStdFunction(), - }; - std::string connection_token = "conntokn"; - absl::Time start_time_{absl::Now()}; -}; - -TEST_F(EndpointManagerTest, ConstructorDestructorWorks) { SUCCEED(); } - -TEST_F(EndpointManagerTest, RegisterEndpointCallsOnConnectionInitiated) { - auto endpoint_channel = std::make_unique<MockEndpointChannel>(); - EXPECT_CALL(*endpoint_channel, Read()) - .WillRepeatedly(Return(ExceptionOr<ByteArray>(Exception::kIo))); - EXPECT_CALL(*endpoint_channel, Close(_)).Times(1); - RegisterEndpoint(std::move(endpoint_channel)); -} - -TEST_F(EndpointManagerTest, UnregisterEndpointCallsOnDisconnected) { - auto endpoint_channel = std::make_unique<MockEndpointChannel>(); - EXPECT_CALL(*endpoint_channel, Read()) - .WillRepeatedly(Return(ExceptionOr<ByteArray>(Exception::kIo))); - RegisterEndpoint(std::make_unique<MockEndpointChannel>()); - // NOTE: disconnect_cb is not called, because we did not reach fully connected - // state. On top of that, UnregisterEndpoint is suppressing this notification. - // (IMO, it should be called as long as any connection callback was called - // before. (in this case initiated_cb is called)). - // Test captures current protocol behavior. - em_.UnregisterEndpoint(&client_, endpoint_id_); -} - -TEST_F(EndpointManagerTest, RegisterFrameProcessorWorks) { - auto endpoint_channel = std::make_unique<MockEndpointChannel>(); - auto connect_request = std::make_unique<MockFrameProcessor>(); - ByteArray endpoint_info{"endpoint_name"}; - auto read_data = - parser::ForConnectionRequest("endpoint_id", endpoint_info, 1234, false, - "", std::vector{Medium::BLE}, 0, 0); - EXPECT_CALL(*connect_request, OnIncomingFrame); - EXPECT_CALL(*connect_request, OnEndpointDisconnect); - EXPECT_CALL(*endpoint_channel, Read()) - .WillOnce(Return(ExceptionOr<ByteArray>(read_data))) - .WillRepeatedly(Return(ExceptionOr<ByteArray>(Exception::kIo))); - EXPECT_CALL(*endpoint_channel, Write(_)) - .WillRepeatedly(Return(Exception{Exception::kSuccess})); - // Register frame processor, then register endpoint. - // Endpoint will read one frame, then fail to read more and terminate. - // On disconnection, it will notify frame processor and we verify that. - em_.RegisterFrameProcessor(V1Frame::CONNECTION_REQUEST, - connect_request.get()); - processors_.emplace_back(std::move(connect_request)); - RegisterEndpoint(std::move(endpoint_channel)); -} - -TEST_F(EndpointManagerTest, UnregisterFrameProcessorWorks) { - auto endpoint_channel = std::make_unique<MockEndpointChannel>(); - EXPECT_CALL(*endpoint_channel, Read()) - .WillRepeatedly(Return(ExceptionOr<ByteArray>(Exception::kIo))); - EXPECT_CALL(*endpoint_channel, Write(_)) - .WillRepeatedly(Return(Exception{Exception::kSuccess})); - - // We should not receive any notifications to frame processor. - auto connect_request = std::make_unique<StrictMock<MockFrameProcessor>>(); - - // Register frame processor and immediately unregister it. - em_.RegisterFrameProcessor(V1Frame::CONNECTION_REQUEST, - connect_request.get()); - em_.UnregisterFrameProcessor(V1Frame::CONNECTION_REQUEST, - connect_request.get()); - - processors_.emplace_back(std::move(connect_request)); - // Endpoint will not send OnDisconnect notification to frame processor. - RegisterEndpoint(std::move(endpoint_channel), false); - em_.UnregisterEndpoint(&client_, endpoint_id_); -} - -TEST_F(EndpointManagerTest, SendControlMessageWorks) { - auto endpoint_channel = std::make_unique<MockEndpointChannel>(); - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::ControlMessage control; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_total_size(1024); - control.set_offset(150); - control.set_event(PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED); - - ON_CALL(*endpoint_channel, Read()) - .WillByDefault([channel = endpoint_channel.get()]() { - if (channel->IsClosed()) return ExceptionOr<ByteArray>(Exception::kIo); - NEARBY_LOG(INFO, "Simulate read delay: wait"); - absl::SleepFor(absl::Milliseconds(100)); - NEARBY_LOG(INFO, "Simulate read delay: done"); - if (channel->IsClosed()) return ExceptionOr<ByteArray>(Exception::kIo); - return ExceptionOr<ByteArray>(ByteArray{}); - }); - ON_CALL(*endpoint_channel, Close(_)) - .WillByDefault( - [channel = endpoint_channel.get()](DisconnectionReason reason) { - channel->DoClose(); - NEARBY_LOG(INFO, "Channel closed"); - }); - EXPECT_CALL(*endpoint_channel, Write(_)) - .WillRepeatedly(Return(Exception{Exception::kSuccess})); - - RegisterEndpoint(std::move(endpoint_channel), false); - auto failed_ids = - em_.SendControlMessage(header, control, std::vector{endpoint_id_}); - EXPECT_EQ(failed_ids, std::vector<std::string>{}); - NEARBY_LOG(INFO, "Will unregister endpoint now"); - em_.UnregisterEndpoint(&client_, endpoint_id_); - NEARBY_LOG(INFO, "Will call destructors now"); -} - -TEST_F(EndpointManagerTest, SingleReadOnInvalidPayload) { - auto endpoint_channel = std::make_unique<MockEndpointChannel>(); - EXPECT_CALL(*endpoint_channel, Read()) - .WillOnce( - Return(ExceptionOr<ByteArray>(Exception::kInvalidProtocolBuffer))); - EXPECT_CALL(*endpoint_channel, Write(_)) - .WillRepeatedly(Return(Exception{Exception::kSuccess})); - EXPECT_CALL(*endpoint_channel, Close(_)).Times(1); - RegisterEndpoint(std::move(endpoint_channel)); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/injected_bluetooth_device_store.cc b/chromium/third_party/nearby/src/cpp/core/internal/injected_bluetooth_device_store.cc deleted file mode 100644 index 1ba0a4229e5..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/injected_bluetooth_device_store.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/injected_bluetooth_device_store.h" - -#include <string> - -#include "core/internal/bluetooth_device_name.h" -#include "platform/api/bluetooth_classic.h" -#include "platform/base/bluetooth_utils.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -// api::BluetoothDevice implementation which stores a name and address passed to -// its constructor and trivially returns them to implement virtual functions. -class InjectedBluetoothDevice : public api::BluetoothDevice { - public: - InjectedBluetoothDevice(const std::string& name, - const std::string& mac_address) - : name_(name), mac_address_(mac_address) {} - - ~InjectedBluetoothDevice() override = default; - - // api::BluetoothDevice: - std::string GetName() const override { return name_; } - - std::string GetMacAddress() const override { return mac_address_; } - - private: - const std::string name_; - const std::string mac_address_; -}; - -} // namespace - -InjectedBluetoothDeviceStore::InjectedBluetoothDeviceStore() = default; - -InjectedBluetoothDeviceStore::~InjectedBluetoothDeviceStore() = default; - -BluetoothDevice InjectedBluetoothDeviceStore::CreateInjectedBluetoothDevice( - const ByteArray& remote_bluetooth_mac_address, - const std::string& endpoint_id, const ByteArray& endpoint_info, - const ByteArray& service_id_hash, Pcp pcp) { - std::string remote_bluetooth_mac_address_str = - BluetoothUtils::ToString(remote_bluetooth_mac_address); - - // Valid MAC address is required. - if (remote_bluetooth_mac_address_str.empty()) - return BluetoothDevice(/*device=*/nullptr); - - // Non-empty endpoint info is required. - if (endpoint_info.Empty()) return BluetoothDevice(/*device=*/nullptr); - - BluetoothDeviceName name(BluetoothDeviceName::Version::kV1, pcp, endpoint_id, - service_id_hash, endpoint_info, - /*uwb_address=*/ByteArray(), - WebRtcState::kConnectable); - - // Note: BluetoothDeviceName internally verifies that |endpoint_id| and - // |service_id_hash| are valid; the check below will fail if they are - // malformed. - if (!name.IsValid()) return BluetoothDevice(/*device=*/nullptr); - - auto injected_device = std::make_unique<InjectedBluetoothDevice>( - static_cast<std::string>(name), remote_bluetooth_mac_address_str); - BluetoothDevice device_to_return(injected_device.get()); - - // Store underlying device to ensure that it is kept alive for future use. - devices_.emplace_back(std::move(injected_device)); - - return device_to_return; -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/injected_bluetooth_device_store.h b/chromium/third_party/nearby/src/cpp/core/internal/injected_bluetooth_device_store.h deleted file mode 100644 index cc61c2fef33..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/injected_bluetooth_device_store.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_INJECTED_BLUETOOTH_DEVICE_STORE_H_ -#define CORE_INTERNAL_INJECTED_BLUETOOTH_DEVICE_STORE_H_ - -#include <memory> -#include <vector> - -#include "core/internal/pcp.h" -#include "platform/base/byte_array.h" -#include "platform/public/bluetooth_adapter.h" - -namespace location { -namespace nearby { -namespace connections { - -// Creates and stores BluetoothDevice objects which have been "injected" (i.e., -// passed to Nearby Connections manually by the client instead of through the -// normal discovery flow). -class InjectedBluetoothDeviceStore { - public: - InjectedBluetoothDeviceStore(); - ~InjectedBluetoothDeviceStore(); - - // Creates an injected BluetoothDevice given the provided parameters: - // |remote_bluetooth_mac_address|: A 6-byte MAC address. - // |endpoint_id|: A string of length 4. - // |endpoint_info|: A non-empty ByteArray whose length is <=131 bytes. - // |service_id_hash|: A ByteArray whose length is 3. - // |pcp|: PCP value to be used for the connection to this device. - // - // If the provided parameters are malformed or of incorrect length, this - // function returns an invalid BluetoothDevice. Clients should use - // BluetoothDevice::IsValid() with the returned device to verify that the - // parameters were successfully processed. - // - // Note that successfully-injected devices stay valid for the lifetime of the - // InjectedBluetoothDeviceStore and are not cleared until this object is - // deleted. - BluetoothDevice CreateInjectedBluetoothDevice( - const ByteArray& remote_bluetooth_mac_address, - const std::string& endpoint_id, const ByteArray& endpoint_info, - const ByteArray& service_id_hash, Pcp pcp); - - private: - // Devices created by this class. BluetoothDevice objects returned by - // CreateInjectedBluetoothDevice() store pointers to underlying - // api::BluetoothDevice objects, so this maintains these underlying devices - // to ensure that they are not deleted before they are referenced. - std::vector<std::unique_ptr<api::BluetoothDevice>> devices_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_INJECTED_BLUETOOTH_DEVICE_STORE_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/injected_bluetooth_device_store_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/injected_bluetooth_device_store_test.cc deleted file mode 100644 index a5e45f47884..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/injected_bluetooth_device_store_test.cc +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/injected_bluetooth_device_store.h" - -#include <array> - -#include "gtest/gtest.h" -#include "core/internal/bluetooth_device_name.h" -#include "platform/base/bluetooth_utils.h" -#include "platform/base/byte_array.h" -#include "platform/public/bluetooth_adapter.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -// Need to wrap with static_cast<char> to silence -Wc++11-narrowing issue. -constexpr std::array<char, 6> kTestRemoteBluetoothMacAddress{ - 0x01, 0x23, 0x45, 0x67, static_cast<char>(0x89), static_cast<char>(0xab)}; -constexpr std::array<char, 2> kTestEndpointInfo{static_cast<char>(0xcd), - static_cast<char>(0xef)}; -constexpr std::array<char, 3> kTestServiceIdHash{0x01, 0x23, 0x45}; - -const char kTestEndpointId[] = "abcd"; - -class InjectedBluetoothDeviceStoreTest : public testing::Test { - protected: - InjectedBluetoothDeviceStore store_; -}; - -TEST_F(InjectedBluetoothDeviceStoreTest, Success) { - ByteArray remote_bluetooth_mac_address(kTestRemoteBluetoothMacAddress); - ByteArray endpoint_info(kTestEndpointInfo); - ByteArray service_id_hash(kTestServiceIdHash); - - BluetoothDevice device = store_.CreateInjectedBluetoothDevice( - remote_bluetooth_mac_address, kTestEndpointId, endpoint_info, - service_id_hash, Pcp::kP2pPointToPoint); - EXPECT_TRUE(device.IsValid()); - - EXPECT_EQ(BluetoothUtils::ToString(remote_bluetooth_mac_address), - device.GetMacAddress()); - - BluetoothDeviceName name(device.GetName()); - EXPECT_TRUE(name.IsValid()); - EXPECT_EQ(kTestEndpointId, name.GetEndpointId()); - EXPECT_EQ(endpoint_info, name.GetEndpointInfo()); - EXPECT_EQ(service_id_hash, name.GetServiceIdHash()); - EXPECT_EQ(Pcp::kP2pPointToPoint, name.GetPcp()); -} - -TEST_F(InjectedBluetoothDeviceStoreTest, Fail_InvalidBluetoothMac) { - // Use address with only 1 byte. - ByteArray remote_bluetooth_mac_address(std::array<char, 1>{0x00}); - ByteArray endpoint_info(kTestEndpointInfo); - ByteArray service_id_hash(kTestServiceIdHash); - - BluetoothDevice device = store_.CreateInjectedBluetoothDevice( - remote_bluetooth_mac_address, kTestEndpointId, endpoint_info, - service_id_hash, Pcp::kP2pPointToPoint); - EXPECT_FALSE(device.IsValid()); -} - -TEST_F(InjectedBluetoothDeviceStoreTest, Fail_InvalidEndpointId) { - ByteArray remote_bluetooth_mac_address(kTestRemoteBluetoothMacAddress); - ByteArray endpoint_info(kTestEndpointInfo); - ByteArray service_id_hash(kTestServiceIdHash); - - // Use empty endpoint ID. - BluetoothDevice device1 = store_.CreateInjectedBluetoothDevice( - remote_bluetooth_mac_address, /*endpoint_id=*/std::string(), - endpoint_info, service_id_hash, Pcp::kP2pPointToPoint); - EXPECT_FALSE(device1.IsValid()); - - // Use endpoint ID of wrong length. - const std::string too_long_endpoint_id = "abcde"; - BluetoothDevice device2 = store_.CreateInjectedBluetoothDevice( - remote_bluetooth_mac_address, too_long_endpoint_id, endpoint_info, - service_id_hash, Pcp::kP2pPointToPoint); - EXPECT_FALSE(device2.IsValid()); -} - -TEST_F(InjectedBluetoothDeviceStoreTest, Fail_EmptyEndpointInfo) { - ByteArray remote_bluetooth_mac_address(kTestRemoteBluetoothMacAddress); - // Use empty endpoint info. - ByteArray endpoint_info; - ByteArray service_id_hash(kTestServiceIdHash); - - BluetoothDevice device = store_.CreateInjectedBluetoothDevice( - remote_bluetooth_mac_address, kTestEndpointId, endpoint_info, - service_id_hash, Pcp::kP2pPointToPoint); - EXPECT_FALSE(device.IsValid()); -} - -TEST_F(InjectedBluetoothDeviceStoreTest, Fail_InvalidServiceIdHash) { - ByteArray remote_bluetooth_mac_address(kTestRemoteBluetoothMacAddress); - ByteArray endpoint_info(kTestEndpointInfo); - // Use address with only 1 byte. - ByteArray service_id_hash(std::array<char, 1>{0x00}); - - BluetoothDevice device = store_.CreateInjectedBluetoothDevice( - remote_bluetooth_mac_address, kTestEndpointId, endpoint_info, - service_id_hash, Pcp::kP2pPointToPoint); - EXPECT_FALSE(device.IsValid()); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/internal_payload.cc b/chromium/third_party/nearby/src/cpp/core/internal/internal_payload.cc deleted file mode 100644 index fcb700256c4..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/internal_payload.cc +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/internal_payload.h" - -namespace location { -namespace nearby { -namespace connections { - -// The definition is necessary before C++17. -constexpr int InternalPayload::kIndeterminateSize; - -InternalPayload::InternalPayload(Payload payload) - : payload_(std::move(payload)), payload_id_(payload_.GetId()) {} - -Payload InternalPayload::ReleasePayload() { return std::move(payload_); } - -Payload::Id InternalPayload::GetId() const { return payload_id_; } - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/internal_payload.h b/chromium/third_party/nearby/src/cpp/core/internal/internal_payload.h deleted file mode 100644 index d4c25b2395c..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/internal_payload.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_INTERNAL_PAYLOAD_H_ -#define CORE_INTERNAL_INTERNAL_PAYLOAD_H_ - -#include <cstdint> - -#include "core/payload.h" -#include "platform/base/byte_array.h" -#include "platform/base/exception.h" - -namespace location { -namespace nearby { -namespace connections { - -// Defines the operations layered atop a Payload, for use inside the -// OfflineServiceController. -// -// <p>There will be an extension of this abstract base class per type of -// Payload. -class InternalPayload { - public: - static constexpr int kIndeterminateSize = -1; - - explicit InternalPayload(Payload payload); - virtual ~InternalPayload() = default; - - Payload ReleasePayload(); - - Payload::Id GetId() const; - - // Returns the PayloadType of the Payload to which this object is bound. - // - // <p>Note that this is supposed to return the type from the OfflineFrame - // proto rather than what is already available via - // Payload::getType(). - // - // @return The PayloadType. - virtual PayloadTransferFrame::PayloadHeader::PayloadType GetType() const = 0; - - // Deduces the total size of the Payload to which this object is bound. - // - // @return The total size, or -1 if it cannot be deduced (for example, when - // dealing with streaming data). - virtual std::int64_t GetTotalSize() const = 0; - - // Breaks off the next chunk from the Payload to which this object is bound. - // - // <p>Used when we have a complete Payload that we want to break into smaller - // byte blobs for sending across a hard boundary (like the other side of - // a Binder, or another device altogether). - // - // @param chunk_size The preferred size of the next chunk. Depending on - // payload type, the provided size may be ignored. - // @return The next chunk from the Payload, or null if we've reached the end. - virtual ByteArray DetachNextChunk(int chunk_size) = 0; - - // Adds the next chunk that comprises the Payload to which this object is - // bound. - // - // <p>Used when we are trying to reconstruct a Payload that lives on the - // other side of a hard boundary (like the other side of a Binder, or another - // device altogether), one byte blob at a time. - // - // @param chunk The next chunk; this being null signals that this is the last - // chunk, which will typically be used as a trigger to perform whatever state - // cleanup may be required by the concrete implementation. - virtual Exception AttachNextChunk(const ByteArray& chunk) = 0; - - // Skips current stream pointer to the offset. - // - // Used when this is a resume outgoing transfer, so we want to skip - // some data until the offset position. - // - // @return the offset really skipped - virtual ExceptionOr<size_t> SkipToOffset(size_t offset) = 0; - - // Cleans up any resources used by this Payload. Called when we're stopping - // early, e.g. after being cancelled or having no more recipients left. - virtual void Close() {} - - protected: - Payload payload_; - // We're caching the payload ID here because the backing payload will be - // released to another owner during the lifetime of an incoming - // InternalPayload. - Payload::Id payload_id_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_INTERNAL_PAYLOAD_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/internal_payload_factory.cc b/chromium/third_party/nearby/src/cpp/core/internal/internal_payload_factory.cc deleted file mode 100644 index 8895992d917..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/internal_payload_factory.cc +++ /dev/null @@ -1,350 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/internal_payload_factory.h" - -#include <cstdint> -#include <memory> - -#include "absl/memory/memory.h" -#include "core/payload.h" -#include "platform/base/byte_array.h" -#include "platform/base/exception.h" -#include "platform/public/condition_variable.h" -#include "platform/public/file.h" -#include "platform/public/logging.h" -#include "platform/public/mutex.h" -#include "platform/public/pipe.h" - -namespace location { -namespace nearby { -namespace connections { - -namespace { - -class BytesInternalPayload : public InternalPayload { - public: - explicit BytesInternalPayload(Payload payload) - : InternalPayload(std::move(payload)), - total_size_(payload_.AsBytes().size()), - detached_only_chunk_(false) {} - - PayloadTransferFrame::PayloadHeader::PayloadType GetType() const override { - return PayloadTransferFrame::PayloadHeader::BYTES; - } - - std::int64_t GetTotalSize() const override { return total_size_; } - - // Relinquishes ownership of the payload_; retrieves and returns the stored - // ByteArray. - ByteArray DetachNextChunk(int chunk_size) override { - if (detached_only_chunk_) { - return {}; - } - - detached_only_chunk_ = true; - return std::move(payload_).AsBytes(); - } - - // Does nothing. - Exception AttachNextChunk(const ByteArray& chunk) override { - return {Exception::kSuccess}; - } - - ExceptionOr<size_t> SkipToOffset(size_t offset) override { - NEARBY_LOGS(WARNING) << "Bytes payload does not support offsets"; - return {Exception::kIo}; - } - - private: - // We're caching the total size here because the backing payload will be - // moved to another owner during the lifetime of an incoming - // InternalPayload. - const std::int64_t total_size_; - bool detached_only_chunk_; -}; - -class OutgoingStreamInternalPayload : public InternalPayload { - public: - explicit OutgoingStreamInternalPayload(Payload payload) - : InternalPayload(std::move(payload)) {} - - PayloadTransferFrame::PayloadHeader::PayloadType GetType() const override { - return PayloadTransferFrame::PayloadHeader::STREAM; - } - - std::int64_t GetTotalSize() const override { return -1; } - - ByteArray DetachNextChunk(int chunk_size) override { - InputStream* input_stream = payload_.AsStream(); - if (!input_stream) return {}; - - ExceptionOr<ByteArray> bytes_read = input_stream->Read(chunk_size); - if (!bytes_read.ok()) { - input_stream->Close(); - return {}; - } - - ByteArray scoped_bytes_read = std::move(bytes_read.result()); - - if (scoped_bytes_read.Empty()) { - NEARBY_LOGS(INFO) << "No more data for outgoing payload " << this - << ", closing InputStream."; - - input_stream->Close(); - return {}; - } - - return scoped_bytes_read; - } - - Exception AttachNextChunk(const ByteArray& chunk) override { - return {Exception::kIo}; - } - - ExceptionOr<size_t> SkipToOffset(size_t offset) override { - InputStream* stream = payload_.AsStream(); - if (stream == nullptr) return {Exception::kIo}; - - ExceptionOr<size_t> real_offset = stream->Skip(offset); - if (real_offset.ok() && real_offset.GetResult() == offset) { - return real_offset; - } - // Close the outgoing stream on any error - stream->Close(); - if (!real_offset.ok()) { - return real_offset; - } - NEARBY_LOGS(WARNING) << "Skip offset: " << real_offset.GetResult() - << ", expected offset: " << offset << " for payload " - << this; - return {Exception::kIo}; - } - - void Close() override { - // Ignore the potential Exception returned by close(), as a counterpart - // to Java's closeQuietly(). - InputStream* stream = payload_.AsStream(); - if (stream) stream->Close(); - } -}; - -class IncomingStreamInternalPayload : public InternalPayload { - public: - IncomingStreamInternalPayload(Payload payload, OutputStream& output_stream) - : InternalPayload(std::move(payload)), output_stream_(&output_stream) {} - - PayloadTransferFrame::PayloadHeader::PayloadType GetType() const override { - return PayloadTransferFrame::PayloadHeader::STREAM; - } - - std::int64_t GetTotalSize() const override { return -1; } - - ByteArray DetachNextChunk(int chunk_size) override { return {}; } - - Exception AttachNextChunk(const ByteArray& chunk) override { - if (chunk.Empty()) { - NEARBY_LOGS(INFO) << "Received null last chunk for incoming payload " - << this << ", closing OutputStream."; - output_stream_->Close(); - return {Exception::kSuccess}; - } - - return output_stream_->Write(chunk); - } - - ExceptionOr<size_t> SkipToOffset(size_t offset) override { - NEARBY_LOGS(WARNING) << "Cannot skip offset for an incoming Payload " - << this; - return {Exception::kIo}; - } - - void Close() override { output_stream_->Close(); } - - private: - OutputStream* output_stream_; -}; - -class OutgoingFileInternalPayload : public InternalPayload { - public: - explicit OutgoingFileInternalPayload(Payload payload) - : InternalPayload(std::move(payload)), - total_size_{payload_.AsFile()->GetTotalSize()} {} - - PayloadTransferFrame::PayloadHeader::PayloadType GetType() const override { - return PayloadTransferFrame::PayloadHeader::FILE; - } - - std::int64_t GetTotalSize() const override { return total_size_; } - - ByteArray DetachNextChunk(int chunk_size) override { - InputFile* file = payload_.AsFile(); - if (!file) return {}; - - ExceptionOr<ByteArray> bytes_read = file->Read(chunk_size); - if (!bytes_read.ok()) { - return {}; - } - - ByteArray bytes = std::move(bytes_read.result()); - - if (bytes.Empty()) { - // No more data for outgoing payload. - - file->Close(); - return {}; - } - - return bytes; - } - - Exception AttachNextChunk(const ByteArray& chunk) override { - return {Exception::kIo}; - } - - ExceptionOr<size_t> SkipToOffset(size_t offset) override { - NEARBY_LOGS(INFO) << "SkipToOffset " << offset; - InputFile* file = payload_.AsFile(); - if (!file) { - return {Exception::kIo}; - } - - ExceptionOr<size_t> real_offset = file->Skip(offset); - if (real_offset.ok() && real_offset.GetResult() == offset) { - return real_offset; - } - // Close the outgoing file on any error - file->Close(); - if (!real_offset.ok()) { - return real_offset; - } - NEARBY_LOGS(WARNING) << "Skip offset: " << real_offset.GetResult() - << ", expected offset: " << offset - << " for file payload " << this; - return {Exception::kIo}; - } - - void Close() override { - InputFile* file = payload_.AsFile(); - if (file) file->Close(); - } - - private: - std::int64_t total_size_; -}; - -class IncomingFileInternalPayload : public InternalPayload { - public: - IncomingFileInternalPayload(Payload payload, OutputFile output_file, - std::int64_t total_size) - : InternalPayload(std::move(payload)), - output_file_(std::move(output_file)), - total_size_(total_size) {} - - PayloadTransferFrame::PayloadHeader::PayloadType GetType() const override { - return PayloadTransferFrame::PayloadHeader::FILE; - } - - std::int64_t GetTotalSize() const override { return total_size_; } - - ByteArray DetachNextChunk(int chunk_size) override { return {}; } - - Exception AttachNextChunk(const ByteArray& chunk) override { - if (chunk.Empty()) { - // Received null last chunk for incoming payload. - output_file_.Close(); - return {Exception::kSuccess}; - } - - return output_file_.Write(chunk); - } - - ExceptionOr<size_t> SkipToOffset(size_t offset) override { - NEARBY_LOGS(WARNING) << "Cannot skip offset for an incoming file Payload " - << this; - return {Exception::kIo}; - } - - void Close() override { output_file_.Close(); } - - private: - OutputFile output_file_; - const std::int64_t total_size_; -}; - -} // namespace - -std::unique_ptr<InternalPayload> CreateOutgoingInternalPayload( - Payload payload) { - switch (payload.GetType()) { - case Payload::Type::kBytes: - return absl::make_unique<BytesInternalPayload>(std::move(payload)); - - case Payload::Type::kFile: { - InputFile* file = payload.AsFile(); - const PayloadId file_payload_id = file ? file->GetPayloadId() : 0; - const PayloadId payload_id = payload.GetId(); - CHECK(payload_id == file_payload_id); - return absl::make_unique<OutgoingFileInternalPayload>(std::move(payload)); - } - - case Payload::Type::kStream: - return absl::make_unique<OutgoingStreamInternalPayload>( - std::move(payload)); - - default: - DCHECK(false); // This should never happen. - return {}; - } -} - -std::unique_ptr<InternalPayload> CreateIncomingInternalPayload( - const PayloadTransferFrame& frame) { - if (frame.packet_type() != PayloadTransferFrame::DATA) { - return {}; - } - - const Payload::Id payload_id = frame.payload_header().id(); - switch (frame.payload_header().type()) { - case PayloadTransferFrame::PayloadHeader::BYTES: { - return absl::make_unique<BytesInternalPayload>( - Payload(payload_id, ByteArray(frame.payload_chunk().body()))); - } - - case PayloadTransferFrame::PayloadHeader::STREAM: { - auto pipe = std::make_shared<Pipe>(); - - return absl::make_unique<IncomingStreamInternalPayload>( - Payload(payload_id, - [pipe]() -> InputStream& { - return pipe->GetInputStream(); // NOLINT - }), - pipe->GetOutputStream()); - } - - case PayloadTransferFrame::PayloadHeader::FILE: { - std::int64_t total_size = frame.payload_header().total_size(); - return absl::make_unique<IncomingFileInternalPayload>( - Payload(payload_id, InputFile(payload_id, total_size)), - OutputFile(payload_id), total_size); - } - default: - DCHECK(false); // This should never happen. - return {}; - } -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/internal_payload_factory.h b/chromium/third_party/nearby/src/cpp/core/internal/internal_payload_factory.h deleted file mode 100644 index a0387b77ed4..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/internal_payload_factory.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_INTERNAL_PAYLOAD_FACTORY_H_ -#define CORE_INTERNAL_INTERNAL_PAYLOAD_FACTORY_H_ - -#include "core/internal/internal_payload.h" -#include "core/payload.h" - -namespace location { -namespace nearby { -namespace connections { - -// Creates an InternalPayload representing an outgoing Payload. -std::unique_ptr<InternalPayload> CreateOutgoingInternalPayload(Payload payload); - -// Creates an InternalPayload representing an incoming Payload from a remote -// endpoint. -std::unique_ptr<InternalPayload> CreateIncomingInternalPayload( - const PayloadTransferFrame& frame); - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_INTERNAL_PAYLOAD_FACTORY_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/internal_payload_factory_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/internal_payload_factory_test.cc deleted file mode 100644 index adfbe9b264a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/internal_payload_factory_test.cc +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/internal_payload_factory.h" - -#include <string> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "core/internal/offline_frames.h" -#include "platform/base/byte_array.h" -#include "platform/public/pipe.h" -#include "proto/connections/offline_wire_formats.pb.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -constexpr char kText[] = "data chunk"; - -TEST(InternalPayloadFActoryTest, CanCreateIternalPayloadFromBytePayload) { - ByteArray data(kText); - std::unique_ptr<InternalPayload> internal_payload = - CreateOutgoingInternalPayload(Payload{data}); - EXPECT_NE(internal_payload, nullptr); - Payload payload = internal_payload->ReleasePayload(); - EXPECT_EQ(payload.AsFile(), nullptr); - EXPECT_EQ(payload.AsStream(), nullptr); - EXPECT_EQ(payload.AsBytes(), ByteArray(kText)); -} - -TEST(InternalPayloadFActoryTest, CanCreateIternalPayloadFromStreamPayload) { - auto pipe = std::make_shared<Pipe>(); - std::unique_ptr<InternalPayload> internal_payload = - CreateOutgoingInternalPayload(Payload{[pipe]() -> InputStream& { - return pipe->GetInputStream(); // NOLINT - }}); - EXPECT_NE(internal_payload, nullptr); - Payload payload = internal_payload->ReleasePayload(); - EXPECT_EQ(payload.AsFile(), nullptr); - EXPECT_NE(payload.AsStream(), nullptr); - EXPECT_EQ(payload.AsBytes(), ByteArray()); -} - -TEST(InternalPayloadFActoryTest, CanCreateIternalPayloadFromFilePayload) { - Payload::Id payload_id = Payload::GenerateId(); - std::unique_ptr<InternalPayload> internal_payload = - CreateOutgoingInternalPayload( - Payload{payload_id, InputFile(payload_id, 512)}); - EXPECT_NE(internal_payload, nullptr); - Payload payload = internal_payload->ReleasePayload(); - EXPECT_NE(payload.AsFile(), nullptr); - EXPECT_EQ(payload.AsStream(), nullptr); - EXPECT_EQ(payload.AsBytes(), ByteArray()); - EXPECT_EQ(payload.GetId(), payload_id); - EXPECT_EQ(payload.AsFile()->GetPayloadId(), payload_id); -} - -TEST(InternalPayloadFActoryTest, CanCreateIternalPayloadFromByteMessage) { - PayloadTransferFrame frame; - frame.set_packet_type(PayloadTransferFrame::DATA); - std::int64_t payload_chunk_offset = 0; - ByteArray data(kText); - PayloadTransferFrame::PayloadChunk payload_chunk; - payload_chunk.set_offset(payload_chunk_offset); - payload_chunk.set_body(std::string(std::move(data))); - payload_chunk.set_flags(0); - auto& header = *frame.mutable_payload_header(); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_id(12345); - header.set_total_size(512); - *frame.mutable_payload_chunk() = std::move(payload_chunk); - std::unique_ptr<InternalPayload> internal_payload = - CreateIncomingInternalPayload(frame); - EXPECT_NE(internal_payload, nullptr); - Payload payload = internal_payload->ReleasePayload(); - EXPECT_EQ(payload.AsFile(), nullptr); - EXPECT_EQ(payload.AsStream(), nullptr); - EXPECT_EQ(payload.AsBytes(), ByteArray(kText)); -} - -TEST(InternalPayloadFActoryTest, CanCreateIternalPayloadFromStreamMessage) { - PayloadTransferFrame frame; - frame.set_packet_type(PayloadTransferFrame::DATA); - auto& header = *frame.mutable_payload_header(); - header.set_type(PayloadTransferFrame::PayloadHeader::STREAM); - header.set_id(12345); - header.set_total_size(0); - std::unique_ptr<InternalPayload> internal_payload = - CreateIncomingInternalPayload(frame); - EXPECT_NE(internal_payload, nullptr); - Payload payload = internal_payload->ReleasePayload(); - EXPECT_EQ(payload.AsFile(), nullptr); - EXPECT_NE(payload.AsStream(), nullptr); - EXPECT_EQ(payload.AsBytes(), ByteArray()); - EXPECT_EQ(payload.GetType(), Payload::Type::kStream); -} - -TEST(InternalPayloadFActoryTest, CanCreateIternalPayloadFromFileMessage) { - PayloadTransferFrame frame; - frame.set_packet_type(PayloadTransferFrame::DATA); - auto& header = *frame.mutable_payload_header(); - header.set_type(PayloadTransferFrame::PayloadHeader::FILE); - header.set_id(12345); - header.set_total_size(512); - std::unique_ptr<InternalPayload> internal_payload = - CreateIncomingInternalPayload(frame); - EXPECT_NE(internal_payload, nullptr); - Payload payload = internal_payload->ReleasePayload(); - EXPECT_NE(payload.AsFile(), nullptr); - EXPECT_EQ(payload.AsStream(), nullptr); - EXPECT_EQ(payload.AsBytes(), ByteArray()); - EXPECT_EQ(payload.GetType(), Payload::Type::kFile); - EXPECT_EQ(payload.GetId(), payload.AsFile()->GetPayloadId()); -} - -void CreateFileWithContents(Payload::Id payload_id, const ByteArray& contents) { - OutputFile file(payload_id); - EXPECT_TRUE(file.Write(contents).Ok()); - EXPECT_TRUE(file.Close().Ok()); -} - -TEST(InternalPayloadFActoryTest, - SkipToOffset_FilePayloadValidOffset_SkipsOffset) { - ByteArray contents("0123456789"); - constexpr size_t kOffset = 4; - size_t size_after_skip = contents.size() - kOffset; - Payload::Id payload_id = Payload::GenerateId(); - CreateFileWithContents(payload_id, contents); - std::unique_ptr<InternalPayload> internal_payload = - CreateOutgoingInternalPayload( - Payload{payload_id, InputFile(payload_id, contents.size())}); - EXPECT_NE(internal_payload, nullptr); - - ExceptionOr<size_t> result = internal_payload->SkipToOffset(kOffset); - - EXPECT_TRUE(result.ok()); - EXPECT_EQ(result.GetResult(), kOffset); - EXPECT_EQ(internal_payload->GetTotalSize(), contents.size()); - ByteArray contents_after_skip = - internal_payload->DetachNextChunk(size_after_skip); - EXPECT_EQ(contents_after_skip, ByteArray("456789")); -} - -TEST(InternalPayloadFActoryTest, - SkipToOffset_StreamPayloadValidOffset_SkipsOffset) { - ByteArray contents("0123456789"); - constexpr size_t kOffset = 6; - auto pipe = std::make_shared<Pipe>(); - std::unique_ptr<InternalPayload> internal_payload = - CreateOutgoingInternalPayload(Payload{[pipe]() -> InputStream& { - return pipe->GetInputStream(); // NOLINT - }}); - EXPECT_NE(internal_payload, nullptr); - pipe->GetOutputStream().Write(contents); - - ExceptionOr<size_t> result = internal_payload->SkipToOffset(kOffset); - - EXPECT_TRUE(result.ok()); - EXPECT_EQ(result.GetResult(), kOffset); - EXPECT_EQ(internal_payload->GetTotalSize(), -1); - ByteArray contents_after_skip = internal_payload->DetachNextChunk(512); - EXPECT_EQ(contents_after_skip, ByteArray("6789")); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/BUILD b/chromium/third_party/nearby/src/cpp/core/internal/mediums/BUILD deleted file mode 100644 index 7f5307234a3..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/BUILD +++ /dev/null @@ -1,142 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -licenses(["notice"]) - -cc_library( - name = "mediums", - srcs = [ - "ble.cc", - "bloom_filter.cc", - "bluetooth_classic.cc", - "bluetooth_radio.cc", - "mediums.cc", - "uuid.cc", - "webrtc.cc", - "wifi_lan.cc", - ], - hdrs = [ - "ble.h", - "bloom_filter.h", - "bluetooth_classic.h", - "bluetooth_radio.h", - "lost_entity_tracker.h", - "mediums.h", - "uuid.h", - "webrtc.h", - "wifi_lan.h", - ], - compatible_with = ["//buildenv/target:non_prod"], - visibility = [ - "//core/internal:__subpackages__", - ], - deps = [ - ":utils", - "//absl/container:flat_hash_map", - "//absl/container:flat_hash_set", - "//absl/functional:bind_front", - "//absl/numeric:int128", - "//absl/strings", - "//absl/strings:str_format", - "//absl/time", - "//core:core_types", - "//core/internal/mediums/ble_v2", - "//core/internal/mediums/webrtc", - "//core/internal/mediums/webrtc:data_types", - "//platform/base", - "//platform/base:cancellation_flag", - "//platform/public:comm", - "//platform/public:logging", - "//platform/public:types", - "//proto/connections:offline_wire_formats_portable_proto", - "//proto/mediums:web_rtc_signaling_frames_cc_proto", - "//smhasher:libmurmur3", - "//webrtc/api:libjingle_peerconnection_api", - ], -) - -cc_library( - name = "utils", - srcs = [ - "utils.cc", - "webrtc_peer_id.cc", - ], - hdrs = [ - "utils.h", - "webrtc_peer_id.h", - "webrtc_socket_wrapper.h", - ], - compatible_with = ["//buildenv/target:non_prod"], - visibility = [ - "//core/internal:__pkg__", - "//core/internal/mediums:__pkg__", - "//core/internal/mediums/webrtc:__pkg__", - ], - deps = [ - "//absl/strings", - "//core/internal/mediums/webrtc:data_types", - "//platform/base", - "//platform/public:types", - "//proto/connections:offline_wire_formats_portable_proto", - ], -) - -cc_test( - name = "core_internal_mediums_test", - size = "small", - srcs = [ - "ble_test.cc", - "bloom_filter_test.cc", - "bluetooth_classic_test.cc", - "bluetooth_radio_test.cc", - "lost_entity_tracker_test.cc", - "uuid_test.cc", - "wifi_lan_test.cc", - ], - shard_count = 16, - deps = [ - ":mediums", - ":utils", - "//testing/base/public:gunit_main", - "//absl/strings", - "//absl/time", - "//platform/base", - "//platform/base:test_util", - "//platform/impl/g3", # build_cleaner: keep - "//platform/public:comm", - "//platform/public:types", - ], -) - -cc_test( - name = "core_internal_mediums_webrtc_test", - size = "small", - srcs = [ - "webrtc_peer_id_test.cc", - "webrtc_test.cc", - ], - shard_count = 16, - tags = [ - "notsan", # NOTE(b/139734036): known data race in usrsctplib. - "requires-net:external", - ], - deps = [ - ":mediums", - ":utils", - "//testing/base/public:gunit_main", - "//platform/base", - "//platform/base:test_util", - "//platform/impl/g3", # build_cleaner: keep - "//platform/public:types", - ], -) diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble.cc deleted file mode 100644 index 63e54f8dce7..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble.cc +++ /dev/null @@ -1,361 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/ble.h" - -#include <memory> -#include <string> -#include <utility> - -#include "absl/strings/escaping.h" -#include "core/internal/mediums/ble_v2/ble_advertisement.h" -#include "core/internal/mediums/utils.h" -#include "platform/base/prng.h" -#include "platform/public/logging.h" -#include "platform/public/mutex_lock.h" - -namespace location { -namespace nearby { -namespace connections { - -ByteArray Ble::GenerateHash(const std::string& source, size_t size) { - return Utils::Sha256Hash(source, size); -} - -ByteArray Ble::GenerateDeviceToken() { - return Utils::Sha256Hash(std::to_string(Prng().NextUint32()), - mediums::BleAdvertisement::kDeviceTokenLength); -} - -Ble::Ble(BluetoothRadio& radio) : radio_(radio) {} - -bool Ble::IsAvailable() const { - MutexLock lock(&mutex_); - - return IsAvailableLocked(); -} - -bool Ble::IsAvailableLocked() const { return medium_.IsValid(); } - -bool Ble::StartAdvertising(const std::string& service_id, - const ByteArray& advertisement_bytes, - const std::string& fast_advertisement_service_uuid) { - MutexLock lock(&mutex_); - - if (advertisement_bytes.Empty()) { - NEARBY_LOGS(INFO) - << "Refusing to turn on BLE advertising. Empty advertisement data."; - return false; - } - - if (advertisement_bytes.size() > kMaxAdvertisementLength) { - NEARBY_LOG(INFO, - "Refusing to start BLE advertising because the advertisement " - "was too long. Expected at most %d bytes but received %d.", - kMaxAdvertisementLength, advertisement_bytes.size()); - return false; - } - - if (IsAdvertisingLocked(service_id)) { - NEARBY_LOGS(INFO) - << "Failed to BLE advertise because we're already advertising."; - return false; - } - - if (!radio_.IsEnabled()) { - NEARBY_LOGS(INFO) - << "Can't start BLE scanning because Bluetooth was never turned on"; - return false; - } - - if (!IsAvailableLocked()) { - NEARBY_LOGS(INFO) << "Can't turn on BLE advertising. BLE is not available."; - return false; - } - - NEARBY_LOGS(INFO) << "Turning on BLE advertising (advertisement size=" - << advertisement_bytes.size() << ")" - << ", service id=" << service_id - << ", fast advertisement service uuid=" - << fast_advertisement_service_uuid; - - // Wrap the connections advertisement to the medium advertisement. - const bool fast_advertisement = !fast_advertisement_service_uuid.empty(); - ByteArray service_id_hash{GenerateHash( - service_id, mediums::BleAdvertisement::kServiceIdHashLength)}; - ByteArray medium_advertisement_bytes{mediums::BleAdvertisement{ - mediums::BleAdvertisement::Version::kV2, - mediums::BleAdvertisement::SocketVersion::kV2, - fast_advertisement ? ByteArray{} : service_id_hash, advertisement_bytes, - GenerateDeviceToken()}}; - if (medium_advertisement_bytes.Empty()) { - NEARBY_LOGS(INFO) << "Failed to BLE advertise because we could not " - "create a medium advertisement."; - return false; - } - - if (!medium_.StartAdvertising(service_id, medium_advertisement_bytes, - fast_advertisement_service_uuid)) { - NEARBY_LOGS(ERROR) - << "Failed to turn on BLE advertising with advertisement bytes=" - << absl::BytesToHexString(advertisement_bytes.data()) - << ", size=" << advertisement_bytes.size() - << ", fast advertisement service uuid=" - << fast_advertisement_service_uuid; - return false; - } - - advertising_info_.Add(service_id); - return true; -} - -bool Ble::StopAdvertising(const std::string& service_id) { - MutexLock lock(&mutex_); - - if (!IsAdvertisingLocked(service_id)) { - NEARBY_LOGS(INFO) << "Can't turn off BLE advertising; it is already off"; - return false; - } - - NEARBY_LOGS(INFO) << "Turned off BLE advertising with service id=" - << service_id; - bool ret = medium_.StopAdvertising(service_id); - // Reset our bundle of advertising state to mark that we're no longer - // advertising. - advertising_info_.Remove(service_id); - return ret; -} - -bool Ble::IsAdvertising(const std::string& service_id) { - MutexLock lock(&mutex_); - - return IsAdvertisingLocked(service_id); -} - -bool Ble::IsAdvertisingLocked(const std::string& service_id) { - return advertising_info_.Existed(service_id); -} - -bool Ble::StartScanning(const std::string& service_id, - const std::string& fast_advertisement_service_uuid, - DiscoveredPeripheralCallback callback) { - MutexLock lock(&mutex_); - - discovered_peripheral_callback_ = std::move(callback); - - if (service_id.empty()) { - NEARBY_LOGS(INFO) - << "Refusing to start BLE scanning with empty service id."; - return false; - } - - if (IsScanningLocked(service_id)) { - NEARBY_LOGS(INFO) << "Refusing to start scan of BLE peripherals because " - "another scanning is already in-progress."; - return false; - } - - if (!radio_.IsEnabled()) { - NEARBY_LOGS(INFO) - << "Can't start BLE scanning because Bluetooth was never turned on"; - return false; - } - - if (!IsAvailableLocked()) { - NEARBY_LOGS(INFO) - << "Can't scan BLE peripherals because BLE isn't available."; - return false; - } - - if (!medium_.StartScanning( - service_id, fast_advertisement_service_uuid, - { - .peripheral_discovered_cb = - [this](BlePeripheral& peripheral, - const std::string& service_id, - const ByteArray& medium_advertisement_bytes, - bool fast_advertisement) { - // Don't bother trying to parse zero byte advertisements. - if (medium_advertisement_bytes.size() == 0) { - NEARBY_LOGS(INFO) << "Skipping zero byte advertisement " - << "with service_id: " << service_id; - return; - } - // Unwrap connection BleAdvertisement from medium - // BleAdvertisement. - auto connection_advertisement_bytes = - UnwrapAdvertisementBytes(medium_advertisement_bytes); - discovered_peripheral_callback_.peripheral_discovered_cb( - peripheral, service_id, connection_advertisement_bytes, - fast_advertisement); - }, - .peripheral_lost_cb = - [this](BlePeripheral& peripheral, - const std::string& service_id) { - discovered_peripheral_callback_.peripheral_lost_cb( - peripheral, service_id); - }, - })) { - NEARBY_LOGS(INFO) << "Failed to start scan of BLE services."; - return false; - } - - NEARBY_LOGS(INFO) << "Turned on BLE scanning with service id=" << service_id; - // Mark the fact that we're currently performing a BLE discovering. - scanning_info_.Add(service_id); - return true; -} - -bool Ble::StopScanning(const std::string& service_id) { - MutexLock lock(&mutex_); - - if (!IsScanningLocked(service_id)) { - NEARBY_LOGS(INFO) << "Can't turn off BLE sacanning because we never " - "started scanning."; - return false; - } - - NEARBY_LOG(INFO, "Turned off BLE scanning with service id=%s", - service_id.c_str()); - bool ret = medium_.StopScanning(service_id); - scanning_info_.Clear(); - return ret; -} - -bool Ble::IsScanning(const std::string& service_id) { - MutexLock lock(&mutex_); - - return IsScanningLocked(service_id); -} - -bool Ble::IsScanningLocked(const std::string& service_id) { - return scanning_info_.Existed(service_id); -} - -bool Ble::StartAcceptingConnections(const std::string& service_id, - AcceptedConnectionCallback callback) { - MutexLock lock(&mutex_); - - if (service_id.empty()) { - NEARBY_LOGS(INFO) - << "Refusing to start accepting BLE connections with empty service id."; - return false; - } - - if (IsAcceptingConnectionsLocked(service_id)) { - NEARBY_LOGS(INFO) - << "Refusing to start accepting BLE connections for " << service_id - << " because another BLE peripheral socket is already in-progress."; - return false; - } - - if (!radio_.IsEnabled()) { - NEARBY_LOGS(INFO) << "Can't start accepting BLE connections for " - << service_id << " because Bluetooth isn't enabled."; - return false; - } - - if (!IsAvailableLocked()) { - NEARBY_LOGS(INFO) << "Can't start accepting BLE connections for " - << service_id << " because BLE isn't available."; - return false; - } - - if (!medium_.StartAcceptingConnections(service_id, callback)) { - NEARBY_LOGS(INFO) << "Failed to accept connections callback for " - << service_id << " ."; - return false; - } - - accepting_connections_info_.Add(service_id); - return true; -} - -bool Ble::StopAcceptingConnections(const std::string& service_id) { - MutexLock lock(&mutex_); - - if (!IsAcceptingConnectionsLocked(service_id)) { - NEARBY_LOGS(INFO) - << "Can't stop accepting BLE connections because it was never started."; - return false; - } - - bool ret = medium_.StopAcceptingConnections(service_id); - // Reset our bundle of accepting connections state to mark that we're no - // longer accepting connections. - accepting_connections_info_.Remove(service_id); - return ret; -} - -bool Ble::IsAcceptingConnections(const std::string& service_id) { - MutexLock lock(&mutex_); - - return IsAcceptingConnectionsLocked(service_id); -} - -bool Ble::IsAcceptingConnectionsLocked(const std::string& service_id) { - return accepting_connections_info_.Existed(service_id); -} - -BleSocket Ble::Connect(BlePeripheral& peripheral, const std::string& service_id, - CancellationFlag* cancellation_flag) { - MutexLock lock(&mutex_); - NEARBY_LOGS(INFO) << "BLE::Connect: service=" << &peripheral; - // Socket to return. To allow for NRVO to work, it has to be a single object. - BleSocket socket; - - if (service_id.empty()) { - NEARBY_LOGS(INFO) << "Refusing to create BLE socket with empty service_id."; - return socket; - } - - if (!radio_.IsEnabled()) { - NEARBY_LOGS(INFO) << "Can't create client BLE socket to " << &peripheral - << " because Bluetooth isn't enabled."; - return socket; - } - - if (!IsAvailableLocked()) { - NEARBY_LOGS(INFO) << "Can't create client BLE socket [service_id=" - << service_id << "]; BLE isn't available."; - return socket; - } - - if (cancellation_flag->Cancelled()) { - NEARBY_LOGS(INFO) << "Can't create client BLE socket due to cancel."; - return socket; - } - - socket = medium_.Connect(peripheral, service_id, cancellation_flag); - if (!socket.IsValid()) { - NEARBY_LOGS(INFO) << "Failed to Connect via BLE [service=" << service_id - << "]"; - } - - return socket; -} - -ByteArray Ble::UnwrapAdvertisementBytes( - const ByteArray& medium_advertisement_data) { - mediums::BleAdvertisement medium_ble_advertisement{medium_advertisement_data}; - if (!medium_ble_advertisement.IsValid()) { - return ByteArray{}; - } - - return medium_ble_advertisement.GetData(); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble.h deleted file mode 100644 index bfacb340bfb..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble.h +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_BLE_H_ -#define CORE_INTERNAL_MEDIUMS_BLE_H_ - -#include <cstdint> -#include <string> - -#include "absl/container/flat_hash_map.h" -#include "absl/container/flat_hash_set.h" -#include "core/internal/mediums/bluetooth_radio.h" -#include "core/listeners.h" -#include "platform/base/byte_array.h" -#include "platform/base/cancellation_flag.h" -#include "platform/public/ble.h" -#include "platform/public/multi_thread_executor.h" -#include "platform/public/mutex.h" - -namespace location { -namespace nearby { -namespace connections { - -class Ble { - public: - using DiscoveredPeripheralCallback = BleMedium::DiscoveredPeripheralCallback; - using AcceptedConnectionCallback = BleMedium::AcceptedConnectionCallback; - - explicit Ble(BluetoothRadio& bluetooth_radio); - ~Ble() = default; - - // Returns true, if Ble communications are supported by a platform. - bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_); - - // Sets custom advertisement data, and then enables Ble advertising. - // Returns true, if data is successfully set, and false otherwise. - bool StartAdvertising(const std::string& service_id, - const ByteArray& advertisement_bytes, - const std::string& fast_advertisement_service_uuid) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Disables Ble advertising. - bool StopAdvertising(const std::string& service_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - bool IsAdvertising(const std::string& service_id) ABSL_LOCKS_EXCLUDED(mutex_); - - // Enables Ble scanning mode. Will report any discoverable peripherals in - // range through a callback. Returns true, if scanning mode was enabled, - // false otherwise. - bool StartScanning(const std::string& service_id, - const std::string& fast_advertisement_service_uuid, - DiscoveredPeripheralCallback callback) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Disables Ble discovery mode. - bool StopScanning(const std::string& service_id) ABSL_LOCKS_EXCLUDED(mutex_); - - bool IsScanning(const std::string& service_id) ABSL_LOCKS_EXCLUDED(mutex_); - - // Starts a worker thread, creates a Ble socket, associates it with a - // service id. - bool StartAcceptingConnections(const std::string& service_id, - AcceptedConnectionCallback callback) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Closes socket corresponding to a service id. - bool StopAcceptingConnections(const std::string& service_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - bool IsAcceptingConnections(const std::string& service_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true if this object owns a valid platform implementation. - bool IsMediumValid() const ABSL_LOCKS_EXCLUDED(mutex_) { - MutexLock lock(&mutex_); - return medium_.IsValid(); - } - - // Returns true if this object has a valid BluetoothAdapter reference. - bool IsAdapterValid() const ABSL_LOCKS_EXCLUDED(mutex_) { - MutexLock lock(&mutex_); - return adapter_.IsValid(); - } - - // Establishes connection to Ble peripheral that was might be started on - // another peripheral with StartAcceptingConnections() using the same - // service_id. Blocks until connection is established, or server-side is - // terminated. Returns socket instance. On success, BleSocket.IsValid() return - // true. - BleSocket Connect(BlePeripheral& peripheral, const std::string& service_id, - CancellationFlag* cancellation_flag) - ABSL_LOCKS_EXCLUDED(mutex_); - - private: - struct AdvertisingInfo { - bool Empty() const { return service_ids.empty(); } - void Clear() { service_ids.clear(); } - void Add(const std::string& service_id) { service_ids.emplace(service_id); } - void Remove(const std::string& service_id) { - service_ids.erase(service_id); - } - bool Existed(const std::string& service_id) const { - return service_ids.contains(service_id); - } - - absl::flat_hash_set<std::string> service_ids; - }; - - struct ScanningInfo { - bool Empty() const { return service_ids.empty(); } - void Clear() { service_ids.clear(); } - void Add(const std::string& service_id) { service_ids.emplace(service_id); } - void Remove(const std::string& service_id) { - service_ids.erase(service_id); - } - bool Existed(const std::string& service_id) const { - return service_ids.contains(service_id); - } - - absl::flat_hash_set<std::string> service_ids; - }; - - struct AcceptingConnectionsInfo { - bool Empty() const { return service_ids.empty(); } - void Clear() { service_ids.clear(); } - void Add(const std::string& service_id) { service_ids.emplace(service_id); } - void Remove(const std::string& service_id) { - service_ids.erase(service_id); - } - bool Existed(const std::string& service_id) const { - return service_ids.contains(service_id); - } - - absl::flat_hash_set<std::string> service_ids; - }; - - static constexpr int kMaxAdvertisementLength = 512; - - static ByteArray GenerateHash(const std::string& source, size_t size); - static ByteArray GenerateDeviceToken(); - - // Same as IsAvailable(), but must be called with mutex_ held. - bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Same as IsAdvertising(), but must be called with mutex_ held. - bool IsAdvertisingLocked(const std::string& service_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Same as IsDiscovering(), but must be called with mutex_ held. - bool IsScanningLocked(const std::string& service_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Same as IsAcceptingConnections(), but must be called with mutex_ held. - bool IsAcceptingConnectionsLocked(const std::string& service_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Extract connection advertisement from medium advertisement. - ByteArray UnwrapAdvertisementBytes( - const ByteArray& medium_advertisement_data); - - mutable Mutex mutex_; - BluetoothRadio& radio_ ABSL_GUARDED_BY(mutex_); - BluetoothAdapter& adapter_ ABSL_GUARDED_BY(mutex_){ - radio_.GetBluetoothAdapter()}; - BleMedium medium_ ABSL_GUARDED_BY(mutex_){adapter_}; - AdvertisingInfo advertising_info_ ABSL_GUARDED_BY(mutex_); - ScanningInfo scanning_info_ ABSL_GUARDED_BY(mutex_); - DiscoveredPeripheralCallback discovered_peripheral_callback_; - AcceptingConnectionsInfo accepting_connections_info_ ABSL_GUARDED_BY(mutex_); -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_BLE_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_test.cc deleted file mode 100644 index 6f03e677617..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_test.cc +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/ble.h" - -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "core/internal/mediums/bluetooth_radio.h" -#include "platform/base/medium_environment.h" -#include "platform/public/ble.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -using FeatureFlags = FeatureFlags::Flags; - -constexpr FeatureFlags kTestCases[] = { - FeatureFlags{ - .enable_cancellation_flag = true, - }, - FeatureFlags{ - .enable_cancellation_flag = false, - }, -}; - -constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000); -constexpr absl::string_view kServiceID{"com.google.location.nearby.apps.test"}; -constexpr absl::string_view kAdvertisementString{"\x0a\x0b\x0c\x0d"}; -constexpr absl::string_view kFastAdvertisementServiceUuid{"\xf3\xfe"}; - -class BleTest : public ::testing::TestWithParam<FeatureFlags> { - protected: - using DiscoveredPeripheralCallback = BleMedium::DiscoveredPeripheralCallback; - - BleTest() { env_.Stop(); } - - MediumEnvironment& env_{MediumEnvironment::Instance()}; -}; - -TEST_P(BleTest, CanStartAcceptingConnectionsAndConnect) { - FeatureFlags feature_flags = GetParam(); - env_.SetFeatureFlags(feature_flags); - env_.Start(); - BluetoothRadio radio_a; - BluetoothRadio radio_b; - Ble ble_a{radio_a}; - Ble ble_b{radio_b}; - radio_a.Enable(); - radio_b.Enable(); - std::string service_id(kServiceID); - ByteArray advertisement_bytes{std::string(kAdvertisementString)}; - std::string fast_advertisement_service_uuid(kFastAdvertisementServiceUuid); - CountDownLatch found_latch(1); - CountDownLatch accept_latch(1); - - ble_a.StartAdvertising(service_id, advertisement_bytes, - fast_advertisement_service_uuid); - ble_a.StartAcceptingConnections( - service_id, - { - .accepted_cb = [&accept_latch]( - BleSocket socket, - const std::string&) { accept_latch.CountDown(); }, - }); - BlePeripheral discovered_peripheral; - ble_b.StartScanning( - service_id, fast_advertisement_service_uuid, - { - .peripheral_discovered_cb = - [&found_latch, &discovered_peripheral]( - BlePeripheral& peripheral, const std::string& service_id, - const ByteArray& advertisement_bytes, - bool fast_advertisement) { - discovered_peripheral = peripheral; - NEARBY_LOG( - INFO, - "Discovered peripheral=%p [impl=%p], fast advertisement=%d", - &peripheral, &peripheral.GetImpl(), fast_advertisement); - found_latch.CountDown(); - }, - }); - - EXPECT_TRUE(found_latch.Await(kWaitDuration).result()); - ASSERT_TRUE(discovered_peripheral.IsValid()); - CancellationFlag flag; - BleSocket socket = ble_b.Connect(discovered_peripheral, service_id, &flag); - EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(socket.IsValid()); - ble_b.StopScanning(service_id); - ble_a.StopAdvertising(service_id); - env_.Stop(); -} - -TEST_P(BleTest, CanCancelConnect) { - FeatureFlags feature_flags = GetParam(); - env_.SetFeatureFlags(feature_flags); - env_.Start(); - BluetoothRadio radio_a; - BluetoothRadio radio_b; - Ble ble_a{radio_a}; - Ble ble_b{radio_b}; - radio_a.Enable(); - radio_b.Enable(); - std::string service_id(kServiceID); - ByteArray advertisement_bytes{std::string(kAdvertisementString)}; - std::string fast_advertisement_service_uuid(kFastAdvertisementServiceUuid); - CountDownLatch found_latch(1); - CountDownLatch accept_latch(1); - - ble_a.StartAdvertising(service_id, advertisement_bytes, - fast_advertisement_service_uuid); - ble_a.StartAcceptingConnections( - service_id, - { - .accepted_cb = [&accept_latch]( - BleSocket socket, - const std::string&) { accept_latch.CountDown(); }, - }); - BlePeripheral discovered_peripheral; - ble_b.StartScanning( - service_id, fast_advertisement_service_uuid, - { - .peripheral_discovered_cb = - [&found_latch, &discovered_peripheral]( - BlePeripheral& peripheral, const std::string& service_id, - const ByteArray& advertisement_bytes, - bool fast_advertisement) { - discovered_peripheral = peripheral; - NEARBY_LOG( - INFO, - "Discovered peripheral=%p [impl=%p], fast advertisement=%d", - &peripheral, &peripheral.GetImpl(), fast_advertisement); - found_latch.CountDown(); - }, - }); - - EXPECT_TRUE(found_latch.Await(kWaitDuration).result()); - ASSERT_TRUE(discovered_peripheral.IsValid()); - CancellationFlag flag(true); - BleSocket socket = ble_b.Connect(discovered_peripheral, service_id, &flag); - // If FeatureFlag is disabled, Cancelled is false as no-op. - if (!feature_flags.enable_cancellation_flag) { - EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(socket.IsValid()); - } else { - EXPECT_FALSE(accept_latch.Await(kWaitDuration).result()); - EXPECT_FALSE(socket.IsValid()); - } - ble_b.StopScanning(service_id); - ble_a.StopAdvertising(service_id); - env_.Stop(); -} - -INSTANTIATE_TEST_SUITE_P(ParametrisedBleTest, BleTest, - ::testing::ValuesIn(kTestCases)); - -TEST_F(BleTest, CanConstructValidObject) { - env_.Start(); - BluetoothRadio radio_a; - BluetoothRadio radio_b; - Ble ble_a{radio_a}; - Ble ble_b{radio_b}; - - EXPECT_TRUE(ble_a.IsMediumValid()); - EXPECT_TRUE(ble_a.IsAdapterValid()); - EXPECT_TRUE(ble_a.IsAvailable()); - EXPECT_TRUE(ble_b.IsMediumValid()); - EXPECT_TRUE(ble_b.IsAdapterValid()); - EXPECT_TRUE(ble_b.IsAvailable()); - EXPECT_NE(&radio_a.GetBluetoothAdapter(), &radio_b.GetBluetoothAdapter()); - env_.Stop(); -} - -TEST_F(BleTest, CanStartAdvertising) { - env_.Start(); - BluetoothRadio radio_a; - BluetoothRadio radio_b; - Ble ble_a{radio_a}; - Ble ble_b{radio_b}; - radio_a.Enable(); - radio_b.Enable(); - std::string service_id(kServiceID); - ByteArray advertisement_bytes{std::string(kAdvertisementString)}; - std::string fast_advertisement_service_uuid(kFastAdvertisementServiceUuid); - CountDownLatch found_latch(1); - - ble_b.StartScanning( - service_id, fast_advertisement_service_uuid, - DiscoveredPeripheralCallback{ - .peripheral_discovered_cb = - [&found_latch]( - BlePeripheral& peripheral, const std::string& service_id, - const ByteArray& advertisement_bytes, - bool fast_advertisement) { found_latch.CountDown(); }, - }); - - EXPECT_TRUE(ble_a.StartAdvertising(service_id, advertisement_bytes, - fast_advertisement_service_uuid)); - EXPECT_TRUE(found_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(ble_a.StopAdvertising(service_id)); - EXPECT_TRUE(ble_b.StopScanning(service_id)); - env_.Stop(); -} - -TEST_F(BleTest, CanStartDiscovery) { - env_.Start(); - BluetoothRadio radio_a; - BluetoothRadio radio_b; - Ble ble_a{radio_a}; - Ble ble_b{radio_b}; - radio_a.Enable(); - radio_b.Enable(); - std::string service_id(kServiceID); - ByteArray advertisement_bytes{std::string(kAdvertisementString)}; - std::string fast_advertisement_service_uuid(kFastAdvertisementServiceUuid); - CountDownLatch accept_latch(1); - CountDownLatch lost_latch(1); - - ble_b.StartAdvertising(service_id, advertisement_bytes, - fast_advertisement_service_uuid); - - EXPECT_TRUE(ble_a.StartScanning( - service_id, fast_advertisement_service_uuid, - DiscoveredPeripheralCallback{ - .peripheral_discovered_cb = - [&accept_latch]( - BlePeripheral& peripheral, const std::string& service_id, - const ByteArray& advertisement_bytes, - bool fast_advertisement) { accept_latch.CountDown(); }, - .peripheral_lost_cb = - [&lost_latch](BlePeripheral& peripheral, - const std::string& service_id) { - lost_latch.CountDown(); - }, - })); - EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - ble_b.StopAdvertising(service_id); - EXPECT_TRUE(lost_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(ble_a.StopScanning(service_id)); - env_.Stop(); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/BUILD b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/BUILD deleted file mode 100644 index 6aff35972f6..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/BUILD +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -licenses(["notice"]) - -cc_library( - name = "ble_v2", - srcs = [ - "advertisement_read_result.cc", - "ble_advertisement.cc", - "ble_advertisement_header.cc", - "ble_packet.cc", - ], - hdrs = [ - "advertisement_read_result.h", - "ble_advertisement.h", - "ble_advertisement_header.h", - "ble_packet.h", - "ble_peripheral.h", - "discovered_peripheral_callback.h", - ], - compatible_with = ["//buildenv/target:non_prod"], - copts = ["-DCORE_ADAPTER_DLL"], - visibility = [ - "//core/internal:__subpackages__", - ], - deps = [ - "//absl/container:flat_hash_map", - "//absl/container:flat_hash_set", - "//absl/strings", - "//absl/time", - "//core:core_types", - "//platform/base", - "//platform/base:util", - "//platform/public:logging", - "//platform/public:types", - ], -) - -cc_test( - name = "ble_v2_test", - srcs = [ - "advertisement_read_result_test.cc", - "ble_advertisement_header_test.cc", - "ble_advertisement_test.cc", - "ble_packet_test.cc", - "ble_peripheral_test.cc", - ], - deps = [ - ":ble_v2", - "//testing/base/public:gunit_main", - "//absl/time", - "//platform/base", - "//platform/impl/g3", # buildcleaner: keep - "//platform/public:comm", - ], -) diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/advertisement_read_result.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/advertisement_read_result.cc deleted file mode 100644 index aa82f0ed522..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/advertisement_read_result.cc +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/ble_v2/advertisement_read_result.h" - -#include <algorithm> -#include <vector> - -#include "absl/container/flat_hash_set.h" -#include "absl/time/clock.h" -#include "platform/public/mutex_lock.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -const AdvertisementReadResult::Config AdvertisementReadResult::kDefaultConfig{ - .backoff_multiplier = 2.0, - .base_backoff_duration = absl::Seconds(1), - .max_backoff_duration = absl::Minutes(5), -}; - -// Adds a successfully read advertisement for the specified slot to this read -// result. This is fundamentally different from RecordLastReadStatus() because -// we can report a read failure, but still manage to read some advertisements. -void AdvertisementReadResult::AddAdvertisement(std::int32_t slot, - const ByteArray& advertisement) { - MutexLock lock(&mutex_); - - // Blindly remove from the advertisements map to make sure any existing - // key-value pair is destroyed. - advertisements_.emplace(slot, advertisement); -} - -// Determines whether or not an advertisement was successfully read at the -// specified slot. -bool AdvertisementReadResult::HasAdvertisement(std::int32_t slot) const { - MutexLock lock(&mutex_); - - return advertisements_.contains(slot); -} - -// Retrieves all raw advertisements that were successfully read. -std::vector<const ByteArray*> AdvertisementReadResult::GetAdvertisements() - const { - MutexLock lock(&mutex_); - - std::vector<const ByteArray*> all_advertisements; - all_advertisements.reserve(advertisements_.size()); - for (const auto& item : advertisements_) { - all_advertisements.emplace_back(&item.second); - } - - return all_advertisements; -} - -// Determines what stage we're in for retrying a read from an advertisement -// GATT server. -AdvertisementReadResult::RetryStatus -AdvertisementReadResult::EvaluateRetryStatus() const { - MutexLock lock(&mutex_); - - // Check if we have already succeeded reading this advertisement. - if (status_ == Status::kSuccess) { - return RetryStatus::kPreviouslySucceeded; - } - - // Check if we have recently failed to read this advertisement. - if (GetDurationSinceReadLocked() < backoff_duration_) { - return RetryStatus::kTooSoon; - } - - return RetryStatus::kRetry; -} - -// Records the status of the latest read, and updates the next backoff -// duration for subsequent reads. Be sure to also call -// AddAdvertisement() if any advertisements were read. -void AdvertisementReadResult::RecordLastReadStatus(bool is_success) { - MutexLock lock(&mutex_); - - // Update the last read timestamp. - last_read_timestamp_ = SystemClock::ElapsedRealtime(); - - // Update the backoff duration. - if (is_success) { - // Reset the backoff duration now that we had a successful read. - backoff_duration_ = config_.base_backoff_duration; - } else { - // Determine whether or not we were already failing before. If we were, we - // should increase the backoff duration. - if (status_ == Status::kFailure) { - // Use exponential backoff to determine the next backoff duration. This - // simply involves multiplying our current backoff duration by some - // multiplier. - absl::Duration next_backoff_duration = - config_.backoff_multiplier * backoff_duration_; - // Update the backoff duration, making sure not to blow past the - // ceiling. - backoff_duration_ = - std::min(next_backoff_duration, config_.max_backoff_duration); - } else { - // This is our first time failing, so we should only backoff for the - // initial duration. - backoff_duration_ = config_.base_backoff_duration; - } - } - - // Update the internal result. - status_ = is_success ? Status::kSuccess : Status::kFailure; -} - -// Returns how much time has passed since we last tried reading from an -// advertisement GATT server. -absl::Duration AdvertisementReadResult::GetDurationSinceRead() const { - MutexLock lock(&mutex_); - return GetDurationSinceReadLocked(); -} - -absl::Duration AdvertisementReadResult::GetDurationSinceReadLocked() const { - return SystemClock::ElapsedRealtime() - last_read_timestamp_; -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/advertisement_read_result.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/advertisement_read_result.h deleted file mode 100644 index afd8bb848e8..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/advertisement_read_result.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_BLE_V2_ADVERTISEMENT_READ_RESULT_H_ -#define CORE_INTERNAL_MEDIUMS_BLE_V2_ADVERTISEMENT_READ_RESULT_H_ - -#include <cstdint> -#include <vector> - -#include "absl/container/flat_hash_map.h" -#include "absl/container/flat_hash_set.h" -#include "absl/time/clock.h" -#include "platform/base/byte_array.h" -#include "platform/public/mutex.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -// Representation of a GATT advertisement read result. This object helps us -// determine whether or not we need to retry GATT reads. -class AdvertisementReadResult { - public: - // We need a long enough duration such that we always trigger a read - // retry AND we always connect to it without delay. The former case - // helps us initialize an AdvertisementReadResult so that we - // unconditionally try reading on the first sighting. And the latter - // case helps us connect immediately when we initialize a dummy read - // result for fast advertisements (which don't use the GATT server). - - struct Config { - // How much to multiply the backoff duration by with every failure to read - // from the advertisement GATT server. This should never be below 1! - float backoff_multiplier; - // The initial backoff duration when we fail to read from an advertisement - // GATT server. - absl::Duration base_backoff_duration; - // The maximum backoff duration allowed between advertisement GATT server - // reads. - absl::Duration max_backoff_duration; - }; - - static const Config kDefaultConfig; - explicit AdvertisementReadResult(const Config& config = kDefaultConfig) - : config_(config) {} - ~AdvertisementReadResult() = default; - - enum class RetryStatus { - kUnknown = 0, - kRetry = 1, - kPreviouslySucceeded = 2, - kTooSoon = 3, - }; - - void AddAdvertisement(std::int32_t slot, const ByteArray& advertisement) - ABSL_LOCKS_EXCLUDED(mutex_); - bool HasAdvertisement(std::int32_t slot) const ABSL_LOCKS_EXCLUDED(mutex_); - std::vector<const ByteArray*> GetAdvertisements() const - ABSL_LOCKS_EXCLUDED(mutex_); - RetryStatus EvaluateRetryStatus() const ABSL_LOCKS_EXCLUDED(mutex_); - void RecordLastReadStatus(bool is_success) ABSL_LOCKS_EXCLUDED(mutex_); - absl::Duration GetDurationSinceRead() const ABSL_LOCKS_EXCLUDED(mutex_); - - private: - enum class Status { - kUnknown = 0, - kSuccess = 1, - kFailure = 2, - }; - - absl::Duration GetDurationSinceReadLocked() const - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - mutable Mutex mutex_; - - // Maps slot numbers to the GATT advertisement found in that slot. - absl::flat_hash_map<std::int32_t, ByteArray> advertisements_ - ABSL_GUARDED_BY(mutex_); - - Config config_; - absl::Duration backoff_duration_ ABSL_GUARDED_BY(mutex_); - absl::Time last_read_timestamp_ ABSL_GUARDED_BY(mutex_); - Status status_ ABSL_GUARDED_BY(mutex_) = Status::kUnknown; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_BLE_V2_ADVERTISEMENT_READ_RESULT_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/advertisement_read_result_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/advertisement_read_result_test.cc deleted file mode 100644 index 90ce51c9a74..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/advertisement_read_result_test.cc +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/ble_v2/advertisement_read_result.h" - -#include "gtest/gtest.h" -#include "absl/time/clock.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { -namespace { - -constexpr char kAdvertisementBytes[] = "\x0A\x0B\x0C"; - -// Default values may be too big and impractical to wait for in the test. -// For the test platform, we redefine them to some reasonable values. -const absl::Duration kAdvertisementBaseBackoffDuration = absl::Seconds(1); -const absl::Duration kAdvertisementMaxBackoffDuration = absl::Seconds(6); - -const AdvertisementReadResult::Config test_config{ - .backoff_multiplier = - AdvertisementReadResult::kDefaultConfig.backoff_multiplier, - .base_backoff_duration = kAdvertisementBaseBackoffDuration, - .max_backoff_duration = kAdvertisementMaxBackoffDuration, -}; - -TEST(AdvertisementReadResultTest, AdvertisementExists) { - AdvertisementReadResult advertisement_read_result(test_config); - advertisement_read_result.RecordLastReadStatus(/* is_success= */ true); - - std::int32_t slot = 6; - advertisement_read_result.AddAdvertisement(slot, - ByteArray(kAdvertisementBytes)); - - EXPECT_TRUE(advertisement_read_result.HasAdvertisement(slot)); -} - -TEST(AdvertisementReadResultTest, AdvertisementNonExistent) { - AdvertisementReadResult advertisement_read_result(test_config); - advertisement_read_result.RecordLastReadStatus(/* is_success= */ true); - - std::int32_t slot = 6; - - EXPECT_FALSE(advertisement_read_result.HasAdvertisement(slot)); -} - -TEST(AdvertisementReadResultTest, EvaluateRetryStatusInitialized) { - AdvertisementReadResult advertisement_read_result(test_config); - - EXPECT_EQ(advertisement_read_result.EvaluateRetryStatus(), - AdvertisementReadResult::RetryStatus::kRetry); -} - -TEST(AdvertisementReadResultTest, EvaluateRetryStatusSuccess) { - AdvertisementReadResult advertisement_read_result(test_config); - advertisement_read_result.RecordLastReadStatus(/* is_success= */ true); - - EXPECT_EQ(advertisement_read_result.EvaluateRetryStatus(), - AdvertisementReadResult::RetryStatus::kPreviouslySucceeded); -} - -TEST(AdvertisementReadResultTest, EvaluateRetryStatusTooSoon) { - AdvertisementReadResult advertisement_read_result(test_config); - advertisement_read_result.RecordLastReadStatus(/* is_success= */ false); - - // Sleep for some time, but not long enough to warrant a retry. - absl::SleepFor(kAdvertisementBaseBackoffDuration / 2); - - EXPECT_EQ(advertisement_read_result.EvaluateRetryStatus(), - AdvertisementReadResult::RetryStatus::kTooSoon); -} - -TEST(AdvertisementReadResultTest, EvaluateRetryStatusRetry) { - AdvertisementReadResult advertisement_read_result(test_config); - advertisement_read_result.RecordLastReadStatus(/* is_success= */ false); - - // Sleep long enough to warrant a retry. - absl::SleepFor(kAdvertisementBaseBackoffDuration); - - EXPECT_EQ(advertisement_read_result.EvaluateRetryStatus(), - AdvertisementReadResult::RetryStatus::kRetry); -} - -TEST(AdvertisementReadResultTest, ReportStatusExponentialBackoff) { - AdvertisementReadResult advertisement_read_result(test_config); - advertisement_read_result.RecordLastReadStatus(/* is_success= */ false); - - // Record an additional failure so our backoff duration increases. - advertisement_read_result.RecordLastReadStatus(/* is_success= */ false); - - // Sleep for the backoff duration. We shouldn't trigger a retry because the - // backoff should have increased from failing a second time. - absl::SleepFor(kAdvertisementBaseBackoffDuration); - - EXPECT_EQ(advertisement_read_result.EvaluateRetryStatus(), - AdvertisementReadResult::RetryStatus::kTooSoon); -} - -TEST(AdvertisementReadResultTest, ReportStatusExponentialBackoffMax) { - AdvertisementReadResult advertisement_read_result(test_config); - advertisement_read_result.RecordLastReadStatus(/* is_success= */ false); - - // Record an absurd amount of failures so we hit the maximum backoff duration. - for (std::int32_t i = 0; i < 1000; i++) { - advertisement_read_result.RecordLastReadStatus(/* is_success= */ false); - } - - // Sleep for the maximum backoff duration. This should be enough to warrant a - // retry. - absl::SleepFor(kAdvertisementMaxBackoffDuration); - - EXPECT_EQ(advertisement_read_result.EvaluateRetryStatus(), - AdvertisementReadResult::RetryStatus::kRetry); -} - -TEST(AdvertisementReadResultTest, GetDurationSinceRead) { - AdvertisementReadResult advertisement_read_result(test_config); - advertisement_read_result.RecordLastReadStatus(/* is_success= */ true); - - absl::Duration sleepTime = absl::Milliseconds(420); - absl::SleepFor(sleepTime); - - EXPECT_GE(advertisement_read_result.GetDurationSinceRead(), sleepTime); -} - -} // namespace -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement.cc deleted file mode 100644 index f6280611954..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement.cc +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/ble_v2/ble_advertisement.h" - -#include <inttypes.h> - -#include "absl/strings/str_cat.h" -#include "platform/base/base_input_stream.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -BleAdvertisement::BleAdvertisement(Version version, - SocketVersion socket_version, - const ByteArray &service_id_hash, - const ByteArray &data, - const ByteArray &device_token) { - DoInitialize(/*fast_advertisement=*/service_id_hash.Empty(), version, - socket_version, service_id_hash, data, device_token); -} - -void BleAdvertisement::DoInitialize(bool fast_advertisement, Version version, - SocketVersion socket_version, - const ByteArray &service_id_hash, - const ByteArray &data, - const ByteArray &device_token) { - // Check that the given input is valid. - fast_advertisement_ = fast_advertisement; - if (!fast_advertisement_) { - if (service_id_hash.size() != kServiceIdHashLength) return; - } - if (!IsSupportedVersion(version) || - !IsSupportedSocketVersion(socket_version) || - (!device_token.Empty() && device_token.size() != kDeviceTokenLength)) { - return; - } - - int advertisement_Length = ComputeAdvertisementLength( - data.size(), device_token.size(), fast_advertisement_); - int max_advertisement_length = fast_advertisement - ? kMaxFastAdvertisementLength - : kMaxAdvertisementLength; - if (advertisement_Length > max_advertisement_length) { - return; - } - - version_ = version; - socket_version_ = socket_version; - if (!fast_advertisement_) service_id_hash_ = service_id_hash; - data_ = data; - device_token_ = device_token; -} - -BleAdvertisement::BleAdvertisement(const ByteArray &ble_advertisement_bytes) { - if (ble_advertisement_bytes.Empty()) { - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement: null bytes passed in."); - return; - } - - if (ble_advertisement_bytes.size() < kVersionLength) { - NEARBY_LOG( - INFO, - "Cannot deserialize BleAdvertisement: expecting min %d raw bytes to " - "parse the version, got %" PRIu64, - kVersionLength, ble_advertisement_bytes.size()); - return; - } - - ByteArray advertisement_bytes{ble_advertisement_bytes}; - BaseInputStream base_input_stream{advertisement_bytes}; - // The first 1 byte is supposed to be the version, socket version and the fast - // advertisement flag. - auto version_byte = static_cast<char>(base_input_stream.ReadUint8()); - - // Version. - version_ = static_cast<Version>((version_byte & kVersionBitmask) >> 5); - if (!IsSupportedVersion(version_)) { - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement: unsupported Version %u", - version_); - return; - } - - // Socket version. - socket_version_ = - static_cast<SocketVersion>((version_byte & kSocketVersionBitmask) >> 2); - if (!IsSupportedSocketVersion(socket_version_)) { - NEARBY_LOG( - INFO, - "Cannot deserialize BleAdvertisement: unsupported SocketVersion %u", - socket_version_); - version_ = Version::kUndefined; - return; - } - - // Fast advertisement flag. - fast_advertisement_ = - static_cast<bool>((version_byte & kFastAdvertisementFlagBitmask) >> 1); - - // The next 3 bytes are supposed to be the service_id_hash if not fast - // advertisement. - if (!fast_advertisement_) { - service_id_hash_ = base_input_stream.ReadBytes(kServiceIdHashLength); - } - - // Data length. - int expected_data_size = - fast_advertisement_ - ? static_cast<int>( - base_input_stream.ReadBytes(kFastDataSizeLength).data()[0]) - : static_cast<int>(base_input_stream.ReadUint32()); - if (expected_data_size < 0) { - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement: negative data size %d", - expected_data_size); - version_ = Version::kUndefined; - return; - } - - // Data. - // Check that the stated data size is the same as what we received. - data_ = base_input_stream.ReadBytes(expected_data_size); - if (data_.size() != expected_data_size) { - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement: expected data to be %u " - "bytes, got %" PRIu64 " bytes ", - expected_data_size, data_.size()); - version_ = Version::kUndefined; - return; - } - - // Device token. If the number of remaining bytes are valid for device token, - // then read it. - if (base_input_stream.IsAvailable(kDeviceTokenLength)) { - device_token_ = base_input_stream.ReadBytes(kDeviceTokenLength); - } -} - -BleAdvertisement::operator ByteArray() const { - if (!IsValid()) { - return ByteArray{}; - } - - // The first 3 bits are the Version. - char version_byte = (static_cast<char>(version_) << 5) & kVersionBitmask; - // The next 3 bits are the Socket version. 2 bits left are reserved. - version_byte |= - (static_cast<char>(socket_version_) << 2) & kSocketVersionBitmask; - // The next 1 bit is the fast advertisement flag. 1 bit left is reserved. - version_byte |= (static_cast<char>(fast_advertisement_ ? 1 : 0) << 1) & - kFastAdvertisementFlagBitmask; - - // Serialize Data size bytes - ByteArray data_size_bytes{static_cast<size_t>( - fast_advertisement_ ? kFastDataSizeLength : kDataSizeLength)}; - auto *data_size_bytes_write_ptr = data_size_bytes.data(); - SerializeDataSize(fast_advertisement_, data_size_bytes_write_ptr, - data_.size()); - - // clang-format on - if (fast_advertisement_) { - std::string out = - absl::StrCat(std::string(1, version_byte), std::string(data_size_bytes), - std::string(data_), std::string(device_token_)); - return ByteArray{std::move(out)}; - } else { - std::string out = absl::StrCat( - std::string(1, version_byte), std::string(service_id_hash_), - std::string(data_size_bytes), std::string(data_), - std::string(device_token_)); - return ByteArray{std::move(out)}; - } - // clang-format on -} - -bool BleAdvertisement::operator==(const BleAdvertisement &rhs) const { - return this->GetVersion() == rhs.GetVersion() && - this->GetSocketVersion() == rhs.GetSocketVersion() && - this->GetServiceIdHash() == rhs.GetServiceIdHash() && - this->GetData() == rhs.GetData() && - this->GetDeviceToken() == rhs.GetDeviceToken(); -} - -bool BleAdvertisement::operator<(const BleAdvertisement &rhs) const { - if (this->GetVersion() != rhs.GetVersion()) { - return this->GetVersion() < rhs.GetVersion(); - } - if (this->GetSocketVersion() != rhs.GetSocketVersion()) { - return this->GetSocketVersion() < rhs.GetSocketVersion(); - } - if (this->GetServiceIdHash() != rhs.GetServiceIdHash()) { - return this->GetServiceIdHash() < rhs.GetServiceIdHash(); - } - if (this->GetDeviceToken() != rhs.GetDeviceToken()) { - return this->GetDeviceToken() < rhs.GetDeviceToken(); - } - return this->GetData() < rhs.GetData(); -} - -bool BleAdvertisement::IsSupportedVersion(Version version) const { - return version >= Version::kV1 && version <= Version::kV2; -} - -bool BleAdvertisement::IsSupportedSocketVersion( - SocketVersion socket_version) const { - return socket_version >= SocketVersion::kV1 && - socket_version <= SocketVersion::kV2; -} - -void BleAdvertisement::SerializeDataSize(bool fast_advertisement, - char *data_size_bytes_write_ptr, - size_t data_size) const { - // Get a raw representation of the data size bytes in memory. - char *data_size_bytes = reinterpret_cast<char *>(&data_size); - - const int data_size_length = - fast_advertisement ? kFastDataSizeLength : kDataSizeLength; - - // Append these raw bytes to advertisement bytes, keeping in mind that we need - // to convert from Little Endian to Big Endian in the process. - for (int i = 0; i < data_size_length; ++i) { - data_size_bytes_write_ptr[i] = data_size_bytes[data_size_length - i - 1]; - } -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement.h deleted file mode 100644 index 176f4bfd7b0..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_ADVERTISEMENT_H_ -#define CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_ADVERTISEMENT_H_ - -#include <utility> - -#include "platform/base/byte_array.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -// Represents the format of the Mediums BLE Advertisement used in Advertising + -// Discovery. -// -// [VERSION][SOCKET_VERSION][FAST_ADVERTISEMENT_FLAG][1_RESERVED_BIT][SERVICE_ID_HASH][DATA_SIZE][DATA][DEVICE_TOKEN] -// -// For fast advertisement, we remove SERVICE_ID_HASH since we already have one -// copy in Nearby Connections(b/138447288) -// [VERSION][SOCKET_VERSION][FAST_ADVERTISEMENT_FLAG][1_RESERVED_BIT][DATA_SIZE][DATA][DEVICE_TOKEN] -// -// See go/nearby-ble-design for more information. -class BleAdvertisement { - public: - // Versions of the BleAdvertisement. - enum class Version { - kUndefined = 0, - kV1 = 1, - kV2 = 2, - // Version is only allocated 3 bits in the BleAdvertisement, so this can - // never go beyond V7. - }; - - // Versions of the BLESocket. - enum class SocketVersion { - kUndefined = 0, - kV1 = 1, - kV2 = 2, - // SocketVersion is only allocated 3 bits in the BleAdvertisement, so this - // can never go beyond V7. - }; - - static constexpr int kServiceIdHashLength = 3; - static constexpr int kDeviceTokenLength = 2; - - BleAdvertisement() = default; - BleAdvertisement(Version version, SocketVersion socket_version, - const ByteArray &service_id_hash, const ByteArray &data, - const ByteArray &device_token); - explicit BleAdvertisement(const ByteArray &ble_advertisement_bytes); - BleAdvertisement(const BleAdvertisement &) = default; - BleAdvertisement &operator=(const BleAdvertisement &) = default; - BleAdvertisement(BleAdvertisement &&) = default; - BleAdvertisement &operator=(BleAdvertisement &&) = default; - ~BleAdvertisement() = default; - - explicit operator ByteArray() const; - // Operator overloads when comparing BleAdvertisement. - bool operator==(const BleAdvertisement &rhs) const; - bool operator<(const BleAdvertisement &rhs) const; - - bool IsValid() const { return IsSupportedVersion(version_); } - Version GetVersion() const { return version_; } - SocketVersion GetSocketVersion() const { return socket_version_; } - bool IsFastAdvertisement() const { return fast_advertisement_; } - ByteArray GetServiceIdHash() const { return service_id_hash_; } - ByteArray &GetData() & { return data_; } - const ByteArray &GetData() const & { return data_; } - ByteArray &&GetData() && { return std::move(data_); } - const ByteArray &&GetData() const && { return std::move(data_); } - ByteArray GetDeviceToken() const { return device_token_; } - - private: - void DoInitialize(bool fast_advertisement, Version version, - SocketVersion socket_version, - const ByteArray &service_id_hash, const ByteArray &data, - const ByteArray &device_token); - bool IsSupportedVersion(Version version) const; - bool IsSupportedSocketVersion(SocketVersion socket_version) const; - void SerializeDataSize(bool fast_advertisement, - char *data_size_bytes_write_ptr, - size_t data_size) const; - int ComputeAdvertisementLength(int data_length, int total_optional_length, - bool fast_advertisement) const { - // The advertisement length is the minimum length + the length of the data + - // the length of in-use optional fields. - return fast_advertisement ? (kMinFastAdvertisementLegth + data_length + - total_optional_length) - : (kMinAdvertisementLength + data_length + - total_optional_length); - } - - static constexpr int kVersionLength = 1; - static constexpr int kVersionBitmask = 0x0E0; - static constexpr int kSocketVersionBitmask = 0x01C; - static constexpr int kFastAdvertisementFlagBitmask = 0x002; - static constexpr int kDataSizeLength = 4; // Length of one int. - static constexpr int kFastDataSizeLength = 1; // Length of one byte. - static constexpr int kMinAdvertisementLength = - kVersionLength + kServiceIdHashLength + kDataSizeLength; - // The maximum length for a Gatt characteristic value is 512 bytes, so make - // sure the entire advertisement is less than that. The data can take up - // whatever space is remaining after the bytes preceding it. - static constexpr int kMaxAdvertisementLength = 512; - static constexpr int kMinFastAdvertisementLegth = - kVersionLength + kFastDataSizeLength; - // The maximum length for the scan response is 31 bytes. However, with the - // required header that comes before the service data, this leaves the - // advertiser with 27 leftover bytes. - static constexpr int kMaxFastAdvertisementLength = 27; - - Version version_{Version::kUndefined}; - SocketVersion socket_version_{SocketVersion::kUndefined}; - bool fast_advertisement_ = false; - ByteArray service_id_hash_; - ByteArray data_; - ByteArray device_token_; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_ADVERTISEMENT_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement_header.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement_header.cc deleted file mode 100644 index 321924e4f90..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement_header.cc +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/ble_v2/ble_advertisement_header.h" - -#include <inttypes.h> - -#include "absl/strings/str_cat.h" -#include "platform/base/base64_utils.h" -#include "platform/base/base_input_stream.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -BleAdvertisementHeader::BleAdvertisementHeader( - Version version, int num_slots, const ByteArray &service_id_bloom_filter, - const ByteArray &advertisement_hash) { - if (version != Version::kV2 || num_slots <= 0 || - service_id_bloom_filter.size() != kServiceIdBloomFilterLength || - advertisement_hash.size() != kAdvertisementHashLength) { - return; - } - - version_ = version; - num_slots_ = num_slots; - service_id_bloom_filter_ = service_id_bloom_filter; - advertisement_hash_ = advertisement_hash; -} - -BleAdvertisementHeader::BleAdvertisementHeader( - const std::string &ble_advertisement_header_string) { - ByteArray ble_advertisement_header_bytes = - Base64Utils::Decode(ble_advertisement_header_string); - - if (ble_advertisement_header_bytes.Empty()) { - NEARBY_LOG( - ERROR, - "Cannot deserialize BLEAdvertisementHeader: failed Base64 decoding"); - return; - } - - if (ble_advertisement_header_bytes.size() < kMinAdvertisementHeaderLength) { - NEARBY_LOG(ERROR, - "Cannot deserialize BleAdvertisementHeader: expecting min %u " - "raw bytes, got %" PRIu64 " instead", - kMinAdvertisementHeaderLength, - ble_advertisement_header_bytes.size()); - return; - } - - BaseInputStream base_input_stream{ble_advertisement_header_bytes}; - // The first 1 byte is supposed to be the version and number of slots. - auto version_and_pcp_byte = static_cast<char>(base_input_stream.ReadUint8()); - // The upper 3 bits are supposed to be the version. - version_ = - static_cast<Version>((version_and_pcp_byte & kVersionBitmask) >> 5); - if (version_ != Version::kV2) { - NEARBY_LOG( - ERROR, - "Cannot deserialize BleAdvertisementHeader: unsupported Version %d", - version_); - return; - } - // The lower 5 bits are supposed to be the number of slots. - num_slots_ = static_cast<int>(version_and_pcp_byte & kNumSlotsBitmask); - if (num_slots_ <= 0) { - version_ = Version::kUndefined; - return; - } - - // The next 10 bytes are supposed to be the service_id_bloom_filter. - service_id_bloom_filter_ = - base_input_stream.ReadBytes(kServiceIdBloomFilterLength); - - // The next 4 bytes are supposed to be the advertisement_hash. - advertisement_hash_ = base_input_stream.ReadBytes(kAdvertisementHashLength); -} - -BleAdvertisementHeader::operator std::string() const { - if (!IsValid()) { - return ""; - } - - // The first 3 bits are the Version. - char version_and_num_slots_byte = - (static_cast<char>(version_) << 5) & kVersionBitmask; - // The next 5 bits are the number of slots. - version_and_num_slots_byte |= - static_cast<char>(num_slots_) & kNumSlotsBitmask; - - // clang-format off - std::string out = absl::StrCat(std::string(1, version_and_num_slots_byte), - std::string(service_id_bloom_filter_), - std::string(advertisement_hash_)); - // clang-format on - - return Base64Utils::Encode(ByteArray(std::move(out))); -} - -bool BleAdvertisementHeader::operator<( - const BleAdvertisementHeader &rhs) const { - if (this->GetVersion() != rhs.GetVersion()) { - return this->GetVersion() < rhs.GetVersion(); - } - if (this->GetNumSlots() != rhs.GetNumSlots()) { - return this->GetNumSlots() < rhs.GetNumSlots(); - } - if (this->GetServiceIdBloomFilter() != rhs.GetServiceIdBloomFilter()) { - return this->GetServiceIdBloomFilter() < rhs.GetServiceIdBloomFilter(); - } - return this->GetAdvertisementHash() < rhs.GetAdvertisementHash(); -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement_header.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement_header.h deleted file mode 100644 index fbf0d457599..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement_header.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_ADVERTISEMENT_HEADER_H_ -#define CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_ADVERTISEMENT_HEADER_H_ - -#include <string> - -#include "platform/base/byte_array.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -// Represents the format of the Mediums BLE Advertisement Header used in -// Advertising + Discovery. -// -// [VERSION][NUM_SLOTS][SERVICE_ID_BLOOM_FILTER][ADVERTISEMENT_HASH] -// -// See go/nearby-ble-design for more information. -// -// Note. The object constructed by default constructor or the parameterized -// constructor with invalid value(s) is treated as invalid instance. Caller -// should be responsible to call IsValid() to check the instance is invalid in -// advance before continue on. -class BleAdvertisementHeader { - public: - // Versions of the BleAdvertisementHeader. - enum class Version { - kUndefined = 0, - kV1 = 1, - kV2 = 2, - // Version is only allocated 3 bits in the BleAdvertisementHeader, so this - // can never go beyond V7. - // - // V1 is not present because it's an old format used in Nearby Connections - // before this logic was pushed down into Nearby Mediums. V1 put - // everything in the service data, while V2 puts the data inside a GATT - // characteristic so the two are not compatible. - }; - - BleAdvertisementHeader() = default; - BleAdvertisementHeader(Version version, int num_slots, - const ByteArray &service_id_bloom_filter, - const ByteArray &advertisement_hash); - explicit BleAdvertisementHeader( - const std::string &ble_advertisement_header_string); - BleAdvertisementHeader(const BleAdvertisementHeader &) = default; - BleAdvertisementHeader &operator=(const BleAdvertisementHeader &) = default; - BleAdvertisementHeader(BleAdvertisementHeader &&) = default; - BleAdvertisementHeader &operator=(BleAdvertisementHeader &&) = default; - ~BleAdvertisementHeader() = default; - - // Produces an encoded binary string which can be decoded by the explicit - // constructor. The returned string is empty if BleAdvertisementHeader is not - // valid - false on IsValid(). - explicit operator std::string() const; - bool operator<(const BleAdvertisementHeader &rhs) const; - - bool IsValid() const { return version_ == Version::kV2; } - Version GetVersion() const { return version_; } - int GetNumSlots() const { return num_slots_; } - ByteArray GetServiceIdBloomFilter() const { return service_id_bloom_filter_; } - ByteArray GetAdvertisementHash() const { return advertisement_hash_; } - - private: - static constexpr int kServiceIdBloomFilterLength = 10; - static constexpr int kAdvertisementHashLength = 4; - static constexpr int kMinAdvertisementHeaderLength = - 1 + kServiceIdBloomFilterLength + kAdvertisementHashLength; - static constexpr int kVersionBitmask = 0x0E0; - static constexpr int kNumSlotsBitmask = 0x01F; - - Version version_ = Version::kUndefined; - int num_slots_; - ByteArray service_id_bloom_filter_; - ByteArray advertisement_hash_; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_ADVERTISEMENT_HEADER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement_header_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement_header_test.cc deleted file mode 100644 index bfd9bb991aa..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement_header_test.cc +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/ble_v2/ble_advertisement_header.h" - -#include "gtest/gtest.h" -#include "platform/base/base64_utils.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { -namespace { - -constexpr BleAdvertisementHeader::Version kVersion = - BleAdvertisementHeader::Version::kV2; -constexpr int kNumSlots = 2; -constexpr absl::string_view kServiceIDBloomFilter{ - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"}; -constexpr absl::string_view kAdvertisementHash{"\x0a\x0b\x0c\x0d"}; - -TEST(BleAdvertisementHeaderTest, ConstructionWorks) { - ByteArray service_id_bloom_filter{std::string(kServiceIDBloomFilter)}; - ByteArray advertisement_hash{std::string(kAdvertisementHash)}; - - BleAdvertisementHeader ble_advertisement_header{ - kVersion, kNumSlots, service_id_bloom_filter, advertisement_hash}; - - EXPECT_TRUE(ble_advertisement_header.IsValid()); - EXPECT_EQ(kVersion, ble_advertisement_header.GetVersion()); - EXPECT_EQ(kNumSlots, ble_advertisement_header.GetNumSlots()); - EXPECT_EQ(service_id_bloom_filter, - ble_advertisement_header.GetServiceIdBloomFilter()); - EXPECT_EQ(advertisement_hash, - ble_advertisement_header.GetAdvertisementHash()); -} - -TEST(BleAdvertisementHeaderTest, ConstructionFailsWithBadVersion) { - auto bad_version = static_cast<BleAdvertisementHeader::Version>(666); - - ByteArray service_id_bloom_filter{std::string(kServiceIDBloomFilter)}; - ByteArray advertisement_hash{std::string(kAdvertisementHash)}; - - BleAdvertisementHeader ble_advertisement_header{ - bad_version, kNumSlots, service_id_bloom_filter, advertisement_hash}; - - EXPECT_FALSE(ble_advertisement_header.IsValid()); -} - -TEST(BleAdvertisementHeaderTest, ConstructionFailsWitZeroNumSlot) { - int num_slot = 0; - - ByteArray service_id_bloom_filter{std::string(kServiceIDBloomFilter)}; - ByteArray advertisement_hash{std::string(kAdvertisementHash)}; - - BleAdvertisementHeader ble_advertisement_header{ - kVersion, num_slot, service_id_bloom_filter, advertisement_hash}; - - EXPECT_FALSE(ble_advertisement_header.IsValid()); -} - -TEST(BleAdvertisementHeaderTest, - ConstructionFailsWithShortServiceIdBloomFilter) { - char short_service_id_bloom_filter[] = "\x01\x02\x03\x04\x05\x06\x07\x08\x09"; - - ByteArray short_service_id_bloom_filter_bytes{short_service_id_bloom_filter}; - ByteArray advertisement_hash{std::string(kAdvertisementHash)}; - - BleAdvertisementHeader ble_advertisement_header{ - kVersion, kNumSlots, short_service_id_bloom_filter_bytes, - advertisement_hash}; - - EXPECT_FALSE(ble_advertisement_header.IsValid()); -} - -TEST(BleAdvertisementHeaderTest, - ConstructionFailsWithLongServiceIdBloomFilter) { - char long_service_id_bloom_filter[] = - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b"; - - ByteArray service_id_bloom_filter{long_service_id_bloom_filter}; - ByteArray advertisement_hash{std::string(kAdvertisementHash)}; - - BleAdvertisementHeader ble_advertisement_header{ - kVersion, kNumSlots, service_id_bloom_filter, advertisement_hash}; - - EXPECT_FALSE(ble_advertisement_header.IsValid()); -} - -TEST(BleAdvertisementHeaderTest, ConstructionFailsWithShortAdvertisementHash) { - char short_advertisement_hash[] = "\x0a\x0b\x0c"; - - ByteArray service_id_bloom_filter{std::string(kServiceIDBloomFilter)}; - ByteArray advertisement_hash{short_advertisement_hash}; - - BleAdvertisementHeader ble_advertisement_header{ - kVersion, kNumSlots, service_id_bloom_filter, advertisement_hash}; - - EXPECT_FALSE(ble_advertisement_header.IsValid()); -} - -TEST(BleAdvertisementHeaderTest, ConstructionFailsWithLongAdvertisementHash) { - char long_advertisement_hash[] = "\x0a\x0b\x0c\x0d\x0e"; - - ByteArray service_id_bloom_filter{std::string(kServiceIDBloomFilter)}; - ByteArray advertisement_hash{long_advertisement_hash}; - BleAdvertisementHeader ble_advertisement_header{ - kVersion, kNumSlots, service_id_bloom_filter, advertisement_hash}; - - EXPECT_FALSE(ble_advertisement_header.IsValid()); -} - -TEST(BleAdvertisementHeaderTest, ConstructionFromSerializedStringWorks) { - ByteArray service_id_bloom_filter{std::string(kServiceIDBloomFilter)}; - ByteArray advertisement_hash{std::string(kAdvertisementHash)}; - - BleAdvertisementHeader org_ble_advertisement_header{ - kVersion, kNumSlots, service_id_bloom_filter, advertisement_hash}; - auto ble_advertisement_header_string = - std::string(org_ble_advertisement_header); - - BleAdvertisementHeader ble_advertisement_header{ - ble_advertisement_header_string}; - - EXPECT_TRUE(ble_advertisement_header.IsValid()); - EXPECT_EQ(kVersion, ble_advertisement_header.GetVersion()); - EXPECT_EQ(kNumSlots, ble_advertisement_header.GetNumSlots()); - EXPECT_EQ(service_id_bloom_filter, - ble_advertisement_header.GetServiceIdBloomFilter()); - EXPECT_EQ(advertisement_hash, - ble_advertisement_header.GetAdvertisementHash()); -} - -TEST(BleAdvertisementHeaderTest, ConstructionFromExtraBytesWorks) { - ByteArray service_id_bloom_filter{std::string(kServiceIDBloomFilter)}; - ByteArray advertisement_hash{std::string(kAdvertisementHash)}; - - BleAdvertisementHeader ble_advertisement_header{ - kVersion, kNumSlots, service_id_bloom_filter, advertisement_hash}; - auto ble_advertisement_header_string = std::string(ble_advertisement_header); - - // Base64 decode the string, add a character, and then re-encode it. - ByteArray ble_advertisement_header_bytes = - Base64Utils::Decode(ble_advertisement_header_string); - ByteArray long_ble_advertisement_header_bytes{ - ble_advertisement_header_bytes.size() + 1}; - long_ble_advertisement_header_bytes.CopyAt(0, ble_advertisement_header_bytes); - std::string long_ble_advertisement_header_string{ - Base64Utils::Encode(long_ble_advertisement_header_bytes)}; - - BleAdvertisementHeader long_ble_advertisement_header{ - long_ble_advertisement_header_string}; - - EXPECT_TRUE(long_ble_advertisement_header.IsValid()); - EXPECT_EQ(kVersion, long_ble_advertisement_header.GetVersion()); - EXPECT_EQ(kNumSlots, long_ble_advertisement_header.GetNumSlots()); - EXPECT_EQ(service_id_bloom_filter, - long_ble_advertisement_header.GetServiceIdBloomFilter()); - EXPECT_EQ(advertisement_hash, - long_ble_advertisement_header.GetAdvertisementHash()); -} - -TEST(BleAdvertisementHeaderTest, ConstructionFromShortLengthFails) { - ByteArray service_id_bloom_filter{std::string(kServiceIDBloomFilter)}; - ByteArray advertisement_hash{std::string(kAdvertisementHash)}; - - BleAdvertisementHeader ble_advertisement_header{ - kVersion, kNumSlots, service_id_bloom_filter, advertisement_hash}; - auto ble_advertisement_header_string = std::string(ble_advertisement_header); - - // Base64 decode the string, remove a character, and then re-encode it. - ByteArray ble_advertisement_header_bytes = - Base64Utils::Decode(ble_advertisement_header_string); - ByteArray short_ble_advertisement_header_bytes{ - ble_advertisement_header_bytes.size() - 1}; - short_ble_advertisement_header_bytes.CopyAt(0, - ble_advertisement_header_bytes); - std::string short_ble_advertisement_header_string{ - Base64Utils::Encode(short_ble_advertisement_header_bytes)}; - - BleAdvertisementHeader short_ble_advertisement_header{ - short_ble_advertisement_header_string}; - - EXPECT_FALSE(short_ble_advertisement_header.IsValid()); -} - -} // namespace -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement_test.cc deleted file mode 100644 index b91e8d95ca5..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_advertisement_test.cc +++ /dev/null @@ -1,455 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/ble_v2/ble_advertisement.h" - -#include <algorithm> - -#include "gtest/gtest.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { -namespace { - -constexpr BleAdvertisement::Version kVersion = BleAdvertisement::Version::kV2; -constexpr BleAdvertisement::SocketVersion kSocketVersion = - BleAdvertisement::SocketVersion::kV2; -constexpr absl::string_view kServiceIDHashBytes{"\x0a\x0b\x0c"}; -constexpr absl::string_view kData{ - "How much wood can a woodchuck chuck if a wood chuck would chuck wood?"}; -constexpr absl::string_view kFastData{"Fast Advertise"}; -constexpr absl::string_view kDeviceToken{"\x04\x20"}; -// kAdvertisementLength/kFastAdvertisementLength corresponds to the length of a -// specific BleAdvertisement packed with the kData/kFastData given above. Be -// sure to update this if kData/kFastData ever changes. -constexpr size_t kAdvertisementLength = 77; -constexpr size_t kFastAdvertisementLength = 16; -constexpr size_t kLongAdvertisementLength = kAdvertisementLength + 1000; - -TEST(BleAdvertisementTest, ConstructionWorksV1) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement ble_advertisement{BleAdvertisement::Version::kV1, - BleAdvertisement::SocketVersion::kV1, - service_id_hash, data, device_token}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_FALSE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(BleAdvertisement::Version::kV1, ble_advertisement.GetVersion()); - EXPECT_EQ(BleAdvertisement::SocketVersion::kV1, - ble_advertisement.GetSocketVersion()); - EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(data.size(), ble_advertisement.GetData().size()); - EXPECT_EQ(data, ble_advertisement.GetData()); - EXPECT_EQ(device_token, ble_advertisement.GetDeviceToken()); -} - -TEST(BleAdvertisementTest, ConstructionWorksV1ForFastAdvertisement) { - ByteArray fast_data{std::string(kFastData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement ble_advertisement{BleAdvertisement::Version::kV1, - BleAdvertisement::SocketVersion::kV1, - ByteArray{}, fast_data, device_token}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_TRUE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(BleAdvertisement::Version::kV1, ble_advertisement.GetVersion()); - EXPECT_EQ(BleAdvertisement::SocketVersion::kV1, - ble_advertisement.GetSocketVersion()); - EXPECT_EQ(fast_data.size(), ble_advertisement.GetData().size()); - EXPECT_EQ(fast_data, ble_advertisement.GetData()); - EXPECT_EQ(device_token, ble_advertisement.GetDeviceToken()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithBadVersion) { - BleAdvertisement::Version bad_version = - static_cast<BleAdvertisement::Version>(666); - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement ble_advertisement{bad_version, kSocketVersion, - service_id_hash, data, device_token}; - EXPECT_FALSE(ble_advertisement.IsValid()); - - BleAdvertisement fast_ble_advertisement{bad_version, kSocketVersion, - ByteArray{}, data, device_token}; - EXPECT_FALSE(fast_ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithBadSocketVersion) { - BleAdvertisement::SocketVersion bad_socket_version = - static_cast<BleAdvertisement::SocketVersion>(666); - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement ble_advertisement{kVersion, bad_socket_version, - service_id_hash, data, device_token}; - EXPECT_FALSE(ble_advertisement.IsValid()); - - BleAdvertisement fast_ble_advertisement{kVersion, bad_socket_version, - ByteArray{}, data, device_token}; - EXPECT_FALSE(fast_ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithShortServiceIdHash) { - char short_service_id_hash_bytes[] = "\x0a\x0b"; - - ByteArray bad_service_id_hash{short_service_id_hash_bytes}; - ByteArray data{std::string(kData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement ble_advertisement{kVersion, kSocketVersion, - bad_service_id_hash, data, device_token}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithLongServiceIdHash) { - char long_service_id_hash_bytes[] = "\x0a\x0b\x0c\x0d"; - - ByteArray bad_service_id_hash{long_service_id_hash_bytes}; - ByteArray data{std::string(kData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement ble_advertisement{kVersion, kSocketVersion, - bad_service_id_hash, data, device_token}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithLongData) { - // BleAdvertisement shouldn't be able to support data with the max GATT - // attribute length because it needs some room for the preceding fields. - char long_data[512]{}; - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray bad_data{long_data, 512}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement ble_advertisement{kVersion, kSocketVersion, service_id_hash, - bad_data, device_token}; - EXPECT_FALSE(ble_advertisement.IsValid()); - - BleAdvertisement fast_ble_advertisement{kVersion, kSocketVersion, ByteArray{}, - bad_data, device_token}; - EXPECT_FALSE(fast_ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionWorksWithEmptyDeviceToken) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - - BleAdvertisement ble_advertisement{kVersion, kSocketVersion, service_id_hash, - data, ByteArray{}}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_FALSE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); - EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(data.size(), ble_advertisement.GetData().size()); - EXPECT_EQ(data, ble_advertisement.GetData()); - EXPECT_TRUE(ble_advertisement.GetDeviceToken().Empty()); -} - -TEST(BleAdvertisementTest, - ConstructionWorksWithEmptyDeviceTokenForFastAdvertisement) { - ByteArray fast_data{std::string(kFastData)}; - - BleAdvertisement ble_advertisement{kVersion, kSocketVersion, ByteArray{}, - fast_data, ByteArray{}}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_TRUE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); - EXPECT_EQ(fast_data.size(), ble_advertisement.GetData().size()); - EXPECT_EQ(fast_data, ble_advertisement.GetData()); - EXPECT_TRUE(ble_advertisement.GetDeviceToken().Empty()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithWrongSizeofDeviceToken) { - char wrong_device_token_bytes_1[] = "\x04\x2\x10"; // over 2 bytes - char wrong_device_token_bytes_2[] = "\x04"; // 1 byte - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - ByteArray bad_device_token_1{wrong_device_token_bytes_1}; - ByteArray bad_device_token_2{wrong_device_token_bytes_2}; - - BleAdvertisement ble_advertisement_1{ - kVersion, kSocketVersion, service_id_hash, data, bad_device_token_1}; - EXPECT_FALSE(ble_advertisement_1.IsValid()); - - BleAdvertisement ble_advertisement_2{ - kVersion, kSocketVersion, service_id_hash, data, bad_device_token_2}; - EXPECT_FALSE(ble_advertisement_2.IsValid()); - - BleAdvertisement fast_ble_advertisement_1{ - kVersion, kSocketVersion, ByteArray{}, data, bad_device_token_1}; - EXPECT_FALSE(fast_ble_advertisement_1.IsValid()); - - BleAdvertisement fast_ble_advertisement_2{ - kVersion, kSocketVersion, ByteArray{}, data, bad_device_token_2}; - EXPECT_FALSE(fast_ble_advertisement_2.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFromSerializedBytesWorks) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, - service_id_hash, data, device_token}; - - ByteArray ble_advertisement_bytes{org_ble_advertisement}; - BleAdvertisement ble_advertisement{ble_advertisement_bytes}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_FALSE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); - EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(data.size(), ble_advertisement.GetData().size()); - EXPECT_EQ(data, ble_advertisement.GetData()); - EXPECT_EQ(device_token, ble_advertisement.GetDeviceToken()); -} - -TEST(BleAdvertisementTest, - ConstructionFromSerializedBytesWorksForAdvertisement) { - ByteArray fast_data{std::string(kFastData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, ByteArray{}, - fast_data, device_token}; - - ByteArray ble_advertisement_bytes{org_ble_advertisement}; - BleAdvertisement ble_advertisement{ble_advertisement_bytes}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_TRUE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); - EXPECT_EQ(fast_data.size(), ble_advertisement.GetData().size()); - EXPECT_EQ(fast_data, ble_advertisement.GetData()); - EXPECT_EQ(device_token, ble_advertisement.GetDeviceToken()); -} - -TEST(BleAdvertisementTest, ConstructionFromSerializedBytesWithEmptyDataWorks) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement org_ble_advertisement{ - kVersion, kSocketVersion, service_id_hash, ByteArray(), device_token}; - ByteArray ble_advertisement_bytes{org_ble_advertisement}; - BleAdvertisement ble_advertisement{ble_advertisement_bytes}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_FALSE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); - EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); - EXPECT_TRUE(ble_advertisement.GetData().Empty()); - EXPECT_EQ(device_token, ble_advertisement.GetDeviceToken()); -} - -TEST(BleAdvertisementTest, - ConstructionFromSerializedBytesWithEmptyDataWorksForFastAdvertisement) { - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, ByteArray{}, - ByteArray(), device_token}; - ByteArray ble_advertisement_bytes{org_ble_advertisement}; - BleAdvertisement ble_advertisement{ble_advertisement_bytes}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_TRUE(ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); - EXPECT_TRUE(ble_advertisement.GetData().Empty()); - EXPECT_EQ(device_token, ble_advertisement.GetDeviceToken()); -} - -TEST(BleAdvertisementTest, ConstructionFromExtraSerializedBytesWorks) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, - service_id_hash, data, device_token}; - ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; - - // Copy the bytes into a new array with extra bytes. We must explicitly - // define how long our array is because we can't use variable length arrays. - char raw_ble_advertisement_bytes[kLongAdvertisementLength]{}; - memcpy(raw_ble_advertisement_bytes, org_ble_advertisement_bytes.data(), - std::min(sizeof(raw_ble_advertisement_bytes), - org_ble_advertisement_bytes.size())); - - // Re-parse the Ble advertisement using our extra long advertisement bytes. - ByteArray long_ble_advertisement_bytes{raw_ble_advertisement_bytes, - kLongAdvertisementLength}; - BleAdvertisement long_ble_advertisement{long_ble_advertisement_bytes}; - - EXPECT_TRUE(long_ble_advertisement.IsValid()); - EXPECT_FALSE(long_ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, long_ble_advertisement.GetVersion()); - EXPECT_EQ(kSocketVersion, long_ble_advertisement.GetSocketVersion()); - EXPECT_EQ(service_id_hash, long_ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(data.size(), long_ble_advertisement.GetData().size()); - EXPECT_EQ(data, long_ble_advertisement.GetData()); - EXPECT_EQ(device_token, long_ble_advertisement.GetDeviceToken()); -} - -TEST(BleAdvertisementTest, - ConstructionFromExtraSerializedBytesWorksForFastAdvertisement) { - ByteArray fast_data{std::string(kFastData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, ByteArray{}, - fast_data, device_token}; - ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; - - // Copy the bytes into a new array with extra bytes. We must explicitly - // define how long our array is because we can't use variable length arrays. - char raw_ble_advertisement_bytes[kLongAdvertisementLength]{}; - memcpy(raw_ble_advertisement_bytes, org_ble_advertisement_bytes.data(), - std::min(sizeof(raw_ble_advertisement_bytes), - org_ble_advertisement_bytes.size())); - - // Re-parse the Ble advertisement using our extra long advertisement bytes. - ByteArray long_ble_advertisement_bytes{raw_ble_advertisement_bytes, - kLongAdvertisementLength}; - BleAdvertisement long_ble_advertisement{long_ble_advertisement_bytes}; - - EXPECT_TRUE(long_ble_advertisement.IsValid()); - EXPECT_TRUE(long_ble_advertisement.IsFastAdvertisement()); - EXPECT_EQ(kVersion, long_ble_advertisement.GetVersion()); - EXPECT_EQ(kSocketVersion, long_ble_advertisement.GetSocketVersion()); - EXPECT_EQ(fast_data.size(), long_ble_advertisement.GetData().size()); - EXPECT_EQ(fast_data, long_ble_advertisement.GetData()); - EXPECT_EQ(device_token, long_ble_advertisement.GetDeviceToken()); -} - -TEST(BleAdvertisementTest, ConstructionFromNullBytesFails) { - BleAdvertisement ble_advertisement{ByteArray{}}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFromShortLengthSerializedBytesFails) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, - service_id_hash, data, device_token}; - ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; - - // Cut off the advertisement so that it's too short. - ByteArray short_ble_advertisement_bytes{org_ble_advertisement_bytes.data(), - 7}; - BleAdvertisement short_ble_advertisement{short_ble_advertisement_bytes}; - - EXPECT_FALSE(short_ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, - ConstructionFromShortLengthSerializedBytesFailsForFastAdvertisement) { - ByteArray fast_data{std::string(kFastData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, ByteArray{}, - fast_data, device_token}; - ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; - - // Cut off the advertisement so that it's too short. - ByteArray short_ble_advertisement_bytes{org_ble_advertisement_bytes.data(), - 2}; - BleAdvertisement short_ble_advertisement{short_ble_advertisement_bytes}; - - EXPECT_FALSE(short_ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, - ConstructionFromSerializedBytesWithInvalidDataLengthFails) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, - service_id_hash, data, device_token}; - ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; - - // Corrupt the DATA_SIZE bits. Start by making a raw copy of the Ble - // advertisement bytes so we can modify it. We must explicitly define how - // long our array is because we can't use variable length arrays. - char raw_ble_advertisement_bytes[kAdvertisementLength]; - memcpy(raw_ble_advertisement_bytes, org_ble_advertisement_bytes.data(), - kAdvertisementLength); - - // The data size field lives in indices 4-7. Corrupt it. - memset(raw_ble_advertisement_bytes + 4, 0xFF, 4); - - // Try to parse the Ble advertisement using our corrupted advertisement bytes. - ByteArray corrupted_ble_advertisement_bytes{raw_ble_advertisement_bytes, - kAdvertisementLength}; - BleAdvertisement corrupted_ble_advertisement{ - corrupted_ble_advertisement_bytes}; - - EXPECT_FALSE(corrupted_ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, - ConstructionFromSerializedBytesWithInvalidDataLengthFails2) { - ByteArray fast_data{std::string(kFastData)}; - ByteArray device_token{std::string(kDeviceToken)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, ByteArray{}, - fast_data, device_token}; - ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; - - // Corrupt the DATA_SIZE bits. Start by making a raw copy of the Ble - // advertisement bytes so we can modify it. We must explicitly define how - // long our array is because we can't use variable length arrays. - char raw_ble_advertisement_bytes[kFastAdvertisementLength]; - memcpy(raw_ble_advertisement_bytes, org_ble_advertisement_bytes.data(), - kFastAdvertisementLength); - - // The data size field lives in index 1. Corrupt it. - memset(raw_ble_advertisement_bytes + 1, 0xFF, 1); - - // Try to parse the Ble advertisement using our corrupted advertisement bytes. - ByteArray corrupted_ble_advertisement_bytes{raw_ble_advertisement_bytes, - kFastAdvertisementLength}; - BleAdvertisement corrupted_ble_advertisement{ - corrupted_ble_advertisement_bytes}; - - EXPECT_FALSE(corrupted_ble_advertisement.IsValid()); -} - -} // namespace -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_packet.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_packet.cc deleted file mode 100644 index 17ab10e3472..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_packet.cc +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/ble_v2/ble_packet.h" - -#include "absl/strings/str_cat.h" -#include "platform/base/base_input_stream.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -BlePacket::BlePacket(const ByteArray& service_id_hash, const ByteArray& data) { - if (service_id_hash.size() != kServiceIdHashLength || - data.size() > kMaxDataSize) { - return; - } - service_id_hash_ = service_id_hash; - data_ = data; -} - -BlePacket::BlePacket(const ByteArray& ble_packet_bytes) { - if (ble_packet_bytes.Empty()) { - NEARBY_LOG(ERROR, "Cannot deserialize BlePacket: null bytes passed in"); - return; - } - - if (ble_packet_bytes.size() < kServiceIdHashLength) { - NEARBY_LOG( - INFO, - "Cannot deserialize BlePacket: expecting min %u raw bytes, got %zu", - kServiceIdHashLength, ble_packet_bytes.size()); - return; - } - - ByteArray packet_bytes{ble_packet_bytes}; - BaseInputStream base_input_stream{packet_bytes}; - // The first 3 bytes are supposed to be the service_id_hash. - service_id_hash_ = base_input_stream.ReadBytes(kServiceIdHashLength); - - // The rest bytes are supposed to be the data. - data_ = base_input_stream.ReadBytes(ble_packet_bytes.size() - - kServiceIdHashLength); -} - -BlePacket::operator ByteArray() const { - if (!IsValid()) { - return ByteArray(); - } - - std::string out = - absl::StrCat(std::string(service_id_hash_), std::string(data_)); - - return ByteArray(std::move(out)); -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_packet.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_packet.h deleted file mode 100644 index b559d4adda3..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_packet.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_PACKET_H_ -#define CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_PACKET_H_ - -#include <limits> - -#include "platform/base/byte_array.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -// Represents the format of data sent over Ble sockets. -// -// [SERVICE_ID_HASH][DATA] -// -// See go/nearby-ble-design for more information. -class BlePacket { - public: - static const std::uint32_t kServiceIdHashLength = 3; - - BlePacket() = default; - BlePacket(const ByteArray& service_id_hash, const ByteArray& data); - explicit BlePacket(const ByteArray& ble_packet_byte); - BlePacket(const BlePacket&) = default; - BlePacket& operator=(const BlePacket&) = default; - BlePacket(BlePacket&&) = default; - BlePacket& operator=(BlePacket&&) = default; - ~BlePacket() = default; - - explicit operator ByteArray() const; - - bool IsValid() const { return !service_id_hash_.Empty(); } - ByteArray GetServiceIdHash() const { return service_id_hash_; } - ByteArray GetData() const { return data_; } - - private: - static const std::uint32_t kMaxDataSize = - std::numeric_limits<int32_t>::max() - kServiceIdHashLength; - - ByteArray service_id_hash_; - ByteArray data_; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_PACKET_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_packet_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_packet_test.cc deleted file mode 100644 index df52c3d6743..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_packet_test.cc +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/ble_v2/ble_packet.h" - -#include "gtest/gtest.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -constexpr absl::string_view kServiceIDHash{"\x0a\x0b\x0c"}; -constexpr absl::string_view kData{"\x01\x02\x03\x04\x05"}; - -TEST(BlePacketTest, ConstructionWorks) { - ByteArray service_id_hash{std::string(kServiceIDHash)}; - ByteArray data{std::string(kData)}; - - BlePacket ble_packet{service_id_hash, data}; - - EXPECT_TRUE(ble_packet.IsValid()); - EXPECT_EQ(service_id_hash, ble_packet.GetServiceIdHash()); - EXPECT_EQ(data, ble_packet.GetData()); -} - -TEST(BlePacketTest, ConstructionWorksWithEmptyData) { - char empty_data[] = ""; - - ByteArray service_id_hash{std::string(kServiceIDHash)}; - ByteArray data{empty_data}; - - BlePacket ble_packet{service_id_hash, data}; - - EXPECT_TRUE(ble_packet.IsValid()); - EXPECT_EQ(service_id_hash, ble_packet.GetServiceIdHash()); - EXPECT_EQ(data, ble_packet.GetData()); -} - -TEST(BlePacketTest, ConstructionFailsWithShortServiceIdHash) { - char short_service_id_hash[] = "\x0a\x0b"; - - ByteArray service_id_hash{short_service_id_hash}; - ByteArray data{std::string(kData)}; - - BlePacket ble_packet(service_id_hash, data); - - EXPECT_FALSE(ble_packet.IsValid()); -} - -TEST(BlePacketTest, ConstructionFailsWithLongServiceIdHash) { - char long_service_id_hash[] = "\x0a\x0b\x0c\x0d"; - - ByteArray service_id_hash{long_service_id_hash}; - ByteArray data{std::string(kData)}; - - BlePacket ble_packet{service_id_hash, data}; - - EXPECT_FALSE(ble_packet.IsValid()); -} - -TEST(BlePacketTest, ConstructionFromSerializedBytesWorks) { - ByteArray service_id_hash{std::string(kServiceIDHash)}; - ByteArray data{std::string(kData)}; - - BlePacket org_ble_packet{service_id_hash, data}; - ByteArray ble_packet_bytes{org_ble_packet}; - - BlePacket ble_packet{ble_packet_bytes}; - - EXPECT_TRUE(ble_packet.IsValid()); - EXPECT_EQ(service_id_hash, ble_packet.GetServiceIdHash()); - EXPECT_EQ(data, ble_packet.GetData()); -} - -TEST(BlePacketTest, ConstructionFromNullBytesFails) { - BlePacket ble_packet{ByteArray{}}; - - EXPECT_FALSE(ble_packet.IsValid()); -} - -TEST(BlePacketTest, ConstructionFromShortLengthDataFails) { - ByteArray service_id_hash{std::string(kServiceIDHash)}; - ByteArray data{std::string(kData)}; - - BlePacket org_ble_packet{service_id_hash, data}; - ByteArray org_ble_packet_bytes{org_ble_packet}; - - // Cut off the packet so that it's too short - ByteArray short_ble_packet_bytes{ByteArray{org_ble_packet_bytes.data(), 2}}; - - BlePacket short_ble_packet{short_ble_packet_bytes}; - - EXPECT_FALSE(short_ble_packet.IsValid()); -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_peripheral.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_peripheral.h deleted file mode 100644 index e3b51a41466..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_peripheral.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_PERIPHERAL_H_ -#define CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_PERIPHERAL_H_ - -#include "platform/base/byte_array.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -class BlePeripheral { - public: - BlePeripheral() = default; - explicit BlePeripheral(const ByteArray& id) : id_(id) {} - BlePeripheral(const BlePeripheral&) = default; - BlePeripheral& operator=(const BlePeripheral&) = default; - BlePeripheral(BlePeripheral&&) = default; - BlePeripheral& operator=(BlePeripheral&&) = default; - ~BlePeripheral() = default; - - bool IsValid() const { return !id_.Empty(); } - ByteArray GetId() const { return id_; } - - private: - // A unique identifier for this peripheral. It can be the BLE advertisement it - // was found on, or even simply the BLE MAC address. - ByteArray id_; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_PERIPHERAL_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_peripheral_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_peripheral_test.cc deleted file mode 100644 index c0a4ecb0899..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/ble_peripheral_test.cc +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/ble_v2/ble_peripheral.h" - -#include "gtest/gtest.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { -namespace { - -constexpr absl::string_view kId{"AB12"}; - -TEST(BlePeripheralTest, ConstructionWorks) { - ByteArray id{std::string(kId)}; - - BlePeripheral ble_peripheral{id}; - - EXPECT_TRUE(ble_peripheral.IsValid()); - EXPECT_EQ(id, ble_peripheral.GetId()); -} - -TEST(BlePeripheralTest, ConstructionEmptyFails) { - BlePeripheral ble_peripheral; - - EXPECT_FALSE(ble_peripheral.IsValid()); - EXPECT_TRUE(ble_peripheral.GetId().Empty()); -} - -} // namespace -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/discovered_peripheral_callback.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/discovered_peripheral_callback.h deleted file mode 100644 index 8aacfed4d2e..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble_v2/discovered_peripheral_callback.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_BLE_V2_DISCOVERED_PERIPHERAL_CALLBACK_H_ -#define CORE_INTERNAL_MEDIUMS_BLE_V2_DISCOVERED_PERIPHERAL_CALLBACK_H_ - -#include "core/internal/mediums/ble_v2/ble_peripheral.h" -#include "core/listeners.h" -#include "platform/base/byte_array.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -/** Callback that is invoked when a {@link BlePeripheral} is discovered. */ -struct DiscoveredPeripheralCallback { - std::function<void(BlePeripheral& peripheral, const std::string& service_id, - const ByteArray& advertisement_byts, - bool fast_advertisement)> - peripheral_discovered_cb = - DefaultCallback<BlePeripheral&, const std::string&, const ByteArray&, - bool>(); - std::function<void(BlePeripheral& peripheral, const std::string& service_id)> - peripheral_lost_cb = - DefaultCallback<BlePeripheral&, const std::string&>(); -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_BLE_V2_DISCOVERED_PERIPHERAL_CALLBACK_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bloom_filter.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/bloom_filter.cc deleted file mode 100644 index 20a2370bf0a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bloom_filter.cc +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/bloom_filter.h" - -#include "absl/numeric/int128.h" -#include "absl/strings/numbers.h" -#include "smhasher/src/MurmurHash3.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -BloomFilterBase::BloomFilterBase(const ByteArray& bytes, BitSet* bit_set) - : bits_(bit_set) { - const char* bytes_read_ptr = bytes.data(); - for (size_t byte_index = 0; byte_index < bytes.size(); byte_index++) { - for (size_t bit_index = 0; bit_index < 8; bit_index++) { - bits_->Set((byte_index * 8) + bit_index, - (*bytes_read_ptr >> bit_index) & 0x01); - } - bytes_read_ptr++; - } -} - -BloomFilterBase::operator ByteArray() const { - // Gets a binary string representation of the bitset where the leftmost - // character corresponds to bitset position (total size) - 1. - // - // If the bitset's internal representation is: - // [position 0] 0 0 1 1 0 0 0 1 0 1 0 1 [position 11] - // The string representation will be outputted like this: - // "1 0 1 0 1 0 0 0 1 1 0 0" - std::string bitset_binary_string = bits_->ToString(); - - ByteArray result_bytes(GetMinBytesForBits()); - char* result_bytes_write_ptr = result_bytes.data(); - // We go through the string backwards because the rightmost character - // corresponds to position 0 in the bitset. - for (size_t i = bits_->Size(); i > 0; i -= 8) { - std::string byte_binary_string = bitset_binary_string.substr(i - 8, 8); - std::uint32_t byte_value; - absl::numbers_internal::safe_strtou32_base(byte_binary_string, &byte_value, - /* base= */ 2); - *result_bytes_write_ptr = static_cast<char>(byte_value & 0x000000FF); - result_bytes_write_ptr++; - } - return result_bytes; -} - -void BloomFilterBase::Add(const std::string& s) { - std::vector<std::int32_t> hashes = GetHashes(s); - for (int32_t hash : hashes) { - size_t position = static_cast<size_t>(hash) % bits_->Size(); - bits_->Set(position, true); - } -} - -bool BloomFilterBase::PossiblyContains(const std::string& s) { - std::vector<std::int32_t> hashes = GetHashes(s); - for (int32_t hash : hashes) { - size_t position = static_cast<size_t>(hash) % bits_->Size(); - if (!bits_->Test(position)) { - return false; - } - } - return true; -} - -std::vector<std::int32_t> BloomFilterBase::GetHashes(const std::string& s) { - std::vector<std::int32_t> hashes(kHasherNumberOfRepetitions, 0); - - absl::uint128 hash128; - MurmurHash3_x64_128(s.data(), s.size(), 0, &hash128); - std::uint64_t hash64 = - absl::Uint128Low64(hash128); // the lower 64 bits of the 128-bit hash - std::int32_t hash1 = static_cast<std::int32_t>( - hash64 & 0x00000000FFFFFFFF); // the lower 32 bits of the 64-bit hash - std::int32_t hash2 = static_cast<std::int32_t>( - (hash64 >> 32) & 0x0FFFFFFFF); // the upper 32 bits of the 64-bit hash - for (size_t i = 1; i <= kHasherNumberOfRepetitions; i++) { - std::int32_t combinedHash = static_cast<std::int32_t>(hash1 + (i * hash2)); - // Flip all the bits if it's negative (guaranteed positive number) - if (combinedHash < 0) combinedHash = ~combinedHash; - hashes[i - 1] = combinedHash; - } - return hashes; -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bloom_filter.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/bloom_filter.h deleted file mode 100644 index 3d3f45c9d36..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bloom_filter.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_BLOOM_FILTER_H_ -#define CORE_INTERNAL_MEDIUMS_BLOOM_FILTER_H_ - -#include <bitset> -#include <vector> - -#include "platform/base/byte_array.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -/** - * A bloom filter that gives access to the underlying BitSet. The implementation - * is copied from our Java version of Bloom filter, which in turn copies from - * Guava's BloomFilter. - * - * BloomFilter is templatized on the size of the byte array and not the size of - * the bit set to ensure the bit set's length is a multiple of 8 (and can - * neatly be returned as a ByteArray). - */ -class BloomFilterBase { - public: - explicit operator ByteArray() const; - - void Add(const std::string& s); - bool PossiblyContains(const std::string& s); - - protected: - class BitSet { - public: - virtual ~BitSet() = default; - virtual std::string ToString() const = 0; - virtual void Set(size_t pos, bool value) = 0; - virtual bool Test(size_t pos) const = 0; - virtual size_t Size() const = 0; - }; - - BloomFilterBase(const ByteArray& bytes, BitSet* bit_set); - virtual ~BloomFilterBase() = default; - - constexpr static int kHasherNumberOfRepetitions = 5; - std::vector<std::int32_t> GetHashes(const std::string& s); - - private: - int GetMinBytesForBits() const { return (bits_->Size() + 7) >> 3; } - - BitSet* bits_; -}; - -template <size_t CapacityInBytes> -class BloomFilter final : public BloomFilterBase { - public: - BloomFilter() : BloomFilterBase(ByteArray{}, &bits_) {} - explicit BloomFilter(const ByteArray& bytes) - : BloomFilterBase(bytes, &bits_) {} - BloomFilter(const BloomFilter&) = default; - BloomFilter& operator=(const BloomFilter&) = default; - BloomFilter(BloomFilter&& other) : BloomFilterBase(ByteArray{}, &bits_) { - *this = std::move(other); - } - BloomFilter& operator=(BloomFilter&& other) { - std::swap((*this).bits_, other.bits_); - return *this; - } - ~BloomFilter() override = default; - - private: - class BitSetImpl final : public BitSet { - public: - std::string ToString() const override { return bits_.to_string(); } - void Set(size_t pos, bool value) override { bits_.set(pos, value); } - bool Test(size_t pos) const override { return bits_.test(pos); } - size_t Size() const override { return bits_.size(); } - - private: - std::bitset<CapacityInBytes * 8> bits_; - } bits_; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_BLOOM_FILTER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bloom_filter_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/bloom_filter_test.cc deleted file mode 100644 index 70e846a69dc..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bloom_filter_test.cc +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/bloom_filter.h" - -#include <algorithm> - -#include "gtest/gtest.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { -namespace { - -constexpr size_t kByteArrayLength = 100; - -TEST(BloomFilterTest, EmptyFilterReturnsEmptyArray) { - BloomFilter<kByteArrayLength> bloom_filter; - - ByteArray bloom_filter_bytes(bloom_filter); - std::string empty_string(kByteArrayLength, '\0'); - - EXPECT_EQ(empty_string, std::string(bloom_filter_bytes)); -} - -TEST(BloomFilterTest, EmptyFilterNeverContains) { - BloomFilter<kByteArrayLength> bloom_filter; - - EXPECT_FALSE(bloom_filter.PossiblyContains("ELEMENT_1")); - EXPECT_FALSE(bloom_filter.PossiblyContains("ELEMENT_2")); - EXPECT_FALSE(bloom_filter.PossiblyContains("ELEMENT_3")); -} - -TEST(BloomFilterTest, AddSuccess) { - BloomFilter<kByteArrayLength> bloom_filter; - - EXPECT_FALSE(bloom_filter.PossiblyContains("ELEMENT_1")); - - bloom_filter.Add("ELEMENT_1"); - - EXPECT_TRUE(bloom_filter.PossiblyContains("ELEMENT_1")); -} - -TEST(BloomFilterTest, AddOnlyGivenArg) { - BloomFilter<kByteArrayLength> bloom_filter; - - bloom_filter.Add("ELEMENT_1"); - - EXPECT_TRUE(bloom_filter.PossiblyContains("ELEMENT_1")); - EXPECT_FALSE(bloom_filter.PossiblyContains("ELEMENT_2")); - EXPECT_FALSE(bloom_filter.PossiblyContains("ELEMENT_3")); -} - -TEST(BloomFilterTest, AddMultipleArgs) { - BloomFilter<kByteArrayLength> bloom_filter; - - bloom_filter.Add("ELEMENT_1"); - bloom_filter.Add("ELEMENT_2"); - - EXPECT_TRUE(bloom_filter.PossiblyContains("ELEMENT_1")); - EXPECT_TRUE(bloom_filter.PossiblyContains("ELEMENT_2")); - EXPECT_FALSE(bloom_filter.PossiblyContains("ELEMENT_3")); -} - -TEST(BloomFilterTest, AddMultipleArgsReturnsNonemptyArray) { - BloomFilter<10> bloom_filter; - - bloom_filter.Add("ELEMENT_1"); - bloom_filter.Add("ELEMENT_2"); - bloom_filter.Add("ELEMENT_3"); - - ByteArray bloom_filter_bytes(bloom_filter); - std::string empty_string(kByteArrayLength, '\0'); - - EXPECT_NE(std::string(bloom_filter_bytes), empty_string); -} - -TEST(BloomFilterTest, CopyConstructorAndAssignmentSuccess) { - BloomFilter<kByteArrayLength> bloom_filter; - - EXPECT_FALSE(bloom_filter.PossiblyContains("ELEMENT_1")); - - bloom_filter.Add("ELEMENT_1"); - - BloomFilter<kByteArrayLength> bloom_filter_copy_1{bloom_filter}; - BloomFilter<kByteArrayLength> bloom_filter_copy_2 = bloom_filter; - - EXPECT_TRUE(bloom_filter.PossiblyContains("ELEMENT_1")); - EXPECT_TRUE(bloom_filter_copy_1.PossiblyContains("ELEMENT_1")); - EXPECT_TRUE(bloom_filter_copy_2.PossiblyContains("ELEMENT_1")); -} - -TEST(BloomFilterTest, MoveConstructorSuccess) { - BloomFilter<kByteArrayLength> bloom_filter; - - bloom_filter.Add("ELEMENT_1"); - - BloomFilter<kByteArrayLength> bloom_filter_move{std::move(bloom_filter)}; - - EXPECT_TRUE(bloom_filter_move.PossiblyContains("ELEMENT_1")); -} - -TEST(BloomFilterTest, MoveAssignmentSuccess) { - BloomFilter<kByteArrayLength> bloom_filter; - - bloom_filter.Add("ELEMENT_1"); - - BloomFilter<kByteArrayLength> bloom_filter_move = std::move(bloom_filter); - - EXPECT_TRUE(bloom_filter_move.PossiblyContains("ELEMENT_1")); -} - -/** - * This test was added because of a bug where the BloomFilter doesn't utilize - * all bits given. Functionally, the filter still works, but we just have a much - * higher false positive rate. The bug was caused by confusing bit length and - * byte length, which made our BloomFilter only set bits on the first byteLength - * (bitLength / 8) bits rather than the whole bitLength bits. - * - * <p>Here, we're verifying that the bits set are somewhat scattered. So instead - * of something like [ 0, 1, 1, 0, 0, 0, 0, ..., 0 ], we should be getting - * something like [ 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, ..., 1, 0]. - */ -TEST(BloomFilterTest, RandomnessNoEndBias) { - BloomFilter<kByteArrayLength> bloom_filter; - - // Add one element to our BloomFilter. - bloom_filter.Add("ELEMENT_1"); - - std::int32_t non_zero_count = 0; - std::int32_t longest_zero_streak = 0; - std::int32_t current_zero_streak = 0; - - // Record the amount of non-zero bytes and the longest streak of zero bytes in - // the resulting BloomFilter. This is an approximation of reasonable - // distribution since we're recording by bytes instead of bits. - ByteArray bloom_filter_bytes(bloom_filter); - const char* bloom_filter_bytes_read_ptr = bloom_filter_bytes.data(); - for (int i = 0; i < bloom_filter_bytes.size(); i++) { - if (*bloom_filter_bytes_read_ptr == '\0') { - current_zero_streak++; - } else { - // Increment the number of non-zero bytes we've seen, update the longest - // zero streak, and then reset the current zero streak. - non_zero_count++; - longest_zero_streak = std::max(longest_zero_streak, current_zero_streak); - current_zero_streak = 0; - } - bloom_filter_bytes_read_ptr++; - } - // Update the longest zero streak again for the tail case. - longest_zero_streak = std::min(longest_zero_streak, current_zero_streak); - - // Since randomness is hard to measure within one unit test, we instead do a - // sanity check. All non-zero bytes should not be packed into one end of the - // array. - // - // In this case, the size of one end is approximated to be: - // kByteArrayLength / nonZeroCount. - // Therefore, the longest zero streak should be less than: - // kByteArrayLength - one end of the array. - std::int32_t longest_acceptable_zero_streak = - kByteArrayLength - (kByteArrayLength / non_zero_count); - - EXPECT_TRUE(longest_zero_streak <= longest_acceptable_zero_streak); -} - -TEST(BloomFilterTest, RandomnessFalsePositiveRate) { - BloomFilter<10> bloom_filter; - - // Add 5 distinct elements to the BloomFilter. - bloom_filter.Add("ELEMENT_1"); - bloom_filter.Add("ELEMENT_2"); - bloom_filter.Add("ELEMENT_3"); - bloom_filter.Add("ELEMENT_4"); - bloom_filter.Add("ELEMENT_5"); - - std::int32_t false_positives = 0; - // Now test 100 other elements and record the number of false positives. - for (int i = 5; i < 105; i++) { - false_positives += - bloom_filter.PossiblyContains("ELEMENT_" + std::to_string(i)) ? 1 : 0; - } - - // We expect the false positive rate to be 3% with 5 elements in a 10 byte - // filter. Thus, we give a little leeway and verify that the false positive - // rate is no more than 5%. - EXPECT_LE(false_positives, 5); -} - -} // namespace -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_classic.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_classic.cc deleted file mode 100644 index bfa15992b26..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_classic.cc +++ /dev/null @@ -1,434 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/bluetooth_classic.h" - -#include <memory> -#include <string> -#include <utility> - -#include "core/internal/mediums/uuid.h" -#include "platform/public/logging.h" -#include "platform/public/mutex_lock.h" - -namespace location { -namespace nearby { -namespace connections { - -BluetoothClassic::BluetoothClassic(BluetoothRadio& radio) : radio_(radio) {} - -BluetoothClassic::~BluetoothClassic() { - // Destructor is not taking locks, but methods it is calling are. - StopDiscovery(); - while (!server_sockets_.empty()) { - StopAcceptingConnections(server_sockets_.begin()->first); - } - TurnOffDiscoverability(); - - // All the AcceptLoopRunnable objects in here should already have gotten an - // opportunity to shut themselves down cleanly in the calls to - // StopAcceptingConnections() above. - accept_loops_runner_.Shutdown(); -} - -bool BluetoothClassic::IsAvailable() const { - MutexLock lock(&mutex_); - - return IsAvailableLocked(); -} - -bool BluetoothClassic::IsAvailableLocked() const { - return medium_.IsValid() && adapter_.IsValid(); -} - -bool BluetoothClassic::TurnOnDiscoverability(const std::string& device_name) { - MutexLock lock(&mutex_); - - if (device_name.empty()) { - NEARBY_LOG(INFO, - "Refusing to turn on BT discoverability. Empty device name."); - return false; - } - - if (!radio_.IsEnabled()) { - NEARBY_LOG(INFO, "Can't turn on BT discoverability. BT is off."); - return false; - } - - if (!IsAvailableLocked()) { - NEARBY_LOG(INFO, "Can't turn on BT discoverability. BT is not available."); - return false; - } - - if (IsDiscoverable()) { - NEARBY_LOG(INFO, - "Refusing to turn on BT discoverability; new name='%s'; " - "current name='%s'", - device_name.c_str(), adapter_.GetName().c_str()); - return false; - } - - if (!ModifyDeviceName(device_name)) { - NEARBY_LOG(INFO, - "Failed to turn on BT discoverability; " - "failed to set name to %s", - device_name.c_str()); - return false; - } - - if (!ModifyScanMode(ScanMode::kConnectableDiscoverable)) { - NEARBY_LOG(INFO, - "Failed to turn on BT discoverability; " - "failed to set scan_mode to %d", - ScanMode::kConnectableDiscoverable); - - // Don't forget to perform this rollback of the partial state changes we've - // made til now. - RestoreDeviceName(); - return false; - } - - NEARBY_LOG(INFO, "Turned on BT discoverability with device_name=%s", - device_name.c_str()); - return true; -} - -bool BluetoothClassic::TurnOffDiscoverability() { - MutexLock lock(&mutex_); - - if (!IsDiscoverable()) { - NEARBY_LOG(INFO, "Can't turn off BT discoverability; it is already off"); - return false; - } - - RestoreScanMode(); - RestoreDeviceName(); - - NEARBY_LOG(INFO, "Turned Bluetooth discoverability off"); - return true; -} - -bool BluetoothClassic::IsDiscoverable() const { - return (!original_device_name_.empty() && - (adapter_.GetScanMode() == ScanMode::kConnectableDiscoverable)); -} - -bool BluetoothClassic::ModifyDeviceName(const std::string& device_name) { - if (original_device_name_.empty()) { - original_device_name_ = adapter_.GetName(); - } - - return adapter_.SetName(device_name); -} - -bool BluetoothClassic::ModifyScanMode(ScanMode scan_mode) { - if (original_scan_mode_ == ScanMode::kUnknown) { - original_scan_mode_ = adapter_.GetScanMode(); - } - - if (!adapter_.SetScanMode(scan_mode)) { - original_scan_mode_ = ScanMode::kUnknown; - return false; - } - - return true; -} - -bool BluetoothClassic::RestoreScanMode() { - if (original_scan_mode_ == ScanMode::kUnknown || - !adapter_.SetScanMode(original_scan_mode_)) { - NEARBY_LOG(INFO, "Failed to restore original Bluetooth scan mode to %d", - original_scan_mode_); - return false; - } - - // Regardless of whether or not we could actually restore the Bluetooth scan - // mode, reset our relevant state. - original_scan_mode_ = ScanMode::kUnknown; - return true; -} - -bool BluetoothClassic::RestoreDeviceName() { - if (original_device_name_.empty() || - !adapter_.SetName(original_device_name_)) { - NEARBY_LOG(INFO, "Failed to restore original Bluetooth device name to %s", - original_device_name_.c_str()); - return false; - } - original_device_name_.clear(); - return true; -} - -bool BluetoothClassic::StartDiscovery(DiscoveredDeviceCallback callback) { - MutexLock lock(&mutex_); - - if (!radio_.IsEnabled()) { - NEARBY_LOG(INFO, "Can't discover BT devices because BT isn't enabled."); - return false; - } - - if (!IsAvailableLocked()) { - NEARBY_LOG(INFO, "Can't discover BT devices because BT isn't available."); - return false; - } - - if (IsDiscovering()) { - NEARBY_LOG(INFO, - "Refusing to start discovery of BT devices because another " - "discovery is already in-progress."); - return false; - } - - if (!medium_.StartDiscovery(callback)) { - NEARBY_LOG(INFO, "Failed to start discovery of BT devices."); - return false; - } - - // Mark the fact that we're currently performing a Bluetooth scan. - scan_info_.valid = true; - - return true; -} - -bool BluetoothClassic::StopDiscovery() { - MutexLock lock(&mutex_); - - if (!IsDiscovering()) { - NEARBY_LOG(INFO, - "Can't stop discovery of BT devices because it never started."); - return false; - } - - if (!medium_.StopDiscovery()) { - NEARBY_LOG(INFO, "Failed to stop discovery of Bluetooth devices."); - return false; - } - - scan_info_.valid = false; - return true; -} - -bool BluetoothClassic::IsDiscovering() const { return scan_info_.valid; } - -bool BluetoothClassic::StartAcceptingConnections( - const std::string& service_name, AcceptedConnectionCallback callback) { - MutexLock lock(&mutex_); - - if (service_name.empty()) { - NEARBY_LOG( - INFO, - "Refusing to start accepting BT connections; service name is empty."); - return false; - } - - if (!radio_.IsEnabled()) { - NEARBY_LOG(INFO, - "Can't create BT server socket [service=%s]; BT is disabled.", - service_name.c_str()); - return false; - } - - if (!IsAvailableLocked()) { - NEARBY_LOG( - INFO, - "Can't start accepting BT connections [service=%s]; BT not available.", - service_name.c_str()); - return false; - } - - if (IsAcceptingConnectionsLocked(service_name)) { - NEARBY_LOG(INFO, - "Refusing to start accepting BT connections [service=%s]; BT " - "server is already in-progress with the same name.", - service_name.c_str()); - return false; - } - - BluetoothServerSocket socket = medium_.ListenForService( - service_name, GenerateUuidFromString(service_name)); - if (!socket.IsValid()) { - NEARBY_LOG(INFO, "Failed to start accepting Bluetooth connections for %s.", - service_name.c_str()); - return false; - } - - // Mark the fact that there's an in-progress Bluetooth server accepting - // connections. - auto owned_socket = - server_sockets_.emplace(service_name, std::move(socket)).first->second; - - // Start the accept loop on a dedicated thread - this stays alive and - // listening for new incoming connections until StopAcceptingConnections() is - // invoked. - accept_loops_runner_.Execute( - "bt-accept", - [callback = std::move(callback), server_socket = std::move(owned_socket), - service_name]() mutable { - while (true) { - BluetoothSocket client_socket = server_socket.Accept(); - if (!client_socket.IsValid()) { - server_socket.Close(); - break; - } - - callback.accepted_cb(std::move(client_socket)); - } - }); - - return true; -} - -bool BluetoothClassic::IsAcceptingConnections(const std::string& service_name) { - MutexLock lock(&mutex_); - - return IsAcceptingConnectionsLocked(service_name); -} - -bool BluetoothClassic::IsAcceptingConnectionsLocked( - const std::string& service_name) { - return server_sockets_.find(service_name) != server_sockets_.end(); -} - -bool BluetoothClassic::StopAcceptingConnections( - const std::string& service_name) { - MutexLock lock(&mutex_); - - if (service_name.empty()) { - NEARBY_LOG(INFO, - "Unable to stop accepting BT connections because the " - "service_name is empty."); - return false; - } - - const auto& it = server_sockets_.find(service_name); - if (it == server_sockets_.end()) { - NEARBY_LOG(INFO, - "Can't stop accepting BT connections for %s because it was " - "never started.", - service_name.c_str()); - return false; - } - - // Closing the BluetoothServerSocket will kick off the suicide of the thread - // in accept_loops_thread_pool_ that blocks on BluetoothServerSocket.accept(). - // That may take some time to complete, but there's no particular reason to - // wait around for it. - auto item = server_sockets_.extract(it); - - // Store a handle to the BluetoothServerSocket, so we can use it after - // removing the entry from server_sockets_; making it scoped - // is a bonus that takes care of deallocation before we leave this method. - BluetoothServerSocket& listening_socket = item.mapped(); - - // Regardless of whether or not we fail to close the existing - // BluetoothServerSocket, remove it from server_sockets_ so that it - // frees up this service for another round. - - // Finally, close the BluetoothServerSocket. - if (!listening_socket.Close().Ok()) { - NEARBY_LOG(INFO, "Failed to close BT server socket for %s.", - service_name.c_str()); - return false; - } - - return true; -} - -BluetoothSocket BluetoothClassic::Connect(BluetoothDevice& bluetooth_device, - const std::string& service_name, - CancellationFlag* cancellation_flag) { - for (int attempts_count = 0; attempts_count < kConnectAttemptsLimit; - attempts_count++) { - auto wrapper_result = - AttemptToConnect(bluetooth_device, service_name, cancellation_flag); - if (wrapper_result.IsValid()) { - return wrapper_result; - } - } - return BluetoothSocket(); -} - -BluetoothSocket BluetoothClassic::AttemptToConnect( - BluetoothDevice& bluetooth_device, const std::string& service_name, - CancellationFlag* cancellation_flag) { - MutexLock lock(&mutex_); - NEARBY_LOG(INFO, "BluetoothClassic::Connect: device=%p", &bluetooth_device); - // Socket to return. To allow for NRVO to work, it has to be a single object. - BluetoothSocket socket; - - if (service_name.empty()) { - NEARBY_LOG( - INFO, - "Refusing to create client BT socket because service_name is empty."); - return socket; - } - - if (!radio_.IsEnabled()) { - NEARBY_LOG(INFO, - "Can't create client BT socket [service=%s]: BT isn't enabled.", - service_name.c_str()); - return socket; - } - - if (!IsAvailableLocked()) { - NEARBY_LOG( - INFO, "Can't create client BT socket [service=%s]; BT isn't available.", - service_name.c_str()); - return socket; - } - - if (cancellation_flag->Cancelled()) { - NEARBY_LOGS(INFO) << "Can't create client BT socket due to cancel."; - return socket; - } - - socket = medium_.ConnectToService(bluetooth_device, - GenerateUuidFromString(service_name), - cancellation_flag); - if (!socket.IsValid()) { - NEARBY_LOG(INFO, "Failed to Connect via BT [service=%s]", - service_name.c_str()); - } - - return socket; -} - -BluetoothDevice BluetoothClassic::GetRemoteDevice( - const std::string& mac_address) { - MutexLock lock(&mutex_); - - if (!IsAvailableLocked()) { - return {}; - } - - return medium_.GetRemoteDevice(mac_address); -} - -std::string BluetoothClassic::GetMacAddress() const { - MutexLock lock(&mutex_); - - if (!IsAvailableLocked()) { - return {}; - } - - return medium_.GetMacAddress(); -} - -std::string BluetoothClassic::GenerateUuidFromString(const std::string& data) { - return std::string(Uuid(data)); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_classic.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_classic.h deleted file mode 100644 index 8389b1a0b7c..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_classic.h +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_BLUETOOTH_CLASSIC_H_ -#define CORE_INTERNAL_MEDIUMS_BLUETOOTH_CLASSIC_H_ - -#include <cstdint> -#include <string> - -#include "absl/container/flat_hash_map.h" -#include "core/internal/mediums/bluetooth_radio.h" -#include "core/listeners.h" -#include "platform/base/byte_array.h" -#include "platform/base/cancellation_flag.h" -#include "platform/public/bluetooth_adapter.h" -#include "platform/public/bluetooth_classic.h" -#include "platform/public/multi_thread_executor.h" -#include "platform/public/mutex.h" - -namespace location { -namespace nearby { -namespace connections { - -class BluetoothClassic { - public: - using DiscoveredDeviceCallback = BluetoothClassicMedium::DiscoveryCallback; - using ScanMode = BluetoothAdapter::ScanMode; - - // Callback that is invoked when a new connection is accepted. - struct AcceptedConnectionCallback { - std::function<void(BluetoothSocket socket)> accepted_cb = - DefaultCallback<BluetoothSocket>(); - }; - - explicit BluetoothClassic(BluetoothRadio& bluetooth_radio); - ~BluetoothClassic(); - - // Returns true, if BT communications are supported by a platform. - bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_); - - // Sets custom device name, and then enables BT discoverable mode. - // Returns true, if name and scan mode are successfully set, and false - // otherwise. - // Called by server. - bool TurnOnDiscoverability(const std::string& device_name) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Disables BT discoverability, and restores scan mode and device name to - // what they were before the call to TurnOnDiscoverability(). - // Returns false if no successful call TurnOnDiscoverability() was previously - // made, otherwise returns true. - // Called by server. - bool TurnOffDiscoverability() ABSL_LOCKS_EXCLUDED(mutex_); - - // Enables BT discovery mode. Will report any discoverable devices in range - // through a callback. - // Returns true, if discovery mode was enabled, false otherwise. - // Called by client. - bool StartDiscovery(DiscoveredDeviceCallback callback) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Disables BT discovery mode. - // Returns true, if discovery mode was previously enabled, false otherwise. - // Called by client. - bool StopDiscovery() ABSL_LOCKS_EXCLUDED(mutex_); - - // Starts a worker thread, creates a BT server socket, associates it with a - // service name; in a worker thread repeatedly calls ServerSocket::Accept(). - // Any connected sockets returned from Accept() are passed to a callback. - // Returns true, if server socket was successfully created, false otherwise. - // Called by server. - bool StartAcceptingConnections(const std::string& service_name, - AcceptedConnectionCallback callback) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true, if object is currently running a Accept() loop. - bool IsAcceptingConnections(const std::string& service_name) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Closes server socket corresponding to a service name. This automatically - // terminates Accept() loop, if it were running. - // Called by server. - bool StopAcceptingConnections(const std::string& service_name) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns true if this object owns a valid platform implementation. - bool IsMediumValid() const ABSL_LOCKS_EXCLUDED(mutex_) { - MutexLock lock(&mutex_); - return medium_.IsValid(); - } - - // Returns true if this object has a valid BluetoothAdapter reference. - bool IsAdapterValid() const ABSL_LOCKS_EXCLUDED(mutex_) { - MutexLock lock(&mutex_); - return adapter_.IsValid(); - } - - // Establishes connection to BT service with internal retry for maximum - // attempts of kConnectAttemptsLimit. - // Blocks until connection is established, or server-side is terminated. - // Returns socket instance. On success, BluetoothSocket.IsValid() return true. - // Called by client. - BluetoothSocket Connect(BluetoothDevice& bluetooth_device, - const std::string& service_name, - CancellationFlag* cancellation_flag) - ABSL_LOCKS_EXCLUDED(mutex_); - - std::string GetMacAddress() const ABSL_LOCKS_EXCLUDED(mutex_); - - BluetoothDevice GetRemoteDevice(const std::string& mac_address) - ABSL_LOCKS_EXCLUDED(mutex_); - - private: - struct ScanInfo { - bool valid = false; - }; - - static constexpr int kMaxConcurrentAcceptLoops = 5; - - static constexpr int kConnectAttemptsLimit = 3; - - // Constructs UUID object from arbitrary string, using MD5 hash, and then - // converts UUID to a readable UUID string and returns it. - static std::string GenerateUuidFromString(const std::string& data); - - // Same as IsAvailable(), but must be called with mutex_ held. - bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Same as IsAcceptingConnections(), but must be called with mutex_ held. - bool IsAcceptingConnectionsLocked(const std::string& service_name) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Returns true, if discoverability is enabled with TurnOnDiscoverability(). - bool IsDiscoverable() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Assignes a different name to BT adapter. - // Returns true if successful. Stores original device name. - bool ModifyDeviceName(const std::string& device_name) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Changes current scan mode. This is an implementation of - // Turn<On/Off>Discoveradility() method. Stores original scan mode. - bool ModifyScanMode(ScanMode scan_mode) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Restores original device name (the one before the very first call to - // ModifyDeviceName()). Returns true if successful. - bool RestoreScanMode() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Restores original device scan mode (the one before the very first call to - // ModifyScanMode()). Returns true if successful. - bool RestoreDeviceName() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Returns true if device is currently in discovery mode. - bool IsDiscovering() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Establishes connection to BT service that was might be started on another - // device with StartAcceptingConnections() using the same service_name. - // Blocks until connection is established, or server-side is terminated. - // Returns socket instance. On success, BluetoothSocket.IsValid() return true. - // Called by client. - BluetoothSocket AttemptToConnect(BluetoothDevice& bluetooth_device, - const std::string& service_name, - CancellationFlag* cancellation_flag); - - mutable Mutex mutex_; - BluetoothRadio& radio_ ABSL_GUARDED_BY(mutex_); - BluetoothAdapter& adapter_ ABSL_GUARDED_BY(mutex_){ - radio_.GetBluetoothAdapter()}; - BluetoothClassicMedium medium_ ABSL_GUARDED_BY(mutex_){adapter_}; - - // A bundle of state required to do a Bluetooth Classic scan. When non-null, - // we are currently performing a Bluetooth scan. - ScanInfo scan_info_ ABSL_GUARDED_BY(mutex_); - - // The original scan mode (that controls visibility to scanners) of the device - // before we modified it. Restored when we stop advertising. - ScanMode original_scan_mode_ ABSL_GUARDED_BY(mutex_) = ScanMode::kUnknown; - - // The original Bluetooth device name, before we modified it. If non-empty, we - // are currently Bluetooth discoverable. Restored when we stop advertising. - std::string original_device_name_ ABSL_GUARDED_BY(mutex_); - - // A thread pool dedicated to running all the accept loops from - // StartAcceptingConnections(). - MultiThreadExecutor accept_loops_runner_{kMaxConcurrentAcceptLoops}; - - // A map of service Name -> ServerSocket. If map is non-empty, we - // are currently listening for incoming connections. - // BluetoothServerSocket instances are used from accept_loops_runner_, - // and thus require pointer stability. - absl::flat_hash_map<std::string, BluetoothServerSocket> server_sockets_ - ABSL_GUARDED_BY(mutex_); -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_BLUETOOTH_CLASSIC_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_classic_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_classic_test.cc deleted file mode 100644 index d386bea51e0..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_classic_test.cc +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/bluetooth_classic.h" - -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/time/time.h" -#include "core/internal/mediums/bluetooth_radio.h" -#include "platform/base/medium_environment.h" -#include "platform/public/bluetooth_classic.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/logging.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -using FeatureFlags = FeatureFlags::Flags; - -constexpr FeatureFlags kTestCases[] = { - FeatureFlags{ - .enable_cancellation_flag = true, - }, - FeatureFlags{ - .enable_cancellation_flag = false, - }, -}; - -constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000); - -class BluetoothClassicTest : public ::testing::TestWithParam<FeatureFlags> { - protected: - using DiscoveryCallback = BluetoothClassicMedium::DiscoveryCallback; - - BluetoothClassicTest() { - env_.Start(); - env_.Reset(); - radio_a_ = std::make_unique<BluetoothRadio>(); - radio_b_ = std::make_unique<BluetoothRadio>(); - bt_a_ = std::make_unique<BluetoothClassic>(*radio_a_); - bt_b_ = std::make_unique<BluetoothClassic>(*radio_b_); - radio_a_->GetBluetoothAdapter().SetName("Device-A"); - radio_b_->GetBluetoothAdapter().SetName("Device-B"); - radio_a_->Enable(); - radio_b_->Enable(); - env_.Sync(); - } - - ~BluetoothClassicTest() override { - env_.Sync(false); - radio_a_->Disable(); - radio_b_->Disable(); - bt_a_.reset(); - bt_b_.reset(); - env_.Sync(false); - radio_a_.reset(); - radio_b_.reset(); - env_.Reset(); - env_.Stop(); - } - - MediumEnvironment& env_{MediumEnvironment::Instance()}; - - std::unique_ptr<BluetoothRadio> radio_a_; - std::unique_ptr<BluetoothRadio> radio_b_; - std::unique_ptr<BluetoothClassic> bt_a_; - std::unique_ptr<BluetoothClassic> bt_b_; -}; - -TEST_P(BluetoothClassicTest, CanConnect) { - FeatureFlags feature_flags = GetParam(); - env_.SetFeatureFlags(feature_flags); - - constexpr absl::string_view kDeviceName{"Simulated BT device #1"}; - constexpr absl::string_view kServiceName{"service name"}; - - BluetoothRadio& radio_for_client = *radio_a_; - BluetoothRadio& radio_for_server = *radio_b_; - BluetoothClassic& bt_client = *bt_a_; - BluetoothClassic& bt_server = *bt_b_; - - EXPECT_TRUE(radio_for_client.IsEnabled()); - EXPECT_TRUE(radio_for_server.IsEnabled()); - - EXPECT_TRUE(bt_server.TurnOnDiscoverability(std::string(kDeviceName))); - EXPECT_EQ(radio_for_server.GetBluetoothAdapter().GetName(), - std::string(kDeviceName)); - CountDownLatch latch(1); - BluetoothDevice discovered_device; - EXPECT_TRUE(bt_client.StartDiscovery({ - .device_discovered_cb = - [&latch, &discovered_device](BluetoothDevice& device) { - discovered_device = device; - NEARBY_LOG(INFO, "Discovered device=%p [impl=%p]", &device, - &device.GetImpl()); - latch.CountDown(); - }, - })); - EXPECT_TRUE(latch.Await(kWaitDuration).result()); - EXPECT_TRUE(bt_server.TurnOffDiscoverability()); - ASSERT_TRUE(discovered_device.IsValid()); - BluetoothSocket socket_for_server; - CountDownLatch accept_latch(1); - EXPECT_TRUE(bt_server.StartAcceptingConnections( - std::string(kServiceName), - { - .accepted_cb = - [&socket_for_server, &accept_latch](BluetoothSocket socket) { - socket_for_server = std::move(socket); - accept_latch.CountDown(); - }, - })); - CancellationFlag flag; - BluetoothSocket socket_for_client = - bt_client.Connect(discovered_device, std::string(kServiceName), &flag); - EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName))); - EXPECT_TRUE(socket_for_server.IsValid()); - EXPECT_TRUE(socket_for_client.IsValid()); - EXPECT_TRUE(socket_for_server.GetRemoteDevice().IsValid()); - EXPECT_TRUE(socket_for_client.GetRemoteDevice().IsValid()); -} - -TEST_P(BluetoothClassicTest, CanCancelConnect) { - FeatureFlags feature_flags = GetParam(); - env_.SetFeatureFlags(feature_flags); - - constexpr absl::string_view kDeviceName{"Simulated BT device #1"}; - constexpr absl::string_view kServiceName{"service name"}; - - BluetoothRadio& radio_for_client = *radio_a_; - BluetoothRadio& radio_for_server = *radio_b_; - BluetoothClassic& bt_client = *bt_a_; - BluetoothClassic& bt_server = *bt_b_; - - EXPECT_TRUE(radio_for_client.IsEnabled()); - EXPECT_TRUE(radio_for_server.IsEnabled()); - - EXPECT_TRUE(bt_server.TurnOnDiscoverability(std::string(kDeviceName))); - EXPECT_EQ(radio_for_server.GetBluetoothAdapter().GetName(), - std::string(kDeviceName)); - CountDownLatch latch(1); - BluetoothDevice discovered_device; - EXPECT_TRUE(bt_client.StartDiscovery({ - .device_discovered_cb = - [&latch, &discovered_device](BluetoothDevice& device) { - discovered_device = device; - NEARBY_LOG(INFO, "Discovered device=%p [impl=%p]", &device, - &device.GetImpl()); - latch.CountDown(); - }, - })); - EXPECT_TRUE(latch.Await(kWaitDuration).result()); - EXPECT_TRUE(bt_server.TurnOffDiscoverability()); - ASSERT_TRUE(discovered_device.IsValid()); - BluetoothSocket socket_for_server; - CountDownLatch accept_latch(1); - EXPECT_TRUE(bt_server.StartAcceptingConnections( - std::string(kServiceName), - { - .accepted_cb = - [&socket_for_server, &accept_latch](BluetoothSocket socket) { - socket_for_server = std::move(socket); - accept_latch.CountDown(); - }, - })); - CancellationFlag flag(true); - BluetoothSocket socket_for_client = - bt_client.Connect(discovered_device, std::string(kServiceName), &flag); - // If FeatureFlag is disabled, Cancelled is false as no-op. - if (!feature_flags.enable_cancellation_flag) { - EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName))); - EXPECT_TRUE(socket_for_server.IsValid()); - EXPECT_TRUE(socket_for_client.IsValid()); - EXPECT_TRUE(socket_for_server.GetRemoteDevice().IsValid()); - EXPECT_TRUE(socket_for_client.GetRemoteDevice().IsValid()); - } else { - EXPECT_FALSE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName))); - EXPECT_FALSE(socket_for_server.IsValid()); - EXPECT_FALSE(socket_for_client.IsValid()); - } -} - -INSTANTIATE_TEST_SUITE_P(ParametrisedBluetoothClassicTest, BluetoothClassicTest, - ::testing::ValuesIn(kTestCases)); - -TEST_F(BluetoothClassicTest, CanConstructValidObject) { - EXPECT_TRUE(bt_a_->IsMediumValid()); - EXPECT_TRUE(bt_a_->IsAdapterValid()); - EXPECT_TRUE(bt_a_->IsAvailable()); - EXPECT_TRUE(bt_b_->IsMediumValid()); - EXPECT_TRUE(bt_b_->IsAdapterValid()); - EXPECT_TRUE(bt_b_->IsAvailable()); - EXPECT_NE(&radio_a_->GetBluetoothAdapter(), &radio_b_->GetBluetoothAdapter()); -} - -TEST_F(BluetoothClassicTest, CanStartAdvertising) { - constexpr absl::string_view kDeviceName{"Simulated BT device #1"}; - EXPECT_TRUE(bt_a_->TurnOnDiscoverability(std::string(kDeviceName))); - EXPECT_EQ(radio_a_->GetBluetoothAdapter().GetName(), kDeviceName); -} - -TEST_F(BluetoothClassicTest, CanStopAdvertising) { - constexpr absl::string_view kDeviceName{"Simulated BT device #1"}; - EXPECT_TRUE(bt_a_->TurnOnDiscoverability(std::string(kDeviceName))); - EXPECT_EQ(radio_a_->GetBluetoothAdapter().GetName(), kDeviceName); - EXPECT_TRUE(bt_a_->TurnOffDiscoverability()); -} - -TEST_F(BluetoothClassicTest, CanStartDiscovery) { - constexpr absl::string_view kDeviceName{"Simulated BT device #1"}; - EXPECT_TRUE(bt_a_->TurnOnDiscoverability(std::string(kDeviceName))); - EXPECT_EQ(radio_a_->GetBluetoothAdapter().GetName(), kDeviceName); - CountDownLatch latch(1); - EXPECT_TRUE(bt_b_->StartDiscovery({ - .device_discovered_cb = - [&latch](BluetoothDevice& device) { latch.CountDown(); }, - })); - EXPECT_TRUE(latch.Await(kWaitDuration).result()); - EXPECT_TRUE(bt_a_->TurnOffDiscoverability()); -} - -TEST_F(BluetoothClassicTest, CanStopDiscovery) { - CountDownLatch latch(1); - EXPECT_TRUE(bt_a_->StartDiscovery({ - .device_discovered_cb = - [&latch](BluetoothDevice& device) { latch.CountDown(); }, - })); - EXPECT_FALSE(latch.Await(kWaitDuration).result()); - EXPECT_TRUE(bt_a_->StopDiscovery()); -} - -TEST_F(BluetoothClassicTest, CanStartAcceptingConnections) { - constexpr absl::string_view kDeviceName{"Simulated BT device #1"}; - constexpr absl::string_view kServiceName{"service name"}; - - BluetoothRadio& radio_for_client = *radio_a_; - BluetoothRadio& radio_for_server = *radio_b_; - BluetoothClassic& bt_client = *bt_a_; - BluetoothClassic& bt_server = *bt_b_; - - EXPECT_TRUE(radio_for_client.IsEnabled()); - EXPECT_TRUE(radio_for_server.IsEnabled()); - - EXPECT_TRUE(bt_server.TurnOnDiscoverability(std::string(kDeviceName))); - EXPECT_EQ(radio_for_server.GetBluetoothAdapter().GetName(), kDeviceName); - CountDownLatch latch(1); - BluetoothDevice discovered_device; - EXPECT_TRUE(bt_client.StartDiscovery({ - .device_discovered_cb = - [&latch, &discovered_device](BluetoothDevice& device) { - discovered_device = device; - NEARBY_LOG(INFO, "Discovered device=%p [impl=%p]", &device, - &device.GetImpl()); - latch.CountDown(); - }, - })); - EXPECT_TRUE(latch.Await(kWaitDuration).result()); - EXPECT_TRUE(bt_server.TurnOffDiscoverability()); - EXPECT_TRUE(discovered_device.IsValid()); - EXPECT_TRUE( - bt_server.StartAcceptingConnections(std::string(kServiceName), {})); - // Allow StartAcceptingConnections do something, before stopping it. - // This is best effort, because no callbacks are invoked in this scenario. - SystemClock::Sleep(kWaitDuration); - EXPECT_TRUE(bt_server.StopAcceptingConnections(std::string(kServiceName))); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_radio.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_radio.cc deleted file mode 100644 index e0ec86149e4..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_radio.cc +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/bluetooth_radio.h" - -#include "platform/base/exception.h" -#include "platform/public/logging.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { - -constexpr absl::Duration BluetoothRadio::kPauseBetweenToggle; - -BluetoothRadio::BluetoothRadio() { - if (!IsAdapterValid()) { - NEARBY_LOG(ERROR, "Bluetooth adapter is not valid: BT is not supported"); - } -} - -BluetoothRadio::~BluetoothRadio() { - // We never enabled Bluetooth, nothing to do. - if (!ever_saved_state_.Get()) { - NEARBY_LOG(INFO, "BT adapter was not used. Not touching HW."); - return; - } - - // Toggle Bluetooth regardless of our original state. Some devices/chips can - // start to freak out after some time (e.g. b/37775337), and this helps to - // ensure BT resets properly. - NEARBY_LOG(INFO, "Toggle BT adapter state before releasing adapter."); - Toggle(); - - NEARBY_LOG(INFO, "Bring BT adapter to original state"); - if (!SetBluetoothState(originally_enabled_.Get())) { - NEARBY_LOG(INFO, "Failed to restore BT adapter original state."); - } -} - -bool BluetoothRadio::Enable() { - if (!SaveOriginalState()) { - return false; - } - - return SetBluetoothState(true); -} - -bool BluetoothRadio::Disable() { - if (!SaveOriginalState()) { - return false; - } - - return SetBluetoothState(false); -} - -bool BluetoothRadio::IsEnabled() const { - return IsAdapterValid() && IsInDesiredState(true); -} - -bool BluetoothRadio::Toggle() { - if (!SaveOriginalState()) { - return false; - } - - if (!SetBluetoothState(false)) { - NEARBY_LOG(INFO, "BT Toggle: Failed to turn BT off."); - return false; - } - - if (SystemClock::Sleep(kPauseBetweenToggle).Raised(Exception::kInterrupted)) { - NEARBY_LOG(INFO, "BT Toggle: interrupted before turing on."); - return false; - } - - if (!SetBluetoothState(true)) { - NEARBY_LOG(INFO, "BT Toggle: Failed to turn BT on."); - return false; - } - - return true; -} - -bool BluetoothRadio::SetBluetoothState(bool enable) { - return bluetooth_adapter_.SetStatus( - enable ? BluetoothAdapter::Status::kEnabled - : BluetoothAdapter::Status::kDisabled); -} - -bool BluetoothRadio::IsInDesiredState(bool should_be_enabled) const { - return bluetooth_adapter_.IsEnabled() == should_be_enabled; -} - -bool BluetoothRadio::SaveOriginalState() { - if (!IsAdapterValid()) { - return false; - } - - // If we haven't saved the original state of the radio, save it. - if (!ever_saved_state_.Set(true)) { - originally_enabled_.Set(bluetooth_adapter_.IsEnabled()); - } - - return true; -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_radio.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_radio.h deleted file mode 100644 index 59ee3f7d572..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_radio.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_BLUETOOTH_RADIO_H_ -#define CORE_INTERNAL_MEDIUMS_BLUETOOTH_RADIO_H_ - -#include <cstdint> - -#include "absl/time/clock.h" -#include "platform/public/atomic_boolean.h" -#include "platform/public/bluetooth_adapter.h" - -namespace location { -namespace nearby { -namespace connections { - -// Provides the operations that can be performed on the Bluetooth radio. -class BluetoothRadio { - public: - BluetoothRadio(); - BluetoothRadio(BluetoothRadio&&) = default; - BluetoothRadio& operator=(BluetoothRadio&&) = default; - - // Reverts the Bluetooth radio to its original state. - ~BluetoothRadio(); - - // Enables Bluetooth. - // - // This must be called before attempting to invoke any other methods of - // this class. - // - // Returns true if enabled successfully. - bool Enable(); - - // Disables Bluetooth. - // - // Returns true if disabled successfully. - bool Disable(); - - // Returns true if the Bluetooth radio is currently enabled. - bool IsEnabled() const; - - // Turn BT radio Off, delay for kPauseBetweenToggle and then turn it On. - // This will block calling thread for at least kPauseBetweenToggle duration. - bool Toggle(); - - // Returns result of BluetoothAdapter::IsValid() for private adapter instance. - bool IsAdapterValid() const { return bluetooth_adapter_.IsValid(); } - - BluetoothAdapter& GetBluetoothAdapter() { return bluetooth_adapter_; } - - private: - static constexpr absl::Duration kPauseBetweenToggle = absl::Seconds(3); - - bool SetBluetoothState(bool enable); - bool IsInDesiredState(bool should_be_enabled) const; - // To be called in enable(), disable(), and toggle(). This will remember the - // original state of the radio before any radio state has been modified. - // Returns false if Bluetooth doesn't exist on the device and the state cannot - // be obtained. - bool SaveOriginalState(); - - // BluetoothAdapter::IsValid() will return false if BT is not supported. - BluetoothAdapter bluetooth_adapter_; - - // The Bluetooth radio's original state, before we modified it. True if - // originally enabled, false if originally disabled. - // We restore the radio to its original state in the destructor. - - AtomicBoolean originally_enabled_{false}; - // false if we never modified the radio state, true otherwise. - AtomicBoolean ever_saved_state_{false}; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_BLUETOOTH_RADIO_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_radio_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_radio_test.cc deleted file mode 100644 index 1a10383dd71..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/bluetooth_radio_test.cc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/bluetooth_radio.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -TEST(BluetoothRadioTest, ConstructorDestructorWorks) { - BluetoothRadio radio; - EXPECT_TRUE(radio.IsAdapterValid()); -} - -TEST(BluetoothRadioTest, CanEnable) { - BluetoothRadio radio; - EXPECT_TRUE(radio.IsAdapterValid()); - EXPECT_FALSE(radio.IsEnabled()); - EXPECT_TRUE(radio.Enable()); - EXPECT_TRUE(radio.IsEnabled()); -} - -TEST(BluetoothRadioTest, CanDisable) { - BluetoothRadio radio; - EXPECT_TRUE(radio.IsAdapterValid()); - EXPECT_FALSE(radio.IsEnabled()); - EXPECT_TRUE(radio.Enable()); - EXPECT_TRUE(radio.IsEnabled()); - EXPECT_TRUE(radio.Disable()); - EXPECT_FALSE(radio.IsEnabled()); -} - -TEST(BluetoothRadioTest, CanToggle) { - BluetoothRadio radio; - EXPECT_TRUE(radio.IsAdapterValid()); - EXPECT_FALSE(radio.IsEnabled()); - EXPECT_TRUE(radio.Toggle()); - EXPECT_TRUE(radio.IsEnabled()); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/lost_entity_tracker.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/lost_entity_tracker.h deleted file mode 100644 index b589155e7ac..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/lost_entity_tracker.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_LOST_ENTITY_TRACKER_H_ -#define CORE_INTERNAL_MEDIUMS_LOST_ENTITY_TRACKER_H_ - -#include "absl/container/flat_hash_set.h" -#include "platform/public/mutex.h" -#include "platform/public/mutex_lock.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -// Tracks "lost" entities based on a manual update/compute model. Used by -// mediums that only report found devices. Lost entities are computed based off -// of whether a specific entity was rediscovered since the last call to -// ComputeLostEntities. -// -// Note: Entity must overload the < and == operators. -template <typename Entity> -class LostEntityTracker { - public: - using EntitySet = absl::flat_hash_set<Entity>; - - LostEntityTracker(); - ~LostEntityTracker(); - - // Records the given entity as being recently found, whether or not this is - // our first time discovering the entity. - void RecordFoundEntity(const Entity& entity) ABSL_LOCKS_EXCLUDED(mutex_); - - // Computes and returns the set of entities considered lost since the last - // time this method was called. - EntitySet ComputeLostEntities() ABSL_LOCKS_EXCLUDED(mutex_); - - private: - Mutex mutex_; - EntitySet current_entities_ ABSL_GUARDED_BY(mutex_); - EntitySet previously_found_entities_ ABSL_GUARDED_BY(mutex_); -}; - -template <typename Entity> -LostEntityTracker<Entity>::LostEntityTracker() - : current_entities_{}, previously_found_entities_{} {} - -template <typename Entity> -LostEntityTracker<Entity>::~LostEntityTracker() { - previously_found_entities_.clear(); - current_entities_.clear(); -} - -template <typename Entity> -void LostEntityTracker<Entity>::RecordFoundEntity(const Entity& entity) { - MutexLock lock(&mutex_); - - current_entities_.insert(entity); -} - -template <typename Entity> -typename LostEntityTracker<Entity>::EntitySet -LostEntityTracker<Entity>::ComputeLostEntities() { - MutexLock lock(&mutex_); - - // The set of lost entities is the previously found set MINUS the currently - // found set. - for (const auto& item : current_entities_) { - previously_found_entities_.erase(item); - } - auto lost_entities = std::move(previously_found_entities_); - previously_found_entities_ = std::move(current_entities_); - current_entities_ = {}; - - return lost_entities; -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_LOST_ENTITY_TRACKER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/lost_entity_tracker_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/lost_entity_tracker_test.cc deleted file mode 100644 index 0c934e73f74..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/lost_entity_tracker_test.cc +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/lost_entity_tracker.h" - -#include "gtest/gtest.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { -namespace { - -struct TestEntity { - int id; - - template <typename H> - friend H AbslHashValue(H h, const TestEntity& test_entity) { - return H::combine(std::move(h), test_entity.id); - } - - bool operator==(const TestEntity& other) const { return id == other.id; } - bool operator<(const TestEntity& other) const { return id < other.id; } -}; - -TEST(LostEntityTrackerTest, NoEntitiesLost) { - LostEntityTracker<TestEntity> lost_entity_tracker; - TestEntity entity_1{1}; - TestEntity entity_2{2}; - TestEntity entity_3{3}; - - // Discover some entities. - lost_entity_tracker.RecordFoundEntity(entity_1); - lost_entity_tracker.RecordFoundEntity(entity_2); - lost_entity_tracker.RecordFoundEntity(entity_3); - - // Make sure none are lost on the first round. - ASSERT_TRUE(lost_entity_tracker.ComputeLostEntities().empty()); - - // Rediscover the same entities. - lost_entity_tracker.RecordFoundEntity(entity_1); - lost_entity_tracker.RecordFoundEntity(entity_2); - lost_entity_tracker.RecordFoundEntity(entity_3); - - // Make sure we still didn't lose any entities. - EXPECT_TRUE(lost_entity_tracker.ComputeLostEntities().empty()); -} - -TEST(LostEntityTrackerTest, AllEntitiesLost) { - LostEntityTracker<TestEntity> lost_entity_tracker; - TestEntity entity_1{1}; - TestEntity entity_2{2}; - TestEntity entity_3{3}; - - // Discover some entities. - lost_entity_tracker.RecordFoundEntity(entity_1); - lost_entity_tracker.RecordFoundEntity(entity_2); - lost_entity_tracker.RecordFoundEntity(entity_3); - - // Make sure none are lost on the first round. - EXPECT_TRUE(lost_entity_tracker.ComputeLostEntities().empty()); - - // Go through a round without rediscovering any entities. - typename LostEntityTracker<TestEntity>::EntitySet lost_entities = - lost_entity_tracker.ComputeLostEntities(); - EXPECT_TRUE(lost_entities.find(entity_1) != lost_entities.end()); - EXPECT_TRUE(lost_entities.find(entity_2) != lost_entities.end()); - EXPECT_TRUE(lost_entities.find(entity_3) != lost_entities.end()); -} - -TEST(LostEntityTrackerTest, SomeEntitiesLost) { - LostEntityTracker<TestEntity> lost_entity_tracker; - TestEntity entity_1{1}; - TestEntity entity_2{2}; - TestEntity entity_3{3}; - - // Discover some entities. - lost_entity_tracker.RecordFoundEntity(entity_1); - lost_entity_tracker.RecordFoundEntity(entity_2); - - // Make sure none are lost on the first round. - EXPECT_TRUE(lost_entity_tracker.ComputeLostEntities().empty()); - - // Go through the next round only rediscovering one of our entities and - // discovering an additional entity as well. Then, verify that only one entity - // was lost after the check. - lost_entity_tracker.RecordFoundEntity(entity_1); - lost_entity_tracker.RecordFoundEntity(entity_3); - typename LostEntityTracker<TestEntity>::EntitySet lost_entities = - lost_entity_tracker.ComputeLostEntities(); - EXPECT_TRUE(lost_entities.find(entity_1) == lost_entities.end()); - EXPECT_TRUE(lost_entities.find(entity_2) != lost_entities.end()); - EXPECT_TRUE(lost_entities.find(entity_3) == lost_entities.end()); -} - -TEST(LostEntityTrackerTest, SameEntityMultipleCopies) { - LostEntityTracker<TestEntity> lost_entity_tracker; - TestEntity entity_1{1}; - TestEntity entity_1_copy{1}; - - // Discover an entity. - lost_entity_tracker.RecordFoundEntity(entity_1); - - // Make sure none are lost on the first round. - EXPECT_TRUE(lost_entity_tracker.ComputeLostEntities().empty()); - - // Rediscover the same entity, but through a copy of it. - lost_entity_tracker.RecordFoundEntity(entity_1_copy); - - // Make sure none are lost on the second round. - EXPECT_TRUE(lost_entity_tracker.ComputeLostEntities().empty()); - - // Go through a round without rediscovering any entities and verify that we - // lost an entity equivalent to both copies of it. - typename LostEntityTracker<TestEntity>::EntitySet lost_entities = - lost_entity_tracker.ComputeLostEntities(); - EXPECT_EQ(lost_entities.size(), 1); - EXPECT_TRUE(lost_entities.find(entity_1) != lost_entities.end()); - EXPECT_TRUE(lost_entities.find(entity_1_copy) != lost_entities.end()); -} - -} // namespace -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/mediums.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/mediums.cc deleted file mode 100644 index 8b0b3100ecf..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/mediums.cc +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/mediums.h" - -namespace location { -namespace nearby { -namespace connections { - -BluetoothRadio& Mediums::GetBluetoothRadio() { return bluetooth_radio_; } - -BluetoothClassic& Mediums::GetBluetoothClassic() { return bluetooth_classic_; } - -Ble& Mediums::GetBle() { return ble_; } - -WifiLan& Mediums::GetWifiLan() { return wifi_lan_; } - -mediums::WebRtc& Mediums::GetWebRtc() { return webrtc_; } - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/mediums.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/mediums.h deleted file mode 100644 index 4c6127eb957..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/mediums.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_MEDIUMS_H_ -#define CORE_INTERNAL_MEDIUMS_MEDIUMS_H_ - -#include "core/internal/mediums/ble.h" -#include "core/internal/mediums/bluetooth_classic.h" -#include "core/internal/mediums/bluetooth_radio.h" -#include "core/internal/mediums/webrtc.h" -#include "core/internal/mediums/wifi_lan.h" - -namespace location { -namespace nearby { -namespace connections { - -// Facilitates convenient and reliable usage of various wireless mediums. -class Mediums { - public: - Mediums() = default; - ~Mediums() = default; - - // Returns a handle to the Bluetooth radio. - BluetoothRadio& GetBluetoothRadio(); - - // Returns a handle to the Bluetooth Classic medium. - BluetoothClassic& GetBluetoothClassic(); - - // Returns a handle to the Ble medium. - Ble& GetBle(); - - // Returns a handle to the Wifi-Lan medium. - WifiLan& GetWifiLan(); - - // Returns a handle to the WebRtc medium. - mediums::WebRtc& GetWebRtc(); - - private: - // The order of declaration is critical for both construction and - // destruction. - // - // 1) Construction: The individual mediums have a dependency on the - // corresponding radio, so the radio must be initialized first. - // - // 2) Destruction: The individual mediums should be shut down before the - // corresponding radio. - BluetoothRadio bluetooth_radio_; - BluetoothClassic bluetooth_classic_{bluetooth_radio_}; - Ble ble_{bluetooth_radio_}; - WifiLan wifi_lan_; - mediums::WebRtc webrtc_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_MEDIUMS_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/utils.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/utils.cc deleted file mode 100644 index 11b581f7710..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/utils.cc +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/utils.h" - -#include <memory> -#include <string> - -#include "platform/base/prng.h" -#include "platform/public/crypto.h" - -namespace location { -namespace nearby { -namespace connections { - -namespace { -constexpr absl::string_view kUpgradeServiceIdPostfix = "_UPGRADE"; -} - -ByteArray Utils::GenerateRandomBytes(size_t length) { - Prng rng; - std::string data; - data.reserve(length); - - // Adds 4 random bytes per iteration. - while (length > 0) { - std::uint32_t val = rng.NextUint32(); - for (int i = 0; i < 4; i++) { - data += val & 0xFF; - val >>= 8; - length--; - - if (!length) break; - } - } - - return ByteArray(data); -} - -ByteArray Utils::Sha256Hash(const ByteArray& source, size_t length) { - return Utils::Sha256Hash(std::string(source), length); -} - -ByteArray Utils::Sha256Hash(const std::string& source, size_t length) { - ByteArray full_hash(length); - full_hash.CopyAt(0, Crypto::Sha256(source)); - return full_hash; -} - -std::string Utils::WrapUpgradeServiceId(const std::string& service_id) { - if (service_id.empty()) { - return {}; - } - return service_id + std::string(kUpgradeServiceIdPostfix); -} - -std::string Utils::UnwrapUpgradeServiceId( - const std::string& upgrade_service_id) { - auto pos = upgrade_service_id.find(std::string(kUpgradeServiceIdPostfix)); - if (pos != std::string::npos) { - return std::string(upgrade_service_id, 0, pos); - } - return upgrade_service_id; -} - -LocationHint Utils::BuildLocationHint(const std::string& location) { - LocationHint location_hint; - location_hint.set_format(LocationStandard::UNKNOWN); - - if (!location.empty()) { - location_hint.set_location(location); - if (location.at(0) == '+') { - location_hint.set_format(LocationStandard::E164_CALLING); - } else { - location_hint.set_format(LocationStandard::ISO_3166_1_ALPHA_2); - } - } - return location_hint; -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/utils.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/utils.h deleted file mode 100644 index 4a26c4e82c6..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/utils.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_UTILS_H_ -#define CORE_INTERNAL_MEDIUMS_UTILS_H_ - -#include <memory> -#include <string> - -#include "platform/base/byte_array.h" -#include "proto/connections/offline_wire_formats.pb.h" - -namespace location { -namespace nearby { -namespace connections { - -class Utils { - public: - static ByteArray GenerateRandomBytes(size_t length); - static ByteArray Sha256Hash(const ByteArray& source, size_t length); - static ByteArray Sha256Hash(const std::string& source, size_t length); - static std::string WrapUpgradeServiceId(const std::string& service_id); - static std::string UnwrapUpgradeServiceId(const std::string& service_id); - static LocationHint BuildLocationHint(const std::string& location); -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_UTILS_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/uuid.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/uuid.cc deleted file mode 100644 index e3c171598fd..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/uuid.cc +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/uuid.h" - -#include <iomanip> -#include <sstream> - -#include "platform/public/crypto.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { -std::ostream& write_hex(std::ostream& os, absl::string_view data) { - for (const auto b : data) { - os << std::setfill('0') << std::setw(2) << std::hex - << (static_cast<unsigned int>(b) & 0x0ff); - } - return os; -} -} // namespace - -Uuid::Uuid(absl::string_view data) : data_(Crypto::Md5(data)) { - // Based on the Java counterpart at - // http://androidxref.com/8.0.0_r4/xref/libcore/ojluni/src/main/java/java/util/UUID.java#162. - data_[6] &= 0x0f; // Clear version. - data_[6] |= 0x30; // Set to version 3. - data_[8] &= 0x3f; // Clear variant. - data_[8] |= 0x80; // Set to IETF variant. -} - -Uuid::Uuid(std::uint64_t most_sig_bits, std::uint64_t least_sig_bits) { - // Base on the Java counterpart at - // http://androidxref.com/8.0.0_r4/xref/libcore/ojluni/src/main/java/java/util/UUID.java#104. - data_.reserve(sizeof(most_sig_bits) + sizeof(least_sig_bits)); - - data_[0] = static_cast<char>((most_sig_bits >> 56) & 0x0ff); - data_[1] = static_cast<char>((most_sig_bits >> 48) & 0x0ff); - data_[2] = static_cast<char>((most_sig_bits >> 40) & 0x0ff); - data_[3] = static_cast<char>((most_sig_bits >> 32) & 0x0ff); - data_[4] = static_cast<char>((most_sig_bits >> 24) & 0x0ff); - data_[5] = static_cast<char>((most_sig_bits >> 16) & 0x0ff); - data_[6] = static_cast<char>((most_sig_bits >> 8) & 0x0ff); - data_[7] = static_cast<char>((most_sig_bits >> 0) & 0x0ff); - - data_[8] = static_cast<char>((least_sig_bits >> 56) & 0x0ff); - data_[9] = static_cast<char>((least_sig_bits >> 48) & 0x0ff); - data_[10] = static_cast<char>((least_sig_bits >> 40) & 0x0ff); - data_[11] = static_cast<char>((least_sig_bits >> 32) & 0x0ff); - data_[12] = static_cast<char>((least_sig_bits >> 24) & 0x0ff); - data_[13] = static_cast<char>((least_sig_bits >> 16) & 0x0ff); - data_[14] = static_cast<char>((least_sig_bits >> 8) & 0x0ff); - data_[15] = static_cast<char>((least_sig_bits >> 0) & 0x0ff); -} - -Uuid::operator std::string() const { - // Based on the Java counterpart at - // http://androidxref.com/8.0.0_r4/xref/libcore/ojluni/src/main/java/java/util/UUID.java#375. - std::ostringstream md5_hex; - write_hex(md5_hex, absl::string_view(&data_[0], 4)); - md5_hex << "-"; - write_hex(md5_hex, absl::string_view(&data_[4], 2)); - md5_hex << "-"; - write_hex(md5_hex, absl::string_view(&data_[6], 2)); - md5_hex << "-"; - write_hex(md5_hex, absl::string_view(&data_[8], 2)); - md5_hex << "-"; - write_hex(md5_hex, absl::string_view(&data_[10], 6)); - - return md5_hex.str(); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/uuid.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/uuid.h deleted file mode 100644 index fec9e071c17..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/uuid.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_UUID_H_ -#define CORE_INTERNAL_MEDIUMS_UUID_H_ - -#include <cstdint> -#include <string> - -#include "absl/strings/string_view.h" - -namespace location { -namespace nearby { -namespace connections { - -// A type 3 name-based -// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based)) -// UUID. -// -// https://developer.android.com/reference/java/util/UUID.html -class Uuid final { - public: - Uuid() : Uuid("uuid") {} - explicit Uuid(absl::string_view data); - Uuid(std::uint64_t most_sig_bits, std::uint64_t least_sig_bits); - Uuid(const Uuid&) = default; - Uuid& operator=(const Uuid&) = default; - Uuid(Uuid&&) = default; - Uuid& operator=(Uuid&&) = default; - ~Uuid() = default; - - // Returns the canonical textual representation - // (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of the - // UUID. - explicit operator std::string() const; - std::string data() const { return data_; } - - private: - std::string data_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_UUID_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/uuid_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/uuid_test.cc deleted file mode 100644 index f5a8303265d..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/uuid_test.cc +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/uuid.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "platform/public/crypto.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -constexpr absl::string_view kString{"some string"}; -constexpr std::uint64_t kNum1 = 0x123456789abcdef0; -constexpr std::uint64_t kNum2 = 0x21436587a9cbed0f; - -TEST(UuidTest, CreateFromStringWithMd5) { - Uuid uuid(kString); - std::string uuid_str(uuid); - std::string uuid_data(uuid.data()); - std::string md5_data(Crypto::Md5(kString)); - NEARBY_LOG(INFO, "MD5-based UUID: '%s'", uuid_str.c_str()); - uuid_data[6] = 0; - uuid_data[8] = 0; - md5_data[6] = 0; - md5_data[8] = 0; - EXPECT_EQ(md5_data, uuid_data); -} - -TEST(UuidTest, CreateFromBinary) { - Uuid uuid(kNum1, kNum2); - std::string uuid_data(uuid.data()); - std::string uuid_str(uuid); - NEARBY_LOG(INFO, "UUID: '%s'", uuid_str.c_str()); - EXPECT_EQ(uuid_data[0], (kNum1 >> 56) & 0xFF); - EXPECT_EQ(uuid_data[1], (kNum1 >> 48) & 0xFF); - EXPECT_EQ(uuid_data[2], (kNum1 >> 40) & 0xFF); - EXPECT_EQ(uuid_data[3], (kNum1 >> 32) & 0xFF); - EXPECT_EQ(uuid_data[4], (kNum1 >> 24) & 0xFF); - EXPECT_EQ(uuid_data[5], (kNum1 >> 16) & 0xFF); - EXPECT_EQ(uuid_data[6], (kNum1 >> 8) & 0xFF); - EXPECT_EQ(uuid_data[7], (kNum1 >> 0) & 0xFF); - EXPECT_EQ(uuid_data[8], (kNum2 >> 56) & 0xFF); - EXPECT_EQ(uuid_data[9], (kNum2 >> 48) & 0xFF); - EXPECT_EQ(uuid_data[10], (kNum2 >> 40) & 0xFF); - EXPECT_EQ(uuid_data[11], (kNum2 >> 32) & 0xFF); - EXPECT_EQ(uuid_data[12], (kNum2 >> 24) & 0xFF); - EXPECT_EQ(uuid_data[13], (kNum2 >> 16) & 0xFF); - EXPECT_EQ(uuid_data[14], (kNum2 >> 8) & 0xFF); - EXPECT_EQ(uuid_data[15], (kNum2 >> 0) & 0xFF); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc.cc deleted file mode 100644 index 1edcf63965a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc.cc +++ /dev/null @@ -1,744 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/webrtc.h" - -#include <functional> -#include <memory> - -#include "absl/functional/bind_front.h" -#include "absl/strings/str_cat.h" -#include "absl/time/time.h" -#include "core/internal/mediums/webrtc/session_description_wrapper.h" -#include "core/internal/mediums/webrtc/signaling_frames.h" -#include "core/internal/mediums/webrtc_socket_wrapper.h" -#include "platform/base/byte_array.h" -#include "platform/base/listeners.h" -#include "platform/public/cancelable_alarm.h" -#include "platform/public/future.h" -#include "platform/public/logging.h" -#include "platform/public/mutex_lock.h" -#include "proto/mediums/web_rtc_signaling_frames.pb.h" -#include "webrtc/api/jsep.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -namespace { - -// The maximum amount of time to wait to connect to a data channel via WebRTC. -constexpr absl::Duration kDataChannelTimeout = absl::Seconds(10); - -// Delay between restarting signaling messenger to receive messages. -constexpr absl::Duration kRestartReceiveMessagesDuration = absl::Seconds(60); - -} // namespace - -WebRtc::WebRtc() = default; - -WebRtc::~WebRtc() { - // This ensures that all pending callbacks are run before we reset the medium - // and we are not accepting new runnables. - single_thread_executor_.Shutdown(); - - // Stop accepting all connections - absl::flat_hash_set<std::string> service_ids; - for (auto& item : accepting_connections_info_) { - service_ids.emplace(item.first); - } - for (const auto& service_id : service_ids) { - StopAcceptingConnections(service_id); - } -} - -const std::string WebRtc::GetDefaultCountryCode() { - return medium_.GetDefaultCountryCode(); -} - -bool WebRtc::IsAvailable() { return medium_.IsValid(); } - -bool WebRtc::IsAcceptingConnections(const std::string& service_id) { - MutexLock lock(&mutex_); - return IsAcceptingConnectionsLocked(service_id); -} - -bool WebRtc::IsAcceptingConnectionsLocked(const std::string& service_id) { - return accepting_connections_info_.contains(service_id); -} - -bool WebRtc::StartAcceptingConnections(const std::string& service_id, - const WebrtcPeerId& self_peer_id, - const LocationHint& location_hint, - AcceptedConnectionCallback callback) { - MutexLock lock(&mutex_); - if (!IsAvailable()) { - NEARBY_LOG(WARNING, - "Cannot start accepting WebRTC connections because WebRTC is " - "not available."); - return false; - } - - if (IsAcceptingConnectionsLocked(service_id)) { - NEARBY_LOG(WARNING, - "Cannot start accepting WebRTC connections because service %s " - "is already accepting WebRTC connections.", - service_id.c_str()); - return false; - } - - // We'll track our state here, so that we're separated from the other services - // who may be also using WebRTC. - AcceptingConnectionsInfo info = AcceptingConnectionsInfo(); - info.self_peer_id = self_peer_id; - info.accepted_connection_callback = callback; - - // Create a new SignalingMessenger so that we can communicate w/ Tachyon. - info.signaling_messenger = - medium_.GetSignalingMessenger(self_peer_id.GetId(), location_hint); - if (!info.signaling_messenger->IsValid()) { - return false; - } - - // This registers ourselves w/ Tachyon, creating a room from the PeerId. - // This allows a remote device to message us over Tachyon. - if (!info.signaling_messenger->StartReceivingMessages( - absl::bind_front(&WebRtc::OnSignalingMessage, this, service_id), - absl::bind_front(&WebRtc::OnSignalingComplete, this, service_id))) { - info.signaling_messenger.reset(); - return false; - } - - // We'll automatically disconnect from Tachyon after 60sec. When this alarm - // fires, we'll recreate our room so we continue to receive messages. - info.restart_tachyon_receive_messages_alarm = CancelableAlarm( - "restart_receiving_messages_webrtc", - std::bind(&WebRtc::ProcessRestartTachyonReceiveMessages, this, - service_id), - kRestartReceiveMessagesDuration, &single_thread_executor_); - - // Now that we're set up to receive messages, we'll save our state and return - // a successful result. - accepting_connections_info_.emplace(service_id, std::move(info)); - NEARBY_LOG(INFO, - "Started listening for WebRTC connections as %s on service %s", - self_peer_id.GetId().c_str(), service_id.c_str()); - return true; -} - -void WebRtc::StopAcceptingConnections(const std::string& service_id) { - MutexLock lock(&mutex_); - if (!IsAcceptingConnectionsLocked(service_id)) { - NEARBY_LOG(WARNING, - "Cannot stop accepting WebRTC connections because service %s " - "is not accepting WebRTC connections.", - service_id.c_str()); - return; - } - - // Grab our info from the map. - auto& info = accepting_connections_info_.find(service_id)->second; - - // Stop receiving messages from Tachyon. - info.signaling_messenger->StopReceivingMessages(); - info.signaling_messenger.reset(); - - // Cancel the scheduled alarm. - if (info.restart_tachyon_receive_messages_alarm.IsValid()) { - info.restart_tachyon_receive_messages_alarm.Cancel(); - info.restart_tachyon_receive_messages_alarm = CancelableAlarm(); - } - - // If we had any in-progress connections that haven't materialized into full - // DataChannels yet, it's time to shut them down since they can't reach us - // anymore. - absl::flat_hash_set<std::string> peer_ids; - for (auto& item : connection_flows_) { - peer_ids.emplace(item.first); - } - for (const auto& peer_id : peer_ids) { - const auto& entry = connection_flows_.find(peer_id); - // Skip outgoing connections in this step. Start/StopAcceptingConnections - // only deals with incoming connections. - if (requesting_connections_info_.contains(peer_id)) { - continue; - } - - // Skip fully connected connections in this step. If the connection was - // formed while we were accepting connections, then it will stay alive until - // it's explicitly closed. - if (!entry->second->CloseIfNotConnected()) { - continue; - } - - connection_flows_.erase(peer_id); - } - - // Clean up our state. We're now no longer listening for connections. - accepting_connections_info_.erase(service_id); - NEARBY_LOG(INFO, "Stopped listening for WebRTC connections for service %s", - service_id.c_str()); -} - -WebRtcSocketWrapper WebRtc::Connect(const std::string& service_id, - const WebrtcPeerId& remote_peer_id, - const LocationHint& location_hint, - CancellationFlag* cancellation_flag) { - for (int attempts_count = 0; attempts_count < kConnectAttemptsLimit; - attempts_count++) { - auto wrapper_result = AttemptToConnect(service_id, remote_peer_id, - location_hint, cancellation_flag); - if (wrapper_result.IsValid()) { - return wrapper_result; - } - } - return WebRtcSocketWrapper(); -} - -WebRtcSocketWrapper WebRtc::AttemptToConnect( - const std::string& service_id, const WebrtcPeerId& remote_peer_id, - const LocationHint& location_hint, CancellationFlag* cancellation_flag) { - ConnectionRequestInfo info = ConnectionRequestInfo(); - info.self_peer_id = WebrtcPeerId::FromRandom(); - Future<WebRtcSocketWrapper> socket_future = info.socket_future; - - { - MutexLock lock(&mutex_); - if (!IsAvailable()) { - NEARBY_LOG( - WARNING, - "Cannot connect to WebRTC peer %s because WebRTC is not available.", - remote_peer_id.GetId().c_str()); - return WebRtcSocketWrapper(); - } - - if (cancellation_flag->Cancelled()) { - NEARBY_LOGS(INFO) << "Cannot connect with WebRtc due to cancel."; - return WebRtcSocketWrapper(); - } - - // Create a new ConnectionFlow for this connection attempt. - std::unique_ptr<ConnectionFlow> connection_flow = - CreateConnectionFlow(service_id, remote_peer_id); - if (!connection_flow) { - NEARBY_LOG( - INFO, - "Cannot connect to WebRTC peer %s because we failed to create a " - "ConnectionFlow.", - remote_peer_id.GetId().c_str()); - return WebRtcSocketWrapper(); - } - - // Create a new SignalingMessenger so that we can communicate over Tachyon. - info.signaling_messenger = - medium_.GetSignalingMessenger(info.self_peer_id.GetId(), location_hint); - if (!info.signaling_messenger->IsValid()) { - NEARBY_LOG( - INFO, - "Cannot connect to WebRTC peer %s because we failed to create a " - "SignalingMessenger.", - remote_peer_id.GetId().c_str()); - return WebRtcSocketWrapper(); - } - - // This registers ourselves w/ Tachyon, creating a room from the PeerId. - // This allows a remote device to message us over Tachyon. - auto signaling_complete_callback = [socket_future](bool success) mutable { - if (!success) { - socket_future.SetException({Exception::kFailed}); - } - }; - if (!info.signaling_messenger->StartReceivingMessages( - absl::bind_front(&WebRtc::OnSignalingMessage, this, service_id), - signaling_complete_callback)) { - NEARBY_LOG(INFO, - "Cannot connect to WebRTC peer %s because we failed to start " - "receiving messages over Tachyon.", - remote_peer_id.GetId().c_str()); - info.signaling_messenger.reset(); - return WebRtcSocketWrapper(); - } - - // Poke the remote device. This will cause them to send us an Offer. - if (!info.signaling_messenger->SendMessage( - remote_peer_id.GetId(), - webrtc_frames::EncodeReadyForSignalingPoke(info.self_peer_id))) { - NEARBY_LOG(INFO, - "Cannot connect to WebRTC peer %s because we failed to poke " - "the peer over Tachyon.", - remote_peer_id.GetId().c_str()); - info.signaling_messenger.reset(); - return WebRtcSocketWrapper(); - } - - // Create a new ConnectionRequest entry. This map will be used later to look - // up state as we negotiate the connection over Tachyon. - requesting_connections_info_.emplace(remote_peer_id.GetId(), - std::move(info)); - connection_flows_.emplace(remote_peer_id.GetId(), - std::move(connection_flow)); - } - - // Wait for the connection to go through. Don't hold the mutex here so that - // we're not blocking necessary operations. - ExceptionOr<WebRtcSocketWrapper> socket_result = - socket_future.Get(kDataChannelTimeout); - - { - MutexLock lock(&mutex_); - - // Reclaim our info, since we had released ownership while talking to - // Tachyon. - auto& info = - requesting_connections_info_.find(remote_peer_id.GetId())->second; - - // Verify that the connection went through. - if (!socket_result.ok()) { - NEARBY_LOG(INFO, "Failed to connect to WebRTC peer %s.", - remote_peer_id.GetId().c_str()); - RemoveConnectionFlow(remote_peer_id); - info.signaling_messenger.reset(); - requesting_connections_info_.erase(remote_peer_id.GetId()); - return WebRtcSocketWrapper(); - } - - // Clean up our ConnectionRequest. - info.signaling_messenger.reset(); - requesting_connections_info_.erase(remote_peer_id.GetId()); - - // Return the result. - return socket_result.GetResult(); - } -} - -void WebRtc::ProcessLocalIceCandidate( - const std::string& service_id, const WebrtcPeerId& remote_peer_id, - const ::location::nearby::mediums::IceCandidate ice_candidate) { - MutexLock lock(&mutex_); - - // Check first if we have an outgoing request w/ this peer. As this request is - // tied to a specific peer, it takes precedence. - const auto& connection_request_entry = - requesting_connections_info_.find(remote_peer_id.GetId()); - if (connection_request_entry != requesting_connections_info_.end()) { - // Pass the ice candidate to the remote side. - if (!connection_request_entry->second.signaling_messenger->SendMessage( - remote_peer_id.GetId(), - webrtc_frames::EncodeIceCandidates( - connection_request_entry->second.self_peer_id, - {ice_candidate}))) { - NEARBY_LOG(INFO, "Failed to send ice candidate to %s.", - remote_peer_id.GetId().c_str()); - } - - NEARBY_LOG(INFO, "Sent ice candidate to %s.", - remote_peer_id.GetId().c_str()); - return; - } - - // Check next if we're expecting incoming connection requests. - const auto& accepting_connection_entry = - accepting_connections_info_.find(service_id); - if (accepting_connection_entry != accepting_connections_info_.end()) { - // Pass the ice candidate to the remote side. - // TODO(xlythe) Consider not blocking here, since this can eat into the - // connection time - if (!accepting_connection_entry->second.signaling_messenger->SendMessage( - remote_peer_id.GetId(), - webrtc_frames::EncodeIceCandidates( - accepting_connection_entry->second.self_peer_id, - {ice_candidate}))) { - NEARBY_LOG(INFO, "Failed to send ice candidate to %s.", - remote_peer_id.GetId().c_str()); - } - - NEARBY_LOG(INFO, "Sent ice candidate to %s.", - remote_peer_id.GetId().c_str()); - return; - } - - NEARBY_LOG(INFO, - "Skipping restart listening for tachyon inbox messages since we " - "are not accepting connections for service %s.", - service_id.c_str()); -} - -void WebRtc::OnSignalingMessage(const std::string& service_id, - const ByteArray& message) { - OffloadFromThread("rtc-on-signaling-message", [this, service_id, message]() { - ProcessTachyonInboxMessage(service_id, message); - }); -} - -void WebRtc::OnSignalingComplete(const std::string& service_id, bool success) { - NEARBY_LOG(INFO, "Signaling completed with status: %d.", success); - if (success) { - return; - } - - OffloadFromThread("rtc-on-signaling-complete", [this, service_id]() { - MutexLock lock(&mutex_); - const auto& info_entry = accepting_connections_info_.find(service_id); - if (info_entry == accepting_connections_info_.end()) { - return; - } - - if (info_entry->second.restart_accept_connections_count < - kRestartAcceptConnectionsLimit) { - ++info_entry->second.restart_accept_connections_count; - } else { - return; - } - - RestartTachyonReceiveMessages(service_id); - }); -} - -void WebRtc::ProcessTachyonInboxMessage(const std::string& service_id, - const ByteArray& message) { - MutexLock lock(&mutex_); - - // Attempt to parse the incoming message as a WebRtcSignalingFrame. - location::nearby::mediums::WebRtcSignalingFrame frame; - if (!frame.ParseFromString(std::string(message))) { - NEARBY_LOG(WARNING, "Failed to parse signaling message."); - return; - } - - // Ensure that the frame is valid (no missing fields). - if (!frame.has_sender_id()) { - NEARBY_LOG(WARNING, "Invalid WebRTC frame: Sender ID is missing."); - return; - } - WebrtcPeerId remote_peer_id = WebrtcPeerId(frame.sender_id().id()); - - // Depending on the message type, we'll respond as appropriate. - if (requesting_connections_info_.contains(remote_peer_id.GetId())) { - // This is from a peer we have an outgoing connection request with, so we'll - // only process the Answer path. - if (frame.has_offer()) { - ReceiveOffer(remote_peer_id, - SessionDescriptionWrapper( - webrtc_frames::DecodeOffer(frame).release())); - SendAnswer(remote_peer_id); - } else if (frame.has_ice_candidates()) { - ReceiveIceCandidates(remote_peer_id, - webrtc_frames::DecodeIceCandidates(frame)); - } else { - NEARBY_LOG(INFO, "Received unknown WebRTC frame: ignoring."); - } - } else if (IsAcceptingConnectionsLocked(service_id)) { - // We don't have an outgoing connection request with this peer, but we are - // accepting incoming requests so we'll only process the Offer path. - if (frame.has_ready_for_signaling_poke()) { - SendOffer(service_id, remote_peer_id); - } else if (frame.has_answer()) { - ReceiveAnswer(remote_peer_id, - SessionDescriptionWrapper( - webrtc_frames::DecodeAnswer(frame).release())); - } else if (frame.has_ice_candidates()) { - ReceiveIceCandidates(remote_peer_id, - webrtc_frames::DecodeIceCandidates(frame)); - } else { - NEARBY_LOG(INFO, "Received unknown WebRTC frame: ignoring."); - } - } else { - NEARBY_LOG( - INFO, - "Ignoring Tachyon message since we are not accepting connections."); - } -} - -void WebRtc::SendOffer(const std::string& service_id, - const WebrtcPeerId& remote_peer_id) { - std::unique_ptr<ConnectionFlow> connection_flow = - CreateConnectionFlow(service_id, remote_peer_id); - if (!connection_flow) { - NEARBY_LOG(INFO, - "Unable to send offer. Failed to create a ConnectionFlow."); - return; - } - - SessionDescriptionWrapper offer = connection_flow->CreateOffer(); - if (!offer.IsValid()) { - NEARBY_LOG(INFO, - "Unable to send offer. Failed to create our offer locally."); - RemoveConnectionFlow(remote_peer_id); - return; - } - - const webrtc::SessionDescriptionInterface& sdp = offer.GetSdp(); - if (!connection_flow->SetLocalSessionDescription(offer)) { - NEARBY_LOG(INFO, - "Unable to send offer. Failed to register our offer locally."); - RemoveConnectionFlow(remote_peer_id); - return; - } - - // Grab our info from the map. - auto& info = accepting_connections_info_.find(service_id)->second; - - // Pass the offer to the remote side. - if (!info.signaling_messenger->SendMessage( - remote_peer_id.GetId(), - webrtc_frames::EncodeOffer(info.self_peer_id, sdp))) { - NEARBY_LOG(INFO, - "Unable to send offer. Failed to write the offer to the remote " - "peer %s.", - remote_peer_id.GetId().c_str()); - RemoveConnectionFlow(remote_peer_id); - return; - } - - // Store the ConnectionFlow so that other methods can use it later. - connection_flows_.emplace(remote_peer_id.GetId(), std::move(connection_flow)); - NEARBY_LOG(INFO, "Sent offer to %s.", remote_peer_id.GetId().c_str()); -} - -void WebRtc::ReceiveOffer(const WebrtcPeerId& remote_peer_id, - SessionDescriptionWrapper offer) { - const auto& entry = connection_flows_.find(remote_peer_id.GetId()); - if (entry == connection_flows_.end()) { - NEARBY_LOG(INFO, - "Unable to receive offer. Failed to create a ConnectionFlow."); - return; - } - - if (!entry->second->OnOfferReceived(offer)) { - NEARBY_LOG(INFO, "Unable to receive offer. Failed to process the offer."); - RemoveConnectionFlow(remote_peer_id); - } -} - -void WebRtc::SendAnswer(const WebrtcPeerId& remote_peer_id) { - const auto& entry = connection_flows_.find(remote_peer_id.GetId()); - if (entry == connection_flows_.end()) { - NEARBY_LOG(INFO, - "Unable to send answer. Failed to create a ConnectionFlow."); - return; - } - - SessionDescriptionWrapper answer = entry->second->CreateAnswer(); - if (!answer.IsValid()) { - NEARBY_LOG(INFO, - "Unable to send answer. Failed to create our answer locally."); - RemoveConnectionFlow(remote_peer_id); - return; - } - - const webrtc::SessionDescriptionInterface& sdp = answer.GetSdp(); - if (!entry->second->SetLocalSessionDescription(answer)) { - NEARBY_LOG(INFO, - "Unable to send answer. Failed to register our answer locally."); - RemoveConnectionFlow(remote_peer_id); - return; - } - - // Grab our info from the map. - const auto& connection_request_entry = - requesting_connections_info_.find(remote_peer_id.GetId()); - if (connection_request_entry == requesting_connections_info_.end()) { - NEARBY_LOG(INFO, - "Unable to send answer. Failed to find an outgoing connection " - "request."); - RemoveConnectionFlow(remote_peer_id); - return; - } - - // Pass the answer to the remote side. - if (!connection_request_entry->second.signaling_messenger->SendMessage( - remote_peer_id.GetId(), - webrtc_frames::EncodeAnswer( - connection_request_entry->second.self_peer_id, sdp))) { - NEARBY_LOG( - INFO, - "Unable to send answer. Failed to write the answer to the remote " - "peer %s.", - remote_peer_id.GetId().c_str()); - RemoveConnectionFlow(remote_peer_id); - return; - } - - NEARBY_LOG(INFO, "Sent answer to %s.", remote_peer_id.GetId().c_str()); -} - -void WebRtc::ReceiveAnswer(const WebrtcPeerId& remote_peer_id, - SessionDescriptionWrapper answer) { - const auto& entry = connection_flows_.find(remote_peer_id.GetId()); - if (entry == connection_flows_.end()) { - NEARBY_LOG(INFO, - "Unable to receive answer. Failed to create a ConnectionFlow."); - return; - } - - if (!entry->second->OnAnswerReceived(answer)) { - NEARBY_LOG(INFO, "Unable to receive answer. Failed to process the answer."); - RemoveConnectionFlow(remote_peer_id); - } -} - -void WebRtc::ReceiveIceCandidates( - const WebrtcPeerId& remote_peer_id, - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> - ice_candidates) { - const auto& entry = connection_flows_.find(remote_peer_id.GetId()); - if (entry == connection_flows_.end()) { - NEARBY_LOG( - INFO, - "Unable to receive ice candidates. Failed to create a ConnectionFlow."); - return; - } - - entry->second->OnRemoteIceCandidatesReceived(std::move(ice_candidates)); -} - -void WebRtc::ProcessRestartTachyonReceiveMessages( - const std::string& service_id) { - MutexLock lock(&mutex_); - RestartTachyonReceiveMessages(service_id); -} - -void WebRtc::RestartTachyonReceiveMessages(const std::string& service_id) { - if (!IsAcceptingConnectionsLocked(service_id)) { - NEARBY_LOG(INFO, - "Skipping restart listening for tachyon inbox messages since we " - "are not accepting connections for service %s.", - service_id.c_str()); - return; - } - - // Grab our info from the map. - auto& info = accepting_connections_info_.find(service_id)->second; - - // Ensure we've disconnected from Tachyon. - info.signaling_messenger->StopReceivingMessages(); - - // Attempt to re-register. - if (!info.signaling_messenger->StartReceivingMessages( - absl::bind_front(&WebRtc::OnSignalingMessage, this, service_id), - absl::bind_front(&WebRtc::OnSignalingComplete, this, service_id))) { - NEARBY_LOG(WARNING, - "Failed to restart listening for tachyon inbox messages for " - "service %s since we failed to reach Tachyon.", - service_id.c_str()); - return; - } - - NEARBY_LOG(INFO, - "Successfully restarted listening for tachyon inbox messages on " - "service %s.", - service_id.c_str()); -} - -void WebRtc::ProcessDataChannelOpen(const std::string& service_id, - const WebrtcPeerId& remote_peer_id, - WebRtcSocketWrapper socket_wrapper) { - MutexLock lock(&mutex_); - - // Notify the client of the newly formed socket. - const auto& connection_request_entry = - requesting_connections_info_.find(remote_peer_id.GetId()); - if (connection_request_entry != requesting_connections_info_.end()) { - connection_request_entry->second.socket_future.Set(socket_wrapper); - return; - } - - const auto& accepting_connection_entry = - accepting_connections_info_.find(service_id); - if (accepting_connection_entry != accepting_connections_info_.end()) { - accepting_connection_entry->second.accepted_connection_callback.accepted_cb( - socket_wrapper); - return; - } - - // No one to handle the newly created DataChannel, so we'll just close it. - socket_wrapper.Close(); - NEARBY_LOG(INFO, - "Ignoring new DataChannel because we " - "are not accepting connections for service %s.", - service_id.c_str()); -} - -void WebRtc::ProcessDataChannelClosed(const WebrtcPeerId& remote_peer_id) { - MutexLock lock(&mutex_); - NEARBY_LOG(INFO, - "Data channel has closed, removing connection flow for peer %s.", - remote_peer_id.GetId().c_str()); - - RemoveConnectionFlow(remote_peer_id); -} - -std::unique_ptr<ConnectionFlow> WebRtc::CreateConnectionFlow( - const std::string& service_id, const WebrtcPeerId& remote_peer_id) { - RemoveConnectionFlow(remote_peer_id); - - return ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - {[this, service_id, remote_peer_id]( - const webrtc::IceCandidateInterface* ice_candidate) { - // Note: We need to encode the ice candidate here, before we jump - // off the thread. Otherwise, it gets destroyed and we can't read - // it later. - ::location::nearby::mediums::IceCandidate encoded_ice_candidate = - webrtc_frames::EncodeIceCandidate(*ice_candidate); - OffloadFromThread( - "rtc-ice-candidates", - [this, service_id, remote_peer_id, encoded_ice_candidate]() { - ProcessLocalIceCandidate(service_id, remote_peer_id, - encoded_ice_candidate); - }); - }}}, - { - .data_channel_open_cb = {[this, service_id, remote_peer_id]( - WebRtcSocketWrapper socket_wrapper) { - OffloadFromThread( - "rtc-channel-created", - [this, service_id, remote_peer_id, socket_wrapper]() { - ProcessDataChannelOpen(service_id, remote_peer_id, - socket_wrapper); - }); - }}, - .data_channel_closed_cb = {[this, remote_peer_id]() { - OffloadFromThread("rtc-channel-closed", [this, remote_peer_id]() { - ProcessDataChannelClosed(remote_peer_id); - }); - }}, - }, - medium_); -} - -void WebRtc::RemoveConnectionFlow(const WebrtcPeerId& remote_peer_id) { - if (!connection_flows_.erase(remote_peer_id.GetId())) { - return; - } - - // If we had an outgoing connection request w/ this peer, report the failure - // to the future that's being waited on. - const auto& connection_request_entry = - requesting_connections_info_.find(remote_peer_id.GetId()); - if (connection_request_entry != requesting_connections_info_.end()) { - connection_request_entry->second.socket_future.SetException( - {Exception::kFailed}); - } -} - -void WebRtc::OffloadFromThread(const std::string& name, Runnable runnable) { - single_thread_executor_.Execute(name, std::move(runnable)); -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc.h deleted file mode 100644 index b5fb959af11..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc.h +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_H_ - -#include <cstddef> -#include <functional> -#include <memory> -#include <string> - -#include "absl/container/flat_hash_map.h" -#include "absl/container/flat_hash_set.h" -#include "core/internal/mediums/webrtc/connection_flow.h" -#include "core/internal/mediums/webrtc/data_channel_listener.h" -#include "core/internal/mediums/webrtc/local_ice_candidate_listener.h" -#include "core/internal/mediums/webrtc/webrtc_socket.h" -#include "core/internal/mediums/webrtc_peer_id.h" -#include "core/internal/mediums/webrtc_socket_wrapper.h" -#include "platform/base/byte_array.h" -#include "platform/base/cancellation_flag.h" -#include "platform/base/listeners.h" -#include "platform/base/runnable.h" -#include "platform/public/atomic_boolean.h" -#include "platform/public/cancelable_alarm.h" -#include "platform/public/future.h" -#include "platform/public/mutex.h" -#include "platform/public/scheduled_executor.h" -#include "platform/public/single_thread_executor.h" -#include "platform/public/webrtc.h" -#include "proto/connections/offline_wire_formats.pb.h" -#include "proto/mediums/web_rtc_signaling_frames.pb.h" -#include "webrtc/api/jsep.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -// Callback that is invoked when a new connection is accepted. -struct AcceptedConnectionCallback { - std::function<void(WebRtcSocketWrapper socket)> accepted_cb = - DefaultCallback<WebRtcSocketWrapper>(); -}; - -// Entry point for connecting a data channel between two devices via WebRtc. -class WebRtc { - public: - WebRtc(); - ~WebRtc(); - - // Gets the default two-letter country code associated with current locale. - // For example, en_US locale resolves to "US". - const std::string GetDefaultCountryCode(); - - // Returns if WebRtc is available as a medium for nearby to transport data. - // Runs on @MainThread. - bool IsAvailable(); - - // Returns if the device is accepting connection with specific service id. - // Runs on @MainThread. - bool IsAcceptingConnections(const std::string& service_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Prepares the device to accept incoming WebRtc connections. Returns a - // boolean value indicating if the device has started accepting connections. - // Runs on @MainThread. - bool StartAcceptingConnections(const std::string& service_id, - const WebrtcPeerId& self_peer_id, - const LocationHint& location_hint, - AcceptedConnectionCallback callback) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Try to stop (accepting) the specific connection with provided service id. - // Runs on @MainThread - void StopAcceptingConnections(const std::string& service_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Initiates a WebRtc connection with peer device identified by |peer_id| - // with internal retry for maximum attempts of kConnectAttemptsLimit. - // Runs on @MainThread. - WebRtcSocketWrapper Connect(const std::string& service_id, - const WebrtcPeerId& peer_id, - const LocationHint& location_hint, - CancellationFlag* cancellation_flag) - ABSL_LOCKS_EXCLUDED(mutex_); - - private: - static constexpr int kConnectAttemptsLimit = 3; - static constexpr int kRestartAcceptConnectionsLimit = 3; - - enum class Role { - kNone = 0, - kOfferer = 1, - kAnswerer = 2, - }; - - struct AcceptingConnectionsInfo { - // The self_peer_id is generated from the BT/WiFi advertisements and allows - // the scanner to message us over Tachyon. - WebrtcPeerId self_peer_id; - - // The registered callback. When there's an incoming connection, this - // callback is notified. - AcceptedConnectionCallback accepted_connection_callback; - - // Allows us to communicate with the Tachyon web server. - std::unique_ptr<WebRtcSignalingMessenger> signaling_messenger; - - // Restarts the tachyon inbox receives messages streaming rpc if the - // streaming rpc times out. The streaming rpc times out after 60s while - // advertising. Non-null when listening for WebRTC connections as an - // offerer. - CancelableAlarm restart_tachyon_receive_messages_alarm; - - // Tracks the number of times we've restarted receiving messages after a - // failure. We limit the number to prevent endless restarts if we are - // repeatedly unable to communicate with Tachyon. - int restart_accept_connections_count = 0; - }; - - struct ConnectionRequestInfo { - // The self_peer_id is randomly generated and allows the advertiser to - // message us over Tachyon. - WebrtcPeerId self_peer_id; - - // Allows us to communicate with the Tachyon web server. - std::unique_ptr<WebRtcSignalingMessenger> signaling_messenger; - - // The pending DataChannel future. Our client will be blocked on this while - // they wait for us to set up the channel over Tachyon. - Future<WebRtcSocketWrapper> socket_future; - }; - - // Attempt to initiates a WebRtc connection with peer device identified by - // |peer_id|. - // Runs on @MainThread. - WebRtcSocketWrapper AttemptToConnect(const std::string& service_id, - const WebrtcPeerId& peer_id, - const LocationHint& location_hint, - CancellationFlag* cancellation_flag) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns if the device is accepting connection with specific service id. - // Runs on @MainThread. - bool IsAcceptingConnectionsLocked(const std::string& service_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Receives a message from the signaling messenger. - void OnSignalingMessage(const std::string& service_id, - const ByteArray& message); - - // Decides whether to restart receiving messages. - void OnSignalingComplete(const std::string& service_id, bool success); - - // Runs on |single_thread_executor_|. - void ProcessTachyonInboxMessage(const std::string& service_id, - const ByteArray& message) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Runs on |single_thread_executor_|. - void SendOffer(const std::string& service_id, - const WebrtcPeerId& remote_peer_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void ReceiveOffer(const WebrtcPeerId& remote_peer_id, - SessionDescriptionWrapper offer) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void SendAnswer(const WebrtcPeerId& remote_peer_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void ReceiveAnswer(const WebrtcPeerId& remote_peer_id, - SessionDescriptionWrapper answer) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void ReceiveIceCandidates( - const WebrtcPeerId& remote_peer_id, - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> - ice_candidates) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - std::unique_ptr<ConnectionFlow> CreateConnectionFlow( - const std::string& service_id, const WebrtcPeerId& remote_peer_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - std::unique_ptr<ConnectionFlow> GetConnectionFlow( - const WebrtcPeerId& remote_peer_id) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void RemoveConnectionFlow(const WebrtcPeerId& remote_peer_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void ProcessDataChannelOpen(const std::string& service_id, - const WebrtcPeerId& remote_peer_id, - WebRtcSocketWrapper socket_wrapper) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Runs on |single_thread_executor_|. - void ProcessDataChannelClosed(const WebrtcPeerId& remote_peer_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Runs on |single_thread_executor_|. - void ProcessLocalIceCandidate( - const std::string& service_id, const WebrtcPeerId& remote_peer_id, - const ::location::nearby::mediums::IceCandidate ice_candidate) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Runs on |single_thread_executor_|. - void ProcessRestartTachyonReceiveMessages(const std::string& service_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Runs on |single_thread_executor_|. - void RestartTachyonReceiveMessages(const std::string& service_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - void OffloadFromThread(const std::string& name, Runnable runnable); - - Mutex mutex_; - - WebRtcMedium medium_; - - // The single thread we throw the potentially blocking work on to. - ScheduledExecutor single_thread_executor_; - - // A map of ServiceID -> State for all services that are listening for - // incoming connections. - absl::flat_hash_map<std::string, AcceptingConnectionsInfo> - accepting_connections_info_ ABSL_GUARDED_BY(mutex_); - - // A map of a remote PeerId -> State for pending connection requests. As - // messages from Tachyon come in, this lets us look up the connection request - // info to handle the interaction. - absl::flat_hash_map<std::string, ConnectionRequestInfo> - requesting_connections_info_ ABSL_GUARDED_BY(mutex_); - - // A map of a remote PeerId -> ConnectionFlow. For each connection, we create - // a unique ConnectionFlow. - absl::flat_hash_map<std::string, std::unique_ptr<ConnectionFlow>> - connection_flows_ ABSL_GUARDED_BY(mutex_); -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/BUILD b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/BUILD deleted file mode 100644 index 9e13e8b8359..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/BUILD +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -licenses(["notice"]) - -cc_library( - name = "webrtc", - srcs = [ - "connection_flow.cc", - "signaling_frames.cc", - ], - hdrs = [ - "connection_flow.h", - "data_channel_listener.h", - "local_ice_candidate_listener.h", - "session_description_wrapper.h", - "signaling_frames.h", - ], - compatible_with = ["//buildenv/target:non_prod"], - copts = ["-DCORE_ADAPTER_DLL"], - visibility = [ - "//core/internal:__subpackages__", - ], - deps = [ - ":data_types", - "//absl/memory", - "//absl/time", - "//core:core_types", - "//core/internal/mediums:utils", - "//platform/base", - "//platform/public:comm", - "//platform/public:logging", - "//platform/public:types", - "//proto/mediums:web_rtc_signaling_frames_cc_proto", - "//webrtc/api:libjingle_peerconnection_api", - "//third_party/webrtc/files/stable/webrtc/pc:peerconnection", - ], -) - -cc_library( - name = "data_types", - srcs = [ - "webrtc_socket.cc", - ], - hdrs = [ - "webrtc_socket.h", - ], - compatible_with = ["//buildenv/target:non_prod"], - copts = ["-DCORE_ADAPTER_DLL"], - visibility = [ - "//core/internal:__subpackages__", - ], - deps = [ - "//core:core_types", - "//platform/base", - "//platform/public:types", - "//webrtc/api:libjingle_peerconnection_api", - ], -) - -cc_test( - name = "webrtc_test", - timeout = "short", - srcs = [ - "connection_flow_test.cc", - "signaling_frames_test.cc", - "webrtc_socket_test.cc", - ], - tags = [ - "notsan", # NOTE(b/139734036): known data race in usrsctplib. - "requires-net:external", - ], - deps = [ - ":data_types", - ":webrtc", - "//net/proto2/compat/public:proto2", - "//testing/base/public:gunit_main", - "//absl/time", - "//core/internal/mediums:utils", - "//platform/base", - "//platform/base:test_util", - "//platform/impl/g3", # buildcleaner: keep - "//platform/public:comm", - "//platform/public:types", - "//webrtc/api:libjingle_peerconnection_api", - "//webrtc/api:rtc_error", - "//webrtc/api:scoped_refptr", - ], -) diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/connection_flow.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/connection_flow.cc deleted file mode 100644 index 2906645348f..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/connection_flow.cc +++ /dev/null @@ -1,556 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/webrtc/connection_flow.h" - -#include <iterator> -#include <memory> - -#include "absl/memory/memory.h" -#include "absl/time/time.h" -#include "core/internal/mediums/webrtc/session_description_wrapper.h" -#include "core/internal/mediums/webrtc/webrtc_socket.h" -#include "core/internal/mediums/webrtc_socket_wrapper.h" -#include "platform/public/logging.h" -#include "platform/public/mutex_lock.h" -#include "platform/public/webrtc.h" -#include "webrtc/api/data_channel_interface.h" -#include "webrtc/api/jsep.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -constexpr absl::Duration ConnectionFlow::kTimeout; -constexpr absl::Duration ConnectionFlow::kPeerConnectionTimeout; - -// This is the same as the nearby data channel name. -constexpr char kDataChannelName[] = "dataChannel"; - -class CreateSessionDescriptionObserverImpl - : public webrtc::CreateSessionDescriptionObserver { - public: - CreateSessionDescriptionObserverImpl( - ConnectionFlow* connection_flow, - Future<SessionDescriptionWrapper> settable_future, - ConnectionFlow::State expected_entry_state, - ConnectionFlow::State exit_state) - : connection_flow_{connection_flow}, - settable_future_{settable_future}, - expected_entry_state_{expected_entry_state}, - exit_state_{exit_state} {} - - // webrtc::CreateSessionDescriptionObserver - void OnSuccess(webrtc::SessionDescriptionInterface* desc) override { - if (connection_flow_->TransitionState(expected_entry_state_, exit_state_)) { - settable_future_.Set(SessionDescriptionWrapper{desc}); - } else { - settable_future_.SetException({Exception::kFailed}); - } - } - - void OnFailure(webrtc::RTCError error) override { - NEARBY_LOG(ERROR, "Error when creating session description: %s", - error.message()); - settable_future_.SetException({Exception::kFailed}); - } - - private: - ConnectionFlow* connection_flow_; - Future<SessionDescriptionWrapper> settable_future_; - ConnectionFlow::State expected_entry_state_; - ConnectionFlow::State exit_state_; -}; - -class SetDescriptionObserverBase { - public: - ExceptionOr<bool> GetResult(absl::Duration timeout) { - return settable_future_.Get(timeout); - } - - protected: - void OnSetDescriptionComplete(webrtc::RTCError error) { - // On success, |error.ok()| is true. - if (error.ok()) { - settable_future_.Set(true); - return; - } - settable_future_.SetException({Exception::kFailed}); - } - - private: - Future<bool> settable_future_; -}; - -class SetLocalDescriptionObserver - : public webrtc::SetLocalDescriptionObserverInterface, - public SetDescriptionObserverBase { - public: - void OnSetLocalDescriptionComplete(webrtc::RTCError error) override { - OnSetDescriptionComplete(error); - } -}; - -class SetRemoteDescriptionObserver - : public webrtc::SetRemoteDescriptionObserverInterface, - public SetDescriptionObserverBase { - public: - void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override { - OnSetDescriptionComplete(error); - } -}; - -using PeerConnectionState = - webrtc::PeerConnectionInterface::PeerConnectionState; - -std::unique_ptr<ConnectionFlow> ConnectionFlow::Create( - LocalIceCandidateListener local_ice_candidate_listener, - DataChannelListener data_channel_listener, WebRtcMedium& webrtc_medium) { - auto connection_flow = absl::WrapUnique( - new ConnectionFlow(std::move(local_ice_candidate_listener), - std::move(data_channel_listener))); - if (connection_flow->InitPeerConnection(webrtc_medium)) { - return connection_flow; - } - - return nullptr; -} - -ConnectionFlow::ConnectionFlow( - LocalIceCandidateListener local_ice_candidate_listener, - DataChannelListener data_channel_listener) - : data_channel_listener_(std::move(data_channel_listener)), - local_ice_candidate_listener_(std::move(local_ice_candidate_listener)) {} - -ConnectionFlow::~ConnectionFlow() { - NEARBY_LOG(INFO, "~ConnectionFlow"); - RunOnSignalingThread([this] { CloseOnSignalingThread(); }); - shutdown_latch_.Await(); - NEARBY_LOG(INFO, "~ConnectionFlow done"); -} - -SessionDescriptionWrapper ConnectionFlow::CreateOffer() { - CHECK(!IsRunningOnSignalingThread()); - Future<SessionDescriptionWrapper> success_future; - if (!RunOnSignalingThread([this, success_future] { - CreateOfferOnSignalingThread(success_future); - })) { - NEARBY_LOG(ERROR, "Failed to create offer"); - return SessionDescriptionWrapper(); - } - ExceptionOr<SessionDescriptionWrapper> result = success_future.Get(kTimeout); - if (result.ok()) { - return std::move(result.result()); - } - NEARBY_LOG(ERROR, "Failed to create offer: %d", result.exception()); - return SessionDescriptionWrapper(); -} - -void ConnectionFlow::CreateOfferOnSignalingThread( - Future<SessionDescriptionWrapper> success_future) { - if (!TransitionState(State::kInitialized, State::kCreatingOffer)) { - success_future.SetException({Exception::kFailed}); - return; - } - webrtc::DataChannelInit data_channel_init; - data_channel_init.reliable = true; - auto pc = GetPeerConnection(); - CreateSocketFromDataChannel( - pc->CreateDataChannel(kDataChannelName, &data_channel_init)); - - webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options; - rtc::scoped_refptr<CreateSessionDescriptionObserverImpl> observer = - new rtc::RefCountedObject<CreateSessionDescriptionObserverImpl>( - this, success_future, State::kCreatingOffer, - State::kWaitingForAnswer); - pc->CreateOffer(observer, options); -} - -SessionDescriptionWrapper ConnectionFlow::CreateAnswer() { - CHECK(!IsRunningOnSignalingThread()); - Future<SessionDescriptionWrapper> success_future; - if (!RunOnSignalingThread([this, success_future] { - CreateAnswerOnSignalingThread(success_future); - })) { - NEARBY_LOG(ERROR, "Failed to create answer"); - return SessionDescriptionWrapper(); - } - ExceptionOr<SessionDescriptionWrapper> result = success_future.Get(kTimeout); - if (result.ok()) { - return std::move(result.result()); - } - NEARBY_LOG(ERROR, "Failed to create answer: %d", result.exception()); - return SessionDescriptionWrapper(); -} - -void ConnectionFlow::CreateAnswerOnSignalingThread( - Future<SessionDescriptionWrapper> success_future) { - if (!TransitionState(State::kReceivedOffer, State::kCreatingAnswer)) { - success_future.SetException({Exception::kFailed}); - return; - } - webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options; - rtc::scoped_refptr<CreateSessionDescriptionObserverImpl> observer = - new rtc::RefCountedObject<CreateSessionDescriptionObserverImpl>( - this, success_future, State::kCreatingAnswer, - State::kWaitingToConnect); - auto pc = GetPeerConnection(); - pc->CreateAnswer(observer, options); -} - -bool ConnectionFlow::SetLocalSessionDescription(SessionDescriptionWrapper sdp) { - CHECK(!IsRunningOnSignalingThread()); - if (!sdp.IsValid()) return false; - - rtc::scoped_refptr<SetLocalDescriptionObserver> observer = - new rtc::RefCountedObject<SetLocalDescriptionObserver>(); - - if (!RunOnSignalingThread([this, observer, sdp = std::move(sdp)]() mutable { - if (state_ == State::kEnded) { - observer->OnSetLocalDescriptionComplete( - webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE)); - return; - } - auto pc = GetPeerConnection(); - - pc->SetLocalDescription( - std::unique_ptr<webrtc::SessionDescriptionInterface>(sdp.Release()), - observer); - })) { - return false; - } - - ExceptionOr<bool> result = observer->GetResult(kTimeout); - bool success = result.ok() && result.result(); - if (!success) { - NEARBY_LOG(ERROR, "Failed to set local session description: %d", - result.exception()); - } - return success; -} - -bool ConnectionFlow::SetRemoteSessionDescription(SessionDescriptionWrapper sdp, - State expected_entry_state, - State exit_state) { - if (!sdp.IsValid()) return false; - - rtc::scoped_refptr<SetRemoteDescriptionObserver> observer = - new rtc::RefCountedObject<SetRemoteDescriptionObserver>(); - - if (!RunOnSignalingThread([this, observer, sdp = std::move(sdp), - expected_entry_state, exit_state]() mutable { - if (!TransitionState(expected_entry_state, exit_state)) { - observer->OnSetRemoteDescriptionComplete( - webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE)); - return; - } - auto pc = GetPeerConnection(); - - pc->SetRemoteDescription( - std::unique_ptr<webrtc::SessionDescriptionInterface>(sdp.Release()), - observer); - })) { - return false; - } - - ExceptionOr<bool> result = observer->GetResult(kTimeout); - bool success = result.ok() && result.result(); - if (!success) { - NEARBY_LOG(ERROR, "Failed to set remote description: %d", - result.exception()); - } - return success; -} - -bool ConnectionFlow::OnOfferReceived(SessionDescriptionWrapper offer) { - CHECK(!IsRunningOnSignalingThread()); - return SetRemoteSessionDescription(std::move(offer), State::kInitialized, - State::kReceivedOffer); -} - -bool ConnectionFlow::OnAnswerReceived(SessionDescriptionWrapper answer) { - CHECK(!IsRunningOnSignalingThread()); - return SetRemoteSessionDescription( - std::move(answer), State::kWaitingForAnswer, State::kWaitingToConnect); -} - -bool ConnectionFlow::OnRemoteIceCandidatesReceived( - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> - ice_candidates) { - CHECK(!IsRunningOnSignalingThread()); - // We can't call RunOnSignalingThread because C++ wants to copy ice_candidates - // if we try. unique_ptr is not CopyConstructible and compilation fails. - auto pc = GetPeerConnection(); - - if (!pc) { - return false; - } - pc->signaling_thread()->PostTask( - RTC_FROM_HERE, [this, can_run_tasks = std::weak_ptr<void>(can_run_tasks_), - candidates = std::move(ice_candidates)]() mutable { - // don't run the task if the weak_ptr is no longer valid. - if (!can_run_tasks.lock()) { - return; - } - AddIceCandidatesOnSignalingThread(std::move(candidates)); - }); - return true; -} - -void ConnectionFlow::AddIceCandidatesOnSignalingThread( - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> - ice_candidates) { - CHECK(IsRunningOnSignalingThread()); - if (state_ == State::kEnded) { - NEARBY_LOG(WARNING, - "You cannot add ice candidates to a disconnected session."); - return; - } - if (state_ != State::kWaitingToConnect && state_ != State::kConnected) { - cached_remote_ice_candidates_.insert( - cached_remote_ice_candidates_.end(), - std::make_move_iterator(ice_candidates.begin()), - std::make_move_iterator(ice_candidates.end())); - return; - } - auto pc = GetPeerConnection(); - for (auto&& ice_candidate : ice_candidates) { - if (!pc->AddIceCandidate(ice_candidate.get())) { - NEARBY_LOG(WARNING, "Unable to add remote ice candidate."); - } - } -} - -bool ConnectionFlow::CloseIfNotConnected() { - CHECK(!IsRunningOnSignalingThread()); - Future<bool> closed; - if (RunOnSignalingThread([this, closed]() mutable { - if (state_ == State::kConnected) { - closed.Set(false); - } else { - CloseOnSignalingThread(); - closed.Set(true); - } - })) { - auto result = closed.Get(); - return result.ok() && result.result(); - } - return true; -} - -bool ConnectionFlow::InitPeerConnection(WebRtcMedium& webrtc_medium) { - Future<bool> success_future; - // CreatePeerConnection callback may be invoked after ConnectionFlow lifetime - // has ended, in case of a timeout. Future is captured by value, and is safe - // to access, but it is not safe to access ConnectionFlow member variables - // unless the Future::Set() returns true. - webrtc_medium.CreatePeerConnection( - this, - [this, success_future](rtc::scoped_refptr<webrtc::PeerConnectionInterface> - peer_connection) mutable { - if (!peer_connection) { - success_future.Set(false); - return; - } - - // If this fails, means we have already assigned something to - // success_future; it is either: - // 1) this is the 2nd call of this callback (and this is a bug), or - // 2) Get(timeout) has set the future value as exception already. - if (success_future.IsSet()) return; - MutexLock lock(&mutex_); - peer_connection_ = peer_connection; - signaling_thread_for_dcheck_only_ = - peer_connection_->signaling_thread(); - success_future.Set(true); - }); - - ExceptionOr<bool> result = success_future.Get(kPeerConnectionTimeout); - bool success = result.ok() && result.result(); - if (!success) { - shutdown_latch_.CountDown(); - NEARBY_LOG(ERROR, "Failed to create peer connection: %d", - result.exception()); - } - return success; -} - -void ConnectionFlow::OnSignalingStable() { - if (state_ != State::kWaitingToConnect && state_ != State::kConnected) return; - auto pc = GetPeerConnection(); - for (auto&& ice_candidate : cached_remote_ice_candidates_) { - if (!pc->AddIceCandidate(ice_candidate.get())) { - NEARBY_LOG(WARNING, "Unable to add remote ice candidate."); - } - } - cached_remote_ice_candidates_.clear(); -} - -void ConnectionFlow::CreateSocketFromDataChannel( - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) { - NEARBY_LOG(INFO, "Creating data channel socket"); - auto socket = - std::make_unique<WebRtcSocket>("WebRtcSocket", std::move(data_channel)); - socket->SetSocketListener({ - .socket_ready_cb = {[this](WebRtcSocket* socket) { - CHECK(IsRunningOnSignalingThread()); - if (!TransitionState(State::kWaitingToConnect, State::kConnected)) { - NEARBY_LOG(ERROR, - "Data channel socket is open but connection flow was not " - "in the required state"); - socket->Close(); - return; - } - // Pass socket wrapper by copy on purpose - data_channel_listener_.data_channel_open_cb(socket_wrapper_); - }}, - .socket_closed_cb = [callback = - data_channel_listener_.data_channel_closed_cb]( - WebRtcSocket*) { callback(); }, - }); - socket_wrapper_ = WebRtcSocketWrapper(std::move(socket)); -} - -void ConnectionFlow::OnIceCandidate( - const webrtc::IceCandidateInterface* candidate) { - CHECK(IsRunningOnSignalingThread()); - local_ice_candidate_listener_.local_ice_candidate_found_cb(candidate); -} - -void ConnectionFlow::OnSignalingChange( - webrtc::PeerConnectionInterface::SignalingState new_state) { - NEARBY_LOG(INFO, "OnSignalingChange: %d", new_state); - CHECK(IsRunningOnSignalingThread()); - if (new_state == webrtc::PeerConnectionInterface::SignalingState::kStable) { - OnSignalingStable(); - } -} - -void ConnectionFlow::OnDataChannel( - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) { - NEARBY_LOG(INFO, "OnDataChannel"); - CHECK(IsRunningOnSignalingThread()); - CreateSocketFromDataChannel(std::move(data_channel)); -} - -void ConnectionFlow::OnIceGatheringChange( - webrtc::PeerConnectionInterface::IceGatheringState new_state) { - NEARBY_LOG(INFO, "OnIceGatheringChange: %d", new_state); - CHECK(IsRunningOnSignalingThread()); -} - -void ConnectionFlow::OnConnectionChange( - webrtc::PeerConnectionInterface::PeerConnectionState new_state) { - NEARBY_LOG(INFO, "OnConnectionChange: %d", new_state); - CHECK(IsRunningOnSignalingThread()); - if (new_state == PeerConnectionState::kClosed || - new_state == PeerConnectionState::kFailed || - new_state == PeerConnectionState::kDisconnected) { - NEARBY_LOG(INFO, "Closing due to peer connection state change: %d", - new_state); - CloseOnSignalingThread(); - } -} - -void ConnectionFlow::OnRenegotiationNeeded() { - NEARBY_LOG(INFO, "OnRenegotiationNeeded"); - CHECK(IsRunningOnSignalingThread()); -} - -bool ConnectionFlow::TransitionState(State current_state, State new_state) { - CHECK(IsRunningOnSignalingThread()); - if (current_state != state_) { - NEARBY_LOG( - WARNING, - "Invalid state transition to %d: current state is %d but expected %d.", - new_state, state_, current_state); - return false; - } - NEARBY_LOG(INFO, "Transition: %d -> %d", state_, new_state); - state_ = new_state; - return true; -} - -bool ConnectionFlow::CloseOnSignalingThread() { - if (state_ == State::kEnded) { - return false; - } - state_ = State::kEnded; - // This prevents other tasks from queuing on the signaling thread for this - // object. - auto pc = GetAndResetPeerConnection(); - - NEARBY_LOG(INFO, "Closing WebRTC peer connection."); - // NOTE: Closing the peer conection will close the data channel and thus the - // socket implicitly. - if (pc) pc->Close(); - NEARBY_LOG(INFO, "Closed WebRTC peer connection."); - // Prevent any already queued tasks from running on the signaling thread - can_run_tasks_.reset(); - // If anyone was waiting for shutdown to be done let them know. - shutdown_latch_.CountDown(); - return true; -} - -bool ConnectionFlow::RunOnSignalingThread(Runnable&& runnable) { - CHECK(!IsRunningOnSignalingThread()); - auto pc = GetPeerConnection(); - if (!pc) { - NEARBY_LOG(WARNING, - "Peer connection not available. Cannot schedule tasks."); - return false; - } - // We are off signaling thread, so we can't use peer connection's methods - // but we can access the signaling thread handle. - pc->signaling_thread()->PostTask( - RTC_FROM_HERE, [can_run_tasks = std::weak_ptr<void>(can_run_tasks_), - task = std::move(runnable)] { - // don't run the task if the weak_ptr is no longer valid. - // shared_ptr |can_run_tasks_| is destroyed on the same thread - // (signaling thread). This guarantees that if the weak_ptr is valid - // when this task starts, it will stay valid until the task ends. - if (!can_run_tasks.lock()) { - NEARBY_LOG(INFO, "Peer connection already closed. Cannot run tasks."); - return; - } - task(); - }); - return true; -} - -bool ConnectionFlow::IsRunningOnSignalingThread() { - return signaling_thread_for_dcheck_only_ != nullptr && - signaling_thread_for_dcheck_only_ == rtc::Thread::Current(); -} - -rtc::scoped_refptr<webrtc::PeerConnectionInterface> -ConnectionFlow::GetPeerConnection() { - // We must use a mutex to ensure that peer connection is - // fully initialized. - // We increase the peer_connection_'s refcount to keep it - // alive while we use it. - MutexLock lock(&mutex_); - return peer_connection_; -} - -rtc::scoped_refptr<webrtc::PeerConnectionInterface> -ConnectionFlow::GetAndResetPeerConnection() { - MutexLock lock(&mutex_); - return std::move(peer_connection_); -} -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/connection_flow.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/connection_flow.h deleted file mode 100644 index 474a1829bda..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/connection_flow.h +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_CONNECTION_FLOW_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_CONNECTION_FLOW_H_ - -#include <memory> - -#include "core/internal/mediums/webrtc/data_channel_listener.h" -#include "core/internal/mediums/webrtc/local_ice_candidate_listener.h" -#include "core/internal/mediums/webrtc/session_description_wrapper.h" -#include "core/internal/mediums/webrtc_socket_wrapper.h" -#include "platform/base/runnable.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/single_thread_executor.h" -#include "platform/public/webrtc.h" -#include "webrtc/api/data_channel_interface.h" -#include "webrtc/api/peer_connection_interface.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -/** - * Flow for an offerer: - * - * <ul> - * <li>INITIALIZED: After construction. - * <li>CREATING_OFFER: After CreateOffer(). Local ice candidate collection - * begins. - * <li>WAITING_FOR_ANSWER: Until the remote peer sends their answer. - * <li>WAITING_TO_CONNECT: Until the data channel actually connects. Remote - * ice candidates should be added with OnRemoteIceCandidatesReceived as they are - * gathered. - * <li>CONNECTED: We successfully connected to the remote data - * channel. - * <li>ENDED: The final state that can occur from any of the previous - * states if we disconnect at any point in the flow. - * </ul> - * - * <p>Flow for an answerer: - * - * <ul> - * <li>INITIALIZED: After construction. - * <li>RECEIVED_OFFER: After onOfferReceived(). - * <li>CREATING_ANSWER: After CreateAnswer(). Local ice candidate collection - * begins. - * <li>WAITING_TO_CONNECT: Until the data channel actually connects. - * Remote ice candidates should be added with OnRemoteIceCandidatesReceived as - * they are gathered. - * <li>CONNECTED: We successfully connected to the remote - * data channel. - * <li>ENDED: The final state that can occur from any of the - * previous states if we disconnect at any point in the flow. - * </ul> - */ -class ConnectionFlow : public webrtc::PeerConnectionObserver { - public: - enum class State { - kInitialized, - kCreatingOffer, - kWaitingForAnswer, - kReceivedOffer, - kCreatingAnswer, - kWaitingToConnect, - kConnected, - kEnded, - }; - - // This method blocks on the creation of the peer connection object. - // Can be called on any thread but never called on signaling thread. - static std::unique_ptr<ConnectionFlow> Create( - LocalIceCandidateListener local_ice_candidate_listener, - DataChannelListener data_channel_listener, WebRtcMedium& webrtc_medium); - ~ConnectionFlow() override; - - // Create the offer that will be sent to the remote. Mirrors the behaviour of - // PeerConnectionInterface::CreateOffer. - // Can be called on any thread but never called on signaling thread. - SessionDescriptionWrapper CreateOffer() ABSL_LOCKS_EXCLUDED(mutex_); - // Create the answer that will be sent to the remote. Mirrors the behaviour of - // PeerConnectionInterface::CreateAnswer. - // Can be called on any thread but never called on signaling thread. - SessionDescriptionWrapper CreateAnswer() ABSL_LOCKS_EXCLUDED(mutex_); - // Set the local session description. |sdp| was created via CreateOffer() - // or CreateAnswer(). - // Can be called on any thread but never called on signaling thread. - bool SetLocalSessionDescription(SessionDescriptionWrapper sdp) - ABSL_LOCKS_EXCLUDED(mutex_); - // Invoked when an offer was received from a remote; this will set the remote - // session description on the peer connection. Returns true if the offer was - // successfully set as remote session description. - // Can be called on any thread but never called on signaling thread. - bool OnOfferReceived(SessionDescriptionWrapper offer) - ABSL_LOCKS_EXCLUDED(mutex_); - // Invoked when an answer was received from a remote; this will set the remote - // session description on the peer connection. Returns true if the offer was - // successfully set as remote session description. - // Can be called on any thread but never called on signaling thread. - bool OnAnswerReceived(SessionDescriptionWrapper answer) - ABSL_LOCKS_EXCLUDED(mutex_); - // Invoked when an ice candidate was received from a remote; this will add the - // ice candidate to the peer connection if ready or cache it otherwise. - // Can be called on any thread but never called on signaling thread. - bool OnRemoteIceCandidatesReceived( - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> - ice_candidates) ABSL_LOCKS_EXCLUDED(mutex_); - // Close the peer connection and data channel if not connected. - // Can be called on any thread but never called on signaling thread. - bool CloseIfNotConnected() ABSL_LOCKS_EXCLUDED(mutex_); - - // webrtc::PeerConnectionObserver: - // All methods called only on signaling thread. - void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override; - void OnSignalingChange( - webrtc::PeerConnectionInterface::SignalingState new_state) override; - void OnDataChannel( - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) override; - void OnIceGatheringChange( - webrtc::PeerConnectionInterface::IceGatheringState new_state) override; - void OnConnectionChange( - webrtc::PeerConnectionInterface::PeerConnectionState new_state) override; - void OnRenegotiationNeeded() override; - - // Public because it's used in tests too. - rtc::scoped_refptr<webrtc::PeerConnectionInterface> GetPeerConnection(); - - private: - ConnectionFlow(LocalIceCandidateListener local_ice_candidate_listener, - DataChannelListener data_channel_listener); - - // Resets peer connection reference. Returns old value. - rtc::scoped_refptr<webrtc::PeerConnectionInterface> - GetAndResetPeerConnection(); - void CreateOfferOnSignalingThread( - Future<SessionDescriptionWrapper> success_future); - void CreateAnswerOnSignalingThread( - Future<SessionDescriptionWrapper> success_future); - void AddIceCandidatesOnSignalingThread( - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> - ice_candidates); - // Invoked when the peer connection indicates that signaling is stable. - void OnSignalingStable() ABSL_LOCKS_EXCLUDED(mutex_); - - void CreateSocketFromDataChannel( - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel); - - // TODO(bfranz): Consider whether this needs to be configurable per platform - static constexpr absl::Duration kTimeout = absl::Milliseconds(250); - static constexpr absl::Duration kPeerConnectionTimeout = - absl::Milliseconds(2500); - - bool InitPeerConnection(WebRtcMedium& webrtc_medium); - - bool TransitionState(State current_state, State new_state); - - bool SetRemoteSessionDescription(SessionDescriptionWrapper sdp, - State expected_entry_state, - State exit_state); - - bool CloseOnSignalingThread() ABSL_LOCKS_EXCLUDED(mutex_); - - bool RunOnSignalingThread(Runnable&& runnable); - bool IsRunningOnSignalingThread(); - - Mutex mutex_; - // Used to prevent the destructor from returning while the signaling thread is - // still running CloseOnSignalingThread() - CountDownLatch shutdown_latch_{1}; - - // State is used on signaling thread only. - State state_ = State::kInitialized; - // Used to communicate data channel events back to the caller of Create() - DataChannelListener data_channel_listener_; - - LocalIceCandidateListener local_ice_candidate_listener_; - // Peer connection can be used only on signaling thread. The only exception - // is accessing the signaling thread handle. Tasks posted on the - // signaling thread may outlive both |peer_connection_| and |this| objects. - // A mutex is required to access peer connection reference because peer - // connection object and the reference can be initialized on different - // threads - the reference could be initialized before peer connection's - // constructor has finished. - // |peer_connection_| is actually implemented by PeerConnectionProxy, which - // runs the real PeerConnection's methods on the correct thread (signaling or - // worker). If a proxy method is called on the correct thread, then the real - // method is called directly. Otherwise, a task is posted on the correct - // thread and the current thread is blocked until that task finishes. We - // choose to explicitly use |peer_connection_| on the signaling thread, - // because it allows us to do state management on the signaling thread too, - // simplifies locking, and we don't have to block the current thread for every - // peer connection call. - rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_ - ABSL_GUARDED_BY(mutex_); - - // Used to hold a reference to the WebRtcSocket while the data channel is - // connecting. - WebRtcSocketWrapper socket_wrapper_; - - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> - cached_remote_ice_candidates_; - // This pointer is only for DCHECK() assertions. - // It allows us to check if we are running on signaling thread even - // after destroying |peer_connection_|. - const void* signaling_thread_for_dcheck_only_ = nullptr; - // This shared_ptr is reset on the signaling thread when ConnectionFlow is - // closed. This prevents us from running tasks on the signaling thread when - // peer connection is closed. The value stored in |can_run_tasks_| is not - // used. We are using std::shared_ptr instead of rtc::WeakPtrFactory because - // the former is thread-safe. - std::shared_ptr<void> can_run_tasks_ = std::make_shared<int>(); - - friend class CreateSessionDescriptionObserverImpl; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_CONNECTION_FLOW_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/connection_flow_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/connection_flow_test.cc deleted file mode 100644 index dfc98d71f6e..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/connection_flow_test.cc +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/webrtc/connection_flow.h" - -#include <memory> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/time/time.h" -#include "core/internal/mediums/webrtc/session_description_wrapper.h" -#include "core/internal/mediums/webrtc_socket_wrapper.h" -#include "platform/base/byte_array.h" -#include "platform/base/medium_environment.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/webrtc.h" -#include "webrtc/api/data_channel_interface.h" -#include "webrtc/api/jsep.h" -#include "webrtc/api/rtc_error.h" -#include "webrtc/api/scoped_refptr.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { -namespace { - -class ConnectionFlowTest : public ::testing::Test { - protected: - ConnectionFlowTest() { - MediumEnvironment::Instance().Stop(); - MediumEnvironment::Instance().Start({.webrtc_enabled = true}); - } -}; - -std::unique_ptr<webrtc::IceCandidateInterface> CopyCandidate( - const webrtc::IceCandidateInterface* candidate) { - return webrtc::CreateIceCandidate(candidate->sdp_mid(), - candidate->sdp_mline_index(), - candidate->candidate()); -} - -// TODO(bfranz) - Add test that deterministically sends answerer_ice_candidates -// before answer is sent. -TEST_F(ConnectionFlowTest, SuccessfulOfferAnswerFlow) { - WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; - - Future<ByteArray> message_received_future; - - Future<WebRtcSocketWrapper> offerer_socket_future, answerer_socket_future; - - std::unique_ptr<ConnectionFlow> offerer, answerer; - - // Send Ice Candidates immediately when you retrieve them - offerer = ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - [&answerer](const webrtc::IceCandidateInterface* candidate) { - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> vec; - vec.push_back(CopyCandidate(candidate)); - // The callback might be alive while the objects in test are - // destroyed. - if (answerer) - answerer->OnRemoteIceCandidatesReceived(std::move(vec)); - }}, - {.data_channel_open_cb = - [&offerer_socket_future](WebRtcSocketWrapper socket) { - offerer_socket_future.Set(std::move(socket)); - }}, - webrtc_medium_offerer); - ASSERT_NE(offerer, nullptr); - answerer = ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - [&offerer](const webrtc::IceCandidateInterface* candidate) { - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> vec; - vec.push_back(CopyCandidate(candidate)); - // The callback might be alive while the objects in test are - // destroyed. - if (offerer) - offerer->OnRemoteIceCandidatesReceived(std::move(vec)); - }}, - {.data_channel_open_cb = - [&answerer_socket_future](WebRtcSocketWrapper socket) { - answerer_socket_future.Set(std::move(socket)); - }}, - webrtc_medium_answerer); - ASSERT_NE(answerer, nullptr); - - // Create and send offer - SessionDescriptionWrapper offer = offerer->CreateOffer(); - ASSERT_TRUE(offer.IsValid()); - EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - EXPECT_TRUE(answerer->OnOfferReceived(offer)); - EXPECT_TRUE(offerer->SetLocalSessionDescription(std::move(offer))); - - // Create and send answer - SessionDescriptionWrapper answer = answerer->CreateAnswer(); - ASSERT_TRUE(answer.IsValid()); - EXPECT_EQ(answer.GetType(), webrtc::SdpType::kAnswer); - EXPECT_TRUE(offerer->OnAnswerReceived(answer)); - EXPECT_TRUE(answerer->SetLocalSessionDescription(std::move(answer))); - - // Retrieve Data Channels - ExceptionOr<WebRtcSocketWrapper> offerer_socket = - offerer_socket_future.Get(absl::Seconds(1)); - EXPECT_TRUE(offerer_socket.ok()); - ExceptionOr<WebRtcSocketWrapper> answerer_socket = - answerer_socket_future.Get(absl::Seconds(1)); - EXPECT_TRUE(answerer_socket.ok()); - - // Send message on data channel - const char message[] = "Test"; - offerer_socket.result().GetImpl().GetOutputStream().Write( - ByteArray(message, 4)); - ExceptionOr<ByteArray> received_message = - answerer_socket.result().GetImpl().GetInputStream().Read(4); - EXPECT_TRUE(received_message.ok()); - EXPECT_EQ(received_message.result(), ByteArray{message}); -} - -TEST_F(ConnectionFlowTest, CreateAnswerBeforeOfferReceived) { - WebRtcMedium webrtc_medium; - - std::unique_ptr<ConnectionFlow> answerer = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), webrtc_medium); - ASSERT_NE(answerer, nullptr); - - SessionDescriptionWrapper answer = answerer->CreateAnswer(); - EXPECT_FALSE(answer.IsValid()); -} - -TEST_F(ConnectionFlowTest, SetAnswerBeforeOffer) { - WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; - - std::unique_ptr<ConnectionFlow> offerer = - ConnectionFlow::Create(LocalIceCandidateListener(), DataChannelListener(), - webrtc_medium_offerer); - ASSERT_NE(offerer, nullptr); - std::unique_ptr<ConnectionFlow> answerer = - ConnectionFlow::Create(LocalIceCandidateListener(), DataChannelListener(), - webrtc_medium_answerer); - ASSERT_NE(answerer, nullptr); - - SessionDescriptionWrapper offer = offerer->CreateOffer(); - ASSERT_TRUE(offer.IsValid()); - EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - // Did not set offer as local session description - EXPECT_TRUE(answerer->OnOfferReceived(offer)); - - SessionDescriptionWrapper answer = answerer->CreateAnswer(); - ASSERT_TRUE(answer.IsValid()); - EXPECT_EQ(answer.GetType(), webrtc::SdpType::kAnswer); - EXPECT_FALSE(offerer->OnAnswerReceived(answer)); -} - -TEST_F(ConnectionFlowTest, CannotCreateOfferAfterClose) { - WebRtcMedium webrtc_medium; - - std::unique_ptr<ConnectionFlow> offerer = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), webrtc_medium); - ASSERT_NE(offerer, nullptr); - - EXPECT_TRUE(offerer->CloseIfNotConnected()); - - EXPECT_FALSE(offerer->CreateOffer().IsValid()); -} - -TEST_F(ConnectionFlowTest, CannotSetSessionDescriptionAfterClose) { - WebRtcMedium webrtc_medium; - - std::unique_ptr<ConnectionFlow> offerer = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), webrtc_medium); - ASSERT_NE(offerer, nullptr); - - SessionDescriptionWrapper offer = offerer->CreateOffer(); - ASSERT_TRUE(offer.IsValid()); - EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - - EXPECT_TRUE(offerer->CloseIfNotConnected()); - - EXPECT_FALSE(offerer->SetLocalSessionDescription(offer)); -} - -TEST_F(ConnectionFlowTest, CannotReceiveOfferAfterClose) { - WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; - - std::unique_ptr<ConnectionFlow> offerer = - ConnectionFlow::Create(LocalIceCandidateListener(), DataChannelListener(), - webrtc_medium_offerer); - ASSERT_NE(offerer, nullptr); - std::unique_ptr<ConnectionFlow> answerer = - ConnectionFlow::Create(LocalIceCandidateListener(), DataChannelListener(), - webrtc_medium_answerer); - ASSERT_NE(answerer, nullptr); - - EXPECT_TRUE(answerer->CloseIfNotConnected()); - - SessionDescriptionWrapper offer = offerer->CreateOffer(); - ASSERT_TRUE(offer.IsValid()); - EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - - EXPECT_FALSE(answerer->OnOfferReceived(offer)); -} - -TEST_F(ConnectionFlowTest, NullPeerConnection) { - MediumEnvironment::Instance().SetUseValidPeerConnection( - /*use_valid_peer_connection=*/false); - - WebRtcMedium medium; - std::unique_ptr<ConnectionFlow> answerer = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), medium); - EXPECT_EQ(answerer, nullptr); -} - -TEST_F(ConnectionFlowTest, PeerConnectionTimeout) { - MediumEnvironment::Instance().SetUseValidPeerConnection( - /*use_valid_peer_connection=*/true); - WebRtcMedium medium1; - std::unique_ptr<ConnectionFlow> flow1 = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), medium1); - EXPECT_NE(flow1, nullptr); - - // Attempt to trigger the 2.5s peer connection timeout. - MediumEnvironment::Instance().SetPeerConnectionLatency(absl::Seconds(5)); - WebRtcMedium medium2; - std::unique_ptr<ConnectionFlow> flow2 = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), medium2); - EXPECT_EQ(flow2, nullptr); -} - -TEST_F(ConnectionFlowTest, TerminateAnswerer) { - WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; - - Future<ByteArray> message_received_future; - - Future<WebRtcSocketWrapper> offerer_socket_future, answerer_socket_future; - - std::unique_ptr<ConnectionFlow> offerer, answerer; - - // Send Ice Candidates immediately when you retrieve them - offerer = ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - [&answerer](const webrtc::IceCandidateInterface* candidate) { - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> vec; - vec.push_back(CopyCandidate(candidate)); - // The callback might be alive while the objects in test are - // destroyed. - if (answerer) - answerer->OnRemoteIceCandidatesReceived(std::move(vec)); - }}, - {.data_channel_open_cb = - [&offerer_socket_future](WebRtcSocketWrapper socket) { - offerer_socket_future.Set(std::move(socket)); - }}, - webrtc_medium_offerer); - ASSERT_NE(offerer, nullptr); - answerer = ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - [&offerer](const webrtc::IceCandidateInterface* candidate) { - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> vec; - vec.push_back(CopyCandidate(candidate)); - // The callback might be alive while the objects in test are - // destroyed. - if (offerer) - offerer->OnRemoteIceCandidatesReceived(std::move(vec)); - }}, - {.data_channel_open_cb = - [&answerer_socket_future](WebRtcSocketWrapper wrapper) { - answerer_socket_future.Set(std::move(wrapper)); - }}, - webrtc_medium_answerer); - ASSERT_NE(answerer, nullptr); - - // Create and send offer - SessionDescriptionWrapper offer = offerer->CreateOffer(); - ASSERT_TRUE(offer.IsValid()); - EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - EXPECT_TRUE(answerer->OnOfferReceived(offer)); - EXPECT_TRUE(offerer->SetLocalSessionDescription(std::move(offer))); - - // Create and send answer - SessionDescriptionWrapper answer = answerer->CreateAnswer(); - ASSERT_TRUE(answer.IsValid()); - EXPECT_EQ(answer.GetType(), webrtc::SdpType::kAnswer); - EXPECT_TRUE(offerer->OnAnswerReceived(answer)); - EXPECT_TRUE(answerer->SetLocalSessionDescription(std::move(answer))); - - // Retrieve Data Channels - ExceptionOr<WebRtcSocketWrapper> offerer_socket = - offerer_socket_future.Get(absl::Seconds(1)); - EXPECT_TRUE(offerer_socket.ok()); - ExceptionOr<WebRtcSocketWrapper> answerer_socket = - answerer_socket_future.Get(absl::Seconds(1)); - EXPECT_TRUE(offerer_socket.ok()); - - CountDownLatch latch(1); - auto pc = answerer->GetPeerConnection(); - pc->signaling_thread()->PostTask(RTC_FROM_HERE, [pc, latch]() mutable { - pc->Close(); - latch.CountDown(); - }); - latch.Await(); - - // Send message on data channel - std::string message = "Test"; - offerer_socket.result().GetOutputStream().Write(ByteArray{message}); - ExceptionOr<ByteArray> received_message = - answerer_socket.result().GetInputStream().Read(4); - EXPECT_FALSE(received_message.ok()); -} - -TEST_F(ConnectionFlowTest, TerminateOfferer) { - WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; - - Future<ByteArray> message_received_future; - - Future<WebRtcSocketWrapper> offerer_socket_future, answerer_socket_future; - - std::unique_ptr<ConnectionFlow> offerer, answerer; - - // Send Ice Candidates immediately when you retrieve them - offerer = ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - [&answerer](const webrtc::IceCandidateInterface* candidate) { - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> vec; - vec.push_back(CopyCandidate(candidate)); - // The callback might be alive while the objects in test are - // destroyed. - if (answerer) - answerer->OnRemoteIceCandidatesReceived(std::move(vec)); - }}, - {.data_channel_open_cb = - [&offerer_socket_future](WebRtcSocketWrapper socket) { - offerer_socket_future.Set(std::move(socket)); - }}, - webrtc_medium_offerer); - ASSERT_NE(offerer, nullptr); - answerer = ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - [&offerer](const webrtc::IceCandidateInterface* candidate) { - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> vec; - vec.push_back(CopyCandidate(candidate)); - // The callback might be alive while the objects in test are - // destroyed. - if (offerer) - offerer->OnRemoteIceCandidatesReceived(std::move(vec)); - }}, - {.data_channel_open_cb = - [&answerer_socket_future](WebRtcSocketWrapper wrapper) { - answerer_socket_future.Set(std::move(wrapper)); - }}, - webrtc_medium_answerer); - ASSERT_NE(answerer, nullptr); - - // Create and send offer - SessionDescriptionWrapper offer = offerer->CreateOffer(); - ASSERT_TRUE(offer.IsValid()); - EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - EXPECT_TRUE(answerer->OnOfferReceived(offer)); - EXPECT_TRUE(offerer->SetLocalSessionDescription(std::move(offer))); - - // Create and send answer - SessionDescriptionWrapper answer = answerer->CreateAnswer(); - ASSERT_TRUE(answer.IsValid()); - EXPECT_EQ(answer.GetType(), webrtc::SdpType::kAnswer); - EXPECT_TRUE(offerer->OnAnswerReceived(answer)); - EXPECT_TRUE(answerer->SetLocalSessionDescription(std::move(answer))); - - // Retrieve Data Channels - ExceptionOr<WebRtcSocketWrapper> offerer_socket = - offerer_socket_future.Get(absl::Seconds(1)); - EXPECT_TRUE(offerer_socket.ok()); - ExceptionOr<WebRtcSocketWrapper> answerer_socket = - answerer_socket_future.Get(absl::Seconds(1)); - EXPECT_TRUE(offerer_socket.ok()); - - CountDownLatch latch(1); - auto pc = offerer->GetPeerConnection(); - pc->signaling_thread()->PostTask(RTC_FROM_HERE, [pc, latch]() mutable { - pc->Close(); - latch.CountDown(); - }); - latch.Await(); - - // Send message on data channel - std::string message = "Test"; - offerer_socket.result().GetOutputStream().Write(ByteArray{message}); - ExceptionOr<ByteArray> received_message = - answerer_socket.result().GetInputStream().Read(4); - EXPECT_FALSE(received_message.ok()); -} -} // namespace -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/data_channel_listener.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/data_channel_listener.h deleted file mode 100644 index 13e6bb5a02e..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/data_channel_listener.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_DATA_CHANNEL_LISTENER_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_DATA_CHANNEL_LISTENER_H_ - -#include "core/internal/mediums/webrtc_socket_wrapper.h" -#include "core/listeners.h" -#include "platform/base/byte_array.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -// Callbacks from the data channel. -struct DataChannelListener { - // Called when the data channel is open and the socket wraper is ready to - // read and write. - std::function<void(WebRtcSocketWrapper)> data_channel_open_cb = - DefaultCallback<WebRtcSocketWrapper>(); - - // Called when the data channel is closed. - std::function<void()> data_channel_closed_cb = DefaultCallback<>(); -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_DATA_CHANNEL_LISTENER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/local_ice_candidate_listener.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/local_ice_candidate_listener.h deleted file mode 100644 index 24085193e39..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/local_ice_candidate_listener.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_LOCAL_ICE_CANDIDATE_LISTENER_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_LOCAL_ICE_CANDIDATE_LISTENER_H_ - -#include "core/listeners.h" -#include "webrtc/api/peer_connection_interface.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -// Callbacks from local ice candidate collection. -struct LocalIceCandidateListener { - // Called when a new local ice candidate has been found. - std::function<void(const webrtc::IceCandidateInterface*)> - local_ice_candidate_found_cb = location::nearby::DefaultCallback< - const webrtc::IceCandidateInterface*>(); -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_LOCAL_ICE_CANDIDATE_LISTENER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/session_description_wrapper.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/session_description_wrapper.h deleted file mode 100644 index dd594917348..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/session_description_wrapper.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_SESSION_DESCRIPTION_WRAPPER_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_SESSION_DESCRIPTION_WRAPPER_H_ - -#include "webrtc/api/peer_connection_interface.h" - -// Wrapper object around SessionDescriptionInterface*. -// This object owns the SessionDescriptionInterface* unless Release() has been -// called. -class SessionDescriptionWrapper { - public: - SessionDescriptionWrapper() = default; - explicit SessionDescriptionWrapper(webrtc::SessionDescriptionInterface* sdp) - : impl_(sdp) {} - - // Copy constructor that performs a deep copy, i.e. creates a new - // SessionDescriptionInterface. - SessionDescriptionWrapper(const SessionDescriptionWrapper& sdp) { - if (sdp.IsValid()) { - impl_ = webrtc::CreateSessionDescription(sdp.GetType(), sdp.ToString()); - } - } - - SessionDescriptionWrapper(SessionDescriptionWrapper&&) = default; - SessionDescriptionWrapper& operator=(SessionDescriptionWrapper&&) = default; - - // Release the ownership of the SessionDescriptionInterface*. - webrtc::SessionDescriptionInterface* Release() { return impl_.release(); } - - // Returns a string representation of the sdp. Only call this, if IsValid() is - // true. - std::string ToString() const { - std::string str; - impl_->ToString(&str); - return str; - } - - // Returns the SdpType of the SessionDescriptionInterface. Only call this, if - // IsValid() is true. - webrtc::SdpType GetType() const { return impl_->GetType(); } - - const webrtc::SessionDescriptionInterface& GetSdp() { return *impl_; } - - // Return whether this object currently holds a SessionDescriptionInterface. - bool IsValid() const { return impl_ != nullptr; } - - private: - std::unique_ptr<webrtc::SessionDescriptionInterface> impl_; -}; - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_SESSION_DESCRIPTION_WRAPPER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/signaling_frames.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/signaling_frames.cc deleted file mode 100644 index 033c2fac17f..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/signaling_frames.cc +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/webrtc/signaling_frames.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { -namespace webrtc_frames { -using WebRtcSignalingFrame = location::nearby::mediums::WebRtcSignalingFrame; - -namespace { - -ByteArray FrameToByteArray(const WebRtcSignalingFrame& signaling_frame) { - std::string message; - signaling_frame.SerializeToString(&message); - return ByteArray(message.c_str(), message.size()); -} - -void SetSenderId(const WebrtcPeerId& sender_id, WebRtcSignalingFrame& frame) { - frame.mutable_sender_id()->set_id(sender_id.GetId()); -} - -std::unique_ptr<webrtc::IceCandidateInterface> DecodeIceCandidate( - location::nearby::mediums::IceCandidate ice_candidate_proto) { - webrtc::SdpParseError error; - return std::unique_ptr<webrtc::IceCandidateInterface>( - webrtc::CreateIceCandidate(ice_candidate_proto.sdp_mid(), - ice_candidate_proto.sdp_m_line_index(), - ice_candidate_proto.sdp(), &error)); -} - -} // namespace - -ByteArray EncodeReadyForSignalingPoke(const WebrtcPeerId& sender_id) { - WebRtcSignalingFrame signaling_frame; - signaling_frame.set_type(WebRtcSignalingFrame::READY_FOR_SIGNALING_POKE_TYPE); - SetSenderId(sender_id, signaling_frame); - signaling_frame.set_allocated_ready_for_signaling_poke( - new location::nearby::mediums::ReadyForSignalingPoke()); - return FrameToByteArray(std::move(signaling_frame)); -} - -ByteArray EncodeOffer(const WebrtcPeerId& sender_id, - const webrtc::SessionDescriptionInterface& offer) { - WebRtcSignalingFrame signaling_frame; - signaling_frame.set_type(WebRtcSignalingFrame::OFFER_TYPE); - SetSenderId(sender_id, signaling_frame); - std::string offer_str; - offer.ToString(&offer_str); - signaling_frame.mutable_offer() - ->mutable_session_description() - ->set_description(offer_str); - return FrameToByteArray(std::move(signaling_frame)); -} - -ByteArray EncodeAnswer(const WebrtcPeerId& sender_id, - const webrtc::SessionDescriptionInterface& answer) { - WebRtcSignalingFrame signaling_frame; - signaling_frame.set_type(WebRtcSignalingFrame::ANSWER_TYPE); - SetSenderId(sender_id, signaling_frame); - std::string answer_str; - answer.ToString(&answer_str); - signaling_frame.mutable_answer() - ->mutable_session_description() - ->set_description(answer_str); - return FrameToByteArray(std::move(signaling_frame)); -} - -ByteArray EncodeIceCandidates( - const WebrtcPeerId& sender_id, - const std::vector<location::nearby::mediums::IceCandidate>& - ice_candidates) { - WebRtcSignalingFrame signaling_frame; - signaling_frame.set_type(WebRtcSignalingFrame::ICE_CANDIDATES_TYPE); - SetSenderId(sender_id, signaling_frame); - for (const auto& ice_candidate : ice_candidates) { - *signaling_frame.mutable_ice_candidates()->add_ice_candidates() = - ice_candidate; - } - return FrameToByteArray(std::move(signaling_frame)); -} - -std::unique_ptr<webrtc::SessionDescriptionInterface> DecodeOffer( - const WebRtcSignalingFrame& frame) { - return webrtc::CreateSessionDescription( - webrtc::SdpType::kOffer, - frame.offer().session_description().description()); -} - -std::unique_ptr<webrtc::SessionDescriptionInterface> DecodeAnswer( - const WebRtcSignalingFrame& frame) { - return webrtc::CreateSessionDescription( - webrtc::SdpType::kAnswer, - frame.answer().session_description().description()); -} - -std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> DecodeIceCandidates( - const WebRtcSignalingFrame& frame) { - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> ice_candidates; - for (const auto& candidate : frame.ice_candidates().ice_candidates()) { - ice_candidates.push_back(DecodeIceCandidate(candidate)); - } - return ice_candidates; -} - -location::nearby::mediums::IceCandidate EncodeIceCandidate( - const webrtc::IceCandidateInterface& ice_candidate) { - std::string sdp; - ice_candidate.ToString(&sdp); - location::nearby::mediums::IceCandidate ice_candidate_proto; - ice_candidate_proto.set_sdp(sdp); - ice_candidate_proto.set_sdp_mid(ice_candidate.sdp_mid()); - ice_candidate_proto.set_sdp_m_line_index(ice_candidate.sdp_mline_index()); - return ice_candidate_proto; -} - -} // namespace webrtc_frames -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/signaling_frames.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/signaling_frames.h deleted file mode 100644 index 8be6a97b325..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/signaling_frames.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_SIGNALING_FRAMES_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_SIGNALING_FRAMES_H_ - -#include <vector> - -#include "core/internal/mediums/webrtc_peer_id.h" -#include "platform/base/byte_array.h" -#include "proto/mediums/web_rtc_signaling_frames.pb.h" -#include "webrtc/api/peer_connection_interface.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { -namespace webrtc_frames { - -ByteArray EncodeReadyForSignalingPoke(const WebrtcPeerId& sender_id); - -ByteArray EncodeOffer(const WebrtcPeerId& sender_id, - const webrtc::SessionDescriptionInterface& offer); -ByteArray EncodeAnswer(const WebrtcPeerId& sender_id, - const webrtc::SessionDescriptionInterface& answer); - -ByteArray EncodeIceCandidates( - const WebrtcPeerId& sender_id, - const std::vector<location::nearby::mediums::IceCandidate>& ice_candidates); -location::nearby::mediums::IceCandidate EncodeIceCandidate( - const webrtc::IceCandidateInterface& ice_candidate); - -std::unique_ptr<webrtc::SessionDescriptionInterface> DecodeOffer( - const location::nearby::mediums::WebRtcSignalingFrame& frame); -std::unique_ptr<webrtc::SessionDescriptionInterface> DecodeAnswer( - const location::nearby::mediums::WebRtcSignalingFrame& frame); - -std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> DecodeIceCandidates( - const location::nearby::mediums::WebRtcSignalingFrame& frame); - -} // namespace webrtc_frames -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_SIGNALING_FRAMES_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/signaling_frames_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/signaling_frames_test.cc deleted file mode 100644 index 4105c7b78f3..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/signaling_frames_test.cc +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/webrtc/signaling_frames.h" - -#include <memory> - -#include "google/protobuf/text_format.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "core/internal/mediums/webrtc_peer_id.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { -namespace webrtc_frames { - -namespace { - -const char kSampleSdp[] = - "v=0\r\no=- 7859371131 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 " - "0\r\na=msid-semantic: WMS\r\n"; - -const char kIceCandidateSdp1[] = - "a=candidate:1 1 UDP 2130706431 10.0.1.1 8998 typ host"; -const char kIceCandidateSdp2[] = - "a=candidate:2 1 UDP 1694498815 192.0.2.3 45664 typ srflx raddr"; - -const char kIceSdpMid[] = "data"; -const int kIceSdpMLineIndex = 0; - -const char kOfferProto[] = R"( - sender_id { id: "abc" } - type: OFFER_TYPE - offer { - session_description { - description: "v=0\r\no=- 7859371131 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=msid-semantic: WMS\r\n" - } - } - )"; - -const char kAnswerProto[] = R"( - sender_id { id: "abc" } - type: ANSWER_TYPE - answer { - session_description { - description: "v=0\r\no=- 7859371131 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=msid-semantic: WMS\r\n" - } - } - )"; - -const char kIceCandidatesProto[] = R"( - sender_id { id: "abc" } - type: ICE_CANDIDATES_TYPE - ice_candidates { - ice_candidates { - sdp: "candidate:1 1 udp 2130706431 10.0.1.1 8998 typ host generation 0" - sdp_mid: "data" - sdp_m_line_index: 0 - } - ice_candidates { - sdp: "candidate:2 1 udp 1694498815 192.0.2.3 45664 typ srflx generation 0" - sdp_mid: "data" - sdp_m_line_index: 0 - } - } - )"; -} // namespace - -TEST(SignalingFramesTest, SignalingPoke) { - WebrtcPeerId sender_id("abc"); - ByteArray encoded_poke = EncodeReadyForSignalingPoke(sender_id); - - location::nearby::mediums::WebRtcSignalingFrame frame; - frame.ParseFromString(std::string(encoded_poke.data(), encoded_poke.size())); - - EXPECT_THAT(frame, testing::EqualsProto(R"pb( - sender_id { id: "abc" } - type: READY_FOR_SIGNALING_POKE_TYPE - ready_for_signaling_poke {} - )pb")); -} - -TEST(SignalingFramesTest, EncodeValidOffer) { - WebrtcPeerId sender_id("abc"); - std::unique_ptr<webrtc::SessionDescriptionInterface> offer = - webrtc::CreateSessionDescription(webrtc::SdpType::kOffer, kSampleSdp); - ByteArray encoded_offer = EncodeOffer(sender_id, *offer); - - location::nearby::mediums::WebRtcSignalingFrame frame; - frame.ParseFromString( - std::string(encoded_offer.data(), encoded_offer.size())); - - EXPECT_THAT(frame, testing::EqualsProto(kOfferProto)); -} - -TEST(SignaingFramesTest, DecodeValidOffer) { - location::nearby::mediums::WebRtcSignalingFrame frame; - proto2::TextFormat::ParseFromString(kOfferProto, &frame); - std::unique_ptr<webrtc::SessionDescriptionInterface> decoded_offer = - DecodeOffer(frame); - - EXPECT_EQ(webrtc::SdpType::kOffer, decoded_offer->GetType()); - std::string description; - decoded_offer->ToString(&description); - EXPECT_EQ(kSampleSdp, description); -} - -TEST(SignalingFramesTest, EncodeValidAnswer) { - WebrtcPeerId sender_id("abc"); - std::unique_ptr<webrtc::SessionDescriptionInterface> answer( - webrtc::CreateSessionDescription(webrtc::SdpType::kAnswer, kSampleSdp)); - ByteArray encoded_answer = EncodeAnswer(sender_id, *answer); - - location::nearby::mediums::WebRtcSignalingFrame frame; - frame.ParseFromString( - std::string(encoded_answer.data(), encoded_answer.size())); - - EXPECT_THAT(frame, testing::EqualsProto(kAnswerProto)); -} - -TEST(SignalingFramesTest, DecodeValidAnswer) { - location::nearby::mediums::WebRtcSignalingFrame frame; - proto2::TextFormat::ParseFromString(kAnswerProto, &frame); - std::unique_ptr<webrtc::SessionDescriptionInterface> decoded_answer = - DecodeAnswer(frame); - - EXPECT_EQ(webrtc::SdpType::kAnswer, decoded_answer->GetType()); - std::string description; - decoded_answer->ToString(&description); - EXPECT_EQ(kSampleSdp, description); -} - -TEST(SignalingFramesTest, EncodeValidIceCandidates) { - WebrtcPeerId sender_id("abc"); - webrtc::SdpParseError error; - - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> ice_candidates; - ice_candidates.emplace_back(webrtc::CreateIceCandidate( - kIceSdpMid, kIceSdpMLineIndex, kIceCandidateSdp1, &error)); - ice_candidates.emplace_back(webrtc::CreateIceCandidate( - kIceSdpMid, kIceSdpMLineIndex, kIceCandidateSdp2, &error)); - std::vector<location::nearby::mediums::IceCandidate> encoded_candidates_vec; - for (const auto& ice_candidate : ice_candidates) { - encoded_candidates_vec.push_back(EncodeIceCandidate(*ice_candidate)); - } - ByteArray encoded_candidates = - EncodeIceCandidates(sender_id, encoded_candidates_vec); - - location::nearby::mediums::WebRtcSignalingFrame frame; - frame.ParseFromString( - std::string(encoded_candidates.data(), encoded_candidates.size())); - - EXPECT_THAT(frame, testing::EqualsProto(kIceCandidatesProto)); -} - -TEST(SignalingFramesTest, DecodeValidIceCandidates) { - webrtc::SdpParseError error; - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> ice_candidates; - ice_candidates.emplace_back(webrtc::CreateIceCandidate( - kIceSdpMid, kIceSdpMLineIndex, kIceCandidateSdp1, &error)); - ice_candidates.emplace_back(webrtc::CreateIceCandidate( - kIceSdpMid, kIceSdpMLineIndex, kIceCandidateSdp2, &error)); - - location::nearby::mediums::WebRtcSignalingFrame frame; - proto2::TextFormat::ParseFromString(kIceCandidatesProto, &frame); - std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> - decoded_candidates = DecodeIceCandidates(frame); - - ASSERT_EQ(2u, decoded_candidates.size()); - for (int i = 0; i < static_cast<int>(decoded_candidates.size()); i++) { - EXPECT_TRUE(ice_candidates[i]->candidate().IsEquivalent( - decoded_candidates[i]->candidate())); - EXPECT_EQ(ice_candidates[i]->sdp_mid(), decoded_candidates[i]->sdp_mid()); - EXPECT_EQ(ice_candidates[i]->sdp_mline_index(), - decoded_candidates[i]->sdp_mline_index()); - } -} - -} // namespace webrtc_frames -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket.cc deleted file mode 100644 index 0e4f34babab..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket.cc +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/webrtc/webrtc_socket.h" - -#include "platform/public/logging.h" -#include "platform/public/mutex_lock.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -// OutputStreamImpl -Exception WebRtcSocket::OutputStreamImpl::Write(const ByteArray& data) { - if (data.size() > kMaxDataSize) { - NEARBY_LOG(WARNING, "Sending data larger than 1MB"); - return {Exception::kIo}; - } - - socket_->BlockUntilSufficientSpaceInBuffer(data.size()); - - if (socket_->IsClosed()) { - NEARBY_LOG(WARNING, "Tried sending message while socket is closed"); - return {Exception::kIo}; - } - - if (!socket_->SendMessage(data)) { - NEARBY_LOG(INFO, "Unable to write data to socket."); - return {Exception::kIo}; - } - return {Exception::kSuccess}; -} - -Exception WebRtcSocket::OutputStreamImpl::Flush() { - // Java implementation is empty. - return {Exception::kSuccess}; -} - -Exception WebRtcSocket::OutputStreamImpl::Close() { - socket_->Close(); - return {Exception::kSuccess}; -} - -// WebRtcSocket -WebRtcSocket::WebRtcSocket( - const std::string& name, - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) - : name_(name), data_channel_(std::move(data_channel)) { - NEARBY_LOGS(INFO) << "WebRtcSocket::WebRtcSocket(" << name_ - << ") this: " << this; - data_channel_->RegisterObserver(this); -} - -WebRtcSocket::~WebRtcSocket() { - NEARBY_LOGS(INFO) << "WebRtcSocket::~WebRtcSocket(" << name_ - << ") this: " << this; - Close(); - NEARBY_LOGS(INFO) << "WebRtcSocket::~WebRtcSocket(" << name_ - << ") this: " << this << " done"; -} - -InputStream& WebRtcSocket::GetInputStream() { return pipe_.GetInputStream(); } - -OutputStream& WebRtcSocket::GetOutputStream() { return output_stream_; } - -void WebRtcSocket::Close() { - NEARBY_LOGS(INFO) << "WebRtcSocket::Close(" << name_ << ") this: " << this; - if (closed_.Set(true)) return; - - ClosePipe(); - // NOTE: This call blocks and triggers a state change on the siginaling thread - // to 'closing' but does not block until 'closed' is sent so the data channel - // is not fully closed when this call is done. - data_channel_->Close(); - NEARBY_LOGS(INFO) << "WebRtcSocket::Close(" << name_ << ") this: " << this - << " done"; -} - -void WebRtcSocket::OnStateChange() { - // Running on the signaling thread right now. - NEARBY_LOGS(ERROR) - << "WebRtcSocket::OnStateChange() webrtc data channel state: " - << webrtc::DataChannelInterface::DataStateString(data_channel_->state()); - switch (data_channel_->state()) { - case webrtc::DataChannelInterface::DataState::kConnecting: - break; - case webrtc::DataChannelInterface::DataState::kOpen: - // We implicitly depend on the |socket_listener_| to offload from - // the signaling thread so it does not get blocked. - socket_listener_.socket_ready_cb(this); - break; - case webrtc::DataChannelInterface::DataState::kClosing: - break; - case webrtc::DataChannelInterface::DataState::kClosed: - NEARBY_LOG( - ERROR, - "WebRtcSocket::OnStateChange() unregistering data channel observer."); - data_channel_->UnregisterObserver(); - // This will trigger a destruction of the owning connection flow - // We implicitly depend on the |socket_listener_| to offload from - // the signaling thread so it does not get blocked. - socket_listener_.socket_closed_cb(this); - - if (!closed_.Set(true)) { - OffloadFromSignalingThread([this] { ClosePipe(); }); - } - break; - } -} -void WebRtcSocket::OnMessage(const webrtc::DataBuffer& buffer) { - // This is a data channel callback on the signaling thread, lets off load so - // we don't block signaling. - OffloadFromSignalingThread( - [this, buffer = ByteArray(buffer.data.data<char>(), buffer.size())] { - if (!pipe_.GetOutputStream().Write(buffer).Ok()) { - Close(); - return; - } - - if (!pipe_.GetOutputStream().Flush().Ok()) { - Close(); - } - }); -} - -void WebRtcSocket::OnBufferedAmountChange(uint64_t sent_data_size) { - // This is a data channel callback on the signaling thread, lets off load so - // we don't block signaling. - OffloadFromSignalingThread([this] { WakeUpWriter(); }); -} - -bool WebRtcSocket::SendMessage(const ByteArray& data) { - return data_channel_->Send( - webrtc::DataBuffer(std::string(data.data(), data.size()))); -} - -bool WebRtcSocket::IsClosed() { return closed_.Get(); } - -void WebRtcSocket::ClosePipe() { - NEARBY_LOGS(INFO) << "WebRtcSocket::ClosePipe(" << name_ - << ") this: " << this; - // This is thread-safe to close these sockets even if a read or write is in - // process on another thread, Close will wait for the exclusive mutex before - // setting state. - pipe_.GetInputStream().Close(); - pipe_.GetOutputStream().Close(); - WakeUpWriter(); - NEARBY_LOGS(INFO) << "WebRtcSocket::ClosePipe(" << name_ << ") this: " << this - << " done"; -} - -// Must not be called on signalling thread. -void WebRtcSocket::WakeUpWriter() { - MutexLock lock(&backpressure_mutex_); - buffer_variable_.Notify(); -} - -void WebRtcSocket::SetSocketListener(SocketListener&& listener) { - socket_listener_ = std::move(listener); -} - -void WebRtcSocket::BlockUntilSufficientSpaceInBuffer(int length) { - MutexLock lock(&backpressure_mutex_); - while (!IsClosed() && - (data_channel_->buffered_amount() + length > kMaxDataSize)) { - // TODO(himanshujaju): Add wait with timeout. - buffer_variable_.Wait(); - } -} - -void WebRtcSocket::OffloadFromSignalingThread(Runnable runnable) { - single_thread_executor_.Execute(std::move(runnable)); -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket.h deleted file mode 100644 index a65f2d5d9ed..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_SOCKET_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_SOCKET_H_ - -#include <memory> - -#include "core/listeners.h" -#include "platform/base/input_stream.h" -#include "platform/base/output_stream.h" -#include "platform/base/socket.h" -#include "platform/public/atomic_boolean.h" -#include "platform/public/condition_variable.h" -#include "platform/public/mutex.h" -#include "platform/public/pipe.h" -#include "platform/public/single_thread_executor.h" -#include "webrtc/api/data_channel_interface.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -// Maximum data size: 1 MB -constexpr int kMaxDataSize = 1 * 1024 * 1024; - -// Defines the Socket implementation specific to WebRTC, which uses the WebRTC -// data channel to send and receive messages. -// -// Messages are buffered here to prevent the data channel from overflowing, -// which could lead to data loss. -class WebRtcSocket : public Socket, public webrtc::DataChannelObserver { - public: - WebRtcSocket(const std::string& name, - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel); - ~WebRtcSocket() override; - - WebRtcSocket(const WebRtcSocket& other) = delete; - WebRtcSocket& operator=(const WebRtcSocket& other) = delete; - - // Overrides for location::nearby::Socket: - InputStream& GetInputStream() override; - OutputStream& GetOutputStream() override; - void Close() override; - - // webrtc::DataChannelObserver: - void OnStateChange() override; - void OnMessage(const webrtc::DataBuffer& buffer) override; - void OnBufferedAmountChange(uint64_t sent_data_size) override; - - // Listener class the gets called when the socket is ready or closed - struct SocketListener { - std::function<void(WebRtcSocket*)> socket_ready_cb = - DefaultCallback<WebRtcSocket*>(); - std::function<void(WebRtcSocket*)> socket_closed_cb = - DefaultCallback<WebRtcSocket*>(); - }; - - void SetSocketListener(SocketListener&& listener); - - private: - class OutputStreamImpl : public OutputStream { - public: - explicit OutputStreamImpl(WebRtcSocket* const socket) : socket_(socket) {} - ~OutputStreamImpl() override = default; - - OutputStreamImpl(const OutputStreamImpl& other) = delete; - OutputStreamImpl& operator=(const OutputStreamImpl& other) = delete; - - // OutputStream: - Exception Write(const ByteArray& data) override; - Exception Flush() override; - Exception Close() override; - - private: - // |this| OutputStreamImpl is owned by |socket_|. - WebRtcSocket* const socket_; - }; - - void WakeUpWriter(); - bool IsClosed(); - void ClosePipe(); - bool SendMessage(const ByteArray& data); - void BlockUntilSufficientSpaceInBuffer(int length); - void OffloadFromSignalingThread(Runnable runnable); - - std::string name_; - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel_; - - Pipe pipe_; - - OutputStreamImpl output_stream_{this}; - - AtomicBoolean closed_{false}; - - SocketListener socket_listener_; - - mutable Mutex backpressure_mutex_; - ConditionVariable buffer_variable_{&backpressure_mutex_}; - - // This should be destroyed first to ensure any remaining tasks flushed on - // shutdown get run while the other members are still alive. - SingleThreadExecutor single_thread_executor_; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_SOCKET_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket_test.cc deleted file mode 100644 index 135a63345db..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket_test.cc +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/webrtc/webrtc_socket.h" - -#include <memory> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "platform/base/byte_array.h" -#include "webrtc/api/data_channel_interface.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -namespace { - -// using TestPlatform = platform::ImplementationPlatform; - -const char kSocketName[] = "TestSocket"; - -class MockDataChannel - : public rtc::RefCountedObject<webrtc::DataChannelInterface> { - public: - MOCK_METHOD(void, RegisterObserver, (webrtc::DataChannelObserver*)); - MOCK_METHOD(void, UnregisterObserver, ()); - - MOCK_METHOD(std::string, label, (), (const)); - - MOCK_METHOD(bool, reliable, (), (const)); - MOCK_METHOD(int, id, (), (const)); - MOCK_METHOD(DataState, state, (), (const)); - MOCK_METHOD(uint32_t, messages_sent, (), (const)); - MOCK_METHOD(uint64_t, bytes_sent, (), (const)); - MOCK_METHOD(uint32_t, messages_received, (), (const)); - MOCK_METHOD(uint64_t, bytes_received, (), (const)); - - MOCK_METHOD(uint64_t, buffered_amount, (), (const)); - - MOCK_METHOD(void, Close, ()); - - MOCK_METHOD(bool, Send, (const webrtc::DataBuffer&)); -}; - -} // namespace - -TEST(WebRtcSocketTest, ReadFromSocket) { - const char* message = "message"; - rtc::scoped_refptr<MockDataChannel> mock_data_channel = new MockDataChannel(); - WebRtcSocket webrtc_socket(kSocketName, mock_data_channel); - - webrtc_socket.OnMessage(webrtc::DataBuffer{message}); - ExceptionOr<ByteArray> result = webrtc_socket.GetInputStream().Read(7); - EXPECT_TRUE(result.ok()); - EXPECT_EQ(result.result(), ByteArray{message}); -} - -TEST(WebRtcSocketTest, ReadMultipleMessages) { - rtc::scoped_refptr<MockDataChannel> mock_data_channel = new MockDataChannel(); - WebRtcSocket webrtc_socket(kSocketName, mock_data_channel); - - webrtc_socket.OnMessage(webrtc::DataBuffer{"Me"}); - webrtc_socket.OnMessage(webrtc::DataBuffer{"ssa"}); - webrtc_socket.OnMessage(webrtc::DataBuffer{"ge"}); - - ExceptionOr<ByteArray> result; - - // This behaviour is different from the Java code - result = webrtc_socket.GetInputStream().Read(7); - EXPECT_TRUE(result.ok()); - EXPECT_EQ(result.result(), ByteArray{"Me"}); - - result = webrtc_socket.GetInputStream().Read(7); - EXPECT_TRUE(result.ok()); - EXPECT_EQ(result.result(), ByteArray{"ssa"}); - - result = webrtc_socket.GetInputStream().Read(7); - EXPECT_TRUE(result.ok()); - EXPECT_EQ(result.result(), ByteArray{"ge"}); -} - -TEST(WebRtcSocketTest, WriteToSocket) { - const ByteArray kMessage{"Message"}; - rtc::scoped_refptr<MockDataChannel> mock_data_channel = new MockDataChannel(); - WebRtcSocket webrtc_socket(kSocketName, mock_data_channel); - - EXPECT_CALL(*mock_data_channel, Send(testing::_)) - .WillRepeatedly(testing::Return(true)); - EXPECT_TRUE(webrtc_socket.GetOutputStream().Write(kMessage).Ok()); -} - -TEST(WebRtcSocketTest, SendDataBiggerThanMax) { - const ByteArray kMessage{kMaxDataSize + 1}; - rtc::scoped_refptr<MockDataChannel> mock_data_channel = new MockDataChannel(); - WebRtcSocket webrtc_socket(kSocketName, mock_data_channel); - - EXPECT_CALL(*mock_data_channel, Send(testing::_)).Times(0); - EXPECT_EQ(webrtc_socket.GetOutputStream().Write(kMessage), - Exception{Exception::kIo}); -} - -TEST(WebRtcSocketTest, WriteToDataChannelFails) { - ByteArray kMessage{"Message"}; - rtc::scoped_refptr<MockDataChannel> mock_data_channel = new MockDataChannel(); - WebRtcSocket webrtc_socket(kSocketName, mock_data_channel); - - ON_CALL(*mock_data_channel, Send(testing::_)) - .WillByDefault(testing::Return(false)); - EXPECT_EQ(webrtc_socket.GetOutputStream().Write(kMessage), - Exception{Exception::kIo}); -} - -TEST(WebRtcSocketTest, Close) { - rtc::scoped_refptr<MockDataChannel> mock_data_channel = new MockDataChannel(); - WebRtcSocket webrtc_socket(kSocketName, mock_data_channel); - - EXPECT_CALL(*mock_data_channel, Close()); - - int socket_closed_cb_called = 0; - - webrtc_socket.SetSocketListener( - {.socket_closed_cb = [&](WebRtcSocket* socket) { - socket_closed_cb_called++; - }}); - webrtc_socket.Close(); - - // We have to fake the close event to get the callback to run. - ON_CALL(*mock_data_channel, state()) - .WillByDefault( - testing::Return(webrtc::DataChannelInterface::DataState::kClosed)); - - webrtc_socket.OnStateChange(); - - EXPECT_EQ(socket_closed_cb_called, 1); -} - -TEST(WebRtcSocketTest, WriteOnClosedChannel) { - ByteArray kMessage{"Message"}; - rtc::scoped_refptr<MockDataChannel> mock_data_channel = new MockDataChannel(); - WebRtcSocket webrtc_socket(kSocketName, mock_data_channel); - webrtc_socket.Close(); - - EXPECT_CALL(*mock_data_channel, Send(testing::_)).Times(0); - EXPECT_EQ(webrtc_socket.GetOutputStream().Write(kMessage), - Exception{Exception::kIo}); -} - -TEST(WebRtcSocketTest, ReadFromClosedChannel) { - ByteArray kMessage{"Message"}; - rtc::scoped_refptr<MockDataChannel> mock_data_channel = new MockDataChannel(); - WebRtcSocket webrtc_socket(kSocketName, mock_data_channel); - ON_CALL(*mock_data_channel, Send(testing::_)) - .WillByDefault(testing::Return(true)); - - webrtc_socket.GetOutputStream().Write(kMessage); - webrtc_socket.Close(); - - EXPECT_EQ(webrtc_socket.GetInputStream().Read(7).exception(), Exception::kIo); -} - -TEST(WebRtcSocketTest, DataChannelCloseEventCleansUp) { - rtc::scoped_refptr<MockDataChannel> mock_data_channel = new MockDataChannel(); - WebRtcSocket webrtc_socket(kSocketName, mock_data_channel); - - ON_CALL(*mock_data_channel, state()) - .WillByDefault( - testing::Return(webrtc::DataChannelInterface::DataState::kClosed)); - - webrtc_socket.OnStateChange(); - - EXPECT_EQ(webrtc_socket.GetInputStream().Read(7).exception(), Exception::kIo); - - // Calling Close again should be safe even if the channel is already shut - // down. - webrtc_socket.Close(); -} - -TEST(WebRtcSocketTest, OpenStateTriggersCallback) { - rtc::scoped_refptr<MockDataChannel> mock_data_channel = new MockDataChannel(); - WebRtcSocket webrtc_socket(kSocketName, mock_data_channel); - - int socket_ready_cb_called = 0; - - webrtc_socket.SetSocketListener( - {.socket_ready_cb = [&](WebRtcSocket* socket) { - socket_ready_cb_called++; - }}); - - ON_CALL(*mock_data_channel, state()) - .WillByDefault( - testing::Return(webrtc::DataChannelInterface::DataState::kOpen)); - - webrtc_socket.OnStateChange(); - - EXPECT_EQ(socket_ready_cb_called, 1); -} - -TEST(WebRtcSocketTest, CloseStateTriggersCallback) { - rtc::scoped_refptr<MockDataChannel> mock_data_channel = new MockDataChannel(); - WebRtcSocket webrtc_socket(kSocketName, mock_data_channel); - - int socket_closed_cb_called = 0; - - webrtc_socket.SetSocketListener( - {.socket_closed_cb = [&](WebRtcSocket* socket) { - socket_closed_cb_called++; - }}); - - ON_CALL(*mock_data_channel, state()) - .WillByDefault( - testing::Return(webrtc::DataChannelInterface::DataState::kClosed)); - - webrtc_socket.OnStateChange(); - - EXPECT_EQ(socket_closed_cb_called, 1); -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_peer_id.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_peer_id.cc deleted file mode 100644 index 9360357c2e2..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_peer_id.cc +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/webrtc_peer_id.h" - -#include <sstream> - -#include "absl/strings/ascii.h" -#include "absl/strings/escaping.h" -#include "core/internal/mediums/utils.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -namespace { -constexpr int kPeerIdLength = 64; - -std::string BytesToStringUppercase(const ByteArray& bytes) { - std::string hex_string( - absl::BytesToHexString(std::string(bytes.data(), bytes.size()))); - absl::AsciiStrToUpper(&hex_string); - return hex_string; -} -} // namespace - -WebrtcPeerId WebrtcPeerId::FromRandom() { - return FromSeed(Utils::GenerateRandomBytes(kPeerIdLength)); -} - -WebrtcPeerId WebrtcPeerId::FromSeed(const ByteArray& seed) { - ByteArray full_hash(Utils::Sha256Hash(seed, kPeerIdLength)); - ByteArray hashed_seed(full_hash.data(), kPeerIdLength / 2); - return WebrtcPeerId(BytesToStringUppercase(hashed_seed)); -} - -bool WebrtcPeerId::IsValid() const { return !id_.empty(); } - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_peer_id.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_peer_id.h deleted file mode 100644 index d2331b5a0d9..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_peer_id.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_PEER_ID_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_PEER_ID_H_ - -#include <memory> -#include <string> - -#include "platform/base/byte_array.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -// WebrtcPeerId is used as an identifier to exchange SDP messages to establish -// WebRTC p2p connection. An empty WebrtcPeerId is considered to be invalid. -class WebrtcPeerId { - public: - WebrtcPeerId() = default; - explicit WebrtcPeerId(const std::string& id) : id_(id) {} - ~WebrtcPeerId() = default; - - static WebrtcPeerId FromRandom(); - static WebrtcPeerId FromSeed(const ByteArray& seed); - - bool IsValid() const; - - const std::string& GetId() const { return id_; } - - private: - std::string id_; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_PEER_ID_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_peer_id_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_peer_id_test.cc deleted file mode 100644 index 612d213c023..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_peer_id_test.cc +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/webrtc_peer_id.h" - -#include <memory> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "platform/base/byte_array.h" -#include "platform/public/crypto.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -TEST(WebrtcPeerIdTest, GenerateRandomPeerId) { - WebrtcPeerId peer_id = WebrtcPeerId::FromRandom(); - EXPECT_EQ(64, peer_id.GetId().size()); -} - -TEST(WebrtcPeerIdTest, GenerateFromSeed) { - // Values calculated by running actual SHA-256 hash on |seed|. - std::string seed = "seed"; - std::string expected_peer_id = - "19B25856E1C150CA834CFFC8B59B23ADBD0EC0389E58EB22B3B64768098D002B"; - - ByteArray seed_bytes(seed); - WebrtcPeerId peer_id = WebrtcPeerId::FromSeed(seed_bytes); - - EXPECT_EQ(64, peer_id.GetId().size()); - EXPECT_EQ(expected_peer_id, peer_id.GetId()); -} - -TEST(WebrtcPeerIdTest, GetId) { - const std::string id = "this_is_a_test"; - WebrtcPeerId peer_id(id); - EXPECT_EQ(id, peer_id.GetId()); -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_socket_wrapper.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_socket_wrapper.h deleted file mode 100644 index bc4671136b5..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_socket_wrapper.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_SOCKET_WRAPPER_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_SOCKET_WRAPPER_H_ - -#include <memory> - -#include "core/internal/mediums/webrtc/webrtc_socket.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -class WebRtcSocketWrapper final { - public: - WebRtcSocketWrapper() = default; - WebRtcSocketWrapper(const WebRtcSocketWrapper&) = default; - WebRtcSocketWrapper& operator=(const WebRtcSocketWrapper&) = default; - explicit WebRtcSocketWrapper(std::unique_ptr<WebRtcSocket> socket) - : impl_(socket.release()) {} - ~WebRtcSocketWrapper() = default; - - InputStream& GetInputStream() { return impl_->GetInputStream(); } - - OutputStream& GetOutputStream() { return impl_->GetOutputStream(); } - - void Close() { return impl_->Close(); } - - bool IsValid() const { return impl_ != nullptr; } - - WebRtcSocket& GetImpl() { return *impl_; } - - private: - std::shared_ptr<WebRtcSocket> impl_; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_SOCKET_WRAPPER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_test.cc deleted file mode 100644 index 863e6ef7310..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc_test.cc +++ /dev/null @@ -1,405 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/webrtc.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "core/internal/mediums/webrtc_socket_wrapper.h" -#include "platform/base/listeners.h" -#include "platform/base/medium_environment.h" -#include "platform/public/mutex_lock.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -namespace { - -using FeatureFlags = FeatureFlags::Flags; - -constexpr FeatureFlags kTestCases[] = { - FeatureFlags{ - .enable_cancellation_flag = true, - }, - FeatureFlags{ - .enable_cancellation_flag = false, - }, -}; - -class WebRtcTest : public ::testing::TestWithParam<FeatureFlags> { - protected: - using MockAcceptedCallback = - testing::MockFunction<void(WebRtcSocketWrapper socket)>; - - WebRtcTest() { env_.Stop(); } - - MediumEnvironment& env_{MediumEnvironment::Instance()}; -}; - -// Tests the flow when the two devices exchange SDP messages and connect to each -// other but the signaling channel is closed before sending the data. -TEST_P(WebRtcTest, ConnectBothDevices_ShutdownSignaling_SendData) { - env_.Start({.webrtc_enabled = true}); - FeatureFlags feature_flags = GetParam(); - env_.SetFeatureFlags(feature_flags); - WebRtc receiver, sender; - WebRtcSocketWrapper receiver_socket, sender_socket; - const WebrtcPeerId self_id("self_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - Future<bool> connected; - ByteArray message("message xyz"); - - receiver.StartAcceptingConnections( - service_id, self_id, location_hint, - {[&receiver_socket, connected](WebRtcSocketWrapper wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket.IsValid()); - }}); - - CancellationFlag flag; - sender_socket = sender.Connect(service_id, self_id, location_hint, &flag); - EXPECT_TRUE(sender_socket.IsValid()); - - ExceptionOr<bool> devices_connected = connected.Get(); - ASSERT_TRUE(devices_connected.ok()); - EXPECT_TRUE(devices_connected.result()); - - // Only shuts down signaling channel. - receiver.StopAcceptingConnections(service_id); - - sender_socket.GetOutputStream().Write(message); - ExceptionOr<ByteArray> received_msg = - receiver_socket.GetInputStream().Read(/*size=*/32); - ASSERT_TRUE(received_msg.ok()); - EXPECT_EQ(message, received_msg.result()); - env_.Stop(); -} - -TEST_P(WebRtcTest, CanCancelConnect) { - env_.Start({.webrtc_enabled = true}); - FeatureFlags feature_flags = GetParam(); - env_.SetFeatureFlags(feature_flags); - WebRtc receiver, sender; - WebRtcSocketWrapper receiver_socket, sender_socket; - const WebrtcPeerId self_id("self_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - Future<bool> connected; - ByteArray message("message"); - - receiver.StartAcceptingConnections( - service_id, self_id, location_hint, - {[&receiver_socket, connected](WebRtcSocketWrapper wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket.IsValid()); - }}); - - CancellationFlag flag(true); - sender_socket = sender.Connect(service_id, self_id, location_hint, &flag); - // If FeatureFlag is disabled, Cancelled is false as no-op. - if (!feature_flags.enable_cancellation_flag) { - EXPECT_TRUE(sender_socket.IsValid()); - - ExceptionOr<bool> devices_connected = connected.Get(); - ASSERT_TRUE(devices_connected.ok()); - EXPECT_TRUE(devices_connected.result()); - - sender_socket.GetOutputStream().Write(message); - ExceptionOr<ByteArray> received_msg = - receiver_socket.GetInputStream().Read(/*size=*/32); - ASSERT_TRUE(received_msg.ok()); - EXPECT_EQ(message, received_msg.result()); - - receiver_socket.Close(); - } else { - EXPECT_FALSE(sender_socket.IsValid()); - } - env_.Stop(); -} - -INSTANTIATE_TEST_SUITE_P(ParametrisedWebRtcTest, WebRtcTest, - ::testing::ValuesIn(kTestCases)); - -// Basic test to check that device is accepting connections when initialized. -TEST_F(WebRtcTest, NotAcceptingConnections) { - env_.Start({.webrtc_enabled = true}); - WebRtc webrtc; - ASSERT_TRUE(webrtc.IsAvailable()); - EXPECT_FALSE(webrtc.IsAcceptingConnections(std::string{})); - env_.Stop(); -} - -// Tests the flow when the device tries to accept connections twice. In this -// case, only the first call is successful and subsequent calls fail. -TEST_F(WebRtcTest, StartAcceptingConnectionTwice) { - env_.Start({.webrtc_enabled = true}); - testing::StrictMock<MockAcceptedCallback> mock_accepted_callback_; - WebRtc webrtc; - WebrtcPeerId self_id("peer_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint{}; - - ASSERT_TRUE(webrtc.IsAvailable()); - ASSERT_TRUE(webrtc.StartAcceptingConnections( - service_id, self_id, location_hint, - {mock_accepted_callback_.AsStdFunction()})); - EXPECT_FALSE(webrtc.StartAcceptingConnections( - service_id, self_id, location_hint, - {mock_accepted_callback_.AsStdFunction()})); - EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); - EXPECT_FALSE(webrtc.IsAcceptingConnections(std::string{})); - env_.Stop(); -} - -// Tests the flow when the device tries to connect but there is no peer -// accepting connections at the given peer ID. -TEST_F(WebRtcTest, Connect_NoPeer) { - env_.Start({.webrtc_enabled = true}); - WebRtc webrtc; - WebrtcPeerId peer_id("peer_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - - ASSERT_TRUE(webrtc.IsAvailable()); - CancellationFlag flag; - WebRtcSocketWrapper wrapper_1 = - webrtc.Connect(service_id, peer_id, location_hint, &flag); - EXPECT_FALSE(wrapper_1.IsValid()); - - EXPECT_TRUE(webrtc.StartAcceptingConnections( - service_id, peer_id, location_hint, AcceptedConnectionCallback())); - env_.Stop(); -} - -// Tests the flow when the device calls Connect() after calling -// StartAcceptingConnections() without StopAcceptingConnections(). -TEST_F(WebRtcTest, StartAcceptingConnection_ThenConnect) { - env_.Start({.webrtc_enabled = true}); - testing::StrictMock<MockAcceptedCallback> mock_accepted_callback_; - WebRtc webrtc; - WebrtcPeerId self_id("peer_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - - ASSERT_TRUE(webrtc.IsAvailable()); - ASSERT_TRUE(webrtc.StartAcceptingConnections( - service_id, self_id, location_hint, - {mock_accepted_callback_.AsStdFunction()})); - CancellationFlag flag; - WebRtcSocketWrapper wrapper = webrtc.Connect( - service_id, WebrtcPeerId("random_peer_id"), location_hint, &flag); - EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); - EXPECT_FALSE(wrapper.IsValid()); - EXPECT_FALSE(webrtc.StartAcceptingConnections( - service_id, self_id, location_hint, - {mock_accepted_callback_.AsStdFunction()})); - env_.Stop(); -} - -// Tests the flow when the device calls StartAcceptingConnections but the medium -// is closed before a peer device can connect to it. -TEST_F(WebRtcTest, StartAndStopAcceptingConnections) { - env_.Start({.webrtc_enabled = true}); - testing::StrictMock<MockAcceptedCallback> mock_accepted_callback_; - WebRtc webrtc; - WebrtcPeerId self_id("peer_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - - ASSERT_TRUE(webrtc.IsAvailable()); - ASSERT_TRUE(webrtc.StartAcceptingConnections( - service_id, self_id, location_hint, - {mock_accepted_callback_.AsStdFunction()})); - EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); - webrtc.StopAcceptingConnections(service_id); - EXPECT_FALSE(webrtc.IsAcceptingConnections(service_id)); - env_.Stop(); -} - -// Tests the flow when the device tries to connect to two different peers -// without disconnecting in between. -TEST_F(WebRtcTest, ConnectTwice) { - env_.Start({.webrtc_enabled = true}); - WebRtc receiver, sender, device_c; - WebRtcSocketWrapper receiver_socket, sender_socket; - const WebrtcPeerId self_id("self_id"), other_id("other_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - Future<bool> connected; - ByteArray message("message xyz"); - - receiver.StartAcceptingConnections( - service_id, self_id, location_hint, - {[&receiver_socket, connected](WebRtcSocketWrapper wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket.IsValid()); - }}); - - device_c.StartAcceptingConnections(service_id, other_id, location_hint, - {[](WebRtcSocketWrapper wrapper) {}}); - - CancellationFlag flag; - sender_socket = sender.Connect(service_id, self_id, location_hint, &flag); - EXPECT_TRUE(sender_socket.IsValid()); - - ExceptionOr<bool> devices_connected = connected.Get(); - ASSERT_TRUE(devices_connected.ok()); - EXPECT_TRUE(devices_connected.result()); - - WebRtcSocketWrapper socket = - sender.Connect(service_id, other_id, location_hint, &flag); - EXPECT_TRUE(socket.IsValid()); - socket.Close(); - - EXPECT_TRUE(receiver_socket.IsValid()); - EXPECT_TRUE(sender_socket.IsValid()); - - sender_socket.GetOutputStream().Write(message); - ExceptionOr<ByteArray> received_msg = - receiver_socket.GetInputStream().Read(/*size=*/32); - ASSERT_TRUE(received_msg.ok()); - EXPECT_EQ(message, received_msg.result()); - - receiver_socket.Close(); - env_.Stop(); -} - -// Tests the flow when the two devices exchange SDP messages and connect to each -// other but disconnect before being able to send/receive the actual data. -TEST_F(WebRtcTest, ConnectBothDevicesAndAbort) { - env_.Start({.webrtc_enabled = true}); - WebRtc receiver, sender; - WebRtcSocketWrapper receiver_socket, sender_socket; - const WebrtcPeerId self_id("self_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - Future<bool> connected; - ByteArray message("message xyz"); - - receiver.StartAcceptingConnections( - service_id, self_id, location_hint, - {[&receiver_socket, connected](WebRtcSocketWrapper wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket.IsValid()); - }}); - - CancellationFlag flag; - sender_socket = sender.Connect(service_id, self_id, location_hint, &flag); - EXPECT_TRUE(sender_socket.IsValid()); - - ExceptionOr<bool> devices_connected = connected.Get(); - ASSERT_TRUE(devices_connected.ok()); - EXPECT_TRUE(devices_connected.result()); - - receiver_socket.Close(); - env_.Stop(); -} - -// Tests the flow when the two devices exchange SDP messages and connect to each -// other and the actual data is exchanged successfully between the devices. -TEST_F(WebRtcTest, ConnectBothDevicesAndSendData) { - env_.Start({.webrtc_enabled = true}); - WebRtc receiver, sender; - WebRtcSocketWrapper receiver_socket, sender_socket; - const WebrtcPeerId self_id("self_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - Future<bool> connected; - ByteArray message("message"); - - receiver.StartAcceptingConnections( - service_id, self_id, location_hint, - {[&receiver_socket, connected](WebRtcSocketWrapper wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket.IsValid()); - }}); - - CancellationFlag flag; - sender_socket = sender.Connect(service_id, self_id, location_hint, &flag); - EXPECT_TRUE(sender_socket.IsValid()); - - ExceptionOr<bool> devices_connected = connected.Get(); - ASSERT_TRUE(devices_connected.ok()); - EXPECT_TRUE(devices_connected.result()); - - sender_socket.GetOutputStream().Write(message); - ExceptionOr<ByteArray> received_msg = - receiver_socket.GetInputStream().Read(/*size=*/32); - ASSERT_TRUE(received_msg.ok()); - EXPECT_EQ(message, received_msg.result()); - - receiver_socket.Close(); - env_.Stop(); -} - -TEST_F(WebRtcTest, Connect_NullPeerConnection) { - env_.Start({.webrtc_enabled = true}); - testing::StrictMock<MockAcceptedCallback> mock_accepted_callback_; - env_.SetUseValidPeerConnection( - /*use_valid_peer_connection=*/false); - - WebRtc webrtc; - const std::string service_id("NearbySharing"); - WebrtcPeerId self_id("peer_id"); - LocationHint location_hint; - - ASSERT_TRUE(webrtc.IsAvailable()); - CancellationFlag flag; - WebRtcSocketWrapper wrapper = webrtc.Connect( - service_id, WebrtcPeerId("random_peer_id"), location_hint, &flag); - EXPECT_FALSE(wrapper.IsValid()); - env_.Stop(); -} - -// Tests the flow when the device calls StartAcceptingConnections and the -// receive messages stream fails. -TEST_F(WebRtcTest, ContinueAcceptingConnectionsOnComplete) { - env_.Start({.webrtc_enabled = true}); - testing::StrictMock<MockAcceptedCallback> mock_accepted_callback_; - WebRtc webrtc; - WebrtcPeerId self_id("peer_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - - ASSERT_TRUE(webrtc.IsAvailable()); - ASSERT_TRUE(webrtc.StartAcceptingConnections( - service_id, self_id, location_hint, - {mock_accepted_callback_.AsStdFunction()})); - EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); - - // Simulate a failure in receiving messages stream, WebRtc should restart - // accepting connections. - env_.SendWebRtcSignalingComplete(self_id.GetId(), - /*success=*/false); - EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); - - // And a "success" message should not cause accepting connections to stop. - env_.SendWebRtcSignalingComplete(self_id.GetId(), - /*success=*/true); - EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); - - webrtc.StopAcceptingConnections(service_id); - EXPECT_FALSE(webrtc.IsAcceptingConnections(service_id)); - env_.Stop(); -} - -} // namespace - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/wifi_lan.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/wifi_lan.cc deleted file mode 100644 index 9e24c5fe2e3..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/wifi_lan.cc +++ /dev/null @@ -1,409 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/wifi_lan.h" - -#include <memory> -#include <string> -#include <utility> - -#include "absl/strings/str_format.h" -#include "core/internal/mediums/utils.h" -#include "platform/public/logging.h" -#include "platform/public/mutex_lock.h" - -namespace location { -namespace nearby { -namespace connections { - -WifiLan::~WifiLan() { - // Destructor is not taking locks, but methods it is calling are. - while (!discovering_info_.service_ids.empty()) { - StopDiscovery(*discovering_info_.service_ids.begin()); - } - while (!server_sockets_.empty()) { - StopAcceptingConnections(server_sockets_.begin()->first); - } - while (!advertising_info_.nsd_service_infos.empty()) { - StopAdvertising(advertising_info_.nsd_service_infos.begin()->first); - } - - // All the AcceptLoopRunnable objects in here should already have gotten an - // opportunity to shut themselves down cleanly in the calls to - // StopAcceptingConnections() above. - accept_loops_runner_.Shutdown(); -} - -bool WifiLan::IsAvailable() const { - MutexLock lock(&mutex_); - - return IsAvailableLocked(); -} - -bool WifiLan::IsAvailableLocked() const { return medium_.IsValid(); } - -bool WifiLan::StartAdvertising(const std::string& service_id, - NsdServiceInfo& nsd_service_info) { - MutexLock lock(&mutex_); - - if (!IsAvailableLocked()) { - NEARBY_LOGS(INFO) - << "Can't turn on WifiLan advertising. WifiLan is not available."; - return false; - } - - if (!nsd_service_info.IsValid()) { - NEARBY_LOGS(INFO) - << "Refusing to turn on WifiLan advertising. nsd_service_info is not " - "valid."; - return false; - } - - if (IsAdvertisingLocked(service_id)) { - NEARBY_LOGS(INFO) - << "Failed to WifiLan advertise because we're already advertising."; - return false; - } - - if (!IsAcceptingConnectionsLocked(service_id)) { - NEARBY_LOGS(INFO) - << "Failed to turn on WifiLan advertising with nsd_service_info=" - << &nsd_service_info - << ", service_name=" << nsd_service_info.GetServiceName() - << ", service_id=" << service_id - << ". Should accept connections before advertising."; - return false; - } - - nsd_service_info.SetServiceType(GenerateServiceType(service_id)); - const auto& it = server_sockets_.find(service_id); - if (it != server_sockets_.end()) { - nsd_service_info.SetIPAddress(it->second.GetIPAddress()); - nsd_service_info.SetPort(it->second.GetPort()); - } - if (!medium_.StartAdvertising(nsd_service_info)) { - NEARBY_LOGS(INFO) - << "Failed to turn on WifiLan advertising with nsd_service_info=" - << &nsd_service_info - << ", service_name=" << nsd_service_info.GetServiceName() - << ", service_id=" << service_id; - return false; - } - - NEARBY_LOGS(INFO) << "Turned on WifiLan advertising with nsd_service_info=" - << &nsd_service_info - << ", service_name=" << nsd_service_info.GetServiceName() - << ", service_id=" << service_id; - advertising_info_.Add(service_id, std::move(nsd_service_info)); - return true; -} - -bool WifiLan::StopAdvertising(const std::string& service_id) { - MutexLock lock(&mutex_); - - if (!IsAdvertisingLocked(service_id)) { - NEARBY_LOGS(INFO) - << "Can't turn off WifiLan advertising; it is already off"; - return false; - } - - NEARBY_LOGS(INFO) << "Turned off WifiLan advertising with service_id=" - << service_id; - bool ret = - medium_.StopAdvertising(*advertising_info_.GetServiceInfo(service_id)); - // Reset our bundle of advertising state to mark that we're no longer - // advertising for specific service_id. - advertising_info_.Remove(service_id); - return ret; -} - -bool WifiLan::IsAdvertising(const std::string& service_id) { - MutexLock lock(&mutex_); - - return IsAdvertisingLocked(service_id); -} - -bool WifiLan::IsAdvertisingLocked(const std::string& service_id) { - return advertising_info_.Existed(service_id); -} - -bool WifiLan::StartDiscovery(const std::string& service_id, - DiscoveredServiceCallback callback) { - MutexLock lock(&mutex_); - - if (service_id.empty()) { - NEARBY_LOGS(INFO) - << "Refusing to start WifiLan discovering with empty service_id."; - return false; - } - - if (!IsAvailableLocked()) { - NEARBY_LOGS(INFO) - << "Can't discover WifiLan services because WifiLan isn't available."; - return false; - } - - if (IsDiscoveringLocked(service_id)) { - NEARBY_LOGS(INFO) - << "Refusing to start discovery of WifiLan services because another " - "discovery is already in-progress."; - return false; - } - - std::string service_type = GenerateServiceType(service_id); - bool ret = medium_.StartDiscovery(service_id, service_type, callback); - if (!ret) { - NEARBY_LOGS(INFO) << "Failed to start discovery of WifiLan services."; - return false; - } - - NEARBY_LOGS(INFO) << "Turned on WifiLan discovering with service_id=" - << service_id; - // Mark the fact that we're currently performing a WifiLan discovering. - discovering_info_.Add(service_id); - return true; -} - -bool WifiLan::StopDiscovery(const std::string& service_id) { - MutexLock lock(&mutex_); - - if (!IsDiscoveringLocked(service_id)) { - NEARBY_LOGS(INFO) - << "Can't turn off WifiLan discovering because we never started " - "discovering."; - return false; - } - - std::string service_type = GenerateServiceType(service_id); - NEARBY_LOGS(INFO) << "Turned off WifiLan discovering with service_id=" - << service_id << ", service_type=" << service_type; - bool ret = medium_.StopDiscovery(service_type); - discovering_info_.Remove(service_id); - return ret; -} - -bool WifiLan::IsDiscovering(const std::string& service_id) { - MutexLock lock(&mutex_); - return IsDiscoveringLocked(service_id); -} - -bool WifiLan::IsDiscoveringLocked(const std::string& service_id) { - return discovering_info_.Existed(service_id); -} - -bool WifiLan::StartAcceptingConnections(const std::string& service_id, - AcceptedConnectionCallback callback) { - MutexLock lock(&mutex_); - - if (service_id.empty()) { - NEARBY_LOGS(INFO) << "Refusing to start accepting WifiLan connections; " - "service_id is empty."; - return false; - } - - if (!IsAvailableLocked()) { - NEARBY_LOGS(INFO) - << "Can't start accepting WifiLan connections [service_id=" - << service_id << "]; WifiLan not available."; - return false; - } - - if (IsAcceptingConnectionsLocked(service_id)) { - NEARBY_LOGS(INFO) - << "Refusing to start accepting WifiLan connections [service=" - << service_id - << "]; WifiLan server is already in-progress with the same name."; - return false; - } - - // We can generate an exact port here on server socket; now we just assign 0 - // to let platform medium decide it. - int port = 0; - WifiLanServerSocket server_socket = medium_.ListenForService(port); - if (!server_socket.IsValid()) { - NEARBY_LOGS(INFO) - << "Failed to start accepting WifiLan connections for service_id=" - << service_id; - return false; - } - - // Mark the fact that there's an in-progress WifiLan server accepting - // connections. - auto owned_server_socket = - server_sockets_.insert({service_id, std::move(server_socket)}) - .first->second; - - // Start the accept loop on a dedicated thread - this stays alive and - // listening for new incoming connections until StopAcceptingConnections() is - // invoked. - accept_loops_runner_.Execute( - "wifi-lan-accept", - [callback = std::move(callback), - server_socket = std::move(owned_server_socket)]() mutable { - while (true) { - WifiLanSocket client_socket = server_socket.Accept(); - if (!client_socket.IsValid()) { - server_socket.Close(); - break; - } - callback.accepted_cb(std::move(client_socket)); - } - }); - - return true; -} - -bool WifiLan::StopAcceptingConnections(const std::string& service_id) { - MutexLock lock(&mutex_); - - if (service_id.empty()) { - NEARBY_LOGS(INFO) << "Unable to stop accepting WifiLan connections because " - "the service_id is empty."; - return false; - } - - const auto& it = server_sockets_.find(service_id); - if (it == server_sockets_.end()) { - NEARBY_LOGS(INFO) << "Can't stop accepting WifiLan connections for " - << service_id << " because it was never started."; - return false; - } - - // Closing the WifiLanServerSocket will kick off the suicide of the thread - // in accept_loops_thread_pool_ that blocks on WifiLanServerSocket.accept(). - // That may take some time to complete, but there's no particular reason to - // wait around for it. - auto item = server_sockets_.extract(it); - - // Store a handle to the WifiLanServerSocket, so we can use it after - // removing the entry from server_sockets_; making it scoped - // is a bonus that takes care of deallocation before we leave this method. - WifiLanServerSocket& listening_socket = item.mapped(); - - // Regardless of whether or not we fail to close the existing - // WifiLanServerSocket, remove it from server_sockets_ so that it - // frees up this service for another round. - - // Finally, close the WifiLanServerSocket. - if (!listening_socket.Close().Ok()) { - NEARBY_LOGS(INFO) << "Failed to close WifiLan server socket for service_id=" - << service_id; - return false; - } - - return true; -} - -bool WifiLan::IsAcceptingConnections(const std::string& service_id) { - MutexLock lock(&mutex_); - return IsAcceptingConnectionsLocked(service_id); -} - -bool WifiLan::IsAcceptingConnectionsLocked(const std::string& service_id) { - return server_sockets_.find(service_id) != server_sockets_.end(); -} - -WifiLanSocket WifiLan::Connect(const std::string& service_id, - const NsdServiceInfo& service_info, - CancellationFlag* cancellation_flag) { - MutexLock lock(&mutex_); - // Socket to return. To allow for NRVO to work, it has to be a single object. - WifiLanSocket socket; - - if (service_id.empty()) { - NEARBY_LOGS(INFO) << "Refusing to create client WifiLan socket because " - "service_id is empty."; - return socket; - } - - if (!IsAvailableLocked()) { - NEARBY_LOGS(INFO) << "Can't create client WifiLan socket [service_id=" - << service_id << "]; WifiLan isn't available."; - return socket; - } - - if (cancellation_flag->Cancelled()) { - NEARBY_LOGS(INFO) << "Can't create client WifiLan socket due to cancel."; - return socket; - } - - socket = medium_.ConnectToService(service_info, cancellation_flag); - if (!socket.IsValid()) { - NEARBY_LOGS(INFO) << "Failed to Connect via WifiLan [service_id=" - << service_id << "]"; - } - - return socket; -} - -WifiLanSocket WifiLan::Connect(const std::string& service_id, - const std::string& ip_address, int port, - CancellationFlag* cancellation_flag) { - MutexLock lock(&mutex_); - // Socket to return. To allow for NRVO to work, it has to be a single object. - WifiLanSocket socket; - - if (service_id.empty()) { - NEARBY_LOGS(INFO) << "Refusing to create client WifiLan socket because " - "service_id is empty."; - return socket; - } - - if (!IsAvailableLocked()) { - NEARBY_LOGS(INFO) << "Can't create client WifiLan socket [service_id=" - << service_id << "]; WifiLan isn't available."; - return socket; - } - - if (cancellation_flag->Cancelled()) { - NEARBY_LOGS(INFO) << "Can't create client WifiLan socket due to cancel."; - return socket; - } - - socket = medium_.ConnectToService(ip_address, port, cancellation_flag); - if (!socket.IsValid()) { - NEARBY_LOGS(INFO) << "Failed to Connect via WifiLan [service_id=" - << service_id << "]"; - } - - return socket; -} - -std::pair<std::string, int> WifiLan::GetCredentials( - const std::string& service_id) { - MutexLock lock(&mutex_); - const auto& it = server_sockets_.find(service_id); - if (it == server_sockets_.end()) { - return std::pair<std::string, int>(); - } - return std::pair<std::string, int>(it->second.GetIPAddress(), - it->second.GetPort()); -} - -std::string WifiLan::GenerateServiceType(const std::string& service_id) { - std::string service_id_hash_string; - - const ByteArray service_id_hash = Utils::Sha256Hash( - service_id, NsdServiceInfo::kTypeFromServiceIdHashLength); - for (auto byte : std::string(service_id_hash)) { - absl::StrAppend(&service_id_hash_string, absl::StrFormat("%02X", byte)); - } - - return absl::StrFormat(NsdServiceInfo::kNsdTypeFormat, - service_id_hash_string); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/wifi_lan.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/wifi_lan.h deleted file mode 100644 index dc5300f7d1f..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/wifi_lan.h +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WIFI_LAN_H_ -#define CORE_INTERNAL_MEDIUMS_WIFI_LAN_H_ - -#include <cstdint> -#include <string> - -#include "absl/container/flat_hash_map.h" -#include "absl/container/flat_hash_set.h" -#include "platform/base/byte_array.h" -#include "platform/base/cancellation_flag.h" -#include "platform/base/nsd_service_info.h" -#include "platform/public/multi_thread_executor.h" -#include "platform/public/mutex.h" -#include "platform/public/wifi_lan.h" - -namespace location { -namespace nearby { -namespace connections { - -class WifiLan { - public: - using DiscoveredServiceCallback = WifiLanMedium::DiscoveredServiceCallback; - - // Callback that is invoked when a new connection is accepted. - struct AcceptedConnectionCallback { - std::function<void(WifiLanSocket socket)> accepted_cb = - DefaultCallback<WifiLanSocket>(); - }; - - WifiLan() = default; - ~WifiLan(); - - // Returns true, if WifiLan communications are supported by a platform. - bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_); - - // Sets custom service info name, endpoint info name in NsdServiceInfo and - // then enables WifiLan advertising. - // Returns true, if NsdServiceInfo is successfully set, and false otherwise. - bool StartAdvertising(const std::string& service_id, - NsdServiceInfo& nsd_service_info) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Disables WifiLan advertising. - // Returns false if no successful call StartAdvertising() was previously - // made, otherwise returns true. - bool StopAdvertising(const std::string& service_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - bool IsAdvertising(const std::string& service_id) ABSL_LOCKS_EXCLUDED(mutex_); - - // Enables WifiLan discovery. Will report any discoverable services - // through a callback. - // Returns true, if discovery was enabled, false otherwise. - bool StartDiscovery(const std::string& service_id, - DiscoveredServiceCallback callback) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Disables WifiLan discovery. - bool StopDiscovery(const std::string& service_id) ABSL_LOCKS_EXCLUDED(mutex_); - - bool IsDiscovering(const std::string& service_id) ABSL_LOCKS_EXCLUDED(mutex_); - - // Starts a worker thread, creates a WifiLan socket, associates it with a - // service id. - bool StartAcceptingConnections(const std::string& service_id, - AcceptedConnectionCallback callback) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Closes socket corresponding to a service id. - bool StopAcceptingConnections(const std::string& service_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - bool IsAcceptingConnections(const std::string& service_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Establishes connection to WifiLan service that was might be started on - // another service with StartAcceptingConnections() using the same service_id. - // Blocks until connection is established, or server-side is terminated. - // Returns socket instance. On success, WifiLanSocket.IsValid() return true. - WifiLanSocket Connect(const std::string& service_id, - const NsdServiceInfo& service_info, - CancellationFlag* cancellation_flag) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Establishes connection to WifiLan service by ip address and port for - // bandwidth upgradation. - // Returns socket instance. On success, WifiLanSocket.IsValid() return true. - WifiLanSocket Connect(const std::string& service_id, - const std::string& ip_address, int port, - CancellationFlag* cancellation_flag) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Gets ip address + port for remote services on the network to identify and - // connect to this service. - // - // Credential is for the currently-hosted Wifi ServerSocket (if any). - std::pair<std::string, int> GetCredentials(const std::string& service_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - private: - struct AdvertisingInfo { - bool Empty() const { return nsd_service_infos.empty(); } - void Clear() { nsd_service_infos.clear(); } - void Add(const std::string& service_id, - const NsdServiceInfo& nsd_service_info) { - nsd_service_infos.insert({service_id, nsd_service_info}); - } - void Remove(const std::string& service_id) { - nsd_service_infos.erase(service_id); - } - bool Existed(const std::string& service_id) const { - return nsd_service_infos.contains(service_id); - } - NsdServiceInfo* GetServiceInfo(const std::string& service_id) { - const auto& it = nsd_service_infos.find(service_id); - if (it == nsd_service_infos.end()) { - return nullptr; - } - return &it->second; - } - - absl::flat_hash_map<std::string, NsdServiceInfo> nsd_service_infos; - }; - - struct DiscoveringInfo { - bool Empty() const { return service_ids.empty(); } - void Clear() { service_ids.clear(); } - void Add(const std::string& service_id) { service_ids.insert(service_id); } - void Remove(const std::string& service_id) { - service_ids.erase(service_id); - } - bool Existed(const std::string& service_id) const { - return service_ids.contains(service_id); - } - - absl::flat_hash_set<std::string> service_ids; - }; - - static constexpr int kMaxConcurrentAcceptLoops = 5; - - // Same as IsAvailable(), but must be called with mutex_ held. - bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Same as IsAdvertising(), but must be called with mutex_ held. - bool IsAdvertisingLocked(const std::string& service_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Same as IsDiscovering(), but must be called with mutex_ held. - bool IsDiscoveringLocked(const std::string& service_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Same as IsAcceptingConnections(), but must be called with mutex_ held. - bool IsAcceptingConnectionsLocked(const std::string& service_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Generates mDNS type. - std::string GenerateServiceType(const std::string& service_id); - - mutable Mutex mutex_; - WifiLanMedium medium_ ABSL_GUARDED_BY(mutex_); - AdvertisingInfo advertising_info_ ABSL_GUARDED_BY(mutex_); - DiscoveringInfo discovering_info_ ABSL_GUARDED_BY(mutex_); - - // A thread pool dedicated to running all the accept loops from - // StartAcceptingConnections(). - MultiThreadExecutor accept_loops_runner_{kMaxConcurrentAcceptLoops}; - - // A map of service_id -> ServerSocket. If map is non-empty, we - // are currently listening for incoming connections. - // WifiLanServerSocket instances are used from accept_loops_runner_, - // and thus require pointer stability. - absl::flat_hash_map<std::string, WifiLanServerSocket> server_sockets_ - ABSL_GUARDED_BY(mutex_); -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_WIFI_LAN_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/wifi_lan_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/wifi_lan_test.cc deleted file mode 100644 index 4640363b98d..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/wifi_lan_test.cc +++ /dev/null @@ -1,347 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/mediums/wifi_lan.h" - -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/strings/string_view.h" -#include "platform/base/medium_environment.h" -#include "platform/base/nsd_service_info.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/logging.h" -#include "platform/public/wifi_lan.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -using FeatureFlags = FeatureFlags::Flags; - -constexpr FeatureFlags kTestCases[] = { - FeatureFlags{ - .enable_cancellation_flag = true, - }, - FeatureFlags{ - .enable_cancellation_flag = false, - }, -}; - -constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000); -constexpr absl::string_view kServiceID{"com.google.location.nearby.apps.test"}; -constexpr absl::string_view kServiceInfoName{"ServiceInfoName"}; -constexpr absl::string_view kEndpointName{"EndpointName"}; -constexpr absl::string_view kEndpointInfoKey{"n"}; - -class WifiLanTest : public ::testing::TestWithParam<FeatureFlags> { - protected: - using DiscoveredServiceCallback = WifiLanMedium::DiscoveredServiceCallback; - - WifiLanTest() { env_.Stop(); } - - MediumEnvironment& env_{MediumEnvironment::Instance()}; -}; - -TEST_P(WifiLanTest, CanConnect) { - FeatureFlags feature_flags = GetParam(); - env_.SetFeatureFlags(feature_flags); - env_.Start(); - WifiLan wifi_lan_client; - WifiLan wifi_lan_server; - std::string service_id(kServiceID); - std::string service_info_name(kServiceInfoName); - std::string endpoint_info_name(kEndpointName); - CountDownLatch discovered_latch(1); - CountDownLatch accept_latch(1); - - WifiLanSocket socket_for_server; - EXPECT_TRUE(wifi_lan_server.StartAcceptingConnections( - service_id, - { - .accepted_cb = - [&socket_for_server, &accept_latch](WifiLanSocket socket) { - socket_for_server = std::move(socket); - accept_latch.CountDown(); - }, - })); - - NsdServiceInfo nsd_service_info; - nsd_service_info.SetServiceName(service_info_name); - nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey), - endpoint_info_name); - wifi_lan_server.StartAdvertising(service_id, nsd_service_info); - - NsdServiceInfo discovered_service_info; - wifi_lan_client.StartDiscovery( - service_id, - { - .service_discovered_cb = - [&discovered_latch, &discovered_service_info]( - NsdServiceInfo service_info, const std::string& service_id) { - NEARBY_LOGS(INFO) - << "Discovered service_info=" << &service_info; - discovered_service_info = service_info; - discovered_latch.CountDown(); - }, - }); - discovered_latch.Await(kWaitDuration).result(); - ASSERT_TRUE(discovered_service_info.IsValid()); - - CancellationFlag flag; - WifiLanSocket socket_for_client = - wifi_lan_client.Connect(service_id, discovered_service_info, &flag); - EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(wifi_lan_server.StopAcceptingConnections(service_id)); - EXPECT_TRUE(wifi_lan_server.StopAdvertising(service_id)); - EXPECT_TRUE(socket_for_server.IsValid()); - EXPECT_TRUE(socket_for_client.IsValid()); - env_.Stop(); -} - -TEST_P(WifiLanTest, CanCancelConnect) { - FeatureFlags feature_flags = GetParam(); - env_.SetFeatureFlags(feature_flags); - env_.Start(); - WifiLan wifi_lan_client; - WifiLan wifi_lan_server; - std::string service_id(kServiceID); - std::string service_info_name(kServiceInfoName); - std::string endpoint_info_name(kEndpointName); - CountDownLatch discovered_latch(1); - CountDownLatch accept_latch(1); - - WifiLanSocket socket_for_server; - EXPECT_TRUE(wifi_lan_server.StartAcceptingConnections( - service_id, - { - .accepted_cb = - [&socket_for_server, &accept_latch](WifiLanSocket socket) { - socket_for_server = std::move(socket); - accept_latch.CountDown(); - }, - })); - - NsdServiceInfo nsd_service_info; - nsd_service_info.SetServiceName(service_info_name); - nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey), - endpoint_info_name); - wifi_lan_server.StartAdvertising(service_id, nsd_service_info); - - NsdServiceInfo discovered_service_info; - wifi_lan_client.StartDiscovery( - service_id, - { - .service_discovered_cb = - [&discovered_latch, &discovered_service_info]( - NsdServiceInfo service_info, const std::string& service_id) { - NEARBY_LOGS(INFO) - << "Discovered service_info=" << &service_info; - discovered_service_info = service_info; - discovered_latch.CountDown(); - }, - }); - EXPECT_TRUE(discovered_latch.Await(kWaitDuration).result()); - ASSERT_TRUE(discovered_service_info.IsValid()); - - CancellationFlag flag(true); - WifiLanSocket socket_for_client = - wifi_lan_client.Connect(service_id, discovered_service_info, &flag); - // If FeatureFlag is disabled, Cancelled is false as no-op. - if (!feature_flags.enable_cancellation_flag) { - EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(wifi_lan_server.StopAcceptingConnections(service_id)); - EXPECT_TRUE(wifi_lan_server.StopAdvertising(service_id)); - EXPECT_TRUE(socket_for_server.IsValid()); - EXPECT_TRUE(socket_for_client.IsValid()); - } else { - EXPECT_FALSE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(wifi_lan_server.StopAcceptingConnections(service_id)); - EXPECT_TRUE(wifi_lan_server.StopAdvertising(service_id)); - EXPECT_FALSE(socket_for_server.IsValid()); - EXPECT_FALSE(socket_for_client.IsValid()); - } - env_.Stop(); -} - -INSTANTIATE_TEST_SUITE_P(ParametrisedWifiLanTest, WifiLanTest, - ::testing::ValuesIn(kTestCases)); - -TEST_F(WifiLanTest, CanConstructValidObject) { - env_.Start(); - WifiLan wifi_lan_a; - WifiLan wifi_lan_b; - std::string service_id(kServiceID); - - EXPECT_TRUE(wifi_lan_a.IsAvailable()); - EXPECT_TRUE(wifi_lan_b.IsAvailable()); - env_.Stop(); -} - -TEST_F(WifiLanTest, CanStartAdvertising) { - env_.Start(); - WifiLan wifi_lan_a; - std::string service_id(kServiceID); - std::string service_info_name(kServiceInfoName); - std::string endpoint_info_name(kEndpointName); - - EXPECT_TRUE(wifi_lan_a.StartAcceptingConnections(service_id, {})); - - NsdServiceInfo nsd_service_info; - nsd_service_info.SetServiceName(service_info_name); - nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey), - endpoint_info_name); - EXPECT_TRUE(wifi_lan_a.StartAdvertising(service_id, nsd_service_info)); - EXPECT_TRUE(wifi_lan_a.StopAdvertising(service_id)); - env_.Stop(); -} - -TEST_F(WifiLanTest, CanStartMultipleAdvertising) { - env_.Start(); - WifiLan wifi_lan_a; - std::string service_id_1(kServiceID); - std::string service_id_2("com.google.location.nearby.apps.test_1"); - std::string service_info_name_1(kServiceInfoName); - std::string service_info_name_2("ServiceInfoName_1"); - std::string endpoint_info_name(kEndpointName); - - EXPECT_TRUE(wifi_lan_a.StartAcceptingConnections(service_id_1, {})); - EXPECT_TRUE(wifi_lan_a.StartAcceptingConnections(service_id_2, {})); - - NsdServiceInfo nsd_service_info_1; - nsd_service_info_1.SetServiceName(service_info_name_1); - nsd_service_info_1.SetTxtRecord(std::string(kEndpointInfoKey), - endpoint_info_name); - NsdServiceInfo nsd_service_info_2; - nsd_service_info_2.SetServiceName(service_info_name_2); - nsd_service_info_2.SetTxtRecord(std::string(kEndpointInfoKey), - endpoint_info_name); - EXPECT_TRUE(wifi_lan_a.StartAdvertising(service_id_1, nsd_service_info_1)); - EXPECT_TRUE(wifi_lan_a.StartAdvertising(service_id_2, nsd_service_info_2)); - EXPECT_TRUE(wifi_lan_a.StopAdvertising(service_id_1)); - EXPECT_TRUE(wifi_lan_a.StopAdvertising(service_id_2)); - EXPECT_TRUE(wifi_lan_a.StopAcceptingConnections(service_id_1)); - EXPECT_TRUE(wifi_lan_a.StopAcceptingConnections(service_id_2)); - env_.Stop(); -} - -TEST_F(WifiLanTest, CanStartDiscovery) { - env_.Start(); - WifiLan wifi_lan_a; - std::string service_id(kServiceID); - - EXPECT_TRUE( - wifi_lan_a.StartDiscovery(service_id, DiscoveredServiceCallback{})); - EXPECT_TRUE(wifi_lan_a.StopDiscovery(service_id)); - env_.Stop(); -} - -TEST_F(WifiLanTest, CanStartMultipleDiscovery) { - env_.Start(); - WifiLan wifi_lan_a; - std::string service_id_1(kServiceID); - std::string service_id_2("com.google.location.nearby.apps.test_1"); - - EXPECT_TRUE( - wifi_lan_a.StartDiscovery(service_id_1, DiscoveredServiceCallback{})); - - EXPECT_TRUE( - wifi_lan_a.StartDiscovery(service_id_2, DiscoveredServiceCallback{})); - EXPECT_TRUE(wifi_lan_a.StopDiscovery(service_id_1)); - EXPECT_TRUE(wifi_lan_a.StopDiscovery(service_id_2)); - env_.Stop(); -} - -TEST_F(WifiLanTest, CanAdvertiseThatOtherMediumDiscover) { - env_.Start(); - WifiLan wifi_lan_a; - WifiLan wifi_lan_b; - std::string service_id(kServiceID); - std::string service_info_name(kServiceInfoName); - std::string endpoint_info_name(kEndpointName); - CountDownLatch discovered_latch(1); - CountDownLatch lost_latch(1); - - wifi_lan_b.StartDiscovery( - service_id, DiscoveredServiceCallback{ - .service_discovered_cb = - [&discovered_latch](NsdServiceInfo service_info, - const std::string& service_id) { - discovered_latch.CountDown(); - }, - .service_lost_cb = - [&lost_latch](NsdServiceInfo service_info, - const std::string& service_id) { - lost_latch.CountDown(); - }, - }); - - EXPECT_TRUE(wifi_lan_a.StartAcceptingConnections(service_id, {})); - - NsdServiceInfo nsd_service_info; - nsd_service_info.SetServiceName(service_info_name); - nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey), - endpoint_info_name); - EXPECT_TRUE(wifi_lan_a.StartAdvertising(service_id, nsd_service_info)); - EXPECT_TRUE(discovered_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(wifi_lan_a.StopAdvertising(service_id)); - EXPECT_TRUE(lost_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(wifi_lan_b.StopDiscovery(service_id)); - env_.Stop(); -} - -TEST_F(WifiLanTest, CanDiscoverThatOtherMediumAdvertise) { - env_.Start(); - WifiLan wifi_lan_a; - WifiLan wifi_lan_b; - std::string service_id(kServiceID); - std::string service_info_name(kServiceInfoName); - std::string endpoint_info_name(kEndpointName); - CountDownLatch discovered_latch(1); - CountDownLatch lost_latch(1); - - EXPECT_TRUE(wifi_lan_b.StartAcceptingConnections(service_id, {})); - - NsdServiceInfo nsd_service_info; - nsd_service_info.SetServiceName(service_info_name); - nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey), - endpoint_info_name); - wifi_lan_b.StartAdvertising(service_id, nsd_service_info); - - EXPECT_TRUE(wifi_lan_a.StartDiscovery( - service_id, DiscoveredServiceCallback{ - .service_discovered_cb = - [&discovered_latch](NsdServiceInfo service_info, - const std::string& service_id) { - discovered_latch.CountDown(); - }, - .service_lost_cb = - [&lost_latch](NsdServiceInfo service_info, - const std::string& service_id) { - lost_latch.CountDown(); - }, - })); - EXPECT_TRUE(discovered_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(wifi_lan_b.StopAdvertising(service_id)); - EXPECT_TRUE(lost_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(wifi_lan_a.StopDiscovery(service_id)); - env_.Stop(); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/message_lite.h b/chromium/third_party/nearby/src/cpp/core/internal/message_lite.h deleted file mode 100644 index 5ce9d91e88a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/message_lite.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MESSAGE_LITE_H_ -#define CORE_INTERNAL_MESSAGE_LITE_H_ - -#include "google/protobuf/message_lite.h" - -#endif // CORE_INTERNAL_MESSAGE_LITE_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mock_service_controller.h b/chromium/third_party/nearby/src/cpp/core/internal/mock_service_controller.h deleted file mode 100644 index 30173eeb1f7..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mock_service_controller.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MOCK_SERVICE_CONTROLLER_H_ -#define CORE_INTERNAL_MOCK_SERVICE_CONTROLLER_H_ - -#include "gmock/gmock.h" -#include "core/internal/service_controller.h" - -namespace location { -namespace nearby { -namespace connections { - -/* Mock implementation for ServiceController: - * All methods execute asynchronously (in a private executor thread). - * To synchronise, two approaches may be used: - * 1. For methods that have result callback, we use it to unblock main thread. - * 2. For methods that do not have callbacks, we provide a mock implementation - * that unblocks main thread. - */ -class MockServiceController : public ServiceController { - public: - MOCK_METHOD(void, Stop, (), (override)); - MOCK_METHOD(Status, StartAdvertising, - (ClientProxy * client, const std::string& service_id, - const ConnectionOptions& options, - const ConnectionRequestInfo& info), - (override)); - - MOCK_METHOD(void, StopAdvertising, (ClientProxy * client), (override)); - - MOCK_METHOD(Status, StartDiscovery, - (ClientProxy * client, const std::string& service_id, - const ConnectionOptions& options, - const DiscoveryListener& listener), - (override)); - - MOCK_METHOD(void, StopDiscovery, (ClientProxy * client), (override)); - - MOCK_METHOD(void, InjectEndpoint, - (ClientProxy * client, const std::string& service_id, - const OutOfBandConnectionMetadata& metadata), - (override)); - - MOCK_METHOD(Status, RequestConnection, - (ClientProxy * client, const std::string& endpoint_id, - const ConnectionRequestInfo& info, - const ConnectionOptions& options), - (override)); - - MOCK_METHOD(Status, AcceptConnection, - (ClientProxy * client, const std::string& endpoint_id, - const PayloadListener& listener), - (override)); - - MOCK_METHOD(Status, RejectConnection, - (ClientProxy * client, const std::string& endpoint_id), - (override)); - - MOCK_METHOD(void, InitiateBandwidthUpgrade, - (ClientProxy * client, const std::string& endpoint_id), - (override)); - - MOCK_METHOD(void, SendPayload, - (ClientProxy * client, - const std::vector<std::string>& endpoint_ids, Payload payload), - (override)); - - MOCK_METHOD(Status, CancelPayload, - (ClientProxy * client, std::int64_t payload_id), (override)); - - MOCK_METHOD(void, DisconnectFromEndpoint, - (ClientProxy * client, const std::string& endpoint_id), - (override)); -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MOCK_SERVICE_CONTROLLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mock_service_controller_router.h b/chromium/third_party/nearby/src/cpp/core/internal/mock_service_controller_router.h deleted file mode 100644 index 32d8d445ea3..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mock_service_controller_router.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MOCK_SERVICE_CONTROLLER_ROUTER_H_ -#define CORE_INTERNAL_MOCK_SERVICE_CONTROLLER_ROUTER_H_ - -#include "gmock/gmock.h" -#include "core/internal/service_controller_router.h" - -namespace location { -namespace nearby { -namespace connections { - -class MockServiceControllerRouter : public ServiceControllerRouter { - public: - MOCK_METHOD(void, StartAdvertising, - (ClientProxy * client, absl::string_view service_id, - const ConnectionOptions& options, - const ConnectionRequestInfo& info, - const ResultCallback& callback), - (override)); - - MOCK_METHOD(void, StopAdvertising, - (ClientProxy * client, const ResultCallback& callback), - (override)); - - MOCK_METHOD(void, StartDiscovery, - (ClientProxy * client, absl::string_view service_id, - const ConnectionOptions& options, - const DiscoveryListener& listener, - const ResultCallback& callback), - (override)); - - MOCK_METHOD(void, StopDiscovery, - (ClientProxy * client, const ResultCallback& callback), - (override)); - - MOCK_METHOD(void, InjectEndpoint, - (ClientProxy * client, absl::string_view service_id, - const OutOfBandConnectionMetadata& metadata, - const ResultCallback& callback), - (override)); - - MOCK_METHOD(void, RequestConnection, - (ClientProxy * client, absl::string_view endpoint_id, - const ConnectionRequestInfo& info, - const ConnectionOptions& options, - const ResultCallback& callback), - (override)); - - MOCK_METHOD(void, AcceptConnection, - (ClientProxy * client, absl::string_view endpoint_id, - const PayloadListener& listener, const ResultCallback& callback), - (override)); - - MOCK_METHOD(void, RejectConnection, - (ClientProxy * client, absl::string_view endpoint_id, - const ResultCallback& callback), - (override)); - - MOCK_METHOD(void, InitiateBandwidthUpgrade, - (ClientProxy * client, absl::string_view endpoint_id, - const ResultCallback& callback), - (override)); - - MOCK_METHOD(void, SendPayload, - (ClientProxy * client, absl::Span<const std::string> endpoint_ids, - Payload payload, const ResultCallback& callback), - (override)); - - MOCK_METHOD(void, CancelPayload, - (ClientProxy * client, std::uint64_t payload_id, - const ResultCallback& callback), - (override)); - - MOCK_METHOD(void, DisconnectFromEndpoint, - (ClientProxy * client, absl::string_view endpoint_id, - const ResultCallback& callback), - (override)); - - MOCK_METHOD(void, StopAllEndpoints, - (ClientProxy * client, const ResultCallback& callback), - (override)); -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MOCK_SERVICE_CONTROLLER_ROUTER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames.cc b/chromium/third_party/nearby/src/cpp/core/internal/offline_frames.cc deleted file mode 100644 index f2862c3e4bc..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames.cc +++ /dev/null @@ -1,502 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/offline_frames.h" - -#include <memory> -#include <utility> - -#include "core/internal/message_lite.h" -#include "core/internal/offline_frames_validator.h" -#include "core/status.h" -#include "platform/base/byte_array.h" - -namespace location { -namespace nearby { -namespace connections { -namespace parser { -namespace { - -using ExceptionOrOfflineFrame = ExceptionOr<OfflineFrame>; -using MessageLite = ::google::protobuf::MessageLite; - -ByteArray ToBytes(OfflineFrame&& frame) { - ByteArray bytes(frame.ByteSizeLong()); - frame.set_version(OfflineFrame::V1); - frame.SerializeToArray(bytes.data(), bytes.size()); - return bytes; -} - -} // namespace - -ExceptionOrOfflineFrame FromBytes(const ByteArray& bytes) { - OfflineFrame frame; - - if (frame.ParseFromString(std::string(bytes))) { - Exception validation_exception = EnsureValidOfflineFrame(frame); - if (validation_exception.Raised()) { - return ExceptionOrOfflineFrame(validation_exception); - } - return ExceptionOrOfflineFrame(std::move(frame)); - } else { - return ExceptionOrOfflineFrame(Exception::kInvalidProtocolBuffer); - } -} - -V1Frame::FrameType GetFrameType(const OfflineFrame& frame) { - if ((frame.version() == OfflineFrame::V1) && frame.has_v1()) { - return frame.v1().type(); - } - - return V1Frame::UNKNOWN_FRAME_TYPE; -} - -ByteArray ForConnectionRequest(const std::string& endpoint_id, - const ByteArray& endpoint_info, - std::int32_t nonce, bool supports_5_ghz, - const std::string& bssid, - const std::vector<Medium>& mediums, - std::int32_t keep_alive_interval_millis, - std::int32_t keep_alive_timeout_millis) { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::CONNECTION_REQUEST); - auto* connection_request = v1_frame->mutable_connection_request(); - if (!endpoint_id.empty()) connection_request->set_endpoint_id(endpoint_id); - if (!endpoint_info.Empty()) { - connection_request->set_endpoint_name(std::string(endpoint_info)); - connection_request->set_endpoint_info(std::string(endpoint_info)); - } - connection_request->set_nonce(nonce); - auto* medium_metadata = connection_request->mutable_medium_metadata(); - medium_metadata->set_supports_5_ghz(supports_5_ghz); - if (!bssid.empty()) medium_metadata->set_bssid(bssid); - if (!mediums.empty()) { - for (const auto& medium : mediums) { - connection_request->add_mediums(MediumToConnectionRequestMedium(medium)); - } - } - if (keep_alive_interval_millis > 0) { - connection_request->set_keep_alive_interval_millis( - keep_alive_interval_millis); - } - if (keep_alive_timeout_millis > 0) { - connection_request->set_keep_alive_timeout_millis( - keep_alive_timeout_millis); - } - - return ToBytes(std::move(frame)); -} - -ByteArray ForConnectionResponse(std::int32_t status) { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::CONNECTION_RESPONSE); - auto* sub_frame = v1_frame->mutable_connection_response(); - - // For backward compatiblility, here still sets both status and response - // parameters until the response feature is roll out in all supported - // devices. - sub_frame->set_status(status); - sub_frame->set_response(status == Status::kSuccess - ? ConnectionResponseFrame::ACCEPT - : ConnectionResponseFrame::REJECT); - - return ToBytes(std::move(frame)); -} - -ByteArray ForDataPayloadTransfer( - const PayloadTransferFrame::PayloadHeader& header, - const PayloadTransferFrame::PayloadChunk& chunk) { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::PAYLOAD_TRANSFER); - auto* sub_frame = v1_frame->mutable_payload_transfer(); - sub_frame->set_packet_type(PayloadTransferFrame::DATA); - *sub_frame->mutable_payload_header() = header; - *sub_frame->mutable_payload_chunk() = chunk; - - return ToBytes(std::move(frame)); -} - -ByteArray ForControlPayloadTransfer( - const PayloadTransferFrame::PayloadHeader& header, - const PayloadTransferFrame::ControlMessage& control) { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::PAYLOAD_TRANSFER); - auto* sub_frame = v1_frame->mutable_payload_transfer(); - sub_frame->set_packet_type(PayloadTransferFrame::CONTROL); - *sub_frame->mutable_payload_header() = header; - *sub_frame->mutable_control_message() = control; - - return ToBytes(std::move(frame)); -} - -ByteArray ForBwuWifiHotspotPathAvailable(const std::string& ssid, - const std::string& password, - std::int32_t port, - const std::string& gateway, - bool supports_disabling_encryption) { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION); - auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation(); - sub_frame->set_event_type( - BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE); - auto* upgrade_path_info = sub_frame->mutable_upgrade_path_info(); - upgrade_path_info->set_medium(UpgradePathInfo::WIFI_HOTSPOT); - upgrade_path_info->set_supports_client_introduction_ack(true); - upgrade_path_info->set_supports_disabling_encryption( - supports_disabling_encryption); - auto* wifi_hotspot_credentials = - upgrade_path_info->mutable_wifi_hotspot_credentials(); - wifi_hotspot_credentials->set_ssid(ssid); - wifi_hotspot_credentials->set_password(password); - wifi_hotspot_credentials->set_port(port); - wifi_hotspot_credentials->set_gateway(gateway); - - return ToBytes(std::move(frame)); -} - -ByteArray ForBwuWifiLanPathAvailable(const std::string& ip_address, - std::int32_t port) { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION); - auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation(); - sub_frame->set_event_type( - BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE); - auto* upgrade_path_info = sub_frame->mutable_upgrade_path_info(); - upgrade_path_info->set_medium(UpgradePathInfo::WIFI_LAN); - upgrade_path_info->set_supports_client_introduction_ack(true); - auto* wifi_lan_socket = upgrade_path_info->mutable_wifi_lan_socket(); - wifi_lan_socket->set_ip_address(ip_address); - wifi_lan_socket->set_wifi_port(port); - - return ToBytes(std::move(frame)); -} - -ByteArray ForBwuWifiAwarePathAvailable(const std::string& service_id, - const std::string& service_info, - const std::string& password, - bool supports_disabling_encryption) { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION); - auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation(); - sub_frame->set_event_type( - BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE); - auto* upgrade_path_info = sub_frame->mutable_upgrade_path_info(); - upgrade_path_info->set_medium(UpgradePathInfo::WIFI_AWARE); - upgrade_path_info->set_supports_client_introduction_ack(true); - upgrade_path_info->set_supports_disabling_encryption( - supports_disabling_encryption); - auto* wifi_aware_credentials = - upgrade_path_info->mutable_wifi_aware_credentials(); - wifi_aware_credentials->set_service_id(service_id); - wifi_aware_credentials->set_service_info(service_info); - if (!password.empty()) wifi_aware_credentials->set_password(password); - - return ToBytes(std::move(frame)); -} - -ByteArray ForBwuWifiDirectPathAvailable(const std::string& ssid, - const std::string& password, - std::int32_t port, - std::int32_t frequency, - bool supports_disabling_encryption) { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION); - auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation(); - sub_frame->set_event_type( - BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE); - auto* upgrade_path_info = sub_frame->mutable_upgrade_path_info(); - upgrade_path_info->set_medium(UpgradePathInfo::WIFI_DIRECT); - upgrade_path_info->set_supports_client_introduction_ack(true); - upgrade_path_info->set_supports_disabling_encryption( - supports_disabling_encryption); - auto* wifi_direct_credentials = - upgrade_path_info->mutable_wifi_direct_credentials(); - wifi_direct_credentials->set_ssid(ssid); - wifi_direct_credentials->set_password(password); - wifi_direct_credentials->set_port(port); - wifi_direct_credentials->set_frequency(frequency); - - return ToBytes(std::move(frame)); -} - -ByteArray ForBwuBluetoothPathAvailable(const std::string& service_id, - const std::string& mac_address) { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION); - auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation(); - sub_frame->set_event_type( - BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE); - auto* upgrade_path_info = sub_frame->mutable_upgrade_path_info(); - upgrade_path_info->set_medium(UpgradePathInfo::BLUETOOTH); - upgrade_path_info->set_supports_client_introduction_ack(true); - auto* bluetooth_credentials = - upgrade_path_info->mutable_bluetooth_credentials(); - bluetooth_credentials->set_mac_address(mac_address); - bluetooth_credentials->set_service_name(service_id); - - return ToBytes(std::move(frame)); -} - -ByteArray ForBwuWebrtcPathAvailable(const std::string& peer_id, - const LocationHint& location_hint) { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION); - auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation(); - sub_frame->set_event_type( - BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE); - auto* upgrade_path_info = sub_frame->mutable_upgrade_path_info(); - upgrade_path_info->set_medium(UpgradePathInfo::WEB_RTC); - upgrade_path_info->set_supports_client_introduction_ack(true); - auto* webrtc_credentials = upgrade_path_info->mutable_web_rtc_credentials(); - webrtc_credentials->set_peer_id(peer_id); - auto* local_location_hint = webrtc_credentials->mutable_location_hint(); - *local_location_hint = location_hint; - - return ToBytes(std::move(frame)); -} - -ByteArray ForBwuLastWrite() { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION); - auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation(); - sub_frame->set_event_type( - BandwidthUpgradeNegotiationFrame::LAST_WRITE_TO_PRIOR_CHANNEL); - - return ToBytes(std::move(frame)); -} - -ByteArray ForBwuSafeToClose() { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION); - auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation(); - sub_frame->set_event_type( - BandwidthUpgradeNegotiationFrame::SAFE_TO_CLOSE_PRIOR_CHANNEL); - - return ToBytes(std::move(frame)); -} - -ByteArray ForBwuIntroduction(const std::string& endpoint_id) { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION); - auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation(); - sub_frame->set_event_type( - BandwidthUpgradeNegotiationFrame::CLIENT_INTRODUCTION); - auto* client_introduction = sub_frame->mutable_client_introduction(); - client_introduction->set_endpoint_id(endpoint_id); - - return ToBytes(std::move(frame)); -} - -ByteArray ForBwuIntroductionAck() { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION); - auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation(); - sub_frame->set_event_type( - BandwidthUpgradeNegotiationFrame::CLIENT_INTRODUCTION_ACK); - - return ToBytes(std::move(frame)); -} - -ByteArray ForBwuFailure(const UpgradePathInfo& info) { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION); - auto* sub_frame = v1_frame->mutable_bandwidth_upgrade_negotiation(); - sub_frame->set_event_type(BandwidthUpgradeNegotiationFrame::UPGRADE_FAILURE); - auto* upgrade_path_info = sub_frame->mutable_upgrade_path_info(); - *upgrade_path_info = info; - - return ToBytes(std::move(frame)); -} - -ByteArray ForKeepAlive() { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::KEEP_ALIVE); - v1_frame->mutable_keep_alive(); - - return ToBytes(std::move(frame)); -} - -ByteArray ForDisconnection() { - OfflineFrame frame; - - frame.set_version(OfflineFrame::V1); - auto* v1_frame = frame.mutable_v1(); - v1_frame->set_type(V1Frame::DISCONNECTION); - v1_frame->mutable_disconnection(); - - return ToBytes(std::move(frame)); -} - -UpgradePathInfo::Medium MediumToUpgradePathInfoMedium(Medium medium) { - switch (medium) { - case Medium::MDNS: - return UpgradePathInfo::MDNS; - case Medium::BLUETOOTH: - return UpgradePathInfo::BLUETOOTH; - case Medium::WIFI_HOTSPOT: - return UpgradePathInfo::WIFI_HOTSPOT; - case Medium::BLE: - return UpgradePathInfo::BLE; - case Medium::WIFI_LAN: - return UpgradePathInfo::WIFI_LAN; - case Medium::WIFI_AWARE: - return UpgradePathInfo::WIFI_AWARE; - case Medium::NFC: - return UpgradePathInfo::NFC; - case Medium::WIFI_DIRECT: - return UpgradePathInfo::WIFI_DIRECT; - case Medium::WEB_RTC: - return UpgradePathInfo::WEB_RTC; - default: - return UpgradePathInfo::UNKNOWN_MEDIUM; - } -} - -Medium UpgradePathInfoMediumToMedium(UpgradePathInfo::Medium medium) { - switch (medium) { - case UpgradePathInfo::MDNS: - return Medium::MDNS; - case UpgradePathInfo::BLUETOOTH: - return Medium::BLUETOOTH; - case UpgradePathInfo::WIFI_HOTSPOT: - return Medium::WIFI_HOTSPOT; - case UpgradePathInfo::BLE: - return Medium::BLE; - case UpgradePathInfo::WIFI_LAN: - return Medium::WIFI_LAN; - case UpgradePathInfo::WIFI_AWARE: - return Medium::WIFI_AWARE; - case UpgradePathInfo::NFC: - return Medium::NFC; - case UpgradePathInfo::WIFI_DIRECT: - return Medium::WIFI_DIRECT; - case UpgradePathInfo::WEB_RTC: - return Medium::WEB_RTC; - default: - return Medium::UNKNOWN_MEDIUM; - } -} - -ConnectionRequestFrame::Medium MediumToConnectionRequestMedium(Medium medium) { - switch (medium) { - case Medium::MDNS: - return ConnectionRequestFrame::MDNS; - case Medium::BLUETOOTH: - return ConnectionRequestFrame::BLUETOOTH; - case Medium::WIFI_HOTSPOT: - return ConnectionRequestFrame::WIFI_HOTSPOT; - case Medium::BLE: - return ConnectionRequestFrame::BLE; - case Medium::WIFI_LAN: - return ConnectionRequestFrame::WIFI_LAN; - case Medium::WIFI_AWARE: - return ConnectionRequestFrame::WIFI_AWARE; - case Medium::NFC: - return ConnectionRequestFrame::NFC; - case Medium::WIFI_DIRECT: - return ConnectionRequestFrame::WIFI_DIRECT; - case Medium::WEB_RTC: - return ConnectionRequestFrame::WEB_RTC; - default: - return ConnectionRequestFrame::UNKNOWN_MEDIUM; - } -} - -Medium ConnectionRequestMediumToMedium(ConnectionRequestFrame::Medium medium) { - switch (medium) { - case ConnectionRequestFrame::MDNS: - return Medium::MDNS; - case ConnectionRequestFrame::BLUETOOTH: - return Medium::BLUETOOTH; - case ConnectionRequestFrame::WIFI_HOTSPOT: - return Medium::WIFI_HOTSPOT; - case ConnectionRequestFrame::BLE: - return Medium::BLE; - case ConnectionRequestFrame::WIFI_LAN: - return Medium::WIFI_LAN; - case ConnectionRequestFrame::WIFI_AWARE: - return Medium::WIFI_AWARE; - case ConnectionRequestFrame::NFC: - return Medium::NFC; - case ConnectionRequestFrame::WIFI_DIRECT: - return Medium::WIFI_DIRECT; - case ConnectionRequestFrame::WEB_RTC: - return Medium::WEB_RTC; - default: - return Medium::UNKNOWN_MEDIUM; - } -} - -std::vector<Medium> ConnectionRequestMediumsToMediums( - const ConnectionRequestFrame& frame) { - std::vector<Medium> result; - for (const auto& int_medium : frame.mediums()) { - result.push_back(ConnectionRequestMediumToMedium( - static_cast<ConnectionRequestFrame::Medium>(int_medium))); - } - return result; -} - -} // namespace parser -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames.h b/chromium/third_party/nearby/src/cpp/core/internal/offline_frames.h deleted file mode 100644 index 74db1071177..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames.h +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_OFFLINE_FRAMES_H_ -#define CORE_INTERNAL_OFFLINE_FRAMES_H_ - -#include <cstdint> -#include <vector> - -#include "core/options.h" -#include "platform/base/byte_array.h" -#include "platform/base/exception.h" -#include "proto/connections/offline_wire_formats.pb.h" - -namespace location { -namespace nearby { -namespace connections { -namespace parser { - -using UpgradePathInfo = BandwidthUpgradeNegotiationFrame::UpgradePathInfo; - -// Serialize/Deserialize Nearby Connections Protocol messages. - -// Parses incoming message. -// Returns OfflineFrame if parser was able to understand it, or -// Exception::kInvalidProtocolBuffer, if parser failed. -ExceptionOr<OfflineFrame> FromBytes(const ByteArray& offline_frame_bytes); - -// Returns FrameType of a parsed message, or -// V1Frame::UNKNOWN_FRAME_TYPE, if frame contents is not recognized. -V1Frame::FrameType GetFrameType(const OfflineFrame& offline_frame); - -// Builds Connection Request / Response messages. -ByteArray ForConnectionRequest(const std::string& endpoint_id, - const ByteArray& endpoint_info, - std::int32_t nonce, bool supports_5_ghz, - const std::string& bssid, - const std::vector<Medium>& mediums, - std::int32_t keep_alive_interval_millis, - std::int32_t keep_alive_timeout_millis); -ByteArray ForConnectionResponse(std::int32_t status); - -// Builds Payload transfer messages. -ByteArray ForDataPayloadTransfer( - const PayloadTransferFrame::PayloadHeader& header, - const PayloadTransferFrame::PayloadChunk& chunk); -ByteArray ForControlPayloadTransfer( - const PayloadTransferFrame::PayloadHeader& header, - const PayloadTransferFrame::ControlMessage& control); - -// Builds Bandwidth Upgrade [BWU] messages. -ByteArray ForBwuIntroduction(const std::string& endpoint_id); -ByteArray ForBwuIntroductionAck(); -ByteArray ForBwuWifiHotspotPathAvailable(const std::string& ssid, - const std::string& password, - std::int32_t port, - const std::string& gateway, - bool supports_disabling_encryption); -ByteArray ForBwuWifiLanPathAvailable(const std::string& ip_address, - std::int32_t port); -ByteArray ForBwuWifiAwarePathAvailable(const std::string& service_id, - const std::string& service_info, - const std::string& password, - bool supports_disabling_encryption); -ByteArray ForBwuWifiDirectPathAvailable(const std::string& ssid, - const std::string& password, - std::int32_t port, - std::int32_t frequency, - bool supports_disabling_encryption); -ByteArray ForBwuBluetoothPathAvailable(const std::string& service_id, - const std::string& mac_address); -ByteArray ForBwuWebrtcPathAvailable(const std::string& peer_id, - const LocationHint& location_hint_a); -ByteArray ForBwuFailure(const UpgradePathInfo& info); -ByteArray ForBwuLastWrite(); -ByteArray ForBwuSafeToClose(); - -ByteArray ForKeepAlive(); -ByteArray ForDisconnection(); - -UpgradePathInfo::Medium MediumToUpgradePathInfoMedium(Medium medium); -Medium UpgradePathInfoMediumToMedium(UpgradePathInfo::Medium medium); - -ConnectionRequestFrame::Medium MediumToConnectionRequestMedium(Medium medium); -Medium ConnectionRequestMediumToMedium(ConnectionRequestFrame::Medium medium); -std::vector<Medium> ConnectionRequestMediumsToMediums( - const ConnectionRequestFrame& connection_request_frame); - -} // namespace parser -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_OFFLINE_FRAMES_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/offline_frames_test.cc deleted file mode 100644 index 3be49db1e33..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames_test.cc +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/offline_frames.h" - -#include <array> -#include <memory> -#include <utility> -#include <vector> - -#include "absl/strings/string_view.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "platform/base/byte_array.h" -#include "proto/connections/offline_wire_formats.pb.h" - -namespace location { -namespace nearby { -namespace connections { -namespace parser { -namespace { - -using Medium = proto::connections::Medium; -using ::testing::EqualsProto; - -constexpr absl::string_view kEndpointId{"ABC"}; -constexpr absl::string_view kEndpointName{"XYZ"}; -constexpr int kNonce = 1234; -constexpr bool kSupports5ghz = true; -constexpr absl::string_view kBssid{"FF:FF:FF:FF:FF:FF"}; -constexpr std::array<Medium, 9> kMediums = { - Medium::MDNS, Medium::BLUETOOTH, Medium::WIFI_HOTSPOT, - Medium::BLE, Medium::WIFI_LAN, Medium::WIFI_AWARE, - Medium::NFC, Medium::WIFI_DIRECT, Medium::WEB_RTC, -}; -constexpr int kKeepAliveIntervalMillis = 1000; -constexpr int kKeepAliveTimeoutMillis = 5000; - -TEST(OfflineFramesTest, CanParseMessageFromBytes) { - OfflineFrame tx_message; - - { - tx_message.set_version(OfflineFrame::V1); - auto* v1_frame = tx_message.mutable_v1(); - auto* sub_frame = v1_frame->mutable_connection_request(); - - v1_frame->set_type(V1Frame::CONNECTION_REQUEST); - // OSS matchers don't like implicitly comparing string_views to strings. - sub_frame->set_endpoint_id(std::string(kEndpointId)); - sub_frame->set_endpoint_name(std::string(kEndpointName)); - sub_frame->set_endpoint_info(std::string(kEndpointName)); - sub_frame->set_nonce(kNonce); - sub_frame->set_keep_alive_interval_millis(kKeepAliveIntervalMillis); - sub_frame->set_keep_alive_timeout_millis(kKeepAliveTimeoutMillis); - auto* medium_metadata = sub_frame->mutable_medium_metadata(); - - medium_metadata->set_supports_5_ghz(kSupports5ghz); - medium_metadata->set_bssid(kBssid); - - for (auto& medium : kMediums) { - sub_frame->add_mediums(MediumToConnectionRequestMedium(medium)); - } - } - auto serialized_bytes = ByteArray(tx_message.SerializeAsString()); - auto ret_value = FromBytes(serialized_bytes); - ASSERT_TRUE(ret_value.ok()); - const auto& rx_message = ret_value.result(); - EXPECT_THAT(rx_message, EqualsProto(tx_message)); - EXPECT_EQ(GetFrameType(rx_message), V1Frame::CONNECTION_REQUEST); - EXPECT_EQ( - ConnectionRequestMediumsToMediums(rx_message.v1().connection_request()), - std::vector(kMediums.begin(), kMediums.end())); -} - -TEST(OfflineFramesTest, CanGenerateConnectionRequest) { - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: CONNECTION_REQUEST - connection_request: < - endpoint_id: "ABC" - endpoint_name: "XYZ" - endpoint_info: "XYZ" - nonce: 1234 - medium_metadata: < supports_5_ghz: true bssid: "FF:FF:FF:FF:FF:FF" > - mediums: MDNS - mediums: BLUETOOTH - mediums: WIFI_HOTSPOT - mediums: BLE - mediums: WIFI_LAN - mediums: WIFI_AWARE - mediums: NFC - mediums: WIFI_DIRECT - mediums: WEB_RTC - keep_alive_interval_millis: 1000 - keep_alive_timeout_millis: 5000 - > - >)pb"; - ByteArray bytes = ForConnectionRequest( - std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, std::string(kBssid), - std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis, - kKeepAliveTimeoutMillis); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -TEST(OfflineFramesTest, CanGenerateConnectionResponse) { - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: CONNECTION_RESPONSE - connection_response: < status: 1 response: REJECT > - >)pb"; - ByteArray bytes = ForConnectionResponse(1); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -TEST(OfflineFramesTest, CanGenerateControlPayloadTransfer) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::ControlMessage control; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_total_size(1024); - control.set_event(PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED); - control.set_offset(150); - - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: PAYLOAD_TRANSFER - payload_transfer: < - packet_type: CONTROL, - payload_header: < type: BYTES id: 12345 total_size: 1024 > - control_message: < event: PAYLOAD_CANCELED offset: 150 > - > - >)pb"; - ByteArray bytes = ForControlPayloadTransfer(header, control); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -TEST(OfflineFramesTest, CanGenerateDataPayloadTransfer) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::PayloadChunk chunk; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_total_size(1024); - chunk.set_body("payload data"); - chunk.set_offset(150); - chunk.set_flags(1); - - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: PAYLOAD_TRANSFER - payload_transfer: < - packet_type: DATA, - payload_header: < type: BYTES id: 12345 total_size: 1024 > - payload_chunk: < flags: 1 offset: 150 body: "payload data" > - > - >)pb"; - ByteArray bytes = ForDataPayloadTransfer(header, chunk); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -TEST(OfflineFramesTest, CanGenerateBwuWifiHotspotPathAvailable) { - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: BANDWIDTH_UPGRADE_NEGOTIATION - bandwidth_upgrade_negotiation: < - event_type: UPGRADE_PATH_AVAILABLE - upgrade_path_info: < - medium: WIFI_HOTSPOT - wifi_hotspot_credentials: < - ssid: "ssid" - password: "password" - port: 1234 - gateway: "0.0.0.0" - > - supports_disabling_encryption: false - supports_client_introduction_ack: true - > - > - >)pb"; - ByteArray bytes = ForBwuWifiHotspotPathAvailable("ssid", "password", 1234, - "0.0.0.0", false); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -TEST(OfflineFramesTest, CanGenerateBwuWifiLanPathAvailable) { - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: BANDWIDTH_UPGRADE_NEGOTIATION - bandwidth_upgrade_negotiation: < - event_type: UPGRADE_PATH_AVAILABLE - upgrade_path_info: < - medium: WIFI_LAN - wifi_lan_socket: < ip_address: "\x01\x02\x03\x04" wifi_port: 1234 > - supports_client_introduction_ack: true - > - > - >)pb"; - ByteArray bytes = ForBwuWifiLanPathAvailable("\x01\x02\x03\x04", 1234); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -TEST(OfflineFramesTest, CanGenerateBwuWifiAwarePathAvailable) { - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: BANDWIDTH_UPGRADE_NEGOTIATION - bandwidth_upgrade_negotiation: < - event_type: UPGRADE_PATH_AVAILABLE - upgrade_path_info: < - medium: WIFI_AWARE - wifi_aware_credentials: < - service_id: "service_id" - service_info: "service_info" - password: "password" - > - supports_disabling_encryption: false - supports_client_introduction_ack: true - > - > - >)pb"; - ByteArray bytes = ForBwuWifiAwarePathAvailable("service_id", "service_info", - "password", false); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -TEST(OfflineFramesTest, CanGenerateBwuWifiDirectPathAvailable) { - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: BANDWIDTH_UPGRADE_NEGOTIATION - bandwidth_upgrade_negotiation: < - event_type: UPGRADE_PATH_AVAILABLE - upgrade_path_info: < - medium: WIFI_DIRECT - wifi_direct_credentials: < - ssid: "DIRECT-A0-0123456789AB" - password: "password" - port: 1000 - frequency: 1000 - > - supports_disabling_encryption: false - supports_client_introduction_ack: true - > - > - >)pb"; - ByteArray bytes = ForBwuWifiDirectPathAvailable( - "DIRECT-A0-0123456789AB", "password", 1000, 1000, false); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -TEST(OfflineFramesTest, CanGenerateBwuBluetoothPathAvailable) { - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: BANDWIDTH_UPGRADE_NEGOTIATION - bandwidth_upgrade_negotiation: < - event_type: UPGRADE_PATH_AVAILABLE - upgrade_path_info: < - medium: BLUETOOTH - bluetooth_credentials: < - service_name: "service" - mac_address: "\x11\x22\x33\x44\x55\x66" - > - supports_client_introduction_ack: true - > - > - >)pb"; - ByteArray bytes = - ForBwuBluetoothPathAvailable("service", "\x11\x22\x33\x44\x55\x66"); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -TEST(OfflineFramesTest, CanGenerateBwuLastWrite) { - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: BANDWIDTH_UPGRADE_NEGOTIATION - bandwidth_upgrade_negotiation: < event_type: LAST_WRITE_TO_PRIOR_CHANNEL > - >)pb"; - ByteArray bytes = ForBwuLastWrite(); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -TEST(OfflineFramesTest, CanGenerateBwuSafeToClose) { - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: BANDWIDTH_UPGRADE_NEGOTIATION - bandwidth_upgrade_negotiation: < event_type: SAFE_TO_CLOSE_PRIOR_CHANNEL > - >)pb"; - ByteArray bytes = ForBwuSafeToClose(); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -TEST(OfflineFramesTest, CanGenerateBwuIntroduction) { - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: BANDWIDTH_UPGRADE_NEGOTIATION - bandwidth_upgrade_negotiation: < - event_type: CLIENT_INTRODUCTION - client_introduction: < endpoint_id: "ABC" > - > - >)pb"; - ByteArray bytes = ForBwuIntroduction(std::string(kEndpointId)); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -TEST(OfflineFramesTest, CanGenerateKeepAlive) { - constexpr char kExpected[] = - R"pb( - version: V1 - v1: < - type: KEEP_ALIVE - keep_alive: <> - >)pb"; - ByteArray bytes = ForKeepAlive(); - auto response = FromBytes(bytes); - ASSERT_TRUE(response.ok()); - OfflineFrame message = FromBytes(bytes).result(); - EXPECT_THAT(message, EqualsProto(kExpected)); -} - -} // namespace -} // namespace parser -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames_validator.cc b/chromium/third_party/nearby/src/cpp/core/internal/offline_frames_validator.cc deleted file mode 100644 index 614c65f8e63..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames_validator.cc +++ /dev/null @@ -1,381 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/offline_frames_validator.h" - -#include <regex> //NOLINT - -#include "core/internal/internal_payload.h" -#include "core/internal/offline_frames.h" -#include "proto/connections/offline_wire_formats.pb.h" - -namespace location { -namespace nearby { -namespace connections { -namespace parser { -namespace { - -using PayloadChunk = PayloadTransferFrame::PayloadChunk; -using ControlMessage = PayloadTransferFrame::ControlMessage; -using ClientIntroduction = BandwidthUpgradeNegotiationFrame::ClientIntroduction; -using WifiHotspotCredentials = UpgradePathInfo::WifiHotspotCredentials; -using WifiLanSocket = UpgradePathInfo::WifiLanSocket; -using WifiAwareCredentials = UpgradePathInfo::WifiAwareCredentials; -using WifiDirectCredentials = UpgradePathInfo::WifiDirectCredentials; -using BluetoothCredentials = UpgradePathInfo::BluetoothCredentials; -using WebRtcCredentials = UpgradePathInfo::WebRtcCredentials; -using Medium = location::nearby::connections::Medium; - -constexpr absl::string_view kIpv4PatternString{ - "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." - "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." - "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." - "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"}; -constexpr absl::string_view kIpv6PatternString{ - "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." - "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." - "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." - "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." - "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." - "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"}; -constexpr absl::string_view kWifiDirectSsidPatternString{ - "^DIRECT-[a-zA-Z0-9]{2}.*$"}; -constexpr int kWifiDirectSsidMaxLength = 32; -constexpr int kWifiPasswordSsidMinLength = 8; -constexpr int kWifiPasswordSsidMaxLength = 64; - -inline bool WithinRange(int value, int min, int max) { - return value >= min && value < max; -} - -Exception EnsureValidConnectionRequestFrame( - const ConnectionRequestFrame& frame) { - if (!frame.has_endpoint_id()) return {Exception::kInvalidProtocolBuffer}; - if (!frame.has_endpoint_name()) return {Exception::kInvalidProtocolBuffer}; - - // For backwards compatibility reasons, no other fields should be - // null-checked for this frame. Parameter checking (eg. must be within this - // range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidConnectionResponseFrame( - const ConnectionResponseFrame& frame) { - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidPayloadTransferDataFrame(const PayloadChunk& payload_chunk, - std::int64_t totalSize) { - if (!payload_chunk.has_flags()) return {Exception::kInvalidProtocolBuffer}; - - // Special case. The body can be null iff the chunk is flagged as the last - // chunk. - bool is_last_chunk = (payload_chunk.flags() & - PayloadTransferFrame::PayloadChunk::LAST_CHUNK) != 0; - if (!payload_chunk.has_body() && !is_last_chunk) - return {Exception::kInvalidProtocolBuffer}; - if (!payload_chunk.has_offset() || payload_chunk.offset() < 0) - return {Exception::kInvalidProtocolBuffer}; - if (totalSize != InternalPayload::kIndeterminateSize && - totalSize < payload_chunk.offset()) { - return {Exception::kInvalidProtocolBuffer}; - } - - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidPayloadTransferControlFrame( - const ControlMessage& control_message, std::int64_t totalSize) { - if (!control_message.has_offset() || control_message.offset() < 0) - return {Exception::kInvalidProtocolBuffer}; - if (totalSize != InternalPayload::kIndeterminateSize && - totalSize < control_message.offset()) { - return {Exception::kInvalidProtocolBuffer}; - } - - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidPayloadTransferFrame(const PayloadTransferFrame& frame) { - if (!frame.has_payload_header()) return {Exception::kInvalidProtocolBuffer}; - if (!frame.payload_header().has_total_size() || - (frame.payload_header().total_size() < 0 && - frame.payload_header().total_size() != - InternalPayload::kIndeterminateSize)) - return {Exception::kInvalidProtocolBuffer}; - if (!frame.has_packet_type()) return {Exception::kInvalidProtocolBuffer}; - - switch (frame.packet_type()) { - case PayloadTransferFrame::DATA: - if (frame.has_payload_chunk()) { - return EnsureValidPayloadTransferDataFrame( - frame.payload_chunk(), frame.payload_header().total_size()); - } - return {Exception::kInvalidProtocolBuffer}; - - case PayloadTransferFrame::CONTROL: - if (frame.has_control_message()) { - return EnsureValidPayloadTransferControlFrame( - frame.control_message(), frame.payload_header().total_size()); - } - return {Exception::kInvalidProtocolBuffer}; - - default: - break; - } - - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidBandwidthUpgradeWifiHotspotPathAvailableFrame( - const WifiHotspotCredentials& wifi_hotspot_credentials) { - if (!wifi_hotspot_credentials.has_ssid()) - return {Exception::kInvalidProtocolBuffer}; - if (!wifi_hotspot_credentials.has_password() || - !WithinRange(wifi_hotspot_credentials.password().length(), - kWifiPasswordSsidMinLength, kWifiPasswordSsidMaxLength)) - return {Exception::kInvalidProtocolBuffer}; - if (!wifi_hotspot_credentials.has_gateway()) - return {Exception::kInvalidProtocolBuffer}; - const std::regex ip4_pattern(std::string(kIpv4PatternString).c_str()); - const std::regex ip6_pattern(std::string(kIpv6PatternString).c_str()); - if (!(std::regex_match(wifi_hotspot_credentials.gateway(), ip4_pattern) || - std::regex_match(wifi_hotspot_credentials.gateway(), ip6_pattern))) - return {Exception::kInvalidProtocolBuffer}; - - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidBandwidthUpgradeWifiLanPathAvailableFrame( - const WifiLanSocket& wifi_lan_socket) { - if (!wifi_lan_socket.has_ip_address()) - return {Exception::kInvalidProtocolBuffer}; - if (!wifi_lan_socket.has_wifi_port() || wifi_lan_socket.wifi_port() < 0) - return {Exception::kInvalidProtocolBuffer}; - - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidBandwidthUpgradeWifiAwarePathAvailableFrame( - const WifiAwareCredentials& wifi_aware_credentials) { - if (!wifi_aware_credentials.has_service_id()) - return {Exception::kInvalidProtocolBuffer}; - if (!wifi_aware_credentials.has_service_info()) - return {Exception::kInvalidProtocolBuffer}; - - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidBandwidthUpgradeWifiDirectPathAvailableFrame( - const WifiDirectCredentials& wifi_direct_credentials) { - const std::regex ssid_pattern( - std::string(kWifiDirectSsidPatternString).c_str()); - if (!wifi_direct_credentials.has_ssid() || - !(wifi_direct_credentials.ssid().length() < kWifiDirectSsidMaxLength && - std::regex_match(wifi_direct_credentials.ssid(), ssid_pattern))) - return {Exception::kInvalidProtocolBuffer}; - - if (!wifi_direct_credentials.has_password() || - !WithinRange(wifi_direct_credentials.password().length(), - kWifiPasswordSsidMinLength, kWifiPasswordSsidMaxLength)) - return {Exception::kInvalidProtocolBuffer}; - - if (!wifi_direct_credentials.has_frequency() || - wifi_direct_credentials.frequency() < -1) - return {Exception::kInvalidProtocolBuffer}; - - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidBandwidthUpgradeBluetoothPathAvailableFrame( - const BluetoothCredentials& bluetooth_credentials) { - if (!bluetooth_credentials.has_service_name()) - return {Exception::kInvalidProtocolBuffer}; - if (!bluetooth_credentials.has_mac_address()) - return {Exception::kInvalidProtocolBuffer}; - - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidBandwidthUpgradeWebRtcPathAvailableFrame( - const WebRtcCredentials& web_rtc_credentials) { - if (!web_rtc_credentials.has_peer_id()) - return {Exception::kInvalidProtocolBuffer}; - - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidBandwidthUpgradePathAvailableFrame( - const UpgradePathInfo& upgrade_path_info) { - if (!upgrade_path_info.has_medium()) - return {Exception::kInvalidProtocolBuffer}; - switch (static_cast<Medium>(upgrade_path_info.medium())) { - case Medium::WIFI_HOTSPOT: - if (upgrade_path_info.has_wifi_hotspot_credentials()) { - return EnsureValidBandwidthUpgradeWifiHotspotPathAvailableFrame( - upgrade_path_info.wifi_hotspot_credentials()); - } - return {Exception::kInvalidProtocolBuffer}; - - case Medium::WIFI_LAN: - if (upgrade_path_info.has_wifi_lan_socket()) { - return EnsureValidBandwidthUpgradeWifiLanPathAvailableFrame( - upgrade_path_info.wifi_lan_socket()); - } - return {Exception::kInvalidProtocolBuffer}; - - case Medium::WIFI_AWARE: - if (upgrade_path_info.has_wifi_aware_credentials()) { - return EnsureValidBandwidthUpgradeWifiAwarePathAvailableFrame( - upgrade_path_info.wifi_aware_credentials()); - } - return {Exception::kInvalidProtocolBuffer}; - - case Medium::WIFI_DIRECT: - if (upgrade_path_info.has_wifi_direct_credentials()) { - return EnsureValidBandwidthUpgradeWifiDirectPathAvailableFrame( - upgrade_path_info.wifi_direct_credentials()); - } - return {Exception::kInvalidProtocolBuffer}; - - case Medium::BLUETOOTH: - if (upgrade_path_info.has_bluetooth_credentials()) { - return EnsureValidBandwidthUpgradeBluetoothPathAvailableFrame( - upgrade_path_info.bluetooth_credentials()); - } - return {Exception::kInvalidProtocolBuffer}; - - case Medium::WEB_RTC: - if (upgrade_path_info.has_web_rtc_credentials()) { - return EnsureValidBandwidthUpgradeWebRtcPathAvailableFrame( - upgrade_path_info.web_rtc_credentials()); - } - return {Exception::kInvalidProtocolBuffer}; - - default: - break; - } - - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidBandwidthUpgradeClientIntroductionFrame( - const ClientIntroduction& client_introduction) { - if (!client_introduction.has_endpoint_id()) - return {Exception::kInvalidProtocolBuffer}; - - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -Exception EnsureValidBandwidthUpgradeNegotiationFrame( - const BandwidthUpgradeNegotiationFrame& frame) { - if (!frame.has_event_type()) return {Exception::kInvalidProtocolBuffer}; - - switch (frame.event_type()) { - case BandwidthUpgradeNegotiationFrame::UPGRADE_PATH_AVAILABLE: - if (frame.has_upgrade_path_info()) { - return EnsureValidBandwidthUpgradePathAvailableFrame( - frame.upgrade_path_info()); - } - return {Exception::kInvalidProtocolBuffer}; - - case BandwidthUpgradeNegotiationFrame::CLIENT_INTRODUCTION: - if (frame.has_client_introduction()) { - return EnsureValidBandwidthUpgradeClientIntroductionFrame( - frame.client_introduction()); - } - return {Exception::kInvalidProtocolBuffer}; - - default: - break; - } - - // For backwards compatibility reasons, no other fields should be null-checked - // for this frame. Parameter checking (eg. must be within this range) is fine. - return {Exception::kSuccess}; -} - -} // namespace - -Exception EnsureValidOfflineFrame(const OfflineFrame& offline_frame) { - V1Frame::FrameType frame_type = GetFrameType(offline_frame); - switch (frame_type) { - case V1Frame::CONNECTION_REQUEST: - if (offline_frame.has_v1() && - offline_frame.v1().has_connection_request()) { - return EnsureValidConnectionRequestFrame( - offline_frame.v1().connection_request()); - } - return {Exception::kInvalidProtocolBuffer}; - - case V1Frame::CONNECTION_RESPONSE: - if (offline_frame.has_v1() && - offline_frame.v1().has_connection_response()) { - return EnsureValidConnectionResponseFrame( - offline_frame.v1().connection_response()); - } - return {Exception::kInvalidProtocolBuffer}; - - case V1Frame::PAYLOAD_TRANSFER: - if (offline_frame.has_v1() && offline_frame.v1().has_payload_transfer()) { - return EnsureValidPayloadTransferFrame( - offline_frame.v1().payload_transfer()); - } - return {Exception::kInvalidProtocolBuffer}; - - case V1Frame::BANDWIDTH_UPGRADE_NEGOTIATION: - if (offline_frame.has_v1() && - offline_frame.v1().has_bandwidth_upgrade_negotiation()) { - return EnsureValidBandwidthUpgradeNegotiationFrame( - offline_frame.v1().bandwidth_upgrade_negotiation()); - } - return {Exception::kInvalidProtocolBuffer}; - - case V1Frame::KEEP_ALIVE: - case V1Frame::UNKNOWN_FRAME_TYPE: - default: - // Nothing to check for these frames. - break; - } - return {Exception::kSuccess}; -} - -} // namespace parser -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames_validator.h b/chromium/third_party/nearby/src/cpp/core/internal/offline_frames_validator.h deleted file mode 100644 index f64c32c31b1..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames_validator.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_OFFLINE_FRAMES_VALIDATOR_H_ -#define CORE_INTERNAL_OFFLINE_FRAMES_VALIDATOR_H_ - -#include "platform/base/exception.h" -#include "proto/connections/offline_wire_formats.pb.h" - -namespace location { -namespace nearby { -namespace connections { -namespace parser { - -Exception EnsureValidOfflineFrame(const OfflineFrame& offline_frame); - -} // namespace parser -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_OFFLINE_FRAMES_VALIDATOR_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames_validator_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/offline_frames_validator_test.cc deleted file mode 100644 index 3136fb2d96a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames_validator_test.cc +++ /dev/null @@ -1,568 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/offline_frames_validator.h" - -#include <string> - -#include "absl/strings/string_view.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "core/internal/offline_frames.h" -#include "platform/base/byte_array.h" -#include "proto/connections/offline_wire_formats.pb.h" - -namespace location { -namespace nearby { -namespace connections { -namespace parser { -namespace { - -constexpr absl::string_view kEndpointId{"ABC"}; -constexpr absl::string_view kEndpointName{"XYZ"}; -constexpr int kNonce = 1234; -constexpr bool kSupports5ghz = true; -constexpr absl::string_view kBssid{"FF:FF:FF:FF:FF:FF"}; -constexpr int kStatusAccepted = 0; -constexpr absl::string_view kSsid = "ssid"; -constexpr absl::string_view kPassword = "password"; -constexpr absl::string_view kWifiHotspotGateway = "0.0.0.0"; -constexpr absl::string_view kWifiDirectSsid = "DIRECT-A0-0123456789AB"; -constexpr absl::string_view kWifiDirectPassword = "WIFIDIRECT123456"; -constexpr int kWifiDirectFrequency = 1000; -constexpr int kPort = 1000; -constexpr bool kSupportsDisablingEncryption = true; -constexpr std::array<Medium, 9> kMediums = { - Medium::MDNS, Medium::BLUETOOTH, Medium::WIFI_HOTSPOT, - Medium::BLE, Medium::WIFI_LAN, Medium::WIFI_AWARE, - Medium::NFC, Medium::WIFI_DIRECT, Medium::WEB_RTC, -}; -constexpr int kKeepAliveIntervalMillis = 1000; -constexpr int kKeepAliveTimeoutMillis = 5000; - -TEST(OfflineFramesValidatorTest, ValidatesAsOkWithValidConnectionRequestFrame) { - OfflineFrame offline_frame; - - ByteArray bytes = ForConnectionRequest( - std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, std::string(kBssid), - std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis, - kKeepAliveTimeoutMillis); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_TRUE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithNullConnectionRequestFrame) { - OfflineFrame offline_frame; - - ByteArray bytes = ForConnectionRequest( - std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, std::string(kBssid), - std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis, - kKeepAliveTimeoutMillis); - offline_frame.ParseFromString(std::string(bytes)); - auto* v1_frame = offline_frame.mutable_v1(); - - v1_frame->clear_connection_request(); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithNullEndpointIdInConnectionRequestFrame) { - OfflineFrame offline_frame; - - std::string empty_enpoint_id; - ByteArray bytes = ForConnectionRequest( - empty_enpoint_id, ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, std::string(kBssid), - std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis, - kKeepAliveTimeoutMillis); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithNullEndpointInfoInConnectionRequestFrame) { - OfflineFrame offline_frame; - - ByteArray empty_endpoint_info; - ByteArray bytes = ForConnectionRequest( - std::string(kEndpointId), empty_endpoint_info, kNonce, kSupports5ghz, - std::string(kBssid), std::vector(kMediums.begin(), kMediums.end()), - kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsOkWithNullBssidInConnectionRequestFrame) { - OfflineFrame offline_frame; - - std::string empty_bssid; - ByteArray bytes = ForConnectionRequest( - std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, empty_bssid, std::vector(kMediums.begin(), kMediums.end()), - kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_TRUE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsOkWithNullMediumsInConnectionRequestFrame) { - OfflineFrame offline_frame; - - std::vector<Medium> empty_mediums; - ByteArray bytes = ForConnectionRequest( - std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, std::string(kBssid), empty_mediums, - kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_TRUE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsOkWithValidConnectionResponseFrame) { - OfflineFrame offline_frame; - - ByteArray bytes = ForConnectionResponse(kStatusAccepted); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_TRUE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithNullConnectionResponseFrame) { - OfflineFrame offline_frame; - - ByteArray bytes = ForConnectionResponse(kStatusAccepted); - offline_frame.ParseFromString(std::string(bytes)); - auto* v1_frame = offline_frame.mutable_v1(); - - v1_frame->clear_connection_response(); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithUnexpectedStatusInConnectionResponseFrame) { - OfflineFrame offline_frame; - - ByteArray bytes = ForConnectionResponse(-1); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - // To maintain forward compatibility, we allow unexpected status codes. - ASSERT_TRUE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, ValidatesAsOkWithValidPayloadTransferFrame) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::PayloadChunk chunk; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - // Sending files larger than 2gb was previously broken (see cl/372382338). - // This tests a file larger than int max. - header.set_total_size(3e10); - chunk.set_body("payload data"); - chunk.set_offset(150); - chunk.set_flags(1); - - OfflineFrame offline_frame; - - ByteArray bytes = ForDataPayloadTransfer(header, chunk); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_TRUE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, ValidatesAsFailWithNullPayloadTransferFrame) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::PayloadChunk chunk; - chunk.set_body("payload data"); - chunk.set_offset(150); - chunk.set_flags(1); - - OfflineFrame offline_frame; - - ByteArray bytes = ForDataPayloadTransfer(header, chunk); - offline_frame.ParseFromString(std::string(bytes)); - auto* v1_frame = offline_frame.mutable_v1(); - - v1_frame->clear_payload_transfer(); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithNullPayloadHeaderInPayloadTransferFrame) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::PayloadChunk chunk; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_total_size(1024); - chunk.set_body("payload data"); - chunk.set_offset(150); - chunk.set_flags(1); - - OfflineFrame offline_frame; - - ByteArray bytes = ForDataPayloadTransfer(header, chunk); - offline_frame.ParseFromString(std::string(bytes)); - auto* v1_frame = offline_frame.mutable_v1(); - auto* payload_transfer = v1_frame->mutable_payload_transfer(); - - payload_transfer->clear_payload_header(); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithInvalidSizeInPayloadHeader) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::PayloadChunk chunk; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_total_size(-5); - chunk.set_body("payload data"); - chunk.set_offset(150); - chunk.set_flags(1); - - OfflineFrame offline_frame; - - ByteArray bytes = ForDataPayloadTransfer(header, chunk); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithNullPayloadChunkInPayloadTransferFrame) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::PayloadChunk chunk; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_total_size(1024); - chunk.set_body("payload data"); - chunk.set_offset(150); - chunk.set_flags(1); - - OfflineFrame offline_frame; - - ByteArray bytes = ForDataPayloadTransfer(header, chunk); - offline_frame.ParseFromString(std::string(bytes)); - auto* v1_frame = offline_frame.mutable_v1(); - auto* payload_transfer = v1_frame->mutable_payload_transfer(); - - payload_transfer->clear_payload_chunk(); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithInvalidOffsetInPayloadChunk) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::PayloadChunk chunk; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_total_size(1024); - chunk.set_body("payload data"); - chunk.set_offset(-1); - chunk.set_flags(1); - - OfflineFrame offline_frame; - - ByteArray bytes = ForDataPayloadTransfer(header, chunk); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithInvalidLargeOffsetInPayloadChunk) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::PayloadChunk chunk; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_total_size(1024); - chunk.set_body("payload data"); - chunk.set_offset(4999); - chunk.set_flags(1); - - OfflineFrame offline_frame; - - ByteArray bytes = ForDataPayloadTransfer(header, chunk); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithInvalidFlagsInPayloadChunk) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::PayloadChunk chunk; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_total_size(1024); - chunk.set_body("payload data"); - chunk.set_offset(150); - chunk.set_flags(1); - - OfflineFrame offline_frame; - - ByteArray bytes = ForDataPayloadTransfer(header, chunk); - offline_frame.ParseFromString(std::string(bytes)); - auto* v1_frame = offline_frame.mutable_v1(); - auto* payload_transfer = v1_frame->mutable_payload_transfer(); - auto* payload_chunk = payload_transfer->mutable_payload_chunk(); - - payload_chunk->clear_flags(); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithNullControlMessageInPayloadTransferFrame) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::ControlMessage control; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_total_size(1024); - control.set_event(PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED); - control.set_offset(150); - - OfflineFrame offline_frame; - - ByteArray bytes = ForControlPayloadTransfer(header, control); - offline_frame.ParseFromString(std::string(bytes)); - - auto* v1_frame = offline_frame.mutable_v1(); - auto* payload_transfer = v1_frame->mutable_payload_transfer(); - - payload_transfer->clear_control_message(); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithInvalidNegativeOffsetInControlMessage) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::ControlMessage control; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_total_size(1024); - control.set_event(PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED); - control.set_offset(-1); - - OfflineFrame offline_frame; - - ByteArray bytes = ForControlPayloadTransfer(header, control); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithInvalidLargeOffsetInControlMessage) { - PayloadTransferFrame::PayloadHeader header; - PayloadTransferFrame::ControlMessage control; - header.set_id(12345); - header.set_type(PayloadTransferFrame::PayloadHeader::BYTES); - header.set_total_size(1024); - control.set_event(PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED); - control.set_offset(4999); - - OfflineFrame offline_frame; - - ByteArray bytes = ForControlPayloadTransfer(header, control); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsOkWithValidBandwidthUpgradeNegotiationFrame) { - OfflineFrame offline_frame; - - ByteArray bytes = ForBwuWifiHotspotPathAvailable( - std::string(kSsid), std::string(kPassword), kPort, - std::string(kWifiHotspotGateway), kSupportsDisablingEncryption); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_TRUE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithNullBandwidthUpgradeNegotiationFrame) { - OfflineFrame offline_frame; - - ByteArray bytes = ForBwuWifiHotspotPathAvailable( - std::string(kSsid), std::string(kPassword), kPort, - std::string(kWifiHotspotGateway), kSupportsDisablingEncryption); - offline_frame.ParseFromString(std::string(bytes)); - auto* v1_frame = offline_frame.mutable_v1(); - - v1_frame->clear_bandwidth_upgrade_negotiation(); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, ValidatesAsOkBandwidthUpgradeWifiDirect) { - OfflineFrame offline_frame; - - ByteArray bytes = ForBwuWifiDirectPathAvailable( - std::string(kWifiDirectSsid), std::string(kWifiDirectPassword), kPort, - kWifiDirectFrequency, kSupportsDisablingEncryption); - offline_frame.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame); - - ASSERT_TRUE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesValidFrequencyInBandwidthUpgradeWifiDirect) { - OfflineFrame offline_frame_1; - OfflineFrame offline_frame_2; - - // Anything less than -1 is invalid - ByteArray bytes = ForBwuWifiDirectPathAvailable( - std::string(kWifiDirectSsid), std::string(kWifiDirectPassword), kPort, -2, - kSupportsDisablingEncryption); - offline_frame_1.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame_1); - - ASSERT_FALSE(ret_value.Ok()); - - // But -1 itself is not invalid - bytes = ForBwuWifiDirectPathAvailable(std::string(kWifiDirectSsid), - std::string(kWifiDirectPassword), kPort, - -1, kSupportsDisablingEncryption); - offline_frame_2.ParseFromString(std::string(bytes)); - - ret_value = EnsureValidOfflineFrame(offline_frame_2); - - ASSERT_TRUE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithInvalidSsidInBandwidthUpgradeWifiDirect) { - OfflineFrame offline_frame_1; - OfflineFrame offline_frame_2; - - std::string wifi_direct_ssid{"DIRECT-A*-0123456789AB"}; - ByteArray bytes = ForBwuWifiDirectPathAvailable( - wifi_direct_ssid, std::string(kWifiDirectPassword), kPort, - kWifiDirectFrequency, kSupportsDisablingEncryption); - offline_frame_1.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame_1); - - ASSERT_FALSE(ret_value.Ok()); - - std::string wifi_direct_ssid_wrong_length = - std::string{kWifiDirectSsid} + "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"; - bytes = ForBwuWifiDirectPathAvailable( - wifi_direct_ssid_wrong_length, std::string(kWifiDirectPassword), kPort, - kWifiDirectFrequency, kSupportsDisablingEncryption); - offline_frame_2.ParseFromString(std::string(bytes)); - - ret_value = EnsureValidOfflineFrame(offline_frame_2); - - ASSERT_FALSE(ret_value.Ok()); -} - -TEST(OfflineFramesValidatorTest, - ValidatesAsFailWithInvalidPasswordInBandwidthUpgradeWifiDirect) { - OfflineFrame offline_frame_1; - OfflineFrame offline_frame_2; - - std::string short_wifi_direct_password{"Test"}; - ByteArray bytes = ForBwuWifiDirectPathAvailable( - std::string(kWifiDirectSsid), short_wifi_direct_password, kPort, - kWifiDirectFrequency, kSupportsDisablingEncryption); - offline_frame_1.ParseFromString(std::string(bytes)); - - auto ret_value = EnsureValidOfflineFrame(offline_frame_1); - - ASSERT_FALSE(ret_value.Ok()); - - std::string long_wifi_direct_password = - std::string{kWifiDirectSsid} + - "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789"; - bytes = ForBwuWifiDirectPathAvailable( - std::string(kWifiDirectSsid), long_wifi_direct_password, kPort, - kWifiDirectFrequency, kSupportsDisablingEncryption); - offline_frame_2.ParseFromString(std::string(bytes)); - - ret_value = EnsureValidOfflineFrame(offline_frame_2); - - ASSERT_FALSE(ret_value.Ok()); -} - -} // namespace -} // namespace parser -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/offline_service_controller.cc b/chromium/third_party/nearby/src/cpp/core/internal/offline_service_controller.cc deleted file mode 100644 index a86eea9d165..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_service_controller.cc +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/offline_service_controller.h" - -#include <string> - -#include "absl/strings/str_join.h" - -namespace location { -namespace nearby { -namespace connections { - -OfflineServiceController::~OfflineServiceController() { Stop(); } - -void OfflineServiceController::Stop() { - NEARBY_LOGS(INFO) << "Initiating shutdown of OfflineServiceController."; - if (stop_.Set(true)) return; - payload_manager_.DisconnectFromEndpointManager(); - pcp_manager_.DisconnectFromEndpointManager(); - NEARBY_LOGS(INFO) << "OfflineServiceController has shut down."; -} - -Status OfflineServiceController::StartAdvertising( - ClientProxy* client, const std::string& service_id, - const ConnectionOptions& options, const ConnectionRequestInfo& info) { - if (stop_) return {Status::kOutOfOrderApiCall}; - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " requested advertising to start."; - return pcp_manager_.StartAdvertising(client, service_id, options, info); -} - -void OfflineServiceController::StopAdvertising(ClientProxy* client) { - if (stop_) return; - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " requested advertising to stop."; - pcp_manager_.StopAdvertising(client); -} - -Status OfflineServiceController::StartDiscovery( - ClientProxy* client, const std::string& service_id, - const ConnectionOptions& options, const DiscoveryListener& listener) { - if (stop_) return {Status::kOutOfOrderApiCall}; - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " requested discovery to start."; - return pcp_manager_.StartDiscovery(client, service_id, options, listener); -} - -void OfflineServiceController::StopDiscovery(ClientProxy* client) { - if (stop_) return; - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " requested discovery to stop."; - pcp_manager_.StopDiscovery(client); -} - -void OfflineServiceController::InjectEndpoint( - ClientProxy* client, const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) { - if (stop_) return; - pcp_manager_.InjectEndpoint(client, service_id, metadata); -} - -Status OfflineServiceController::RequestConnection( - ClientProxy* client, const std::string& endpoint_id, - const ConnectionRequestInfo& info, const ConnectionOptions& options) { - if (stop_) return {Status::kOutOfOrderApiCall}; - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " requested a connection to endpoint_id=" << endpoint_id; - return pcp_manager_.RequestConnection(client, endpoint_id, info, options); -} - -Status OfflineServiceController::AcceptConnection( - ClientProxy* client, const std::string& endpoint_id, - const PayloadListener& listener) { - if (stop_) return {Status::kOutOfOrderApiCall}; - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " accepted the connection with endpoint_id=" - << endpoint_id; - return pcp_manager_.AcceptConnection(client, endpoint_id, listener); -} - -Status OfflineServiceController::RejectConnection( - ClientProxy* client, const std::string& endpoint_id) { - if (stop_) return {Status::kOutOfOrderApiCall}; - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " rejected the connection with endpoint_id=" - << endpoint_id; - return pcp_manager_.RejectConnection(client, endpoint_id); -} - -void OfflineServiceController::InitiateBandwidthUpgrade( - ClientProxy* client, const std::string& endpoint_id) { - if (stop_) return; - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " initiated a manual bandwidth upgrade with endpoint_id=" - << endpoint_id; - bwu_manager_.InitiateBwuForEndpoint(client, endpoint_id); -} - -void OfflineServiceController::SendPayload( - ClientProxy* client, const std::vector<std::string>& endpoint_ids, - Payload payload) { - if (stop_) return; - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " is sending payload_id=" << payload.GetId() - << " to endpoint_ids={" << absl::StrJoin(endpoint_ids, ",") - << "}"; - payload_manager_.SendPayload(client, endpoint_ids, std::move(payload)); -} - -Status OfflineServiceController::CancelPayload(ClientProxy* client, - std::int64_t payload_id) { - if (stop_) return {Status::kOutOfOrderApiCall}; - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " cancelled payload_id=" << payload_id; - return payload_manager_.CancelPayload(client, payload_id); -} - -void OfflineServiceController::DisconnectFromEndpoint( - ClientProxy* client, const std::string& endpoint_id) { - if (stop_) return; - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " requested a disconnection from endpoint_id=" - << endpoint_id; - endpoint_manager_.UnregisterEndpoint(client, endpoint_id); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/offline_service_controller.h b/chromium/third_party/nearby/src/cpp/core/internal/offline_service_controller.h deleted file mode 100644 index 6e397de9b02..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_service_controller.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_OFFLINE_SERVICE_CONTROLLER_H_ -#define CORE_INTERNAL_OFFLINE_SERVICE_CONTROLLER_H_ - -#include <cstdint> -#include <string> -#include <vector> - -#include "core/internal/bwu_manager.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel_manager.h" -#include "core/internal/endpoint_manager.h" -#include "core/internal/injected_bluetooth_device_store.h" -#include "core/internal/mediums/mediums.h" -#include "core/internal/payload_manager.h" -#include "core/internal/pcp_manager.h" -#include "core/internal/service_controller.h" -#include "core/listeners.h" -#include "core/options.h" -#include "core/payload.h" -#include "core/status.h" - -namespace location { -namespace nearby { -namespace connections { - -class OfflineServiceController : public ServiceController { - public: - OfflineServiceController() = default; - ~OfflineServiceController() override; - - Status StartAdvertising(ClientProxy* client, const std::string& service_id, - const ConnectionOptions& options, - const ConnectionRequestInfo& info) override; - void StopAdvertising(ClientProxy* client) override; - - Status StartDiscovery(ClientProxy* client, const std::string& service_id, - const ConnectionOptions& options, - const DiscoveryListener& listener) override; - void StopDiscovery(ClientProxy* client) override; - - void InjectEndpoint(ClientProxy* client, const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) override; - - Status RequestConnection(ClientProxy* client, const std::string& endpoint_id, - const ConnectionRequestInfo& info, - const ConnectionOptions& options) override; - Status AcceptConnection(ClientProxy* client, const std::string& endpoint_id, - const PayloadListener& listener) override; - Status RejectConnection(ClientProxy* client, - const std::string& endpoint_id) override; - - void InitiateBandwidthUpgrade(ClientProxy* client, - const std::string& endpoint_id) override; - - void SendPayload(ClientProxy* client, - const std::vector<std::string>& endpoint_ids, - Payload payload) override; - Status CancelPayload(ClientProxy* client, Payload::Id payload_id) override; - - void DisconnectFromEndpoint(ClientProxy* client, - const std::string& endpoint_id) override; - - void Stop() override; - - private: - // Note that the order of declaration of these is crucial, because we depend - // on the destructors running (strictly) in the reverse order; a deviation - // from that will lead to crashes at runtime. - AtomicBoolean stop_{false}; - Mediums mediums_; - EndpointChannelManager channel_manager_; - EndpointManager endpoint_manager_{&channel_manager_}; - PayloadManager payload_manager_{endpoint_manager_}; - BwuManager bwu_manager_{ - mediums_, endpoint_manager_, channel_manager_, {}, {}}; - InjectedBluetoothDeviceStore injected_bluetooth_device_store_; - PcpManager pcp_manager_{mediums_, channel_manager_, endpoint_manager_, - bwu_manager_, injected_bluetooth_device_store_}; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_OFFLINE_SERVICE_CONTROLLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/offline_service_controller_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/offline_service_controller_test.cc deleted file mode 100644 index 35f0484516a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_service_controller_test.cc +++ /dev/null @@ -1,388 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/offline_service_controller.h" - -#include <array> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "core/internal/offline_simulation_user.h" -#include "platform/base/medium_environment.h" -#include "platform/base/output_stream.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/logging.h" -#include "platform/public/pipe.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -using ::testing::Eq; - -constexpr std::array<char, 6> kFakeMacAddress = {'a', 'b', 'c', 'd', 'e', 'f'}; -constexpr absl::string_view kServiceId = "service-id"; -constexpr absl::string_view kDeviceA = "device-a"; -constexpr absl::string_view kDeviceB = "device-b"; -constexpr absl::string_view kMessage = "message"; -constexpr absl::Duration kProgressTimeout = absl::Milliseconds(1500); -constexpr absl::Duration kDefaultTimeout = absl::Milliseconds(1500); -constexpr absl::Duration kDisconnectTimeout = absl::Milliseconds(15000); - -constexpr BooleanMediumSelector kTestCases[] = { - BooleanMediumSelector{ - .bluetooth = true, - }, - BooleanMediumSelector{ - .wifi_lan = true, - }, - BooleanMediumSelector{ - .bluetooth = true, - .wifi_lan = true, - }, -}; - -class OfflineServiceControllerTest - : public ::testing::TestWithParam<BooleanMediumSelector> { - protected: - OfflineServiceControllerTest() { env_.Stop(); } - - bool SetupConnection(OfflineSimulationUser& user_a, - OfflineSimulationUser& user_b) { - user_a.StartAdvertising(std::string(kServiceId), &connect_latch_); - user_b.StartDiscovery(std::string(kServiceId), &discover_latch_); - EXPECT_TRUE(discover_latch_.Await(kDefaultTimeout).result()); - EXPECT_EQ(user_b.GetDiscovered().service_id, kServiceId); - EXPECT_EQ(user_b.GetDiscovered().endpoint_info, user_a.GetInfo()); - EXPECT_FALSE(user_b.GetDiscovered().endpoint_id.empty()); - NEARBY_LOG(INFO, "EP-B: [discovered] %s", - user_b.GetDiscovered().endpoint_id.c_str()); - user_b.RequestConnection(&connect_latch_); - EXPECT_TRUE(connect_latch_.Await(kDefaultTimeout).result()); - EXPECT_FALSE(user_a.GetDiscovered().endpoint_id.empty()); - NEARBY_LOG(INFO, "EP-A: [discovered] %s", - user_a.GetDiscovered().endpoint_id.c_str()); - NEARBY_LOG(INFO, "Both users discovered their peers."); - user_a.AcceptConnection(&accept_latch_); - user_b.AcceptConnection(&accept_latch_); - EXPECT_TRUE(accept_latch_.Await(kDefaultTimeout).result()); - NEARBY_LOG(INFO, "Both users reached connected state."); - return user_a.IsConnected() && user_b.IsConnected(); - } - - CountDownLatch discover_latch_{1}; - CountDownLatch lost_latch_{1}; - CountDownLatch connect_latch_{2}; - CountDownLatch accept_latch_{2}; - CountDownLatch payload_latch_{1}; - MediumEnvironment& env_ = MediumEnvironment::Instance(); -}; - -TEST_P(OfflineServiceControllerTest, CanCreateOne) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanCreateMany) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanStartAdvertising) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - EXPECT_FALSE(user_a.IsAdvertising()); - EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), nullptr), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(user_a.IsAdvertising()); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanStartDiscoveryBeforeAdvertising) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - EXPECT_FALSE(user_b.IsDiscovering()); - EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(user_b.IsDiscovering()); - EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), nullptr), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(discover_latch_.Await(kDefaultTimeout).result()); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanStartDiscoveryAfterAdvertising) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - EXPECT_FALSE(user_b.IsDiscovering()); - EXPECT_FALSE(user_b.IsAdvertising()); - EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), nullptr), - Eq(Status{Status::kSuccess})); - EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(user_a.IsAdvertising()); - EXPECT_TRUE(user_b.IsDiscovering()); - EXPECT_TRUE(discover_latch_.Await(kDefaultTimeout).result()); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanStopAdvertising) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - EXPECT_FALSE(user_a.IsAdvertising()); - EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), nullptr), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(user_a.IsAdvertising()); - user_a.StopAdvertising(); - EXPECT_FALSE(user_a.IsAdvertising()); - EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_, - &lost_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(user_b.IsDiscovering()); - auto discover_none = discover_latch_.Await(kDefaultTimeout).GetResult(); - if (!discover_none) { - EXPECT_TRUE(true); - } else { - // There are rare cases (1/1000) that advertisment data has been captured by - // discovery device before advertising is stopped. So we need to check if - // lost_cb has grabbed the event in the end to prove the advertising service - // is stopped. - EXPECT_TRUE(lost_latch_.Await(kDefaultTimeout).result()); - } - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanStopDiscovery) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - EXPECT_FALSE(user_b.IsDiscovering()); - EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(user_b.IsDiscovering()); - user_b.StopDiscovery(); - EXPECT_FALSE(user_b.IsDiscovering()); - EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), nullptr), - Eq(Status{Status::kSuccess})); - EXPECT_FALSE(discover_latch_.Await(kDefaultTimeout).result()); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanConnect) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), &connect_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(discover_latch_.Await(kDefaultTimeout).result()); - EXPECT_THAT(user_b.RequestConnection(&connect_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(connect_latch_.Await(kDefaultTimeout).result()); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanAcceptConnection) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), &connect_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(discover_latch_.Await(kDefaultTimeout).result()); - EXPECT_THAT(user_b.RequestConnection(&connect_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(connect_latch_.Await(kDefaultTimeout).result()); - EXPECT_THAT(user_a.AcceptConnection(&accept_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_THAT(user_b.AcceptConnection(&accept_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(accept_latch_.Await(kDefaultTimeout).result()); - EXPECT_TRUE(user_a.IsConnected()); - EXPECT_TRUE(user_b.IsConnected()); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanRejectConnection) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - CountDownLatch reject_latch(1); - EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), &connect_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(discover_latch_.Await(kDefaultTimeout).result()); - EXPECT_THAT(user_b.RequestConnection(&connect_latch_), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(connect_latch_.Await(kDefaultTimeout).result()); - user_a.ExpectRejectedConnection(reject_latch); - EXPECT_THAT(user_b.RejectConnection(nullptr), Eq(Status{Status::kSuccess})); - EXPECT_TRUE(reject_latch.Await(kDefaultTimeout).result()); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanSendBytePayload) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - ASSERT_TRUE(SetupConnection(user_a, user_b)); - ByteArray message(std::string{kMessage}); - user_a.SendPayload(Payload(message)); - user_b.ExpectPayload(payload_latch_); - EXPECT_TRUE(payload_latch_.Await(kDefaultTimeout).result()); - EXPECT_EQ(user_b.GetPayload().AsBytes(), message); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanSendStreamPayload) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - ASSERT_TRUE(SetupConnection(user_a, user_b)); - ByteArray message(std::string{kMessage}); - auto pipe = std::make_shared<Pipe>(); - OutputStream& tx = pipe->GetOutputStream(); - user_a.SendPayload(Payload([pipe]() -> InputStream& { - return pipe->GetInputStream(); // NOLINT - })); - user_b.ExpectPayload(payload_latch_); - tx.Write(message); - EXPECT_TRUE(payload_latch_.Await(kDefaultTimeout).result()); - EXPECT_NE(user_b.GetPayload().AsStream(), nullptr); - InputStream& rx = *user_b.GetPayload().AsStream(); - ASSERT_TRUE(user_b.WaitForProgress( - [size = message.size()](const PayloadProgressInfo& info) -> bool { - return info.bytes_transferred >= size; - }, - kProgressTimeout)); - EXPECT_EQ(rx.Read(Pipe::kChunkSize).result(), message); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanCancelStreamPayload) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - ASSERT_TRUE(SetupConnection(user_a, user_b)); - ByteArray message(std::string{kMessage}); - auto pipe = std::make_shared<Pipe>(); - OutputStream& tx = pipe->GetOutputStream(); - user_a.SendPayload(Payload([pipe]() -> InputStream& { - return pipe->GetInputStream(); // NOLINT - })); - user_b.ExpectPayload(payload_latch_); - tx.Write(message); - EXPECT_TRUE(payload_latch_.Await(kDefaultTimeout).result()); - EXPECT_NE(user_b.GetPayload().AsStream(), nullptr); - InputStream& rx = *user_b.GetPayload().AsStream(); - ASSERT_TRUE(user_b.WaitForProgress( - [size = message.size()](const PayloadProgressInfo& info) -> bool { - return info.bytes_transferred >= size; - }, - kProgressTimeout)); - EXPECT_EQ(rx.Read(Pipe::kChunkSize).result(), message); - user_b.CancelPayload(); - int count = 0; - while (true) { - count++; - if (!tx.Write(message).Ok()) break; - SystemClock::Sleep(kDefaultTimeout); - } - EXPECT_TRUE(user_a.WaitForProgress( - [](const PayloadProgressInfo& info) -> bool { - return info.status == PayloadProgressInfo::Status::kCanceled; - }, - kProgressTimeout)); - EXPECT_LT(count, 10); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(OfflineServiceControllerTest, CanDisconnect) { - env_.Start(); - CountDownLatch disconnect_latch(1); - OfflineSimulationUser user_a(kDeviceA, GetParam()); - OfflineSimulationUser user_b(kDeviceB, GetParam()); - ASSERT_TRUE(SetupConnection(user_a, user_b)); - NEARBY_LOGS(INFO) << "Disconnecting"; - user_b.ExpectDisconnect(disconnect_latch); - user_b.Disconnect(); - EXPECT_TRUE(disconnect_latch.Await(kDisconnectTimeout).result()); - NEARBY_LOGS(INFO) << "Disconnected"; - EXPECT_FALSE(user_b.IsConnected()); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -INSTANTIATE_TEST_SUITE_P(ParametrisedOfflineServiceControllerTest, - OfflineServiceControllerTest, - ::testing::ValuesIn(kTestCases)); - -// Verifies that InjectEndpoint() can be run successfully; does not test the -// full connection flow given that normal discovery/advertisement is skipped. -// Note: Not parameterized because InjectEndpoint only works over Bluetooth. -TEST_F(OfflineServiceControllerTest, InjectEndpoint) { - env_.Start(); - OfflineSimulationUser user_a(kDeviceA, - BooleanMediumSelector{.bluetooth = true}); - EXPECT_THAT(user_a.StartDiscovery(std::string(kServiceId), - /*found_latch=*/nullptr), - Eq(Status{Status::kSuccess})); - EXPECT_TRUE(user_a.IsDiscovering()); - user_a.InjectEndpoint( - std::string(kServiceId), - OutOfBandConnectionMetadata{ - .medium = Medium::BLUETOOTH, - .remote_bluetooth_mac_address = ByteArray(kFakeMacAddress), - }); - user_a.Stop(); - env_.Stop(); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/offline_simulation_user.cc b/chromium/third_party/nearby/src/cpp/core/internal/offline_simulation_user.cc deleted file mode 100644 index 6b6db548c9a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_simulation_user.cc +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/offline_simulation_user.h" - -#include "absl/functional/bind_front.h" -#include "core/listeners.h" -#include "platform/base/byte_array.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { - -void OfflineSimulationUser::OnConnectionInitiated( - const std::string& endpoint_id, const ConnectionResponseInfo& info, - bool is_outgoing) { - if (is_outgoing) { - NEARBY_LOG(INFO, "RequestConnection: initiated_cb called"); - } else { - NEARBY_LOG(INFO, "StartAdvertising: initiated_cb called"); - discovered_ = DiscoveredInfo{ - .endpoint_id = endpoint_id, - .endpoint_info = GetInfo(), - .service_id = service_id_, - }; - } - if (initiated_latch_) initiated_latch_->CountDown(); -} - -void OfflineSimulationUser::OnConnectionAccepted( - const std::string& endpoint_id) { - if (accept_latch_) accept_latch_->CountDown(); -} - -void OfflineSimulationUser::OnConnectionRejected(const std::string& endpoint_id, - Status status) { - if (reject_latch_) reject_latch_->CountDown(); -} - -void OfflineSimulationUser::OnEndpointDisconnect( - const std::string& endpoint_id) { - NEARBY_LOGS(INFO) << "OnEndpointDisconnect: self=" << this - << "; id=" << endpoint_id; - if (disconnect_latch_) disconnect_latch_->CountDown(); -} - -void OfflineSimulationUser::OnEndpointFound(const std::string& endpoint_id, - const ByteArray& endpoint_info, - const std::string& service_id) { - NEARBY_LOG(INFO, "Device discovered: id=%s", endpoint_id.c_str()); - discovered_ = DiscoveredInfo{ - .endpoint_id = endpoint_id, - .endpoint_info = endpoint_info, - .service_id = service_id, - }; - if (found_latch_) found_latch_->CountDown(); -} - -void OfflineSimulationUser::OnEndpointLost(const std::string& endpoint_id) { - if (lost_latch_) lost_latch_->CountDown(); -} - -void OfflineSimulationUser::OnPayload(const std::string& endpoint_id, - Payload payload) { - payload_ = std::move(payload); - if (payload_latch_) payload_latch_->CountDown(); -} - -void OfflineSimulationUser::OnPayloadProgress(const std::string& endpoint_id, - const PayloadProgressInfo& info) { - MutexLock lock(&progress_mutex_); - progress_info_ = info; - if (future_ && predicate_ && predicate_(info)) future_->Set(true); -} - -bool OfflineSimulationUser::WaitForProgress( - std::function<bool(const PayloadProgressInfo&)> predicate, - absl::Duration timeout) { - Future<bool> future; - { - MutexLock lock(&progress_mutex_); - if (predicate(progress_info_)) return true; - future_ = &future; - predicate_ = std::move(predicate); - } - auto response = future.Get(timeout); - { - MutexLock lock(&progress_mutex_); - future_ = nullptr; - predicate_ = nullptr; - } - return response.ok() && response.result(); -} - -Status OfflineSimulationUser::StartAdvertising(const std::string& service_id, - CountDownLatch* latch) { - initiated_latch_ = latch; - service_id_ = service_id; - ConnectionListener listener = { - .initiated_cb = - std::bind(&OfflineSimulationUser::OnConnectionInitiated, this, - std::placeholders::_1, std::placeholders::_2, false), - .accepted_cb = - absl::bind_front(&OfflineSimulationUser::OnConnectionAccepted, this), - .rejected_cb = - absl::bind_front(&OfflineSimulationUser::OnConnectionRejected, this), - .disconnected_cb = - absl::bind_front(&OfflineSimulationUser::OnEndpointDisconnect, this), - }; - return ctrl_.StartAdvertising(&client_, service_id_, options_, - { - .endpoint_info = info_, - .listener = std::move(listener), - }); -} - -void OfflineSimulationUser::StopAdvertising() { - ctrl_.StopAdvertising(&client_); -} - -Status OfflineSimulationUser::StartDiscovery(const std::string& service_id, - CountDownLatch* found_latch, - CountDownLatch* lost_latch) { - found_latch_ = found_latch; - lost_latch_ = lost_latch; - DiscoveryListener listener = { - .endpoint_found_cb = - absl::bind_front(&OfflineSimulationUser::OnEndpointFound, this), - .endpoint_lost_cb = - absl::bind_front(&OfflineSimulationUser::OnEndpointLost, this), - }; - return ctrl_.StartDiscovery(&client_, service_id, options_, - std::move(listener)); -} - -void OfflineSimulationUser::StopDiscovery() { ctrl_.StopDiscovery(&client_); } - -void OfflineSimulationUser::InjectEndpoint( - const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) { - ctrl_.InjectEndpoint(&client_, service_id, metadata); -} - -Status OfflineSimulationUser::RequestConnection(CountDownLatch* latch) { - initiated_latch_ = latch; - ConnectionListener listener = { - .initiated_cb = - std::bind(&OfflineSimulationUser::OnConnectionInitiated, this, - std::placeholders::_1, std::placeholders::_2, true), - .accepted_cb = - absl::bind_front(&OfflineSimulationUser::OnConnectionAccepted, this), - .rejected_cb = - absl::bind_front(&OfflineSimulationUser::OnConnectionRejected, this), - .disconnected_cb = - absl::bind_front(&OfflineSimulationUser::OnEndpointDisconnect, this), - }; - client_.AddCancellationFlag(discovered_.endpoint_id); - return ctrl_.RequestConnection(&client_, discovered_.endpoint_id, - { - .endpoint_info = discovered_.endpoint_info, - .listener = std::move(listener), - }, - connection_options_); -} - -Status OfflineSimulationUser::AcceptConnection(CountDownLatch* latch) { - accept_latch_ = latch; - PayloadListener listener = { - .payload_cb = absl::bind_front(&OfflineSimulationUser::OnPayload, this), - .payload_progress_cb = - absl::bind_front(&OfflineSimulationUser::OnPayloadProgress, this), - }; - return ctrl_.AcceptConnection(&client_, discovered_.endpoint_id, - std::move(listener)); -} - -Status OfflineSimulationUser::RejectConnection(CountDownLatch* latch) { - reject_latch_ = latch; - return ctrl_.RejectConnection(&client_, discovered_.endpoint_id); -} - -void OfflineSimulationUser::Disconnect() { - NEARBY_LOGS(INFO) << "Disconnecting from id=" << discovered_.endpoint_id; - ctrl_.DisconnectFromEndpoint(&client_, discovered_.endpoint_id); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/offline_simulation_user.h b/chromium/third_party/nearby/src/cpp/core/internal/offline_simulation_user.h deleted file mode 100644 index 01de6f886de..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_simulation_user.h +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_OFFLINE_SIMULATION_USER_H_ -#define CORE_INTERNAL_OFFLINE_SIMULATION_USER_H_ - -#include <string> - -#include "gtest/gtest.h" -#include "absl/strings/string_view.h" -#include "core/internal/client_proxy.h" -#include "core/internal/offline_service_controller.h" -#include "core/options.h" -#include "platform/public/atomic_boolean.h" -#include "platform/public/condition_variable.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/future.h" - -// Test-only class to help run end-to-end simulations for nearby connections -// protocol. -// -// This is a "standalone" version of PcpManager. It can run independently, -// provided MediumEnvironment has adequate support for all medium types in use. -namespace location { -namespace nearby { -namespace connections { - -class OfflineSimulationUser { - public: - struct DiscoveredInfo { - std::string endpoint_id; - ByteArray endpoint_info; - std::string service_id; - - bool Empty() const { return endpoint_id.empty(); } - void Clear() { endpoint_id.clear(); } - }; - - explicit OfflineSimulationUser( - absl::string_view device_name, - BooleanMediumSelector allowed = BooleanMediumSelector()) - : connection_options_{ - .keep_alive_interval_millis = FeatureFlags::GetInstance() - .GetFlags() - .keep_alive_interval_millis, - .keep_alive_timeout_millis = FeatureFlags::GetInstance() - .GetFlags() - .keep_alive_timeout_millis, - }, - info_{ByteArray{std::string(device_name)}}, - options_{ - .strategy = Strategy::kP2pCluster, - .allowed = allowed, - } {} - virtual ~OfflineSimulationUser() = default; - - // Calls PcpManager::StartAdvertising(). - // If latch is provided, will call latch->CountDown() in the initiated_cb - // callback. - Status StartAdvertising(const std::string& service_id, CountDownLatch* latch); - - // Calls PcpManager::StopAdvertising(). - void StopAdvertising(); - - // Calls PcpManager::StartDiscovery(). - // If found_latch is provided, will call found_latch->CountDown() in the - // endpoint_found_cb callback. - // If lost_latch is provided, will call lost_latch->CountDown() in the - // endpoint_lost_cb callback. - Status StartDiscovery(const std::string& service_id, - CountDownLatch* found_latch, - CountDownLatch* lost_latch = nullptr); - - // Calls PcpManager::StopDiscovery(). - void StopDiscovery(); - - // Calls PcpManager::InjectEndpoint(); - void InjectEndpoint(const std::string& service_id, - const OutOfBandConnectionMetadata& metadata); - - // Calls PcpManager::RequestConnection(). - // If latch is provided, latch->CountDown() will be called in the initiated_cb - // callback. - Status RequestConnection(CountDownLatch* latch); - - // Calls PcpManager::AcceptConnection. - // If latch is provided, latch->CountDown() will be called in the accepted_cb - // callback. - Status AcceptConnection(CountDownLatch* latch); - - // Calls PcpManager::RejectConnection. - // If latch is provided, latch->CountDown() will be called in the rejected_cb - // callback. - Status RejectConnection(CountDownLatch* latch); - - // Unlike acceptance, rejection does not have to be mutual, in order to work. - // This method will allow to synchronize on the remote rejection, without - // performing a local rejection. - // latch.CountDown() will be called in the rejected_cb callback. - void ExpectRejectedConnection(CountDownLatch& latch) { - reject_latch_ = &latch; - } - - void ExpectPayload(CountDownLatch& latch) { payload_latch_ = &latch; } - void ExpectDisconnect(CountDownLatch& latch) { disconnect_latch_ = &latch; } - - const DiscoveredInfo& GetDiscovered() const { return discovered_; } - ByteArray GetInfo() const { return info_; } - - bool WaitForProgress(std::function<bool(const PayloadProgressInfo&)> pred, - absl::Duration timeout); - - Payload& GetPayload() { return payload_; } - void SendPayload(Payload payload) { - sender_payload_id_ = payload.GetId(); - ctrl_.SendPayload(&client_, {discovered_.endpoint_id}, std::move(payload)); - } - - Status CancelPayload() { - if (sender_payload_id_) { - return ctrl_.CancelPayload(&client_, sender_payload_id_); - } else { - return ctrl_.CancelPayload(&client_, payload_.GetId()); - } - } - - void Disconnect(); - - bool IsAdvertising() const { return client_.IsAdvertising(); } - - bool IsDiscovering() const { return client_.IsDiscovering(); } - - bool IsConnected() const { - return client_.IsConnectedToEndpoint(discovered_.endpoint_id); - } - - void Stop() { - StopAdvertising(); - StopDiscovery(); - ctrl_.Stop(); - } - - protected: - // ConnectionListener callbacks - void OnConnectionInitiated(const std::string& endpoint_id, - const ConnectionResponseInfo& info, - bool is_outgoing); - void OnConnectionAccepted(const std::string& endpoint_id); - void OnConnectionRejected(const std::string& endpoint_id, Status status); - void OnEndpointDisconnect(const std::string& endpoint_id); - - // DiscoveryListener callbacks - void OnEndpointFound(const std::string& endpoint_id, - const ByteArray& endpoint_info, - const std::string& service_id); - void OnEndpointLost(const std::string& endpoint_id); - - // PayloadListener callbacks - void OnPayload(const std::string& endpoint_id, Payload payload); - void OnPayloadProgress(const std::string& endpoint_id, - const PayloadProgressInfo& info); - - std::string service_id_; - DiscoveredInfo discovered_; - ConnectionOptions connection_options_; - - Mutex progress_mutex_; - ConditionVariable progress_sync_{&progress_mutex_}; - PayloadProgressInfo progress_info_; - Payload payload_; - Payload::Id sender_payload_id_ = 0; - CountDownLatch* initiated_latch_ = nullptr; - CountDownLatch* accept_latch_ = nullptr; - CountDownLatch* reject_latch_ = nullptr; - CountDownLatch* found_latch_ = nullptr; - CountDownLatch* lost_latch_ = nullptr; - CountDownLatch* payload_latch_ = nullptr; - CountDownLatch* disconnect_latch_ = nullptr; - Future<bool>* future_ = nullptr; - std::function<bool(const PayloadProgressInfo&)> predicate_; - ByteArray info_; - ConnectionOptions options_; - ClientProxy client_; - OfflineServiceController ctrl_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_OFFLINE_SIMULATION_USER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/p2p_cluster_pcp_handler.cc b/chromium/third_party/nearby/src/cpp/core/internal/p2p_cluster_pcp_handler.cc deleted file mode 100644 index 1bcc5999da4..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/p2p_cluster_pcp_handler.cc +++ /dev/null @@ -1,1364 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/p2p_cluster_pcp_handler.h" - -#include "absl/functional/bind_front.h" -#include "absl/strings/escaping.h" -#include "core/internal/base_pcp_handler.h" -#include "core/internal/ble_advertisement.h" -#include "core/internal/ble_endpoint_channel.h" -#include "core/internal/bluetooth_endpoint_channel.h" -#include "core/internal/bwu_manager.h" -#include "core/internal/mediums/utils.h" -#include "core/internal/mediums/webrtc_socket_wrapper.h" -#include "core/internal/webrtc_endpoint_channel.h" -#include "core/internal/wifi_lan_endpoint_channel.h" -#include "platform/base/nsd_service_info.h" -#include "platform/base/types.h" -#include "platform/public/crypto.h" -#include "proto/connections_enums.pb.h" - -namespace location { -namespace nearby { -namespace connections { - -ByteArray P2pClusterPcpHandler::GenerateHash(const std::string& source, - size_t size) { - return Utils::Sha256Hash(source, size); -} - -bool P2pClusterPcpHandler::ShouldAdvertiseBluetoothMacOverBle( - PowerLevel power_level) { - return power_level == PowerLevel::kHighPower; -} - -bool P2pClusterPcpHandler::ShouldAcceptBluetoothConnections( - const ConnectionOptions& options) { - return options.enable_bluetooth_listening; -} - -P2pClusterPcpHandler::P2pClusterPcpHandler( - Mediums* mediums, EndpointManager* endpoint_manager, - EndpointChannelManager* endpoint_channel_manager, BwuManager* bwu_manager, - InjectedBluetoothDeviceStore& injected_bluetooth_device_store, Pcp pcp) - : BasePcpHandler(mediums, endpoint_manager, endpoint_channel_manager, - bwu_manager, pcp), - bluetooth_radio_(mediums->GetBluetoothRadio()), - bluetooth_medium_(mediums->GetBluetoothClassic()), - ble_medium_(mediums->GetBle()), - wifi_lan_medium_(mediums->GetWifiLan()), - webrtc_medium_(mediums->GetWebRtc()), - injected_bluetooth_device_store_(injected_bluetooth_device_store) {} - -// Returns a vector or mediums sorted in order or decreasing priority for -// all the supported mediums. -// Example: WiFi_LAN, WEB_RTC, BT, BLE -std::vector<proto::connections::Medium> -P2pClusterPcpHandler::GetConnectionMediumsByPriority() { - std::vector<proto::connections::Medium> mediums; - if (wifi_lan_medium_.IsAvailable()) { - mediums.push_back(proto::connections::WIFI_LAN); - } - if (webrtc_medium_.IsAvailable()) { - mediums.push_back(proto::connections::WEB_RTC); - } - if (bluetooth_medium_.IsAvailable()) { - mediums.push_back(proto::connections::BLUETOOTH); - } - if (ble_medium_.IsAvailable()) { - mediums.push_back(proto::connections::BLE); - } - return mediums; -} - -proto::connections::Medium P2pClusterPcpHandler::GetDefaultUpgradeMedium() { - return proto::connections::WIFI_LAN; -} - -BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartAdvertisingImpl( - ClientProxy* client, const std::string& service_id, - const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, - const ConnectionOptions& options) { - std::vector<proto::connections::Medium> mediums_started_successfully; - - WebRtcState web_rtc_state{WebRtcState::kUnconnectable}; - - if (options.allowed.wifi_lan) { - proto::connections::Medium wifi_lan_medium = - StartWifiLanAdvertising(client, service_id, local_endpoint_id, - local_endpoint_info, web_rtc_state); - if (wifi_lan_medium != proto::connections::UNKNOWN_MEDIUM) { - NEARBY_LOGS(INFO) - << "P2pClusterPcpHandler::StartAdvertisingImpl: WifiLan added"; - mediums_started_successfully.push_back(wifi_lan_medium); - } - } - - if (options.allowed.bluetooth) { - const ByteArray bluetooth_hash = - GenerateHash(service_id, BluetoothDeviceName::kServiceIdHashLength); - proto::connections::Medium bluetooth_medium = StartBluetoothAdvertising( - client, service_id, bluetooth_hash, local_endpoint_id, - local_endpoint_info, web_rtc_state); - if (bluetooth_medium != proto::connections::UNKNOWN_MEDIUM) { - NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartAdvertisingImpl: BT added"); - mediums_started_successfully.push_back(bluetooth_medium); - bluetooth_classic_advertiser_client_id_ = client->GetClientId(); - } - } - - if (options.allowed.ble) { - proto::connections::Medium ble_medium = - StartBleAdvertising(client, service_id, local_endpoint_id, - local_endpoint_info, options, web_rtc_state); - if (ble_medium != proto::connections::UNKNOWN_MEDIUM) { - NEARBY_LOGS(INFO) - << "P2pClusterPcpHandler::StartAdvertisingImpl: Ble added"; - mediums_started_successfully.push_back(ble_medium); - } - } - - if (mediums_started_successfully.empty()) { - NEARBY_LOGS(ERROR) << "Failed StartAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << ") for client=" << client->GetClientId(); - return { - .status = {Status::kBluetoothError}, - }; - } - - // The rest of the operations for startAdvertising() will continue - // asynchronously via - // IncomingBluetoothConnectionProcessor.onIncomingBluetoothConnection(), so - // leave it to that to signal any errors that may occur. - return { - .status = {Status::kSuccess}, - .mediums = std::move(mediums_started_successfully), - }; -} - -Status P2pClusterPcpHandler::StopAdvertisingImpl(ClientProxy* client) { - if (client->GetClientId() == bluetooth_classic_advertiser_client_id_) { - bluetooth_medium_.TurnOffDiscoverability(); - bluetooth_classic_advertiser_client_id_ = 0; - } else { - NEARBY_LOGS(INFO) << "Skipped BT TurnOffDiscoverability for client=" - << client->GetClientId() - << ", client that turned on discoverability is " - << bluetooth_classic_advertiser_client_id_; - } - - bluetooth_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId()); - - ble_medium_.StopAdvertising(client->GetAdvertisingServiceId()); - ble_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId()); - - wifi_lan_medium_.StopAdvertising(client->GetAdvertisingServiceId()); - wifi_lan_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId()); - - return {Status::kSuccess}; -} - -bool P2pClusterPcpHandler::IsRecognizedBluetoothEndpoint( - const std::string& name_string, const std::string& service_id, - const BluetoothDeviceName& name) const { - if (!name.IsValid()) { - NEARBY_LOGS(INFO) - << name_string - << " doesn't conform to the BluetoothDeviceName format, discarding."; - return false; - } - - if (name.GetPcp() != GetPcp()) { - NEARBY_LOGS(INFO) << name_string << " doesn't match on Pcp; expected " - << PcpToStrategy(GetPcp()).GetName() << ", found " - << PcpToStrategy(name.GetPcp()).GetName(); - return false; - } - - ByteArray expected_service_id_hash = - GenerateHash(service_id, BluetoothDeviceName::kServiceIdHashLength); - - if (name.GetServiceIdHash() != expected_service_id_hash) { - NEARBY_LOGS(INFO) << name_string - << " doesn't match on expected service_id_hash; expected " - << absl::BytesToHexString(expected_service_id_hash.data()) - << ", found " - << absl::BytesToHexString(name.GetServiceIdHash().data()); - return false; - } - - return true; -} - -void P2pClusterPcpHandler::BluetoothDeviceDiscoveredHandler( - ClientProxy* client, const std::string& service_id, - BluetoothDevice device) { - RunOnPcpHandlerThread( - "p2p-bt-device-discovered", - [this, client, service_id, device]() - RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOGS(WARNING) << "Skipping discovery of BluetoothDevice " - << device.GetName() - << " because we are no longer discovering."; - return; - } - - // Parse the Bluetooth device name. - const std::string device_name_string = device.GetName(); - BluetoothDeviceName device_name(device_name_string); - - // Make sure the Bluetooth device name points to a valid - // endpoint we're discovering. - if (!IsRecognizedBluetoothEndpoint(device_name_string, service_id, - device_name)) { - NEARBY_LOGS(INFO) << "Found unrecognized BluetoothDeviceName " - << device_name_string; - return; - } - - // Report the discovered endpoint to the client. - NEARBY_LOGS(INFO) - << "Found BluetoothDeviceName " << device_name_string - << " (with endpoint_id=" << device_name.GetEndpointId() - << " and endpoint_info=" - << absl::BytesToHexString(device_name.GetEndpointInfo().data()) - << ")."; - OnEndpointFound( - client, - std::make_shared<BluetoothEndpoint>(BluetoothEndpoint{ - {device_name.GetEndpointId(), device_name.GetEndpointInfo(), - service_id, proto::connections::Medium::BLUETOOTH, - device_name.GetWebRtcState()}, - device, - })); - }); -} - -void P2pClusterPcpHandler::BluetoothNameChangedHandler( - ClientProxy* client, const std::string& service_id, - BluetoothDevice device) { - RunOnPcpHandlerThread( - "p2p-bt-name-changed", - [this, client, service_id, device]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOGS(WARNING) - << "Ignoring lost BluetoothDevice " << device.GetName() - << " because Connections is no longer discovering."; - return; - } - - // Parse the Bluetooth device name. - const std::string device_name_string = device.GetName(); - BluetoothDeviceName device_name(device_name_string); - NEARBY_LOGS(INFO) << "BT discovery handler (CHANGED) [client_id=" - << client->GetClientId() - << ", service_id=" << service_id - << "]: processing new name " << device_name_string; - - // By this point, the BluetoothDevice passed to us has a different name - // than what we may have discovered before. We need to iterate over the - // found BluetoothEndpoints and compare their addresses to see the - // devices are the same. We are not guaranteed to discover a match, - // since the old name may not have been formatted for Nearby - // Connections. - for (auto endpoint : - GetDiscoveredEndpoints(proto::connections::Medium::BLUETOOTH)) { - BluetoothEndpoint* bluetoothEndpoint = - static_cast<BluetoothEndpoint*>(endpoint); - NEARBY_LOGS(INFO) - << "BT discovery handler (CHANGED) [client_id=" - << client->GetClientId() << ", service_id=" << service_id - << "]: comparing MAC addresses with existing endpoint " - << bluetoothEndpoint->bluetooth_device.GetName() - << ". They have MAC address " - << bluetoothEndpoint->bluetooth_device.GetMacAddress() - << " and the new endpoint has MAC address " - << device.GetMacAddress(); - if (bluetoothEndpoint->bluetooth_device.GetMacAddress() == - device.GetMacAddress()) { - // Report the BluetoothEndpoint as lost to the client. - NEARBY_LOGS(INFO) << "Reporting lost BluetoothDevice " - << bluetoothEndpoint->bluetooth_device.GetName() - << ", due to device name change."; - OnEndpointLost(client, *endpoint); - break; - } - } - - // Make sure the Bluetooth device name points to a valid - // endpoint we're discovering. - if (!IsRecognizedBluetoothEndpoint(device_name_string, service_id, - device_name)) { - NEARBY_LOGS(INFO) << "Found unrecognized BluetoothDeviceName " - << device_name_string; - return; - } - - // Report the discovered endpoint to the client. - NEARBY_LOGS(INFO) << "Found BluetoothDeviceName " << device_name_string - << " (with endpoint_id=" - << device_name.GetEndpointId() - << " and endpoint_info=" - << absl::BytesToHexString( - device_name.GetEndpointInfo().data()) - << ")."; - OnEndpointFound( - client, - std::make_shared<BluetoothEndpoint>(BluetoothEndpoint{ - {device_name.GetEndpointId(), device_name.GetEndpointInfo(), - service_id, proto::connections::Medium::BLUETOOTH, - device_name.GetWebRtcState()}, - device, - })); - }); -} - -void P2pClusterPcpHandler::BluetoothDeviceLostHandler( - ClientProxy* client, const std::string& service_id, - BluetoothDevice& device) { - const std::string& device_name_string = device.GetName(); - RunOnPcpHandlerThread( - "p2p-bt-device-lost", [this, client, service_id, - device_name_string]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOGS(WARNING) - << "Ignoring lost BluetoothDevice " << device_name_string - << " because Connections is no " - "longer discovering."; - return; - } - - // Parse the Bluetooth device name. - BluetoothDeviceName device_name(device_name_string); - - // Make sure the Bluetooth device name points to a valid - // endpoint we're discovering. - if (!IsRecognizedBluetoothEndpoint(device_name_string, service_id, - device_name)) - return; - - // Report the BluetoothEndpoint as lost to the client. - NEARBY_LOGS(INFO) << "Processing lost BluetoothDeviceName " - << device_name_string; - OnEndpointLost(client, DiscoveredEndpoint{ - device_name.GetEndpointId(), - device_name.GetEndpointInfo(), service_id, - proto::connections::Medium::BLUETOOTH, - WebRtcState::kUndefined}); - }); -} - -bool P2pClusterPcpHandler::IsRecognizedBleEndpoint( - const std::string& service_id, - const BleAdvertisement& advertisement) const { - if (!advertisement.IsValid()) { - NEARBY_LOGS(INFO) - << "BleAdvertisement doesn't conform to the format, discarding."; - return false; - } - - if (advertisement.GetVersion() != kBleAdvertisementVersion) { - NEARBY_LOGS(INFO) << "BleAdvertisement has an unknown version; expected " - << static_cast<int>(kBleAdvertisementVersion) - << ", found " - << static_cast<int>(advertisement.GetVersion()); - return false; - } - - if (advertisement.GetPcp() != GetPcp()) { - NEARBY_LOGS(INFO) << "BleAdvertisement doesn't match on Pcp; expected " - << PcpToStrategy(GetPcp()).GetName() << ", found " - << PcpToStrategy(advertisement.GetPcp()).GetName(); - return false; - } - - // Check ServiceId for normal advertisement. - // ServiceIdHash is empty for fast advertisement. - if (!advertisement.IsFastAdvertisement()) { - ByteArray expected_service_id_hash = - GenerateHash(service_id, BleAdvertisement::kServiceIdHashLength); - - if (advertisement.GetServiceIdHash() != expected_service_id_hash) { - NEARBY_LOGS(INFO) - << "BleAdvertisement doesn't match on expected service_id_hash; " - "expected " - << absl::BytesToHexString(expected_service_id_hash.data()) - << ", found " - << absl::BytesToHexString(advertisement.GetServiceIdHash().data()); - return false; - } - } - - return true; -} - -void P2pClusterPcpHandler::BlePeripheralDiscoveredHandler( - ClientProxy* client, BlePeripheral& peripheral, - const std::string& service_id, const ByteArray& advertisement_bytes, - bool fast_advertisement) { - RunOnPcpHandlerThread( - "p2p-ble-device-discovered", - [this, client, &peripheral, service_id, advertisement_bytes, - fast_advertisement]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOGS(WARNING) - << "Skipping discovery of BleAdvertisement header " - << absl::BytesToHexString(advertisement_bytes.data()) - << " because we are no longer discovering."; - return; - } - - // Parse the BLE advertisement bytes. - BleAdvertisement advertisement(fast_advertisement, advertisement_bytes); - - // Make sure the BLE advertisement points to a valid - // endpoint we're discovering. - if (!IsRecognizedBleEndpoint(service_id, advertisement)) return; - - // Store all the state we need to be able to re-create a BleEndpoint - // in BlePeripheralLostHandler, since that isn't privy to - // the bytes of the ble advertisement itself. - found_ble_endpoints_.emplace( - peripheral.GetName(), - BleEndpointState(advertisement.GetEndpointId(), - advertisement.GetEndpointInfo())); - - // Report the discovered endpoint to the client. - NEARBY_LOGS(INFO) << "Found BleAdvertisement " - << absl::BytesToHexString(advertisement_bytes.data()) - << " (with endpoint_id=" - << advertisement.GetEndpointId() - << ", and endpoint_info=" - << absl::BytesToHexString( - advertisement.GetEndpointInfo().data()) - << ").", - OnEndpointFound(client, - std::make_shared<BleEndpoint>(BleEndpoint{ - {advertisement.GetEndpointId(), - advertisement.GetEndpointInfo(), service_id, - proto::connections::Medium::BLE, - advertisement.GetWebRtcState()}, - peripheral, - })); - - // Make sure we can connect to this device via Classic Bluetooth. - std::string remote_bluetooth_mac_address = - advertisement.GetBluetoothMacAddress(); - if (remote_bluetooth_mac_address.empty()) { - NEARBY_LOGS(INFO) - << "No Bluetooth Classic MAC address found in advertisement."; - return; - } - - BluetoothDevice remote_bluetooth_device = - bluetooth_medium_.GetRemoteDevice(remote_bluetooth_mac_address); - if (!remote_bluetooth_device.IsValid()) { - NEARBY_LOGS(INFO) - << "A valid Bluetooth device could not be derived from the MAC " - "address " - << remote_bluetooth_mac_address; - return; - } - - OnEndpointFound(client, - std::make_shared<BluetoothEndpoint>(BluetoothEndpoint{ - { - advertisement.GetEndpointId(), - advertisement.GetEndpointInfo(), - service_id, - proto::connections::Medium::BLUETOOTH, - advertisement.GetWebRtcState(), - }, - remote_bluetooth_device, - })); - }); -} - -void P2pClusterPcpHandler::BlePeripheralLostHandler( - ClientProxy* client, BlePeripheral& peripheral, - const std::string& service_id) { - std::string peripheral_name = peripheral.GetName(); - NEARBY_LOG(INFO, "Ble: [LOST, SCHED] peripheral_name=%s", - peripheral_name.c_str()); - RunOnPcpHandlerThread( - "p2p-ble-device-lost", - [this, client, service_id, &peripheral]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOGS(WARNING) - << "Ignoring lost BlePeripheral " << peripheral.GetName() - << " because we are no longer discovering."; - return; - } - - // Remove this BlePeripheral from found_ble_endpoints_, and - // report the endpoint as lost to the client. - auto item = found_ble_endpoints_.find(peripheral.GetName()); - if (item != found_ble_endpoints_.end()) { - BleEndpointState ble_endpoint_state(item->second); - found_ble_endpoints_.erase(item); - - // Report the discovered endpoint to the client. - NEARBY_LOGS(INFO) - << "Lost BleEndpoint for BlePeripheral " << peripheral.GetName() - << " (with endpoint_id=" << ble_endpoint_state.endpoint_id - << " and endpoint_info=" - << absl::BytesToHexString(ble_endpoint_state.endpoint_info.data()) - << ")."; - OnEndpointLost(client, DiscoveredEndpoint{ - ble_endpoint_state.endpoint_id, - ble_endpoint_state.endpoint_info, - service_id, - proto::connections::Medium::BLE, - WebRtcState::kUndefined, - }); - } - }); -} - -bool P2pClusterPcpHandler::IsRecognizedWifiLanEndpoint( - const std::string& service_id, - const WifiLanServiceInfo& wifi_lan_service_info) const { - if (!wifi_lan_service_info.IsValid()) { - NEARBY_LOGS(INFO) - << "WifiLanServiceInfo doesn't conform to the format, discarding."; - return false; - } - - if (wifi_lan_service_info.GetPcp() != GetPcp()) { - NEARBY_LOGS(INFO) - << "WifiLanServiceInfo doesn't match on Pcp; expected " - << PcpToStrategy(GetPcp()).GetName() << ", found " - << PcpToStrategy(wifi_lan_service_info.GetPcp()).GetName(); - return false; - } - - ByteArray expected_service_id_hash = - GenerateHash(service_id, WifiLanServiceInfo::kServiceIdHashLength); - - if (wifi_lan_service_info.GetServiceIdHash() != expected_service_id_hash) { - NEARBY_LOGS(INFO) - << "WifiLanServiceInfo doesn't match on expected service_id_hash; " - "expected " - << absl::BytesToHexString(expected_service_id_hash.data()) << ", found " - << absl::BytesToHexString( - wifi_lan_service_info.GetServiceIdHash().data()); - return false; - } - - return true; -} - -void P2pClusterPcpHandler::WifiLanServiceDiscoveredHandler( - ClientProxy* client, NsdServiceInfo service_info, - const std::string& service_id) { - RunOnPcpHandlerThread( - "p2p-wifi-service-discovered", - [this, client, service_id, service_info]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOGS(WARNING) << "Skipping discovery of NsdServiceInfo " - << service_info.GetServiceName() - << " because we are no longer discovering."; - return; - } - - // Parse the WifiLanServiceInfo. - WifiLanServiceInfo wifi_lan_service_info(service_info); - // Make sure the WifiLan service name points to a valid - // endpoint we're discovering. - if (!IsRecognizedWifiLanEndpoint(service_id, wifi_lan_service_info)) { - return; - } - - // Report the discovered endpoint to the client. - NEARBY_LOGS(INFO) << "Found NsdServiceInfo " - << service_info.GetServiceName() - << " (with endpoint_id=" - << wifi_lan_service_info.GetEndpointId() - << "and endpoint_info=" - << absl::BytesToHexString( - wifi_lan_service_info.GetEndpointInfo().data()) - << ")."; - OnEndpointFound(client, - std::make_shared<WifiLanEndpoint>(WifiLanEndpoint{ - { - wifi_lan_service_info.GetEndpointId(), - wifi_lan_service_info.GetEndpointInfo(), - service_id, - proto::connections::Medium::WIFI_LAN, - wifi_lan_service_info.GetWebRtcState(), - }, - service_info, - })); - }); -} - -void P2pClusterPcpHandler::WifiLanServiceLostHandler( - ClientProxy* client, NsdServiceInfo service_info, - const std::string& service_id) { - NEARBY_LOGS(INFO) << "WifiLan: [LOST, SCHED] service_info=" << &service_info - << ", service_name=" << service_info.GetServiceName(); - RunOnPcpHandlerThread( - "p2p-wifi-service-lost", - [this, client, service_id, service_info]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOGS(WARNING) << "Ignoring lost NsdServiceInfo " - << service_info.GetServiceName() - << " because we are no longer " - "discovering."; - return; - } - - // Parse the WifiLanServiceInfo. - WifiLanServiceInfo wifi_lan_service_info(service_info); - - // Make sure the WifiLan service name points to a valid - // endpoint we're discovering. - if (!IsRecognizedWifiLanEndpoint(service_id, wifi_lan_service_info)) - return; - - // Report the lost endpoint to the client. - NEARBY_LOGS(INFO) << "Lost NsdServiceInfo " - << service_info.GetServiceName() - << " (with endpoint_id=" - << wifi_lan_service_info.GetEndpointId() - << " and endpoint_info=" - << absl::BytesToHexString( - wifi_lan_service_info.GetEndpointInfo().data()) - << ")."; - OnEndpointLost(client, DiscoveredEndpoint{ - wifi_lan_service_info.GetEndpointId(), - wifi_lan_service_info.GetEndpointInfo(), - service_id, - proto::connections::Medium::WIFI_LAN, - WebRtcState::kUndefined, - }); - }); -} - -BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartDiscoveryImpl( - ClientProxy* client, const std::string& service_id, - const ConnectionOptions& options) { - // If this is an out-of-band connection, do not start actual discovery, since - // this connection is intended to be completed via InjectEndpointImpl(). - if (options.is_out_of_band_connection) { - return {.status = {Status::kSuccess}, - .mediums = options.allowed.GetMediums(true)}; - } - - std::vector<proto::connections::Medium> mediums_started_successfully; - - if (options.allowed.wifi_lan) { - proto::connections::Medium wifi_lan_medium = StartWifiLanDiscovery( - { - .service_discovered_cb = absl::bind_front( - &P2pClusterPcpHandler::WifiLanServiceDiscoveredHandler, this, - client), - .service_lost_cb = absl::bind_front( - &P2pClusterPcpHandler::WifiLanServiceLostHandler, this, client), - }, - client, service_id); - if (wifi_lan_medium != proto::connections::UNKNOWN_MEDIUM) { - NEARBY_LOGS(INFO) - << "P2pClusterPcpHandler::StartDiscoveryImpl: WifiLan added"; - mediums_started_successfully.push_back(wifi_lan_medium); - } - } - - if (options.allowed.bluetooth) { - proto::connections::Medium bluetooth_medium = StartBluetoothDiscovery( - { - .device_discovered_cb = absl::bind_front( - &P2pClusterPcpHandler::BluetoothDeviceDiscoveredHandler, this, - client, service_id), - .device_name_changed_cb = absl::bind_front( - &P2pClusterPcpHandler::BluetoothNameChangedHandler, this, - client, service_id), - .device_lost_cb = absl::bind_front( - &P2pClusterPcpHandler::BluetoothDeviceLostHandler, this, client, - service_id), - }, - client, service_id); - if (bluetooth_medium != proto::connections::UNKNOWN_MEDIUM) { - NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartDiscoveryImpl: BT added"); - mediums_started_successfully.push_back(bluetooth_medium); - bluetooth_classic_discoverer_client_id_ = client->GetClientId(); - } - } - - if (options.allowed.ble) { - proto::connections::Medium ble_medium = StartBleScanning( - { - .peripheral_discovered_cb = absl::bind_front( - &P2pClusterPcpHandler::BlePeripheralDiscoveredHandler, this, - client), - .peripheral_lost_cb = absl::bind_front( - &P2pClusterPcpHandler::BlePeripheralLostHandler, this, client), - }, - client, service_id, options.fast_advertisement_service_uuid); - if (ble_medium != proto::connections::UNKNOWN_MEDIUM) { - NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartDiscoveryImpl: Ble added"); - mediums_started_successfully.push_back(ble_medium); - } - } - - if (mediums_started_successfully.empty()) { - NEARBY_LOGS(ERROR) - << "Failed StartDiscovery() for client=" << client->GetClientId() - << " because we couldn't scan on Bluetooth, BLE, or WifiLan for " - "service_id=" - << service_id; - return { - .status = {Status::kBluetoothError}, - }; - } - - return { - .status = {Status::kSuccess}, - .mediums = std::move(mediums_started_successfully), - }; -} - -Status P2pClusterPcpHandler::StopDiscoveryImpl(ClientProxy* client) { - wifi_lan_medium_.StopDiscovery(client->GetDiscoveryServiceId()); - if (client->GetClientId() == bluetooth_classic_discoverer_client_id_) { - bluetooth_medium_.StopDiscovery(); - bluetooth_classic_discoverer_client_id_ = 0; - } else { - NEARBY_LOGS(INFO) << "Skipped BT StopDiscovery for client=" - << client->GetClientId() - << ", client that started discovery is " - << bluetooth_classic_discoverer_client_id_; - } - - ble_medium_.StopScanning(client->GetDiscoveryServiceId()); - return {Status::kSuccess}; -} - -Status P2pClusterPcpHandler::InjectEndpointImpl( - ClientProxy* client, const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) { - NEARBY_LOGS(INFO) << "InjectEndpoint."; - // Bluetooth is the only supported out-of-band connection medium. - if (metadata.medium != Medium::BLUETOOTH) { - NEARBY_LOGS(WARNING) << "InjectEndpointImpl: Only Bluetooth is supported."; - return {Status::kError}; - } - - BluetoothDevice remote_bluetooth_device = - injected_bluetooth_device_store_.CreateInjectedBluetoothDevice( - metadata.remote_bluetooth_mac_address, metadata.endpoint_id, - metadata.endpoint_info, - GenerateHash(service_id, BluetoothDeviceName::kServiceIdHashLength), - GetPcp()); - - if (!remote_bluetooth_device.IsValid()) { - NEARBY_LOG(WARNING, "InjectEndpointImpl: Invalid parameters."); - return {Status::kError}; - } - - BluetoothDeviceDiscoveredHandler(client, service_id, remote_bluetooth_device); - return {Status::kSuccess}; -} - -BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::ConnectImpl( - ClientProxy* client, BasePcpHandler::DiscoveredEndpoint* endpoint) { - if (!endpoint) { - return BasePcpHandler::ConnectImplResult{ - .status = {Status::kError}, - }; - } - switch (endpoint->medium) { - case proto::connections::Medium::BLUETOOTH: { - auto* bluetooth_endpoint = down_cast<BluetoothEndpoint*>(endpoint); - if (bluetooth_endpoint) { - return BluetoothConnectImpl(client, bluetooth_endpoint); - } - break; - } - case proto::connections::Medium::BLE: { - auto* ble_endpoint = down_cast<BleEndpoint*>(endpoint); - if (ble_endpoint) { - return BleConnectImpl(client, ble_endpoint); - } - break; - } - case proto::connections::Medium::WIFI_LAN: { - auto* wifi_lan_endpoint = down_cast<WifiLanEndpoint*>(endpoint); - if (wifi_lan_endpoint) { - return WifiLanConnectImpl(client, wifi_lan_endpoint); - } - break; - } - case proto::connections::Medium::WEB_RTC: { - break; - } - default: - break; - } - - return BasePcpHandler::ConnectImplResult{ - .status = {Status::kError}, - }; -} - -proto::connections::Medium P2pClusterPcpHandler::StartBluetoothAdvertising( - ClientProxy* client, const std::string& service_id, - const ByteArray& service_id_hash, const std::string& local_endpoint_id, - const ByteArray& local_endpoint_info, WebRtcState web_rtc_state) { - // Start listening for connections before advertising in case a connection - // request comes in very quickly. - NEARBY_LOG( - INFO, - "P2pClusterPcpHandler::StartBluetoothAdvertising: service=%s: start", - service_id.c_str()); - if (!bluetooth_medium_.IsAcceptingConnections(service_id)) { - if (!bluetooth_radio_.Enable() || - !bluetooth_medium_.StartAcceptingConnections( - service_id, {.accepted_cb = [this, client, local_endpoint_info]( - BluetoothSocket socket) { - if (!socket.IsValid()) { - NEARBY_LOGS(WARNING) - << "Invalid socket in accept callback(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId(); - return; - } - RunOnPcpHandlerThread( - "p2p-bt-on-incoming-connection", - [this, client, local_endpoint_info, - socket = std::move(socket)]() - RUN_ON_PCP_HANDLER_THREAD() mutable { - std::string remote_device_name = - socket.GetRemoteDevice().GetName(); - auto channel = - absl::make_unique<BluetoothEndpointChannel>( - remote_device_name, socket); - ByteArray remote_device_info{remote_device_name}; - - OnIncomingConnection( - client, remote_device_info, std::move(channel), - proto::connections::Medium::BLUETOOTH); - }); - }})) { - NEARBY_LOGS(WARNING) - << "In StartBluetoothAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " failed to start listening for incoming Bluetooth " - "connections to service_id=" - << service_id; - return proto::connections::UNKNOWN_MEDIUM; - } - NEARBY_LOGS(INFO) - << "In StartBluetoothAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " started listening for incoming Bluetooth connections to " - "service_id=" - << service_id; - } - - // Generate a BluetoothDeviceName with which to become Bluetooth discoverable. - // TODO(b/169550050): Implement UWBAddress. - std::string device_name(BluetoothDeviceName( - kBluetoothDeviceNameVersion, GetPcp(), local_endpoint_id, service_id_hash, - local_endpoint_info, ByteArray{}, web_rtc_state)); - if (device_name.empty()) { - NEARBY_LOGS(WARNING) << "In StartBluetoothAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " failed to generate BluetoothDeviceName {version=" - << static_cast<int>(kBluetoothDeviceNameVersion) - << ", pcp=" << PcpToStrategy(GetPcp()).GetName() - << ", endpoint_id=" << local_endpoint_id - << ", service_id_hash=" - << absl::BytesToHexString(service_id_hash.data()) - << ", endpoint_info=" - << absl::BytesToHexString(local_endpoint_info.data()) - << "}."; - bluetooth_medium_.StopAcceptingConnections(service_id); - return proto::connections::UNKNOWN_MEDIUM; - } - NEARBY_LOGS(INFO) << "In StartBluetoothAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " generated BluetoothDeviceName " << device_name - << " with service_id=" << service_id; - - // Become Bluetooth discoverable. - if (!bluetooth_medium_.TurnOnDiscoverability(device_name)) { - NEARBY_LOGS(INFO) - << "In StartBluetoothAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " couldn't start Bluetooth advertising with BluetoothDeviceName " - << device_name; - bluetooth_medium_.StopAcceptingConnections(service_id); - return proto::connections::UNKNOWN_MEDIUM; - } - NEARBY_LOGS(INFO) - << "In StartBluetoothAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " started Bluetooth advertising with BluetoothDeviceName " - << device_name; - return proto::connections::BLUETOOTH; -} - -proto::connections::Medium P2pClusterPcpHandler::StartBluetoothDiscovery( - BluetoothDiscoveredDeviceCallback callback, ClientProxy* client, - const std::string& service_id) { - if (bluetooth_radio_.Enable() && - bluetooth_medium_.StartDiscovery(std::move(callback))) { - NEARBY_LOGS(INFO) << "In StartBluetoothDiscovery(), client=" - << client->GetClientId() - << " started scanning for Bluetooth for service_id=" - << service_id; - return proto::connections::BLUETOOTH; - } else { - NEARBY_LOGS(INFO) << "In StartBluetoothDiscovery(), client=" - << client->GetClientId() - << " couldn't start scanning on Bluetooth for service_id=" - << service_id; - return proto::connections::UNKNOWN_MEDIUM; - } -} - -BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BluetoothConnectImpl( - ClientProxy* client, BluetoothEndpoint* endpoint) { - NEARBY_LOGS(VERBOSE) << "Client " << client->GetClientId() - << " is attempting to connect to endpoint(id=" - << endpoint->endpoint_id << ") over Bluetooth Classic."; - BluetoothDevice& device = endpoint->bluetooth_device; - - BluetoothSocket bluetooth_socket = bluetooth_medium_.Connect( - device, endpoint->service_id, - client->GetCancellationFlag(endpoint->endpoint_id)); - if (!bluetooth_socket.IsValid()) { - NEARBY_LOGS(ERROR) - << "In BluetoothConnectImpl(), failed to connect to Bluetooth device " - << device.GetName() << " for endpoint(id=" << endpoint->endpoint_id - << ")."; - return BasePcpHandler::ConnectImplResult{ - .status = {Status::kBluetoothError}, - }; - } - - auto channel = absl::make_unique<BluetoothEndpointChannel>( - endpoint->endpoint_id, bluetooth_socket); - NEARBY_LOGS(VERBOSE) << "Client" << client->GetClientId() - << " created Bluetooth endpoint channel to endpoint(id=" - << endpoint->endpoint_id << ")."; - return BasePcpHandler::ConnectImplResult{ - .medium = proto::connections::Medium::BLUETOOTH, - .status = {Status::kSuccess}, - .endpoint_channel = std::move(channel), - }; -} - -proto::connections::Medium P2pClusterPcpHandler::StartBleAdvertising( - ClientProxy* client, const std::string& service_id, - const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, - const ConnectionOptions& options, WebRtcState web_rtc_state) { - bool fast_advertisement = !options.fast_advertisement_service_uuid.empty(); - PowerLevel power_level = - options.low_power ? PowerLevel::kLowPower : PowerLevel::kHighPower; - - // Start listening for connections before advertising in case a connection - // request comes in very quickly. BLE allows connecting over BLE itself, as - // well as advertising the Bluetooth MAC address to allow connecting over - // Bluetooth Classic. - NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::StartBleAdvertising: service_id=" - << service_id << " : start"; - if (!ble_medium_.IsAcceptingConnections(service_id)) { - if (!bluetooth_radio_.Enable() || - !ble_medium_.StartAcceptingConnections( - service_id, {.accepted_cb = [this, client, local_endpoint_info]( - BleSocket socket, - const std::string& service_id) { - if (!socket.IsValid()) { - NEARBY_LOGS(WARNING) - << "Invalid socket in accept callback(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId(); - return; - } - RunOnPcpHandlerThread( - "p2p-ble-on-incoming-connection", - [this, client, local_endpoint_info, service_id, - socket = std::move(socket)]() - RUN_ON_PCP_HANDLER_THREAD() mutable { - std::string remote_peripheral_name = - socket.GetRemotePeripheral().GetName(); - auto channel = absl::make_unique<BleEndpointChannel>( - remote_peripheral_name, socket); - ByteArray remote_peripheral_info = - socket.GetRemotePeripheral().GetAdvertisementBytes( - service_id); - - OnIncomingConnection(client, remote_peripheral_info, - std::move(channel), - proto::connections::Medium::BLE); - }); - }})) { - NEARBY_LOGS(WARNING) - << "In StartBleAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " failed to start accepting for incoming BLE connections to " - "service_id=" - << service_id; - return proto::connections::UNKNOWN_MEDIUM; - } - NEARBY_LOGS(INFO) - << "In StartBleAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " started accepting for incoming BLE connections to service_id=" - << service_id; - } - - if (ShouldAdvertiseBluetoothMacOverBle(power_level) || - ShouldAcceptBluetoothConnections(options)) { - if (bluetooth_medium_.IsAvailable() && - !bluetooth_medium_.IsAcceptingConnections(service_id)) { - if (!bluetooth_radio_.Enable() || - !bluetooth_medium_.StartAcceptingConnections( - service_id, {.accepted_cb = [this, client, local_endpoint_info]( - BluetoothSocket socket) { - if (!socket.IsValid()) { - NEARBY_LOGS(WARNING) - << "In BT StartAcceptingConnections.accepted_cb(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << ": Invalid socket in accept callback."; - return; - } - RunOnPcpHandlerThread( - "p2p-bt-on-incoming-connection", - [this, client, local_endpoint_info, - socket = std::move(socket)]() - RUN_ON_PCP_HANDLER_THREAD() mutable { - std::string remote_device_name = - socket.GetRemoteDevice().GetName(); - auto channel = - absl::make_unique<BluetoothEndpointChannel>( - remote_device_name, socket); - ByteArray remote_device_info{remote_device_name}; - - OnIncomingConnection( - client, remote_device_info, std::move(channel), - proto::connections::Medium::BLUETOOTH); - }); - }})) { - NEARBY_LOGS(WARNING) - << "In BT StartBleAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " failed to start accepting for incoming BLE connections to " - "service_id=" - << service_id; - ble_medium_.StopAcceptingConnections(service_id); - return proto::connections::UNKNOWN_MEDIUM; - } - NEARBY_LOGS(INFO) - << "In BT StartBleAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " started accepting for incoming BLE connections to service_id=" - << service_id; - } - } - - NEARBY_LOGS(INFO) << "In StartBleAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " start to generate BleAdvertisement with service_id=" - << service_id - << ", local endpoint_id=" << local_endpoint_id; - // Generate a BleAdvertisement. If a fast advertisement service UUID was - // provided, create a fast BleAdvertisement. - ByteArray advertisement_bytes; - // TODO(b/169550050): Implement UWBAddress. - if (fast_advertisement) { - advertisement_bytes = ByteArray( - BleAdvertisement(kBleAdvertisementVersion, GetPcp(), local_endpoint_id, - local_endpoint_info, ByteArray{})); - } else { - const ByteArray service_id_hash = - GenerateHash(service_id, BleAdvertisement::kServiceIdHashLength); - std::string bluetooth_mac_address; - if (bluetooth_medium_.IsAvailable() && - ShouldAdvertiseBluetoothMacOverBle(power_level)) - bluetooth_mac_address = bluetooth_medium_.GetMacAddress(); - - advertisement_bytes = ByteArray( - BleAdvertisement(kBleAdvertisementVersion, GetPcp(), service_id_hash, - local_endpoint_id, local_endpoint_info, - bluetooth_mac_address, ByteArray{}, web_rtc_state)); - } - if (advertisement_bytes.Empty()) { - NEARBY_LOGS(WARNING) << "In StartBleAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " failed to create an advertisement.", - ble_medium_.StopAcceptingConnections(service_id); - return proto::connections::UNKNOWN_MEDIUM; - } - - NEARBY_LOGS(INFO) << "In StartBleAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " generated BleAdvertisement with service_id=" - << service_id; - - if (!ble_medium_.StartAdvertising(service_id, advertisement_bytes, - options.fast_advertisement_service_uuid)) { - NEARBY_LOGS(WARNING) - << "In StartBleAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " couldn't start BLE Advertising with BleAdvertisement " - << absl::BytesToHexString(advertisement_bytes.data()); - ble_medium_.StopAcceptingConnections(service_id); - return proto::connections::UNKNOWN_MEDIUM; - } - NEARBY_LOGS(INFO) << "In startBleAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " started BLE Advertising with BleAdvertisement " - << absl::BytesToHexString(advertisement_bytes.data()); - return proto::connections::BLE; -} - -proto::connections::Medium P2pClusterPcpHandler::StartBleScanning( - BleDiscoveredPeripheralCallback callback, ClientProxy* client, - const std::string& service_id, - const std::string& fast_advertisement_service_uuid) { - if (bluetooth_radio_.Enable() && - ble_medium_.StartScanning(service_id, fast_advertisement_service_uuid, - std::move(callback))) { - NEARBY_LOGS(INFO) - << "In StartBleScanning(), client=" << client->GetClientId() - << " started scanning for BLE advertisements for service_id=" - << service_id; - return proto::connections::BLE; - } else { - NEARBY_LOGS(INFO) << "In StartBleScanning(), client=" - << client->GetClientId() - << " couldn't start scanning on BLE for service_id=" - << service_id; - return proto::connections::UNKNOWN_MEDIUM; - } -} - -BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BleConnectImpl( - ClientProxy* client, BleEndpoint* endpoint) { - NEARBY_LOGS(VERBOSE) << "Client " << client->GetClientId() - << " is attempting to connect to endpoint(id=" - << endpoint->endpoint_id << ") over BLE."; - - BlePeripheral& peripheral = endpoint->ble_peripheral; - - BleSocket ble_socket = - ble_medium_.Connect(peripheral, endpoint->service_id, - client->GetCancellationFlag(endpoint->endpoint_id)); - if (!ble_socket.IsValid()) { - NEARBY_LOGS(ERROR) - << "In BleConnectImpl(), failed to connect to BLE device " - << peripheral.GetName() << " for endpoint(id=" << endpoint->endpoint_id - << ")."; - return BasePcpHandler::ConnectImplResult{ - .status = {Status::kBleError}, - }; - } - - auto channel = - absl::make_unique<BleEndpointChannel>(endpoint->endpoint_id, ble_socket); - - return BasePcpHandler::ConnectImplResult{ - .medium = proto::connections::Medium::BLE, - .status = {Status::kSuccess}, - .endpoint_channel = std::move(channel), - }; -} - -proto::connections::Medium P2pClusterPcpHandler::StartWifiLanAdvertising( - ClientProxy* client, const std::string& service_id, - const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, - WebRtcState web_rtc_state) { - // Start listening for connections before advertising in case a connection - // request comes in very quickly. - NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::StartWifiLanAdvertising: service=" - << service_id << ": start"; - if (!wifi_lan_medium_.IsAcceptingConnections(service_id)) { - if (!wifi_lan_medium_.StartAcceptingConnections( - service_id, - {.accepted_cb = [this, client, local_endpoint_info, - local_endpoint_id](WifiLanSocket socket) { - if (!socket.IsValid()) { - NEARBY_LOGS(WARNING) - << "Invalid socket in accept callback(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId(); - return; - } - RunOnPcpHandlerThread( - "p2p-wifi-on-incoming-connection", - [this, client, local_endpoint_id, local_endpoint_info, - socket = std::move( - socket)]() RUN_ON_PCP_HANDLER_THREAD() mutable { - std::string remote_service_name = local_endpoint_id; - auto channel = absl::make_unique<WifiLanEndpointChannel>( - remote_service_name, socket); - ByteArray remote_service_name_byte{remote_service_name}; - - OnIncomingConnection(client, remote_service_name_byte, - std::move(channel), - proto::connections::Medium::WIFI_LAN); - }); - }})) { - NEARBY_LOGS(WARNING) - << "In StartWifiLanAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " failed to start listening for incoming WifiLan connections " - "to service_id=" - << service_id; - return proto::connections::UNKNOWN_MEDIUM; - } - NEARBY_LOGS(INFO) << "In StartWifiLanAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " started listening for incoming WifiLan connections " - "to service_id = " - << service_id; - } - - // Generate a WifiLanServiceInfo with which to become WifiLan discoverable. - // TODO(b/169550050): Implement UWBAddress. - const ByteArray service_id_hash = - GenerateHash(service_id, WifiLanServiceInfo::kServiceIdHashLength); - WifiLanServiceInfo service_info{kWifiLanServiceInfoVersion, - GetPcp(), - local_endpoint_id, - service_id_hash, - local_endpoint_info, - ByteArray{}, - web_rtc_state}; - NsdServiceInfo nsd_service_info(service_info); - if (!nsd_service_info.IsValid()) { - NEARBY_LOGS(WARNING) << "In StartWifiLanAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " failed to generate WifiLanServiceInfo {version=" - << static_cast<int>(kWifiLanServiceInfoVersion) - << ", pcp=" << PcpToStrategy(GetPcp()).GetName() - << ", endpoint_id=" << local_endpoint_id - << ", service_id_hash=" - << absl::BytesToHexString(service_id_hash.data()) - << ", endpoint_info=" - << absl::BytesToHexString(local_endpoint_info.data()) - << "}."; - wifi_lan_medium_.StopAcceptingConnections(service_id); - return proto::connections::UNKNOWN_MEDIUM; - } - NEARBY_LOGS(INFO) << "In StartWifiLanAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " generated WifiLanServiceInfo " - << nsd_service_info.GetServiceName() - << " with service_id=" << service_id; - - if (!wifi_lan_medium_.StartAdvertising(service_id, nsd_service_info)) { - NEARBY_LOGS(INFO) << "In StartWifiLanAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " couldn't advertise with WifiLanServiceInfo " - << nsd_service_info.GetServiceName(); - wifi_lan_medium_.StopAcceptingConnections(service_id); - return proto::connections::UNKNOWN_MEDIUM; - } - NEARBY_LOGS(INFO) << "In StartWifiLanAdvertising(" - << absl::BytesToHexString(local_endpoint_info.data()) - << "), client=" << client->GetClientId() - << " advertised with WifiLanServiceInfo " - << nsd_service_info.GetServiceName(); - return proto::connections::WIFI_LAN; -} - -proto::connections::Medium P2pClusterPcpHandler::StartWifiLanDiscovery( - WifiLanDiscoveredServiceCallback callback, ClientProxy* client, - const std::string& service_id) { - if (wifi_lan_medium_.StartDiscovery(service_id, std::move(callback))) { - NEARBY_LOGS(INFO) << "In StartWifiLanDiscovery(), client=" - << client->GetClientId() - << " started scanning for Wifi devices for service_id=" - << service_id; - return proto::connections::WIFI_LAN; - } else { - NEARBY_LOGS(INFO) << "In StartWifiLanDiscovery(), client=" - << client->GetClientId() - << " couldn't start scanning on Wifi for service_id=" - << service_id; - return proto::connections::UNKNOWN_MEDIUM; - } -} - -BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::WifiLanConnectImpl( - ClientProxy* client, WifiLanEndpoint* endpoint) { - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " is attempting to connect to endpoint(id=" - << endpoint->endpoint_id << ") over WifiLan."; - WifiLanSocket socket = wifi_lan_medium_.Connect( - endpoint->service_id, endpoint->service_info, - client->GetCancellationFlag(endpoint->endpoint_id)); - NEARBY_LOGS(ERROR) << "In WifiLanConnectImpl(), connect to service " - << " socket=" << &socket.GetImpl() - << " for endpoint(id=" << endpoint->endpoint_id << ")."; - if (!socket.IsValid()) { - NEARBY_LOGS(ERROR) - << "In WifiLanConnectImpl(), failed to connect to service " - << endpoint->service_info.GetServiceName() - << " for endpoint(id=" << endpoint->endpoint_id << ")."; - return BasePcpHandler::ConnectImplResult{ - .status = {Status::kWifiLanError}, - }; - } - - auto channel = - absl::make_unique<WifiLanEndpointChannel>(endpoint->endpoint_id, socket); - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " created WifiLan endpoint channel to endpoint(id=" - << endpoint->endpoint_id << ")."; - return BasePcpHandler::ConnectImplResult{ - .medium = proto::connections::Medium::WIFI_LAN, - .status = {Status::kSuccess}, - .endpoint_channel = std::move(channel), - }; -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/p2p_cluster_pcp_handler.h b/chromium/third_party/nearby/src/cpp/core/internal/p2p_cluster_pcp_handler.h deleted file mode 100644 index 6fe0178ba81..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/p2p_cluster_pcp_handler.h +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_P2P_CLUSTER_PCP_HANDLER_H_ -#define CORE_INTERNAL_P2P_CLUSTER_PCP_HANDLER_H_ - -#include <memory> -#include <vector> - -#include "core/internal/base_pcp_handler.h" -#include "core/internal/ble_advertisement.h" -#include "core/internal/bluetooth_device_name.h" -#include "core/internal/bwu_manager.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel_manager.h" -#include "core/internal/endpoint_manager.h" -#include "core/internal/injected_bluetooth_device_store.h" -#include "core/internal/mediums/bluetooth_classic.h" -#include "core/internal/mediums/mediums.h" -#include "core/internal/mediums/webrtc.h" -#include "core/internal/pcp.h" -#include "core/internal/wifi_lan_service_info.h" -#include "core/options.h" -#include "core/strategy.h" -#include "platform/base/byte_array.h" -#include "platform/public/bluetooth_classic.h" -#include "platform/public/wifi_lan.h" - -namespace location { -namespace nearby { -namespace connections { - -// Concrete implementation of the PCPHandler for the P2P_CLUSTER PCP. This PCP -// is reserved for mediums that can connect to multiple devices simultaneously -// and all devices are considered equal. For asymmetric mediums, where one -// device is a server and the others are clients, use P2PStarPCPHandler instead. -// -// Currently, this implementation advertises/discovers over Bluetooth and -// connects over Bluetooth. -class P2pClusterPcpHandler : public BasePcpHandler { - public: - P2pClusterPcpHandler( - Mediums* mediums, EndpointManager* endpoint_manager, - EndpointChannelManager* channel_manager, BwuManager* bwu_manager, - InjectedBluetoothDeviceStore& injected_bluetooth_device_store, - Pcp pcp = Pcp::kP2pCluster); - ~P2pClusterPcpHandler() override = default; - - protected: - std::vector<proto::connections::Medium> GetConnectionMediumsByPriority() - override; - proto::connections::Medium GetDefaultUpgradeMedium() override; - - // @PCPHandlerThread - BasePcpHandler::StartOperationResult StartAdvertisingImpl( - ClientProxy* client, const std::string& service_id, - const std::string& local_endpoint_id, - const ByteArray& local_endpoint_info, - const ConnectionOptions& options) override; - - // @PCPHandlerThread - Status StopAdvertisingImpl(ClientProxy* client) override; - - // @PCPHandlerThread - BasePcpHandler::StartOperationResult StartDiscoveryImpl( - ClientProxy* client, const std::string& service_id, - const ConnectionOptions& options) override; - - // @PCPHandlerThread - Status StopDiscoveryImpl(ClientProxy* client) override; - - // @PCPHandlerThread - Status InjectEndpointImpl( - ClientProxy* client, const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) override; - - // @PCPHandlerThread - BasePcpHandler::ConnectImplResult ConnectImpl( - ClientProxy* client, - BasePcpHandler::DiscoveredEndpoint* endpoint) override; - - private: - // Holds the state required to re-create a BleEndpoint we see on a - // BlePeripheral, so BlePeripheralLostHandler can call - // BasePcpHandler::OnEndpointLost() with the same information as was passed - // in to BasePCPHandler::onEndpointFound(). - struct BleEndpointState { - public: - BleEndpointState(const string& endpoint_id, const ByteArray& endpoint_info) - : endpoint_id(endpoint_id), endpoint_info(endpoint_info) {} - - std::string endpoint_id; - ByteArray endpoint_info; - }; - - using BluetoothDiscoveredDeviceCallback = - BluetoothClassic::DiscoveredDeviceCallback; - using BleDiscoveredPeripheralCallback = Ble::DiscoveredPeripheralCallback; - using WifiLanDiscoveredServiceCallback = WifiLan::DiscoveredServiceCallback; - - static constexpr BluetoothDeviceName::Version kBluetoothDeviceNameVersion = - BluetoothDeviceName::Version::kV1; - static constexpr BleAdvertisement::Version kBleAdvertisementVersion = - BleAdvertisement::Version::kV1; - static constexpr WifiLanServiceInfo::Version kWifiLanServiceInfoVersion = - WifiLanServiceInfo::Version::kV1; - - static ByteArray GenerateHash(const std::string& source, size_t size); - static bool ShouldAdvertiseBluetoothMacOverBle(PowerLevel power_level); - static bool ShouldAcceptBluetoothConnections( - const ConnectionOptions& options); - - // Bluetooth - bool IsRecognizedBluetoothEndpoint(const std::string& name_string, - const std::string& service_id, - const BluetoothDeviceName& name) const; - void BluetoothDeviceDiscoveredHandler(ClientProxy* client, - const std::string& service_id, - BluetoothDevice device); - void BluetoothNameChangedHandler(ClientProxy* client, - const std::string& service_id, - BluetoothDevice device); - void BluetoothDeviceLostHandler(ClientProxy* client, - const std::string& service_id, - BluetoothDevice& device); - proto::connections::Medium StartBluetoothAdvertising( - ClientProxy* client, const std::string& service_id, - const ByteArray& service_id_hash, const std::string& local_endpoint_id, - const ByteArray& local_endpoint_info, WebRtcState web_rtc_state); - proto::connections::Medium StartBluetoothDiscovery( - BluetoothDiscoveredDeviceCallback callback, ClientProxy* client, - const std::string& service_id); - BasePcpHandler::ConnectImplResult BluetoothConnectImpl( - ClientProxy* client, BluetoothEndpoint* endpoint); - - // Ble - // Maps a BlePeripheral to its corresponding BleEndpointState. - absl::flat_hash_map<std::string, BleEndpointState> found_ble_endpoints_; - bool IsRecognizedBleEndpoint(const std::string& service_id, - const BleAdvertisement& advertisement) const; - void BlePeripheralDiscoveredHandler(ClientProxy* client, - BlePeripheral& peripheral, - const std::string& service_id, - const ByteArray& advertisement_bytes, - bool fast_advertisement); - void BlePeripheralLostHandler(ClientProxy* client, BlePeripheral& peripheral, - const std::string& service_id); - proto::connections::Medium StartBleAdvertising( - ClientProxy* client, const std::string& service_id, - const std::string& local_endpoint_id, - const ByteArray& local_endpoint_info, const ConnectionOptions& options, - WebRtcState web_rtc_state); - proto::connections::Medium StartBleScanning( - BleDiscoveredPeripheralCallback callback, ClientProxy* client, - const std::string& service_id, - const std::string& fast_advertisement_service_uuid); - BasePcpHandler::ConnectImplResult BleConnectImpl(ClientProxy* client, - BleEndpoint* endpoint); - - // WifiLan - bool IsRecognizedWifiLanEndpoint( - const std::string& service_id, - const WifiLanServiceInfo& wifi_lan_service_info) const; - void WifiLanServiceDiscoveredHandler(ClientProxy* client, - NsdServiceInfo service_info, - const std::string& service_id); - void WifiLanServiceLostHandler(ClientProxy* client, - NsdServiceInfo service_info, - const std::string& service_id); - proto::connections::Medium StartWifiLanAdvertising( - ClientProxy* client, const std::string& service_id, - const std::string& local_endpoint_id, - const ByteArray& local_endpoint_info, WebRtcState web_rtc_state); - proto::connections::Medium StartWifiLanDiscovery( - WifiLanDiscoveredServiceCallback callback, ClientProxy* client, - const std::string& service_id); - BasePcpHandler::ConnectImplResult WifiLanConnectImpl( - ClientProxy* client, WifiLanEndpoint* endpoint); - - BluetoothRadio& bluetooth_radio_; - BluetoothClassic& bluetooth_medium_; - Ble& ble_medium_; - WifiLan& wifi_lan_medium_; - mediums::WebRtc& webrtc_medium_; - InjectedBluetoothDeviceStore& injected_bluetooth_device_store_; - std::int64_t bluetooth_classic_discoverer_client_id_{0}; - std::int64_t bluetooth_classic_advertiser_client_id_{0}; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_P2P_CLUSTER_PCP_HANDLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/p2p_cluster_pcp_handler_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/p2p_cluster_pcp_handler_test.cc deleted file mode 100644 index 526cee6648a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/p2p_cluster_pcp_handler_test.cc +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/p2p_cluster_pcp_handler.h" - -#include <memory> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/time/time.h" -#include "core/internal/bwu_manager.h" -#include "core/internal/injected_bluetooth_device_store.h" -#include "core/options.h" -#include "platform/base/medium_environment.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -constexpr BooleanMediumSelector kTestCases[] = { - BooleanMediumSelector{ - .bluetooth = true, - }, - BooleanMediumSelector{ - .wifi_lan = true, - }, - BooleanMediumSelector{ - .bluetooth = true, - .wifi_lan = true, - }, -}; - -class P2pClusterPcpHandlerTest - : public ::testing::TestWithParam<BooleanMediumSelector> { - protected: - void SetUp() override { - NEARBY_LOG(INFO, "SetUp: begin"); - env_.Stop(); - if (options_.allowed.bluetooth) { - NEARBY_LOG(INFO, "SetUp: BT enabled"); - } - if (options_.allowed.wifi_lan) { - NEARBY_LOG(INFO, "SetUp: WifiLan enabled"); - } - if (options_.allowed.web_rtc) { - NEARBY_LOG(INFO, "SetUp: WebRTC enabled"); - } - NEARBY_LOG(INFO, "SetUp: end"); - } - - ClientProxy client_a_; - ClientProxy client_b_; - std::string service_id_{"service"}; - ConnectionOptions options_{ - .strategy = Strategy::kP2pCluster, - .allowed = GetParam(), - }; - MediumEnvironment& env_{MediumEnvironment::Instance()}; -}; - -TEST_P(P2pClusterPcpHandlerTest, CanConstructOne) { - env_.Start(); - Mediums mediums; - EndpointChannelManager ecm; - EndpointManager em(&ecm); - BwuManager bwu(mediums, em, ecm, {}, {}); - InjectedBluetoothDeviceStore ibds; - P2pClusterPcpHandler handler(&mediums, &em, &ecm, &bwu, ibds); - env_.Stop(); -} - -TEST_P(P2pClusterPcpHandlerTest, CanConstructMultiple) { - env_.Start(); - Mediums mediums_a; - Mediums mediums_b; - EndpointChannelManager ecm_a; - EndpointChannelManager ecm_b; - EndpointManager em_a(&ecm_a); - EndpointManager em_b(&ecm_b); - BwuManager bwu_a(mediums_a, em_a, ecm_a, {}, {}); - BwuManager bwu_b(mediums_b, em_b, ecm_b, {}, {}); - InjectedBluetoothDeviceStore ibds_a; - InjectedBluetoothDeviceStore ibds_b; - P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a, ibds_a); - P2pClusterPcpHandler handler_b(&mediums_b, &em_b, &ecm_b, &bwu_b, ibds_b); - env_.Stop(); -} - -TEST_P(P2pClusterPcpHandlerTest, CanAdvertise) { - env_.Start(); - std::string endpoint_name{"endpoint_name"}; - Mediums mediums_a; - EndpointChannelManager ecm_a; - EndpointManager em_a(&ecm_a); - BwuManager bwu_a(mediums_a, em_a, ecm_a, {}, {}); - InjectedBluetoothDeviceStore ibds_a; - P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a, ibds_a); - EXPECT_EQ( - handler_a.StartAdvertising(&client_a_, service_id_, options_, - {.endpoint_info = ByteArray{endpoint_name}}), - Status{Status::kSuccess}); - env_.Stop(); -} - -TEST_P(P2pClusterPcpHandlerTest, CanDiscover) { - env_.Start(); - std::string endpoint_name{"endpoint_name"}; - Mediums mediums_a; - Mediums mediums_b; - EndpointChannelManager ecm_a; - EndpointChannelManager ecm_b; - EndpointManager em_a(&ecm_a); - EndpointManager em_b(&ecm_b); - BwuManager bwu_a(mediums_a, em_a, ecm_a, {}, {}); - BwuManager bwu_b(mediums_b, em_b, ecm_b, {}, {}); - InjectedBluetoothDeviceStore ibds_a; - InjectedBluetoothDeviceStore ibds_b; - P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a, ibds_a); - P2pClusterPcpHandler handler_b(&mediums_b, &em_b, &ecm_b, &bwu_b, ibds_b); - CountDownLatch latch(1); - EXPECT_EQ( - handler_a.StartAdvertising(&client_a_, service_id_, options_, - {.endpoint_info = ByteArray{endpoint_name}}), - Status{Status::kSuccess}); - EXPECT_EQ(handler_b.StartDiscovery( - &client_b_, service_id_, options_, - { - .endpoint_found_cb = - [&latch](const std::string& endpoint_id, - const ByteArray& endpoint_info, - const std::string& service_id) { - NEARBY_LOG(INFO, "Device discovered: id=%s", - endpoint_id.c_str()); - latch.CountDown(); - }, - }), - Status{Status::kSuccess}); - EXPECT_TRUE(latch.Await(absl::Milliseconds(1000)).result()); - // We discovered endpoint over one medium. Before we finish the test, we have - // to stop discovery for other mediums that may be still ongoing. - handler_b.StopDiscovery(&client_b_); - env_.Stop(); -} - -TEST_P(P2pClusterPcpHandlerTest, CanConnect) { - env_.Start(); - std::string endpoint_name_a{"endpoint_name"}; - Mediums mediums_a; - Mediums mediums_b; - BluetoothRadio& radio_a = mediums_a.GetBluetoothRadio(); - BluetoothRadio& radio_b = mediums_b.GetBluetoothRadio(); - radio_a.GetBluetoothAdapter().SetName("BT Device A"); - radio_b.GetBluetoothAdapter().SetName("BT Device B"); - EndpointChannelManager ecm_a; - EndpointChannelManager ecm_b; - EndpointManager em_a(&ecm_a); - EndpointManager em_b(&ecm_b); - BwuManager bwu_a(mediums_a, em_a, ecm_a, {}, - {.allow_upgrade_to = {.bluetooth = true}}); - BwuManager bwu_b(mediums_b, em_b, ecm_b, {}, - {.allow_upgrade_to = {.bluetooth = true}}); - InjectedBluetoothDeviceStore ibds_a; - InjectedBluetoothDeviceStore ibds_b; - P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a, ibds_a); - P2pClusterPcpHandler handler_b(&mediums_b, &em_b, &ecm_b, &bwu_b, ibds_b); - CountDownLatch discover_latch(1); - CountDownLatch connect_latch(2); - struct DiscoveredInfo { - std::string endpoint_id; - ByteArray endpoint_info; - std::string service_id; - } discovered; - EXPECT_EQ( - handler_a.StartAdvertising( - &client_a_, service_id_, options_, - { - .endpoint_info = ByteArray{endpoint_name_a}, - .listener = - { - .initiated_cb = - [&connect_latch](const std::string& endpoint_id, - const ConnectionResponseInfo& info) { - NEARBY_LOG(INFO, - "StartAdvertising: initiated_cb called"); - connect_latch.CountDown(); - }, - }, - }), - Status{Status::kSuccess}); - EXPECT_EQ(handler_b.StartDiscovery( - &client_b_, service_id_, options_, - { - .endpoint_found_cb = - [&discover_latch, &discovered]( - const std::string& endpoint_id, - const ByteArray& endpoint_info, - const std::string& service_id) { - NEARBY_LOG( - INFO, - "Device discovered: id=%s, endpoint_info=%s", - endpoint_id.c_str(), - std::string{endpoint_info}.c_str()); - discovered = { - .endpoint_id = endpoint_id, - .endpoint_info = endpoint_info, - .service_id = service_id, - }; - discover_latch.CountDown(); - }, - }), - Status{Status::kSuccess}); - - EXPECT_TRUE(discover_latch.Await(absl::Milliseconds(1000)).result()); - EXPECT_EQ(endpoint_name_a, std::string{discovered.endpoint_info}); - - client_b_.AddCancellationFlag(discovered.endpoint_id); - handler_b.RequestConnection( - &client_b_, discovered.endpoint_id, - { - .endpoint_info = discovered.endpoint_info, - .listener = - { - .initiated_cb = - [&connect_latch](const std::string& endpoint_id, - const ConnectionResponseInfo& info) { - NEARBY_LOG(INFO, - "RequestConnection: initiated_cb called"); - connect_latch.CountDown(); - }, - }, - }, - options_); - EXPECT_TRUE(connect_latch.Await(absl::Milliseconds(1000)).result()); - bwu_a.Shutdown(); - bwu_b.Shutdown(); - env_.Stop(); -} - -INSTANTIATE_TEST_SUITE_P(ParametrisedPcpHandlerTest, P2pClusterPcpHandlerTest, - ::testing::ValuesIn(kTestCases)); - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/p2p_point_to_point_pcp_handler.cc b/chromium/third_party/nearby/src/cpp/core/internal/p2p_point_to_point_pcp_handler.cc deleted file mode 100644 index 2ac80e78226..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/p2p_point_to_point_pcp_handler.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/p2p_point_to_point_pcp_handler.h" - -namespace location { -namespace nearby { -namespace connections { - -P2pPointToPointPcpHandler::P2pPointToPointPcpHandler( - Mediums& mediums, EndpointManager& endpoint_manager, - EndpointChannelManager& channel_manager, BwuManager& bwu_manager, - InjectedBluetoothDeviceStore& injected_bluetooth_device_store, Pcp pcp) - : P2pStarPcpHandler(mediums, endpoint_manager, channel_manager, bwu_manager, - injected_bluetooth_device_store, pcp) {} - -std::vector<proto::connections::Medium> -P2pPointToPointPcpHandler::GetConnectionMediumsByPriority() { - std::vector<proto::connections::Medium> mediums; - if (mediums_->GetWifiLan().IsAvailable()) { - mediums.push_back(proto::connections::WIFI_LAN); - } - if (mediums_->GetWebRtc().IsAvailable()) { - mediums.push_back(proto::connections::WEB_RTC); - } - if (mediums_->GetBluetoothClassic().IsAvailable()) { - mediums.push_back(proto::connections::BLUETOOTH); - } - if (mediums_->GetBle().IsAvailable()) { - mediums.push_back(proto::connections::BLE); - } - return mediums; -} - -bool P2pPointToPointPcpHandler::CanSendOutgoingConnection( - ClientProxy* client) const { - // For point to point, we can only send an outgoing connection while we have - // no other connections. - return !this->HasOutgoingConnections(client) && - !this->HasIncomingConnections(client); -} - -bool P2pPointToPointPcpHandler::CanReceiveIncomingConnection( - ClientProxy* client) const { - // For point to point, we can only receive an incoming connection while we - // have no other connections. - return !this->HasOutgoingConnections(client) && - !this->HasIncomingConnections(client); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/p2p_point_to_point_pcp_handler.h b/chromium/third_party/nearby/src/cpp/core/internal/p2p_point_to_point_pcp_handler.h deleted file mode 100644 index fa6ac46c218..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/p2p_point_to_point_pcp_handler.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_P2P_POINT_TO_POINT_PCP_HANDLER_H_ -#define CORE_INTERNAL_P2P_POINT_TO_POINT_PCP_HANDLER_H_ - -#include "core/internal/endpoint_channel_manager.h" -#include "core/internal/endpoint_manager.h" -#include "core/internal/p2p_star_pcp_handler.h" -#include "core/internal/pcp.h" -#include "core/strategy.h" - -namespace location { -namespace nearby { -namespace connections { - -// Concrete implementation of the PCPHandler for the P2P_POINT_TO_POINT. This -// PCP is for mediums that have limitations on the number of simultaneous -// connections; all mediums in P2P_STAR are valid for P2P_POINT_TO_POINT, but -// not all mediums in P2P_POINT_TO_POINT are valid for P2P_STAR. -// -// Currently, this implementation advertises/discovers over Bluetooth -// and connects over Bluetooth. -class P2pPointToPointPcpHandler : public P2pStarPcpHandler { - public: - P2pPointToPointPcpHandler( - Mediums& mediums, EndpointManager& endpoint_manager, - EndpointChannelManager& channel_manager, BwuManager& bwu_manager, - InjectedBluetoothDeviceStore& injected_bluetooth_device_store, - Pcp pcp = Pcp::kP2pPointToPoint); - - protected: - std::vector<proto::connections::Medium> GetConnectionMediumsByPriority() - override; - - bool CanSendOutgoingConnection(ClientProxy* client) const override; - bool CanReceiveIncomingConnection(ClientProxy* client) const override; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_P2P_POINT_TO_POINT_PCP_HANDLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/p2p_star_pcp_handler.cc b/chromium/third_party/nearby/src/cpp/core/internal/p2p_star_pcp_handler.cc deleted file mode 100644 index c870ffa0228..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/p2p_star_pcp_handler.cc +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/p2p_star_pcp_handler.h" - -#include <vector> - -namespace location { -namespace nearby { -namespace connections { - -P2pStarPcpHandler::P2pStarPcpHandler( - Mediums& mediums, EndpointManager& endpoint_manager, - EndpointChannelManager& channel_manager, BwuManager& bwu_manager, - InjectedBluetoothDeviceStore& injected_bluetooth_device_store, Pcp pcp) - : P2pClusterPcpHandler(&mediums, &endpoint_manager, &channel_manager, - &bwu_manager, injected_bluetooth_device_store, pcp) { -} - -std::vector<proto::connections::Medium> -P2pStarPcpHandler::GetConnectionMediumsByPriority() { - std::vector<proto::connections::Medium> mediums; - if (mediums_->GetWifiLan().IsAvailable()) { - mediums.push_back(proto::connections::WIFI_LAN); - } - if (mediums_->GetWebRtc().IsAvailable()) { - mediums.push_back(proto::connections::WEB_RTC); - } - if (mediums_->GetBluetoothClassic().IsAvailable()) { - mediums.push_back(proto::connections::BLUETOOTH); - } - if (mediums_->GetBle().IsAvailable()) { - mediums.push_back(proto::connections::BLE); - } - return mediums; -} - -proto::connections::Medium P2pStarPcpHandler::GetDefaultUpgradeMedium() { - return proto::connections::Medium::WIFI_HOTSPOT; -} - -bool P2pStarPcpHandler::CanSendOutgoingConnection(ClientProxy* client) const { - // For star, we can only send an outgoing connection while we have no other - // connections. - return !this->HasOutgoingConnections(client) && - !this->HasIncomingConnections(client); -} - -bool P2pStarPcpHandler::CanReceiveIncomingConnection( - ClientProxy* client) const { - // For star, we can only receive an incoming connection if we've sent no - // outgoing connections. - return !this->HasOutgoingConnections(client); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/p2p_star_pcp_handler.h b/chromium/third_party/nearby/src/cpp/core/internal/p2p_star_pcp_handler.h deleted file mode 100644 index cc01c717c12..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/p2p_star_pcp_handler.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_P2P_STAR_PCP_HANDLER_H_ -#define CORE_INTERNAL_P2P_STAR_PCP_HANDLER_H_ - -#include <vector> - -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel_manager.h" -#include "core/internal/endpoint_manager.h" -#include "core/internal/p2p_cluster_pcp_handler.h" -#include "core/internal/pcp.h" -#include "core/strategy.h" - -namespace location { -namespace nearby { -namespace connections { - -// Concrete implementation of the PcpHandler for the P2P_STAR PCP. This Pcp is -// for mediums that have one server with (potentially) many clients; all mediums -// in P2P_CLUSTER are valid for P2P_STAR, but not all mediums in P2P_STAR are -// valid for P2P_CLUSTER. -// -// Currently, this implementation advertises/discovers over Bluetooth -// and connects over Bluetooth. -class P2pStarPcpHandler : public P2pClusterPcpHandler { - public: - P2pStarPcpHandler( - Mediums& mediums, EndpointManager& endpoint_manager, - EndpointChannelManager& channel_manager, BwuManager& bwu_manager, - InjectedBluetoothDeviceStore& injected_bluetooth_device_store, - Pcp pcp = Pcp::kP2pStar); - - protected: - std::vector<proto::connections::Medium> GetConnectionMediumsByPriority() - override; - proto::connections::Medium GetDefaultUpgradeMedium() override; - - bool CanSendOutgoingConnection(ClientProxy* client) const override; - bool CanReceiveIncomingConnection(ClientProxy* client) const override; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_P2P_STAR_PCP_HANDLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/payload_manager.cc b/chromium/third_party/nearby/src/cpp/core/internal/payload_manager.cc deleted file mode 100644 index 403be7e0445..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/payload_manager.cc +++ /dev/null @@ -1,1318 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/payload_manager.h" - -#include <algorithm> -#include <limits> -#include <memory> -#include <string> -#include <utility> - -#include "absl/memory/memory.h" -#include "absl/strings/str_cat.h" -#include "absl/time/time.h" -#include "core/internal/internal_payload_factory.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/mutex_lock.h" -#include "platform/public/single_thread_executor.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { - -// C++14 requires to declare this. -// TODO(apolyudov): remove when migration to c++17 is possible. -constexpr const absl::Duration PayloadManager::kWaitCloseTimeout; - -bool PayloadManager::SendPayloadLoop( - ClientProxy* client, PendingPayload& pending_payload, - PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t& next_chunk_offset, size_t resume_offset) { - // in lieu of structured binding: - auto pair = GetAvailableAndUnavailableEndpoints(pending_payload); - const EndpointIds& available_endpoint_ids = - EndpointsToEndpointIds(pair.first); - const Endpoints& unavailable_endpoints = pair.second; - - // First, handle any non-available endpoints. - for (const auto& endpoint : unavailable_endpoints) { - HandleFinishedOutgoingPayload( - client, {endpoint->id}, payload_header, next_chunk_offset, - EndpointInfoStatusToPayloadStatus(endpoint->status.Get())); - } - - // Update the still-active recipients of this payload. - if (available_endpoint_ids.empty()) { - NEARBY_LOGS(INFO) - << "PayloadManager short-circuiting payload_id=" - << pending_payload.GetInternalPayload()->GetId() << " after sending " - << next_chunk_offset - << " bytes because none of the endpoints are available anymore."; - return false; - } - - // Check if the payload has been cancelled by the client and, if so, - // notify the remaining recipients. - if (pending_payload.IsLocallyCanceled()) { - NEARBY_LOGS(INFO) << "Aborting send of payload_id=" - << pending_payload.GetInternalPayload()->GetId() - << " at offset " << next_chunk_offset - << " since it is marked canceled."; - HandleFinishedOutgoingPayload( - client, available_endpoint_ids, payload_header, next_chunk_offset, - proto::connections::PayloadStatus::LOCAL_CANCELLATION); - return false; - } - - // Update the current offsets for all endpoints still active for this - // payload. For the sake of accuracy, we update the pending payload here - // because it's after all payload terminating events are handled, but - // right before we actually start detaching the next chunk. - if (next_chunk_offset == 0 && resume_offset > 0) { - ExceptionOr<size_t> real_offset = - pending_payload.GetInternalPayload()->SkipToOffset(resume_offset); - if (!real_offset.ok()) { - // Stop sending since it may cause remote file merging failed. - NEARBY_LOGS(WARNING) << "PayloadManager failed to skip offset " - << resume_offset << " on payload_id " - << pending_payload.GetInternalPayload()->GetId(); - HandleFinishedOutgoingPayload( - client, available_endpoint_ids, payload_header, next_chunk_offset, - proto::connections::PayloadStatus::LOCAL_ERROR); - return false; - } - NEARBY_LOGS(VERBOSE) << "PayloadManager successfully skipped " - << real_offset.GetResult() << " bytes on payload_id " - << pending_payload.GetInternalPayload()->GetId(); - next_chunk_offset = real_offset.GetResult(); - } - for (const auto& endpoint_id : available_endpoint_ids) { - pending_payload.SetOffsetForEndpoint(endpoint_id, next_chunk_offset); - } - - // This will block if there is no data to transfer. - // It will resume when new data arrives, or if Close() is called. - int chunk_size = GetOptimalChunkSize(available_endpoint_ids); - ByteArray next_chunk = - pending_payload.GetInternalPayload()->DetachNextChunk(chunk_size); - if (shutdown_.Get()) return false; - // Save chunk size. We'll need it after we move next_chunk. - auto next_chunk_size = next_chunk.size(); - if (!next_chunk_size && - pending_payload.GetInternalPayload()->GetTotalSize() > 0 && - pending_payload.GetInternalPayload()->GetTotalSize() < - next_chunk_offset) { - NEARBY_LOGS(INFO) << "Payload xfer failed: payload_id=" - << pending_payload.GetInternalPayload()->GetId(); - HandleFinishedOutgoingPayload( - client, available_endpoint_ids, payload_header, next_chunk_offset, - proto::connections::PayloadStatus::LOCAL_ERROR); - return false; - } - - // Only need to handle outgoing data chunk offset, because the offset will be - // used to decide if the received chunk is the initial payload chunk. - // In other cases, the offset should only be used in both side logs when error - // happened. - PayloadTransferFrame::PayloadChunk payload_chunk(CreatePayloadChunk( - next_chunk_offset - resume_offset, std::move(next_chunk))); - const EndpointIds& failed_endpoint_ids = endpoint_manager_->SendPayloadChunk( - payload_header, payload_chunk, available_endpoint_ids); - // Check whether at least one endpoint failed. - if (!failed_endpoint_ids.empty()) { - NEARBY_LOGS(INFO) << "Payload xfer: endpoints failed: payload_id=" - << payload_header.id() << "; endpoint_ids={" - << ToString(failed_endpoint_ids) << "}", - HandleFinishedOutgoingPayload( - client, failed_endpoint_ids, payload_header, next_chunk_offset, - proto::connections::PayloadStatus::ENDPOINT_IO_ERROR); - } - - // Check whether at least one endpoint succeeded -- if they all failed, - // we'll just go right back to the top of the loop and break out when - // availableEndpointIds is re-synced and found to be empty at that point. - if (failed_endpoint_ids.size() < available_endpoint_ids.size()) { - for (const auto& endpoint_id : available_endpoint_ids) { - if (std::find(failed_endpoint_ids.begin(), failed_endpoint_ids.end(), - endpoint_id) == failed_endpoint_ids.end()) { - HandleSuccessfulOutgoingChunk( - client, endpoint_id, payload_header, payload_chunk.flags(), - payload_chunk.offset(), payload_chunk.body().size()); - } - } - NEARBY_LOGS(VERBOSE) << "PayloadManager done sending chunk at offset " - << next_chunk_offset << " of payload_id=" - << pending_payload.GetInternalPayload()->GetId(); - next_chunk_offset += next_chunk_size; - - if (!next_chunk_size) { - // That was the last chunk, we're outta here. - NEARBY_LOGS(INFO) << "Payload xfer done: payload_id=" - << pending_payload.GetInternalPayload()->GetId() - << "; size=" << next_chunk_offset; - return false; - } - } - - return true; -} - -std::pair<PayloadManager::Endpoints, PayloadManager::Endpoints> -PayloadManager::GetAvailableAndUnavailableEndpoints( - const PendingPayload& pending_payload) { - Endpoints available; - Endpoints unavailable; - for (auto* endpoint_info : pending_payload.GetEndpoints()) { - if (endpoint_info->status.Get() == - PayloadManager::EndpointInfo::Status::kAvailable) { - available.push_back(endpoint_info); - } else { - unavailable.push_back(endpoint_info); - } - } - return std::make_pair(std::move(available), std::move(unavailable)); -} - -PayloadManager::EndpointIds PayloadManager::EndpointsToEndpointIds( - const Endpoints& endpoints) { - EndpointIds endpoint_ids; - endpoint_ids.reserve(endpoints.size()); - for (const auto& item : endpoints) { - if (item) { - endpoint_ids.emplace_back(item->id); - } - } - return endpoint_ids; -} - -std::string PayloadManager::ToString(const Endpoints& endpoints) { - std::string endpoints_string = absl::StrCat(endpoints.size(), ": "); - bool first = true; - for (const auto& item : endpoints) { - if (first) { - absl::StrAppend(&endpoints_string, item->id); - first = false; - } else { - absl::StrAppend(&endpoints_string, ", ", item->id); - } - } - return endpoints_string; -} - -std::string PayloadManager::ToString(const EndpointIds& endpoint_ids) { - std::string endpoints_string = absl::StrCat(endpoint_ids.size(), ": "); - bool first = true; - for (const auto& id : endpoint_ids) { - if (first) { - absl::StrAppend(&endpoints_string, id); - first = false; - } else { - absl::StrAppend(&endpoints_string, ", ", id); - } - } - return endpoints_string; -} - -std::string PayloadManager::ToString(Payload::Type type) { - switch (type) { - case Payload::Type::kBytes: - return std::string("Bytes"); - case Payload::Type::kStream: - return std::string("Stream"); - case Payload::Type::kFile: - return std::string("File"); - case Payload::Type::kUnknown: - return std::string("Unknown"); - } -} - -std::string PayloadManager::ToString(EndpointInfo::Status status) { - switch (status) { - case EndpointInfo::Status::kAvailable: - return std::string("Available"); - case EndpointInfo::Status::kCanceled: - return std::string("Cancelled"); - case EndpointInfo::Status::kError: - return std::string("Error"); - case EndpointInfo::Status::kUnknown: - return std::string("Unknown"); - } -} - -// Creates and starts tracking a PendingPayload for this Payload. -Payload::Id PayloadManager::CreateOutgoingPayload( - Payload payload, const EndpointIds& endpoint_ids) { - auto internal_payload{CreateOutgoingInternalPayload(std::move(payload))}; - Payload::Id payload_id = internal_payload->GetId(); - NEARBY_LOGS(INFO) << "CreateOutgoingPayload: payload_id=" << payload_id; - MutexLock lock(&mutex_); - pending_payloads_.StartTrackingPayload( - payload_id, absl::make_unique<PendingPayload>(std::move(internal_payload), - endpoint_ids, - /*is_incoming=*/false)); - - return payload_id; -} - -PayloadManager::PayloadManager(EndpointManager& endpoint_manager) - : endpoint_manager_(&endpoint_manager) { - endpoint_manager_->RegisterFrameProcessor(V1Frame::PAYLOAD_TRANSFER, this); -} - -void PayloadManager::CancelAllPayloads() { - NEARBY_LOG(INFO, "PayloadManager: canceling payloads; self=%p", this); - { - MutexLock lock(&mutex_); - int pending_outgoing_payloads = 0; - for (const auto& pending_id : pending_payloads_.GetAllPayloads()) { - auto* pending = pending_payloads_.GetPayload(pending_id); - if (!pending->IsIncoming()) pending_outgoing_payloads++; - pending->MarkLocallyCanceled(); - pending->Close(); // To unblock the sender thread, if there is no data. - } - if (pending_outgoing_payloads) { - shutdown_barrier_ = - absl::make_unique<CountDownLatch>(pending_outgoing_payloads); - } - } - - if (shutdown_barrier_) { - NEARBY_LOG(INFO, - "PayloadManager: waiting for pending outgoing payloads; self=%p", - this); - shutdown_barrier_->Await(); - } -} - -void PayloadManager::DisconnectFromEndpointManager() { - if (shutdown_.Set(true)) return; - // Unregister ourselves from the FrameProcessors. - endpoint_manager_->UnregisterFrameProcessor(V1Frame::PAYLOAD_TRANSFER, this); -} - -PayloadManager::~PayloadManager() { - NEARBY_LOG(INFO, "PayloadManager: going down; self=%p", this); - DisconnectFromEndpointManager(); - CancelAllPayloads(); - NEARBY_LOG(INFO, "PayloadManager: turn down payload executors; self=%p", - this); - bytes_payload_executor_.Shutdown(); - stream_payload_executor_.Shutdown(); - file_payload_executor_.Shutdown(); - - CountDownLatch stop_latch(1); - // Clear our tracked pending payloads. - RunOnStatusUpdateThread( - "~payload-manager", - [this, &stop_latch]() RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { - NEARBY_LOG(INFO, "PayloadManager: stop tracking payloads; self=%p", - this); - MutexLock lock(&mutex_); - for (const auto& pending_id : pending_payloads_.GetAllPayloads()) { - pending_payloads_.StopTrackingPayload(pending_id); - } - stop_latch.CountDown(); - }); - stop_latch.Await(); - - NEARBY_LOG(INFO, "PayloadManager: turn down notification executor; self=%p", - this); - // Stop all the ongoing Runnables (as gracefully as possible). - payload_status_update_executor_.Shutdown(); - - NEARBY_LOG(INFO, "PayloadManager: down; self=%p", this); -} - -bool PayloadManager::NotifyShutdown() { - MutexLock lock(&mutex_); - if (!shutdown_.Get()) return false; - if (!shutdown_barrier_) return false; - NEARBY_LOG(INFO, "PayloadManager [shutdown mode]"); - shutdown_barrier_->CountDown(); - return true; -} - -void PayloadManager::SendPayload(ClientProxy* client, - const EndpointIds& endpoint_ids, - Payload payload) { - if (shutdown_.Get()) return; - NEARBY_LOG(INFO, "SendPayload: endpoint_ids={%s}", - ToString(endpoint_ids).c_str()); - // Before transfer to internal payload, retrieves the Payload size for - // analytics. - std::int64_t payload_total_size; - switch (payload.GetType()) { - case connections::Payload::Type::kBytes: - payload_total_size = payload.AsBytes().size(); - break; - case connections::Payload::Type::kFile: - payload_total_size = payload.AsFile()->GetTotalSize(); - break; - case connections::Payload::Type::kStream: - case connections::Payload::Type::kUnknown: - payload_total_size = -1; - break; - } - - auto executor = GetOutgoingPayloadExecutor(payload.GetType()); - // The |executor| will be null if the payload is of a type we cannot work - // with. This should never be reached since the ServiceControllerRouter has - // already checked whether or not we can work with this Payload type. - if (!executor) { - RecordInvalidPayloadAnalytics(client, endpoint_ids, payload.GetId(), - payload.GetType(), payload.GetOffset(), - payload_total_size); - NEARBY_LOGS(INFO) - << "PayloadManager failed to determine the right executor for " - "outgoing payload_id=" - << payload.GetId() << ", payload_type=" << ToString(payload.GetType()); - return; - } - - // Each payload is sent in FCFS order within each Payload type, blocking any - // other payload of the same type from even starting until this one is - // completely done with. If we ever want to provide isolation across - // ClientProxy objects this will need to be significantly re-architected. - Payload::Type payload_type = payload.GetType(); - size_t resume_offset = - FeatureFlags::GetInstance().GetFlags().enable_send_payload_offset - ? payload.GetOffset() - : 0; - - Payload::Id payload_id = - CreateOutgoingPayload(std::move(payload), endpoint_ids); - executor->Execute( - "send-payload", [this, client, endpoint_ids, payload_id, payload_type, - resume_offset, payload_total_size]() { - if (shutdown_.Get()) return; - PendingPayload* pending_payload = GetPayload(payload_id); - if (!pending_payload) { - RecordInvalidPayloadAnalytics(client, endpoint_ids, payload_id, - payload_type, resume_offset, - payload_total_size); - NEARBY_LOGS(INFO) - << "PayloadManager failed to create InternalPayload for outgoing " - "payload_id=" - << payload_id << ", payload_type=" << ToString(payload_type) - << ", aborting sendPayload()."; - return; - } - auto* internal_payload = pending_payload->GetInternalPayload(); - if (!internal_payload) return; - - RecordPayloadStartedAnalytics(client, endpoint_ids, payload_id, - payload_type, resume_offset, - internal_payload->GetTotalSize()); - - PayloadTransferFrame::PayloadHeader payload_header{ - CreatePayloadHeader(*internal_payload, resume_offset)}; - bool should_continue = true; - std::int64_t next_chunk_offset = 0; - while (should_continue && !shutdown_.Get()) { - should_continue = - SendPayloadLoop(client, *pending_payload, payload_header, - next_chunk_offset, resume_offset); - } - RunOnStatusUpdateThread("destroy-payload", - [this, payload_id]() - RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { - DestroyPendingPayload(payload_id); - }); - }); - NEARBY_LOGS(INFO) << "PayloadManager: xfer scheduled: self=" << this - << "; payload_id=" << payload_id - << ", payload_type=" << ToString(payload_type); -} - -PayloadManager::PendingPayload* PayloadManager::GetPayload( - Payload::Id payload_id) const { - MutexLock lock(&mutex_); - return pending_payloads_.GetPayload(payload_id); -} - -Status PayloadManager::CancelPayload(ClientProxy* client, - Payload::Id payload_id) { - PendingPayload* canceled_payload = GetPayload(payload_id); - if (!canceled_payload) { - NEARBY_LOGS(INFO) << "Client requested cancel for unknown payload_id=" - << payload_id << ", ignoring."; - return {Status::kPayloadUnknown}; - } - - // Mark the payload as canceled. - canceled_payload->MarkLocallyCanceled(); - NEARBY_LOGS(INFO) << "Cancelling " - << (canceled_payload->IsIncoming() ? "incoming" - : "outgoing") - << " payload_id=" << payload_id << " at request of client."; - - // Return SUCCESS immediately. Remaining cleanup and updates will be sent - // in SendPayload() or OnIncomingFrame() - return {Status::kSuccess}; -} - -// @EndpointManagerDataPool -void PayloadManager::OnIncomingFrame( - OfflineFrame& offline_frame, const std::string& from_endpoint_id, - ClientProxy* to_client, proto::connections::Medium current_medium) { - PayloadTransferFrame& frame = - *offline_frame.mutable_v1()->mutable_payload_transfer(); - - switch (frame.packet_type()) { - case PayloadTransferFrame::CONTROL: - NEARBY_LOGS(INFO) << "PayloadManager::OnIncomingFrame [CONTROL]: self=" - << this << "; endpoint_id=" << from_endpoint_id; - ProcessControlPacket(to_client, from_endpoint_id, frame); - break; - case PayloadTransferFrame::DATA: - ProcessDataPacket(to_client, from_endpoint_id, frame); - break; - default: - NEARBY_LOGS(WARNING) - << "PayloadManager: invalid frame; remote endpoint: self=" << this - << "; endpoint_id=" << from_endpoint_id; - break; - } -} - -void PayloadManager::OnEndpointDisconnect(ClientProxy* client, - const std::string& endpoint_id, - CountDownLatch barrier) { - if (shutdown_.Get()) { - barrier.CountDown(); - return; - } - RunOnStatusUpdateThread( - "payload-manager-on-disconnect", - [this, client, endpoint_id, barrier]() - RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() mutable { - // Iterate through all our payloads and look for payloads associated - // with this endpoint. - MutexLock lock(&mutex_); - for (const auto& payload_id : pending_payloads_.GetAllPayloads()) { - auto* pending_payload = pending_payloads_.GetPayload(payload_id); - if (!pending_payload) continue; - auto endpoint_info = pending_payload->GetEndpoint(endpoint_id); - if (!endpoint_info) continue; - std::int64_t endpoint_offset = endpoint_info->offset; - // Stop tracking the endpoint for this payload. - pending_payload->RemoveEndpoints({endpoint_id}); - // |endpoint_info| is longer valid after calling RemoveEndpoints. - endpoint_info = nullptr; - - std::int64_t payload_total_size = - pending_payload->GetInternalPayload()->GetTotalSize(); - - // If no endpoints are left for this payload, close it. - if (pending_payload->GetEndpoints().empty()) { - pending_payload->Close(); - } - - // Create the payload transfer update. - PayloadProgressInfo update{payload_id, - PayloadProgressInfo::Status::kFailure, - payload_total_size, endpoint_offset}; - - // Send a client notification of a payload transfer failure. - client->OnPayloadProgress(endpoint_id, update); - - if (pending_payload->IsIncoming()) { - client->GetAnalyticsRecorder().OnIncomingPayloadDone( - endpoint_id, pending_payload->GetId(), - proto::connections::ENDPOINT_IO_ERROR); - } else { - client->GetAnalyticsRecorder().OnOutgoingPayloadDone( - endpoint_id, pending_payload->GetId(), - proto::connections::ENDPOINT_IO_ERROR); - } - } - - barrier.CountDown(); - }); -} - -proto::connections::PayloadStatus -PayloadManager::EndpointInfoStatusToPayloadStatus(EndpointInfo::Status status) { - switch (status) { - case EndpointInfo::Status::kCanceled: - return proto::connections::PayloadStatus::REMOTE_CANCELLATION; - case EndpointInfo::Status::kError: - return proto::connections::PayloadStatus::REMOTE_ERROR; - case EndpointInfo::Status::kAvailable: - return proto::connections::PayloadStatus::SUCCESS; - default: - NEARBY_LOGS(INFO) << "PayloadManager: Unknown PayloadStatus"; - return proto::connections::PayloadStatus::UNKNOWN_PAYLOAD_STATUS; - } -} - -proto::connections::PayloadStatus -PayloadManager::ControlMessageEventToPayloadStatus( - PayloadTransferFrame::ControlMessage::EventType event) { - switch (event) { - case PayloadTransferFrame::ControlMessage::PAYLOAD_ERROR: - return proto::connections::PayloadStatus::REMOTE_ERROR; - case PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED: - return proto::connections::PayloadStatus::REMOTE_CANCELLATION; - default: - NEARBY_LOG(INFO, "PayloadManager: unknown event=%d", event); - return proto::connections::PayloadStatus::UNKNOWN_PAYLOAD_STATUS; - } -} - -PayloadProgressInfo::Status PayloadManager::PayloadStatusToTransferUpdateStatus( - proto::connections::PayloadStatus status) { - switch (status) { - case proto::connections::LOCAL_CANCELLATION: - case proto::connections::REMOTE_CANCELLATION: - return PayloadProgressInfo::Status::kCanceled; - case proto::connections::SUCCESS: - return PayloadProgressInfo::Status::kSuccess; - default: - return PayloadProgressInfo::Status::kFailure; - } -} - -SingleThreadExecutor* PayloadManager::GetOutgoingPayloadExecutor( - Payload::Type payload_type) { - switch (payload_type) { - case Payload::Type::kBytes: - return &bytes_payload_executor_; - case Payload::Type::kFile: - return &file_payload_executor_; - case Payload::Type::kStream: - return &stream_payload_executor_; - default: - return nullptr; - } -} - -int PayloadManager::GetOptimalChunkSize(EndpointIds endpoint_ids) { - int minChunkSize = std::numeric_limits<int>::max(); - for (const auto& endpoint_id : endpoint_ids) { - minChunkSize = std::min( - minChunkSize, endpoint_manager_->GetMaxTransmitPacketSize(endpoint_id)); - } - return minChunkSize; -} - -PayloadTransferFrame::PayloadHeader PayloadManager::CreatePayloadHeader( - const InternalPayload& internal_payload, size_t offset) { - PayloadTransferFrame::PayloadHeader payload_header; - size_t payload_size = internal_payload.GetTotalSize(); - - payload_header.set_id(internal_payload.GetId()); - payload_header.set_type(internal_payload.GetType()); - payload_header.set_total_size(payload_size == - InternalPayload::kIndeterminateSize - ? InternalPayload::kIndeterminateSize - : payload_size - offset); - - return payload_header; -} - -PayloadTransferFrame::PayloadChunk PayloadManager::CreatePayloadChunk( - std::int64_t payload_chunk_offset, ByteArray payload_chunk_body) { - PayloadTransferFrame::PayloadChunk payload_chunk; - - payload_chunk.set_offset(payload_chunk_offset); - payload_chunk.set_flags(0); - if (!payload_chunk_body.Empty()) { - payload_chunk.set_body(std::string(std::move(payload_chunk_body))); - } else { - payload_chunk.set_flags(payload_chunk.flags() | - PayloadTransferFrame::PayloadChunk::LAST_CHUNK); - } - - return payload_chunk; -} - -PayloadManager::PendingPayload* PayloadManager::CreateIncomingPayload( - const PayloadTransferFrame& frame, const std::string& endpoint_id) { - auto internal_payload = CreateIncomingInternalPayload(frame); - if (!internal_payload) { - return nullptr; - } - - Payload::Id payload_id = internal_payload->GetId(); - NEARBY_LOGS(INFO) << "CreateIncomingPayload: payload_id=" << payload_id; - MutexLock lock(&mutex_); - pending_payloads_.StartTrackingPayload( - payload_id, - absl::make_unique<PendingPayload>(std::move(internal_payload), - EndpointIds{endpoint_id}, true)); - - return pending_payloads_.GetPayload(payload_id); -} - -void PayloadManager::SendClientCallbacksForFinishedOutgoingPayload( - ClientProxy* client, const EndpointIds& finished_endpoint_ids, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t num_bytes_successfully_transferred, - proto::connections::PayloadStatus status) { - RunOnStatusUpdateThread( - "outgoing-payload-callbacks", - [this, client, finished_endpoint_ids, payload_header, - num_bytes_successfully_transferred, - status]() RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { - // Make sure we're still tracking this payload. - PendingPayload* pending_payload = GetPayload(payload_header.id()); - if (!pending_payload) { - return; - } - - PayloadProgressInfo update{ - payload_header.id(), - PayloadManager::PayloadStatusToTransferUpdateStatus(status), - payload_header.total_size(), num_bytes_successfully_transferred}; - for (const auto& endpoint_id : finished_endpoint_ids) { - // Skip sending notifications if we have stopped tracking this - // endpoint. - if (!pending_payload->GetEndpoint(endpoint_id)) { - continue; - } - - // Notify the client. - client->OnPayloadProgress(endpoint_id, update); - - // Mark this payload as done for analytics. - client->GetAnalyticsRecorder().OnOutgoingPayloadDone( - endpoint_id, payload_header.id(), status); - } - - // Remove these endpoints from our tracking list for this payload. - pending_payload->RemoveEndpoints(finished_endpoint_ids); - - // Close the payload if no endpoints remain. - if (pending_payload->GetEndpoints().empty()) { - pending_payload->Close(); - } - }); -} - -void PayloadManager::SendClientCallbacksForFinishedIncomingPayload( - ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t offset_bytes, proto::connections::PayloadStatus status) { - RunOnStatusUpdateThread( - "incoming-payload-callbacks", - [this, client, endpoint_id, payload_header, offset_bytes, - status]() RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { - // Make sure we're still tracking this payload. - PendingPayload* pending_payload = GetPayload(payload_header.id()); - if (!pending_payload) { - return; - } - - // Unless we never started tracking this payload (meaning we failed to - // even create the InternalPayload), notify the client (and close it). - PayloadProgressInfo update{ - payload_header.id(), - PayloadManager::PayloadStatusToTransferUpdateStatus(status), - payload_header.total_size(), offset_bytes}; - NotifyClientOfIncomingPayloadProgressInfo(client, endpoint_id, update); - DestroyPendingPayload(payload_header.id()); - - // Analyze - client->GetAnalyticsRecorder().OnIncomingPayloadDone( - endpoint_id, payload_header.id(), status); - }); -} - -void PayloadManager::SendControlMessage( - const EndpointIds& endpoint_ids, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t num_bytes_successfully_transferred, - PayloadTransferFrame::ControlMessage::EventType event_type) { - PayloadTransferFrame::ControlMessage control_message; - control_message.set_event(event_type); - control_message.set_offset(num_bytes_successfully_transferred); - - endpoint_manager_->SendControlMessage(payload_header, control_message, - endpoint_ids); -} - -void PayloadManager::HandleFinishedOutgoingPayload( - ClientProxy* client, const EndpointIds& finished_endpoint_ids, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t num_bytes_successfully_transferred, - proto::connections::PayloadStatus status) { - // This call will destroy a pending payload. - SendClientCallbacksForFinishedOutgoingPayload( - client, finished_endpoint_ids, payload_header, - num_bytes_successfully_transferred, status); - - switch (status) { - case proto::connections::PayloadStatus::LOCAL_ERROR: - SendControlMessage(finished_endpoint_ids, payload_header, - num_bytes_successfully_transferred, - PayloadTransferFrame::ControlMessage::PAYLOAD_ERROR); - break; - case proto::connections::PayloadStatus::LOCAL_CANCELLATION: - NEARBY_LOGS(INFO) - << "Sending PAYLOAD_CANCEL to receiver side; payload_id=" - << payload_header.id(); - SendControlMessage( - finished_endpoint_ids, payload_header, - num_bytes_successfully_transferred, - PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED); - break; - case proto::connections::PayloadStatus::ENDPOINT_IO_ERROR: - // Unregister these endpoints, since we had an IO error on the physical - // connection. - for (const auto& endpoint_id : finished_endpoint_ids) { - endpoint_manager_->DiscardEndpoint(client, endpoint_id); - } - break; - case proto::connections::PayloadStatus::REMOTE_ERROR: - case proto::connections::PayloadStatus::REMOTE_CANCELLATION: - // No special handling needed for these. - break; - default: - NEARBY_LOGS(INFO) - << "PayloadManager: Unhandled finished outgoing payload with " - "payload_status=" - << status; - break; - } -} - -void PayloadManager::HandleFinishedIncomingPayload( - ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t offset_bytes, proto::connections::PayloadStatus status) { - SendClientCallbacksForFinishedIncomingPayload( - client, endpoint_id, payload_header, offset_bytes, status); - - switch (status) { - case proto::connections::PayloadStatus::LOCAL_ERROR: - SendControlMessage({endpoint_id}, payload_header, offset_bytes, - PayloadTransferFrame::ControlMessage::PAYLOAD_ERROR); - break; - case proto::connections::PayloadStatus::LOCAL_CANCELLATION: - SendControlMessage( - {endpoint_id}, payload_header, offset_bytes, - PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED); - break; - default: - NEARBY_LOGS(INFO) << "Unhandled finished incoming payload_id=" - << payload_header.id() - << " with payload_status=" << status; - break; - } -} - -void PayloadManager::HandleSuccessfulOutgoingChunk( - ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int32_t payload_chunk_flags, std::int64_t payload_chunk_offset, - std::int64_t payload_chunk_body_size) { - RunOnStatusUpdateThread( - "outgoing-chunk-success", - [this, client, endpoint_id, payload_header, payload_chunk_flags, - payload_chunk_offset, - payload_chunk_body_size]() RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { - // Make sure we're still tracking this payload and its associated - // endpoint. - PendingPayload* pending_payload = GetPayload(payload_header.id()); - if (!pending_payload || !pending_payload->GetEndpoint(endpoint_id)) { - NEARBY_LOGS(INFO) - << "HandleSuccessfulOutgoingChunk: endpoint not found: " - "endpoint_id=" - << endpoint_id; - return; - } - - bool is_last_chunk = - (payload_chunk_flags & - PayloadTransferFrame::PayloadChunk::LAST_CHUNK) != 0; - PayloadProgressInfo update{ - payload_header.id(), - is_last_chunk ? PayloadProgressInfo::Status::kSuccess - : PayloadProgressInfo::Status::kInProgress, - payload_header.total_size(), - is_last_chunk ? payload_chunk_offset - : payload_chunk_offset + payload_chunk_body_size}; - - // Notify the client. - client->OnPayloadProgress(endpoint_id, update); - - if (is_last_chunk) { - client->GetAnalyticsRecorder().OnOutgoingPayloadDone( - endpoint_id, payload_header.id(), proto::connections::SUCCESS); - - // Stop tracking this endpoint. - pending_payload->RemoveEndpoints({endpoint_id}); - - // Close the payload if no endpoints remain. - if (pending_payload->GetEndpoints().empty()) { - pending_payload->Close(); - } - } else { - client->GetAnalyticsRecorder().OnPayloadChunkSent( - endpoint_id, payload_header.id(), payload_chunk_body_size); - } - }); -} - -// @PayloadManagerStatusUpdateThread -void PayloadManager::DestroyPendingPayload(Payload::Id payload_id) { - bool is_incoming = false; - { - MutexLock lock(&mutex_); - auto pending = pending_payloads_.StopTrackingPayload(payload_id); - if (!pending) return; - is_incoming = pending->IsIncoming(); - const char* direction = is_incoming ? "incoming" : "outgoing"; - NEARBY_LOGS(INFO) << "PayloadManager: destroying " << direction - << " pending payload: self=" << this - << "; payload_id=" << payload_id; - pending->Close(); - pending.reset(); - } - if (!is_incoming) NotifyShutdown(); -} - -void PayloadManager::HandleSuccessfulIncomingChunk( - ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int32_t payload_chunk_flags, std::int64_t payload_chunk_offset, - std::int64_t payload_chunk_body_size) { - RunOnStatusUpdateThread( - "incoming-chunk-success", - [this, client, endpoint_id, payload_header, payload_chunk_flags, - payload_chunk_offset, - payload_chunk_body_size]() RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { - // Make sure we're still tracking this payload. - PendingPayload* pending_payload = GetPayload(payload_header.id()); - if (!pending_payload) { - return; - } - - bool is_last_chunk = - (payload_chunk_flags & - PayloadTransferFrame::PayloadChunk::LAST_CHUNK) != 0; - PayloadProgressInfo update{ - payload_header.id(), - is_last_chunk ? PayloadProgressInfo::Status::kSuccess - : PayloadProgressInfo::Status::kInProgress, - payload_header.total_size(), - is_last_chunk ? payload_chunk_offset - : payload_chunk_offset + payload_chunk_body_size}; - - // Notify the client of this update. - NotifyClientOfIncomingPayloadProgressInfo(client, endpoint_id, update); - - // Analyze the success. - if (is_last_chunk) { - client->GetAnalyticsRecorder().OnIncomingPayloadDone( - endpoint_id, payload_header.id(), proto::connections::SUCCESS); - } else { - client->GetAnalyticsRecorder().OnPayloadChunkReceived( - endpoint_id, payload_header.id(), payload_chunk_body_size); - } - }); -} - -// @EndpointManagerDataPool -void PayloadManager::ProcessDataPacket( - ClientProxy* to_client, const std::string& from_endpoint_id, - PayloadTransferFrame& payload_transfer_frame) { - PayloadTransferFrame::PayloadHeader& payload_header = - *payload_transfer_frame.mutable_payload_header(); - PayloadTransferFrame::PayloadChunk& payload_chunk = - *payload_transfer_frame.mutable_payload_chunk(); - NEARBY_LOGS(VERBOSE) << "PayloadManager got data OfflineFrame for payload_id=" - << payload_header.id() - << " from endpoint_id=" << from_endpoint_id - << " at offset " << payload_chunk.offset(); - - PendingPayload* pending_payload; - if (payload_chunk.offset() == 0) { - RunOnStatusUpdateThread( - "process-data-packet", [to_client, from_endpoint_id, payload_header, - this]() RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { - // This is the first chunk of a new incoming - // payload. Start the analysis. - to_client->GetAnalyticsRecorder().OnIncomingPayloadStarted( - from_endpoint_id, payload_header.id(), - FramePayloadTypeToPayloadType(payload_header.type()), - payload_header.total_size()); - }); - - pending_payload = - CreateIncomingPayload(payload_transfer_frame, from_endpoint_id); - if (!pending_payload) { - NEARBY_LOGS(WARNING) - << "PayloadManager failed to create InternalPayload from " - "PayloadTransferFrame with payload_id=" - << payload_header.id() << " and type " << payload_header.type() - << ", aborting receipt."; - // Send the error to the remote endpoint. - SendControlMessage({from_endpoint_id}, payload_header, - payload_chunk.offset(), - PayloadTransferFrame::ControlMessage::PAYLOAD_ERROR); - return; - } - - // Also, let the client know of this new incoming payload. - RunOnStatusUpdateThread( - "process-data-packet", - [to_client, from_endpoint_id, pending_payload]() - RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { - NEARBY_LOGS(INFO) - << "PayloadManager received new payload_id=" - << pending_payload->GetInternalPayload()->GetId() - << " from endpoint_id=" << from_endpoint_id; - to_client->OnPayload( - from_endpoint_id, - pending_payload->GetInternalPayload()->ReleasePayload()); - }); - } else { - pending_payload = GetPayload(payload_header.id()); - if (!pending_payload) { - NEARBY_LOGS(WARNING) << "ProcessDataPacket: [missing] endpoint_id=" - << from_endpoint_id - << "; payload_id=" << payload_header.id(); - return; - } - } - - if (pending_payload->IsLocallyCanceled()) { - // This incoming payload was canceled by the client. Drop this frame and do - // all the cleanup. See go/nc-cancel-payload - NEARBY_LOGS(INFO) << "ProcessDataPacket: [cancel] endpoint_id=" - << from_endpoint_id - << "; payload_id=" << pending_payload->GetId(); - HandleFinishedIncomingPayload( - to_client, from_endpoint_id, payload_header, payload_chunk.offset(), - proto::connections::PayloadStatus::LOCAL_CANCELLATION); - return; - } - - // Update the offset for this payload. An endpoint disconnection might occur - // from another thread and we would need to know the current offset to report - // back to the client. For the sake of accuracy, we update the pending payload - // here because it's after all payload terminating events are handled, but - // right before we actually start attaching the next chunk. - pending_payload->SetOffsetForEndpoint(from_endpoint_id, - payload_chunk.offset()); - - // Save size of packet before we move it. - std::int64_t payload_body_size = payload_chunk.body().size(); - if (pending_payload->GetInternalPayload() - ->AttachNextChunk(ByteArray(std::move(*payload_chunk.mutable_body()))) - .Raised()) { - NEARBY_LOGS(ERROR) << "ProcessDataPacket: [data: error] endpoint_id=" - << from_endpoint_id - << "; payload_id=" << pending_payload->GetId(); - HandleFinishedIncomingPayload( - to_client, from_endpoint_id, payload_header, payload_chunk.offset(), - proto::connections::PayloadStatus::LOCAL_ERROR); - return; - } - - HandleSuccessfulIncomingChunk(to_client, from_endpoint_id, payload_header, - payload_chunk.flags(), payload_chunk.offset(), - payload_body_size); -} - -// @EndpointManagerDataPool -void PayloadManager::ProcessControlPacket( - ClientProxy* to_client, const std::string& from_endpoint_id, - PayloadTransferFrame& payload_transfer_frame) { - const PayloadTransferFrame::PayloadHeader& payload_header = - payload_transfer_frame.payload_header(); - const PayloadTransferFrame::ControlMessage& control_message = - payload_transfer_frame.control_message(); - PendingPayload* pending_payload = GetPayload(payload_header.id()); - if (!pending_payload) { - NEARBY_LOGS(INFO) << "Got ControlMessage for unknown payload_id=" - << payload_header.id() - << ", ignoring: " << control_message.event(); - return; - } - - switch (control_message.event()) { - case PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED: - if (pending_payload->IsIncoming()) { - NEARBY_LOGS(INFO) << "Incoming PAYLOAD_CANCELED: from endpoint_id=" - << from_endpoint_id << "; self=" << this; - // No need to mark the pending payload as cancelled, since this is a - // remote cancellation for an incoming payload -- we handle everything - // inline here. - HandleFinishedIncomingPayload( - to_client, from_endpoint_id, payload_header, - control_message.offset(), - ControlMessageEventToPayloadStatus(control_message.event())); - } else { - NEARBY_LOGS(INFO) << "Outgoing PAYLOAD_CANCELED: from endpoint_id=" - << from_endpoint_id << "; self=" << this; - // Mark the payload as canceled *for this endpoint*. - pending_payload->SetEndpointStatusFromControlMessage(from_endpoint_id, - control_message); - } - NEARBY_LOGS(VERBOSE) - << "Marked " - << (pending_payload->IsIncoming() ? "incoming" : "outgoing") - << " payload_id=" << pending_payload->GetInternalPayload()->GetId() - << " as canceled at request of endpoint_id=" << from_endpoint_id; - break; - case PayloadTransferFrame::ControlMessage::PAYLOAD_ERROR: - if (pending_payload->IsIncoming()) { - HandleFinishedIncomingPayload( - to_client, from_endpoint_id, payload_header, - control_message.offset(), - ControlMessageEventToPayloadStatus(control_message.event())); - } else { - pending_payload->SetEndpointStatusFromControlMessage(from_endpoint_id, - control_message); - } - break; - default: - NEARBY_LOGS(INFO) << "Unhandled control message " - << control_message.event() << " for payload_id=" - << pending_payload->GetInternalPayload()->GetId(); - break; - } -} - -// @PayloadManagerStatusUpdateThread -void PayloadManager::NotifyClientOfIncomingPayloadProgressInfo( - ClientProxy* client, const std::string& endpoint_id, - const PayloadProgressInfo& payload_transfer_update) { - client->OnPayloadProgress(endpoint_id, payload_transfer_update); -} - -void PayloadManager::RecordPayloadStartedAnalytics( - ClientProxy* client, const EndpointIds& endpoint_ids, - std::int64_t payload_id, Payload::Type payload_type, std::int64_t offset, - std::int64_t total_size) { - client->GetAnalyticsRecorder().OnOutgoingPayloadStarted( - endpoint_ids, payload_id, payload_type, - total_size == -1 ? -1 : total_size - offset); -} - -void PayloadManager::RecordInvalidPayloadAnalytics( - ClientProxy* client, const EndpointIds& endpoint_ids, - std::int64_t payload_id, Payload::Type payload_type, std::int64_t offset, - std::int64_t total_size) { - RecordPayloadStartedAnalytics(client, endpoint_ids, payload_id, payload_type, - offset, total_size); - - for (const auto& endpoint_id : endpoint_ids) { - client->GetAnalyticsRecorder().OnOutgoingPayloadDone( - endpoint_id, payload_id, proto::connections::LOCAL_ERROR); - } -} - -Payload::Type PayloadManager::FramePayloadTypeToPayloadType( - PayloadTransferFrame::PayloadHeader::PayloadType type) { - switch (type) { - case PayloadTransferFrame_PayloadHeader_PayloadType_BYTES: - return connections::Payload::Type::kBytes; - case PayloadTransferFrame_PayloadHeader_PayloadType_FILE: - return connections::Payload::Type::kFile; - case PayloadTransferFrame_PayloadHeader_PayloadType_STREAM: - return connections::Payload::Type::kStream; - default: - return connections::Payload::Type::kUnknown; - } -} - -///////////////////////////////// EndpointInfo ///////////////////////////////// - -PayloadManager::EndpointInfo::Status -PayloadManager::EndpointInfo::ControlMessageEventToEndpointInfoStatus( - PayloadTransferFrame::ControlMessage::EventType event) { - switch (event) { - case PayloadTransferFrame::ControlMessage::PAYLOAD_ERROR: - return Status::kError; - case PayloadTransferFrame::ControlMessage::PAYLOAD_CANCELED: - return Status::kCanceled; - default: - NEARBY_LOGS(INFO) - << "Unknown EndpointInfo.Status for ControlMessage.EventType " - << event; - return Status::kUnknown; - } -} - -void PayloadManager::EndpointInfo::SetStatusFromControlMessage( - const PayloadTransferFrame::ControlMessage& control_message) { - status.Set(ControlMessageEventToEndpointInfoStatus(control_message.event())); - NEARBY_LOGS(VERBOSE) << "Marked endpoint " << id << " with status " - << ToString(status.Get()) - << " based on OOB ControlMessage"; -} - -//////////////////////////////// PendingPayload //////////////////////////////// - -PayloadManager::PendingPayload::PendingPayload( - std::unique_ptr<InternalPayload> internal_payload, - const EndpointIds& endpoint_ids, bool is_incoming) - : is_incoming_(is_incoming), - internal_payload_(std::move(internal_payload)) { - // Initially we mark all endpoints as available. - // Later on some may become canceled, some may experience data transfer - // failures. Any of these situations will cause endpoint to be marked as - // unavailable. - for (const auto& id : endpoint_ids) { - EndpointInfo endpoint_info{}; - endpoint_info.id = id; - endpoint_info.status.Set(EndpointInfo::Status::kAvailable); - - endpoints_.emplace(id, std::move(endpoint_info)); - } -} - -Payload::Id PayloadManager::PendingPayload::GetId() const { - return internal_payload_->GetId(); -} - -InternalPayload* PayloadManager::PendingPayload::GetInternalPayload() { - return internal_payload_.get(); -} - -bool PayloadManager::PendingPayload::IsLocallyCanceled() const { - return is_locally_canceled_.Get(); -} - -void PayloadManager::PendingPayload::MarkLocallyCanceled() { - is_locally_canceled_.Set(true); -} - -bool PayloadManager::PendingPayload::IsIncoming() const { return is_incoming_; } - -std::vector<const PayloadManager::EndpointInfo*> -PayloadManager::PendingPayload::GetEndpoints() const { - MutexLock lock(&mutex_); - - std::vector<const EndpointInfo*> result; - for (const auto& item : endpoints_) { - result.push_back(&item.second); - } - return result; -} - -PayloadManager::EndpointInfo* PayloadManager::PendingPayload::GetEndpoint( - const std::string& endpoint_id) { - MutexLock lock(&mutex_); - - auto it = endpoints_.find(endpoint_id); - if (it == endpoints_.end()) { - return {}; - } - - return &it->second; -} - -void PayloadManager::PendingPayload::RemoveEndpoints( - const EndpointIds& endpoint_ids) { - MutexLock lock(&mutex_); - - for (const auto& id : endpoint_ids) { - endpoints_.erase(id); - } -} - -void PayloadManager::PendingPayload::SetEndpointStatusFromControlMessage( - const std::string& endpoint_id, - const PayloadTransferFrame::ControlMessage& control_message) { - MutexLock lock(&mutex_); - - auto item = endpoints_.find(endpoint_id); - if (item != endpoints_.end()) { - item->second.SetStatusFromControlMessage(control_message); - } -} - -void PayloadManager::PendingPayload::SetOffsetForEndpoint( - const std::string& endpoint_id, std::int64_t offset) { - MutexLock lock(&mutex_); - - auto item = endpoints_.find(endpoint_id); - if (item != endpoints_.end()) { - item->second.offset = offset; - } -} - -void PayloadManager::PendingPayload::Close() { - if (internal_payload_) internal_payload_->Close(); - close_event_.CountDown(); -} - -bool PayloadManager::PendingPayload::WaitForClose() { - return close_event_.Await(kWaitCloseTimeout).result(); -} - -bool PayloadManager::PendingPayload::IsClosed() { - return close_event_.Await(absl::ZeroDuration()).result(); -} - -void PayloadManager::RunOnStatusUpdateThread(const std::string& name, - std::function<void()> runnable) { - payload_status_update_executor_.Execute(name, std::move(runnable)); -} - -/////////////////////////////// PendingPayloads /////////////////////////////// - -void PayloadManager::PendingPayloads::StartTrackingPayload( - Payload::Id payload_id, std::unique_ptr<PendingPayload> pending_payload) { - MutexLock lock(&mutex_); - - // If the |payload_id| is being re-used, always prefer the newer payload. - auto it = pending_payloads_.find(payload_id); - if (it != pending_payloads_.end()) { - pending_payloads_.erase(payload_id); - } - auto pair = pending_payloads_.emplace(payload_id, std::move(pending_payload)); - NEARBY_LOGS(INFO) << "StartTrackingPayload: payload_id=" << payload_id - << "; inserted=" << pair.second; -} - -std::unique_ptr<PayloadManager::PendingPayload> -PayloadManager::PendingPayloads::StopTrackingPayload(Payload::Id payload_id) { - MutexLock lock(&mutex_); - - auto it = pending_payloads_.find(payload_id); - if (it == pending_payloads_.end()) return {}; - - auto item = pending_payloads_.extract(it); - return std::move(item.mapped()); -} - -PayloadManager::PendingPayload* PayloadManager::PendingPayloads::GetPayload( - Payload::Id payload_id) const { - MutexLock lock(&mutex_); - - auto item = pending_payloads_.find(payload_id); - return item != pending_payloads_.end() ? item->second.get() : nullptr; -} - -std::vector<Payload::Id> PayloadManager::PendingPayloads::GetAllPayloads() { - MutexLock lock(&mutex_); - - std::vector<Payload::Id> result; - for (const auto& item : pending_payloads_) { - result.push_back(item.first); - } - return result; -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/payload_manager.h b/chromium/third_party/nearby/src/cpp/core/internal/payload_manager.h deleted file mode 100644 index 4e605ab864f..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/payload_manager.h +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_PAYLOAD_MANAGER_H_ -#define CORE_INTERNAL_PAYLOAD_MANAGER_H_ - -#include <cstdint> -#include <memory> -#include <string> -#include <vector> - -#include "absl/container/flat_hash_map.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_manager.h" -#include "core/internal/internal_payload.h" -#include "core/listeners.h" -#include "core/payload.h" -#include "core/status.h" -#include "platform/base/byte_array.h" -#include "platform/public/atomic_boolean.h" -#include "platform/public/atomic_reference.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/mutex.h" - -namespace location { -namespace nearby { -namespace connections { - -// Annotations for methods that need to run on PayloadStatusUpdateThread. -// Use only in PayloadManager -#define RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() \ - ABSL_EXCLUSIVE_LOCKS_REQUIRED(payload_status_update_executor_) - -class PayloadManager : public EndpointManager::FrameProcessor { - public: - using EndpointIds = std::vector<std::string>; - constexpr static const absl::Duration kWaitCloseTimeout = - absl::Milliseconds(5000); - - explicit PayloadManager(EndpointManager& endpoint_manager); - ~PayloadManager() override; - - void SendPayload(ClientProxy* client, const EndpointIds& endpoint_ids, - Payload payload); - Status CancelPayload(ClientProxy* client, Payload::Id payload_id); - - // @EndpointManagerReaderThread - void OnIncomingFrame(OfflineFrame& offline_frame, - const std::string& from_endpoint_id, - ClientProxy* to_client, - proto::connections::Medium current_medium) override; - - // @EndpointManagerThread - void OnEndpointDisconnect(ClientProxy* client, const std::string& endpoint_id, - CountDownLatch barrier) override; - - void DisconnectFromEndpointManager(); - - private: - // Information about an endpoint for a particular payload. - struct EndpointInfo { - // Status set for the endpoint out-of-band via a ControlMessage. - enum class Status { - kUnknown, - kAvailable, - kCanceled, - kError, - }; - - void SetStatusFromControlMessage( - const PayloadTransferFrame::ControlMessage& control_message); - - static Status ControlMessageEventToEndpointInfoStatus( - PayloadTransferFrame::ControlMessage::EventType event); - - std::string id; - AtomicReference<Status> status{Status::kUnknown}; - std::int64_t offset = 0; - }; - - // Tracks state for an InternalPayload and the endpoints associated with it. - class PendingPayload { - public: - PendingPayload(std::unique_ptr<InternalPayload> internal_payload, - const EndpointIds& endpoint_ids, bool is_incoming); - PendingPayload(PendingPayload&&) = default; - PendingPayload& operator=(PendingPayload&&) = default; - - ~PendingPayload() { Close(); } - - Payload::Id GetId() const; - - InternalPayload* GetInternalPayload(); - - bool IsLocallyCanceled() const; - void MarkLocallyCanceled(); - bool IsIncoming() const; - - // Gets the EndpointInfo objects for the endpoints (still) associated with - // this payload. - std::vector<const EndpointInfo*> GetEndpoints() const - ABSL_LOCKS_EXCLUDED(mutex_); - // Returns the EndpointInfo for a given endpoint ID. Returns null if the - // endpoint is not associated with this payload. - EndpointInfo* GetEndpoint(const std::string& endpoint_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Removes the given endpoints, e.g. on error. - void RemoveEndpoints(const EndpointIds& endpoint_ids_to_remove) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Sets the status for a particular endpoint. - void SetEndpointStatusFromControlMessage( - const std::string& endpoint_id, - const PayloadTransferFrame::ControlMessage& control_message) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Sets the offset for a particular endpoint. - void SetOffsetForEndpoint(const std::string& endpoint_id, - std::int64_t offset) ABSL_LOCKS_EXCLUDED(mutex_); - - // Closes internal_payload_ and triggers close_event_. - // Close is called when a pending peyload does not have associated - // endpoints. - void Close(); - - // Waits for close_event_ or for timeout to happen. - // Returns true, if event happened, false otherwise. - bool WaitForClose(); - bool IsClosed(); - - private: - mutable Mutex mutex_; - bool is_incoming_; - AtomicBoolean is_locally_canceled_{false}; - CountDownLatch close_event_{1}; - std::unique_ptr<InternalPayload> internal_payload_; - absl::flat_hash_map<std::string, EndpointInfo> endpoints_ - ABSL_GUARDED_BY(mutex_); - }; - - // Tracks and manages PendingPayload objects in a synchronized manner. - class PendingPayloads { - public: - PendingPayloads() = default; - ~PendingPayloads() = default; - - void StartTrackingPayload(Payload::Id payload_id, - std::unique_ptr<PendingPayload> pending_payload) - ABSL_LOCKS_EXCLUDED(mutex_); - std::unique_ptr<PendingPayload> StopTrackingPayload(Payload::Id payload_id) - ABSL_LOCKS_EXCLUDED(mutex_); - PendingPayload* GetPayload(Payload::Id payload_id) const - ABSL_LOCKS_EXCLUDED(mutex_); - std::vector<Payload::Id> GetAllPayloads() ABSL_LOCKS_EXCLUDED(mutex_); - - private: - mutable Mutex mutex_; - absl::flat_hash_map<Payload::Id, std::unique_ptr<PendingPayload>> - pending_payloads_ ABSL_GUARDED_BY(mutex_); - }; - - using Endpoints = std::vector<const EndpointInfo*>; - static std::string ToString(const EndpointIds& endpoint_ids); - static std::string ToString(const Endpoints& endpoints); - static std::string ToString(Payload::Type type); - static std::string ToString(EndpointInfo::Status status); - - // Splits the endpoints for this payload by availability. - // Returns a pair of lists of EndpointInfo*, with the first being the list of - // still-available endpoints, and the second for unavailable endpoints. - static std::pair<Endpoints, Endpoints> GetAvailableAndUnavailableEndpoints( - const PendingPayload& pending_payload); - - // Converts list of EndpointInfo to list of Endpoint ids. - // Returns list of endpoint ids. - static EndpointIds EndpointsToEndpointIds(const Endpoints& endpoints); - - bool SendPayloadLoop(ClientProxy* client, PendingPayload& pending_payload, - PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t& next_chunk_offset, size_t resume_offset); - void SendClientCallbacksForFinishedIncomingPayloadRunnable( - ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t offset_bytes, proto::connections::PayloadStatus status); - - // Converts the status of an endpoint that's been set out-of-band via a remote - // ControlMessage to the PayloadStatus for handling of that endpoint-payload - // pair. - static proto::connections::PayloadStatus EndpointInfoStatusToPayloadStatus( - EndpointInfo::Status status); - // Converts a ControlMessage::EventType for a particular payload to a - // PayloadStatus. Called when we've received a ControlMessage with this event - // from a remote endpoint; thus the PayloadStatuses are REMOTE_*. - static proto::connections::PayloadStatus ControlMessageEventToPayloadStatus( - PayloadTransferFrame::ControlMessage::EventType event); - static PayloadProgressInfo::Status PayloadStatusToTransferUpdateStatus( - proto::connections::PayloadStatus status); - - int GetOptimalChunkSize(EndpointIds endpoint_ids); - - PayloadTransferFrame::PayloadHeader CreatePayloadHeader( - const InternalPayload& payload, size_t offset); - PayloadTransferFrame::PayloadChunk CreatePayloadChunk(std::int64_t offset, - ByteArray body); - - PendingPayload* CreateIncomingPayload(const PayloadTransferFrame& frame, - const std::string& endpoint_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - Payload::Id CreateOutgoingPayload(Payload payload, - const EndpointIds& endpoint_ids) - ABSL_LOCKS_EXCLUDED(mutex_); - - void SendClientCallbacksForFinishedOutgoingPayload( - ClientProxy* client, const EndpointIds& finished_endpoint_ids, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t num_bytes_successfully_transferred, - proto::connections::PayloadStatus status); - void SendClientCallbacksForFinishedIncomingPayload( - ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t offset_bytes, proto::connections::PayloadStatus status); - - void SendControlMessage( - const EndpointIds& endpoint_ids, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t num_bytes_successfully_transferred, - PayloadTransferFrame::ControlMessage::EventType event_type); - - // Handles a finished outgoing payload for the given endpointIds. All statuses - // except for SUCCESS are handled here. - void HandleFinishedOutgoingPayload( - ClientProxy* client, const EndpointIds& finished_endpoint_ids, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t num_bytes_successfully_transferred, - proto::connections::PayloadStatus status = - proto::connections::PayloadStatus::UNKNOWN_PAYLOAD_STATUS); - void HandleFinishedIncomingPayload( - ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int64_t offset_bytes, proto::connections::PayloadStatus status); - - void HandleSuccessfulOutgoingChunk( - ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int32_t payload_chunk_flags, std::int64_t payload_chunk_offset, - std::int64_t payload_chunk_body_size); - void HandleSuccessfulIncomingChunk( - ClientProxy* client, const std::string& endpoint_id, - const PayloadTransferFrame::PayloadHeader& payload_header, - std::int32_t payload_chunk_flags, std::int64_t payload_chunk_offset, - std::int64_t payload_chunk_body_size); - - void ProcessDataPacket(ClientProxy* to_client, - const std::string& from_endpoint_id, - PayloadTransferFrame& payload_transfer_frame); - void ProcessControlPacket(ClientProxy* to_client, - const std::string& from_endpoint_id, - PayloadTransferFrame& payload_transfer_frame); - - void NotifyClientOfIncomingPayloadProgressInfo( - ClientProxy* client, const std::string& endpoint_id, - const PayloadProgressInfo& payload_transfer_update) - RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD(); - - SingleThreadExecutor* GetOutgoingPayloadExecutor(Payload::Type payload_type); - - void RunOnStatusUpdateThread(const std::string& name, - std::function<void()> runnable); - bool NotifyShutdown() ABSL_LOCKS_EXCLUDED(mutex_); - void DestroyPendingPayload(Payload::Id payload_id) - ABSL_LOCKS_EXCLUDED(mutex_); - PendingPayload* GetPayload(Payload::Id payload_id) const - ABSL_LOCKS_EXCLUDED(mutex_); - void CancelAllPayloads() ABSL_LOCKS_EXCLUDED(mutex_); - - void RecordPayloadStartedAnalytics(ClientProxy* client, - const EndpointIds& endpoint_ids, - std::int64_t payload_id, - Payload::Type payload_type, - std::int64_t offset, - std::int64_t total_size); - void RecordInvalidPayloadAnalytics(ClientProxy* client, - const EndpointIds& endpoint_ids, - std::int64_t payload_id, - Payload::Type payload_type, - std::int64_t offset, - std::int64_t total_size); - - Payload::Type FramePayloadTypeToPayloadType( - PayloadTransferFrame::PayloadHeader::PayloadType type); - - mutable Mutex mutex_; - AtomicBoolean shutdown_{false}; - std::unique_ptr<CountDownLatch> shutdown_barrier_; - int send_payload_count_ = 0; - PendingPayloads pending_payloads_ ABSL_GUARDED_BY(mutex_); - SingleThreadExecutor bytes_payload_executor_; - SingleThreadExecutor file_payload_executor_; - SingleThreadExecutor stream_payload_executor_; - SingleThreadExecutor payload_status_update_executor_; - - EndpointManager* endpoint_manager_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_PAYLOAD_MANAGER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/payload_manager_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/payload_manager_test.cc deleted file mode 100644 index 372642d3926..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/payload_manager_test.cc +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/payload_manager.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/strings/string_view.h" -#include "core/internal/simulation_user.h" -#include "platform/base/byte_array.h" -#include "platform/public/pipe.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -constexpr absl::string_view kServiceId = "service-id"; -constexpr absl::string_view kDeviceA = "device-a"; -constexpr absl::string_view kDeviceB = "device-b"; -constexpr absl::string_view kMessage = "message"; -constexpr absl::Duration kProgressTimeout = absl::Milliseconds(1000); -constexpr absl::Duration kDefaultTimeout = absl::Milliseconds(1000); - -constexpr BooleanMediumSelector kTestCases[] = { - BooleanMediumSelector{ - .bluetooth = true, - }, - BooleanMediumSelector{ - .wifi_lan = true, - }, - BooleanMediumSelector{ - .bluetooth = true, - .wifi_lan = true, - }, -}; - -class PayloadSimulationUser : public SimulationUser { - public: - explicit PayloadSimulationUser( - absl::string_view name, - BooleanMediumSelector allowed = BooleanMediumSelector()) - : SimulationUser(std::string(name), allowed) {} - ~PayloadSimulationUser() override { - NEARBY_LOGS(INFO) << "PayloadSimulationUser: [down] name=" << info_.data(); - // SystemClock::Sleep(kDefaultTimeout); - } - - Payload& GetPayload() { return payload_; } - void SendPayload(Payload payload) { - sender_payload_id_ = payload.GetId(); - pm_.SendPayload(&client_, {discovered_.endpoint_id}, std::move(payload)); - } - - Status CancelPayload() { - if (sender_payload_id_) { - return pm_.CancelPayload(&client_, sender_payload_id_); - } else { - return pm_.CancelPayload(&client_, payload_.GetId()); - } - } - - bool IsConnected() const { - return client_.IsConnectedToEndpoint(discovered_.endpoint_id); - } - - protected: - Payload::Id sender_payload_id_ = 0; -}; - -class PayloadManagerTest - : public ::testing::TestWithParam<BooleanMediumSelector> { - protected: - PayloadManagerTest() { env_.Stop(); } - - bool SetupConnection(PayloadSimulationUser& user_a, - PayloadSimulationUser& user_b) { - user_a.StartAdvertising(std::string(kServiceId), &connection_latch_); - user_b.StartDiscovery(std::string(kServiceId), &discovery_latch_); - EXPECT_TRUE(discovery_latch_.Await(kDefaultTimeout).result()); - EXPECT_EQ(user_b.GetDiscovered().service_id, kServiceId); - EXPECT_EQ(user_b.GetDiscovered().endpoint_info, user_a.GetInfo()); - EXPECT_FALSE(user_b.GetDiscovered().endpoint_id.empty()); - NEARBY_LOG(INFO, "EP-B: [discovered] %s", - user_b.GetDiscovered().endpoint_id.c_str()); - user_b.RequestConnection(&connection_latch_); - EXPECT_TRUE(connection_latch_.Await(kDefaultTimeout).result()); - EXPECT_FALSE(user_a.GetDiscovered().endpoint_id.empty()); - NEARBY_LOG(INFO, "EP-A: [discovered] %s", - user_a.GetDiscovered().endpoint_id.c_str()); - NEARBY_LOG(INFO, "Both users discovered their peers."); - user_a.AcceptConnection(&accept_latch_); - user_b.AcceptConnection(&accept_latch_); - EXPECT_TRUE(accept_latch_.Await(kDefaultTimeout).result()); - NEARBY_LOG(INFO, "Both users reached connected state."); - return user_a.IsConnected() && user_b.IsConnected(); - } - - CountDownLatch discovery_latch_{1}; - CountDownLatch connection_latch_{2}; - CountDownLatch accept_latch_{2}; - CountDownLatch payload_latch_{1}; - MediumEnvironment& env_{MediumEnvironment::Instance()}; -}; - -TEST_P(PayloadManagerTest, CanCreateOne) { - env_.Start(); - PayloadSimulationUser user_a(kDeviceA, GetParam()); - env_.Stop(); -} - -TEST_P(PayloadManagerTest, CanCreateMultiple) { - env_.Start(); - PayloadSimulationUser user_a(kDeviceA, GetParam()); - PayloadSimulationUser user_b(kDeviceB, GetParam()); - env_.Stop(); -} - -TEST_P(PayloadManagerTest, CanSendBytePayload) { - env_.Start(); - PayloadSimulationUser user_a(kDeviceA, GetParam()); - PayloadSimulationUser user_b(kDeviceB, GetParam()); - ASSERT_TRUE(SetupConnection(user_a, user_b)); - - user_a.ExpectPayload(payload_latch_); - user_b.SendPayload(Payload(ByteArray{std::string(kMessage)})); - EXPECT_TRUE(payload_latch_.Await(kDefaultTimeout).result()); - EXPECT_EQ(user_a.GetPayload().AsBytes(), ByteArray(std::string(kMessage))); - NEARBY_LOG(INFO, "Test completed."); - - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(PayloadManagerTest, CanSendStreamPayload) { - env_.Start(); - PayloadSimulationUser user_a(kDeviceA, GetParam()); - PayloadSimulationUser user_b(kDeviceB, GetParam()); - ASSERT_TRUE(SetupConnection(user_a, user_b)); - - auto pipe = std::make_shared<Pipe>(); - OutputStream& tx = pipe->GetOutputStream(); - - user_a.ExpectPayload(payload_latch_); - const ByteArray message{std::string(kMessage)}; - // The first write to the output stream will send the first PAYLOAD_TRANSFER - // packet with payload info and message data. - tx.Write(message); - - user_b.SendPayload(Payload([pipe]() -> InputStream& { - return pipe->GetInputStream(); // NOLINT - })); - ASSERT_TRUE(payload_latch_.Await(kDefaultTimeout).result()); - ASSERT_NE(user_a.GetPayload().AsStream(), nullptr); - InputStream& rx = *user_a.GetPayload().AsStream(); - NEARBY_LOG(INFO, "Stream extracted."); - - EXPECT_TRUE(user_a.WaitForProgress( - [&message](const PayloadProgressInfo& info) { - return info.bytes_transferred >= message.size(); - }, - kProgressTimeout)); - ByteArray result = rx.Read(Pipe::kChunkSize).result(); - EXPECT_EQ(result, message); - NEARBY_LOG(INFO, "Packet 1 handled."); - - tx.Write(message); - EXPECT_TRUE(user_a.WaitForProgress( - [&message](const PayloadProgressInfo& info) { - return info.bytes_transferred >= 2 * message.size(); - }, - kProgressTimeout)); - ByteArray result2 = rx.Read(Pipe::kChunkSize).result(); - EXPECT_EQ(result2, message); - NEARBY_LOG(INFO, "Packet 2 handled."); - - rx.Close(); - tx.Close(); - NEARBY_LOG(INFO, "Test completed."); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(PayloadManagerTest, CanCancelPayloadOnReceiverSide) { - env_.Start(); - PayloadSimulationUser user_a(kDeviceA, GetParam()); - PayloadSimulationUser user_b(kDeviceB, GetParam()); - ASSERT_TRUE(SetupConnection(user_a, user_b)); - - auto pipe = std::make_shared<Pipe>(); - OutputStream& tx = pipe->GetOutputStream(); - - user_a.ExpectPayload(payload_latch_); - const ByteArray message{std::string(kMessage)}; - tx.Write(message); - - user_b.SendPayload(Payload([pipe]() -> InputStream& { - return pipe->GetInputStream(); // NOLINT - })); - ASSERT_TRUE(payload_latch_.Await(kDefaultTimeout).result()); - ASSERT_NE(user_a.GetPayload().AsStream(), nullptr); - InputStream& rx = *user_a.GetPayload().AsStream(); - NEARBY_LOG(INFO, "Stream extracted."); - - EXPECT_TRUE(user_a.WaitForProgress( - [&message](const PayloadProgressInfo& info) { - return info.bytes_transferred >= message.size(); - }, - kProgressTimeout)); - ByteArray result = rx.Read(Pipe::kChunkSize).result(); - EXPECT_EQ(result, message); - NEARBY_LOG(INFO, "Packet 1 handled."); - - EXPECT_EQ(user_a.CancelPayload(), Status{Status::kSuccess}); - NEARBY_LOG(INFO, "Stream canceled on receiver side."); - - // Sender will only handle cancel event if it is sending. - // Once cancel is handled, write will fail. - int count = 0; - while (true) { - if (!tx.Write(message).Ok()) break; - SystemClock::Sleep(kDefaultTimeout); - count++; - } - ASSERT_LE(count, 10); - - EXPECT_TRUE(user_a.WaitForProgress( - [status = PayloadProgressInfo::Status::kCanceled]( - const PayloadProgressInfo& info) { return info.status == status; }, - kProgressTimeout)); - NEARBY_LOG(INFO, "Stream cancelation received."); - - tx.Close(); - rx.Close(); - - NEARBY_LOG(INFO, "Test completed."); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(PayloadManagerTest, CanCancelPayloadOnSenderSide) { - env_.Start(); - PayloadSimulationUser user_a(kDeviceA, GetParam()); - PayloadSimulationUser user_b(kDeviceB, GetParam()); - ASSERT_TRUE(SetupConnection(user_a, user_b)); - - auto pipe = std::make_shared<Pipe>(); - OutputStream& tx = pipe->GetOutputStream(); - - user_a.ExpectPayload(payload_latch_); - const ByteArray message{std::string(kMessage)}; - tx.Write(message); - - user_b.SendPayload(Payload([pipe]() -> InputStream& { - return pipe->GetInputStream(); // NOLINT - })); - ASSERT_TRUE(payload_latch_.Await(kDefaultTimeout).result()); - ASSERT_NE(user_a.GetPayload().AsStream(), nullptr); - InputStream& rx = *user_a.GetPayload().AsStream(); - NEARBY_LOG(INFO, "Stream extracted."); - - EXPECT_TRUE(user_a.WaitForProgress( - [&message](const PayloadProgressInfo& info) { - return info.bytes_transferred >= message.size(); - }, - kProgressTimeout)); - ByteArray result = rx.Read(Pipe::kChunkSize).result(); - EXPECT_EQ(result, message); - NEARBY_LOG(INFO, "Packet 1 handled."); - - EXPECT_EQ(user_b.CancelPayload(), Status{Status::kSuccess}); - NEARBY_LOG(INFO, "Stream canceled on sender side."); - - // Sender will only handle cancel event if it is sending. - // Once cancel is handled, write will fail. - int count = 0; - while (true) { - if (!tx.Write(message).Ok()) break; - SystemClock::Sleep(kDefaultTimeout); - count++; - } - ASSERT_LE(count, 10); - - EXPECT_TRUE(user_a.WaitForProgress( - [status = PayloadProgressInfo::Status::kCanceled]( - const PayloadProgressInfo& info) { return info.status == status; }, - kProgressTimeout)); - NEARBY_LOG(INFO, "Stream cancelation received."); - - tx.Close(); - rx.Close(); - - NEARBY_LOG(INFO, "Test completed."); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(PayloadManagerTest, SendPayloadWithSkip_StreamPayload) { - constexpr size_t kOffset = 3; - env_.Start(); - PayloadSimulationUser user_a(kDeviceA, GetParam()); - PayloadSimulationUser user_b(kDeviceB, GetParam()); - ASSERT_TRUE(SetupConnection(user_a, user_b)); - - auto pipe = std::make_shared<Pipe>(); - OutputStream& tx = pipe->GetOutputStream(); - - user_a.ExpectPayload(payload_latch_); - const ByteArray message{std::string(kMessage)}; - // The first write to the output stream will send the first PAYLOAD_TRANSFER - // packet with payload info and message data. - tx.Write(message); - - Payload payload([pipe]() -> InputStream& { - return pipe->GetInputStream(); // NOLINT - }); - payload.SetOffset(kOffset); - user_b.SendPayload(std::move(payload)); - ASSERT_TRUE(payload_latch_.Await(kDefaultTimeout).result()); - ASSERT_NE(user_a.GetPayload().AsStream(), nullptr); - InputStream& rx = *user_a.GetPayload().AsStream(); - NEARBY_LOG(INFO, "Stream extracted."); - - EXPECT_TRUE(user_a.WaitForProgress( - [&message](const PayloadProgressInfo& info) { - return info.bytes_transferred >= message.size() - kOffset; - }, - kProgressTimeout)); - ByteArray result = rx.Read(Pipe::kChunkSize).result(); - EXPECT_EQ(result, ByteArray("sage")); - NEARBY_LOG(INFO, "Packet 1 handled."); - - tx.Write(message); - EXPECT_TRUE(user_a.WaitForProgress( - [&message](const PayloadProgressInfo& info) { - return info.bytes_transferred >= 2 * message.size() - kOffset; - }, - kProgressTimeout)); - ByteArray result2 = rx.Read(Pipe::kChunkSize).result(); - EXPECT_EQ(result2, message); - NEARBY_LOG(INFO, "Packet 2 handled."); - - rx.Close(); - tx.Close(); - NEARBY_LOG(INFO, "Test completed."); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -INSTANTIATE_TEST_SUITE_P(ParametrisedPayloadManagerTest, PayloadManagerTest, - ::testing::ValuesIn(kTestCases)); - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/pcp.h b/chromium/third_party/nearby/src/cpp/core/internal/pcp.h deleted file mode 100644 index 657db612e30..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/pcp.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_PCP_H_ -#define CORE_INTERNAL_PCP_H_ - -namespace location { -namespace nearby { -namespace connections { - -// The PreConnectionProtocol (PCP) defines the combinations of interactions -// between the techniques (ultrasound audio, Bluetooth device names, BLE -// advertisements) used for offline Advertisement + Discovery, and identifies -// the steps to go through on each device. -// -// See go/nearby-offline-data-interchange-formats for more. -enum class Pcp { - kUnknown = 0, - kP2pStar = 1, - kP2pCluster = 2, - kP2pPointToPoint = 3, - // PCP is only allocated 5 bits in our data interchange formats, so there can - // never be more than 31 PCP values. -}; -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_PCP_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/pcp_handler.h b/chromium/third_party/nearby/src/cpp/core/internal/pcp_handler.h deleted file mode 100644 index b7ad50c0295..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/pcp_handler.h +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_PCP_HANDLER_H_ -#define CORE_INTERNAL_PCP_HANDLER_H_ - -#include <vector> - -#include "core/internal/client_proxy.h" -#include "core/internal/pcp.h" -#include "core/listeners.h" -#include "core/options.h" -#include "core/params.h" -#include "core/status.h" -#include "core/strategy.h" - -namespace location { -namespace nearby { -namespace connections { - -inline Pcp StrategyToPcp(Strategy strategy) { - if (strategy == Strategy::kP2pCluster) return Pcp::kP2pCluster; - if (strategy == Strategy::kP2pStar) return Pcp::kP2pStar; - if (strategy == Strategy::kP2pPointToPoint) return Pcp::kP2pPointToPoint; - return Pcp::kUnknown; -} - -inline Strategy PcpToStrategy(Pcp pcp) { - if (pcp == Pcp::kP2pCluster) return Strategy::kP2pCluster; - if (pcp == Pcp::kP2pStar) return Strategy::kP2pStar; - if (pcp == Pcp::kP2pPointToPoint) return Strategy::kP2pPointToPoint; - return Strategy::kNone; -} - -// Defines the set of methods that need to be implemented to handle the -// per-PCP-specific operations in the OfflineServiceController. -// -// These methods are all meant to be synchronous, and should return only after -// knowing they've done what they were supposed to do (or unequivocally failed -// to do so). -// -// See details here: -// cpp/core/core.h -class PcpHandler { - public: - virtual ~PcpHandler() = default; - - // Return strategy supported by this protocol. - virtual Strategy GetStrategy() const = 0; - - // Return concrete variant of protocol. - virtual Pcp GetPcp() const = 0; - - // We have been asked by the client to start advertising. Once we successfully - // start advertising, we'll change the ClientProxy's state. - // ConnectionListener (info.listener) will be notified in case of any event. - // See - // cpp/core/listeners.h - virtual Status StartAdvertising(ClientProxy* client, - const std::string& service_id, - const ConnectionOptions& options, - const ConnectionRequestInfo& info) = 0; - - // If Advertising is active, stop it, and change CLientProxy state, - // otherwise do nothing. - virtual void StopAdvertising(ClientProxy* client) = 0; - - // Start discovery of endpoints that may be advertising. - // Update ClientProxy state once discovery started. - // DiscoveryListener will get called in case of any event. - virtual Status StartDiscovery(ClientProxy* client, - const std::string& service_id, - const ConnectionOptions& options, - const DiscoveryListener& listener) = 0; - - // If Discovery is active, stop it, and change CLientProxy state, - // otherwise do nothing. - virtual void StopDiscovery(ClientProxy* client) = 0; - - // If Discovery is active with is_out_of_band_connection == true, invoke the - // callback with the provided endpoint info. - virtual void InjectEndpoint(ClientProxy* client, - const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) = 0; - - // If remote endpoint has been successfully discovered, request it to form a - // connection, update state on ClientProxy. - virtual Status RequestConnection(ClientProxy* client, - const std::string& endpoint_id, - const ConnectionRequestInfo& info, - const ConnectionOptions& options) = 0; - - // Either party may call this to accept connection on their part. - // Until both parties call it, connection will not reach a data phase. - // Update state in ClientProxy. - virtual Status AcceptConnection(ClientProxy* client, - const std::string& endpoint_id, - const PayloadListener& payload_listener) = 0; - - // Either party may call this to reject connection on their part before - // connection reaches data phase. If either party does call it, connection - // will terminate. Update state in ClientProxy. - virtual Status RejectConnection(ClientProxy* client, - const std::string& endpoint_id) = 0; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_PCP_HANDLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/pcp_manager.cc b/chromium/third_party/nearby/src/cpp/core/internal/pcp_manager.cc deleted file mode 100644 index 98de1acfa0d..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/pcp_manager.cc +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/pcp_manager.h" - -#include "core/internal/p2p_cluster_pcp_handler.h" -#include "core/internal/p2p_point_to_point_pcp_handler.h" -#include "core/internal/p2p_star_pcp_handler.h" -#include "core/internal/pcp_handler.h" - -namespace location { -namespace nearby { -namespace connections { - -PcpManager::PcpManager( - Mediums& mediums, EndpointChannelManager& channel_manager, - EndpointManager& endpoint_manager, BwuManager& bwu_manager, - InjectedBluetoothDeviceStore& injected_bluetooth_device_store) { - handlers_[Pcp::kP2pCluster] = std::make_unique<P2pClusterPcpHandler>( - &mediums, &endpoint_manager, &channel_manager, &bwu_manager, - injected_bluetooth_device_store); - handlers_[Pcp::kP2pStar] = std::make_unique<P2pStarPcpHandler>( - mediums, endpoint_manager, channel_manager, bwu_manager, - injected_bluetooth_device_store); - handlers_[Pcp::kP2pPointToPoint] = - std::make_unique<P2pPointToPointPcpHandler>( - mediums, endpoint_manager, channel_manager, bwu_manager, - injected_bluetooth_device_store); -} - -void PcpManager::DisconnectFromEndpointManager() { - if (shutdown_.Set(true)) return; - for (auto& item : handlers_) { - if (!item.second) continue; - item.second->DisconnectFromEndpointManager(); - } -} - -PcpManager::~PcpManager() { - NEARBY_LOGS(INFO) << "Initiating shutdown of PcpManager."; - DisconnectFromEndpointManager(); - NEARBY_LOGS(INFO) << "PcpManager has shut down."; -} - -Status PcpManager::StartAdvertising(ClientProxy* client, - const string& service_id, - const ConnectionOptions& options, - const ConnectionRequestInfo& info) { - if (!SetCurrentPcpHandler(options.strategy)) { - return {Status::kError}; - } - - return current_->StartAdvertising(client, service_id, options, info); -} - -void PcpManager::StopAdvertising(ClientProxy* client) { - if (current_) { - current_->StopAdvertising(client); - } -} - -Status PcpManager::StartDiscovery(ClientProxy* client, const string& service_id, - const ConnectionOptions& options, - DiscoveryListener listener) { - if (!SetCurrentPcpHandler(options.strategy)) { - return {Status::kError}; - } - - return current_->StartDiscovery(client, service_id, options, - std::move(listener)); -} - -void PcpManager::StopDiscovery(ClientProxy* client) { - if (current_) { - current_->StopDiscovery(client); - } -} - -void PcpManager::InjectEndpoint(ClientProxy* client, - const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) { - if (current_) { - current_->InjectEndpoint(client, service_id, metadata); - } -} - -Status PcpManager::RequestConnection(ClientProxy* client, - const string& endpoint_id, - const ConnectionRequestInfo& info, - const ConnectionOptions& options) { - if (!current_) { - return {Status::kOutOfOrderApiCall}; - } - - return current_->RequestConnection(client, endpoint_id, info, options); -} - -Status PcpManager::AcceptConnection(ClientProxy* client, - const string& endpoint_id, - const PayloadListener& payload_listener) { - if (!current_) { - return {Status::kOutOfOrderApiCall}; - } - - return current_->AcceptConnection(client, endpoint_id, payload_listener); -} - -Status PcpManager::RejectConnection(ClientProxy* client, - const string& endpoint_id) { - if (!current_) { - return {Status::kOutOfOrderApiCall}; - } - - return current_->RejectConnection(client, endpoint_id); -} - -bool PcpManager::SetCurrentPcpHandler(Strategy strategy) { - current_ = GetPcpHandler(StrategyToPcp(strategy)); - - if (!current_) { - NEARBY_LOG(ERROR, "Failed to set current PCP handler: strategy=%s", - strategy.GetName().c_str()); - } - - return current_; -} - -PcpHandler* PcpManager::GetPcpHandler(Pcp pcp) const { - auto item = handlers_.find(pcp); - return item != handlers_.end() ? item->second.get() : nullptr; -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/pcp_manager.h b/chromium/third_party/nearby/src/cpp/core/internal/pcp_manager.h deleted file mode 100644 index 5c8dd8a99ec..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/pcp_manager.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_PCP_MANAGER_H_ -#define CORE_INTERNAL_PCP_MANAGER_H_ - -#include <string> - -#include "absl/container/flat_hash_map.h" -#include "core/internal/base_pcp_handler.h" -#include "core/internal/bwu_manager.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel_manager.h" -#include "core/internal/endpoint_manager.h" -#include "core/internal/injected_bluetooth_device_store.h" -#include "core/internal/mediums/mediums.h" -#include "core/listeners.h" -#include "core/options.h" -#include "core/status.h" -#include "core/strategy.h" -#include "platform/public/atomic_boolean.h" - -namespace location { -namespace nearby { -namespace connections { - -// Manages all known PcpHandler implementations, delegating operations to the -// appropriate one as per the parameters passed in. -// -// This will only ever be used by the OfflineServiceController, which has all -// of its entrypoints invoked serially, so there's no synchronization needed. -// Public method semantics matches definition in the -// cpp/core/internal/service_controller.h -class PcpManager { - public: - PcpManager(Mediums& mediums, EndpointChannelManager& channel_manager, - EndpointManager& endpoint_manager, BwuManager& bwu_manager, - InjectedBluetoothDeviceStore& injected_bluetooth_device_store); - ~PcpManager(); - - Status StartAdvertising(ClientProxy* client, const string& service_id, - const ConnectionOptions& options, - const ConnectionRequestInfo& info); - void StopAdvertising(ClientProxy* client); - - Status StartDiscovery(ClientProxy* client, const string& service_id, - const ConnectionOptions& options, - DiscoveryListener listener); - void StopDiscovery(ClientProxy* client); - - void InjectEndpoint(ClientProxy* client, const std::string& service_id, - const OutOfBandConnectionMetadata& metadata); - - Status RequestConnection(ClientProxy* client, const string& endpoint_id, - const ConnectionRequestInfo& info, - const ConnectionOptions& options); - Status AcceptConnection(ClientProxy* client, const string& endpoint_id, - const PayloadListener& payload_listener); - Status RejectConnection(ClientProxy* client, const string& endpoint_id); - - proto::connections::Medium GetBandwidthUpgradeMedium(); - void DisconnectFromEndpointManager(); - - private: - bool SetCurrentPcpHandler(Strategy strategy); - PcpHandler* GetPcpHandler(Pcp pcp) const; - - AtomicBoolean shutdown_{false}; - absl::flat_hash_map<Pcp, std::unique_ptr<BasePcpHandler>> handlers_; - PcpHandler* current_ = nullptr; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_PCP_MANAGER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/pcp_manager_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/pcp_manager_test.cc deleted file mode 100644 index fd703d1662a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/pcp_manager_test.cc +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/pcp_manager.h" - -#include <array> -#include <string> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/time/time.h" -#include "core/internal/endpoint_channel_manager.h" -#include "core/internal/simulation_user.h" -#include "core/options.h" -#include "platform/base/medium_environment.h" -#include "platform/public/count_down_latch.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -constexpr std::array<char, 6> kFakeMacAddress = {'a', 'b', 'c', 'd', 'e', 'f'}; -constexpr char kServiceId[] = "service-id"; -constexpr char kDeviceA[] = "device-A"; -constexpr char kDeviceB[] = "device-B"; - -constexpr BooleanMediumSelector kTestCases[] = { - BooleanMediumSelector{ - .bluetooth = true, - }, - BooleanMediumSelector{ - .wifi_lan = true, - }, - BooleanMediumSelector{ - .bluetooth = true, - .wifi_lan = true, - }, -}; - -class PcpManagerTest : public ::testing::TestWithParam<BooleanMediumSelector> { - protected: - PcpManagerTest() { env_.Stop(); } - - MediumEnvironment& env_{MediumEnvironment::Instance()}; -}; - -TEST_P(PcpManagerTest, CanCreateOne) { - env_.Start(); - SimulationUser user(kDeviceA, GetParam()); - env_.Stop(); -} - -TEST_P(PcpManagerTest, CanCreateMany) { - env_.Start(); - SimulationUser user_a(kDeviceA, GetParam()); - SimulationUser user_b(kDeviceB, GetParam()); - env_.Stop(); -} - -TEST_P(PcpManagerTest, CanAdvertise) { - env_.Start(); - SimulationUser user_a(kDeviceA, GetParam()); - SimulationUser user_b(kDeviceB, GetParam()); - user_a.StartAdvertising(kServiceId, nullptr); - env_.Stop(); -} - -TEST_P(PcpManagerTest, CanDiscover) { - env_.Start(); - SimulationUser user_a("device-a", GetParam()); - SimulationUser user_b("device-b", GetParam()); - user_a.StartAdvertising(kServiceId, nullptr); - CountDownLatch latch(1); - user_b.StartDiscovery(kServiceId, &latch); - EXPECT_TRUE(latch.Await(absl::Milliseconds(1000)).result()); - EXPECT_EQ(user_b.GetDiscovered().service_id, kServiceId); - EXPECT_EQ(user_b.GetDiscovered().endpoint_info, user_a.GetInfo()); - env_.Stop(); -} - -TEST_P(PcpManagerTest, CanConnect) { - env_.Start(); - SimulationUser user_a("device-a", GetParam()); - SimulationUser user_b("device-b", GetParam()); - CountDownLatch discovery_latch(1); - CountDownLatch connection_latch(2); - user_a.StartAdvertising(kServiceId, &connection_latch); - user_b.StartDiscovery(kServiceId, &discovery_latch); - EXPECT_TRUE(discovery_latch.Await(absl::Milliseconds(1000)).result()); - EXPECT_EQ(user_b.GetDiscovered().service_id, kServiceId); - EXPECT_EQ(user_b.GetDiscovered().endpoint_info, user_a.GetInfo()); - user_b.RequestConnection(&connection_latch); - EXPECT_TRUE(connection_latch.Await(absl::Milliseconds(1000)).result()); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(PcpManagerTest, CanAccept) { - env_.Start(); - SimulationUser user_a("device-a", GetParam()); - SimulationUser user_b("device-b", GetParam()); - CountDownLatch discovery_latch(1); - CountDownLatch connection_latch(2); - CountDownLatch accept_latch(2); - user_a.StartAdvertising(kServiceId, &connection_latch); - user_b.StartDiscovery(kServiceId, &discovery_latch); - EXPECT_TRUE(discovery_latch.Await(absl::Milliseconds(1000)).result()); - EXPECT_EQ(user_b.GetDiscovered().service_id, kServiceId); - EXPECT_EQ(user_b.GetDiscovered().endpoint_info, user_a.GetInfo()); - user_b.RequestConnection(&connection_latch); - EXPECT_TRUE(connection_latch.Await(absl::Milliseconds(1000)).result()); - user_a.AcceptConnection(&accept_latch); - user_b.AcceptConnection(&accept_latch); - EXPECT_TRUE(accept_latch.Await(absl::Milliseconds(1000)).result()); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -TEST_P(PcpManagerTest, CanReject) { - env_.Start(); - SimulationUser user_a("device-a", GetParam()); - SimulationUser user_b("device-b", GetParam()); - CountDownLatch discovery_latch(1); - CountDownLatch connection_latch(2); - CountDownLatch reject_latch(1); - user_a.StartAdvertising(kServiceId, &connection_latch); - user_b.StartDiscovery(kServiceId, &discovery_latch); - EXPECT_TRUE(discovery_latch.Await(absl::Milliseconds(1000)).result()); - EXPECT_EQ(user_b.GetDiscovered().service_id, kServiceId); - EXPECT_EQ(user_b.GetDiscovered().endpoint_info, user_a.GetInfo()); - user_b.RequestConnection(&connection_latch); - EXPECT_TRUE(connection_latch.Await(absl::Milliseconds(1000)).result()); - user_b.ExpectRejectedConnection(reject_latch); - user_a.RejectConnection(nullptr); - EXPECT_TRUE(reject_latch.Await(absl::Milliseconds(1000)).result()); - user_a.Stop(); - user_b.Stop(); - env_.Stop(); -} - -INSTANTIATE_TEST_SUITE_P(ParametrisedPcpManagerTest, PcpManagerTest, - ::testing::ValuesIn(kTestCases)); - -// Verifies that InjectEndpoint() can be run successfully; does not test the -// full connection flow given that normal discovery/advertisement is skipped. -// Note: Not parameterized because InjectEndpoint only works over Bluetooth. -TEST_F(PcpManagerTest, InjectEndpoint) { - env_.Start(); - SimulationUser user_a(kDeviceA, BooleanMediumSelector{.bluetooth = true}); - user_a.StartDiscovery(kServiceId, /*latch=*/nullptr); - user_a.InjectEndpoint(kServiceId, OutOfBandConnectionMetadata{ - .medium = Medium::BLUETOOTH, - .remote_bluetooth_mac_address = - ByteArray(kFakeMacAddress), - }); - user_a.Stop(); - env_.Stop(); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/service_controller.h b/chromium/third_party/nearby/src/cpp/core/internal/service_controller.h deleted file mode 100644 index 1fa3f6466be..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/service_controller.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_SERVICE_CONTROLLER_H_ -#define CORE_INTERNAL_SERVICE_CONTROLLER_H_ - -#include <cstdint> -#include <string> -#include <vector> - -#include "core/internal/client_proxy.h" -#include "core/listeners.h" -#include "core/options.h" -#include "core/params.h" -#include "core/payload.h" -#include "core/status.h" - -namespace location { -namespace nearby { -namespace connections { - -// Interface defines the core functionality of Nearby Connections Service. -// -// In every method, ClientProxy* represents the client app which receives -// notifications from Nearby Connections service and forwards them to the app. -// ResultCallback arguments are not provided for this class, because all methods -// are called synchronously. -// The rest of arguments have the same meaning as the corresponding -// methods in the definition of location::nearby::Core API. -// -// See details here: -// cpp/core/core.h -class ServiceController { - public: - virtual ~ServiceController() = default; - ServiceController() = default; - ServiceController(const ServiceController&) = delete; - ServiceController& operator=(const ServiceController&) = delete; - - // Stops and disables service controller. - // - // When service controller is stopped all API call fail early. - // Note that all Core, ClientProxy objects referencing this service - // controller are affected. - virtual void Stop() = 0; - - // Starts advertising an endpoint for a local app. - virtual Status StartAdvertising(ClientProxy* client, - const std::string& service_id, - const ConnectionOptions& options, - const ConnectionRequestInfo& info) = 0; - virtual void StopAdvertising(ClientProxy* client) = 0; - - virtual Status StartDiscovery(ClientProxy* client, - const std::string& service_id, - const ConnectionOptions& options, - const DiscoveryListener& listener) = 0; - virtual void StopDiscovery(ClientProxy* client) = 0; - - virtual void InjectEndpoint(ClientProxy* client, - const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) = 0; - - virtual Status RequestConnection(ClientProxy* client, - const std::string& endpoint_id, - const ConnectionRequestInfo& info, - const ConnectionOptions& options) = 0; - virtual Status AcceptConnection(ClientProxy* client, - const std::string& endpoint_id, - const PayloadListener& listener) = 0; - virtual Status RejectConnection(ClientProxy* client, - const std::string& endpoint_id) = 0; - - virtual void InitiateBandwidthUpgrade(ClientProxy* client, - const std::string& endpoint_id) = 0; - - virtual void SendPayload(ClientProxy* client, - const std::vector<std::string>& endpoint_ids, - Payload payload) = 0; - - virtual Status CancelPayload(ClientProxy* client, Payload::Id payload_id) = 0; - - virtual void DisconnectFromEndpoint(ClientProxy* client, - const std::string& endpoint_id) = 0; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_SERVICE_CONTROLLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/service_controller_router.cc b/chromium/third_party/nearby/src/cpp/core/internal/service_controller_router.cc deleted file mode 100644 index 7c5eaffd0ac..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/service_controller_router.cc +++ /dev/null @@ -1,384 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/service_controller_router.h" - -#include <cstddef> -#include <memory> -#include <string> -#include <utility> - -#include "absl/memory/memory.h" -#include "core/internal/client_proxy.h" -#include "core/internal/offline_service_controller.h" -#include "core/listeners.h" -#include "core/options.h" -#include "core/params.h" -#include "core/payload.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { -// Length of a MAC address, which consists of 6 bytes uniquely identifying a -// hardware interface. -const std::size_t kMacAddressLength = 6u; - -// Length used for an endpoint ID, which identifies a device discovery and -// associated connection request. -const std::size_t kEndpointIdLength = 4u; - -// Maximum length for information describing an endpoint; this information is -// advertised by one device and can be used by the other device to identify the -// advertiser. -const std::size_t kMaxEndpointInfoLength = 131u; - -bool ClientHasConnectionToAtLeastOneEndpoint( - ClientProxy* client, const std::vector<std::string>& remote_endpoint_ids) { - for (auto& endpoint_id : remote_endpoint_ids) { - if (client->IsConnectedToEndpoint(endpoint_id)) { - return true; - } - } - return false; -} -} // namespace - -ServiceControllerRouter::ServiceControllerRouter() { - NEARBY_LOGS(INFO) << "ServiceControllerRouter going up."; -} - -ServiceControllerRouter::~ServiceControllerRouter() { - NEARBY_LOGS(INFO) << "ServiceControllerRouter going down."; - - if (service_controller_) { - service_controller_->Stop(); - } - // And make sure that cleanup is the last thing we do. - serializer_.Shutdown(); -} - -void ServiceControllerRouter::StartAdvertising( - ClientProxy* client, absl::string_view service_id, - const ConnectionOptions& options, const ConnectionRequestInfo& info, - const ResultCallback& callback) { - RouteToServiceController( - "scr-start-advertising", - [this, client, service_id = std::string(service_id), options, info, - callback]() { - if (client->IsAdvertising()) { - callback.result_cb({Status::kAlreadyAdvertising}); - return; - } - - callback.result_cb(GetServiceController()->StartAdvertising( - client, service_id, options, info)); - }); -} - -void ServiceControllerRouter::StopAdvertising(ClientProxy* client, - const ResultCallback& callback) { - RouteToServiceController("scr-stop-advertising", [this, client, callback]() { - if (client->IsAdvertising()) { - GetServiceController()->StopAdvertising(client); - } - callback.result_cb({Status::kSuccess}); - }); -} - -void ServiceControllerRouter::StartDiscovery(ClientProxy* client, - absl::string_view service_id, - const ConnectionOptions& options, - const DiscoveryListener& listener, - const ResultCallback& callback) { - RouteToServiceController( - "scr-start-discovery", - [this, client, service_id = std::string(service_id), options, listener, - callback]() { - if (client->IsDiscovering()) { - callback.result_cb({Status::kAlreadyDiscovering}); - return; - } - - callback.result_cb(GetServiceController()->StartDiscovery( - client, service_id, options, listener)); - }); -} - -void ServiceControllerRouter::StopDiscovery(ClientProxy* client, - const ResultCallback& callback) { - RouteToServiceController("scr-stop-discovery", [this, client, callback]() { - if (client->IsDiscovering()) { - GetServiceController()->StopDiscovery(client); - } - callback.result_cb({Status::kSuccess}); - }); -} - -void ServiceControllerRouter::InjectEndpoint( - ClientProxy* client, absl::string_view service_id, - const OutOfBandConnectionMetadata& metadata, - const ResultCallback& callback) { - RouteToServiceController( - "scr-inject-endpoint", - [this, client, service_id = std::string(service_id), metadata, - callback]() { - // Currently, Bluetooth is the only supported medium for endpoint - // injection. - if (metadata.medium != Medium::BLUETOOTH || - metadata.remote_bluetooth_mac_address.size() != kMacAddressLength) { - callback.result_cb({Status::kError}); - return; - } - - if (metadata.endpoint_id.size() != kEndpointIdLength) { - callback.result_cb({Status::kError}); - return; - } - - if (metadata.endpoint_info.Empty() || - metadata.endpoint_info.size() > kMaxEndpointInfoLength) { - callback.result_cb({Status::kError}); - return; - } - - if (!client->IsDiscovering()) { - callback.result_cb({Status::kOutOfOrderApiCall}); - return; - } - - GetServiceController()->InjectEndpoint(client, service_id, metadata); - callback.result_cb({Status::kSuccess}); - }); -} - -void ServiceControllerRouter::RequestConnection( - ClientProxy* client, absl::string_view endpoint_id, - const ConnectionRequestInfo& info, const ConnectionOptions& options, - const ResultCallback& callback) { - // Cancellations can be fired from clients anytime, need to add the - // CancellationListener as soon as possible. - client->AddCancellationFlag(std::string(endpoint_id)); - - RouteToServiceController( - "scr-request-connection", - [this, client, endpoint_id = std::string(endpoint_id), info, options, - callback]() { - if (client->HasPendingConnectionToEndpoint(endpoint_id) || - client->IsConnectedToEndpoint(endpoint_id)) { - callback.result_cb({Status::kAlreadyConnectedToEndpoint}); - return; - } - - Status status = GetServiceController()->RequestConnection( - client, endpoint_id, info, options); - if (!status.Ok()) { - client->CancelEndpoint(endpoint_id); - } - callback.result_cb(status); - }); -} - -void ServiceControllerRouter::AcceptConnection(ClientProxy* client, - absl::string_view endpoint_id, - const PayloadListener& listener, - const ResultCallback& callback) { - RouteToServiceController( - "scr-accept-connection", - [this, client, endpoint_id = std::string(endpoint_id), listener, - callback]() { - if (client->IsConnectedToEndpoint(endpoint_id)) { - callback.result_cb({Status::kAlreadyConnectedToEndpoint}); - return; - } - - if (client->HasLocalEndpointResponded(endpoint_id)) { - NEARBY_LOGS(WARNING) - << "Client " << client->GetClientId() - << " invoked acceptConnectionRequest() after having already " - "accepted/rejected the connection to endpoint(id=" - << endpoint_id << ")"; - callback.result_cb({Status::kOutOfOrderApiCall}); - return; - } - - callback.result_cb(GetServiceController()->AcceptConnection( - client, endpoint_id, listener)); - }); -} - -void ServiceControllerRouter::RejectConnection(ClientProxy* client, - absl::string_view endpoint_id, - const ResultCallback& callback) { - client->CancelEndpoint(std::string(endpoint_id)); - - RouteToServiceController( - "scr-reject-connection", - [this, client, endpoint_id = std::string(endpoint_id), callback]() { - if (client->IsConnectedToEndpoint(endpoint_id)) { - callback.result_cb({Status::kAlreadyConnectedToEndpoint}); - return; - } - - if (client->HasLocalEndpointResponded(endpoint_id)) { - NEARBY_LOGS(WARNING) - << "Client " << client->GetClientId() - << " invoked rejectConnectionRequest() after having already " - "accepted/rejected the connection to endpoint(id=" - << endpoint_id << ")"; - callback.result_cb({Status::kOutOfOrderApiCall}); - return; - } - - callback.result_cb( - GetServiceController()->RejectConnection(client, endpoint_id)); - }); -} - -void ServiceControllerRouter::InitiateBandwidthUpgrade( - ClientProxy* client, absl::string_view endpoint_id, - const ResultCallback& callback) { - RouteToServiceController( - "scr-init-bwu", - [this, client, endpoint_id = std::string(endpoint_id), callback]() { - if (!client->IsConnectedToEndpoint(endpoint_id)) { - callback.result_cb({Status::kOutOfOrderApiCall}); - return; - } - - GetServiceController()->InitiateBandwidthUpgrade(client, endpoint_id); - - // Operation is triggered; the caller can listen to - // ConnectionListener::OnBandwidthChanged() to determine its success. - callback.result_cb({Status::kSuccess}); - }); -} - -void ServiceControllerRouter::SendPayload( - ClientProxy* client, absl::Span<const std::string> endpoint_ids, - Payload payload, const ResultCallback& callback) { - // Payload is a move-only type. - // We have to capture it by value inside the lambda, and pass it over to - // the executor as an std::function<void()> instance. - // Lambda must be copyable, in order ot satisfy std::function<> requirements. - // To make it so, we need Payload wrapped by a copyable wrapper. - // std::shared_ptr<> is used, because it is copyable. - auto shared_payload = std::make_shared<Payload>(std::move(payload)); - const std::vector<std::string> endpoints = - std::vector<std::string>(endpoint_ids.begin(), endpoint_ids.end()); - - RouteToServiceController("scr-send-payload", [this, client, shared_payload, - endpoints, callback]() { - if (!ClientHasConnectionToAtLeastOneEndpoint(client, endpoints)) { - callback.result_cb({Status::kEndpointUnknown}); - return; - } - - GetServiceController()->SendPayload(client, endpoints, - std::move(*shared_payload)); - - // At this point, we've queued up the send Payload request with the - // ServiceController; any further failures (e.g. one of the endpoints is - // unknown, goes away, or otherwise fails) will be returned to the - // client as a PayloadTransferUpdate. - callback.result_cb({Status::kSuccess}); - }); -} - -void ServiceControllerRouter::CancelPayload(ClientProxy* client, - std::uint64_t payload_id, - const ResultCallback& callback) { - RouteToServiceController( - "scr-cancel-payload", [this, client, payload_id, callback]() { - callback.result_cb( - GetServiceController()->CancelPayload(client, payload_id)); - }); -} - -void ServiceControllerRouter::DisconnectFromEndpoint( - ClientProxy* client, absl::string_view endpoint_id, - const ResultCallback& callback) { - // Client can emit the cancellation at anytime, we need to execute the request - // without further posting it. - client->CancelEndpoint(std::string(endpoint_id)); - - RouteToServiceController( - "scr-disconnect-endpoint", - [this, client, endpoint_id = std::string(endpoint_id), callback]() { - if (!client->IsConnectedToEndpoint(endpoint_id) && - !client->HasPendingConnectionToEndpoint(endpoint_id)) { - callback.result_cb({Status::kOutOfOrderApiCall}); - return; - } - - GetServiceController()->DisconnectFromEndpoint(client, endpoint_id); - callback.result_cb({Status::kSuccess}); - }); -} - -void ServiceControllerRouter::StopAllEndpoints(ClientProxy* client, - const ResultCallback& callback) { - // Client can emit the cancellation at anytime, we need to execute the request - // without further posting it. - client->CancelAllEndpoints(); - - RouteToServiceController( - "scr-stop-all-endpoints", [this, client, callback]() { - NEARBY_LOGS(INFO) << "Client " << client->GetClientId() - << " has requested us to stop all endpoints. We will " - "now reset the client."; - FinishClientSession(client); - callback.result_cb({Status::kSuccess}); - }); -} - -void ServiceControllerRouter::SetServiceControllerForTesting( - std::unique_ptr<ServiceController> service_controller) { - service_controller_ = std::move(service_controller); -} - -ServiceController* ServiceControllerRouter::GetServiceController() { - if (!service_controller_) { - service_controller_ = std::make_unique<OfflineServiceController>(); - } - return service_controller_.get(); -} - -void ServiceControllerRouter::FinishClientSession(ClientProxy* client) { - // Disconnect from all the connected endpoints tied to this clientProxy. - for (auto& endpoint_id : client->GetPendingConnectedEndpoints()) { - GetServiceController()->DisconnectFromEndpoint(client, endpoint_id); - } - - for (auto& endpoint_id : client->GetConnectedEndpoints()) { - GetServiceController()->DisconnectFromEndpoint(client, endpoint_id); - } - - // Stop any advertising and discovery that may be underway due to this client. - GetServiceController()->StopAdvertising(client); - GetServiceController()->StopDiscovery(client); - - // Finally, clear all state maintained by this client. - client->Reset(); -} - -void ServiceControllerRouter::RouteToServiceController(const std::string& name, - Runnable runnable) { - serializer_.Execute(name, std::move(runnable)); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/service_controller_router.h b/chromium/third_party/nearby/src/cpp/core/internal/service_controller_router.h deleted file mode 100644 index 54520ac2807..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/service_controller_router.h +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_SERVICE_CONTROLLER_ROUTER_H_ -#define CORE_INTERNAL_SERVICE_CONTROLLER_ROUTER_H_ - -#include <memory> -#include <string> -#include <vector> - -#include "absl/container/flat_hash_set.h" -#include "absl/strings/string_view.h" -#include "absl/types/span.h" -#include "core/internal/client_proxy.h" -#include "core/internal/service_controller.h" -#include "core/options.h" -#include "core/params.h" -#include "platform/base/runnable.h" -#include "platform/public/single_thread_executor.h" - -namespace location { -namespace nearby { -namespace connections { - -// ServiceControllerRouter: this class is an implementation detail of a -// location::nearby::Core class. The latter delegates all of its activities to -// the former. -// -// All the activities are documented in the public API class: -// cpp/core_v2/core.h -// -// In every method, ClientProxy* represents the client app which receives -// notifications from Nearby Connections service and forwards them to the app. -// The rest of arguments have the same meaning as the corresponding -// methods in the definition of location::nearby::Core API. -// -// Every activity is handled the same way: -// 1) all the arguments to the call are captured by value; -// 2) the actual processing is scheduled on a private single-threaded executor, -// which makes locking unnecessary, when internal data is being manipulated. -// 3) activity handlers are delegating much of their work to an implementation -// of a ServiceController interface, which does the actual job. -class ServiceControllerRouter { - public: - ServiceControllerRouter(); - virtual ~ServiceControllerRouter(); - // Not copyable or movable - ServiceControllerRouter(const ServiceControllerRouter&) = delete; - ServiceControllerRouter& operator=(const ServiceControllerRouter&) = delete; - ServiceControllerRouter(ServiceControllerRouter&&) = delete; - ServiceControllerRouter& operator=(ServiceControllerRouter&&) = delete; - - virtual void StartAdvertising(ClientProxy* client, - absl::string_view service_id, - const ConnectionOptions& options, - const ConnectionRequestInfo& info, - const ResultCallback& callback); - virtual void StopAdvertising(ClientProxy* client, - const ResultCallback& callback); - - virtual void StartDiscovery(ClientProxy* client, absl::string_view service_id, - const ConnectionOptions& options, - const DiscoveryListener& listener, - const ResultCallback& callback); - virtual void StopDiscovery(ClientProxy* client, - const ResultCallback& callback); - - virtual void InjectEndpoint(ClientProxy* client, absl::string_view service_id, - const OutOfBandConnectionMetadata& metadata, - const ResultCallback& callback); - - virtual void RequestConnection(ClientProxy* client, - absl::string_view endpoint_id, - const ConnectionRequestInfo& info, - const ConnectionOptions& options, - const ResultCallback& callback); - virtual void AcceptConnection(ClientProxy* client, - absl::string_view endpoint_id, - const PayloadListener& listener, - const ResultCallback& callback); - virtual void RejectConnection(ClientProxy* client, - absl::string_view endpoint_id, - const ResultCallback& callback); - - virtual void InitiateBandwidthUpgrade(ClientProxy* client, - absl::string_view endpoint_id, - const ResultCallback& callback); - - virtual void SendPayload(ClientProxy* client, - absl::Span<const std::string> endpoint_ids, - Payload payload, const ResultCallback& callback); - virtual void CancelPayload(ClientProxy* client, std::uint64_t payload_id, - const ResultCallback& callback); - - virtual void DisconnectFromEndpoint(ClientProxy* client, - absl::string_view endpoint_id, - const ResultCallback& callback); - virtual void StopAllEndpoints(ClientProxy* client, - const ResultCallback& callback); - - void SetServiceControllerForTesting( - std::unique_ptr<ServiceController> service_controller); - - private: - // Lazily create ServiceController. - ServiceController* GetServiceController(); - - void RouteToServiceController(const std::string& name, Runnable runnable); - void FinishClientSession(ClientProxy* client); - - std::unique_ptr<ServiceController> service_controller_; - SingleThreadExecutor serializer_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_SERVICE_CONTROLLER_ROUTER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/service_controller_router_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/service_controller_router_test.cc deleted file mode 100644 index 74ed7c2c010..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/service_controller_router_test.cc +++ /dev/null @@ -1,421 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/service_controller_router.h" - -#include <array> -#include <cinttypes> -#include <memory> -#include <string> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/container/flat_hash_set.h" -#include "absl/time/clock.h" -#include "absl/types/span.h" -#include "core/internal/client_proxy.h" -#include "core/internal/mock_service_controller.h" -#include "core/internal/service_controller.h" -#include "core/listeners.h" -#include "core/options.h" -#include "core/params.h" -#include "platform/base/byte_array.h" -#include "platform/public/condition_variable.h" -#include "platform/public/mutex.h" -#include "platform/public/mutex_lock.h" - -namespace location { -namespace nearby { -namespace connections { - -namespace { -using ::testing::Return; -constexpr std::array<char, 6> kFakeMacAddress = {'a', 'b', 'c', 'd', 'e', 'f'}; -constexpr std::array<char, 6> kFakeInjectedEndpointInfo = {'g', 'h', 'i'}; -const char kFakeInejctedEndpointId[] = "abcd"; -} // namespace - -// This class must be in the same namespace as ServiceControllerRouter for -// friend class to work. -class ServiceControllerRouterTest : public testing::Test { - public: - void SetUp() override { - auto mock = std::make_unique<MockServiceController>(); - mock_ = mock.get(); - router_.SetServiceControllerForTesting(std::move(mock)); - } - - void StartAdvertising(ClientProxy* client, std::string service_id, - ConnectionOptions options, ConnectionRequestInfo info, - ResultCallback callback) { - EXPECT_CALL(*mock_, StartAdvertising) - .WillOnce(Return(Status{Status::kSuccess})); - { - MutexLock lock(&mutex_); - complete_ = false; - router_.StartAdvertising(client, service_id, options, info, callback); - while (!complete_) cond_.Wait(); - EXPECT_EQ(result_, Status{Status::kSuccess}); - } - client->StartedAdvertising(kServiceId, options.strategy, info.listener, - absl::MakeSpan(mediums_)); - EXPECT_TRUE(client->IsAdvertising()); - } - - void StopAdvertising(ClientProxy* client, ResultCallback callback) { - EXPECT_CALL(*mock_, StopAdvertising).Times(1); - { - MutexLock lock(&mutex_); - complete_ = false; - router_.StopAdvertising(client, callback); - while (!complete_) cond_.Wait(); - } - client->StoppedAdvertising(); - EXPECT_FALSE(client->IsAdvertising()); - } - - void StartDiscovery(ClientProxy* client, std::string service_id, - ConnectionOptions options, - const DiscoveryListener& listener, - const ResultCallback& callback) { - EXPECT_CALL(*mock_, StartDiscovery) - .WillOnce(Return(Status{Status::kSuccess})); - { - MutexLock lock(&mutex_); - complete_ = false; - router_.StartDiscovery(client, kServiceId, options, listener, callback); - while (!complete_) cond_.Wait(); - EXPECT_EQ(result_, Status{Status::kSuccess}); - } - client->StartedDiscovery(service_id, options.strategy, listener, - absl::MakeSpan(mediums_)); - EXPECT_TRUE(client->IsDiscovering()); - } - - void StopDiscovery(ClientProxy* client, ResultCallback callback) { - EXPECT_CALL(*mock_, StopDiscovery).Times(1); - { - MutexLock lock(&mutex_); - complete_ = false; - router_.StopDiscovery(client, callback); - while (!complete_) cond_.Wait(); - } - client->StoppedDiscovery(); - EXPECT_FALSE(client->IsDiscovering()); - } - - void InjectEndpoint(ClientProxy* client, std::string service_id, - const OutOfBandConnectionMetadata& metadata, - ResultCallback callback) { - EXPECT_CALL(*mock_, InjectEndpoint).Times(1); - { - MutexLock lock(&mutex_); - complete_ = false; - router_.InjectEndpoint(client, service_id, metadata, callback); - while (!complete_) cond_.Wait(); - } - } - - void RequestConnection(ClientProxy* client, const std::string& endpoint_id, - const ConnectionRequestInfo& request_info, - ResultCallback callback) { - EXPECT_CALL(*mock_, RequestConnection) - .WillOnce(Return(Status{Status::kSuccess})); - ConnectionOptions options; - { - MutexLock lock(&mutex_); - complete_ = false; - router_.RequestConnection(client, endpoint_id, request_info, options, - callback); - while (!complete_) cond_.Wait(); - EXPECT_EQ(result_, Status{Status::kSuccess}); - } - ConnectionResponseInfo response_info{ - .remote_endpoint_info = ByteArray{"endpoint_name"}, - .authentication_token = "auth_token", - .raw_authentication_token = ByteArray{"auth_token"}, - .is_incoming_connection = true, - }; - std::string connection_token{"conntokn"}; - client->OnConnectionInitiated(endpoint_id, response_info, options, - request_info.listener, connection_token); - EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint_id)); - } - - void AcceptConnection(ClientProxy* client, const std::string endpoint_id, - const PayloadListener& listener, - const ResultCallback& callback) { - EXPECT_CALL(*mock_, AcceptConnection) - .WillOnce(Return(Status{Status::kSuccess})); - // Pre-condition for successful Accept is: connection must exist. - EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint_id)); - { - MutexLock lock(&mutex_); - complete_ = false; - router_.AcceptConnection(client, endpoint_id, listener, callback); - while (!complete_) cond_.Wait(); - EXPECT_EQ(result_, Status{Status::kSuccess}); - } - client->LocalEndpointAcceptedConnection(endpoint_id, listener); - client->RemoteEndpointAcceptedConnection(endpoint_id); - EXPECT_TRUE(client->IsConnectionAccepted(endpoint_id)); - client->OnConnectionAccepted(endpoint_id); - EXPECT_TRUE(client->IsConnectedToEndpoint(endpoint_id)); - } - - void RejectConnection(ClientProxy* client, const std::string endpoint_id, - ResultCallback callback) { - EXPECT_CALL(*mock_, RejectConnection) - .WillOnce(Return(Status{Status::kSuccess})); - // Pre-condition for successful Accept is: connection must exist. - EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint_id)); - { - MutexLock lock(&mutex_); - complete_ = false; - router_.RejectConnection(client, endpoint_id, callback); - while (!complete_) cond_.Wait(); - EXPECT_EQ(result_, Status{Status::kSuccess}); - } - client->LocalEndpointRejectedConnection(endpoint_id); - EXPECT_TRUE(client->IsConnectionRejected(endpoint_id)); - } - - void InitiateBandwidthUpgrade(ClientProxy* client, - const std::string endpoint_id, - ResultCallback callback) { - EXPECT_CALL(*mock_, InitiateBandwidthUpgrade).Times(1); - EXPECT_TRUE(client->IsConnectedToEndpoint(endpoint_id)); - { - MutexLock lock(&mutex_); - complete_ = false; - router_.InitiateBandwidthUpgrade(client, endpoint_id, callback); - while (!complete_) cond_.Wait(); - EXPECT_EQ(result_, Status{Status::kSuccess}); - } - } - - void SendPayload(ClientProxy* client, - const std::vector<std::string>& endpoint_ids, - Payload payload, ResultCallback callback) { - EXPECT_CALL(*mock_, SendPayload).Times(1); - - bool connected = false; - for (const auto& endpoint_id : endpoint_ids) { - connected = connected || client->IsConnectedToEndpoint(endpoint_id); - } - EXPECT_TRUE(connected); - { - MutexLock lock(&mutex_); - complete_ = false; - router_.SendPayload(client, absl::MakeSpan(endpoint_ids), - std::move(payload), callback); - while (!complete_) cond_.Wait(); - EXPECT_EQ(result_, Status{Status::kSuccess}); - } - } - - void CancelPayload(ClientProxy* client, std::int64_t payload_id, - ResultCallback callback) { - EXPECT_CALL(*mock_, CancelPayload) - .WillOnce(Return(Status{Status::kSuccess})); - { - MutexLock lock(&mutex_); - complete_ = false; - router_.CancelPayload(client, payload_id, callback); - while (!complete_) cond_.Wait(); - EXPECT_EQ(result_, Status{Status::kSuccess}); - } - } - - void DisconnectFromEndpoint(ClientProxy* client, - const std::string endpoint_id, - ResultCallback callback) { - EXPECT_CALL(*mock_, DisconnectFromEndpoint).Times(1); - EXPECT_TRUE(client->IsConnectedToEndpoint(endpoint_id)); - { - MutexLock lock(&mutex_); - complete_ = false; - router_.DisconnectFromEndpoint(client, endpoint_id, callback); - while (!complete_) cond_.Wait(); - } - client->OnDisconnected(endpoint_id, false); - EXPECT_FALSE(client->IsConnectedToEndpoint(endpoint_id)); - } - - protected: - const ResultCallback kCallback{ - .result_cb = - [this](Status status) { - MutexLock lock(&mutex_); - result_ = status; - complete_ = true; - cond_.Notify(); - }, - }; - const std::string kServiceId = "service id"; - const std::string kRequestorName = "requestor name"; - const std::string kRemoteEndpointId = "remote endpoint id"; - const std::int64_t kPayloadId = UINT64_C(0x123456789ABCDEF0); - const ConnectionOptions kConnectionOptions{ - .strategy = Strategy::kP2pPointToPoint, - .auto_upgrade_bandwidth = true, - .enforce_topology_constraints = true, - }; - const OutOfBandConnectionMetadata kOutOfBandConnectionMetadata{ - .medium = Medium::BLUETOOTH, - .endpoint_id = kFakeInejctedEndpointId, - .endpoint_info = ByteArray(kFakeInjectedEndpointInfo), - .remote_bluetooth_mac_address = ByteArray(kFakeMacAddress), - }; - - std::vector<proto::connections::Medium> mediums_{ - proto::connections::Medium::BLUETOOTH}; - const ConnectionRequestInfo kConnectionRequestInfo{ - .endpoint_info = ByteArray{kRequestorName}, - .listener = ConnectionListener(), - }; - - DiscoveryListener discovery_listener_; - PayloadListener payload_listener_; - - Mutex mutex_; - ConditionVariable cond_{&mutex_}; - Status result_ ABSL_GUARDED_BY(mutex_) = {Status::kError}; - bool complete_ ABSL_GUARDED_BY(mutex_) = false; - MockServiceController* mock_; - ClientProxy client_; - - ServiceControllerRouter router_; -}; - -namespace { -TEST_F(ServiceControllerRouterTest, StartAdvertisingCalled) { - StartAdvertising(&client_, kServiceId, kConnectionOptions, - kConnectionRequestInfo, kCallback); -} - -TEST_F(ServiceControllerRouterTest, StopAdvertisingCalled) { - StartAdvertising(&client_, kServiceId, kConnectionOptions, - kConnectionRequestInfo, kCallback); - StopAdvertising(&client_, kCallback); -} - -TEST_F(ServiceControllerRouterTest, StartDiscoveryCalled) { - StartDiscovery(&client_, kServiceId, kConnectionOptions, discovery_listener_, - kCallback); -} - -TEST_F(ServiceControllerRouterTest, StopDiscoveryCalled) { - StartDiscovery(&client_, kServiceId, kConnectionOptions, discovery_listener_, - kCallback); - StopDiscovery(&client_, kCallback); -} - -TEST_F(ServiceControllerRouterTest, InjectEndpointCalled) { - StartDiscovery(&client_, kServiceId, kConnectionOptions, discovery_listener_, - kCallback); - InjectEndpoint(&client_, kServiceId, kOutOfBandConnectionMetadata, kCallback); - StopDiscovery(&client_, kCallback); -} - -TEST_F(ServiceControllerRouterTest, RequestConnectionCalled) { - // Either Advertising, or Discovery should be ongoing. - StartDiscovery(&client_, kServiceId, kConnectionOptions, discovery_listener_, - kCallback); - RequestConnection(&client_, kRemoteEndpointId, kConnectionRequestInfo, - kCallback); -} - -TEST_F(ServiceControllerRouterTest, AcceptConnectionCalled) { - // Either Adviertisng, or Discovery should be ongoing. - StartDiscovery(&client_, kServiceId, kConnectionOptions, discovery_listener_, - kCallback); - // Establish connection. - RequestConnection(&client_, kRemoteEndpointId, kConnectionRequestInfo, - kCallback); - // Now, we can accept connection. - AcceptConnection(&client_, kRemoteEndpointId, payload_listener_, kCallback); -} - -TEST_F(ServiceControllerRouterTest, RejectConnectionCalled) { - // Either Adviertisng, or Discovery should be ongoing. - StartDiscovery(&client_, kServiceId, kConnectionOptions, discovery_listener_, - kCallback); - // Establish connection. - RequestConnection(&client_, kRemoteEndpointId, kConnectionRequestInfo, - kCallback); - // Now, we can reject connection. - RejectConnection(&client_, kRemoteEndpointId, kCallback); -} - -TEST_F(ServiceControllerRouterTest, InitiateBandwidthUpgradeCalled) { - // Either Adviertisng, or Discovery should be ongoing. - StartDiscovery(&client_, kServiceId, kConnectionOptions, discovery_listener_, - kCallback); - // Establish connection. - RequestConnection(&client_, kRemoteEndpointId, kConnectionRequestInfo, - kCallback); - // Now, we can accept connection. - AcceptConnection(&client_, kRemoteEndpointId, payload_listener_, kCallback); - // Now we can change connection bandwidth. - InitiateBandwidthUpgrade(&client_, kRemoteEndpointId, kCallback); -} - -TEST_F(ServiceControllerRouterTest, SendPayloadCalled) { - // Either Adviertisng, or Discovery should be ongoing. - StartDiscovery(&client_, kServiceId, kConnectionOptions, discovery_listener_, - kCallback); - // Establish connection. - RequestConnection(&client_, kRemoteEndpointId, kConnectionRequestInfo, - kCallback); - // Now, we can accept connection. - AcceptConnection(&client_, kRemoteEndpointId, payload_listener_, kCallback); - // Now we can send payload. - SendPayload(&client_, std::vector<std::string>{kRemoteEndpointId}, - Payload{ByteArray("data")}, kCallback); -} - -TEST_F(ServiceControllerRouterTest, CancelPayloadCalled) { - // Either Adviertisng, or Discovery should be ongoing. - StartDiscovery(&client_, kServiceId, kConnectionOptions, discovery_listener_, - kCallback); - // Establish connection. - RequestConnection(&client_, kRemoteEndpointId, kConnectionRequestInfo, - kCallback); - // Now, we can accept connection. - AcceptConnection(&client_, kRemoteEndpointId, payload_listener_, kCallback); - // We have to know payload id, before we can cancel payload transfer. - // It is either after a call to SendPayload, or after receiving - // PayloadProgress callback. Let's assume we have it, and proceed. - CancelPayload(&client_, kPayloadId, kCallback); -} - -TEST_F(ServiceControllerRouterTest, DisconnectFromEndpointCalled) { - // Either Adviertisng, or Discovery should be ongoing. - StartDiscovery(&client_, kServiceId, kConnectionOptions, discovery_listener_, - kCallback); - // Establish connection. - RequestConnection(&client_, kRemoteEndpointId, kConnectionRequestInfo, - kCallback); - // Now, we can accept connection. - AcceptConnection(&client_, kRemoteEndpointId, payload_listener_, kCallback); - // We can disconnect at any time after RequestConnection. - DisconnectFromEndpoint(&client_, kRemoteEndpointId, kCallback); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/simulation_user.cc b/chromium/third_party/nearby/src/cpp/core/internal/simulation_user.cc deleted file mode 100644 index afeab13404b..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/simulation_user.cc +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/simulation_user.h" - -#include "absl/functional/bind_front.h" -#include "core/listeners.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/system_clock.h" - -namespace location { -namespace nearby { -namespace connections { - -void SimulationUser::OnConnectionInitiated(const std::string& endpoint_id, - const ConnectionResponseInfo& info, - bool is_outgoing) { - if (is_outgoing) { - NEARBY_LOG(INFO, "RequestConnection: initiated_cb called"); - } else { - NEARBY_LOG(INFO, "StartAdvertising: initiated_cb called"); - discovered_ = DiscoveredInfo{ - .endpoint_id = endpoint_id, - .endpoint_info = GetInfo(), - .service_id = service_id_, - }; - } - if (initiated_latch_) initiated_latch_->CountDown(); -} - -void SimulationUser::OnConnectionAccepted(const std::string& endpoint_id) { - if (accept_latch_) accept_latch_->CountDown(); -} - -void SimulationUser::OnConnectionRejected(const std::string& endpoint_id, - Status status) { - if (reject_latch_) reject_latch_->CountDown(); -} - -void SimulationUser::OnEndpointFound(const std::string& endpoint_id, - const ByteArray& endpoint_info, - const std::string& service_id) { - NEARBY_LOG(INFO, "Device discovered: id=%s", endpoint_id.c_str()); - discovered_ = DiscoveredInfo{ - .endpoint_id = endpoint_id, - .endpoint_info = endpoint_info, - .service_id = service_id, - }; - if (found_latch_) found_latch_->CountDown(); -} - -void SimulationUser::OnEndpointLost(const std::string& endpoint_id) { - if (lost_latch_) lost_latch_->CountDown(); -} - -void SimulationUser::OnPayload(const std::string& endpoint_id, - Payload payload) { - payload_ = std::move(payload); - if (payload_latch_) payload_latch_->CountDown(); -} - -void SimulationUser::OnPayloadProgress(const std::string& endpoint_id, - const PayloadProgressInfo& info) { - MutexLock lock(&progress_mutex_); - progress_info_ = info; - if (future_ && predicate_ && predicate_(info)) future_->Set(true); -} - -bool SimulationUser::WaitForProgress( - std::function<bool(const PayloadProgressInfo&)> predicate, - absl::Duration timeout) { - Future<bool> future; - { - MutexLock lock(&progress_mutex_); - if (predicate(progress_info_)) return true; - future_ = &future; - predicate_ = std::move(predicate); - } - auto response = future.Get(timeout); - { - MutexLock lock(&progress_mutex_); - future_ = nullptr; - predicate_ = nullptr; - } - return response.ok() && response.result(); -} - -void SimulationUser::StartAdvertising(const std::string& service_id, - CountDownLatch* latch) { - initiated_latch_ = latch; - service_id_ = service_id; - ConnectionListener listener = { - .initiated_cb = - std::bind(&SimulationUser::OnConnectionInitiated, this, - std::placeholders::_1, std::placeholders::_2, false), - .accepted_cb = - absl::bind_front(&SimulationUser::OnConnectionAccepted, this), - .rejected_cb = - absl::bind_front(&SimulationUser::OnConnectionRejected, this), - }; - EXPECT_TRUE(mgr_.StartAdvertising(&client_, service_id_, options_, - { - .endpoint_info = info_, - .listener = std::move(listener), - }) - .Ok()); -} - -void SimulationUser::StartDiscovery(const std::string& service_id, - CountDownLatch* latch) { - found_latch_ = latch; - EXPECT_TRUE( - mgr_.StartDiscovery(&client_, service_id, options_, - { - .endpoint_found_cb = absl::bind_front( - &SimulationUser::OnEndpointFound, this), - .endpoint_lost_cb = absl::bind_front( - &SimulationUser::OnEndpointLost, this), - }) - .Ok()); -} - -void SimulationUser::InjectEndpoint( - const std::string& service_id, - const OutOfBandConnectionMetadata& metadata) { - mgr_.InjectEndpoint(&client_, service_id, metadata); -} - -void SimulationUser::RequestConnection(CountDownLatch* latch) { - initiated_latch_ = latch; - ConnectionListener listener = { - .initiated_cb = - std::bind(&SimulationUser::OnConnectionInitiated, this, - std::placeholders::_1, std::placeholders::_2, true), - .accepted_cb = - absl::bind_front(&SimulationUser::OnConnectionAccepted, this), - .rejected_cb = - absl::bind_front(&SimulationUser::OnConnectionRejected, this), - }; - client_.AddCancellationFlag(discovered_.endpoint_id); - EXPECT_TRUE( - mgr_.RequestConnection(&client_, discovered_.endpoint_id, - { - .endpoint_info = discovered_.endpoint_info, - .listener = std::move(listener), - }, - connection_options_) - .Ok()); -} - -void SimulationUser::AcceptConnection(CountDownLatch* latch) { - accept_latch_ = latch; - PayloadListener listener = { - .payload_cb = absl::bind_front(&SimulationUser::OnPayload, this), - .payload_progress_cb = - absl::bind_front(&SimulationUser::OnPayloadProgress, this), - }; - EXPECT_TRUE(mgr_.AcceptConnection(&client_, discovered_.endpoint_id, - std::move(listener)) - .Ok()); -} - -void SimulationUser::RejectConnection(CountDownLatch* latch) { - reject_latch_ = latch; - EXPECT_TRUE(mgr_.RejectConnection(&client_, discovered_.endpoint_id).Ok()); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/simulation_user.h b/chromium/third_party/nearby/src/cpp/core/internal/simulation_user.h deleted file mode 100644 index 6e62a6be6fb..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/simulation_user.h +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_SIMULATION_USER_H_ -#define CORE_INTERNAL_SIMULATION_USER_H_ - -#include <string> - -#include "gtest/gtest.h" -#include "core/internal/bwu_manager.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel_manager.h" -#include "core/internal/endpoint_manager.h" -#include "core/internal/injected_bluetooth_device_store.h" -#include "core/internal/payload_manager.h" -#include "core/internal/pcp_manager.h" -#include "core/options.h" -#include "platform/base/medium_environment.h" -#include "platform/public/condition_variable.h" -#include "platform/public/count_down_latch.h" -#include "platform/public/future.h" - -// Test-only class to help run end-to-end simulations for nearby connections -// protocol. -// -// This is a "standalone" version of PcpManager. It can run independently, -// provided MediumEnvironment has adequate support for all medium types in use. -namespace location { -namespace nearby { -namespace connections { - -class SimulationUser { - public: - struct DiscoveredInfo { - std::string endpoint_id; - ByteArray endpoint_info; - std::string service_id; - - bool Empty() const { return endpoint_id.empty(); } - void Clear() { endpoint_id.clear(); } - }; - - explicit SimulationUser( - const std::string& device_name, - BooleanMediumSelector allowed = BooleanMediumSelector()) - : connection_options_{ - .keep_alive_interval_millis = FeatureFlags::GetInstance() - .GetFlags() - .keep_alive_interval_millis, - .keep_alive_timeout_millis = FeatureFlags::GetInstance() - .GetFlags() - .keep_alive_timeout_millis, - }, - info_{ByteArray{device_name}}, - options_{ - .strategy = Strategy::kP2pCluster, - .allowed = allowed, - } {} - virtual ~SimulationUser() { Stop(); } - void Stop() { - pm_.DisconnectFromEndpointManager(); - mgr_.DisconnectFromEndpointManager(); - bwu_.Shutdown(); - } - - // Calls PcpManager::StartAdvertising. - // If latch is provided, will call latch->CountDown() in the initiated_cb - // callback. - void StartAdvertising(const std::string& service_id, CountDownLatch* latch); - - // Calls PcpManager::StartDiscovery. - // If latch is provided, will call latch->CountDown() in the endpoint_found_cb - // callback. - void StartDiscovery(const std::string& service_id, CountDownLatch* latch); - - // Calls PcpManager::InjectEndpoint. - void InjectEndpoint(const std::string& service_id, - const OutOfBandConnectionMetadata& metadata); - - // Calls PcpManager::RequestConnection. - // If latch is provided, latch->CountDown() will be called in the initiated_cb - // callback. - void RequestConnection(CountDownLatch* latch); - - // Calls PcpManager::AcceptConnection. - // If latch is provided, latch->CountDown() will be called in the accepted_cb - // callback. - void AcceptConnection(CountDownLatch* latch); - - // Calls PcpManager::RejectConnection. - // If latch is provided, latch->CountDown() will be called in the rejected_cb - // callback. - void RejectConnection(CountDownLatch* latch); - - // Unlike acceptance, rejection does not have to be mutual, in order to work. - // This method will allow to synchronize on the remote rejection, without - // performing a local rejection. - // latch.CountDown() will be called in the rejected_cb callback. - void ExpectRejectedConnection(CountDownLatch& latch) { - reject_latch_ = &latch; - } - - void ExpectPayload(CountDownLatch& latch) { payload_latch_ = &latch; } - - const DiscoveredInfo& GetDiscovered() const { return discovered_; } - ByteArray GetInfo() const { return info_; } - - bool WaitForProgress(std::function<bool(const PayloadProgressInfo&)> pred, - absl::Duration timeout); - - protected: - // ConnectionListener callbacks - void OnConnectionInitiated(const std::string& endpoint_id, - const ConnectionResponseInfo& info, - bool is_outgoing); - void OnConnectionAccepted(const std::string& endpoint_id); - void OnConnectionRejected(const std::string& endpoint_id, Status status); - - // DiscoveryListener callbacks - void OnEndpointFound(const std::string& endpoint_id, - const ByteArray& endpoint_info, - const std::string& service_id); - void OnEndpointLost(const std::string& endpoint_id); - - // PayloadListener callbacks - void OnPayload(const std::string& endpoint_id, Payload payload); - void OnPayloadProgress(const std::string& endpoint_id, - const PayloadProgressInfo& info); - - std::string service_id_; - DiscoveredInfo discovered_; - ConnectionOptions connection_options_; - Mutex progress_mutex_; - ConditionVariable progress_sync_{&progress_mutex_}; - PayloadProgressInfo progress_info_; - Payload payload_; - CountDownLatch* initiated_latch_ = nullptr; - CountDownLatch* accept_latch_ = nullptr; - CountDownLatch* reject_latch_ = nullptr; - CountDownLatch* found_latch_ = nullptr; - CountDownLatch* lost_latch_ = nullptr; - CountDownLatch* payload_latch_ = nullptr; - Future<bool>* future_ = nullptr; - std::function<bool(const PayloadProgressInfo&)> predicate_; - ByteArray info_; - Mediums mediums_; - ConnectionOptions options_; - ClientProxy client_; - EndpointChannelManager ecm_; - EndpointManager em_{&ecm_}; - BwuManager bwu_{mediums_, em_, ecm_, {}, {}}; - InjectedBluetoothDeviceStore injected_bluetooth_device_store_; - PcpManager mgr_{mediums_, ecm_, em_, bwu_, injected_bluetooth_device_store_}; - PayloadManager pm_{em_}; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_SIMULATION_USER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/webrtc_bwu_handler.cc b/chromium/third_party/nearby/src/cpp/core/internal/webrtc_bwu_handler.cc deleted file mode 100644 index c3b536de0a9..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/webrtc_bwu_handler.cc +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/webrtc_bwu_handler.h" - -#include <string> - -#include "absl/functional/bind_front.h" -#include "core/internal/client_proxy.h" -#include "core/internal/mediums/utils.h" -#include "core/internal/mediums/webrtc_peer_id.h" -#include "core/internal/offline_frames.h" -#include "core/internal/webrtc_endpoint_channel.h" - -namespace location { -namespace nearby { -namespace connections { - -WebrtcBwuHandler::WebrtcBwuHandler(Mediums& mediums, - EndpointChannelManager& channel_manager, - BwuNotifications notifications) - : BaseBwuHandler(channel_manager, std::move(notifications)), - mediums_(mediums) {} - -void WebrtcBwuHandler::Revert() { - for (const auto& service_id : active_service_ids_) { - webrtc_.StopAcceptingConnections(service_id); - } - active_service_ids_.clear(); - - NEARBY_LOG(INFO, "WebrtcBwuHandler successfully reverted state."); -} - -// Accept Connection Callback. -// Notifies that the remote party called WebRtc::Connect() -// for this socket. -void WebrtcBwuHandler::OnIncomingWebrtcConnection( - ClientProxy* client, const std::string& upgrade_service_id, - mediums::WebRtcSocketWrapper socket) { - std::string service_id = Utils::UnwrapUpgradeServiceId(upgrade_service_id); - auto channel = std::make_unique<WebRtcEndpointChannel>(service_id, socket); - auto webrtc_socket = - std::make_unique<WebrtcIncomingSocket>(service_id, socket); - std::unique_ptr<IncomingSocketConnection> connection( - new IncomingSocketConnection{std::move(webrtc_socket), - std::move(channel)}); - - bwu_notifications_.incoming_connection_cb(client, std::move(connection)); -} - -// Called by BWU initiator. Set up WebRTC upgraded medium for this endpoint, -// and returns a upgrade path info (PeerId, LocationHint) for remote party to -// perform discovery. -ByteArray WebrtcBwuHandler::InitializeUpgradedMediumForEndpoint( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id) { - // Use wrapped service ID to avoid have the same ID with the one for - // startAdvertising. Otherwise, the listening request would be ignored because - // the medium already start accepting the connection because the client not - // stop the advertising yet. - std::string upgrade_service_id = Utils::WrapUpgradeServiceId(service_id); - - LocationHint location_hint = - Utils::BuildLocationHint(webrtc_.GetDefaultCountryCode()); - - mediums::WebrtcPeerId self_id{mediums::WebrtcPeerId::FromRandom()}; - if (!webrtc_.IsAcceptingConnections(service_id)) { - if (!webrtc_.StartAcceptingConnections( - upgrade_service_id, self_id, location_hint, - { - .accepted_cb = absl::bind_front( - &WebrtcBwuHandler::OnIncomingWebrtcConnection, this, client, - upgrade_service_id), - })) { - NEARBY_LOG(ERROR, - "WebRtcBwuHandler couldn't initiate the WEB_RTC upgrade for " - "endpoint %s because it failed to start listening for " - "incoming WebRTC connections.", - endpoint_id.c_str()); - return {}; - } - NEARBY_LOG(INFO, - "WebRtcBwuHandler successfully started listening for incoming " - "WebRTC connections while upgrading endpoint %s", - endpoint_id.c_str()); - } - - // cache service ID to revert - active_service_ids_.emplace(upgrade_service_id); - - return parser::ForBwuWebrtcPathAvailable(self_id.GetId(), location_hint); -} - -// Called by BWU target. Retrieves a new medium info from incoming message, -// and establishes connection over WebRTC using this info. -std::unique_ptr<EndpointChannel> -WebrtcBwuHandler::CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) { - const UpgradePathInfo::WebRtcCredentials& web_rtc_credentials = - upgrade_path_info.web_rtc_credentials(); - mediums::WebrtcPeerId peer_id(web_rtc_credentials.peer_id()); - - LocationHint location_hint; - location_hint.set_format(LocationStandard::UNKNOWN); - if (web_rtc_credentials.has_location_hint()) { - location_hint = web_rtc_credentials.location_hint(); - } - NEARBY_LOG(INFO, - "WebRtcBwuHandler is attempting to connect to remote peer %s, " - "location hint %s", - peer_id.GetId().c_str(), location_hint.DebugString().c_str()); - - mediums::WebRtcSocketWrapper socket = - webrtc_.Connect(service_id, peer_id, location_hint, - client->GetCancellationFlag(endpoint_id)); - if (!socket.IsValid()) { - NEARBY_LOG(ERROR, - "WebRtcBwuHandler failed to connect to remote peer (%s) on " - "endpoint %s, aborting upgrade.", - peer_id.GetId().c_str(), endpoint_id.c_str()); - return nullptr; - } - - NEARBY_LOG(INFO, - "WebRtcBwuHandler successfully connected to remote " - "peer (%s) while upgrading endpoint %s.", - peer_id.GetId().c_str(), endpoint_id.c_str()); - - // Create a new WebRtcEndpointChannel. - auto channel = std::make_unique<WebRtcEndpointChannel>(service_id, socket); - if (channel == nullptr) { - socket.Close(); - NEARBY_LOG(ERROR, - "WebRtcBwuHandler failed to create new EndpointChannel for " - "outgoing socket %p, aborting upgrade.", - &socket.GetImpl()); - } - - return channel; -} - -void WebrtcBwuHandler::OnEndpointDisconnect(ClientProxy* client, - const std::string& endpoint_id) {} - -WebrtcBwuHandler::WebrtcIncomingSocket::WebrtcIncomingSocket( - const std::string& name, mediums::WebRtcSocketWrapper socket) - : name_(name), socket_(socket) {} - -void WebrtcBwuHandler::WebrtcIncomingSocket::Close() { socket_.Close(); } - -std::string WebrtcBwuHandler::WebrtcIncomingSocket::ToString() { return name_; } - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/webrtc_bwu_handler.h b/chromium/third_party/nearby/src/cpp/core/internal/webrtc_bwu_handler.h deleted file mode 100644 index 6587b643e2b..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/webrtc_bwu_handler.h +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_WEBRTC_BWU_HANDLER_H_ -#define CORE_INTERNAL_WEBRTC_BWU_HANDLER_H_ - -#include "core/internal/base_bwu_handler.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel_manager.h" -#include "core/internal/mediums/mediums.h" -#include "core/internal/mediums/webrtc_socket_wrapper.h" - -namespace location { -namespace nearby { -namespace connections { - -using BwuNegotiationFrame = BandwidthUpgradeNegotiationFrame; - -// Defines the set of methods that need to be implemented to handle the -// per-Medium-specific operations needed to upgrade an EndpointChannel. -class WebrtcBwuHandler : public BaseBwuHandler { - public: - WebrtcBwuHandler(Mediums& mediums, EndpointChannelManager& channel_manager, - BwuNotifications notifications); - ~WebrtcBwuHandler() override = default; - - private: - // Called by the Initiator to setup the upgraded medium for this endpoint (if - // that hasn't already been done), and returns a serialized UpgradePathInfo - // that can be sent to the Responder. - // @BwuHandlerThread - ByteArray InitializeUpgradedMediumForEndpoint( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id) override; - // Called to revert any state changed by the Initiator to setup the upgraded - // medium for an endpoint. - // @BwuHandlerThread - void Revert() override; - - // Called by the Responder to setup the upgraded medium for this endpoint (if - // that hasn't already been done) using the UpgradePathInfo sent by the - // Initiator, and returns a new EndpointChannel for the upgraded medium. - // @BwuHandlerThread - std::unique_ptr<EndpointChannel> CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) override; - // Returns the upgrade medium of the BwuHandler. - // @BwuHandlerThread - Medium GetUpgradeMedium() const override { return Medium::WEB_RTC; } - - void OnIncomingWebrtcConnection(ClientProxy* client, - const std::string& service_id, - mediums::WebRtcSocketWrapper socket); - - void OnEndpointDisconnect(ClientProxy* client, - const std::string& endpoint_id) override; - - std::string GetCountryCode(); - - class WebrtcIncomingSocket : public BwuHandler::IncomingSocket { - public: - explicit WebrtcIncomingSocket(const std::string& name, - mediums::WebRtcSocketWrapper socket); - ~WebrtcIncomingSocket() override = default; - - std::string ToString() override; - void Close() override; - - private: - std::string name_; - mediums::WebRtcSocketWrapper socket_; - }; - - Mediums& mediums_; - mediums::WebRtc& webrtc_{mediums_.GetWebRtc()}; - absl::flat_hash_set<std::string> active_service_ids_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_WEBRTC_BWU_HANDLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/webrtc_endpoint_channel.cc b/chromium/third_party/nearby/src/cpp/core/internal/webrtc_endpoint_channel.cc deleted file mode 100644 index 18d7c701cc9..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/webrtc_endpoint_channel.cc +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/webrtc_endpoint_channel.h" - -namespace location { -namespace nearby { -namespace connections { - -WebRtcEndpointChannel::WebRtcEndpointChannel( - const std::string& channel_name, mediums::WebRtcSocketWrapper socket) - : BaseEndpointChannel(channel_name, &socket.GetInputStream(), - &socket.GetOutputStream()), - webrtc_socket_(std::move(socket)) {} - -proto::connections::Medium WebRtcEndpointChannel::GetMedium() const { - return proto::connections::Medium::WEB_RTC; -} - -void WebRtcEndpointChannel::CloseImpl() { webrtc_socket_.Close(); } - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/webrtc_endpoint_channel.h b/chromium/third_party/nearby/src/cpp/core/internal/webrtc_endpoint_channel.h deleted file mode 100644 index 5515ab6e38f..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/webrtc_endpoint_channel.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_WEBRTC_ENDPOINT_CHANNEL_H_ -#define CORE_INTERNAL_WEBRTC_ENDPOINT_CHANNEL_H_ - -#include "core/internal/base_endpoint_channel.h" -#include "core/internal/mediums/webrtc_socket_wrapper.h" - -namespace location { -namespace nearby { -namespace connections { - -class WebRtcEndpointChannel final : public BaseEndpointChannel { - public: - WebRtcEndpointChannel(const std::string& channel_name, - mediums::WebRtcSocketWrapper webrtc_socket); - - proto::connections::Medium GetMedium() const override; - - private: - void CloseImpl() override; - - mediums::WebRtcSocketWrapper webrtc_socket_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_WEBRTC_ENDPOINT_CHANNEL_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_bwu_handler.cc b/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_bwu_handler.cc deleted file mode 100644 index 9b8eeedb96a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_bwu_handler.cc +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/wifi_lan_bwu_handler.h" - -#include <locale> -#include <string> - -#include "absl/functional/bind_front.h" -#include "core/internal/client_proxy.h" -#include "core/internal/mediums/utils.h" -#include "core/internal/offline_frames.h" -#include "core/internal/wifi_lan_endpoint_channel.h" -#include "platform/public/wifi_lan.h" - -namespace location { -namespace nearby { -namespace connections { - -WifiLanBwuHandler::WifiLanBwuHandler(Mediums& mediums, - EndpointChannelManager& channel_manager, - BwuNotifications notifications) - : BaseBwuHandler(channel_manager, std::move(notifications)), - mediums_(mediums) {} - -// Called by BWU initiator. Set up WifiLan upgraded medium for this endpoint, -// and returns a upgrade path info (ip address, port) for remote party to -// perform discovery. -ByteArray WifiLanBwuHandler::InitializeUpgradedMediumForEndpoint( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id) { - // Use wrapped service ID to avoid have the same ID with the one for - // startAdvertising. Otherwise, the listening request would be ignored because - // the medium already start accepting the connection because the client not - // stop the advertising yet. - std::string upgrade_service_id = Utils::WrapUpgradeServiceId(service_id); - - auto credential = wifi_lan_medium_.GetCredentials(upgrade_service_id); - auto ip_address = credential.first; - auto port = credential.second; - if (ip_address.empty()) { - NEARBY_LOGS(INFO) - << "WifiLanBwuHandler couldn't initiate the wifi_lan upgrade for " - "endpoint " - << endpoint_id - << " because the wifi_lan ip address were unable to be obtained."; - return {}; - } - - if (!wifi_lan_medium_.IsAcceptingConnections(upgrade_service_id)) { - if (!wifi_lan_medium_.StartAcceptingConnections( - upgrade_service_id, - { - .accepted_cb = absl::bind_front( - &WifiLanBwuHandler::OnIncomingWifiLanConnection, this, - client, service_id), - })) { - NEARBY_LOGS(ERROR) - << "WifiLanBwuHandler couldn't initiate the WifiLan upgrade for " - "endpoint " - << endpoint_id - << " because it failed to start listening for " - "incoming WifiLan connections."; - return {}; - } - NEARBY_LOGS(INFO) - << "WifiLanBwuHandler successfully started listening for incoming " - "WifiLan connections while upgrading endpoint " - << endpoint_id; - } - - // cache service ID to revert - active_service_ids_.insert(upgrade_service_id); - - return parser::ForBwuWifiLanPathAvailable(ip_address, port); -} - -void WifiLanBwuHandler::Revert() { - for (const std::string& service_id : active_service_ids_) { - wifi_lan_medium_.StopAcceptingConnections(service_id); - } - active_service_ids_.clear(); - - NEARBY_LOG(INFO, "WifiLanBwuHandler successfully reverted all states."); -} - -// Called by BWU target. Retrieves a new medium info from incoming message, -// and establishes connection over WifiLan using this info. -std::unique_ptr<EndpointChannel> -WifiLanBwuHandler::CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, const UpgradePathInfo& upgrade_path_info) { - if (!upgrade_path_info.has_wifi_lan_socket()) { - return nullptr; - } - const UpgradePathInfo::WifiLanSocket& upgrade_path_info_socket = - upgrade_path_info.wifi_lan_socket(); - if (!upgrade_path_info_socket.has_ip_address() || - !upgrade_path_info_socket.has_wifi_port()) { - NEARBY_LOG(ERROR, "WifiLanBwuHandler failed to parse UpgradePathInfo."); - return nullptr; - } - - const std::string& ip_address = upgrade_path_info_socket.ip_address(); - std::int32_t port = upgrade_path_info_socket.wifi_port(); - - NEARBY_LOGS(VERBOSE) << "WifiLanBwuHandler is attempting to connect to " - "available WifiLan service (" - << ip_address << ":" << port << ") for endpoint " - << endpoint_id; - - WifiLanSocket socket = wifi_lan_medium_.Connect( - service_id, ip_address, port, client->GetCancellationFlag(endpoint_id)); - if (!socket.IsValid()) { - NEARBY_LOGS(ERROR) - << "WifiLanBwuHandler failed to connect to the WifiLan service (" - << ip_address << ":" << port << ") for endpoint " << endpoint_id; - return nullptr; - } - - NEARBY_LOGS(VERBOSE) - << "WifiLanBwuHandler successfully connected to WifiLan service (" - << ip_address << ":" << port << ") while upgrading endpoint " - << endpoint_id; - - // Create a new WifiLanEndpointChannel. - auto channel = absl::make_unique<WifiLanEndpointChannel>(service_id, socket); - if (channel == nullptr) { - NEARBY_LOGS(ERROR) << "WifiLanBwuHandler failed to create WifiLan endpoint " - "channel to the WifiLan service (" - << ip_address << ":" << port << ") for endpoint " - << endpoint_id; - socket.Close(); - return nullptr; - } - - return channel; -} - -// Accept Connection Callback. -void WifiLanBwuHandler::OnIncomingWifiLanConnection( - ClientProxy* client, const std::string& service_id, WifiLanSocket socket) { - auto channel = absl::make_unique<WifiLanEndpointChannel>(service_id, socket); - std::unique_ptr<IncomingSocketConnection> connection( - new IncomingSocketConnection{ - .socket = - absl::make_unique<WifiLanIncomingSocket>(service_id, socket), - .channel = std::move(channel), - }); - bwu_notifications_.incoming_connection_cb(client, std::move(connection)); -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_bwu_handler.h b/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_bwu_handler.h deleted file mode 100644 index c16fbe74c17..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_bwu_handler.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_WIFI_LAN_BWU_HANDLER_H_ -#define CORE_INTERNAL_WIFI_LAN_BWU_HANDLER_H_ - -#include "core/internal/base_bwu_handler.h" -#include "core/internal/client_proxy.h" -#include "core/internal/endpoint_channel_manager.h" -#include "core/internal/mediums/mediums.h" - -namespace location { -namespace nearby { -namespace connections { - -// Defines the set of methods that need to be implemented to handle the -// per-Medium-specific operations needed to upgrade an EndpointChannel. -class WifiLanBwuHandler : public BaseBwuHandler { - public: - WifiLanBwuHandler(Mediums& mediums, EndpointChannelManager& channel_manager, - BwuNotifications notifications); - ~WifiLanBwuHandler() override = default; - - private: - ByteArray InitializeUpgradedMediumForEndpoint( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id) override; - - void Revert() override; - - std::unique_ptr<EndpointChannel> CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const UpgradePathInfo& upgrade_path_info) override; - - Medium GetUpgradeMedium() const override { return Medium::WIFI_LAN; } - - void OnEndpointDisconnect(ClientProxy* client, - const std::string& endpoint_id) override {} - - void OnIncomingWifiLanConnection(ClientProxy* client, - const std::string& service_id, - WifiLanSocket socket); - - class WifiLanIncomingSocket : public BwuHandler::IncomingSocket { - public: - explicit WifiLanIncomingSocket(const std::string& name, - WifiLanSocket socket) - : name_(name), socket_(socket) {} - ~WifiLanIncomingSocket() override = default; - - std::string ToString() override { return name_; } - void Close() override { socket_.Close(); } - - private: - std::string name_; - WifiLanSocket socket_; - }; - - Mediums& mediums_; - WifiLan& wifi_lan_medium_{mediums_.GetWifiLan()}; - absl::flat_hash_set<std::string> active_service_ids_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_WIFI_LAN_BWU_HANDLER_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_endpoint_channel.cc b/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_endpoint_channel.cc deleted file mode 100644 index ec7503efd15..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_endpoint_channel.cc +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/wifi_lan_endpoint_channel.h" - -#include <string> - -#include "platform/public/logging.h" -#include "platform/public/wifi_lan.h" - -namespace location { -namespace nearby { -namespace connections { - -WifiLanEndpointChannel::WifiLanEndpointChannel(const std::string& channel_name, - WifiLanSocket socket) - : BaseEndpointChannel(channel_name, &socket.GetInputStream(), - &socket.GetOutputStream()), - socket_(std::move(socket)) {} - -proto::connections::Medium WifiLanEndpointChannel::GetMedium() const { - return proto::connections::Medium::WIFI_LAN; -} - -void WifiLanEndpointChannel::CloseImpl() { - auto status = socket_.Close(); - if (!status.Ok()) { - NEARBY_LOGS(INFO) - << "Failed to close underlying socket for WifiLanEndpointChannel " - << GetName() << " : exception = " << status.value; - } -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_endpoint_channel.h b/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_endpoint_channel.h deleted file mode 100644 index e7c79f9ceb4..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_endpoint_channel.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_WIFI_LAN_ENDPOINT_CHANNEL_H_ -#define CORE_INTERNAL_WIFI_LAN_ENDPOINT_CHANNEL_H_ - -#include "core/internal/base_endpoint_channel.h" -#include "platform/public/wifi_lan.h" - -namespace location { -namespace nearby { -namespace connections { - -class WifiLanEndpointChannel final : public BaseEndpointChannel { - public: - // Creates both outgoing and incoming WifiLan channels. - WifiLanEndpointChannel(const std::string& channel_name, WifiLanSocket socket); - - proto::connections::Medium GetMedium() const override; - - private: - void CloseImpl() override; - - WifiLanSocket socket_; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_WIFI_LAN_ENDPOINT_CHANNEL_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_service_info.cc b/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_service_info.cc deleted file mode 100644 index e3bfcf71126..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_service_info.cc +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/wifi_lan_service_info.h" - -#include <inttypes.h> - -#include <cstring> -#include <utility> - -#include "absl/strings/str_cat.h" -#include "platform/base/base64_utils.h" -#include "platform/base/base_input_stream.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { - -// These definitions are necessary before C++17. -constexpr absl::string_view WifiLanServiceInfo::kKeyEndpointInfo; -constexpr std::uint32_t WifiLanServiceInfo::kServiceIdHashLength; -constexpr int WifiLanServiceInfo::kMaxEndpointInfoLength; - -WifiLanServiceInfo::WifiLanServiceInfo(Version version, Pcp pcp, - absl::string_view endpoint_id, - const ByteArray& service_id_hash, - const ByteArray& endpoint_info, - const ByteArray& uwb_address, - WebRtcState web_rtc_state) { - if (version != Version::kV1 || endpoint_id.empty() || - endpoint_id.length() != kEndpointIdLength || - service_id_hash.size() != kServiceIdHashLength || - endpoint_info.size() > kMaxEndpointInfoLength) { - return; - } - switch (pcp) { - case Pcp::kP2pCluster: // Fall through - case Pcp::kP2pStar: // Fall through - case Pcp::kP2pPointToPoint: - break; - default: - return; - } - - version_ = version; - pcp_ = pcp; - service_id_hash_ = service_id_hash; - endpoint_id_ = std::string(endpoint_id); - endpoint_info_ = endpoint_info; - uwb_address_ = uwb_address; - web_rtc_state_ = web_rtc_state; -} - -WifiLanServiceInfo::WifiLanServiceInfo(const NsdServiceInfo& nsd_service_info) { - auto txt_endpoint_info_name = - nsd_service_info.GetTxtRecord(std::string(kKeyEndpointInfo)); - if (!txt_endpoint_info_name.empty()) { - endpoint_info_ = Base64Utils::Decode(txt_endpoint_info_name); - if (endpoint_info_.size() > kMaxEndpointInfoLength) { - NEARBY_LOG(INFO, - "Cannot deserialize EndpointInfo: expecting endpoint info " - "max %d raw bytes, got %" PRIu64, - kMaxEndpointInfoLength, endpoint_info_.size()); - return; - } - } - - auto service_info_name = nsd_service_info.GetServiceName(); - ByteArray service_info_bytes = Base64Utils::Decode(service_info_name); - if (service_info_bytes.Empty()) { - NEARBY_LOG( - INFO, - "Cannot deserialize WifiLanServiceInfo: failed Base64 decoding of %s", - std::string(service_info_name).c_str()); - return; - } - - if (service_info_bytes.size() < kMinLanServiceNameLength) { - NEARBY_LOG(INFO, - "Cannot deserialize WifiLanServiceInfo: expecting min %d raw " - "bytes, got %" PRIu64, - kMinLanServiceNameLength, service_info_bytes.size()); - return; - } - - BaseInputStream base_input_stream{service_info_bytes}; - // The first 1 byte is supposed to be the version and pcp. - auto version_and_pcp_byte = static_cast<char>(base_input_stream.ReadUint8()); - // The upper 3 bits are supposed to be the version. - version_ = - static_cast<Version>((version_and_pcp_byte & kVersionBitmask) >> 5); - if (version_ != Version::kV1) { - NEARBY_LOG(INFO, - "Cannot deserialize WifiLanServiceInfo: unsupported Version %d", - version_); - return; - } - // The lower 5 bits are supposed to be the Pcp. - pcp_ = static_cast<Pcp>(version_and_pcp_byte & kPcpBitmask); - switch (pcp_) { - case Pcp::kP2pCluster: // Fall through - case Pcp::kP2pStar: // Fall through - case Pcp::kP2pPointToPoint: - break; - default: - NEARBY_LOG(INFO, - "Cannot deserialize WifiLanServiceInfo: unsupported V1 PCP %d", - pcp_); - } - - // The next 4 bytes are supposed to be the endpoint_id. - endpoint_id_ = std::string{base_input_stream.ReadBytes(kEndpointIdLength)}; - - // The next 3 bytes are supposed to be the service_id_hash. - service_id_hash_ = base_input_stream.ReadBytes(kServiceIdHashLength); - - // The next 1 byte is supposed to be the length of the uwb_address. If - // available, continues to deserialize UWB address and extra field of WebRtc - // state. - if (base_input_stream.IsAvailable(1)) { - std::uint32_t expected_uwb_address_length = base_input_stream.ReadUint8(); - // If the length of uwb_address is not zero, then retrieve it. - if (expected_uwb_address_length != 0) { - uwb_address_ = base_input_stream.ReadBytes(expected_uwb_address_length); - if (uwb_address_.Empty() || - uwb_address_.size() != expected_uwb_address_length) { - NEARBY_LOG(INFO, - "Cannot deserialize WifiLanServiceInfo: expected " - "uwbAddress size to be %d bytes, got %" PRIu64, - expected_uwb_address_length, uwb_address_.size()); - // Clear enpoint_id for validity. - endpoint_id_.clear(); - return; - } - } - - // The next 1 byte is extra field. - web_rtc_state_ = WebRtcState::kUndefined; - if (base_input_stream.IsAvailable(kExtraFieldLength)) { - auto extra_field = static_cast<char>(base_input_stream.ReadUint8()); - web_rtc_state_ = (extra_field & kWebRtcConnectableFlagBitmask) == 1 - ? WebRtcState::kConnectable - : WebRtcState::kUnconnectable; - } - } -} - -WifiLanServiceInfo::operator NsdServiceInfo() const { - if (!IsValid()) { - return {}; - } - - // The upper 3 bits are the Version. - auto version_and_pcp_byte = static_cast<char>( - (static_cast<uint32_t>(Version::kV1) << 5) & kVersionBitmask); - // The lower 5 bits are the PCP. - version_and_pcp_byte |= - static_cast<char>(static_cast<uint32_t>(pcp_) & kPcpBitmask); - - std::string out = absl::StrCat(std::string(1, version_and_pcp_byte), - endpoint_id_, std::string(service_id_hash_)); - - // The next bytes are UWB address field. - if (!uwb_address_.Empty()) { - absl::StrAppend(&out, std::string(1, uwb_address_.size())); - absl::StrAppend(&out, std::string(uwb_address_)); - } else { - // Write UWB address with length 0 to be able to read the next field, which - // needs to be appended. - if (web_rtc_state_ != WebRtcState::kUndefined) - absl::StrAppend(&out, std::string(1, uwb_address_.size())); - } - - // The next 1 byte is extra field. - if (web_rtc_state_ != WebRtcState::kUndefined) { - int web_rtc_connectable_flag = - (web_rtc_state_ == WebRtcState::kConnectable) ? 1 : 0; - char field_byte = static_cast<char>(web_rtc_connectable_flag) & - kWebRtcConnectableFlagBitmask; - absl::StrAppend(&out, std::string(1, field_byte)); - } - - NsdServiceInfo nsd_service_info; - nsd_service_info.SetServiceName( - Base64Utils::Encode(ByteArray{std::move(out)})); - nsd_service_info.SetTxtRecord(std::string(kKeyEndpointInfo), - Base64Utils::Encode(endpoint_info_)); - return nsd_service_info; -} - -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_service_info.h b/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_service_info.h deleted file mode 100644 index 943fe51db20..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_service_info.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_WIFI_LAN_SERVICE_INFO_H_ -#define CORE_INTERNAL_WIFI_LAN_SERVICE_INFO_H_ - -#include <cstdint> - -#include "absl/strings/string_view.h" -#include "core/internal/base_pcp_handler.h" -#include "core/internal/pcp.h" -#include "platform/base/byte_array.h" -#include "platform/base/nsd_service_info.h" - -namespace location { -namespace nearby { -namespace connections { - -// Represents the format of the WifiLan service info used in Advertising + -// Discovery. -// -// See go/nearby-offline-data-interchange-formats for the specification. -class WifiLanServiceInfo { - public: - // Versions of the WifiLanServiceInfo. - enum class Version { - kUndefined = 0, - kV1 = 1, - }; - - // The key of TXTRecord for EndpointInfo. - static constexpr absl::string_view kKeyEndpointInfo{"n"}; - static constexpr std::uint32_t kServiceIdHashLength = 3; - static constexpr int kMaxEndpointInfoLength = 131; - - WifiLanServiceInfo() = default; - WifiLanServiceInfo(Version version, Pcp pcp, absl::string_view endpoint_id, - const ByteArray& service_id_hash, - const ByteArray& endpoint_info, - const ByteArray& uwb_address, WebRtcState web_rtc_state); - - // Constructs WifiLanServiceInfo through NsdServiceInfo. - explicit WifiLanServiceInfo(const NsdServiceInfo& nsd_service_info); - WifiLanServiceInfo(const WifiLanServiceInfo&) = default; - WifiLanServiceInfo& operator=(const WifiLanServiceInfo&) = default; - WifiLanServiceInfo(WifiLanServiceInfo&&) = default; - WifiLanServiceInfo& operator=(WifiLanServiceInfo&&) = default; - ~WifiLanServiceInfo() = default; - - explicit operator NsdServiceInfo() const; - - bool IsValid() const { return !endpoint_id_.empty(); } - Version GetVersion() const { return version_; } - Pcp GetPcp() const { return pcp_; } - std::string GetEndpointId() const { return endpoint_id_; } - ByteArray GetEndpointInfo() const { return endpoint_info_; } - ByteArray GetServiceIdHash() const { return service_id_hash_; } - ByteArray GetUwbAddress() const { return uwb_address_; } - WebRtcState GetWebRtcState() const { return web_rtc_state_; } - - private: - static constexpr int kMinLanServiceNameLength = 9; - static constexpr int kEndpointIdLength = 4; - static constexpr int kUwbAddressLengthSize = 1; - static constexpr int kExtraFieldLength = 1; - - static constexpr int kVersionBitmask = 0x0E0; - static constexpr int kPcpBitmask = 0x01F; - static constexpr int kVersionShift = 5; - static constexpr int kWebRtcConnectableFlagBitmask = 0x01; - - Version version_{Version::kUndefined}; - Pcp pcp_{Pcp::kUnknown}; - std::string endpoint_id_; - ByteArray service_id_hash_; - ByteArray endpoint_info_; - // TODO(b/169550050): Define UWB address field. - ByteArray uwb_address_; - WebRtcState web_rtc_state_{WebRtcState::kUndefined}; -}; - -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_WIFI_LAN_SERVICE_INFO_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_service_info_test.cc b/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_service_info_test.cc deleted file mode 100644 index ffa9d79b81a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/wifi_lan_service_info_test.cc +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "core/internal/wifi_lan_service_info.h" - -#include <cstring> -#include <memory> - -#include "gtest/gtest.h" -#include "platform/base/base64_utils.h" -#include "platform/base/nsd_service_info.h" - -namespace location { -namespace nearby { -namespace connections { -namespace { - -constexpr WifiLanServiceInfo::Version kVersion = - WifiLanServiceInfo::Version::kV1; -constexpr Pcp kPcp = Pcp::kP2pCluster; -constexpr absl::string_view kEndPointID{"AB12"}; -constexpr absl::string_view kServiceIDHashBytes{"\x0a\x0b\x0c"}; -constexpr absl::string_view kEndPointName{"RAWK + ROWL!"}; -constexpr WebRtcState kWebRtcState = WebRtcState::kConnectable; - -// TODO(b/169550050): Implement UWBAddress. -TEST(WifiLanServiceInfoTest, ConstructionWorks) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - WifiLanServiceInfo wifi_lan_service_info{ - kVersion, kPcp, kEndPointID, service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_TRUE(wifi_lan_service_info.IsValid()); - EXPECT_EQ(kPcp, wifi_lan_service_info.GetPcp()); - EXPECT_EQ(kVersion, wifi_lan_service_info.GetVersion()); - EXPECT_EQ(kEndPointID, wifi_lan_service_info.GetEndpointId()); - EXPECT_EQ(service_id_hash, wifi_lan_service_info.GetServiceIdHash()); - EXPECT_EQ(endpoint_info, wifi_lan_service_info.GetEndpointInfo()); -} - -TEST(WifiLanServiceInfoTest, ConstructionFromSerializedStringWorks) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - WifiLanServiceInfo org_wifi_lan_service_info{ - kVersion, kPcp, kEndPointID, service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - NsdServiceInfo nsd_service_info{org_wifi_lan_service_info}; - - WifiLanServiceInfo wifi_lan_service_info{nsd_service_info}; - - EXPECT_TRUE(wifi_lan_service_info.IsValid()); - EXPECT_EQ(kPcp, wifi_lan_service_info.GetPcp()); - EXPECT_EQ(kVersion, wifi_lan_service_info.GetVersion()); - EXPECT_EQ(kEndPointID, wifi_lan_service_info.GetEndpointId()); - EXPECT_EQ(service_id_hash, wifi_lan_service_info.GetServiceIdHash()); - EXPECT_EQ(endpoint_info, wifi_lan_service_info.GetEndpointInfo()); - EXPECT_EQ(kWebRtcState, wifi_lan_service_info.GetWebRtcState()); -} - -TEST(WifiLanServiceInfoTest, ConstructionFailsWithBadVersion) { - auto bad_version = static_cast<WifiLanServiceInfo::Version>(666); - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - WifiLanServiceInfo wifi_lan_service_info{ - bad_version, kPcp, kEndPointID, service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(wifi_lan_service_info.IsValid()); -} - -TEST(WifiLanServiceInfoTest, ConstructionFailsWithBadPCP) { - auto bad_pcp = static_cast<Pcp>(666); - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - WifiLanServiceInfo wifi_lan_service_info{ - kVersion, bad_pcp, kEndPointID, service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(wifi_lan_service_info.IsValid()); -} - -TEST(WifiLanServiceInfoTest, ConstructionFailsWithShortEndpointId) { - std::string short_endpoint_id("AB1"); - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - WifiLanServiceInfo wifi_lan_service_info{ - kVersion, kPcp, short_endpoint_id, service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(wifi_lan_service_info.IsValid()); -} - -TEST(WifiLanServiceInfoTest, ConstructionFailsWithLongEndpointId) { - std::string long_endpoint_id("AB12X"); - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray endpoint_info{std::string(kEndPointName)}; - WifiLanServiceInfo wifi_lan_service_info{ - kVersion, kPcp, long_endpoint_id, service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(wifi_lan_service_info.IsValid()); -} - -TEST(WifiLanServiceInfoTest, ConstructionFailsWithShortServiceIdHash) { - char short_service_id_hash_bytes[] = "\x0a\x0b"; - - ByteArray short_service_id_hash{short_service_id_hash_bytes}; - ByteArray endpoint_info{std::string(kEndPointName)}; - WifiLanServiceInfo wifi_lan_service_info{ - kVersion, kPcp, kEndPointID, short_service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(wifi_lan_service_info.IsValid()); -} - -TEST(WifiLanServiceInfoTest, ConstructionFailsWithLongServiceIdHash) { - char long_service_id_hash_bytes[] = "\x0a\x0b\x0c\x0d"; - - ByteArray long_service_id_hash{long_service_id_hash_bytes}; - ByteArray endpoint_info{std::string(kEndPointName)}; - WifiLanServiceInfo wifi_lan_service_info{ - kVersion, kPcp, kEndPointID, long_service_id_hash, - endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(wifi_lan_service_info.IsValid()); -} - -TEST(WifiLanServiceInfoTest, ConstructionFailsWithShortServiceNameLength) { - char wifi_lan_service_info_name[] = {'X', '\0'}; - ByteArray wifi_lan_service_info_bytes{wifi_lan_service_info_name}; - - NsdServiceInfo nsd_service_info; - nsd_service_info.SetServiceName( - Base64Utils::Encode(wifi_lan_service_info_bytes)); - - WifiLanServiceInfo wifi_lan_service_info{nsd_service_info}; - - EXPECT_FALSE(wifi_lan_service_info.IsValid()); -} - -TEST(WifiLanServiceInfoTest, ConstructionFailsWithLongEndpointInfoLength) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray long_endpoint_info(WifiLanServiceInfo::kMaxEndpointInfoLength + 1); - - WifiLanServiceInfo wifi_lan_service_info{ - kVersion, kPcp, kEndPointID, service_id_hash, - long_endpoint_info, ByteArray{}, kWebRtcState}; - - EXPECT_FALSE(wifi_lan_service_info.IsValid()); -} - -} // namespace -} // namespace connections -} // namespace nearby -} // namespace location |