diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-09-01 11:08:40 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-10-01 12:16:21 +0000 |
commit | 03c549e0392f92c02536d3f86d5e1d8dfa3435ac (patch) | |
tree | fe49d170a929b34ba82cd10db1a0bd8e3760fa4b /chromium/third_party/nearby | |
parent | 5d013f5804a0d91fcf6c626b2d6fb6eca5c845b0 (diff) | |
download | qtwebengine-chromium-03c549e0392f92c02536d3f86d5e1d8dfa3435ac.tar.gz |
BASELINE: Update Chromium to 91.0.4472.160
Change-Id: I0def1f08a2412aeed79a9ab95dd50eb5c3f65f31
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/nearby')
134 files changed, 4833 insertions, 1652 deletions
diff --git a/chromium/third_party/nearby/BUILD.gn b/chromium/third_party/nearby/BUILD.gn index 61e188dac19..cf400abf858 100644 --- a/chromium/third_party/nearby/BUILD.gn +++ b/chromium/third_party/nearby/BUILD.gn @@ -193,7 +193,11 @@ source_set("platform_base_cancellation_flag") { source_set("platform_public_types") { public_configs = [ ":nearby_include_config" ] - sources = [ "src/cpp/platform/public/pipe.cc" ] + sources = [ + "src/cpp/platform/public/monitored_runnable.cc", + "src/cpp/platform/public/pending_job_registry.cc", + "src/cpp/platform/public/pipe.cc", + ] public = [ "src/cpp/platform/public/atomic_boolean.h", "src/cpp/platform/public/atomic_reference.h", @@ -205,9 +209,11 @@ source_set("platform_public_types") { "src/cpp/platform/public/file.h", "src/cpp/platform/public/future.h", "src/cpp/platform/public/logging.h", + "src/cpp/platform/public/monitored_runnable.h", "src/cpp/platform/public/multi_thread_executor.h", "src/cpp/platform/public/mutex.h", "src/cpp/platform/public/mutex_lock.h", + "src/cpp/platform/public/pending_job_registry.h", "src/cpp/platform/public/pipe.h", "src/cpp/platform/public/scheduled_executor.h", "src/cpp/platform/public/settable_future.h", @@ -465,8 +471,6 @@ source_set("core_internal_mediums_webrtc") { sources = [ "src/cpp/core/internal/mediums/utils.cc", "src/cpp/core/internal/mediums/webrtc/connection_flow.cc", - "src/cpp/core/internal/mediums/webrtc/data_channel_observer_impl.cc", - "src/cpp/core/internal/mediums/webrtc/peer_connection_observer_impl.cc", "src/cpp/core/internal/mediums/webrtc/peer_id.cc", "src/cpp/core/internal/mediums/webrtc/signaling_frames.cc", "src/cpp/core/internal/mediums/webrtc/webrtc_socket.cc", @@ -475,9 +479,7 @@ source_set("core_internal_mediums_webrtc") { "src/cpp/core/internal/mediums/utils.h", "src/cpp/core/internal/mediums/webrtc/connection_flow.h", "src/cpp/core/internal/mediums/webrtc/data_channel_listener.h", - "src/cpp/core/internal/mediums/webrtc/data_channel_observer_impl.h", "src/cpp/core/internal/mediums/webrtc/local_ice_candidate_listener.h", - "src/cpp/core/internal/mediums/webrtc/peer_connection_observer_impl.h", "src/cpp/core/internal/mediums/webrtc/peer_id.h", "src/cpp/core/internal/mediums/webrtc/session_description_wrapper.h", "src/cpp/core/internal/mediums/webrtc/signaling_frames.h", diff --git a/chromium/third_party/nearby/README.chromium b/chromium/third_party/nearby/README.chromium index 57f8ca0399b..d850a328ea0 100644 --- a/chromium/third_party/nearby/README.chromium +++ b/chromium/third_party/nearby/README.chromium @@ -1,7 +1,7 @@ Name: Nearby Connections Library Short Name: Nearby URL: https://github.com/google/nearby-connections -Version: a7b99e7509c3734b94a151739bc4035de6497a37 +Version: 93eec2c07b588985da41af77a4589dd0de37c677 License: Apache 2.0 License File: LICENSE Security Critical: yes diff --git a/chromium/third_party/nearby/src/cpp/core/BUILD b/chromium/third_party/nearby/src/cpp/core/BUILD index f0b551ee31a..6a6ebd27ce6 100644 --- a/chromium/third_party/nearby/src/cpp/core/BUILD +++ b/chromium/third_party/nearby/src/cpp/core/BUILD @@ -26,7 +26,7 @@ cc_library( deps = [ ":core_types", "//core/internal", - "//platform/public:comm", + "//platform/base", "//platform/public:logging", "//platform/public:types", "//absl/strings", @@ -54,8 +54,6 @@ cc_library( deps = [ "//platform/base", "//platform/base:util", - "//platform/public:comm", - "//platform/public:logging", "//platform/public:types", "//proto:connections_enums_portable_proto", "//absl/strings", @@ -81,7 +79,6 @@ cc_test( "//core/internal:internal_test", "//platform/base", "//platform/impl/g3", # build_cleaner: keep - "//platform/public:comm", "//platform/public:logging", "//platform/public:types", "//testing/base/public:gunit_main", diff --git a/chromium/third_party/nearby/src/cpp/core/core.cc b/chromium/third_party/nearby/src/cpp/core/core.cc index 11dd795f61e..9c7813b1f71 100644 --- a/chromium/third_party/nearby/src/cpp/core/core.cc +++ b/chromium/third_party/nearby/src/cpp/core/core.cc @@ -18,6 +18,7 @@ #include <vector> #include "core/options.h" +#include "platform/base/feature_flags.h" #include "platform/public/count_down_latch.h" #include "platform/public/logging.h" #include "absl/time/clock.h" @@ -78,6 +79,22 @@ void Core::RequestConnection(absl::string_view endpoint_id, ResultCallback callback) { assert(!endpoint_id.empty()); + // Assign the default from feature flags for the keep-alive frame interval and + // timeout values if client don't mind them or has the unexpected ones. + if (options.keep_alive_interval_millis == 0 || + options.keep_alive_timeout_millis == 0 || + options.keep_alive_interval_millis >= options.keep_alive_timeout_millis) { + NEARBY_LOG( + WARNING, + "Client request connection with keep-alive frame as interval=%d, " + "timeout=%d, which is un-expected. Change to default.", + options.keep_alive_interval_millis, options.keep_alive_timeout_millis); + options.keep_alive_interval_millis = + FeatureFlags::GetInstance().GetFlags().keep_alive_interval_millis; + options.keep_alive_timeout_millis = + FeatureFlags::GetInstance().GetFlags().keep_alive_timeout_millis; + } + router_.RequestConnection(&client_, endpoint_id, info, options, callback); } 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 index 7bcde6f5263..71e35123967 100644 --- 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 @@ -22,12 +22,10 @@ #include "core/internal/bwu_handler.h" #include "core/internal/client_proxy.h" #include "core/internal/endpoint_channel_manager.h" -#include "proto/connections/offline_wire_formats.pb.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" -#include "proto/connections_enums.pb.h" #include "absl/container/flat_hash_map.h" #include "absl/time/clock.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 index 30e8c8bec57..df5c2d5980e 100644 --- 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 @@ -66,6 +66,7 @@ ExceptionOr<ByteArray> ReadExactly(InputStream* reader, std::int64_t size) { ByteArray result = read_bytes.result(); if (result.Empty()) { + NEARBY_LOGS(WARNING) << __func__ << ": Empty result when reading bytes."; return ExceptionOr<ByteArray>(Exception::kIo); } @@ -106,6 +107,8 @@ ExceptionOr<ByteArray> BaseEndpointChannel::Read() { } 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); } @@ -134,12 +137,24 @@ ExceptionOr<ByteArray> BaseEndpointChannel::Read() { // TODO(apolyudov): verify this happens at most once per session. result = {}; auto parsed = parser::FromBytes(ByteArray(input)); - if (parsed.ok() && - parser::GetFrameType(parsed.result()) == V1Frame::KEEP_ALIVE) { - result = 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); } } @@ -174,7 +189,10 @@ Exception BaseEndpointChannel::Write(const ByteArray& data) { // If encryption is enabled, encode the message. std::unique_ptr<std::string> encrypted = crypto_context_->EncodeMessageToPeer(std::string(data)); - if (!encrypted) return {Exception::kIo}; + if (!encrypted) { + NEARBY_LOGS(WARNING) << __func__ << ": Failed to encrypt data."; + return {Exception::kIo}; + } encrypted_data = ByteArray(std::move(*encrypted)); data_to_write = &encrypted_data; } @@ -183,14 +201,20 @@ Exception BaseEndpointChannel::Write(const ByteArray& 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; } } @@ -216,7 +240,8 @@ void BaseEndpointChannel::CloseIo() { // IO and Read() will proceed normally (with Exception::kIo). Exception exception = reader_->Close(); if (!exception.Ok()) { - // Add logging. + NEARBY_LOGS(WARNING) << __func__ + << ": Exception closing reader: " << exception.value; } } { @@ -225,13 +250,16 @@ void BaseEndpointChannel::CloseIo() { // IO and Write() will proceed normally (with Exception::kIo). Exception exception = writer_->Close(); if (!exception.Ok()) { - // Add logging. + NEARBY_LOGS(WARNING) << __func__ + << ": Exception closing writer: " << exception.value; } } } void BaseEndpointChannel::Close( proto::connections::DisconnectionReason reason) { + NEARBY_LOGS(INFO) << __func__ + << ": Closing endpoint channel, reason: " << reason; Close(); } @@ -306,6 +334,8 @@ void BaseEndpointChannel::BlockUntilUnpaused() { 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; } } 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 index 5b64170c6ed..89688a5d9f9 100644 --- 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 @@ -27,7 +27,6 @@ #include "platform/public/condition_variable.h" #include "platform/public/mutex.h" #include "platform/public/system_clock.h" -#include "proto/connections_enums.pb.h" #include "securegcm/d2d_connection_context_v1.h" #include "absl/base/thread_annotations.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 index 80668a4414d..3a667c333b6 100644 --- 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 @@ -17,7 +17,9 @@ #include <utility> #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" @@ -26,7 +28,6 @@ #include "platform/public/pipe.h" #include "platform/public/single_thread_executor.h" #include "proto/connections_enums.pb.h" -#include "proto/connections_enums.pb.h" #include "securegcm/d2d_connection_context_v1.h" #include "securegcm/ukey2_handshake.h" #include "gmock/gmock.h" @@ -354,6 +355,51 @@ TEST(BaseEndpointChannelTest, ReadAfterInputStreamClosed) { 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 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 index c41176a36af..720dc51eba3 100644 --- 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 @@ -82,47 +82,50 @@ Status BasePcpHandler::StartAdvertising(ClientProxy* client, NEARBY_LOG(INFO, "StartAdvertising with supported mediums: %s", GetStringValueOfSupportedMediums(options).c_str()); ConnectionOptions advertising_options = options.CompatibleOptions(); - RunOnPcpHandlerThread([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. - std::vector<proto::connections::Medium> supported_mediums = - advertising_options.GetMediums(); - advertising_listener_ = info.listener; - client->StartedAdvertising(service_id, GetStrategy(), info.listener, - absl::MakeSpan(result.mediums), - advertising_options); - response.Set({Status::kSuccess}); - }); + 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 id=" << client->GetLocalEndpointId(); CountDownLatch latch(1); - RunOnPcpHandlerThread([this, client, &latch]() RUN_ON_PCP_HANDLER_THREAD() { - StopAdvertisingImpl(client); - client->StoppedAdvertising(); - latch.CountDown(); - }); + RunOnPcpHandlerThread("stop-advertising", + [this, client, &latch]() RUN_ON_PCP_HANDLER_THREAD() { + StopAdvertisingImpl(client); + client->StoppedAdvertising(); + latch.CountDown(); + }); WaitForLatch("StopAdvertising", &latch); } @@ -143,6 +146,43 @@ bool BasePcpHandler::ShouldEnterHighVisibilityMode( 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); + } + } + + return {.bluetooth = intersection.contains(Medium::BLUETOOTH), + .ble = intersection.contains(Medium::BLE), + .web_rtc = intersection.contains(Medium::WEB_RTC), + .wifi_lan = intersection.contains(Medium::WIFI_LAN)}; +} + Status BasePcpHandler::StartDiscovery(ClientProxy* client, const std::string& service_id, const ConnectionOptions& options, @@ -152,33 +192,36 @@ Status BasePcpHandler::StartDiscovery(ClientProxy* client, NEARBY_LOG(INFO, "StartDiscovery with supported mediums: %s", GetStringValueOfSupportedMediums(options).c_str()); - RunOnPcpHandlerThread([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; - } + 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}); - }); + // 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([this, client, &latch]() RUN_ON_PCP_HANDLER_THREAD() { - StopDiscoveryImpl(client); - client->StoppedDiscovery(); - latch.CountDown(); - }); + RunOnPcpHandlerThread("stop-discovery", + [this, client, &latch]() RUN_ON_PCP_HANDLER_THREAD() { + StopDiscoveryImpl(client); + client->StoppedDiscovery(); + latch.CountDown(); + }); WaitForLatch("StopDiscovery", &latch); } @@ -187,7 +230,8 @@ void BasePcpHandler::InjectEndpoint( ClientProxy* client, const std::string& service_id, const OutOfBandConnectionMetadata& metadata) { CountDownLatch latch(1); - RunOnPcpHandlerThread([this, client, service_id, metadata, &latch]() + RunOnPcpHandlerThread("inject-endpoint", + [this, client, service_id, metadata, &latch]() RUN_ON_PCP_HANDLER_THREAD() { InjectEndpointImpl(client, service_id, metadata); latch.CountDown(); @@ -225,8 +269,9 @@ Status BasePcpHandler::WaitForResult(const std::string& method_name, return result.result(); } -void BasePcpHandler::RunOnPcpHandlerThread(Runnable runnable) { - serial_executor_.Execute(std::move(runnable)); +void BasePcpHandler::RunOnPcpHandlerThread(const std::string& name, + Runnable runnable) { + serial_executor_.Execute(name, std::move(runnable)); } EncryptionRunner::ResultListener BasePcpHandler::GetResultListener() { @@ -237,6 +282,7 @@ EncryptionRunner::ResultListener BasePcpHandler::GetResultListener() { 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( @@ -246,12 +292,13 @@ EncryptionRunner::ResultListener BasePcpHandler::GetResultListener() { }, .on_failure_cb = [this](const std::string& endpoint_id, EndpointChannel* channel) { - RunOnPcpHandlerThread([this, endpoint_id, - channel]() RUN_ON_PCP_HANDLER_THREAD() { - NEARBY_LOG(ERROR, "Encryption failed for %s on medium %d", - endpoint_id.c_str(), channel->GetMedium()); - OnEncryptionFailureRunnable(endpoint_id, channel); - }); + RunOnPcpHandlerThread( + "encryption-failure", + [this, endpoint_id, channel]() RUN_ON_PCP_HANDLER_THREAD() { + NEARBY_LOG(ERROR, "Encryption failed for %s on medium %d", + endpoint_id.c_str(), channel->GetMedium()); + OnEncryptionFailureRunnable(endpoint_id, channel); + }); }, }; } @@ -296,8 +343,30 @@ void BasePcpHandler::OnEncryptionSuccessRunnable( .raw_authentication_token = raw_auth_token, .is_incoming_connection = connection_info.is_incoming, }, - connection_info.options, std::move(connection_info.channel), - connection_info.listener); + { + .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); if (auto future_status = connection_info.result.lock()) { NEARBY_LOG(INFO, "Connection established; Finalising future OK"); @@ -341,119 +410,128 @@ Status BasePcpHandler::RequestConnection(ClientProxy* client, const ConnectionRequestInfo& info, const ConnectionOptions& options) { auto result = std::make_shared<Future<Status>>(); - RunOnPcpHandlerThread([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_LOG(INFO, "Connection already exists: id=%s", endpoint_id.c_str()); - 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_LOG(INFO, "Outgoing connection not allowed: id=%s", - endpoint_id.c_str()); - result->Set({Status::kOutOfOrderApiCall}); - return; - } - - DiscoveredEndpoint* endpoint = GetDiscoveredEndpoint(endpoint_id); - if (endpoint == nullptr) { - NEARBY_LOG(INFO, "Discovered endpoint not found: id=%s", - endpoint_id.c_str()); - result->Set({Status::kEndpointUnknown}); - return; - } + 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_LOG(INFO, "Connection already exists: id=%s", + endpoint_id.c_str()); + result->Set({Status::kAlreadyConnectedToEndpoint}); + 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 our child class says we can't send any more outgoing connections, + // listen to them. + if (ShouldEnforceTopologyConstraints(client->GetAdvertisingOptions()) && + !CanSendOutgoingConnection(client)) { + NEARBY_LOG(INFO, "Outgoing connection not allowed: id=%s", + endpoint_id.c_str()); + result->Set({Status::kOutOfOrderApiCall}); + return; + } - if (AppendWebRTCEndpoint(endpoint_id, client->GetDiscoveryOptions())) - NEARBY_LOGS(INFO) << "Appended Web RTC endpoint."; + DiscoveredEndpoint* endpoint = GetDiscoveredEndpoint(endpoint_id); + if (endpoint == nullptr) { + NEARBY_LOG(INFO, "Discovered endpoint not found: id=%s", + endpoint_id.c_str()); + result->Set({Status::kEndpointUnknown}); + return; + } - auto discovered_endpoints = GetDiscoveredEndpoints(endpoint_id); - std::unique_ptr<EndpointChannel> channel; - ConnectImplResult connect_impl_result; + 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 << "]"; + } - for (auto connect_endpoint : discovered_endpoints) { - 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; - } - } + 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) { + 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; + } + } - if (channel == nullptr) { - NEARBY_LOG(INFO, "Endpoint channel not available: id=%s", - endpoint_id.c_str()); - ProcessPreConnectionInitiationFailure( - endpoint_id, channel.get(), connect_impl_result.status, result.get()); - return; - } + if (channel == nullptr) { + NEARBY_LOG(INFO, "Endpoint channel not available: id=%s", + endpoint_id.c_str()); + ProcessPreConnectionInitiationFailure(endpoint_id, channel.get(), + connect_impl_result.status, + result.get()); + return; + } - NEARBY_LOG(INFO, "Sending connection request: id=%s", endpoint_id.c_str()); - // 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)); - if (!write_exception.Ok()) { - NEARBY_LOG(INFO, "Failed to send connection request: id=%s", - endpoint_id.c_str()); - ProcessPreConnectionInitiationFailure( - endpoint_id, channel.get(), {Status::kEndpointIoError}, result.get()); - return; - } + NEARBY_LOG(INFO, "Sending connection request: id=%s", + endpoint_id.c_str()); + // 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_LOG(INFO, "Failed to send connection request: id=%s", + endpoint_id.c_str()); + ProcessPreConnectionInitiationFailure(endpoint_id, channel.get(), + {Status::kEndpointIoError}, + result.get()); + return; + } - NEARBY_LOG(INFO, "adding connection to pending set: id=%s", - endpoint_id.c_str()); + NEARBY_LOG(INFO, "adding connection to pending set: id=%s", + endpoint_id.c_str()); - // 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. - EndpointChannel* endpoint_channel = - pending_connections_ - .emplace(endpoint_id, - PendingConnectionInfo{ - .client = client, - .remote_endpoint_info = endpoint->endpoint_info, - .nonce = nonce, - .is_incoming = false, - .start_time = start_time, - .listener = info.listener, - .options = options, - .result = result, - .channel = std::move(channel), - }) - .first->second.channel.get(); - - NEARBY_LOG(INFO, "Initiating secure connection: id=%s", - endpoint_id.c_str()); - // 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()); - }); + // 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. + EndpointChannel* endpoint_channel = + pending_connections_ + .emplace(endpoint_id, + PendingConnectionInfo{ + .client = client, + .remote_endpoint_info = endpoint->endpoint_info, + .nonce = nonce, + .is_incoming = false, + .start_time = start_time, + .listener = info.listener, + .options = options, + .result = result, + .channel = std::move(channel), + }) + .first->second.channel.get(); + + NEARBY_LOG(INFO, "Initiating secure connection: id=%s", + endpoint_id.c_str()); + // 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_LOG(INFO, "Waiting for connection to complete: id=%s", endpoint_id.c_str()); auto status = @@ -562,11 +640,13 @@ bool BasePcpHandler::CanReceiveIncomingConnection(ClientProxy* client) const { 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) { - // TODO(b/172178926): Add WifiLan 5GHz and BSSID support. + 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)); + /*bssid=*/std::string{}, supported_mediums, keep_alive_interval_millis, + keep_alive_timeout_millis)); } void BasePcpHandler::ProcessPreConnectionInitiationFailure( @@ -619,8 +699,8 @@ Status BasePcpHandler::AcceptConnection( const PayloadListener& payload_listener) { Future<Status> response; RunOnPcpHandlerThread( - [this, client, endpoint_id, payload_listener, - &response]() RUN_ON_PCP_HANDLER_THREAD() { + "accept-connection", [this, client, endpoint_id, payload_listener, + &response]() RUN_ON_PCP_HANDLER_THREAD() { NEARBY_LOG(INFO, "AcceptConnection: id=%s", endpoint_id.c_str()); if (!pending_connections_.count(endpoint_id)) { NEARBY_LOG(INFO, "AcceptConnection: no pending connection for id=%s", @@ -673,51 +753,52 @@ Status BasePcpHandler::AcceptConnection( Status BasePcpHandler::RejectConnection(ClientProxy* client, const std::string& endpoint_id) { Future<Status> response; - RunOnPcpHandlerThread([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_LOG(INFO, "RejectConnection: no pending connection for id=%s", - endpoint_id.c_str()); - 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_LOG( - ERROR, - "Channel destroyed before Reject; bring down connection: id=%s", - endpoint_id.c_str()); - ProcessPreConnectionResultFailure(client, endpoint_id); - response.Set({Status::kEndpointUnknown}); - return; - } + 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_LOG(INFO, "RejectConnection: no pending connection for id=%s", + endpoint_id.c_str()); + response.Set({Status::kEndpointUnknown}); + return; + } + auto& connection_info = pending_connections_[endpoint_id]; - Exception write_exception = channel->Write( - parser::ForConnectionResponse(Status::kConnectionRejected)); - if (!write_exception.Ok()) { - NEARBY_LOG(INFO, "RejectConnection: failed to send response: id=%s", - endpoint_id.c_str()); - ProcessPreConnectionResultFailure(client, endpoint_id); - response.Set({Status::kEndpointIoError}); - return; - } + // 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_LOG( + ERROR, + "Channel destroyed before Reject; bring down connection: id=%s", + endpoint_id.c_str()); + ProcessPreConnectionResultFailure(client, endpoint_id); + response.Set({Status::kEndpointUnknown}); + return; + } - NEARBY_LOG(INFO, "RejectConnection: rejecting locally: id=%s", - endpoint_id.c_str()); - connection_info.LocalEndpointRejectedConnection(endpoint_id); - EvaluateConnectionResult(client, endpoint_id, - false /* can_close_immediately */); - response.Set({Status::kSuccess}); - }); + Exception write_exception = channel->Write( + parser::ForConnectionResponse(Status::kConnectionRejected)); + if (!write_exception.Ok()) { + NEARBY_LOG(INFO, "RejectConnection: failed to send response: id=%s", + endpoint_id.c_str()); + ProcessPreConnectionResultFailure(client, endpoint_id); + response.Set({Status::kEndpointIoError}); + return; + } + + NEARBY_LOG(INFO, "RejectConnection: rejecting locally: id=%s", + endpoint_id.c_str()); + 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); @@ -728,45 +809,46 @@ void BasePcpHandler::OnIncomingFrame(OfflineFrame& frame, ClientProxy* client, proto::connections::Medium medium) { CountDownLatch latch(1); - RunOnPcpHandlerThread([this, client, endpoint_id, frame, - &latch]() RUN_ON_PCP_HANDLER_THREAD() { - NEARBY_LOG(INFO, "OnConnectionResponse: id=%s", endpoint_id.c_str()); - - if (client->HasRemoteEndpointResponded(endpoint_id)) { - NEARBY_LOG(INFO, "OnConnectionResponse: already handled; id=%s", - endpoint_id.c_str()); - return; - } + RunOnPcpHandlerThread( + "incoming-frame", + [this, client, endpoint_id, frame, &latch]() RUN_ON_PCP_HANDLER_THREAD() { + NEARBY_LOG(INFO, "OnConnectionResponse: id=%s", endpoint_id.c_str()); - const ConnectionResponseFrame& connection_response = - frame.v1().connection_response(); + if (client->HasRemoteEndpointResponded(endpoint_id)) { + NEARBY_LOG(INFO, "OnConnectionResponse: already handled; id=%s", + endpoint_id.c_str()); + return; + } - // 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_LOG(INFO, "OnConnectionResponse: remote accepted; id=%s", - endpoint_id.c_str()); - client->RemoteEndpointAcceptedConnection(endpoint_id); - } else { - NEARBY_LOG(INFO, - "OnConnectionResponse: remote rejected; id=%s; status=%d", - endpoint_id.c_str(), connection_response.status()); - client->RemoteEndpointRejectedConnection(endpoint_id); - } + 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_LOG(INFO, "OnConnectionResponse: remote accepted; id=%s", + endpoint_id.c_str()); + client->RemoteEndpointAcceptedConnection(endpoint_id); + } else { + NEARBY_LOG(INFO, + "OnConnectionResponse: remote rejected; id=%s; status=%d", + endpoint_id.c_str(), connection_response.status()); + client->RemoteEndpointRejectedConnection(endpoint_id); + } - EvaluateConnectionResult(client, endpoint_id, - /* can_close_immediately= */ true); + EvaluateConnectionResult(client, endpoint_id, + /* can_close_immediately= */ true); - latch.CountDown(); - }); + latch.CountDown(); + }); WaitForLatch("OnIncomingFrame()", &latch); } @@ -777,17 +859,19 @@ void BasePcpHandler::OnEndpointDisconnect(ClientProxy* client, barrier.CountDown(); return; } - RunOnPcpHandlerThread([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(); - }); + 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( @@ -969,6 +1053,32 @@ Exception BasePcpHandler::OnIncomingConnection( ? 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_LOG(WARNING, + "Incoming connection has wrong keep-alive frame interval=%d, " + "timeout=%d values; correct them as default.", + options.keep_alive_interval_millis, + options.keep_alive_timeout_millis); + 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 @@ -983,6 +1093,7 @@ Exception BasePcpHandler::OnIncomingConnection( .is_incoming = true, .start_time = start_time, .listener = advertising_listener_, + .options = options, .supported_mediums = parser::ConnectionRequestMediumsToMediums( connection_request), @@ -1043,48 +1154,6 @@ void BasePcpHandler::ProcessTieBreakLoss( ProcessPreConnectionResultFailure(client, endpoint_id); } -void BasePcpHandler::InitiateBandwidthUpgrade( - ClientProxy* client, const std::string& endpoint_id, - const std::vector<Medium>& their_supported_mediums) { - // There was comments for re-using the same highest medium for upgrading. But - // given that end users may change data options all the time, it makes more - // sense to dynamically select the proper medium for upgrading. - // TODO(hais): when we add more mediums like Wifi Hotspot, we need to prevent - // upgrading interfering with active connections. - Medium bwu_medium = ChooseBestUpgradeMedium(their_supported_mediums, - client->GetAdvertisingOptions()); - - if (AutoUpgradeBandwidth(client->GetAdvertisingOptions()) && - bwu_medium != Medium::UNKNOWN_MEDIUM) { - bwu_manager_->InitiateBwuForEndpoint(client, endpoint_id, bwu_medium); - } -} - -proto::connections::Medium BasePcpHandler::ChooseBestUpgradeMedium( - const std::vector<proto::connections::Medium>& their_supported_mediums, - const ConnectionOptions& local_advertising_options) { - // If the remote side did not report their supported mediums, choose an - // appropriate default. - std::vector<proto::connections::Medium> their_mediums = - their_supported_mediums; - if (their_supported_mediums.empty()) { - their_mediums.push_back(GetDefaultUpgradeMedium()); - } - - // Otherwise, pick the best medium we support. - std::vector<proto::connections::Medium> my_mediums = - GetSupportedConnectionMediumsByPriority(local_advertising_options); - for (const auto& my_medium : my_mediums) { - for (const auto& their_medium : their_mediums) { - if (my_medium == their_medium) { - return my_medium; - } - } - } - - return proto::connections::Medium::UNKNOWN_MEDIUM; -} - bool BasePcpHandler::AppendRemoteBluetoothMacAddressEndpoint( const std::string& endpoint_id, const std::string& remote_bluetooth_mac_address, @@ -1239,9 +1308,9 @@ void BasePcpHandler::EvaluateConnectionResult(ClientProxy* client, } // Kick off the bandwidth upgrade for incoming connections. - if (connection_info.is_incoming) { - InitiateBandwidthUpgrade(client, endpoint_id, - connection_info.supported_mediums); + if (connection_info.is_incoming && + AutoUpgradeBandwidth(client->GetAdvertisingOptions())) { + bwu_manager_->InitiateBwuForEndpoint(client, endpoint_id); } } 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 index 9508cc1c1fc..f54ad96e41b 100644 --- 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 @@ -32,7 +32,6 @@ #include "core/listeners.h" #include "core/options.h" #include "core/status.h" -#include "proto/connections/offline_wire_formats.pb.h" #include "platform/base/byte_array.h" #include "platform/base/prng.h" #include "platform/public/atomic_boolean.h" @@ -43,7 +42,6 @@ #include "platform/public/scheduled_executor.h" #include "platform/public/single_thread_executor.h" #include "platform/public/system_clock.h" -#include "proto/connections_enums.pb.h" #include "securegcm/d2d_connection_context_v1.h" #include "securegcm/ukey2_handshake.h" #include "absl/container/btree_map.h" @@ -223,7 +221,7 @@ class BasePcpHandler : public PcpHandler, std::unique_ptr<EndpointChannel> endpoint_channel; }; - void RunOnPcpHandlerThread(Runnable runnable); + void RunOnPcpHandlerThread(const std::string& name, Runnable runnable); BluetoothDevice GetRemoteBluetoothDevice( const std::string& remote_bluetooth_mac_address); @@ -376,7 +374,9 @@ class BasePcpHandler : public PcpHandler, 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); + 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); @@ -410,23 +410,6 @@ class BasePcpHandler : public PcpHandler, void ProcessTieBreakLoss(ClientProxy* client, const std::string& endpoint_id, PendingConnectionInfo* info); - // Called when an incoming connection has been accepted by both sides. - // - // @param client_proxy The client - // @param endpoint_id The id of the remote device - // @param supported_mediums The mediums supported by the remote device. - // Empty - // for outgoing connections and older devices that don't report their - // supported mediums. - void InitiateBandwidthUpgrade( - ClientProxy* client, const std::string& endpoint_id, - const std::vector<proto::connections::Medium>& supported_mediums); - - // Returns the optimal medium supported by both devices. - proto::connections::Medium ChooseBestUpgradeMedium( - const std::vector<proto::connections::Medium>& supported_mediums, - const ConnectionOptions& local_advertising_options); - // Returns true if the bluetooth endpoint based on remote bluetooth mac // address is created and appended into discovered_endpoints_ with key // endpoint_id. @@ -481,6 +464,11 @@ class BasePcpHandler : public PcpHandler, // 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_; 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 index fd1ac0301db..1d60f47362e 100644 --- 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 @@ -329,6 +329,10 @@ class BasePcpHandlerTest 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) 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 index 3d358903e6a..18c6954e4d9 100644 --- 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 @@ -17,7 +17,6 @@ #include "core/internal/base_endpoint_channel.h" #include "platform/public/ble.h" -#include "proto/connections_enums.pb.h" namespace location { namespace nearby { 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 index 172d9f56cd3..d39aa55df30 100644 --- 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 @@ -21,10 +21,8 @@ #include "core/internal/client_proxy.h" #include "core/internal/mediums/mediums.h" #include "core/internal/mediums/utils.h" -#include "proto/connections/offline_wire_formats.pb.h" #include "platform/public/bluetooth_classic.h" #include "platform/public/count_down_latch.h" -#include "proto/connections_enums.pb.h" namespace location { namespace nearby { 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 index 06b919579a5..f9059348056 100644 --- 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 @@ -19,7 +19,6 @@ #include "core/internal/base_endpoint_channel.h" #include "platform/public/bluetooth_classic.h" -#include "proto/connections_enums.pb.h" namespace location { namespace nearby { 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 index 1297c9b2419..c31fa731529 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/bwu_handler.h +++ b/chromium/third_party/nearby/src/cpp/core/internal/bwu_handler.h @@ -19,7 +19,6 @@ #include "core/internal/endpoint_channel.h" #include "core/internal/offline_frames.h" #include "platform/public/count_down_latch.h" -#include "proto/connections_enums.pb.h" namespace location { namespace nearby { 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 index d9c5814415e..b5063b8526b 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager.cc +++ b/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager.cc @@ -131,7 +131,7 @@ void BwuManager::InitiateBwuForEndpoint(ClientProxy* client, Medium new_medium) { NEARBY_LOG(INFO, "InitiateBwuForEndpoint for endpoint %s with medium %d", endpoint_id.c_str(), new_medium); - RunOnBwuManagerThread([this, client, endpoint_id, 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) { @@ -207,12 +207,14 @@ void BwuManager::OnIncomingFrame(OfflineFrame& frame, return; auto bwu_frame = frame.v1().bandwidth_upgrade_negotiation(); if (FeatureFlags::GetInstance().GetFlags().enable_async_bandwidth_upgrade) { - RunOnBwuManagerThread([this, client, endpoint_id, bwu_frame]() { - OnBwuNegotiationFrame(client, bwu_frame, endpoint_id); - }); + RunOnBwuManagerThread( + "bwu-on-incoming-frame", [this, client, endpoint_id, bwu_frame]() { + OnBwuNegotiationFrame(client, bwu_frame, endpoint_id); + }); } else { CountDownLatch latch(1); - RunOnBwuManagerThread([this, client, endpoint_id, bwu_frame, &latch]() { + RunOnBwuManagerThread("bwu-on-incoming-frame", [this, client, endpoint_id, + bwu_frame, &latch]() { OnBwuNegotiationFrame(client, bwu_frame, endpoint_id); latch.CountDown(); }); @@ -224,38 +226,40 @@ void BwuManager::OnEndpointDisconnect(ClientProxy* client, const std::string& endpoint_id, CountDownLatch barrier) { NEARBY_LOG(INFO, "OnEndpointDisconnect for endpoint %s", endpoint_id.c_str()); - RunOnBwuManagerThread([this, client, endpoint_id, barrier]() mutable { - if (medium_ == Medium::UNKNOWN_MEDIUM) { - 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); - 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(); - }); + RunOnBwuManagerThread( + "bwu-on-endpoint-disconnect", + [this, client, endpoint_id, barrier]() mutable { + if (medium_ == Medium::UNKNOWN_MEDIUM) { + 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); + 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) { @@ -275,9 +279,9 @@ void BwuManager::Revert() { NEARBY_LOG(INFO, "Revert reseting medium %d", medium_); if (handler_) { handler_->Revert(); - medium_ = Medium::UNKNOWN_MEDIUM; handler_ = nullptr; } + medium_ = Medium::UNKNOWN_MEDIUM; } void BwuManager::OnBwuNegotiationFrame(ClientProxy* client, @@ -312,7 +316,8 @@ void BwuManager::OnIncomingConnection( client->GetServiceId().c_str()); std::shared_ptr<BwuHandler::IncomingSocketConnection> connection( mutable_connection.release()); - RunOnBwuManagerThread([this, client, connection]() { + RunOnBwuManagerThread("bwu-on-incoming-connection", [this, client, + connection]() { EndpointChannel* channel = connection->channel.get(); if (channel == nullptr) { connection->socket->Close(); @@ -356,8 +361,9 @@ void BwuManager::OnIncomingConnection( }); } -void BwuManager::RunOnBwuManagerThread(Runnable runnable) { - serial_executor_.Execute(std::move(runnable)); +void BwuManager::RunOnBwuManagerThread(const std::string& name, + Runnable runnable) { + serial_executor_.Execute(name, std::move(runnable)); } void BwuManager::RunUpgradeProtocol( @@ -717,10 +723,12 @@ void BwuManager::ProcessSafeToClosePriorChannelEvent( previous_endpoint_channel->DisableEncryption(); previous_endpoint_channel->Write(parser::ForDisconnection()); - // TODO(b/172380349): Match the Java implementation with no sleep call - - // Wait for in-flight messages to reach their peers. - SystemClock::Sleep(absl::Seconds(1)); + // 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); // Now that the old channel has been drained, we can unpause the new channel @@ -910,7 +918,8 @@ void BwuManager::RetryUpgradesAfterDelay(ClientProxy* client, CancelableAlarm alarm( "BWU alarm", [this, client, endpoint_id]() { - RunOnBwuManagerThread([this, client, endpoint_id]() { + RunOnBwuManagerThread("bwu-retry-upgrade", [this, client, + endpoint_id]() { if (!client->IsConnectedToEndpoint(endpoint_id)) { return; } @@ -946,10 +955,13 @@ void BwuManager::CancelRetryUpgradeAlarm(const std::string& endpoint_id) { void BwuManager::CancelAllRetryUpgradeAlarms() { NEARBY_LOG(INFO, "CancelAllRetryUpgradeAlarms invoked"); - for (const auto& item : retry_upgrade_alarms_) { + for (auto& item : retry_upgrade_alarms_) { const std::string& endpoint_id = item.first; - CancelRetryUpgradeAlarm(endpoint_id); + CancelableAlarm& cancellable_alarm = item.second.first; + NEARBY_LOG(INFO, "CancelRetryUpgradeAlarm for %s", endpoint_id.c_str()); + cancellable_alarm.Cancel(); } + retry_upgrade_alarms_.clear(); } Medium BwuManager::GetEndpointMedium(const std::string& endpoint_id) { 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 index 2ba3766605f..f18ddebfa67 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager.h +++ b/chromium/third_party/nearby/src/cpp/core/internal/bwu_manager.h @@ -24,10 +24,8 @@ #include "core/internal/endpoint_manager.h" #include "core/internal/mediums/mediums.h" #include "core/options.h" -#include "proto/connections/offline_wire_formats.pb.h" #include "platform/base/byte_array.h" #include "platform/public/scheduled_executor.h" -#include "proto/connections_enums.pb.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" #include "absl/time/time.h" @@ -103,7 +101,8 @@ class BwuManager : public EndpointManager::FrameProcessor { absl::Seconds(5); BwuHandler* SetCurrentBwuHandler(Medium medium); void InitBwuHandlers(); - void RunOnBwuManagerThread(std::function<void()> runnable); + 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); 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 index 52ab827846f..50f1905499c 100644 --- 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 @@ -21,6 +21,7 @@ #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" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -57,20 +58,49 @@ TEST(BwuManagerTest, CanInitiateBwu) { bwu_manager.Shutdown(); } -TEST(BwuManagerTest, CanProcessPathAvailableFrame) { +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, {}, {}}; - LocationHint location_hint = Utils::BuildLocationHint("US"); - ExceptionOr<OfflineFrame> wrapped_frame = parser::FromBytes( + 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); - bwu_manager.OnIncomingFrame(wrapped_frame.result(), endpoint_id, &client, + 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(); } 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 index 9ecb6b2c463..92884e15fe5 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/client_proxy.h +++ b/chromium/third_party/nearby/src/cpp/core/internal/client_proxy.h @@ -28,7 +28,6 @@ #include "platform/base/prng.h" #include "platform/public/cancelable_alarm.h" #include "platform/public/mutex.h" -#include "proto/connections_enums.pb.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" 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 index 24832a602d4..24833d758d4 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/encryption_runner.cc +++ b/chromium/third_party/nearby/src/cpp/core/internal/encryption_runner.cc @@ -360,6 +360,7 @@ void EncryptionRunner::StartServer( EndpointChannel* endpoint_channel, EncryptionRunner::ResultListener&& listener) { server_executor_.Execute( + "encryption-server", [runnable{ServerRunnable(client, &alarm_executor_, endpoint_id, endpoint_channel, std::move(listener))}]() { runnable(); @@ -371,6 +372,7 @@ void EncryptionRunner::StartClient( EndpointChannel* endpoint_channel, EncryptionRunner::ResultListener&& listener) { client_executor_.Execute( + "encryption-client", [runnable{ClientRunnable(client, &alarm_executor_, endpoint_id, endpoint_channel, std::move(listener))}]() { runnable(); 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 index 31ce2cd278c..fc30e24f82e 100644 --- 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 @@ -31,8 +31,8 @@ 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 -// it they are mutable. +// 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 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 index 500b1e4a2ae..d0d4d0c0d54 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager.cc +++ b/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager.cc @@ -20,18 +20,16 @@ #include "core/internal/endpoint_channel.h" #include "core/internal/offline_frames.h" #include "platform/base/exception.h" -#include "platform/base/feature_flags.h" #include "platform/public/count_down_latch.h" #include "platform/public/logging.h" -#include "proto/connections_enums.pb.h" +#include "platform/public/mutex_lock.h" + namespace location { namespace nearby { namespace connections { using ::location::nearby::proto::connections::Medium; -constexpr absl::Duration EndpointManager::kKeepAliveWriteInterval; -constexpr absl::Duration EndpointManager::kKeepAliveReadTimeout; constexpr absl::Duration EndpointManager::kProcessEndpointDisconnectionTimeout; constexpr absl::Time EndpointManager::kInvalidTimestamp; @@ -90,6 +88,8 @@ void EndpointManager::EndpointChannelLoopRunnable( // 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 @@ -217,13 +217,13 @@ ExceptionOr<bool> EndpointManager::HandleData( } ExceptionOr<bool> EndpointManager::HandleKeepAlive( - EndpointChannel* endpoint_channel) { + EndpointChannel* endpoint_channel, absl::Duration keep_alive_interval, + absl::Duration keep_alive_timeout) { // Check if it has been too long since we received a frame from our // endpoint. auto last_read_time = endpoint_channel->GetLastReadTimestamp(); if (last_read_time != kInvalidTimestamp && - SystemClock::ElapsedRealtime() > - (last_read_time + EndpointManager::kKeepAliveReadTimeout)) { + SystemClock::ElapsedRealtime() > (last_read_time + keep_alive_timeout)) { NEARBY_LOG(INFO, "Receive timeout expired; aborting KeepAlive worker."); return ExceptionOr<bool>(false); } @@ -241,8 +241,7 @@ ExceptionOr<bool> EndpointManager::HandleKeepAlive( // switched out from under us in BandwidthUpgradeManager, our write will // trigger an erroneous write to the encryption context that will cascade // into all our remote endpoint's future reads failing. - Exception sleep_exception = - SystemClock::Sleep(EndpointManager::kKeepAliveWriteInterval); + Exception sleep_exception = SystemClock::Sleep(keep_alive_interval); if (!sleep_exception.Ok()) { return ExceptionOr<bool>(sleep_exception); } @@ -270,7 +269,7 @@ EndpointManager::EndpointManager(EndpointChannelManager* manager) EndpointManager::~EndpointManager() { NEARBY_LOG(INFO, "EndpointManager going down"); CountDownLatch latch(1); - RunOnEndpointManagerThread([this, &latch]() { + RunOnEndpointManagerThread("bring-down-endpoints", [this, &latch]() { NEARBY_LOG(INFO, "Bringing down endpoints"); for (auto& item : endpoints_) { const std::string& endpoint_id = item.first; @@ -304,22 +303,16 @@ EndpointManager::~EndpointManager() { void EndpointManager::RegisterFrameProcessor( V1Frame::FrameType frame_type, EndpointManager::FrameProcessor* processor) { - CountDownLatch latch(1); - RunOnEndpointManagerThread([this, frame_type, &latch, processor]() { - auto it = frame_processors_.find(frame_type); - if (it != frame_processors_.end()) { - NEARBY_LOGS(INFO) << "Frame processor found: updated; type=" << frame_type - << "; processor=" << processor << "; self=" << this; - LockedFrameProcessor frame_processor_lock(&it->second); - frame_processor_lock.set(processor); - } else { - NEARBY_LOGS(INFO) << "Frame processor added; type=" << frame_type - << "; processor=" << processor << "; self=" << this; - frame_processors_.emplace(frame_type, processor); - } - latch.CountDown(); - }); - latch.Await(); + if (auto frame_processor = GetFrameProcessor(frame_type)) { + NEARBY_LOGS(INFO) << "Frame processor found: updated; type=" << frame_type + << "; processor=" << processor << "; self=" << this; + frame_processor.set(processor); + } else { + MutexLock lock(&frame_processors_lock_); + NEARBY_LOGS(INFO) << "Frame processor added; type=" << frame_type + << "; processor=" << processor << "; self=" << this; + frame_processors_.emplace(frame_type, processor); + } } void EndpointManager::UnregisterFrameProcessor( @@ -328,20 +321,9 @@ void EndpointManager::UnregisterFrameProcessor( NEARBY_LOGS(INFO) << "UnregisterFrameProcessor [enter]: processor =" << processor; if (processor == nullptr) return; - CountDownLatch latch(1); - RunOnEndpointManagerThread([this, frame_type, processor, &latch]() { - auto it = frame_processors_.find(frame_type); - if (it == frame_processors_.end()) { - NEARBY_LOGS(INFO) << "UnregisterFrameProcessor [not found]: processor=" - << processor; - latch.CountDown(); - return; - } - NEARBY_LOGS(INFO) << "UnregisterFrameProcessor [found]: processor=" - << processor; - LockedFrameProcessor frame_processor_lock(&it->second); - if (frame_processor_lock.get() == processor) { - frame_processor_lock.reset(); + if (auto frame_processor = GetFrameProcessor(frame_type)) { + if (frame_processor.get() == processor) { + frame_processor.reset(); NEARBY_LOGS(INFO) << "Unregistered: type=" << frame_type << "; processor=" << processor << "; self=" << this; } else { @@ -349,17 +331,17 @@ void EndpointManager::UnregisterFrameProcessor( INFO, "Failed to unregister: type=%d; processor mismatch: passed=%p, " "expected=%p", - frame_type, processor, frame_processor_lock.get()); + frame_type, processor, frame_processor.get()); } - latch.CountDown(); - }); - latch.Await(); - NEARBY_LOGS(INFO) << "Unregistered [sync done]: type=" << frame_type - << "; processor=" << processor << "; self=" << this; + } 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); @@ -408,9 +390,11 @@ void EndpointManager::RegisterEndpoint(ClientProxy* client, // 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([this, client, channel = channel.release(), - &endpoint_id, &info, &options, &listener, - &latch]() { + RunOnEndpointManagerThread("register-endpoint", [this, client, + channel = channel.release(), + &endpoint_id, &info, + &options, &listener, + &latch]() { if (endpoints_.contains(endpoint_id)) { NEARBY_LOG(WARNING, "Registing duplicate endpoint %s", endpoint_id.c_str()); @@ -420,6 +404,18 @@ void EndpointManager::RegisterEndpoint(ClientProxy* client, EnsureWorkersTerminated(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.c_str() + << " for client " << client->GetClientId() + << " with keep-alive frame as interval=" + << absl::FormatDuration(keep_alive_interval).c_str() + << ", timeout=" + << absl::FormatDuration(keep_alive_timeout).c_str(); + // Pass ownership of channel to EndpointChannelManager NEARBY_LOG(INFO, "Registering endpoint with channel manager: id=%s", endpoint_id.c_str()); @@ -455,8 +451,7 @@ void EndpointManager::RegisterEndpoint(ClientProxy* client, // running on the keep_alive_executor_ pool. 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 kKeepAliveReadTimeoutMillis milliseconds, it initiates a - // disconnection. + // within keep_alive_interval_, 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. @@ -466,14 +461,17 @@ void EndpointManager::RegisterEndpoint(ClientProxy* client, // // Using weak_ptr just in case the barrier is freed, to save the UAF crash // in b/179800119. - StartEndpointKeepAliveManager([this, client, endpoint_id, - barrier = std::weak_ptr<CountDownLatch>( - endpoint_state.barrier)]() { - EndpointChannelLoopRunnable("KeepAliveManager", client, endpoint_id, - barrier, [this](EndpointChannel* channel) { - return HandleKeepAlive(channel); - }); - }); + StartEndpointKeepAliveManager( + [this, client, endpoint_id, keep_alive_interval, keep_alive_timeout, + barrier = std::weak_ptr<CountDownLatch>(endpoint_state.barrier)]() { + EndpointChannelLoopRunnable( + "KeepAliveManager", client, endpoint_id, barrier, + [this, keep_alive_interval, + keep_alive_timeout](EndpointChannel* channel) { + return HandleKeepAlive(channel, keep_alive_interval, + keep_alive_timeout); + }); + }); NEARBY_LOG(INFO, "Workers started, notifying client; id=%s", endpoint_id.c_str()); @@ -489,11 +487,12 @@ void EndpointManager::UnregisterEndpoint(ClientProxy* client, const std::string& endpoint_id) { NEARBY_LOG(ERROR, "UnregisterEndpoint for endpoint %s", endpoint_id.c_str()); CountDownLatch latch(1); - RunOnEndpointManagerThread([this, client, endpoint_id, &latch]() { - RemoveEndpoint(client, endpoint_id, - client->IsConnectedToEndpoint(endpoint_id)); - latch.CountDown(); - }); + RunOnEndpointManagerThread( + "unregister-endpoint", [this, client, endpoint_id, &latch]() { + RemoveEndpoint(client, endpoint_id, + client->IsConnectedToEndpoint(endpoint_id)); + latch.CountDown(); + }); latch.Await(); } @@ -525,7 +524,7 @@ std::vector<std::string> EndpointManager::SendPayloadChunk( void EndpointManager::DiscardEndpoint(ClientProxy* client, const std::string& endpoint_id) { NEARBY_LOG(ERROR, "DiscardEndpoint for endpoint %s", endpoint_id.c_str()); - RunOnEndpointManagerThread([this, client, endpoint_id]() { + RunOnEndpointManagerThread("discard-endpoint", [this, client, endpoint_id]() { RemoveEndpoint(client, endpoint_id, /*notify=*/ client->IsConnectedToEndpoint(endpoint_id)); @@ -573,9 +572,28 @@ void EndpointManager::RemoveEndpoint(ClientProxy* client, void EndpointManager::WaitForEndpointDisconnectionProcessing( ClientProxy* client, const std::string& endpoint_id) { NEARBY_LOGS(INFO) << "Wait: client=" << client << "; id=" << endpoint_id; + CountDownLatch barrier = + NotifyFrameProcessorsOnEndpointDisconnect(client, endpoint_id); + + NEARBY_LOGS(INFO) << "Waiting for frame processors to disconnect from: " + << endpoint_id; + if (!barrier.Await(kProcessEndpointDisconnectionTimeout).result()) { + NEARBY_LOGS(INFO) << "Failed to disconnect frame processors from: " + << endpoint_id; + } else { + NEARBY_LOGS(INFO) + << "Finished waiting for frame processors to disconnect from: " + << endpoint_id; + } +} + +CountDownLatch EndpointManager::NotifyFrameProcessorsOnEndpointDisconnect( + ClientProxy* client, const std::string& endpoint_id) { + NEARBY_LOGS(INFO) << "NotifyFrameProcessorsOnEndpointDisconnect: client=" + << client << "; id=" << endpoint_id; + MutexLock lock(&frame_processors_lock_); auto total_size = frame_processors_.size(); NEARBY_LOGS(INFO) << "Total frame processors: " << total_size; - if (!total_size) return; CountDownLatch barrier(total_size); int valid = 0; @@ -593,21 +611,10 @@ void EndpointManager::WaitForEndpointDisconnectionProcessing( if (!valid) { NEARBY_LOGS(INFO) << "No valid frame processors."; - return; } else { NEARBY_LOGS(INFO) << "Valid frame processors: " << valid; } - - NEARBY_LOGS(INFO) << "Waiting for " << valid - << " frame processors to disconnect from: " << endpoint_id; - if (!barrier.Await(kProcessEndpointDisconnectionTimeout).result()) { - NEARBY_LOGS(INFO) << "Failed to disconnect frame processors from: " - << endpoint_id; - } else { - NEARBY_LOGS(INFO) - << "Finished waiting for frame processors to disconnect from: " - << endpoint_id; - } + return barrier; } std::vector<std::string> EndpointManager::SendTransferFrameBytes( @@ -640,15 +647,16 @@ std::vector<std::string> EndpointManager::SendTransferFrameBytes( } void EndpointManager::StartEndpointReader(Runnable runnable) { - handlers_executor_.Execute(std::move(runnable)); + handlers_executor_.Execute("reader", std::move(runnable)); } void EndpointManager::StartEndpointKeepAliveManager(Runnable runnable) { - keep_alive_executor_.Execute(std::move(runnable)); + keep_alive_executor_.Execute("keep-alive", std::move(runnable)); } -void EndpointManager::RunOnEndpointManagerThread(Runnable runnable) { - serial_executor_.Execute(std::move(runnable)); +void EndpointManager::RunOnEndpointManagerThread(const std::string& name, + Runnable runnable) { + serial_executor_.Execute(name, std::move(runnable)); } } // namespace connections 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 index 02c0a7cc4b4..8105c23efcb 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager.h +++ b/chromium/third_party/nearby/src/cpp/core/internal/endpoint_manager.h @@ -22,14 +22,13 @@ #include "core/internal/endpoint_channel.h" #include "core/internal/endpoint_channel_manager.h" #include "core/listeners.h" -#include "proto/connections/offline_wire_formats.pb.h" #include "platform/base/byte_array.h" #include "platform/base/runnable.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" -#include "proto/connections_enums.pb.h" +#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" @@ -172,7 +171,9 @@ class EndpointManager { ClientProxy* client_proxy, EndpointChannel* endpoint_channel); - ExceptionOr<bool> HandleKeepAlive(EndpointChannel* endpoint_channel); + ExceptionOr<bool> HandleKeepAlive(EndpointChannel* endpoint_channel, + absl::Duration keep_alive_interval, + absl::Duration keep_alive_timeout); // Waits for a given endpoint EndpointChannelLoopRunnable() workers to // terminate. @@ -191,10 +192,6 @@ class EndpointManager { static void WaitForLatch(const std::string& method_name, CountDownLatch* latch, std::int32_t timeout_millis); - static constexpr absl::Duration kKeepAliveWriteInterval = - absl::Milliseconds(5000); - static constexpr absl::Duration kKeepAliveReadTimeout = - absl::Milliseconds(30000); static constexpr absl::Duration kProcessEndpointDisconnectionTimeout = absl::Milliseconds(2000); static constexpr std::int32_t kMaxConcurrentEndpoints = 50; @@ -212,6 +209,9 @@ class EndpointManager { 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, @@ -230,12 +230,13 @@ class EndpointManager { void StartEndpointKeepAliveManager(Runnable runnable); // Executes all jobs sequentially, on a serial_executor_. - void RunOnEndpointManagerThread(Runnable runnable); + void RunOnEndpointManagerThread(const std::string& name, Runnable runnable); EndpointChannelManager* channel_manager_; + RecursiveMutex frame_processors_lock_; absl::flat_hash_map<V1Frame::FrameType, FrameProcessorWithMutex> - frame_processors_; + 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_; 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 index e5e1b7aaebb..137a49547aa 100644 --- 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 @@ -176,8 +176,9 @@ 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}); + 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()) 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 index 8861f17eb5c..9a36fa88ef2 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/internal_payload.h +++ b/chromium/third_party/nearby/src/cpp/core/internal/internal_payload.h @@ -18,7 +18,6 @@ #include <cstdint> #include "core/payload.h" -#include "proto/connections/offline_wire_formats.pb.h" #include "platform/base/byte_array.h" #include "platform/base/exception.h" 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 index cd7efc568b9..a0387b77ed4 100644 --- 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 @@ -17,7 +17,6 @@ #include "core/internal/internal_payload.h" #include "core/payload.h" -#include "proto/connections/offline_wire_formats.pb.h" namespace location { namespace nearby { diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/BUILD b/chromium/third_party/nearby/src/cpp/core/internal/mediums/BUILD index 6b9fb0303ba..9a721a3d8ce 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/BUILD +++ b/chromium/third_party/nearby/src/cpp/core/internal/mediums/BUILD @@ -88,21 +88,37 @@ cc_test( "bluetooth_radio_test.cc", "lost_entity_tracker_test.cc", "uuid_test.cc", - "webrtc_test.cc", "wifi_lan_test.cc", ], shard_count = 16, deps = [ ":mediums", - "//core/internal/mediums/webrtc", - "//platform/base", "//platform/base:test_util", "//platform/impl/g3", # build_cleaner: keep "//platform/public:comm", - "//platform/public:logging", "//platform/public:types", "//testing/base/public:gunit_main", "//absl/strings", "//absl/time", ], ) + +cc_test( + name = "core_internal_mediums_webrtc_test", + size = "small", + srcs = [ + "webrtc_test.cc", + ], + shard_count = 16, + tags = ["notsan"], # NOTE(b/139734036): known data race in usrsctplib. + deps = [ + ":mediums", + "//core/internal/mediums/webrtc", + "//platform/base", + "//platform/base:test_util", + "//platform/impl/g3", # build_cleaner: keep + "//platform/public:types", + "//testing/base/public:gunit_main", + "//absl/strings", + ], +) 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 index 6085928f2fa..841d04a23e5 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble.cc +++ b/chromium/third_party/nearby/src/cpp/core/internal/mediums/ble.cc @@ -255,16 +255,14 @@ bool Ble::StartAcceptingConnections(const std::string& service_id, if (IsAcceptingConnectionsLocked(service_id)) { NEARBY_LOGS(INFO) - << "Refusing to start accepting BLE connections for " - << service_id + << "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."; + << service_id << " because Bluetooth isn't enabled."; return false; } @@ -310,7 +308,6 @@ bool Ble::IsAcceptingConnectionsLocked(const std::string& service_id) { return accepting_connections_info_.Existed(service_id); } -// TODO(b/169303284): Handles Cancellation and registration. BleSocket Ble::Connect(BlePeripheral& peripheral, const std::string& service_id, CancellationFlag* cancellation_flag) { MutexLock lock(&mutex_); @@ -324,8 +321,8 @@ BleSocket Ble::Connect(BlePeripheral& peripheral, const std::string& service_id, } if (!radio_.IsEnabled()) { - NEARBY_LOGS(INFO) << "Can't create client BLE socket to " - << &peripheral << " because Bluetooth isn't enabled."; + NEARBY_LOGS(INFO) << "Can't create client BLE socket to " << &peripheral + << " because Bluetooth isn't enabled."; return socket; } 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 index ad0f49ecb14..6f870b17117 100644 --- 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 @@ -271,19 +271,20 @@ bool BluetoothClassic::StartAcceptingConnections( // 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([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)); - } - }); + 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; } @@ -344,7 +345,6 @@ bool BluetoothClassic::StopAcceptingConnections( return true; } -// TODO(b/169303284): Handles Cancellation and registration. BluetoothSocket BluetoothClassic::Connect(BluetoothDevice& bluetooth_device, const std::string& service_name, CancellationFlag* cancellation_flag) { 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 index 28f275cefca..c8957c783b1 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/utils.h +++ b/chromium/third_party/nearby/src/cpp/core/internal/mediums/utils.h @@ -18,7 +18,6 @@ #include <memory> #include "proto/connections/offline_wire_formats.pb.h" -#include "proto/connections/offline_wire_formats.pb.h" #include "platform/base/byte_array.h" 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 index 1c839415f7c..929d60c02c0 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc.cc +++ b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc.cc @@ -62,15 +62,6 @@ WebRtc::~WebRtc() { for (const auto& service_id : service_ids) { StopAcceptingConnections(service_id); } - - // Disconnect all connections - absl::flat_hash_set<std::string> peer_ids; - for (auto& item : sockets_) { - peer_ids.emplace(item.first); - } - for (const auto& peer_id : peer_ids) { - sockets_.find(peer_id)->second.Close(); - } } const std::string WebRtc::GetDefaultCountryCode() { @@ -188,11 +179,10 @@ void WebRtc::StopAcceptingConnections(const std::string& service_id) { // 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->GetState() == ConnectionFlow::State::kConnected) { + if (!entry->second->CloseIfNotConnected()) { continue; } - entry->second->Close(); connection_flows_.erase(peer_id); } @@ -260,17 +250,14 @@ WebRtcSocketWrapper WebRtc::AttemptToConnect( "Cannot connect to WebRTC peer %s because we failed to create a " "SignalingMessenger.", remote_peer_id.GetId().c_str()); - connection_flow->Close(); 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 = [this, &socket_future](bool success) { + auto signaling_complete_callback = [socket_future](bool success) mutable { if (!success) { - OffloadFromThread([&socket_future]() { - socket_future.SetException({Exception::kFailed}); - }); + socket_future.SetException({Exception::kFailed}); } }; if (!info.signaling_messenger->StartReceivingMessages( @@ -281,7 +268,6 @@ WebRtcSocketWrapper WebRtc::AttemptToConnect( "receiving messages over Tachyon.", remote_peer_id.GetId().c_str()); info.signaling_messenger.reset(); - connection_flow->Close(); return WebRtcSocketWrapper(); } @@ -294,7 +280,6 @@ WebRtcSocketWrapper WebRtc::AttemptToConnect( "the peer over Tachyon.", remote_peer_id.GetId().c_str()); info.signaling_messenger.reset(); - connection_flow->Close(); return WebRtcSocketWrapper(); } @@ -392,7 +377,7 @@ void WebRtc::ProcessLocalIceCandidate( void WebRtc::OnSignalingMessage(const std::string& service_id, const ByteArray& message) { - OffloadFromThread([this, service_id, message]() { + OffloadFromThread("rtc-on-signaling-message", [this, service_id, message]() { ProcessTachyonInboxMessage(service_id, message); }); } @@ -403,7 +388,7 @@ void WebRtc::OnSignalingComplete(const std::string& service_id, bool success) { return; } - OffloadFromThread([this, service_id]() { + 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()) { @@ -657,27 +642,16 @@ void WebRtc::RestartTachyonReceiveMessages(const std::string& service_id) { service_id.c_str()); } -void WebRtc::ProcessDataChannelCreated( - const std::string& service_id, const PeerId& remote_peer_id, - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) { +void WebRtc::ProcessDataChannelOpen(const std::string& service_id, + const PeerId& remote_peer_id, + WebRtcSocketWrapper socket_wrapper) { MutexLock lock(&mutex_); - // Transform the DataChannel into a socket. - auto socket = std::make_unique<WebRtcSocket>("WebRtcSocket", data_channel); - socket->SetOnSocketClosedListener({[this, remote_peer_id]() { - OffloadFromThread( - [this, remote_peer_id]() { ProcessDataChannelClosed(remote_peer_id); }); - }}); - WebRtcSocketWrapper wrapper = WebRtcSocketWrapper(std::move(socket)); - - // Store this DataChannel so that we can update it later. - sockets_.emplace(remote_peer_id.GetId(), wrapper); - // 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(wrapper); + connection_request_entry->second.socket_future.Set(socket_wrapper); return; } @@ -685,49 +659,23 @@ void WebRtc::ProcessDataChannelCreated( accepting_connections_info_.find(service_id); if (accepting_connection_entry != accepting_connections_info_.end()) { accepting_connection_entry->second.accepted_connection_callback.accepted_cb( - wrapper); + socket_wrapper); return; } // No one to handle the newly created DataChannel, so we'll just close it. - wrapper.Close(); + socket_wrapper.Close(); NEARBY_LOG(INFO, "Ignoring new DataChannel because we " "are not accepting connections for service %s.", service_id.c_str()); } -void WebRtc::ProcessDataChannelMessage(const PeerId& remote_peer_id, - const ByteArray& message) { - MutexLock lock(&mutex_); - const auto& entry = sockets_.find(remote_peer_id.GetId()); - if (entry == sockets_.end()) { - return; - } - - entry->second.NotifyDataChannelMsgReceived(message); -} - -void WebRtc::ProcessDataChannelBufferAmountChanged( - const PeerId& remote_peer_id) { - MutexLock lock(&mutex_); - const auto& entry = sockets_.find(remote_peer_id.GetId()); - if (entry == sockets_.end()) { - return; - } - - entry->second.NotifyDataChannelBufferedAmountChanged(); -} - void WebRtc::ProcessDataChannelClosed(const PeerId& remote_peer_id) { MutexLock lock(&mutex_); - const auto& entry = sockets_.find(remote_peer_id.GetId()); - if (entry == sockets_.end()) { - return; - } - - entry->second.Close(); - sockets_.erase(remote_peer_id.GetId()); + NEARBY_LOG(INFO, + "Data channel has closed, removing connection flow for peer %s.", + remote_peer_id.GetId().c_str()); RemoveConnectionFlow(remote_peer_id); } @@ -746,35 +694,24 @@ std::unique_ptr<ConnectionFlow> WebRtc::CreateConnectionFlow( ::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_created_cb = - {[this, service_id, - remote_peer_id](rtc::scoped_refptr<webrtc::DataChannelInterface> - data_channel) { - OffloadFromThread( - [this, service_id, remote_peer_id, data_channel]() { - ProcessDataChannelCreated(service_id, remote_peer_id, - data_channel); - }); - }}, - .data_channel_message_received_cb = {[this, remote_peer_id]( - const ByteArray& message) { - OffloadFromThread([this, remote_peer_id, message]() { - ProcessDataChannelMessage(remote_peer_id, message); - }); - }}, - .data_channel_buffered_amount_changed_cb = {[this, remote_peer_id]() { - OffloadFromThread([this, remote_peer_id]() { - ProcessDataChannelBufferAmountChanged(remote_peer_id); - }); + .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([this, remote_peer_id]() { + OffloadFromThread("rtc-channel-closed", [this, remote_peer_id]() { ProcessDataChannelClosed(remote_peer_id); }); }}, @@ -783,14 +720,10 @@ std::unique_ptr<ConnectionFlow> WebRtc::CreateConnectionFlow( } void WebRtc::RemoveConnectionFlow(const PeerId& remote_peer_id) { - const auto& entry = connection_flows_.find(remote_peer_id.GetId()); - if (entry == connection_flows_.end()) { + if (!connection_flows_.erase(remote_peer_id.GetId())) { return; } - entry->second->Close(); - connection_flows_.erase(remote_peer_id.GetId()); - // 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 = @@ -801,8 +734,8 @@ void WebRtc::RemoveConnectionFlow(const PeerId& remote_peer_id) { } } -void WebRtc::OffloadFromThread(Runnable runnable) { - single_thread_executor_.Execute(std::move(runnable)); +void WebRtc::OffloadFromThread(const std::string& name, Runnable runnable) { + single_thread_executor_.Execute(name, std::move(runnable)); } } // namespace mediums 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 index ac3ae2c2324..b22315e4d91 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc.h +++ b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc.h @@ -26,7 +26,6 @@ #include "core/internal/mediums/webrtc/webrtc_socket.h" #include "core/internal/mediums/webrtc/webrtc_socket_wrapper.h" #include "proto/connections/offline_wire_formats.pb.h" -#include "proto/connections/offline_wire_formats.pb.h" #include "platform/base/byte_array.h" #include "platform/base/cancellation_flag.h" #include "platform/base/listeners.h" @@ -209,18 +208,9 @@ class WebRtc { ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); // Runs on |single_thread_executor_|. - void ProcessDataChannelCreated( - const std::string& service_id, const PeerId& remote_peer_id, - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Runs on |single_thread_executor_|. - void ProcessDataChannelMessage(const PeerId& remote_peer_id, - const ByteArray& message) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Runs on |single_thread_executor_|. - void ProcessDataChannelBufferAmountChanged(const PeerId& remote_peer_id) + void ProcessDataChannelOpen(const std::string& service_id, + const PeerId& remote_peer_id, + WebRtcSocketWrapper socket_wrapper) ABSL_LOCKS_EXCLUDED(mutex_); // Runs on |single_thread_executor_|. @@ -241,7 +231,7 @@ class WebRtc { void RestartTachyonReceiveMessages(const std::string& service_id) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - void OffloadFromThread(Runnable runnable); + void OffloadFromThread(const std::string& name, Runnable runnable); Mutex mutex_; @@ -265,11 +255,6 @@ class WebRtc { // a unique ConnectionFlow. absl::flat_hash_map<std::string, std::unique_ptr<ConnectionFlow>> connection_flows_ ABSL_GUARDED_BY(mutex_); - - // A map of a remote PeerId -> Socket. Non-empty while we have active - // connections. - absl::flat_hash_map<std::string, WebRtcSocketWrapper> sockets_ - ABSL_GUARDED_BY(mutex_); }; } // namespace mediums 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 index a310c2aa2ee..ddff64b2f6f 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/BUILD +++ b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/BUILD @@ -16,8 +16,6 @@ cc_library( name = "webrtc", srcs = [ "connection_flow.cc", - "data_channel_observer_impl.cc", - "peer_connection_observer_impl.cc", "peer_id.cc", "signaling_frames.cc", "webrtc_socket.cc", @@ -25,9 +23,7 @@ cc_library( hdrs = [ "connection_flow.h", "data_channel_listener.h", - "data_channel_observer_impl.h", "local_ice_candidate_listener.h", - "peer_connection_observer_impl.h", "peer_id.h", "session_description_wrapper.h", "signaling_frames.h", @@ -54,6 +50,7 @@ cc_library( cc_test( name = "webrtc_test", + timeout = "short", srcs = [ "connection_flow_test.cc", "peer_id_test.cc", 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 index ff8582c92d1..af11aa945de 100644 --- 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 @@ -18,6 +18,8 @@ #include <memory> #include "core/internal/mediums/webrtc/session_description_wrapper.h" +#include "core/internal/mediums/webrtc/webrtc_socket.h" +#include "core/internal/mediums/webrtc/webrtc_socket_wrapper.h" #include "platform/public/logging.h" #include "platform/public/mutex_lock.h" #include "platform/public/webrtc.h" @@ -32,57 +34,87 @@ namespace connections { namespace mediums { constexpr absl::Duration ConnectionFlow::kTimeout; +constexpr absl::Duration ConnectionFlow::kPeerConnectionTimeout; -namespace { // This is the same as the nearby data channel name. -const char kDataChannelName[] = "dataChannel"; +constexpr char kDataChannelName[] = "dataChannel"; class CreateSessionDescriptionObserverImpl : public webrtc::CreateSessionDescriptionObserver { public: - explicit CreateSessionDescriptionObserverImpl( - Future<SessionDescriptionWrapper>* settable_future) - : settable_future_(settable_future) {} - ~CreateSessionDescriptionObserverImpl() override = default; + 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 { - settable_future_->Set(SessionDescriptionWrapper{desc}); + 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}); + settable_future_.SetException({Exception::kFailed}); } private: - std::unique_ptr<Future<SessionDescriptionWrapper>> settable_future_; + ConnectionFlow* connection_flow_; + Future<SessionDescriptionWrapper> settable_future_; + ConnectionFlow::State expected_entry_state_; + ConnectionFlow::State exit_state_; }; -class SetSessionDescriptionObserverImpl - : public webrtc::SetSessionDescriptionObserver { +class SetDescriptionObserverBase { public: - explicit SetSessionDescriptionObserverImpl(Future<bool>* settable_future) - : settable_future_(settable_future) {} - - void OnSuccess() override { settable_future_->Set(true); } + ExceptionOr<bool> GetResult(absl::Duration timeout) { + return settable_future_.Get(timeout); + } - void OnFailure(webrtc::RTCError error) override { - NEARBY_LOG(ERROR, "Error when setting session description: %s", - error.message()); - settable_future_->SetException({Exception::kFailed}); + 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: - std::unique_ptr<Future<bool>> settable_future_; + 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; -} // namespace - std::unique_ptr<ConnectionFlow> ConnectionFlow::Create( LocalIceCandidateListener local_ice_candidate_listener, DataChannelListener data_channel_listener, WebRtcMedium& webrtc_medium) { @@ -100,147 +132,222 @@ ConnectionFlow::ConnectionFlow( LocalIceCandidateListener local_ice_candidate_listener, DataChannelListener data_channel_listener) : data_channel_listener_(std::move(data_channel_listener)), - peer_connection_observer_(this, std::move(local_ice_candidate_listener)) { -} + local_ice_candidate_listener_(std::move(local_ice_candidate_listener)) {} -ConnectionFlow::~ConnectionFlow() { Close(); } - -ConnectionFlow::State ConnectionFlow::GetState() { - MutexLock lock(&mutex_); - return state_; +ConnectionFlow::~ConnectionFlow() { + NEARBY_LOG(INFO, "~ConnectionFlow"); + RunOnSignalingThread([this] { CloseOnSignalingThread(); }); + shutdown_latch_.Await(); + NEARBY_LOG(INFO, "~ConnectionFlow done"); } SessionDescriptionWrapper ConnectionFlow::CreateOffer() { - MutexLock lock(&mutex_); - - if (!TransitionState(State::kInitialized, State::kCreatingOffer)) { + 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; - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel = - peer_connection_->CreateDataChannel(kDataChannelName, &data_channel_init); - data_channel->RegisterObserver(CreateDataChannelObserver(data_channel)); + auto pc = GetPeerConnection(); + CreateSocketFromDataChannel( + pc->CreateDataChannel(kDataChannelName, &data_channel_init)); - auto success_future = new Future<SessionDescriptionWrapper>(); webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options; rtc::scoped_refptr<CreateSessionDescriptionObserverImpl> observer = new rtc::RefCountedObject<CreateSessionDescriptionObserverImpl>( - success_future); - peer_connection_->CreateOffer(observer, options); + this, success_future, State::kCreatingOffer, + State::kWaitingForAnswer); + pc->CreateOffer(observer, options); +} - ExceptionOr<SessionDescriptionWrapper> result = success_future->Get(kTimeout); - if (result.ok() && - TransitionState(State::kCreatingOffer, State::kWaitingForAnswer)) { +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(); } -SessionDescriptionWrapper ConnectionFlow::CreateAnswer() { - MutexLock lock(&mutex_); - +void ConnectionFlow::CreateAnswerOnSignalingThread( + Future<SessionDescriptionWrapper> success_future) { if (!TransitionState(State::kReceivedOffer, State::kCreatingAnswer)) { - return SessionDescriptionWrapper(); + success_future.SetException({Exception::kFailed}); + return; } - - auto success_future = new Future<SessionDescriptionWrapper>(); webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options; rtc::scoped_refptr<CreateSessionDescriptionObserverImpl> observer = new rtc::RefCountedObject<CreateSessionDescriptionObserverImpl>( - success_future); - peer_connection_->CreateAnswer(observer, options); - - ExceptionOr<SessionDescriptionWrapper> result = success_future->Get(kTimeout); - if (result.ok() && - TransitionState(State::kCreatingAnswer, State::kWaitingToConnect)) { - return std::move(result.result()); - } - - return SessionDescriptionWrapper(); + this, success_future, State::kCreatingAnswer, + State::kWaitingToConnect); + auto pc = GetPeerConnection(); + pc->CreateAnswer(observer, options); } bool ConnectionFlow::SetLocalSessionDescription(SessionDescriptionWrapper sdp) { - MutexLock lock(&mutex_); - + CHECK(!IsRunningOnSignalingThread()); if (!sdp.IsValid()) return false; - auto success_future = new Future<bool>(); - rtc::scoped_refptr<SetSessionDescriptionObserverImpl> observer = - new rtc::RefCountedObject<SetSessionDescriptionObserverImpl>( - success_future); + rtc::scoped_refptr<SetLocalDescriptionObserver> observer = + new rtc::RefCountedObject<SetLocalDescriptionObserver>(); - peer_connection_->SetLocalDescription(observer, sdp.Release()); + 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(); - ExceptionOr<bool> result = success_future->Get(kTimeout); - return result.ok() && result.result(); + 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) { +bool ConnectionFlow::SetRemoteSessionDescription(SessionDescriptionWrapper sdp, + State expected_entry_state, + State exit_state) { if (!sdp.IsValid()) return false; - auto success_future = new Future<bool>(); - rtc::scoped_refptr<SetSessionDescriptionObserverImpl> observer = - new rtc::RefCountedObject<SetSessionDescriptionObserverImpl>( - success_future); + rtc::scoped_refptr<SetRemoteDescriptionObserver> observer = + new rtc::RefCountedObject<SetRemoteDescriptionObserver>(); - peer_connection_->SetRemoteDescription(observer, sdp.Release()); + 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(); - ExceptionOr<bool> result = success_future->Get(kTimeout); - return result.ok() && result.result(); + 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) { - MutexLock lock(&mutex_); - - if (!TransitionState(State::kInitialized, State::kReceivedOffer)) { - return false; - } - return SetRemoteSessionDescription(std::move(offer)); + CHECK(!IsRunningOnSignalingThread()); + return SetRemoteSessionDescription(std::move(offer), State::kInitialized, + State::kReceivedOffer); } bool ConnectionFlow::OnAnswerReceived(SessionDescriptionWrapper answer) { - MutexLock lock(&mutex_); + 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 (!TransitionState(State::kWaitingForAnswer, State::kWaitingToConnect)) { + if (!pc) { return false; } - return SetRemoteSessionDescription(std::move(answer)); + 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; } -bool ConnectionFlow::OnRemoteIceCandidatesReceived( +void ConnectionFlow::AddIceCandidatesOnSignalingThread( std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> ice_candidates) { - MutexLock lock(&mutex_); - + CHECK(IsRunningOnSignalingThread()); if (state_ == State::kEnded) { NEARBY_LOG(WARNING, "You cannot add ice candidates to a disconnected session."); - return false; + 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 true; + return; } - + auto pc = GetPeerConnection(); for (auto&& ice_candidate : ice_candidates) { - if (!peer_connection_->AddIceCandidate(ice_candidate.get())) { + if (!pc->AddIceCandidate(ice_candidate.get())) { NEARBY_LOG(WARNING, "Unable to add remote ice candidate."); } } - return true; } -bool ConnectionFlow::Close() { - MutexLock lock(&mutex_); - return CloseLocked(); +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) { @@ -250,7 +357,7 @@ bool ConnectionFlow::InitPeerConnection(WebRtcMedium& webrtc_medium) { // to access, but it is not safe to access ConnectionFlow member variables // unless the Future::Set() returns true. webrtc_medium.CreatePeerConnection( - &peer_connection_observer_, + this, [this, success_future](rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection) mutable { if (!peer_connection) { @@ -263,74 +370,107 @@ bool ConnectionFlow::InitPeerConnection(WebRtcMedium& webrtc_medium) { // 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(kTimeout); - return result.ok() && result.result(); + 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() { - MutexLock lock(&mutex_); - if (state_ != State::kWaitingToConnect && state_ != State::kConnected) return; - + auto pc = GetPeerConnection(); for (auto&& ice_candidate : cached_remote_ice_candidates_) { - if (!peer_connection_->AddIceCandidate(ice_candidate.get())) { + if (!pc->AddIceCandidate(ice_candidate.get())) { NEARBY_LOG(WARNING, "Unable to add remote ice candidate."); } } cached_remote_ice_candidates_.clear(); } -void ConnectionFlow::ProcessOnPeerConnectionChange( - webrtc::PeerConnectionInterface::PeerConnectionState new_state) { - if (new_state == PeerConnectionState::kClosed || - new_state == PeerConnectionState::kFailed || - new_state == PeerConnectionState::kDisconnected) { - Close(); +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::ProcessDataChannelConnected( +void ConnectionFlow::OnDataChannel( rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) { - MutexLock lock(&mutex_); - NEARBY_LOG(INFO, "Data channel state changed to connected."); - if (!TransitionState(State::kWaitingToConnect, State::kConnected)) { - data_channel->Close(); - return; - } + NEARBY_LOG(INFO, "OnDataChannel"); + CHECK(IsRunningOnSignalingThread()); + CreateSocketFromDataChannel(std::move(data_channel)); +} - data_channel_listener_.data_channel_created_cb(std::move(data_channel)); +void ConnectionFlow::OnIceGatheringChange( + webrtc::PeerConnectionInterface::IceGatheringState new_state) { + NEARBY_LOG(INFO, "OnIceGatheringChange: %d", new_state); + CHECK(IsRunningOnSignalingThread()); } -webrtc::DataChannelObserver* ConnectionFlow::CreateDataChannelObserver( - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) { - if (!data_channel_observer_) { - auto state_change_callback = [this, - data_channel{std::move(data_channel)}]() { - if (data_channel->state() == - webrtc::DataChannelInterface::DataState::kOpen) { - OffloadFromSignalingThread( - [this, data_channel{std::move(data_channel)}]() { - ProcessDataChannelConnected(std::move(data_channel)); - }); - } else if (data_channel->state() == - webrtc::DataChannelInterface::DataState::kClosed) { - data_channel->UnregisterObserver(); - data_channel_listener_.data_channel_closed_cb(); - } - }; - data_channel_observer_ = absl::make_unique<DataChannelObserverImpl>( - &data_channel_listener_, std::move(state_change_callback)); +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(); } +} - return reinterpret_cast<webrtc::DataChannelObserver*>( - data_channel_observer_.get()); +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, @@ -338,31 +478,79 @@ bool ConnectionFlow::TransitionState(State current_state, State new_state) { new_state, state_, current_state); return false; } + NEARBY_LOG(INFO, "Transition: %d -> %d", state_, new_state); state_ = new_state; return true; } -bool ConnectionFlow::CloseLocked() { - NEARBY_LOG(INFO, "Closing WebRTC connection."); +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; +} - single_threaded_signaling_offloader_.Shutdown(); - peer_connection_observer_.DisconnectConnectionFlow(); - - if (peer_connection_) peer_connection_->Close(); - - data_channel_observer_.reset(); - NEARBY_LOG(INFO, "Closed WebRTC connection."); +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; } -void ConnectionFlow::OffloadFromSignalingThread(Runnable runnable) { - single_threaded_signaling_offloader_.Execute(std::move(runnable)); +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 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 index f524794a733..7ac24869c9f 100644 --- 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 @@ -18,11 +18,11 @@ #include <memory> #include "core/internal/mediums/webrtc/data_channel_listener.h" -#include "core/internal/mediums/webrtc/data_channel_observer_impl.h" #include "core/internal/mediums/webrtc/local_ice_candidate_listener.h" -#include "core/internal/mediums/webrtc/peer_connection_observer_impl.h" #include "core/internal/mediums/webrtc/session_description_wrapper.h" +#include "core/internal/mediums/webrtc/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" @@ -66,7 +66,7 @@ namespace mediums { * previous states if we disconnect at any point in the flow. * </ul> */ -class ConnectionFlow { +class ConnectionFlow : public webrtc::PeerConnectionObserver { public: enum class State { kInitialized, @@ -80,90 +80,149 @@ class ConnectionFlow { }; // 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(); - - // Returns the current state of the ConnectionFlow. - State GetState() ABSL_LOCKS_EXCLUDED(mutex_); + ~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. - bool Close() ABSL_LOCKS_EXCLUDED(mutex_); - - // Invoked when the peer connection indicates that signaling is stable. - void OnSignalingStable() ABSL_LOCKS_EXCLUDED(mutex_); - webrtc::DataChannelObserver* CreateDataChannelObserver( - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel); - - // Invoked upon changes in the state of peer connection, e.g. react to - // disconnect. - void ProcessOnPeerConnectionChange( - webrtc::PeerConnectionInterface::PeerConnectionState new_state) - 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) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + bool TransitionState(State current_state, State new_state); - bool SetRemoteSessionDescription(SessionDescriptionWrapper sdp); + bool SetRemoteSessionDescription(SessionDescriptionWrapper sdp, + State expected_entry_state, + State exit_state); - void ProcessDataChannelConnected( - rtc::scoped_refptr<webrtc::DataChannelInterface>) - ABSL_LOCKS_EXCLUDED(mutex_); - - void CloseAndNotifyLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - bool CloseLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + bool CloseOnSignalingThread() ABSL_LOCKS_EXCLUDED(mutex_); - void OffloadFromSignalingThread(Runnable runnable); + 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 state_ ABSL_GUARDED_BY(mutex_) = State::kInitialized; + // 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_; - std::unique_ptr<DataChannelObserverImpl> data_channel_observer_; - - PeerConnectionObserverImpl peer_connection_observer_; - rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_; + 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_ ABSL_GUARDED_BY(mutex_); - - SingleThreadExecutor single_threaded_signaling_offloader_; + 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 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 index c29d7577b95..04bf9f1fbdb 100644 --- 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 @@ -18,8 +18,10 @@ #include <vector> #include "core/internal/mediums/webrtc/session_description_wrapper.h" +#include "core/internal/mediums/webrtc/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 "gmock/gmock.h" #include "gtest/gtest.h" @@ -57,10 +59,7 @@ TEST_F(ConnectionFlowTest, SuccessfulOfferAnswerFlow) { Future<ByteArray> message_received_future; - Future<rtc::scoped_refptr<webrtc::DataChannelInterface>> - offerer_data_channel_future; - Future<rtc::scoped_refptr<webrtc::DataChannelInterface>> - answerer_data_channel_future; + Future<WebRtcSocketWrapper> offerer_socket_future, answerer_socket_future; std::unique_ptr<ConnectionFlow> offerer, answerer; @@ -75,10 +74,9 @@ TEST_F(ConnectionFlowTest, SuccessfulOfferAnswerFlow) { if (answerer) answerer->OnRemoteIceCandidatesReceived(std::move(vec)); }}, - {.data_channel_created_cb = - [&offerer_data_channel_future]( - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) { - offerer_data_channel_future.Set(std::move(data_channel)); + {.data_channel_open_cb = + [&offerer_socket_future](WebRtcSocketWrapper socket) { + offerer_socket_future.Set(std::move(socket)); }}, webrtc_medium_offerer); ASSERT_NE(offerer, nullptr); @@ -92,14 +90,9 @@ TEST_F(ConnectionFlowTest, SuccessfulOfferAnswerFlow) { if (offerer) offerer->OnRemoteIceCandidatesReceived(std::move(vec)); }}, - {.data_channel_created_cb = - [&answerer_data_channel_future]( - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) { - answerer_data_channel_future.Set(std::move(data_channel)); - }, - .data_channel_message_received_cb = - [&message_received_future](ByteArray bytes) { - message_received_future.Set(std::move(bytes)); + {.data_channel_open_cb = + [&answerer_socket_future](WebRtcSocketWrapper socket) { + answerer_socket_future.Set(std::move(socket)); }}, webrtc_medium_answerer); ASSERT_NE(answerer, nullptr); @@ -117,18 +110,19 @@ TEST_F(ConnectionFlowTest, SuccessfulOfferAnswerFlow) { EXPECT_TRUE(answerer->SetLocalSessionDescription(std::move(answer))); // Retrieve Data Channels - ExceptionOr<rtc::scoped_refptr<webrtc::DataChannelInterface>> - offerer_channel = offerer_data_channel_future.Get(absl::Seconds(1)); - EXPECT_TRUE(offerer_channel.ok()); - ExceptionOr<rtc::scoped_refptr<webrtc::DataChannelInterface>> - answerer_channel = answerer_data_channel_future.Get(absl::Seconds(1)); - EXPECT_TRUE(answerer_channel.ok()); + 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_channel.result()->Send(webrtc::DataBuffer(message)); + offerer_socket.result().GetImpl().GetOutputStream().Write( + ByteArray(message, 4)); ExceptionOr<ByteArray> received_message = - message_received_future.Get(absl::Seconds(1)); + answerer_socket.result().GetImpl().GetInputStream().Read(4); EXPECT_TRUE(received_message.ok()); EXPECT_EQ(received_message.result(), ByteArray{message}); } @@ -173,7 +167,7 @@ TEST_F(ConnectionFlowTest, CannotCreateOfferAfterClose) { LocalIceCandidateListener(), DataChannelListener(), webrtc_medium); ASSERT_NE(offerer, nullptr); - EXPECT_TRUE(offerer->Close()); + EXPECT_TRUE(offerer->CloseIfNotConnected()); EXPECT_FALSE(offerer->CreateOffer().IsValid()); } @@ -188,7 +182,7 @@ TEST_F(ConnectionFlowTest, CannotSetSessionDescriptionAfterClose) { SessionDescriptionWrapper offer = offerer->CreateOffer(); EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - EXPECT_TRUE(offerer->Close()); + EXPECT_TRUE(offerer->CloseIfNotConnected()); EXPECT_FALSE(offerer->SetLocalSessionDescription(offer)); } @@ -205,7 +199,7 @@ TEST_F(ConnectionFlowTest, CannotReceiveOfferAfterClose) { webrtc_medium_answerer); ASSERT_NE(answerer, nullptr); - EXPECT_TRUE(answerer->Close()); + EXPECT_TRUE(answerer->CloseIfNotConnected()); SessionDescriptionWrapper offer = offerer->CreateOffer(); EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); @@ -223,6 +217,179 @@ TEST_F(ConnectionFlowTest, NullPeerConnection) { 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(); + 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(); + 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(); + 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(); + 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 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 index ee4587521a9..9e2c71a9231 100644 --- 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 @@ -15,6 +15,7 @@ #ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_DATA_CHANNEL_LISTENER_H_ #define CORE_INTERNAL_MEDIUMS_WEBRTC_DATA_CHANNEL_LISTENER_H_ +#include "core/internal/mediums/webrtc/webrtc_socket_wrapper.h" #include "core/listeners.h" #include "platform/base/byte_array.h" @@ -25,19 +26,10 @@ namespace mediums { // Callbacks from the data channel. struct DataChannelListener { - // Called when the data channel is created. - std::function<void(rtc::scoped_refptr<webrtc::DataChannelInterface>)> - data_channel_created_cb = - DefaultCallback<rtc::scoped_refptr<webrtc::DataChannelInterface>>(); - - // Called when a new message was received on the data channel. - std::function<void(const ByteArray&)> data_channel_message_received_cb = - DefaultCallback<const ByteArray&>(); - - // Called when the data channel indicates that the buffered amount has - // changed. - std::function<void()> data_channel_buffered_amount_changed_cb = - DefaultCallback<>(); + // 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<>(); diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/data_channel_observer_impl.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/data_channel_observer_impl.cc deleted file mode 100644 index cba998d679a..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/data_channel_observer_impl.cc +++ /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. - -#include "core/internal/mediums/webrtc/data_channel_observer_impl.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -DataChannelObserverImpl::DataChannelObserverImpl( - DataChannelListener* data_channel_listener, - DataChannelStateChangeCallback callback) - : data_channel_listener_(data_channel_listener), - state_change_callback_(std::move(callback)) {} - -void DataChannelObserverImpl::OnStateChange() { state_change_callback_(); } - -void DataChannelObserverImpl::OnMessage(const webrtc::DataBuffer& buffer) { - data_channel_listener_->data_channel_message_received_cb( - ByteArray(buffer.data.data<char>(), buffer.size())); -} - -void DataChannelObserverImpl::OnBufferedAmountChange(uint64_t sent_data_size) { - data_channel_listener_->data_channel_buffered_amount_changed_cb(); -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/data_channel_observer_impl.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/data_channel_observer_impl.h deleted file mode 100644 index 4de3f346b92..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/data_channel_observer_impl.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_WEBRTC_DATA_CHANNEL_OBSERVER_IMPL_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_DATA_CHANNEL_OBSERVER_IMPL_H_ - -#include "core/internal/mediums/webrtc/data_channel_listener.h" -#include "webrtc/api/data_channel_interface.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -class DataChannelObserverImpl : public webrtc::DataChannelObserver { - public: - using DataChannelStateChangeCallback = std::function<void()>; - - ~DataChannelObserverImpl() override = default; - DataChannelObserverImpl(DataChannelListener* data_channel_listener, - DataChannelStateChangeCallback callback); - - // webrtc::DataChannelObserver: - void OnStateChange() override; - void OnMessage(const webrtc::DataBuffer& buffer) override; - void OnBufferedAmountChange(uint64_t sent_data_size) override; - - private: - DataChannelListener* data_channel_listener_; - DataChannelStateChangeCallback state_change_callback_; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_DATA_CHANNEL_OBSERVER_IMPL_H_ diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/peer_connection_observer_impl.cc b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/peer_connection_observer_impl.cc deleted file mode 100644 index 950b2dcbf46..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/peer_connection_observer_impl.cc +++ /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. - -#include "core/internal/mediums/webrtc/peer_connection_observer_impl.h" - -#include "core/internal/mediums/webrtc/connection_flow.h" -#include "platform/public/logging.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -PeerConnectionObserverImpl::PeerConnectionObserverImpl( - ConnectionFlow* connection_flow, - LocalIceCandidateListener local_ice_candidate_listener) - : connection_flow_(connection_flow), - local_ice_candidate_listener_(std::move(local_ice_candidate_listener)) {} - -PeerConnectionObserverImpl::~PeerConnectionObserverImpl() { - MutexLock lock(&mutex_); - connection_flow_ = nullptr; -} - -void PeerConnectionObserverImpl::OnIceCandidate( - const webrtc::IceCandidateInterface* candidate) { - local_ice_candidate_listener_.local_ice_candidate_found_cb(candidate); -} - -void PeerConnectionObserverImpl::OnSignalingChange( - webrtc::PeerConnectionInterface::SignalingState new_state) { - NEARBY_LOG(INFO, "OnSignalingChange: %d", new_state); - - OffloadFromSignalingThread([this, new_state]() { - MutexLock lock(&mutex_); - if (new_state == webrtc::PeerConnectionInterface::SignalingState::kStable && - connection_flow_) { - connection_flow_->OnSignalingStable(); - } - }); -} - -void PeerConnectionObserverImpl::OnDataChannel( - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) { - NEARBY_LOG(INFO, "OnDataChannel"); - - webrtc::DataChannelObserver* data_channel_observer = nullptr; - { - MutexLock lock(&mutex_); - if (!connection_flow_) { - return; - } - - data_channel_observer = - connection_flow_->CreateDataChannelObserver(data_channel); - } - data_channel->RegisterObserver(data_channel_observer); -} - -void PeerConnectionObserverImpl::OnIceGatheringChange( - webrtc::PeerConnectionInterface::IceGatheringState new_state) { - NEARBY_LOG(INFO, "OnIceGatheringChange: %d", new_state); -} - -void PeerConnectionObserverImpl::OnConnectionChange( - webrtc::PeerConnectionInterface::PeerConnectionState new_state) { - NEARBY_LOG(INFO, "OnConnectionChange: %d", new_state); - - OffloadFromSignalingThread([this, new_state]() { - MutexLock lock(&mutex_); - if (connection_flow_) { - connection_flow_->ProcessOnPeerConnectionChange(new_state); - } - }); -} - -void PeerConnectionObserverImpl ::OnRenegotiationNeeded() { - NEARBY_LOG(INFO, "OnRenegotiationNeeded"); -} - -void PeerConnectionObserverImpl::DisconnectConnectionFlow() { - MutexLock lock(&mutex_); - connection_flow_ = nullptr; -} - -void PeerConnectionObserverImpl::OffloadFromSignalingThread(Runnable runnable) { - single_threaded_signaling_offloader_.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/peer_connection_observer_impl.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/peer_connection_observer_impl.h deleted file mode 100644 index 7bcd86b1812..00000000000 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/peer_connection_observer_impl.h +++ /dev/null @@ -1,68 +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_CONNECTION_OBSERVER_IMPL_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_PEER_CONNECTION_OBSERVER_IMPL_H_ - -#include "core/internal/mediums/webrtc/local_ice_candidate_listener.h" -#include "platform/public/single_thread_executor.h" -#include "webrtc/api/peer_connection_interface.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -class ConnectionFlow; - -class PeerConnectionObserverImpl : public webrtc::PeerConnectionObserver { - public: - PeerConnectionObserverImpl( - ConnectionFlow* connection_flow, - LocalIceCandidateListener local_ice_candidate_listener); - ~PeerConnectionObserverImpl() override; - - // webrtc::PeerConnectionObserver: - void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override; - void OnSignalingChange( - webrtc::PeerConnectionInterface::SignalingState new_state) override - ABSL_LOCKS_EXCLUDED(mutex_); - void OnDataChannel( - rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) override - ABSL_LOCKS_EXCLUDED(mutex_); - void OnIceGatheringChange( - webrtc::PeerConnectionInterface::IceGatheringState new_state) override; - void OnConnectionChange( - webrtc::PeerConnectionInterface::PeerConnectionState new_state) override - ABSL_LOCKS_EXCLUDED(mutex_); - void OnRenegotiationNeeded() override; - - void DisconnectConnectionFlow() ABSL_LOCKS_EXCLUDED(mutex_); - - private: - void OffloadFromSignalingThread(Runnable runnable); - - // NOTE: This must be a recursive mutex due to the call interactions. - RecursiveMutex mutex_; // protects access to connection_flow_ - ConnectionFlow* connection_flow_ ABSL_GUARDED_BY(mutex_); - LocalIceCandidateListener local_ice_candidate_listener_; - SingleThreadExecutor single_threaded_signaling_offloader_; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_PEER_CONNECTION_OBSERVER_IMPL_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 index aabd386680d..6fe8384ac09 100644 --- 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 @@ -86,11 +86,11 @@ TEST(SignalingFramesTest, SignalingPoke) { location::nearby::mediums::WebRtcSignalingFrame frame; frame.ParseFromString(std::string(encoded_poke.data(), encoded_poke.size())); - EXPECT_THAT(frame, testing::EqualsProto(R"( + 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) { 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 index 1d030929838..71d80ce7fa9 100644 --- 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 @@ -37,6 +37,7 @@ Exception WebRtcSocket::OutputStreamImpl::Write(const ByteArray& data) { } if (!socket_->SendMessage(data)) { + NEARBY_LOG(INFO, "Unable to write data to socket."); return {Exception::kIo}; } return {Exception::kSuccess}; @@ -56,32 +57,89 @@ Exception WebRtcSocket::OutputStreamImpl::Close() { WebRtcSocket::WebRtcSocket( const std::string& name, rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) - : name_(name), data_channel_(std::move(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; - pipe_.GetInputStream().Close(); - pipe_.GetOutputStream().Close(); + 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(); - WakeUpWriter(); - socket_closed_listener_.socket_closed_cb(); + NEARBY_LOGS(INFO) << "WebRtcSocket::Close(" << name_ << ") this: " << this + << " done"; } -void WebRtcSocket::NotifyDataChannelMsgReceived(const ByteArray& message) { - if (!pipe_.GetOutputStream().Write(message).Ok()) { - Close(); - return; +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)) { + ClosePipe(); + } + break; } - - if (!pipe_.GetOutputStream().Flush().Ok()) Close(); +} +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::NotifyDataChannelBufferedAmountChanged() { WakeUpWriter(); } +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( @@ -90,13 +148,26 @@ bool WebRtcSocket::SendMessage(const ByteArray& data) { 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"; +} + void WebRtcSocket::WakeUpWriter() { MutexLock lock(&backpressure_mutex_); buffer_variable_.Notify(); } -void WebRtcSocket::SetOnSocketClosedListener(SocketClosedListener&& listener) { - socket_closed_listener_ = std::move(listener); +void WebRtcSocket::SetSocketListener(SocketListener&& listener) { + socket_listener_ = std::move(listener); } void WebRtcSocket::BlockUntilSufficientSpaceInBuffer(int length) { @@ -108,6 +179,10 @@ void WebRtcSocket::BlockUntilSufficientSpaceInBuffer(int length) { } } +void WebRtcSocket::OffloadFromSignalingThread(Runnable runnable) { + single_thread_executor_.Execute(std::move(runnable)); +} + } // namespace mediums } // namespace connections } // namespace nearby 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 index 37bf0480f0b..a65f2d5d9ed 100644 --- 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 @@ -25,7 +25,9 @@ #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 { @@ -39,11 +41,11 @@ constexpr int kMaxDataSize = 1 * 1024 * 1024; // // Messages are buffered here to prevent the data channel from overflowing, // which could lead to data loss. -class WebRtcSocket : public Socket { +class WebRtcSocket : public Socket, public webrtc::DataChannelObserver { public: WebRtcSocket(const std::string& name, rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel); - ~WebRtcSocket() override = default; + ~WebRtcSocket() override; WebRtcSocket(const WebRtcSocket& other) = delete; WebRtcSocket& operator=(const WebRtcSocket& other) = delete; @@ -53,20 +55,20 @@ class WebRtcSocket : public Socket { OutputStream& GetOutputStream() override; void Close() override; - // Callback from WebRTC data channel when new message has been received from - // the remote. - void NotifyDataChannelMsgReceived(const ByteArray& message); - - // Callback from WebRTC data channel that the buffered data amount has - // changed. - void NotifyDataChannelBufferedAmountChanged(); - - // Listener class the gets called when the socket is closed. - struct SocketClosedListener { - std::function<void()> socket_closed_cb = DefaultCallback<>(); + // 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 SetOnSocketClosedListener(SocketClosedListener&& listener); + void SetSocketListener(SocketListener&& listener); private: class OutputStreamImpl : public OutputStream { @@ -89,8 +91,10 @@ class WebRtcSocket : public 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_; @@ -101,10 +105,14 @@ class WebRtcSocket : public Socket { AtomicBoolean closed_{false}; - SocketClosedListener socket_closed_listener_; + 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 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 index 72c4e346790..7ff3886163a 100644 --- 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 @@ -58,23 +58,23 @@ class MockDataChannel } // namespace TEST(WebRtcSocketTest, ReadFromSocket) { - const ByteArray kMessage{"Message"}; + const char* message = "message"; rtc::scoped_refptr<MockDataChannel> mock_data_channel = new MockDataChannel(); WebRtcSocket webrtc_socket(kSocketName, mock_data_channel); - webrtc_socket.NotifyDataChannelMsgReceived(kMessage); + webrtc_socket.OnMessage(webrtc::DataBuffer{message}); ExceptionOr<ByteArray> result = webrtc_socket.GetInputStream().Read(7); EXPECT_TRUE(result.ok()); - EXPECT_EQ(result.result(), kMessage); + 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.NotifyDataChannelMsgReceived(ByteArray{"Me"}); - webrtc_socket.NotifyDataChannelMsgReceived(ByteArray{"ssa"}); - webrtc_socket.NotifyDataChannelMsgReceived(ByteArray{"ge"}); + webrtc_socket.OnMessage(webrtc::DataBuffer{"Me"}); + webrtc_socket.OnMessage(webrtc::DataBuffer{"ssa"}); + webrtc_socket.OnMessage(webrtc::DataBuffer{"ge"}); ExceptionOr<ByteArray> result; @@ -131,10 +131,19 @@ TEST(WebRtcSocketTest, Close) { int socket_closed_cb_called = 0; - webrtc_socket.SetOnSocketClosedListener( - {.socket_closed_cb = [&]() { socket_closed_cb_called++; }}); + 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); } @@ -162,6 +171,63 @@ TEST(WebRtcSocketTest, ReadFromClosedChannel) { 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 diff --git a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket_wrapper.h b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket_wrapper.h index 67c8e2b5604..4da6151deb3 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket_wrapper.h +++ b/chromium/third_party/nearby/src/cpp/core/internal/mediums/webrtc/webrtc_socket_wrapper.h @@ -37,14 +37,6 @@ class WebRtcSocketWrapper final { OutputStream& GetOutputStream() { return impl_->GetOutputStream(); } - void NotifyDataChannelMsgReceived(const ByteArray& message) { - impl_->NotifyDataChannelMsgReceived(message); - } - - void NotifyDataChannelBufferedAmountChanged() { - impl_->NotifyDataChannelBufferedAmountChanged(); - } - void Close() { return impl_->Close(); } bool IsValid() const { return impl_ != nullptr; } 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 index f37dc5a4263..1a0e9a0f283 100644 --- 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 @@ -384,12 +384,12 @@ TEST_F(WebRtcTest, ContinueAcceptingConnectionsOnComplete) { // Simulate a failure in receiving messages stream, WebRtc should restart // accepting connections. env_.SendWebRtcSignalingComplete(self_id.GetId(), - /*success=*/false); + /*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); + /*success=*/true); EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); webrtc.StopAcceptingConnections(service_id); 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 index 782807f4983..cf0e5427b56 100644 --- 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 @@ -222,7 +222,6 @@ bool WifiLan::IsAcceptingConnectionsLocked(const std::string& service_id) { return accepting_connections_info_.Existed(service_id); } -// TODO(b/169303284): Handles Cancellation and registration. WifiLanSocket WifiLan::Connect(WifiLanService& wifi_lan_service, const std::string& service_id, CancellationFlag* cancellation_flag) { 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 index af83a034f11..5ac4c920525 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames.cc +++ b/chromium/third_party/nearby/src/cpp/core/internal/offline_frames.cc @@ -20,7 +20,6 @@ #include "core/internal/message_lite.h" #include "core/internal/offline_frames_validator.h" #include "core/status.h" -#include "proto/connections/offline_wire_formats.pb.h" #include "platform/base/byte_array.h" namespace location { @@ -65,9 +64,12 @@ V1Frame::FrameType GetFrameType(const OfflineFrame& frame) { ByteArray ForConnectionRequest(const std::string& endpoint_id, const ByteArray& endpoint_info, - std::int32_t nonce, bool supports_5_ghz, + std::int32_t nonce, + bool supports_5_ghz, const std::string& bssid, - const std::vector<Medium>& mediums) { + 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); @@ -90,6 +92,14 @@ ByteArray ForConnectionRequest(const std::string& endpoint_id, 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)); } 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 index b8694d74125..b50886de723 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/offline_frames.h +++ b/chromium/third_party/nearby/src/cpp/core/internal/offline_frames.h @@ -22,7 +22,6 @@ #include "proto/connections/offline_wire_formats.pb.h" #include "platform/base/byte_array.h" #include "platform/base/exception.h" -#include "proto/connections_enums.pb.h" namespace location { namespace nearby { @@ -45,9 +44,12 @@ 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, + std::int32_t nonce, + bool supports_5_ghz, const std::string& bssid, - const std::vector<Medium>& mediums); + 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. 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 index a64355d196f..cfe8b78762a 100644 --- 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 @@ -43,6 +43,8 @@ constexpr std::array<Medium, 9> kMediums = { 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; @@ -57,6 +59,8 @@ TEST(OfflineFramesTest, CanParseMessageFromBytes) { sub_frame->set_endpoint_name(kEndpointName); sub_frame->set_endpoint_info(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); @@ -101,12 +105,15 @@ TEST(OfflineFramesTest, CanGenerateConnectionRequest) { 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())); + std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis, + kKeepAliveTimeoutMillis); auto response = FromBytes(bytes); ASSERT_TRUE(response.ok()); OfflineFrame message = FromBytes(bytes).result(); 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 index 209d206b9dd..614c65f8e63 100644 --- 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 @@ -78,7 +78,7 @@ Exception EnsureValidConnectionResponseFrame( } Exception EnsureValidPayloadTransferDataFrame(const PayloadChunk& payload_chunk, - int totalSize) { + 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 @@ -100,7 +100,7 @@ Exception EnsureValidPayloadTransferDataFrame(const PayloadChunk& payload_chunk, } Exception EnsureValidPayloadTransferControlFrame( - const ControlMessage& control_message, int totalSize) { + const ControlMessage& control_message, std::int64_t totalSize) { if (!control_message.has_offset() || control_message.offset() < 0) return {Exception::kInvalidProtocolBuffer}; if (totalSize != InternalPayload::kIndeterminateSize && 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 index 09fecac483d..e659e86f09d 100644 --- 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 @@ -45,6 +45,8 @@ constexpr std::array<Medium, 9> kMediums = { 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; @@ -52,7 +54,8 @@ TEST(OfflineFramesValidatorTest, ValidatesAsOkWithValidConnectionRequestFrame) { ByteArray bytes = ForConnectionRequest( std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, kSupports5ghz, std::string(kBssid), - std::vector(kMediums.begin(), kMediums.end())); + std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis, + kKeepAliveTimeoutMillis); offline_frame.ParseFromString(std::string(bytes)); auto ret_value = EnsureValidOfflineFrame(offline_frame); @@ -67,7 +70,8 @@ TEST(OfflineFramesValidatorTest, ByteArray bytes = ForConnectionRequest( std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, kSupports5ghz, std::string(kBssid), - std::vector(kMediums.begin(), kMediums.end())); + std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis, + kKeepAliveTimeoutMillis); offline_frame.ParseFromString(std::string(bytes)); auto* v1_frame = offline_frame.mutable_v1(); @@ -86,7 +90,8 @@ TEST(OfflineFramesValidatorTest, ByteArray bytes = ForConnectionRequest( empty_enpoint_id, ByteArray{std::string(kEndpointName)}, kNonce, kSupports5ghz, std::string(kBssid), - std::vector(kMediums.begin(), kMediums.end())); + std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis, + kKeepAliveTimeoutMillis); offline_frame.ParseFromString(std::string(bytes)); auto ret_value = EnsureValidOfflineFrame(offline_frame); @@ -101,7 +106,8 @@ TEST(OfflineFramesValidatorTest, ByteArray empty_endpoint_info; ByteArray bytes = ForConnectionRequest( std::string(kEndpointId), empty_endpoint_info, kNonce, kSupports5ghz, - std::string(kBssid), std::vector(kMediums.begin(), kMediums.end())); + std::string(kBssid), std::vector(kMediums.begin(), kMediums.end()), + kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); offline_frame.ParseFromString(std::string(bytes)); auto ret_value = EnsureValidOfflineFrame(offline_frame); @@ -116,8 +122,8 @@ TEST(OfflineFramesValidatorTest, std::string empty_bssid; ByteArray bytes = ForConnectionRequest( std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, empty_bssid, - std::vector(kMediums.begin(), kMediums.end())); + kSupports5ghz, empty_bssid, std::vector(kMediums.begin(), kMediums.end()), + kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); offline_frame.ParseFromString(std::string(bytes)); auto ret_value = EnsureValidOfflineFrame(offline_frame); @@ -132,7 +138,8 @@ TEST(OfflineFramesValidatorTest, std::vector<Medium> empty_mediums; ByteArray bytes = ForConnectionRequest( std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce, - kSupports5ghz, std::string(kBssid), empty_mediums); + kSupports5ghz, std::string(kBssid), empty_mediums, + kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis); offline_frame.ParseFromString(std::string(bytes)); auto ret_value = EnsureValidOfflineFrame(offline_frame); 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 index d4299d02398..bbd9eb6e143 100644 --- 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 @@ -50,7 +50,15 @@ class OfflineSimulationUser { explicit OfflineSimulationUser( absl::string_view device_name, BooleanMediumSelector allowed = BooleanMediumSelector()) - : info_{ByteArray{std::string(device_name)}}, + : 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, 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 index f8cef073a1f..de793744635 100644 --- 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 @@ -206,155 +206,168 @@ bool P2pClusterPcpHandler::IsRecognizedBluetoothEndpoint( void P2pClusterPcpHandler::BluetoothDeviceDiscoveredHandler( ClientProxy* client, const std::string& service_id, BluetoothDevice device) { - RunOnPcpHandlerThread([this, client, service_id, - device]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOG(INFO, - "BT discovery handler (FOUND) [client=%p, service=%s]: not " - "in discovery mode", - client, service_id.c_str()); - return; - } + 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_LOG( + INFO, + "BT discovery handler (FOUND) [client=%p, service=%s]: not " + "in discovery mode", + client, service_id.c_str()); + return; + } - // Parse the Bluetooth device name. - const std::string device_name_string = device.GetName(); - BluetoothDeviceName device_name(device_name_string); + // 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)) - return; + // 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 discovered endpoint to the client. - NEARBY_LOGS(INFO) - << "Invoking BasePcpHandler::OnEndpointFound() for BT service=" - << service_id << "; id=" << device_name.GetEndpointId() << "; name=" - << absl::BytesToHexString(device_name.GetEndpointInfo().data()); - OnEndpointFound( - client, std::make_shared<BluetoothEndpoint>(BluetoothEndpoint{ + // Report the discovered endpoint to the client. + NEARBY_LOGS(INFO) + << "Invoking BasePcpHandler::OnEndpointFound() for BT service=" + << service_id << "; id=" << device_name.GetEndpointId() + << "; name=" + << 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([this, client, service_id, - device]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOG(INFO, - "BT discovery handler (CHANGED) [client=%p, service=%s]: not " - "in discovery mode", - client, service_id.c_str()); - return; - } - - // Parse the Bluetooth device name. - const std::string device_name_string = device.GetName(); - BluetoothDeviceName device_name(device_name_string); - NEARBY_LOG(INFO, - "BT discovery handler (CHANGED) [client=%p, service=%s]: " - "processing new name %s", - client, service_id.c_str(), device_name_string.c_str()); - - // 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_LOG(INFO, - "BT discovery handler (CHANGED) [client=%p, service=%s]: " - "comparing MAC addresses with existing endpoint %s. They have " - "MAC address %s and the new endpoint has MAC address %s.", - client, service_id.c_str(), - bluetoothEndpoint->bluetooth_device.GetName().c_str(), - bluetoothEndpoint->bluetooth_device.GetMacAddress().c_str(), - device.GetMacAddress().c_str()); - if (bluetoothEndpoint->bluetooth_device.GetMacAddress() == - device.GetMacAddress()) { - // Report the BluetoothEndpoint as lost to the client. - NEARBY_LOG( - INFO, - "BT discovery handler (LOST) [client=%p, service=%s]: report " - "to client", - client, service_id.c_str()); - 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_LOG(INFO, - "BT discovery handler (CHANGED) [client=%p, service=%s]: The " - "new name is not recognized. Ignoring.", - client, service_id.c_str()); - return; - } - - // Report the discovered endpoint to the client. - NEARBY_LOGS(INFO) - << "Invoking BasePcpHandler::OnEndpointFound() for BT service=" - << service_id << "; id=" << device_name.GetEndpointId() << "; name=" - << 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, - })); - }); + 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_LOG( + INFO, + "BT discovery handler (CHANGED) [client=%p, service=%s]: not " + "in discovery mode", + client, service_id.c_str()); + return; + } + + // Parse the Bluetooth device name. + const std::string device_name_string = device.GetName(); + BluetoothDeviceName device_name(device_name_string); + NEARBY_LOG(INFO, + "BT discovery handler (CHANGED) [client=%p, service=%s]: " + "processing new name %s", + client, service_id.c_str(), device_name_string.c_str()); + + // 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_LOG( + INFO, + "BT discovery handler (CHANGED) [client=%p, service=%s]: " + "comparing MAC addresses with existing endpoint %s. They have " + "MAC address %s and the new endpoint has MAC address %s.", + client, service_id.c_str(), + bluetoothEndpoint->bluetooth_device.GetName().c_str(), + bluetoothEndpoint->bluetooth_device.GetMacAddress().c_str(), + device.GetMacAddress().c_str()); + if (bluetoothEndpoint->bluetooth_device.GetMacAddress() == + device.GetMacAddress()) { + // Report the BluetoothEndpoint as lost to the client. + NEARBY_LOG( + INFO, + "BT discovery handler (LOST) [client=%p, service=%s]: report " + "to client", + client, service_id.c_str()); + 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_LOG( + INFO, + "BT discovery handler (CHANGED) [client=%p, service=%s]: The " + "new name is not recognized. Ignoring.", + client, service_id.c_str()); + return; + } + + // Report the discovered endpoint to the client. + NEARBY_LOGS(INFO) + << "Invoking BasePcpHandler::OnEndpointFound() for BT service=" + << service_id << "; id=" << device_name.GetEndpointId() << "; name=" + << 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([this, client, service_id, - device_name_string]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOG(INFO, - "BT discovery handler (LOST) [client=%p, service=%s]: not " - "in discovery mode", - client, service_id.c_str()); - return; - } + 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_LOG(INFO, + "BT discovery handler (LOST) [client=%p, service=%s]: not " + "in discovery mode", + client, service_id.c_str()); + 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; - // 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_LOG(INFO, - "BT discovery handler (LOST) [client=%p, service=%s]: report " - "to client", - client, service_id.c_str()); - OnEndpointLost(client, - DiscoveredEndpoint{device_name.GetEndpointId(), - device_name.GetEndpointInfo(), service_id, - proto::connections::Medium::BLUETOOTH, - WebRtcState::kUndefined}); - }); + // Report the BluetoothEndpoint as lost to the client. + NEARBY_LOG( + INFO, + "BT discovery handler (LOST) [client=%p, service=%s]: report " + "to client", + client, service_id.c_str()); + OnEndpointLost(client, DiscoveredEndpoint{ + device_name.GetEndpointId(), + device_name.GetEndpointInfo(), service_id, + proto::connections::Medium::BLUETOOTH, + WebRtcState::kUndefined}); + }); } bool P2pClusterPcpHandler::IsRecognizedBleEndpoint( @@ -408,76 +421,81 @@ void P2pClusterPcpHandler::BlePeripheralDiscoveredHandler( ClientProxy* client, BlePeripheral& peripheral, const std::string& service_id, const ByteArray& advertisement_bytes, bool fast_advertisement) { - RunOnPcpHandlerThread([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_LOG(INFO, - "Ble scanning handler (FOUND) [client=%p, service_id=%s]: not " - "in discovery mode", - client, service_id.c_str()); - 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) - << "Invoking BasePcpHandler::OnEndpointFound() for Ble service=" - << service_id << "; id=" << advertisement.GetEndpointId() << "; name=" - << 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, - })); - }); + 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_LOG( + INFO, + "Ble scanning handler (FOUND) [client=%p, service_id=%s]: not " + "in discovery mode", + client, service_id.c_str()); + 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) + << "Invoking BasePcpHandler::OnEndpointFound() for Ble service=" + << service_id << "; id=" << advertisement.GetEndpointId() + << "; name=" + << 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( @@ -486,38 +504,40 @@ void P2pClusterPcpHandler::BlePeripheralLostHandler( std::string peripheral_name = peripheral.GetName(); NEARBY_LOG(INFO, "Ble: [LOST, SCHED] peripheral_name=%s", peripheral_name.c_str()); - RunOnPcpHandlerThread([this, client, service_id, - &peripheral]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOG(INFO, - "Ble scanning handler (LOST) [client=%p, service_id=%s]: not " - "in scanning mode", - client, service_id.c_str()); - 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_LOG(INFO, - "Ble scanning handler (LOST) [client=%p, " - "service_id=%s]: report to client", - client, service_id.c_str()); - OnEndpointLost(client, DiscoveredEndpoint{ - ble_endpoint_state.endpoint_id, - ble_endpoint_state.endpoint_info, - service_id, - proto::connections::Medium::BLE, - WebRtcState::kUndefined, - }); - } - }); + 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_LOG( + INFO, + "Ble scanning handler (LOST) [client=%p, service_id=%s]: not " + "in scanning mode", + client, service_id.c_str()); + 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_LOG(INFO, + "Ble scanning handler (LOST) [client=%p, " + "service_id=%s]: report to client", + client, service_id.c_str()); + OnEndpointLost(client, DiscoveredEndpoint{ + ble_endpoint_state.endpoint_id, + ble_endpoint_state.endpoint_info, + service_id, + proto::connections::Medium::BLE, + WebRtcState::kUndefined, + }); + } + }); } bool P2pClusterPcpHandler::IsRecognizedWifiLanEndpoint( @@ -557,43 +577,46 @@ bool P2pClusterPcpHandler::IsRecognizedWifiLanEndpoint( void P2pClusterPcpHandler::WifiLanServiceDiscoveredHandler( ClientProxy* client, WifiLanService& wifi_lan_service, const std::string& service_id) { - RunOnPcpHandlerThread([this, client, service_id, - &wifi_lan_service]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOG( - INFO, - "WifiLan discovery handler (FOUND) [client=%p, service=%s]: not " - "in discovery mode", - client, service_id.c_str()); - return; - } - - // Parse the WifiLanServiceInfo. - WifiLanServiceInfo service_info(wifi_lan_service.GetServiceInfo()); - - // Make sure the WifiLan service name points to a valid - // endpoint we're discovering. - if (!IsRecognizedWifiLanEndpoint(service_id, service_info)) return; - - // Report the discovered endpoint to the client. - NEARBY_LOG( - INFO, - "Invoking BasePcpHandler::OnEndpointFound() for WifiLan " - "service_id=%s; endpoint_id=%s; endpoint_info=%s", - service_id.c_str(), service_info.GetEndpointId().c_str(), - absl::BytesToHexString(service_info.GetEndpointInfo().data()).c_str()); - OnEndpointFound(client, std::make_shared<WifiLanEndpoint>(WifiLanEndpoint{ - { - service_info.GetEndpointId(), - service_info.GetEndpointInfo(), - service_id, - proto::connections::Medium::WIFI_LAN, - service_info.GetWebRtcState(), - }, - wifi_lan_service, - })); - }); + RunOnPcpHandlerThread( + "p2p-wifi-service-discovered", + [this, client, service_id, + &wifi_lan_service]() RUN_ON_PCP_HANDLER_THREAD() { + // Make sure we are still discovering before proceeding. + if (!client->IsDiscovering()) { + NEARBY_LOG( + INFO, + "WifiLan discovery handler (FOUND) [client=%p, service=%s]: not " + "in discovery mode", + client, service_id.c_str()); + return; + } + + // Parse the WifiLanServiceInfo. + WifiLanServiceInfo service_info(wifi_lan_service.GetServiceInfo()); + + // Make sure the WifiLan service name points to a valid + // endpoint we're discovering. + if (!IsRecognizedWifiLanEndpoint(service_id, service_info)) return; + + // Report the discovered endpoint to the client. + NEARBY_LOG(INFO, + "Invoking BasePcpHandler::OnEndpointFound() for WifiLan " + "service_id=%s; endpoint_id=%s; endpoint_info=%s", + service_id.c_str(), service_info.GetEndpointId().c_str(), + absl::BytesToHexString(service_info.GetEndpointInfo().data()) + .c_str()); + OnEndpointFound(client, + std::make_shared<WifiLanEndpoint>(WifiLanEndpoint{ + { + service_info.GetEndpointId(), + service_info.GetEndpointInfo(), + service_id, + proto::connections::Medium::WIFI_LAN, + service_info.GetWebRtcState(), + }, + wifi_lan_service, + })); + }); } void P2pClusterPcpHandler::WifiLanServiceLostHandler( @@ -603,39 +626,41 @@ void P2pClusterPcpHandler::WifiLanServiceLostHandler( NEARBY_LOG(INFO, "WifiLan: [LOST, SCHED] wifi_lan_service=%p, service_info_name=%s", &wifi_lan_service, nsd_service_info.GetServiceInfoName().c_str()); - RunOnPcpHandlerThread([this, client, service_id, - nsd_service_info]() RUN_ON_PCP_HANDLER_THREAD() { - // Make sure we are still discovering before proceeding. - if (!client->IsDiscovering()) { - NEARBY_LOG( - INFO, - "WifiLan discovery handler (LOST) [client=%p, service=%s]: not " - "in discovery mode", - client, service_id.c_str()); - return; - } - - // Parse the WifiLanServiceInfo. - WifiLanServiceInfo service_info(nsd_service_info); - - // Make sure the WifiLan service name points to a valid - // endpoint we're discovering. - if (!IsRecognizedWifiLanEndpoint(service_id, service_info)) return; - - // Report the discovered endpoint to the client. - NEARBY_LOG( - INFO, - "WifiLan discovery handler (LOST) [client=%p, service_id=%s]: report " - "to client", - client, service_id.c_str()); - OnEndpointLost(client, DiscoveredEndpoint{ - service_info.GetEndpointId(), - service_info.GetEndpointInfo(), - service_id, - proto::connections::Medium::WIFI_LAN, - WebRtcState::kUndefined, - }); - }); + RunOnPcpHandlerThread( + "p2p-wifi-service-lost", + [this, client, service_id, + nsd_service_info]() RUN_ON_PCP_HANDLER_THREAD() { + // Make sure we are still discovering before proceeding. + if (!client->IsDiscovering()) { + NEARBY_LOG( + INFO, + "WifiLan discovery handler (LOST) [client=%p, service=%s]: not " + "in discovery mode", + client, service_id.c_str()); + return; + } + + // Parse the WifiLanServiceInfo. + WifiLanServiceInfo service_info(nsd_service_info); + + // Make sure the WifiLan service name points to a valid + // endpoint we're discovering. + if (!IsRecognizedWifiLanEndpoint(service_id, service_info)) return; + + // Report the discovered endpoint to the client. + NEARBY_LOG(INFO, + "WifiLan discovery handler (LOST) [client=%p, " + "service_id=%s]: report " + "to client", + client, service_id.c_str()); + OnEndpointLost(client, DiscoveredEndpoint{ + service_info.GetEndpointId(), + service_info.GetEndpointInfo(), + service_id, + proto::connections::Medium::WIFI_LAN, + WebRtcState::kUndefined, + }); + }); } BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartDiscoveryImpl( @@ -830,6 +855,7 @@ proto::connections::Medium P2pClusterPcpHandler::StartBluetoothAdvertising( return; } RunOnPcpHandlerThread( + "p2p-bt-on-incoming-connection", [this, client, local_endpoint_info, socket = std::move(socket)]() RUN_ON_PCP_HANDLER_THREAD() mutable { @@ -959,6 +985,7 @@ proto::connections::Medium P2pClusterPcpHandler::StartBleAdvertising( return; } RunOnPcpHandlerThread( + "p2p-ble-on-incoming-connection", [this, client, local_endpoint_info, service_id, socket = std::move(socket)]() RUN_ON_PCP_HANDLER_THREAD() mutable { @@ -999,6 +1026,7 @@ proto::connections::Medium P2pClusterPcpHandler::StartBleAdvertising( return; } RunOnPcpHandlerThread( + "p2p-bt-on-incoming-connection", [this, client, local_endpoint_info, socket = std::move(socket)]() RUN_ON_PCP_HANDLER_THREAD() mutable { @@ -1143,6 +1171,7 @@ proto::connections::Medium P2pClusterPcpHandler::StartWifiLanAdvertising( return; } RunOnPcpHandlerThread( + "p2p-wifi-on-incoming-connection", [this, client, local_endpoint_info, socket = std::move(socket)]() RUN_ON_PCP_HANDLER_THREAD() mutable { @@ -1272,6 +1301,7 @@ P2pClusterPcpHandler::StartListeningForWebRtcConnections( } RunOnPcpHandlerThread( + "p2p-rtc-on-incoming-connection", [this, client, socket = std::move(socket)]() RUN_ON_PCP_HANDLER_THREAD() { std::string remote_device_name = "WebRtcSocket"; 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 index 43b84f3e5c3..fda43215348 100644 --- 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 @@ -37,7 +37,6 @@ #include "platform/base/byte_array.h" #include "platform/public/bluetooth_classic.h" #include "platform/public/wifi_lan.h" -#include "proto/connections_enums.pb.h" namespace location { namespace nearby { 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 index d9a0ba6cbfa..965aba47a63 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/payload_manager.cc +++ b/chromium/third_party/nearby/src/cpp/core/internal/payload_manager.cc @@ -264,6 +264,7 @@ PayloadManager::~PayloadManager() { 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); @@ -317,7 +318,7 @@ void PayloadManager::SendPayload(ClientProxy* client, Payload::Type payload_type = payload.GetType(); Payload::Id payload_id = CreateOutgoingPayload(std::move(payload), endpoint_ids); - executor->Execute([this, client, endpoint_ids, payload_id]() { + executor->Execute("send-payload", [this, client, endpoint_ids, payload_id]() { if (shutdown_.Get()) return; PendingPayload* pending_payload = GetPayload(payload_id); if (!pending_payload) return; @@ -331,7 +332,8 @@ void PayloadManager::SendPayload(ClientProxy* client, should_continue = SendPayloadLoop(client, *pending_payload, payload_header, next_chunk_offset); } - RunOnStatusUpdateThread([this, payload_id]() + RunOnStatusUpdateThread("destroy-payload", + [this, payload_id]() RUN_ON_PAYLOAD_STATUS_UPDATE_THREAD() { DestroyPendingPayload(payload_id); }); @@ -399,6 +401,7 @@ void PayloadManager::OnEndpointDisconnect(ClientProxy* client, 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 @@ -551,38 +554,40 @@ void PayloadManager::SendClientCallbacksForFinishedOutgoingPayload( const PayloadTransferFrame::PayloadHeader& payload_header, std::int64_t num_bytes_successfully_transferred, proto::connections::PayloadStatus status) { - RunOnStatusUpdateThread([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; - } + 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; - } + 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); - } + // Notify the client. + client->OnPayloadProgress(endpoint_id, update); + } - // Remove these endpoints from our tracking list for this payload. - pending_payload->RemoveEndpoints(finished_endpoint_ids); + // 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(); - } - }); + // Close the payload if no endpoints remain. + if (pending_payload->GetEndpoints().empty()) { + pending_payload->Close(); + } + }); } void PayloadManager::SendClientCallbacksForFinishedIncomingPayload( @@ -590,6 +595,7 @@ void PayloadManager::SendClientCallbacksForFinishedIncomingPayload( 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. @@ -693,6 +699,7 @@ void PayloadManager::HandleSuccessfulOutgoingChunk( 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() { @@ -757,6 +764,7 @@ void PayloadManager::HandleSuccessfulIncomingChunk( 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() { @@ -805,6 +813,7 @@ void PayloadManager::ProcessDataPacket( // 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_LOG(INFO, @@ -1046,8 +1055,9 @@ bool PayloadManager::PendingPayload::IsClosed() { return close_event_.Await(absl::ZeroDuration()).result(); } -void PayloadManager::RunOnStatusUpdateThread(std::function<void()> runnable) { - payload_status_update_executor_.Execute(std::move(runnable)); +void PayloadManager::RunOnStatusUpdateThread(const std::string& name, + std::function<void()> runnable) { + payload_status_update_executor_.Execute(name, std::move(runnable)); } /////////////////////////////// PendingPayloads /////////////////////////////// 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 index 9c18756502e..c62ff3c055b 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/payload_manager.h +++ b/chromium/third_party/nearby/src/cpp/core/internal/payload_manager.h @@ -26,13 +26,11 @@ #include "core/listeners.h" #include "core/payload.h" #include "core/status.h" -#include "proto/connections/offline_wire_formats.pb.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" -#include "proto/connections_enums.pb.h" #include "absl/container/flat_hash_map.h" namespace location { @@ -277,7 +275,8 @@ class PayloadManager : public EndpointManager::FrameProcessor { SingleThreadExecutor* GetOutgoingPayloadExecutor(Payload::Type payload_type); - void RunOnStatusUpdateThread(std::function<void()> runnable); + 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_); 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 index eaf8aabf4fb..b7ad50c0295 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/pcp_handler.h +++ b/chromium/third_party/nearby/src/cpp/core/internal/pcp_handler.h @@ -24,7 +24,6 @@ #include "core/params.h" #include "core/status.h" #include "core/strategy.h" -#include "proto/connections_enums.pb.h" namespace location { namespace nearby { 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 index 0e1932ae5cc..653f9003db7 100644 --- 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 @@ -61,28 +61,31 @@ void ServiceControllerRouter::StartAdvertising( ClientProxy* client, absl::string_view service_id, const ConnectionOptions& options, const ConnectionRequestInfo& info, const ResultCallback& callback) { - RouteToServiceController([this, client, service_id = std::string(service_id), - options, info, callback]() { - Status status = AcquireServiceControllerForClient(client, options.strategy); - if (!status.Ok()) { - callback.result_cb(status); - return; - } + RouteToServiceController( + "scr-start-advertising", + [this, client, service_id = std::string(service_id), options, info, + callback]() { + Status status = + AcquireServiceControllerForClient(client, options.strategy); + if (!status.Ok()) { + callback.result_cb(status); + return; + } - if (client->IsAdvertising()) { - callback.result_cb({Status::kAlreadyAdvertising}); - return; - } + if (client->IsAdvertising()) { + callback.result_cb({Status::kAlreadyAdvertising}); + return; + } - status = service_controller_->StartAdvertising(client, service_id, options, - info); - callback.result_cb(status); - }); + status = service_controller_->StartAdvertising(client, service_id, + options, info); + callback.result_cb(status); + }); } void ServiceControllerRouter::StopAdvertising(ClientProxy* client, const ResultCallback& callback) { - RouteToServiceController([this, client, callback]() { + RouteToServiceController("scr-stop-advertising", [this, client, callback]() { if (ClientHasAcquiredServiceController(client) && client->IsAdvertising()) { service_controller_->StopAdvertising(client); } @@ -95,8 +98,11 @@ void ServiceControllerRouter::StartDiscovery(ClientProxy* client, const ConnectionOptions& options, const DiscoveryListener& listener, const ResultCallback& callback) { - RouteToServiceController([this, client, service_id = std::string(service_id), - options, listener, callback]() { + RouteToServiceController("scr-start-discovery", [this, client, + service_id = + std::string(service_id), + options, listener, + callback]() { Status status = AcquireServiceControllerForClient(client, options.strategy); if (!status.Ok()) { callback.result_cb(status); @@ -116,7 +122,7 @@ void ServiceControllerRouter::StartDiscovery(ClientProxy* client, void ServiceControllerRouter::StopDiscovery(ClientProxy* client, const ResultCallback& callback) { - RouteToServiceController([this, client, callback]() { + RouteToServiceController("scr-stop-discovery", [this, client, callback]() { if (ClientHasAcquiredServiceController(client) && client->IsDiscovering()) { service_controller_->StopDiscovery(client); } @@ -128,8 +134,10 @@ void ServiceControllerRouter::InjectEndpoint( ClientProxy* client, absl::string_view service_id, const OutOfBandConnectionMetadata& metadata, const ResultCallback& callback) { - RouteToServiceController([this, client, service_id = std::string(service_id), - metadata, 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) { @@ -167,36 +175,38 @@ void ServiceControllerRouter::RequestConnection( // CancellationListener as soon as possible. client->AddCancellationFlag(std::string(endpoint_id)); - RouteToServiceController([this, client, - endpoint_id = std::string(endpoint_id), info, - options, callback]() { - if (!ClientHasAcquiredServiceController(client)) { - callback.result_cb({Status::kOutOfOrderApiCall}); - return; - } + RouteToServiceController( + "scr-request-connection", + [this, client, endpoint_id = std::string(endpoint_id), info, options, + callback]() { + if (!ClientHasAcquiredServiceController(client)) { + callback.result_cb({Status::kOutOfOrderApiCall}); + return; + } - if (client->HasPendingConnectionToEndpoint(endpoint_id) || - client->IsConnectedToEndpoint(endpoint_id)) { - callback.result_cb({Status::kAlreadyConnectedToEndpoint}); - return; - } + if (client->HasPendingConnectionToEndpoint(endpoint_id) || + client->IsConnectedToEndpoint(endpoint_id)) { + callback.result_cb({Status::kAlreadyConnectedToEndpoint}); + return; + } - Status status = service_controller_->RequestConnection(client, endpoint_id, - info, options); - if (!status.Ok()) { - client->CancelEndpoint(endpoint_id); - } - callback.result_cb(status); - }); + Status status = service_controller_->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([this, client, - endpoint_id = std::string(endpoint_id), listener, - callback]() { + RouteToServiceController("scr-accept-connection", [this, client, + endpoint_id = std::string( + endpoint_id), + listener, callback]() { if (!ClientHasAcquiredServiceController(client)) { callback.result_cb({Status::kOutOfOrderApiCall}); return; @@ -227,6 +237,7 @@ void ServiceControllerRouter::RejectConnection(ClientProxy* client, client->CancelEndpoint(std::string(endpoint_id)); RouteToServiceController( + "scr-reject-connection", [this, client, endpoint_id = std::string(endpoint_id), callback]() { if (!ClientHasAcquiredServiceController(client)) { callback.result_cb({Status::kOutOfOrderApiCall}); @@ -256,6 +267,7 @@ 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 (!ClientHasAcquiredServiceController(client) || !client->IsConnectedToEndpoint(endpoint_id)) { @@ -285,6 +297,7 @@ void ServiceControllerRouter::SendPayload( std::vector<std::string>(endpoint_ids.begin(), endpoint_ids.end()); RouteToServiceController( + "scr-send-payload", [this, client, shared_payload, endpoints, callback]() { if (!ClientHasAcquiredServiceController(client)) { callback.result_cb({Status::kOutOfOrderApiCall}); @@ -310,7 +323,8 @@ void ServiceControllerRouter::SendPayload( void ServiceControllerRouter::CancelPayload(ClientProxy* client, std::uint64_t payload_id, const ResultCallback& callback) { - RouteToServiceController([this, client, payload_id, callback]() { + RouteToServiceController("scr-cancel-payload", [this, client, payload_id, + callback]() { if (!ClientHasAcquiredServiceController(client)) { callback.result_cb({Status::kOutOfOrderApiCall}); return; @@ -328,6 +342,7 @@ void ServiceControllerRouter::DisconnectFromEndpoint( client->CancelEndpoint(std::string(endpoint_id)); RouteToServiceController( + "scr-disconnect-endpoint", [this, client, endpoint_id = std::string(endpoint_id), callback]() { if (ClientHasAcquiredServiceController(client)) { if (!client->IsConnectedToEndpoint(endpoint_id) && @@ -347,7 +362,11 @@ void ServiceControllerRouter::StopAllEndpoints(ClientProxy* client, // without further posting it. client->CancelAllEndpoints(); - RouteToServiceController([this, client, callback]() { + 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."; if (ClientHasAcquiredServiceController(client)) { DoneWithStrategySessionForClient(client); } @@ -361,7 +380,8 @@ void ServiceControllerRouter::ClientDisconnecting( // without further posting it. client->CancelAllEndpoints(); - RouteToServiceController([this, client, callback]() { + RouteToServiceController("scr-client-disconnecting", [this, client, + callback]() { if (ClientHasAcquiredServiceController(client)) { DoneWithStrategySessionForClient(client); NEARBY_LOG(INFO, @@ -459,8 +479,9 @@ void ServiceControllerRouter::DoneWithStrategySessionForClient( ReleaseServiceControllerForClient(client); } -void ServiceControllerRouter::RouteToServiceController(Runnable runnable) { - serializer_.Execute(std::move(runnable)); +void ServiceControllerRouter::RouteToServiceController(const std::string& name, + Runnable runnable) { + serializer_.Execute(name, std::move(runnable)); } bool ServiceControllerRouter::ClientHasConnectionToAtLeastOneEndpoint( 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 index 8c9e7039094..fa209e63585 100644 --- 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 @@ -104,11 +104,10 @@ class ServiceControllerRouter { void ClientDisconnecting(ClientProxy* client, const ResultCallback& callback); private: - friend class ServiceControllerRouterTest; static bool ClientHasConnectionToAtLeastOneEndpoint( ClientProxy* client, const std::vector<std::string>& remote_endpoint_ids); - void RouteToServiceController(Runnable runnable); + void RouteToServiceController(const std::string& name, Runnable runnable); Status AcquireServiceControllerForClient(ClientProxy* client, Strategy strategy); 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 index 14152bf0f01..98522921df6 100644 --- a/chromium/third_party/nearby/src/cpp/core/internal/simulation_user.h +++ b/chromium/third_party/nearby/src/cpp/core/internal/simulation_user.h @@ -54,7 +54,15 @@ class SimulationUser { explicit SimulationUser( const std::string& device_name, BooleanMediumSelector allowed = BooleanMediumSelector()) - : info_{ByteArray{device_name}}, + : 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, 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 index e15cc0c7124..48d8d37f7dc 100644 --- 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 @@ -17,7 +17,6 @@ #include "core/internal/base_endpoint_channel.h" #include "core/internal/mediums/webrtc/webrtc_socket_wrapper.h" -#include "proto/connections_enums.pb.h" namespace location { namespace nearby { 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 index 87eb359e9a5..38459c810a0 100644 --- 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 @@ -17,7 +17,6 @@ #include "core/internal/base_endpoint_channel.h" #include "platform/public/wifi_lan.h" -#include "proto/connections_enums.pb.h" namespace location { namespace nearby { diff --git a/chromium/third_party/nearby/src/cpp/core/options.h b/chromium/third_party/nearby/src/cpp/core/options.h index 100e80e3760..09c1c98d75a 100644 --- a/chromium/third_party/nearby/src/cpp/core/options.h +++ b/chromium/third_party/nearby/src/cpp/core/options.h @@ -18,7 +18,6 @@ #include "core/strategy.h" #include "platform/base/byte_array.h" #include "proto/connections_enums.pb.h" -#include "proto/connections_enums.pb.h" namespace location { namespace nearby { @@ -95,10 +94,13 @@ struct ConnectionOptions { bool enforce_topology_constraints; bool low_power; bool enable_bluetooth_listening; + bool enable_webrtc_listening; // Whether this is intended to be used in conjunction with InjectEndpoint(). bool is_out_of_band_connection = false; ByteArray remote_bluetooth_mac_address; std::string fast_advertisement_service_uuid; + int keep_alive_interval_millis = 0; + int keep_alive_timeout_millis = 0; // Verify if ConnectionOptions is in a not-initialized (Empty) state. bool Empty() const { return strategy.IsNone(); } // Bring ConnectionOptions to a not-initialized (Empty) state. diff --git a/chromium/third_party/nearby/src/cpp/platform/api/BUILD b/chromium/third_party/nearby/src/cpp/platform/api/BUILD index e31a848af6e..cad9831364b 100644 --- a/chromium/third_party/nearby/src/cpp/platform/api/BUILD +++ b/chromium/third_party/nearby/src/cpp/platform/api/BUILD @@ -34,6 +34,7 @@ cc_library( "system_clock.h", ], visibility = [ + "//googlemac/iPhone/Shared/Nearby/Connections_v2:__subpackages__", "//platform/base:__pkg__", "//platform/impl:__subpackages__", "//platform/public:__pkg__", diff --git a/chromium/third_party/nearby/src/cpp/platform/api/log_message.h b/chromium/third_party/nearby/src/cpp/platform/api/log_message.h index 11374ed13d0..3f43c0bc352 100644 --- a/chromium/third_party/nearby/src/cpp/platform/api/log_message.h +++ b/chromium/third_party/nearby/src/cpp/platform/api/log_message.h @@ -23,9 +23,13 @@ namespace api { // A log message that prints to appropraite destination when ~LogMessage() is // called. +// +// note: the Severity enum should map (best effort) to the corresponding level +// id that the platform logging implementation has. class LogMessage { public: enum class Severity { + kVerbose = -1, kInfo = 0, kWarning = 1, kError = 2, diff --git a/chromium/third_party/nearby/src/cpp/platform/api/webrtc.h b/chromium/third_party/nearby/src/cpp/platform/api/webrtc.h index 16fc30e5f26..9d01f20ef99 100644 --- a/chromium/third_party/nearby/src/cpp/platform/api/webrtc.h +++ b/chromium/third_party/nearby/src/cpp/platform/api/webrtc.h @@ -18,7 +18,6 @@ #include <memory> #include "proto/connections/offline_wire_formats.pb.h" -#include "proto/connections/offline_wire_formats.pb.h" #include "platform/base/byte_array.h" #include "absl/strings/string_view.h" #include "webrtc/api/peer_connection_interface.h" diff --git a/chromium/third_party/nearby/src/cpp/platform/base/BUILD b/chromium/third_party/nearby/src/cpp/platform/base/BUILD index 3f010ebb920..b61a8e8603f 100644 --- a/chromium/third_party/nearby/src/cpp/platform/base/BUILD +++ b/chromium/third_party/nearby/src/cpp/platform/base/BUILD @@ -102,6 +102,7 @@ cc_library( ], hdrs = [ "cancellation_flag.h", + "cancellation_flag_listener.h", ], visibility = [ "//core/internal:__subpackages__", diff --git a/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag.cc b/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag.cc index 7aaf4d2d965..1d6b792af79 100644 --- a/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag.cc +++ b/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag.cc @@ -28,25 +28,37 @@ CancellationFlag::CancellationFlag(bool cancelled) { cancelled_ = cancelled; } -void CancellationFlag::Cancel() { - absl::MutexLock lock(mutex_.get()); +CancellationFlag::~CancellationFlag() { + listeners_.clear(); +} +void CancellationFlag::Cancel() { // Return immediately as no-op if feature flag is not enabled. if (!FeatureFlags::GetInstance().GetFlags().enable_cancellation_flag) { return; } - if (cancelled_) { - // Someone already cancelled. Return immediately. - return; + absl::flat_hash_set<CancelListener *> listeners; + { + absl::MutexLock lock(mutex_.get()); + if (cancelled_) { + // Someone already cancelled. Return immediately. + return; + } + cancelled_ = true; + + listeners = listeners_; + } + + for (const auto *listener : listeners) { + (*listener)(); } - cancelled_ = true; } bool CancellationFlag::Cancelled() const { absl::MutexLock lock(mutex_.get()); - // Return falsea as no-op if feature flag is not enabled. + // Return false as no-op if feature flag is not enabled. if (!FeatureFlags::GetInstance().GetFlags().enable_cancellation_flag) { return false; } @@ -54,5 +66,17 @@ bool CancellationFlag::Cancelled() const { return cancelled_; } +void CancellationFlag::RegisterOnCancelListener(CancelListener *listener) { + absl::MutexLock lock(mutex_.get()); + + listeners_.emplace(listener); +} + +void CancellationFlag::UnregisterOnCancelListener(CancelListener *listener) { + absl::MutexLock lock(mutex_.get()); + + listeners_.erase(listener); +} + } // namespace nearby } // namespace location diff --git a/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag.h b/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag.h index a9cd9450a1f..e861bfe0ab4 100644 --- a/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag.h +++ b/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag.h @@ -17,6 +17,7 @@ #include <memory> +#include "absl/container/flat_hash_set.h" #include "absl/synchronization/mutex.h" namespace location { @@ -26,13 +27,16 @@ namespace nearby { // cleaned up as soon as possible. class CancellationFlag { public: + // The listener for cancellation. + using CancelListener = std::function<void()>; + CancellationFlag(); explicit CancellationFlag(bool cancelled); CancellationFlag(const CancellationFlag &) = delete; CancellationFlag &operator=(const CancellationFlag &) = delete; CancellationFlag(CancellationFlag &&) = default; CancellationFlag &operator=(CancellationFlag &&) = default; - virtual ~CancellationFlag() = default; + virtual ~CancellationFlag(); // Set the flag as cancelled. void Cancel() ABSL_LOCKS_EXCLUDED(mutex_); @@ -41,8 +45,33 @@ class CancellationFlag { bool Cancelled() const ABSL_LOCKS_EXCLUDED(mutex_); private: + friend class CancellationFlagListener; + friend class CancellationFlagPeer; + + // The registration inserts the pointer of caller's listener callback into + // `listeners_`, a flat hash set which support the pointer type for hashing + // function. It conducts that 2 different pointers might point to the same + // callback function which is unusal and should avoid. Hence we make it as + // private and use `CancellationFlagListener` as a RAII to wrap the function. + // The caller should register listener as lambda or std::function + // via `CancellationFlagListener`. + void RegisterOnCancelListener(CancelListener *listener) + ABSL_LOCKS_EXCLUDED(mutex_); + + // The un-registration erases the pointer of caller's listener callback from + // `listeners_`. This is paired to RegisterOnCancelListener which is + // guaranteed to be called under `CancellationFlagListener`. + void UnregisterOnCancelListener(CancelListener *listener) + ABSL_LOCKS_EXCLUDED(mutex_); + + int CancelListenersSize() const ABSL_LOCKS_EXCLUDED(mutex_) { + absl::MutexLock lock(mutex_.get()); + return listeners_.size(); + } + std::unique_ptr<absl::Mutex> mutex_; bool cancelled_ ABSL_GUARDED_BY(mutex_) = false; + absl::flat_hash_set<CancelListener *> ABSL_GUARDED_BY(mutex_) listeners_; }; } // namespace nearby diff --git a/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag_listener.h b/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag_listener.h new file mode 100644 index 00000000000..8a5d9d37794 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag_listener.h @@ -0,0 +1,43 @@ +// 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 PLATFORM_BASE_CANCELLATION_FLAG_LISTENER_H_ +#define PLATFORM_BASE_CANCELLATION_FLAG_LISTENER_H_ + +#include "platform/base/cancellation_flag.h" + +namespace location { +namespace nearby { + +// An RAII mechanism to register CancelListener over a life cycle of medium +// class. +class CancellationFlagListener { + public: + CancellationFlagListener(CancellationFlag* flag, + std::function<void()> listener) + : flag_(flag), listener_(std::move(listener)) { + flag_->RegisterOnCancelListener(&listener_); + } + + ~CancellationFlagListener() { flag_->UnregisterOnCancelListener(&listener_); } + + private: + CancellationFlag* flag_; + std::function<void()> listener_; +}; + +} // namespace nearby +} // namespace location + +#endif // PLATFORM_BASE_CANCELLATION_FLAG_LISTENER_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag_test.cc b/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag_test.cc index e5f05af9c97..f5a55316123 100644 --- a/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag_test.cc +++ b/chromium/third_party/nearby/src/cpp/platform/base/cancellation_flag_test.cc @@ -14,15 +14,40 @@ #include "platform/base/cancellation_flag.h" +#include <memory> + +#include "platform/base/cancellation_flag_listener.h" #include "platform/base/feature_flags.h" #include "platform/base/medium_environment.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" namespace location { namespace nearby { + +class CancellationFlagPeer { + public: + explicit CancellationFlagPeer(CancellationFlag* cancellation_flag) + : cancellation_flag_(cancellation_flag) {} + void RegisterOnCancelListener(CancellationFlag::CancelListener* listener) { + cancellation_flag_->RegisterOnCancelListener(listener); + } + void UnregisterOnCancelListener(CancellationFlag::CancelListener* listener) { + cancellation_flag_->UnregisterOnCancelListener(listener); + } + int CancelListenersSize() const { + return cancellation_flag_->CancelListenersSize(); + } + + private: + CancellationFlag* cancellation_flag_; // Not owned by CancellationFlagPeer. +}; + namespace { using FeatureFlags = FeatureFlags::Flags; +using ::testing::MockFunction; +using ::testing::StrictMock; constexpr FeatureFlags kTestCases[] = { FeatureFlags{ @@ -64,7 +89,36 @@ TEST_P(CancellationFlagTest, InitialValueAsTrue) { } TEST_P(CancellationFlagTest, CanCancel) { + StrictMock<MockFunction<void()>> mock_cancel_callback; + CancellationFlag::CancelListener cancel_callback = + mock_cancel_callback.AsStdFunction(); + EXPECT_CALL(mock_cancel_callback, Call) + .Times(feature_flags_.enable_cancellation_flag ? 1 : 0); + CancellationFlag flag; + CancellationFlagListener cancellation_flag_listener(&flag, cancel_callback); + flag.Cancel(); + + // If FeatureFlag is disabled, return as no-op immediately and + // Cancelled is always false. + if (!feature_flags_.enable_cancellation_flag) { + EXPECT_FALSE(flag.Cancelled()); + return; + } + + EXPECT_TRUE(flag.Cancelled()); +} + +TEST_P(CancellationFlagTest, ShouldOnlyCancelOnce) { + StrictMock<MockFunction<void()>> mock_cancel_callback; + CancellationFlag::CancelListener cancel_callback = + mock_cancel_callback.AsStdFunction(); + EXPECT_CALL(mock_cancel_callback, Call) + .Times(feature_flags_.enable_cancellation_flag ? 1 : 0); + CancellationFlag flag; + CancellationFlagListener cancellation_flag_listener(&flag, cancel_callback); + flag.Cancel(); + flag.Cancel(); flag.Cancel(); // If FeatureFlag is disabled, return as no-op immediately and @@ -77,9 +131,82 @@ TEST_P(CancellationFlagTest, CanCancel) { EXPECT_TRUE(flag.Cancelled()); } +TEST_P(CancellationFlagTest, CannotCancelAfterUnregister) { + StrictMock<MockFunction<void()>> mock_cancel_callback; + CancellationFlag::CancelListener cancel_callback = + mock_cancel_callback.AsStdFunction(); + EXPECT_CALL(mock_cancel_callback, Call).Times(0); + + CancellationFlag flag; + auto cancellation_flag_listener = + std::make_unique<CancellationFlagListener>(&flag, cancel_callback); + // Release immediately. + cancellation_flag_listener.reset(); + flag.Cancel(); +} + INSTANTIATE_TEST_SUITE_P(ParametrisedCancellationFlagTest, CancellationFlagTest, ::testing::ValuesIn(kTestCases)); } // namespace + +TEST(CancellationFlagTest, + CancelMultiplesIfMultiplePointersToTheSameFunctionRegistered) { + location::nearby::FeatureFlags::Flags feature_flags_ = + location::nearby::FeatureFlags::Flags{ + .enable_cancellation_flag = true, + }; + MediumEnvironment::Instance().SetFeatureFlags(feature_flags_); + + StrictMock<MockFunction<void()>> mock_cancel_callback; + CancellationFlag::CancelListener cancel_callback = + mock_cancel_callback.AsStdFunction(); + + CancellationFlag::CancelListener *callback_pointer_1 = &cancel_callback; + auto callback_pointer_2 = + std::make_unique<CancellationFlag::CancelListener>(); + *callback_pointer_2 = cancel_callback; + + EXPECT_NE(callback_pointer_1, callback_pointer_2.get()); + EXPECT_CALL(mock_cancel_callback, Call).Times(2); + + CancellationFlag flag; + CancellationFlagPeer flag_peer(&flag); + flag_peer.RegisterOnCancelListener(callback_pointer_1); + flag_peer.RegisterOnCancelListener(callback_pointer_2.get()); + + flag.Cancel(); + + flag_peer.UnregisterOnCancelListener(callback_pointer_2.get()); + EXPECT_EQ(1, flag_peer.CancelListenersSize()); + flag_peer.UnregisterOnCancelListener(callback_pointer_1); + EXPECT_EQ(0, flag_peer.CancelListenersSize()); +} + +TEST(CancellationFlagTest, RegisteredMultuipleTimesOnlyCancelOnce) { + location::nearby::FeatureFlags::Flags feature_flags_ = + location::nearby::FeatureFlags::Flags{ + .enable_cancellation_flag = true, + }; + MediumEnvironment::Instance().SetFeatureFlags(feature_flags_); + + StrictMock<MockFunction<void()>> mock_cancel_callback; + CancellationFlag::CancelListener cancel_callback = + mock_cancel_callback.AsStdFunction(); + EXPECT_CALL(mock_cancel_callback, Call).Times(1); + + CancellationFlag flag; + CancellationFlagPeer flag_peer(&flag); + flag_peer.RegisterOnCancelListener(&cancel_callback); + flag_peer.RegisterOnCancelListener(&cancel_callback); + EXPECT_EQ(1, flag_peer.CancelListenersSize()); + + flag.Cancel(); + + flag_peer.UnregisterOnCancelListener(&cancel_callback); + EXPECT_EQ(0, flag_peer.CancelListenersSize()); + flag_peer.UnregisterOnCancelListener(&cancel_callback); +} + } // namespace nearby } // namespace location diff --git a/chromium/third_party/nearby/src/cpp/platform/base/feature_flags.h b/chromium/third_party/nearby/src/cpp/platform/base/feature_flags.h index ff30b43235d..d62c7a458f3 100644 --- a/chromium/third_party/nearby/src/cpp/platform/base/feature_flags.h +++ b/chromium/third_party/nearby/src/cpp/platform/base/feature_flags.h @@ -34,6 +34,9 @@ class FeatureFlags { // If a scheduled runnable is already running, Cancel() will synchronously // wait for the task to complete. bool cancel_waits_for_running_tasks = true; + // Keep Alive frame interval and timeout in millis. + std::int32_t keep_alive_interval_millis = 5000; + std::int32_t keep_alive_timeout_millis = 30000; }; static const FeatureFlags& GetInstance() { diff --git a/chromium/third_party/nearby/src/cpp/platform/base/feature_flags_test.cc b/chromium/third_party/nearby/src/cpp/platform/base/feature_flags_test.cc index 2ad5e44fc28..075a75f4008 100644 --- a/chromium/third_party/nearby/src/cpp/platform/base/feature_flags_test.cc +++ b/chromium/third_party/nearby/src/cpp/platform/base/feature_flags_test.cc @@ -21,13 +21,18 @@ namespace location { namespace nearby { namespace { -constexpr FeatureFlags::Flags kTestFeatureFlags{.enable_cancellation_flag = - true}; +constexpr FeatureFlags::Flags kTestFeatureFlags{ + .enable_cancellation_flag = true, + .keep_alive_interval_millis = 5000, + .keep_alive_timeout_millis = 30000}; TEST(FeatureFlagsTest, ToSetFeatureWorks) { const FeatureFlags& features = FeatureFlags::GetInstance(); EXPECT_FALSE(features.GetFlags().enable_cancellation_flag); + EXPECT_EQ(5000, features.GetFlags().keep_alive_interval_millis); + EXPECT_EQ(30000, features.GetFlags().keep_alive_timeout_millis); + MediumEnvironment& medium_environment = MediumEnvironment::Instance(); medium_environment.SetFeatureFlags(kTestFeatureFlags); EXPECT_TRUE(features.GetFlags().enable_cancellation_flag); diff --git a/chromium/third_party/nearby/src/cpp/platform/base/logging.h b/chromium/third_party/nearby/src/cpp/platform/base/logging.h index c50e57cefef..36a6416ce53 100644 --- a/chromium/third_party/nearby/src/cpp/platform/base/logging.h +++ b/chromium/third_party/nearby/src/cpp/platform/base/logging.h @@ -36,7 +36,10 @@ class LogMessageVoidify { } // namespace location // Severity enum conversion -#define NEARBY_SEVERITY_INFO location::nearby::api::LogMessage::Severity::kInfo +#define NEARBY_SEVERITY_VERBOSE \ + location::nearby::api::LogMessage::Severity::kVerbose +#define NEARBY_SEVERITY_INFO \ + location::nearby::api::LogMessage::Severity::kInfo #define NEARBY_SEVERITY_WARNING \ location::nearby::api::LogMessage::Severity::kWarning #define NEARBY_SEVERITY_ERROR \ diff --git a/chromium/third_party/nearby/src/cpp/platform/base/medium_environment.cc b/chromium/third_party/nearby/src/cpp/platform/base/medium_environment.cc index 42733cd865b..870eeffe40c 100644 --- a/chromium/third_party/nearby/src/cpp/platform/base/medium_environment.cc +++ b/chromium/third_party/nearby/src/cpp/platform/base/medium_environment.cc @@ -62,6 +62,8 @@ void MediumEnvironment::Reset() { webrtc_signaling_message_callback_.clear(); webrtc_signaling_complete_callback_.clear(); wifi_lan_mediums_.clear(); + use_valid_peer_connection_ = true; + peer_connection_latency_ = absl::ZeroDuration(); }); Sync(); } @@ -511,6 +513,15 @@ bool MediumEnvironment::GetUseValidPeerConnection() { return use_valid_peer_connection_; } +void MediumEnvironment::SetPeerConnectionLatency( + absl::Duration peer_connection_latency) { + peer_connection_latency_ = peer_connection_latency; +} + +absl::Duration MediumEnvironment::GetPeerConnectionLatency() { + return peer_connection_latency_; +} + void MediumEnvironment::RegisterWifiLanMedium(api::WifiLanMedium& medium) { if (!enabled_) return; RunOnMediumEnvironmentThread([this, &medium]() { diff --git a/chromium/third_party/nearby/src/cpp/platform/base/medium_environment.h b/chromium/third_party/nearby/src/cpp/platform/base/medium_environment.h index bd7126dc795..15eb0becb48 100644 --- a/chromium/third_party/nearby/src/cpp/platform/base/medium_environment.h +++ b/chromium/third_party/nearby/src/cpp/platform/base/medium_environment.h @@ -153,6 +153,11 @@ class MediumEnvironment { bool GetUseValidPeerConnection(); + // Used to set latency when creating the peer connection in tests. + void SetPeerConnectionLatency(absl::Duration peer_connection_latency); + + absl::Duration GetPeerConnectionLatency(); + // Adds medium-related info to allow for scanning/advertising to work. // This provides acccess to this medium from other mediums, when protocol // expects they should communicate. @@ -319,6 +324,7 @@ class MediumEnvironment { wifi_lan_mediums_; bool use_valid_peer_connection_ = true; + absl::Duration peer_connection_latency_ = absl::ZeroDuration(); }; } // namespace nearby diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/g3/ble.cc b/chromium/third_party/nearby/src/cpp/platform/impl/g3/ble.cc index 0595c80aaa2..ecd9ac03190 100644 --- a/chromium/third_party/nearby/src/cpp/platform/impl/g3/ble.cc +++ b/chromium/third_party/nearby/src/cpp/platform/impl/g3/ble.cc @@ -19,6 +19,7 @@ #include <string> #include "platform/api/ble.h" +#include "platform/base/cancellation_flag_listener.h" #include "platform/base/logging.h" #include "platform/base/medium_environment.h" #include "absl/synchronization/mutex.h" @@ -44,9 +45,7 @@ InputStream& BleSocket::GetInputStream() { return remote_socket->GetLocalInputStream(); } -OutputStream& BleSocket::GetOutputStream() { - return GetLocalOutputStream(); -} +OutputStream& BleSocket::GetOutputStream() { return GetLocalOutputStream(); } BleSocket* BleSocket::GetRemoteSocket() { absl::MutexLock lock(&mutex_); @@ -354,6 +353,11 @@ std::unique_ptr<api::BleSocket> BleMedium::Connect( return {}; } + CancellationFlagListener listener(cancellation_flag, [this]() { + NEARBY_LOGS(INFO) << "G3 BLE Cancel Connect."; + if (server_socket_ != nullptr) server_socket_->Close(); + }); + BlePeripheral peripheral = static_cast<BlePeripheral&>(remote_peripheral); auto socket = std::make_unique<BleSocket>(&peripheral); // Finally, Request to connect to this socket. diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/g3/bluetooth_classic.cc b/chromium/third_party/nearby/src/cpp/platform/impl/g3/bluetooth_classic.cc index 7af8b6c477d..995b93a999d 100644 --- a/chromium/third_party/nearby/src/cpp/platform/impl/g3/bluetooth_classic.cc +++ b/chromium/third_party/nearby/src/cpp/platform/impl/g3/bluetooth_classic.cc @@ -18,6 +18,7 @@ #include <string> #include "platform/api/bluetooth_classic.h" +#include "platform/base/cancellation_flag_listener.h" #include "platform/base/logging.h" #include "platform/base/medium_environment.h" #include "platform/impl/g3/bluetooth_adapter.h" @@ -234,6 +235,11 @@ std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService( return {}; } + CancellationFlagListener listener(cancellation_flag, [&server_socket]() { + NEARBY_LOGS(INFO) << "G3 Bluetooth Cancel Connect."; + if (server_socket != nullptr) server_socket->Close(); + }); + auto socket = std::make_unique<BluetoothSocket>(&GetAdapter()); // Finally, Request to connect to this socket. if (!server_socket->Connect(*socket)) { diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/g3/log_message.cc b/chromium/third_party/nearby/src/cpp/platform/impl/g3/log_message.cc index b227392a668..dd63c332d43 100644 --- a/chromium/third_party/nearby/src/cpp/platform/impl/g3/log_message.cc +++ b/chromium/third_party/nearby/src/cpp/platform/impl/g3/log_message.cc @@ -26,6 +26,10 @@ api::LogMessage::Severity g_min_log_severity = api::LogMessage::Severity::kInfo; inline absl::LogSeverity ConvertSeverity(api::LogMessage::Severity severity) { switch (severity) { + // api::LogMessage::Severity kVerbose and kInfo is mapped to + // absl::LogSeverity kInfo since absl::LogSeverity doesn't have kVerbose + // level. + case api::LogMessage::Severity::kVerbose: case api::LogMessage::Severity::kInfo: return absl::LogSeverity::kInfo; case api::LogMessage::Severity::kWarning: diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/g3/webrtc.cc b/chromium/third_party/nearby/src/cpp/platform/impl/g3/webrtc.cc index cd5f467ce84..c02cde71adc 100644 --- a/chromium/third_party/nearby/src/cpp/platform/impl/g3/webrtc.cc +++ b/chromium/third_party/nearby/src/cpp/platform/impl/g3/webrtc.cc @@ -48,6 +48,8 @@ void WebRtcSignalingMessenger::StopReceivingMessages() { env.UnregisterWebRtcSignalingMessenger(self_id_); } +WebRtcMedium::~WebRtcMedium() { single_thread_executor_.Shutdown(); } + const std::string WebRtcMedium::GetDefaultCountryCode() { return "US"; } @@ -72,9 +74,17 @@ void WebRtcMedium::CreatePeerConnection( webrtc::CreateDefaultTaskQueueFactory(); factory_dependencies.signaling_thread = signaling_thread.release(); - callback(webrtc::CreateModularPeerConnectionFactory( - std::move(factory_dependencies)) - ->CreatePeerConnection(rtc_config, std::move(dependencies))); + rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection = + webrtc::CreateModularPeerConnectionFactory( + std::move(factory_dependencies)) + ->CreatePeerConnection(rtc_config, std::move(dependencies)); + + single_thread_executor_.Execute( + [&env, callback = std::move(callback), + peer_connection = std::move(peer_connection)]() { + absl::SleepFor(env.GetPeerConnectionLatency()); + callback(peer_connection); + }); } std::unique_ptr<api::WebRtcSignalingMessenger> diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/g3/webrtc.h b/chromium/third_party/nearby/src/cpp/platform/impl/g3/webrtc.h index 235fb6495f1..14930f5923d 100644 --- a/chromium/third_party/nearby/src/cpp/platform/impl/g3/webrtc.h +++ b/chromium/third_party/nearby/src/cpp/platform/impl/g3/webrtc.h @@ -18,6 +18,7 @@ #include <memory> #include "platform/api/webrtc.h" +#include "platform/impl/g3/single_thread_executor.h" #include "absl/strings/string_view.h" #include "webrtc/api/peer_connection_interface.h" @@ -54,7 +55,7 @@ class WebRtcMedium : public api::WebRtcMedium { using PeerConnectionCallback = api::WebRtcMedium::PeerConnectionCallback; WebRtcMedium() = default; - ~WebRtcMedium() override = default; + ~WebRtcMedium() override; const std::string GetDefaultCountryCode() override; @@ -69,6 +70,8 @@ class WebRtcMedium : public api::WebRtcMedium { const connections::LocationHint& location_hint) override; private: + // Executor for handling calls to create a peer connection. + SingleThreadExecutor single_thread_executor_; }; } // namespace g3 diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/g3/wifi_lan.cc b/chromium/third_party/nearby/src/cpp/platform/impl/g3/wifi_lan.cc index 2ae2b9feaea..31b2732f763 100644 --- a/chromium/third_party/nearby/src/cpp/platform/impl/g3/wifi_lan.cc +++ b/chromium/third_party/nearby/src/cpp/platform/impl/g3/wifi_lan.cc @@ -19,6 +19,7 @@ #include <string> #include "platform/api/wifi_lan.h" +#include "platform/base/cancellation_flag_listener.h" #include "platform/base/logging.h" #include "platform/base/medium_environment.h" #include "platform/base/nsd_service_info.h" @@ -361,6 +362,11 @@ std::unique_ptr<api::WifiLanSocket> WifiLanMedium::Connect( return {}; } + CancellationFlagListener listener(cancellation_flag, [this]() { + NEARBY_LOGS(INFO) << "G3 WifiLan Cancel Connect."; + if (server_socket_ != nullptr) server_socket_->Close(); + }); + WifiLanService wifi_lan_service = static_cast<WifiLanService&>(remote_wifi_lan_service); auto socket = std::make_unique<WifiLanSocket>(&wifi_lan_service); diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/shared/BUILD b/chromium/third_party/nearby/src/cpp/platform/impl/shared/BUILD index b2c31460e2d..64f96218639 100644 --- a/chromium/third_party/nearby/src/cpp/platform/impl/shared/BUILD +++ b/chromium/third_party/nearby/src/cpp/platform/impl/shared/BUILD @@ -21,7 +21,7 @@ cc_library( "posix_mutex.h", ], visibility = [ - "//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__", + "//googlemac/iPhone/Shared/Nearby/Connections_v2:__subpackages__", "//platform/impl:__subpackages__", ], deps = ["//platform/api:types"], @@ -36,7 +36,7 @@ cc_library( "posix_condition_variable.h", ], visibility = [ - "//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__", + "//googlemac/iPhone/Shared/Nearby/Connections_v2:__subpackages__", ], deps = [ ":posix_mutex", @@ -49,7 +49,7 @@ cc_library( srcs = ["file.cc"], hdrs = ["file.h"], visibility = [ - "//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__", + "//googlemac/iPhone/Shared/Nearby/Connections_v2:__subpackages__", "//platform/impl:__subpackages__", ], deps = [ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/BUILD b/chromium/third_party/nearby/src/cpp/platform/impl/windows/BUILD new file mode 100644 index 00000000000..25c2086e04c --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/BUILD @@ -0,0 +1,104 @@ +# 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. + +cc_library( + name = "types", + srcs = [ + "log_message.cc", + "system_clock.cc", + ], + hdrs = [ + "atomic_boolean.h", + "atomic_reference.h", + "cancelable.h", + "condition_variable.h", + "count_down_latch.h", + "executor.h", + "future.h", + "input_file.h", + "listenable_future.h", + "log_message.h", + "mutex.h", + "output_file.h", + "scheduled_executor.h", + "settable_future.h", + "submittable_executor.h", + ], + deps = [ + "//platform/api:types", + "//platform/base", + ], +) + +cc_library( + name = "comm", + hdrs = [ + "ble.h", + "bluetooth_adapter.h", + "bluetooth_classic.h", + "server_sync.h", + "webrtc.h", + "wifi.h", + "wifi_lan.h", + ], + visibility = ["//visibility:private"], + deps = [ + "//platform/api:comm", + "//platform/base", + ], +) + +cc_library( + name = "crypto", + srcs = [ + "crypto.cc", + ], + visibility = ["//visibility:private"], + deps = [ + "//platform/api:types", + "//platform/base", + "//absl/strings", + "//openssl:crypto", + ], +) + +cc_library( + name = "windows", + srcs = [ + "platform.cc", + ], + deps = [ + ":comm", + ":crypto", # build_cleaner: keep + ":types", + "//platform/api:comm", + "//platform/api:platform", + "//platform/api:types", + ], +) + +cc_test( + name = "impl_test", + size = "small", + srcs = [ + "crypto_test.cc", + ], + deps = [ + ":comm", + ":crypto", + ":types", + "//platform/api:types", + "//testing/base/public:gunit_main", + ], +) diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/atomic_boolean.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/atomic_boolean.h new file mode 100644 index 00000000000..74239da4d56 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/atomic_boolean.h @@ -0,0 +1,47 @@ +// 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 PLATFORM_IMPL_WINDOWS_ATOMIC_BOOLEAN_H_ +#define PLATFORM_IMPL_WINDOWS_ATOMIC_BOOLEAN_H_ + +#include "platform/api/atomic_boolean.h" + +namespace location { +namespace nearby { +namespace windows { + +// A boolean value that may be updated atomically. +class AtomicBoolean : public api::AtomicBoolean { + public: + // TODO(b/184975123): replace with real implementation. + ~AtomicBoolean() override = default; + + // Atomically read and return current value. + bool Get() const override { + // TODO(b/184975123): replace with real implementation. + return false; + }; + + // Atomically exchange original value with a new one. Return previous value. + bool Set(bool value) override { + // TODO(b/184975123): replace with real implementation. + return false; + }; +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_ATOMIC_BOOLEAN_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/atomic_reference.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/atomic_reference.h new file mode 100644 index 00000000000..0653f4a2fa0 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/atomic_reference.h @@ -0,0 +1,43 @@ +// 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 PLATFORM_IMPL_WINDOWS_ATOMIC_REFERENCE_H_ +#define PLATFORM_IMPL_WINDOWS_ATOMIC_REFERENCE_H_ + +#include "platform/api/atomic_reference.h" + +namespace location { +namespace nearby { +namespace windows { + +// Type that allows 32-bit atomic reads and writes. +class AtomicUint32 : public api::AtomicUint32 { + public: + // TODO(b/184975123): replace with real implementation. + ~AtomicUint32() override = default; + + // Atomically reads and returns stored value. + // TODO(b/184975123): replace with real implementation. + std::uint32_t Get() const override { return 0; }; + + // Atomically stores value. + // TODO(b/184975123): replace with real implementation. + void Set(std::uint32_t value) override {} +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_ATOMIC_REFERENCE_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/ble.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/ble.h new file mode 100644 index 00000000000..4141f732623 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/ble.h @@ -0,0 +1,155 @@ +// 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 PLATFORM_IMPL_WINDOWS_BLE_H_ +#define PLATFORM_IMPL_WINDOWS_BLE_H_ + +#include "platform/api/ble.h" +#include "platform/base/exception.h" +#include "platform/base/input_stream.h" +#include "platform/base/output_stream.h" + +namespace location { +namespace nearby { +namespace windows { + +// Opaque wrapper over a BLE peripheral. Must contain enough data about a +// particular BLE device to connect to its GATT server. +class BlePeripheral : public api::BlePeripheral { + public: + // TODO(b/184975123): replace with real implementation. + ~BlePeripheral() override = default; + + // TODO(b/184975123): replace with real implementation. + std::string GetName() const override { return std::string{""}; } + // TODO(b/184975123): replace with real implementation. + ByteArray GetAdvertisementBytes( + const std::string& service_id) const override { + return ByteArray{}; + } +}; + +class BleSocket : public api::BleSocket { + public: + // TODO(b/184975123): replace with real implementation. + ~BleSocket() override; + + // Returns the InputStream of the BleSocket. + // On error, returned stream will report Exception::kIo on any operation. + // + // The returned object is not owned by the caller, and can be invalidated once + // the BleSocket object is destroyed. + // TODO(b/184975123): replace with real implementation. + InputStream& GetInputStream() override { return fake_input_stream_; } + + // Returns the OutputStream of the BleSocket. + // On error, returned stream will report Exception::kIo on any operation. + // + // The returned object is not owned by the caller, and can be invalidated once + // the BleSocket object is destroyed. + // TODO(b/184975123): replace with real implementation. + OutputStream& GetOutputStream() override { return fake_output_stream_; } + + // Conforms to the same contract as + // https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#close(). + // + // Returns Exception::kIo on error, Exception::kSuccess otherwise. + // TODO(b/184975123): replace with real implementation. + Exception Close() override { return Exception{}; } + + // Returns valid BlePeripheral pointer if there is a connection, and + // nullptr otherwise. + // TODO(b/184975123): replace with real implementation. + BlePeripheral* GetRemotePeripheral() override { return nullptr; } + + // Unhooked InputStream & OutputStream for empty implementation. + // TODO(b/184975123): replace with real implementation. + private: + class FakeInputStream : public InputStream { + ~FakeInputStream() override = default; + ExceptionOr<ByteArray> Read(std::int64_t size) override { + return ExceptionOr<ByteArray>(Exception::kFailed); + } + Exception Close() override { return {.value = Exception::kFailed}; } + }; + class FakeOutputStream : public OutputStream { + ~FakeOutputStream() override = default; + + Exception Write(const ByteArray& data) override { + return {.value = Exception::kFailed}; + } + Exception Flush() override { return {.value = Exception::kFailed}; } + Exception Close() override { return {.value = Exception::kFailed}; } + }; + FakeInputStream fake_input_stream_; + FakeOutputStream fake_output_stream_; +}; + +// Container of operations that can be performed over the BLE medium. +class BleMedium : public api::BleMedium { + public: + // TODO(b/184975123): replace with real implementation. + ~BleMedium() override = default; + + // TODO(b/184975123): replace with real implementation. + bool StartAdvertising( + const std::string& service_id, const ByteArray& advertisement_bytes, + const std::string& fast_advertisement_service_uuid) override { + return false; + } + // TODO(b/184975123): replace with real implementation. + bool StopAdvertising(const std::string& service_id) override { return false; } + + // Returns true once the BLE scan has been initiated. + // TODO(b/184975123): replace with real implementation. + bool StartScanning(const std::string& service_id, + const std::string& fast_advertisement_service_uuid, + DiscoveredPeripheralCallback callback) override { + return false; + } + + // Returns true once BLE scanning for service_id is well and truly stopped; + // after this returns, there must be no more invocations of the + // DiscoveredPeripheralCallback passed in to StartScanning() for service_id. + // TODO(b/184975123): replace with real implementation. + bool StopScanning(const std::string& service_id) override { return false; } + + // Returns true once BLE socket connection requests to service_id can be + // accepted. + // TODO(b/184975123): replace with real implementation. + bool StartAcceptingConnections(const std::string& service_id, + AcceptedConnectionCallback callback) override { + return false; + } + // TODO(b/184975123): replace with real implementation. + bool StopAcceptingConnections(const std::string& service_id) override { + return false; + } + + // Connects to a BLE peripheral. + // On success, returns a new BleSocket. + // On error, returns nullptr. + // TODO(b/184975123): replace with real implementation. + std::unique_ptr<api::BleSocket> Connect( + api::BlePeripheral& peripheral, const std::string& service_id, + CancellationFlag* cancellation_flag) override { + return nullptr; + } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_BLE_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/bluetooth_adapter.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/bluetooth_adapter.h new file mode 100644 index 00000000000..60a7e8ebe67 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/bluetooth_adapter.h @@ -0,0 +1,68 @@ +// 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 PLATFORM_IMPL_WINDOWS_BLUETOOTH_ADAPTER_H_ +#define PLATFORM_IMPL_WINDOWS_BLUETOOTH_ADAPTER_H_ + +#include <string> + +#include "platform/api/bluetooth_adapter.h" + +namespace location { +namespace nearby { +namespace windows { + +// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html +class BluetoothAdapter : public api::BluetoothAdapter { + public: + // TODO(b/184975123): replace with real implementation. + ~BluetoothAdapter() override = default; + + // Synchronously sets the status of the BluetoothAdapter to 'status', and + // returns true if the operation was a success. + // TODO(b/184975123): replace with real implementation. + bool SetStatus(Status status) override { return false; } + // Returns true if the BluetoothAdapter's current status is + // Status::Value::kEnabled. + // TODO(b/184975123): replace with real implementation. + bool IsEnabled() const override { return false; } + + // https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getScanMode() + // + // Returns ScanMode::kUnknown on error. + // TODO(b/184975123): replace with real implementation. + ScanMode GetScanMode() const override { return ScanMode::kUnknown; } + // Synchronously sets the scan mode of the adapter, and returns true if the + // operation was a success. + // TODO(b/184975123): replace with real implementation. + bool SetScanMode(ScanMode scan_mode) override { return false; } + + // https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getName() + // Returns an empty string on error + // TODO(b/184975123): replace with real implementation. + std::string GetName() const override { return "Un-implemented"; } + // https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#setName(java.lang.String) + // TODO(b/184975123): replace with real implementation. + bool SetName(absl::string_view name) override { return false; } + + // Returns BT MAC address assigned to this adapter. + // TODO(b/184975123): replace with real implementation. + std::string GetMacAddress() const override { return "Un-implemented"; } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_BLUETOOTH_ADAPTER_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/bluetooth_classic.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/bluetooth_classic.h new file mode 100644 index 00000000000..7681e7105af --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/bluetooth_classic.h @@ -0,0 +1,186 @@ +// 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 PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_H_ +#define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_H_ + +#include "platform/api/bluetooth_classic.h" +#include "platform/base/exception.h" +#include "platform/base/input_stream.h" +#include "platform/base/output_stream.h" +namespace location { +namespace nearby { +namespace windows { + +// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html. +class BluetoothDevice : public api::BluetoothDevice { + public: + // TODO(b/184975123): replace with real implementation. + ~BluetoothDevice() override = default; + + // https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#getName() + // TODO(b/184975123): replace with real implementation. + std::string GetName() const override { return "Un-implemented"; } + + // Returns BT MAC address assigned to this device. + // TODO(b/184975123): replace with real implementation. + std::string GetMacAddress() const override { return "Un-implemented"; } +}; + +// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html. +class BluetoothSocket : public api::BluetoothSocket { + public: + // TODO(b/184975123): replace with real implementation. + ~BluetoothSocket() override; + + // NOTE: + // It is an undefined behavior if GetInputStream() or GetOutputStream() is + // called for a not-connected BluetoothSocket, i.e. any object that is not + // returned by BluetoothClassicMedium::ConnectToService() for client side or + // BluetoothServerSocket::Accept() for server side of connection. + + // Returns the InputStream of this connected BluetoothSocket. + // TODO(b/184975123): replace with real implementation. + InputStream& GetInputStream() override { return fake_input_stream_; } + + // Returns the OutputStream of this connected BluetoothSocket. + // TODO(b/184975123): replace with real implementation. + OutputStream& GetOutputStream() override { return fake_output_stream_; } + + // Closes both input and output streams, marks Socket as closed. + // After this call object should be treated as not connected. + // Returns Exception::kIo on error, Exception::kSuccess otherwise. + // TODO(b/184975123): replace with real implementation. + Exception Close() override { return Exception{}; } + + // https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#getRemoteDevice() + // Returns valid BluetoothDevice pointer if there is a connection, and + // nullptr otherwise. + // TODO(b/184975123): replace with real implementation. + BluetoothDevice* GetRemoteDevice() override { return nullptr; } + + private: + class FakeInputStream : public InputStream { + ~FakeInputStream() override = default; + ExceptionOr<ByteArray> Read(std::int64_t size) override { + return ExceptionOr<ByteArray>(Exception::kFailed); + } + Exception Close() override { return {.value = Exception::kFailed}; } + }; + class FakeOutputStream : public OutputStream { + ~FakeOutputStream() override = default; + + Exception Write(const ByteArray& data) override { + return {.value = Exception::kFailed}; + } + Exception Flush() override { return {.value = Exception::kFailed}; } + Exception Close() override { return {.value = Exception::kFailed}; } + }; + FakeInputStream fake_input_stream_; + FakeOutputStream fake_output_stream_; +}; + +// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html. +class BluetoothServerSocket : public api::BluetoothServerSocket { + public: + // TODO(b/184975123): replace with real implementation. + ~BluetoothServerSocket() override = default; + + // https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#accept() + // + // Blocks until either: + // - at least one incoming connection request is available, or + // - ServerSocket is closed. + // On success, returns connected socket, ready to exchange data. + // Returns nullptr on error. + // Once error is reported, it is permanent, and ServerSocket has to be closed. + // TODO(b/184975123): replace with real implementation. + std::unique_ptr<api::BluetoothSocket> Accept() override { return nullptr; } + + // https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#close() + // + // Returns Exception::kIo on error, Exception::kSuccess otherwise. + // TODO(b/184975123): replace with real implementation. + Exception Close() override { return Exception{}; } +}; + +// Container of operations that can be performed over the Bluetooth Classic +// medium. +class BluetoothClassicMedium : public api::BluetoothClassicMedium { + public: + // TODO(b/184975123): replace with real implementation. + ~BluetoothClassicMedium() override = default; + + // https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery() + // + // Returns true once the process of discovery has been initiated. + // TODO(b/184975123): replace with real implementation. + bool StartDiscovery(DiscoveryCallback discovery_callback) override { + return false; + } + // https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#cancelDiscovery() + // + // Returns true once discovery is well and truly stopped; after this returns, + // there must be no more invocations of the DiscoveryCallback passed in to + // StartDiscovery(). + // TODO(b/184975123): replace with real implementation. + bool StopDiscovery() override { return false; } + + // A combination of + // https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#createInsecureRfcommSocketToServiceRecord + // followed by + // https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#connect(). + // + // service_uuid is the canonical textual representation + // (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a + // type 3 name-based + // (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based)) + // UUID. + // + // On success, returns a new BluetoothSocket. + // On error, returns nullptr. + // TODO(b/184975123): replace with real implementation. + std::unique_ptr<api::BluetoothSocket> ConnectToService( + api::BluetoothDevice& remote_device, const std::string& service_uuid, + CancellationFlag* cancellation_flag) override { + return nullptr; + } + + // https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord + // + // service_uuid is the canonical textual representation + // (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a + // type 3 name-based + // (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based)) + // UUID. + // + // Returns nullptr error. + // TODO(b/184975123): replace with real implementation. + std::unique_ptr<api::BluetoothServerSocket> ListenForService( + const std::string& service_name, + const std::string& service_uuid) override { + return nullptr; + } + + // TODO(b/184975123): replace with real implementation. + BluetoothDevice* GetRemoteDevice(const std::string& mac_address) override { + return nullptr; + } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/cancelable.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/cancelable.h new file mode 100644 index 00000000000..b538ea5e2e1 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/cancelable.h @@ -0,0 +1,39 @@ +// 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 PLATFORM_IMPL_WINDOWS_CANCELABLE_H_ +#define PLATFORM_IMPL_WINDOWS_CANCELABLE_H_ + +#include "platform/api/cancelable.h" + +namespace location { +namespace nearby { +namespace windows { + +// An interface to provide a cancellation mechanism for objects that represent +// long-running operations. +class Cancelable : public api::Cancelable { + public: + // TODO(b/184975123): replace with real implementation. + ~Cancelable() override = default; + + // TODO(b/184975123): replace with real implementation. + bool Cancel() override { return false; }; +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_CANCELABLE_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/condition_variable.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/condition_variable.h new file mode 100644 index 00000000000..cd8c75d483f --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/condition_variable.h @@ -0,0 +1,54 @@ +// 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 PLATFORM_IMPL_WINDOWS_CONDITION_VARIABLE_H_ +#define PLATFORM_IMPL_WINDOWS_CONDITION_VARIABLE_H_ + +#include "platform/api/condition_variable.h" + +namespace location { +namespace nearby { +namespace windows { + +// The ConditionVariable class is a synchronization primitive that can be used +// to block a thread, or multiple threads at the same time, until another thread +// both modifies a shared variable (the condition), and notifies the +// ConditionVariable. +class ConditionVariable : public api::ConditionVariable { + public: + // TODO(b/184975123): replace with real implementation. + ~ConditionVariable() override = default; + + // Notifies all the waiters that condition state has changed. + // TODO(b/184975123): replace with real implementation. + void Notify() override {} + + // Waits indefinitely for Notify to be called. + // May return prematurely in case of interrupt, if supported by platform. + // Returns kSuccess, or kInterrupted on interrupt. + // TODO(b/184975123): replace with real implementation. + Exception Wait() override { return Exception{}; } + + // Waits while timeout has not expired for Notify to be called. + // May return prematurely in case of interrupt, if supported by platform. + // Returns kSuccess, or kInterrupted on interrupt. + // TODO(b/184975123): replace with real implementation. + Exception Wait(absl::Duration timeout) override { return Exception{}; } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_CONDITION_VARIABLE_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/count_down_latch.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/count_down_latch.h new file mode 100644 index 00000000000..bacac4b7865 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/count_down_latch.h @@ -0,0 +1,47 @@ +// 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 PLATFORM_IMPL_WINDOWS_COUNT_DOWN_LATCH_H_ +#define PLATFORM_IMPL_WINDOWS_COUNT_DOWN_LATCH_H_ + +#include "platform/api/count_down_latch.h" + +namespace location { +namespace nearby { +namespace windows { + +// A synchronization aid that allows one or more threads to wait until a set of +// operations being performed in other threads completes. +// +// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html +class CountDownLatch : public api::CountDownLatch { + public: + // TODO(b/184975123): replace with real implementation. + ~CountDownLatch() override = default; + + // TODO(b/184975123): replace with real implementation. + Exception Await() override { return Exception{}; } + // TODO(b/184975123): replace with real implementation. + ExceptionOr<bool> Await(absl::Duration timeout) override { + return Exception{}; + } + // TODO(b/184975123): replace with real implementation. + void CountDown() override{}; +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_COUNT_DOWN_LATCH_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/crypto.cc b/chromium/third_party/nearby/src/cpp/platform/impl/windows/crypto.cc new file mode 100644 index 00000000000..263bec273b4 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/crypto.cc @@ -0,0 +1,54 @@ +// 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 "platform/api/crypto.h" + +#include <cstdint> +#include <string> + +#include "platform/base/byte_array.h" +#include "absl/strings/string_view.h" +#include "openssl/digest.h" + +// Function implementations for platform/api/crypto.h. +namespace location { +namespace nearby { + +// Initialize global crypto state. +void Crypto::Init() {} + +static ByteArray Hash(absl::string_view input, const EVP_MD* algo) { + unsigned int md_out_size = EVP_MAX_MD_SIZE; + uint8_t digest_buffer[EVP_MAX_MD_SIZE]; + if (input.empty()) return {}; + + if (!EVP_Digest(input.data(), input.size(), digest_buffer, &md_out_size, algo, + nullptr)) + return {}; + + return ByteArray{reinterpret_cast<char*>(digest_buffer), md_out_size}; +} + +// Return MD5 hash of input. +ByteArray Crypto::Md5(absl::string_view input) { + return Hash(input, EVP_md5()); +} + +// Return SHA256 hash of input. +ByteArray Crypto::Sha256(absl::string_view input) { + return Hash(input, EVP_sha256()); +} + +} // namespace nearby +} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/crypto_test.cc b/chromium/third_party/nearby/src/cpp/platform/impl/windows/crypto_test.cc new file mode 100644 index 00000000000..5276a9e6f05 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/crypto_test.cc @@ -0,0 +1,50 @@ +// 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 "platform/api/crypto.h" + +#include "gtest/gtest.h" + +namespace location { +namespace nearby { +namespace { + +TEST(CryptoTest, Md5Hash) { + const std::string input{"Hello Nearby Connection"}; + const ByteArray expected_md5( + "\x94\xa3\xbe\xc1\x8d\x30\xe3\x24\x5f\xa1\x4c\xee\xe7\x52\xe9\x36"); + ByteArray md5_hash = Crypto::Md5(input); + EXPECT_EQ(md5_hash, expected_md5); +} + +TEST(CryptoTest, Md5HashOnEmptyInput) { + EXPECT_EQ(Crypto::Md5(""), ByteArray{}); +} + +TEST(CryptoTest, Sha256Hash) { + const std::string input("Hello Nearby Connection"); + const ByteArray expected_sha256( + "\xb4\x24\xd3\xc0\x58\x12\x9a\x42\xcb\x81\xa0\x4b\x6e\x9d\xfe\x45\x45\x9f" + "\x15\xf7\xc0\xa9\x32\x2f\xfb\x9\x45\xf0\xf9\xbe\x75\xb"); + ByteArray sha256_hash = Crypto::Sha256(input); + EXPECT_EQ(sha256_hash, expected_sha256); +} + +TEST(CryptoTest, Sha256HashOnEmptyInput) { + EXPECT_EQ(Crypto::Sha256(""), ByteArray{}); +} + +} // namespace +} // namespace nearby +} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/executor.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/executor.h new file mode 100644 index 00000000000..4f521368a14 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/executor.h @@ -0,0 +1,48 @@ +// 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 PLATFORM_IMPL_WINDOWS_EXECUTOR_H_ +#define PLATFORM_IMPL_WINDOWS_EXECUTOR_H_ + +#include "platform/api/executor.h" + +namespace location { +namespace nearby { +namespace windows { + +// This abstract class is the superclass of all classes representing an +// Executor. +class Executor : public api::Executor { + public: + // Before returning from destructor, executor must wait for all pending + // jobs to finish. + // TODO(b/184975123): replace with real implementation. + ~Executor() override = default; + // https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable- + // TODO(b/184975123): replace with real implementation. + void Execute(Runnable&& runnable) override {} + + // https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown-- + // TODO(b/184975123): replace with real implementation. + void Shutdown() override {} + + // TODO(b/184975123): replace with real implementation. + int GetTid(int index) const override { return 0; } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_EXECUTOR_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/future.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/future.h new file mode 100644 index 00000000000..6dee7e37f65 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/future.h @@ -0,0 +1,50 @@ +// 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 PLATFORM_IMPL_WINDOWS_FUTURE_H_ +#define PLATFORM_IMPL_WINDOWS_FUTURE_H_ + +#include "platform/api/future.h" + +namespace location { +namespace nearby { +namespace windows { + +// A Future represents the result of an asynchronous computation. +// +// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html +template <typename T> +class Future : public api::Future<T> { + public: + // TODO(b/184975123): replace with real implementation. + ~Future() override = default; + + // throws Exception::kInterrupted, Exception::kExecution + // TODO(b/184975123): replace with real implementation. + ExceptionOr<T> Get() override { return ExceptionOr<T>{Exception::kFailed}; } + + // throws Exception::kInterrupted, Exception::kExecution + // throws Exception::kTimeout if timeout is exceeded while waiting for + // result. + // TODO(b/184975123): replace with real implementation. + ExceptionOr<T> Get(absl::Duration timeout) override { + return ExceptionOr<T>{Exception::kFailed}; + } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_FUTURE_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/input_file.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/input_file.h new file mode 100644 index 00000000000..1ed3982141c --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/input_file.h @@ -0,0 +1,50 @@ +// 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 PLATFORM_IMPL_WINDOWS_INPUT_FILE_H_ +#define PLATFORM_IMPL_WINDOWS_INPUT_FILE_H_ + +#include "platform/api/input_file.h" +#include "platform/base/byte_array.h" +#include "platform/base/exception.h" + +namespace location { +namespace nearby { +namespace windows { + +// An InputFile represents a readable file on the system. +class InputFile : public api::InputFile { + public: + // TODO(b/184975123): replace with real implementation. + ~InputFile() override = default; + // TODO(b/184975123): replace with real implementation. + std::string GetFilePath() const override { return "Un-implemented"; } + // TODO(b/184975123): replace with real implementation. + std::int64_t GetTotalSize() const override { return 0; } + + // throws Exception::kIo + // TODO(b/184975123): replace with real implementation. + ExceptionOr<ByteArray> Read(std::int64_t size) override { + return ExceptionOr<ByteArray>(Exception::kFailed); + } + // throws Exception::kIo + // TODO(b/184975123): replace with real implementation. + Exception Close() override { return Exception{}; } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_INPUT_FILE_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/listenable_future.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/listenable_future.h new file mode 100644 index 00000000000..954fe01badb --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/listenable_future.h @@ -0,0 +1,41 @@ +// 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 PLATFORM_IMPL_WINDOWS_LISTENABLE_FUTURE_H_ +#define PLATFORM_IMPL_WINDOWS_LISTENABLE_FUTURE_H_ + +#include "platform/api/listenable_future.h" + +namespace location { +namespace nearby { +namespace windows { + +// A Future that accepts completion listeners. +// +// https://guava.dev/releases/20.0/api/docs/com/google/common/util/concurrent/ListenableFuture.html +template <typename T> +class ListenableFuture : public api::ListenableFuture<T> { + public: + // TODO(b/184975123): replace with real implementation. + ~ListenableFuture() override = default; + + // TODO(b/184975123): replace with real implementation. + void AddListener(Runnable runnable, api::Executor* executor) {} +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_LISTENABLE_FUTURE_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/log_message.cc b/chromium/third_party/nearby/src/cpp/platform/impl/windows/log_message.cc new file mode 100644 index 00000000000..f220176f561 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/log_message.cc @@ -0,0 +1,29 @@ +// 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 "platform/impl/windows/log_message.h" + +namespace location { +namespace nearby { +namespace api { + +// TODO(b/184975123): replace with real implementation. +void LogMessage::SetMinLogSeverity(Severity severity) {} + +// TODO(b/184975123): replace with real implementation. +bool LogMessage::ShouldCreateLogMessage(Severity severity) { return false; } + +} // namespace api +} // namespace nearby +} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/log_message.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/log_message.h new file mode 100644 index 00000000000..2fd5308c06c --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/log_message.h @@ -0,0 +1,50 @@ +// 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 PLATFORM_IMPL_WINDOWS_LOG_MESSAGE_H_ +#define PLATFORM_IMPL_WINDOWS_LOG_MESSAGE_H_ + +#include "platform/api/log_message.h" + +namespace location { +namespace nearby { +namespace windows { + +// A log message that prints to appropraite destination when ~LogMessage() is +// called. +// +// note: the Severity enum should map (best effort) to the corresponding level +// id that the platform logging implementation has. +class LogMessage : public api::LogMessage { + public: + // TODO(b/184975123): replace with real implementation. + ~LogMessage() override = default; + + // Printf like logging. + // TODO(b/184975123): replace with real implementation. + void Print(const char* format, ...) override {} + + // Returns a stream for std::cout like logging. + // TODO(b/184975123): replace with real implementation. + std::ostream& Stream() override { return empty_stream_; } + + // TODO(b/184975123): replace with real implementation. + std::ostream empty_stream_; +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_LOG_MESSAGE_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/mutex.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/mutex.h new file mode 100644 index 00000000000..2fee6a2f861 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/mutex.h @@ -0,0 +1,43 @@ +// 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 PLATFORM_IMPL_WINDOWS_MUTEX_H_ +#define PLATFORM_IMPL_WINDOWS_MUTEX_H_ + +#include "platform/api/mutex.h" + +namespace location { +namespace nearby { +namespace windows { + +// A lock is a tool for controlling access to a shared resource by multiple +// threads. +// +// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Lock.html +class Mutex : public api::Mutex { + public: + // TODO(b/184975123): replace with real implementation. + ~Mutex() override = default; + + // TODO(b/184975123): replace with real implementation. + void Lock() override {} + // TODO(b/184975123): replace with real implementation. + void Unlock() override {} +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_MUTEX_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/output_file.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/output_file.h new file mode 100644 index 00000000000..9ad479b6c1b --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/output_file.h @@ -0,0 +1,47 @@ +// 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 PLATFORM_IMPL_WINDOWS_OUTPUT_FILE_H_ +#define PLATFORM_IMPL_WINDOWS_OUTPUT_FILE_H_ + +#include "platform/api/output_file.h" +#include "platform/base/byte_array.h" +#include "platform/base/exception.h" + +namespace location { +namespace nearby { +namespace windows { + +// An OutputFile represents a writable file on the system. +class OutputFile : public api::OutputFile { + public: + // TODO(b/184975123): replace with real implementation. + ~OutputFile() override = default; + + // throws Exception::kIo + // TODO(b/184975123): replace with real implementation. + Exception Write(const ByteArray& data) override { return Exception{}; } + // throws Exception::kIo + // TODO(b/184975123): replace with real implementation. + Exception Flush() override { return Exception{}; } + // throws Exception::kIo + // TODO(b/184975123): replace with real implementation. + Exception Close() override { return Exception{}; } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_OUTPUT_FILE_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/platform.cc b/chromium/third_party/nearby/src/cpp/platform/impl/windows/platform.cc new file mode 100644 index 00000000000..e8f3372db6e --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/platform.cc @@ -0,0 +1,158 @@ +// 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 "platform/api/platform.h" + +#include "platform/impl/windows/atomic_boolean.h" +#include "platform/impl/windows/atomic_reference.h" +#include "platform/impl/windows/ble.h" +#include "platform/impl/windows/bluetooth_adapter.h" +#include "platform/impl/windows/bluetooth_classic.h" +#include "platform/impl/windows/cancelable.h" +#include "platform/impl/windows/condition_variable.h" +#include "platform/impl/windows/count_down_latch.h" +#include "platform/impl/windows/executor.h" +#include "platform/impl/windows/future.h" +#include "platform/impl/windows/input_file.h" +#include "platform/impl/windows/listenable_future.h" +#include "platform/impl/windows/log_message.h" +#include "platform/impl/windows/mutex.h" +#include "platform/impl/windows/output_file.h" +#include "platform/impl/windows/scheduled_executor.h" +#include "platform/impl/windows/server_sync.h" +#include "platform/impl/windows/settable_future.h" +#include "platform/impl/windows/submittable_executor.h" +#include "platform/impl/windows/webrtc.h" +#include "platform/impl/windows/wifi.h" +#include "platform/impl/windows/wifi_lan.h" + +namespace location { +namespace nearby { +namespace api { + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<AtomicBoolean> ImplementationPlatform::CreateAtomicBoolean( + bool initial_value) { + return absl::make_unique<windows::AtomicBoolean>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<AtomicUint32> ImplementationPlatform::CreateAtomicUint32( + std::uint32_t value) { + return absl::make_unique<windows::AtomicUint32>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<CountDownLatch> ImplementationPlatform::CreateCountDownLatch( + std::int32_t count) { + return absl::make_unique<windows::CountDownLatch>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<Mutex> ImplementationPlatform::CreateMutex(Mutex::Mode mode) { + return absl::make_unique<windows::Mutex>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<ConditionVariable> +ImplementationPlatform::CreateConditionVariable(Mutex* mutex) { + return std::unique_ptr<ConditionVariable>(new windows::ConditionVariable()); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<InputFile> ImplementationPlatform::CreateInputFile( + PayloadId payload_id, std::int64_t total_size) { + return absl::make_unique<windows::InputFile>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile( + PayloadId payload_id) { + return absl::make_unique<windows::OutputFile>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<LogMessage> ImplementationPlatform::CreateLogMessage( + const char* file, int line, LogMessage::Severity severity) { + return nullptr; +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<SubmittableExecutor> +ImplementationPlatform::CreateSingleThreadExecutor() { + return absl::make_unique<windows::SubmittableExecutor>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<SubmittableExecutor> +ImplementationPlatform::CreateMultiThreadExecutor( + std::int32_t max_concurrency) { + return absl::make_unique<windows::SubmittableExecutor>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<ScheduledExecutor> +ImplementationPlatform::CreateScheduledExecutor() { + return absl::make_unique<windows::ScheduledExecutor>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<BluetoothAdapter> +ImplementationPlatform::CreateBluetoothAdapter() { + return absl::make_unique<windows::BluetoothAdapter>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<BluetoothClassicMedium> +ImplementationPlatform::CreateBluetoothClassicMedium( + BluetoothAdapter& adapter) { + return absl::make_unique<windows::BluetoothClassicMedium>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium( + BluetoothAdapter& adapter) { + return absl::make_unique<windows::BleMedium>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<ble_v2::BleMedium> ImplementationPlatform::CreateBleV2Medium( + BluetoothAdapter&) { + return nullptr; +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<ServerSyncMedium> +ImplementationPlatform::CreateServerSyncMedium() { + return std::unique_ptr<windows::ServerSyncMedium>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<WifiMedium> ImplementationPlatform::CreateWifiMedium() { + return std::unique_ptr<WifiMedium>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<WifiLanMedium> ImplementationPlatform::CreateWifiLanMedium() { + return absl::make_unique<windows::WifiLanMedium>(); +} + +// TODO(b/184975123): replace with real implementation. +std::unique_ptr<WebRtcMedium> ImplementationPlatform::CreateWebRtcMedium() { + return absl::make_unique<windows::WebRtcMedium>(); +} + +} // namespace api +} // namespace nearby +} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/scheduled_executor.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/scheduled_executor.h new file mode 100644 index 00000000000..a1e6122780f --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/scheduled_executor.h @@ -0,0 +1,59 @@ +// 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 PLATFORM_IMPL_WINDOWS_SCHEDULED_EXECUTOR_H_ +#define PLATFORM_IMPL_WINDOWS_SCHEDULED_EXECUTOR_H_ + +#include "platform/api/scheduled_executor.h" + +namespace location { +namespace nearby { +namespace windows { + +// An Executor that can schedule commands to run after a given delay, or to +// execute periodically. +// +// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html +class ScheduledExecutor : public api::ScheduledExecutor { + public: + // TODO(b/184975123): replace with real implementation. + ~ScheduledExecutor() override = default; + + // Cancelable is kept both in the executor context, and in the caller context. + // We want Cancelable to live until both caller and executor are done with it. + // Exclusive ownership model does not work for this case; + // using std:shared_ptr<> instead if std::unique_ptr<>. + // TODO(b/184975123): replace with real implementation. + std::shared_ptr<api::Cancelable> Schedule(Runnable&& runnable, + absl::Duration duration) override { + return nullptr; + } + + // https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable- + // TODO(b/184975123): replace with real implementation. + void Execute(Runnable&& runnable) override {} + + // https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown-- + // TODO(b/184975123): replace with real implementation. + void Shutdown() override {} + + // TODO(b/184975123): replace with real implementation. + int GetTid(int index) const override { return 0; } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_SCHEDULED_EXECUTOR_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/server_sync.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/server_sync.h new file mode 100644 index 00000000000..ec59745f365 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/server_sync.h @@ -0,0 +1,90 @@ +// 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 PLATFORM_IMPL_WINDOWS_SERVER_SYNC_H_ +#define PLATFORM_IMPL_WINDOWS_SERVER_SYNC_H_ + +#include "platform/api/server_sync.h" + +namespace location { +namespace nearby { +namespace windows { + +// Abstraction that represents a Nearby endpoint exchanging data through +// ServerSync Medium. +class ServerSyncDevice : public api::ServerSyncDevice { + public: + // TODO(b/184975123): replace with real implementation. + ~ServerSyncDevice() override = default; + + // TODO(b/184975123): replace with real implementation. + std::string GetName() const override { return "Un-implemented"; } + // TODO(b/184975123): replace with real implementation. + std::string GetGuid() const override { return "Un-implemented"; } + // TODO(b/184975123): replace with real implementation. + std::string GetOwnGuid() const override { return "Un-implemented"; } +}; + +// Container of operations that can be performed over the Chrome Sync medium. +class ServerSyncMedium : public api::ServerSyncMedium { + public: + // TODO(b/184975123): replace with real implementation. + ~ServerSyncMedium() override = default; + + // TODO(b/184975123): replace with real implementation. + bool StartAdvertising(absl::string_view service_id, + absl::string_view endpoint_id, + const ByteArray& endpoint_info) override { + return false; + } + // TODO(b/184975123): replace with real implementation. + void StopAdvertising(absl::string_view service_id) override {} + + class DiscoveredDeviceCallback + : public api::ServerSyncMedium::DiscoveredDeviceCallback { + public: + // TODO(b/184975123): replace with real implementation. + ~DiscoveredDeviceCallback() override = default; + + // Called on a new ServerSyncDevice discovery. + // TODO(b/184975123): replace with real implementation. + void OnDeviceDiscovered(api::ServerSyncDevice* device, + absl::string_view service_id, + absl::string_view endpoint_id, + const ByteArray& endpoint_info) override {} + // Called when ServerSyncDevice is no longer reachable. + // TODO(b/184975123): replace with real implementation. + void OnDeviceLost(api::ServerSyncDevice* device, + absl::string_view service_id) override {} + }; + + // Returns true once the Chrome Sync scan has been initiated. + // TODO(b/184975123): replace with real implementation. + bool StartDiscovery(absl::string_view service_id, + const api::ServerSyncMedium::DiscoveredDeviceCallback& + discovered_device_callback) override { + return false; + } + // Returns true once Chrome Sync scan for service_id is well and truly + // stopped; after this returns, there must be no more invocations of the + // DiscoveredDeviceCallback passed in to startScanning() for service_id. + // TODO(b/184975123): replace with real implementation. + void StopDiscovery(absl::string_view service_id) override {} +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_SERVER_SYNC_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/settable_future.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/settable_future.h new file mode 100644 index 00000000000..99f9a02c059 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/settable_future.h @@ -0,0 +1,51 @@ +// 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 PLATFORM_IMPL_WINDOWS_SETTABLE_FUTURE_H_ +#define PLATFORM_IMPL_WINDOWS_SETTABLE_FUTURE_H_ + +#include "platform/api/settable_future.h" + +namespace location { +namespace nearby { +namespace windows { + +// A SettableFuture is a type of Future whose result can be set. +// +// https://google.github.io/guava/releases/20.0/api/docs/com/google/common/util/concurrent/SettableFuture.html +template <typename T> +class SettableFuture : public api::SettableFuture<T> { + public: + // TODO(b/184975123): replace with real implementation. + ~SettableFuture() override = default; + + // Completes the future successfully. The value is returned to any waiters. + // Returns true, if value was set. + // Returns false, if Future is already in "done" state. + // TODO(b/184975123): replace with real implementation. + bool Set(T value) override { return false; } + + // Completes the future unsuccessfully. The exception value is returned to any + // waiters. + // Returns true, if exception was set. + // Returns false, if Future is already in "done" state. + // TODO(b/184975123): replace with real implementation. + bool SetException(Exception exception) override { return false; } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_SETTABLE_FUTURE_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/submittable_executor.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/submittable_executor.h new file mode 100644 index 00000000000..9533a5e906d --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/submittable_executor.h @@ -0,0 +1,55 @@ +// 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 PLATFORM_IMPL_WINDOWS_SUBMITTABLE_EXECUTOR_H_ +#define PLATFORM_IMPL_WINDOWS_SUBMITTABLE_EXECUTOR_H_ + +#include "platform/api/submittable_executor.h" + +namespace location { +namespace nearby { +namespace windows { + +// Main interface to be used by platform as a base class for +// - MultiThreadExecutorWrapper +// - SingleThreadExecutorWrapper +// Platform must override bool submit(std::function<void()>) method. +class SubmittableExecutor : public api::SubmittableExecutor { + public: + // TODO(b/184975123): replace with real implementation. + ~SubmittableExecutor() override = default; + + // Submit a callable (with no delay). + // Returns true, if callable was submitted, false otherwise. + // Callable is not submitted if shutdown is in progress. + // TODO(b/184975123): replace with real implementation. + bool DoSubmit(Runnable&& wrapped_callable) override { return false; } + + // https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable- + // TODO(b/184975123): replace with real implementation. + void Execute(Runnable&& runnable) override {} + + // https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown-- + // TODO(b/184975123): replace with real implementation. + void Shutdown() override {} + + // TODO(b/184975123): replace with real implementation. + int GetTid(int index) const override { return 0; } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_SUBMITTABLE_EXECUTOR_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/system_clock.cc b/chromium/third_party/nearby/src/cpp/platform/impl/windows/system_clock.cc new file mode 100644 index 00000000000..7da94eb8683 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/system_clock.cc @@ -0,0 +1,36 @@ +// 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 PLATFORM_IMPL_WINDOWS_SYSTEM_CLOCK_H_ +#define PLATFORM_IMPL_WINDOWS_SYSTEM_CLOCK_H_ + +#include "platform/api/system_clock.h" + +namespace location { +namespace nearby { + +// Initialize global system state. +// TODO(b/184975123): replace with real implementation. +void SystemClock::Init() {} +// Returns current absolute time. It is guaranteed to be monotonic. +// TODO(b/184975123): replace with real implementation. +absl::Time SystemClock::ElapsedRealtime() { return absl::UnixEpoch(); } +// Pauses current thread for the specified duration. +// TODO(b/184975123): replace with real implementation. +Exception SystemClock::Sleep(absl::Duration duration) { return Exception{}; } + +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_SYSTEM_CLOCK_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/webrtc.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/webrtc.h new file mode 100644 index 00000000000..24aa5a92466 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/webrtc.h @@ -0,0 +1,78 @@ +// 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 PLATFORM_IMPL_WINDOWS_WEBRTC_H_ +#define PLATFORM_IMPL_WINDOWS_WEBRTC_H_ + +#include "platform/api/webrtc.h" + +namespace location { +namespace nearby { +namespace windows { + +class WebRtcSignalingMessenger : public api::WebRtcSignalingMessenger { + public: + // TODO(b/184975123): replace with real implementation. + ~WebRtcSignalingMessenger() override = default; + + // TODO(b/184975123): replace with real implementation. + bool SendMessage(absl::string_view peer_id, + const ByteArray& message) override { + return false; + } + + // TODO(b/184975123): replace with real implementation. + bool StartReceivingMessages( + api::WebRtcSignalingMessenger::OnSignalingMessageCallback + on_message_callback, + api::WebRtcSignalingMessenger::OnSignalingCompleteCallback + on_complete_callback) override { + return false; + } + // TODO(b/184975123): replace with real implementation. + void StopReceivingMessages() override {} +}; + +class WebRtcMedium : public api::WebRtcMedium { + public: + // TODO(b/184975123): replace with real implementation. + ~WebRtcMedium() override = default; + + // Gets the default two-letter country code associated with current locale. + // For example, en_US locale resolves to "US". + // TODO(b/184975123): replace with real implementation. + const std::string GetDefaultCountryCode() override { + return "Un-implemented"; + } + + // Creates and returns a new webrtc::PeerConnectionInterface object via + // |callback|. + // TODO(b/184975123): replace with real implementation. + void CreatePeerConnection(webrtc::PeerConnectionObserver* observer, + PeerConnectionCallback callback) override {} + + // Returns a signaling messenger for sending WebRTC signaling messages. + // TODO(b/184975123): replace with real implementation. + std::unique_ptr<api::WebRtcSignalingMessenger> GetSignalingMessenger( + absl::string_view self_id, + const connections::LocationHint& location_hint) override { + return nullptr; + } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_WEBRTC_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/wifi.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/wifi.h new file mode 100644 index 00000000000..00ca53580d0 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/wifi.h @@ -0,0 +1,98 @@ +// 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 PLATFORM_IMPL_WINDOWS_WIFI_H_ +#define PLATFORM_IMPL_WINDOWS_WIFI_H_ + +#include "platform/api/wifi.h" + +namespace location { +namespace nearby { +namespace windows { + +// Represents a WiFi network found during a call to WifiMedium#scan(). +class WifiScanResult : public api::WifiScanResult { + public: + // TODO(b/184975123): replace with real implementation. + ~WifiScanResult() override = default; + + // Gets the SSID of this WiFi network. + // TODO(b/184975123): replace with real implementation. + std::string GetSsid() const override { return "Un-implemented"; } + // Gets the signal strength of this WiFi network in dBm. + // TODO(b/184975123): replace with real implementation. + std::int32_t GetSignalStrengthDbm() const override { return 0; } + // Gets the frequency band of this WiFi network in MHz. + // TODO(b/184975123): replace with real implementation. + std::int32_t GetFrequencyMhz() const override { return 0; } + // Gets the authentication type of this WiFi network. + // TODO(b/184975123): replace with real implementation. + api::WifiAuthType GetAuthType() const override { + return api::WifiAuthType::kUnknown; + } +}; + +// Container of operations that can be performed over the WiFi medium. +class WifiMedium : public api::WifiMedium { + public: + // TODO(b/184975123): replace with real implementation. + ~WifiMedium() override = default; + + class ScanResultCallback : public api::WifiMedium::ScanResultCallback { + public: + // TODO(b/184975123): replace with real implementation. + ~ScanResultCallback() override = default; + + // TODO(b/184975123): replace with real implementation. + void OnScanResults( + const std::vector<api::WifiScanResult>& scan_results) override {} + }; + + // Does not take ownership of the passed-in scan_result_callback -- destroying + // that is up to the caller. + // TODO(b/184975123): replace with real implementation. + bool Scan(const api::WifiMedium::ScanResultCallback& scan_result_callback) + override { + return false; + } + + // If 'password' is an empty string, none has been provided. Returns + // WifiConnectionStatus::CONNECTED on success, or the appropriate failure code + // otherwise. + // TODO(b/184975123): replace with real implementation. + api::WifiConnectionStatus ConnectToNetwork( + absl::string_view ssid, absl::string_view password, + api::WifiAuthType auth_type) override { + return api::WifiConnectionStatus::kUnknown; + } + + // Blocks until it's certain of there being a connection to the internet, or + // returns false if it fails to do so. + // + // How this method wants to verify said connection is totally up to it (so it + // can feel free to ping whatever server, download whatever resource, etc. + // that it needs to gain confidence that the internet is reachable hereon in). + // TODO(b/184975123): replace with real implementation. + bool VerifyInternetConnectivity() override { return false; } + + // Returns the local device's IP address in the IPv4 dotted-quad format. + // TODO(b/184975123): replace with real implementation. + std::string GetIpAddress() override { return "Un-implemented"; } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_WIFI_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/impl/windows/wifi_lan.h b/chromium/third_party/nearby/src/cpp/platform/impl/windows/wifi_lan.h new file mode 100644 index 00000000000..84f5c28319d --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/impl/windows/wifi_lan.h @@ -0,0 +1,160 @@ +// 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 PLATFORM_IMPL_WINDOWS_WIFI_LAN_H_ +#define PLATFORM_IMPL_WINDOWS_WIFI_LAN_H_ + +#include "platform/api/wifi_lan.h" +#include "platform/base/exception.h" +#include "platform/base/input_stream.h" +#include "platform/base/output_stream.h" + +namespace location { +namespace nearby { +namespace windows { + +// Opaque wrapper over a WifiLan service which contains |NsdServiceInfo|. +class WifiLanService : public api::WifiLanService { + public: + // TODO(b/184975123): replace with real implementation. + ~WifiLanService() override = default; + + // Returns the |NsdServiceInfo| which contains the packed string of + // |WifiLanServiceInfo| and the endpoint info with named key in a TXTRecord + // map. + // The details refer to + // https://developer.android.com/reference/android/net/nsd/NsdServiceInfo.html. + // TODO(b/184975123): replace with real implementation. + NsdServiceInfo GetServiceInfo() const override { return NsdServiceInfo{}; } +}; + +class WifiLanSocket : public api::WifiLanSocket { + public: + // TODO(b/184975123): replace with real implementation. + ~WifiLanSocket() override; + + // Returns the InputStream of the WifiLanSocket. + // On error, returned stream will report Exception::kIo on any operation. + // + // The returned object is not owned by the caller, and can be invalidated once + // the WifiLanSocket object is destroyed. + // TODO(b/184975123): replace with real implementation. + InputStream& GetInputStream() override { return fake_input_stream_; } + + // Returns the OutputStream of the WifiLanSocket. + // On error, returned stream will report Exception::kIo on any operation. + // + // The returned object is not owned by the caller, and can be invalidated once + // the WifiLanSocket object is destroyed. + // TODO(b/184975123): replace with real implementation. + OutputStream& GetOutputStream() override { return fake_output_stream_; } + + // Returns Exception::kIo on error, Exception::kSuccess otherwise. + // TODO(b/184975123): replace with real implementation. + Exception Close() override { return Exception{}; } + + // Returns valid WifiLanService pointer if there is a connection, and + // nullptr otherwise. + // TODO(b/184975123): replace with real implementation. + WifiLanService* GetRemoteWifiLanService() override { return nullptr; } + + private: + // TODO(b/184975123): replace with real implementation. + class FakeInputStream : public InputStream { + ~FakeInputStream() override = default; + ExceptionOr<ByteArray> Read(std::int64_t size) override { + return ExceptionOr<ByteArray>(Exception::kFailed); + } + Exception Close() override { return {.value = Exception::kFailed}; } + }; + class FakeOutputStream : public OutputStream { + ~FakeOutputStream() override = default; + + Exception Write(const ByteArray& data) override { + return {.value = Exception::kFailed}; + } + Exception Flush() override { return {.value = Exception::kFailed}; } + Exception Close() override { return {.value = Exception::kFailed}; } + }; + FakeInputStream fake_input_stream_; + FakeOutputStream fake_output_stream_; +}; + +// Container of operations that can be performed over the WifiLan medium. +class WifiLanMedium : public api::WifiLanMedium { + public: + // TODO(b/184975123): replace with real implementation. + ~WifiLanMedium() override = default; + + // TODO(b/184975123): replace with real implementation. + bool StartAdvertising(const std::string& service_id, + const NsdServiceInfo& nsd_service_info) override { + return false; + } + // TODO(b/184975123): replace with real implementation. + bool StopAdvertising(const std::string& service_id) override { return false; } + + // Returns true once the WifiLan discovery has been initiated. + // TODO(b/184975123): replace with real implementation. + bool StartDiscovery(const std::string& service_id, + DiscoveredServiceCallback callback) override { + return false; + } + + // Returns true once WifiLan discovery for service_id is well and truly + // stopped; after this returns, there must be no more invocations of the + // DiscoveredServiceCallback passed in to StartDiscovery() for service_id. + // TODO(b/184975123): replace with real implementation. + bool StopDiscovery(const std::string& service_id) override { return false; } + + // Returns true once WifiLan socket connection requests to service_id can be + // accepted. + // TODO(b/184975123): replace with real implementation. + bool StartAcceptingConnections(const std::string& service_id, + AcceptedConnectionCallback callback) override { + return false; + } + // TODO(b/184975123): replace with real implementation. + bool StopAcceptingConnections(const std::string& service_id) override { + return false; + } + + // Connects to a WifiLan service. + // On success, returns a new WifiLanSocket. + // On error, returns nullptr. + // TODO(b/184975123): replace with real implementation. + std::unique_ptr<api::WifiLanSocket> Connect( + api::WifiLanService& wifi_lan_service, const std::string& service_id, + CancellationFlag* cancellation_flag) override { + return nullptr; + } + + // TODO(b/184975123): replace with real implementation. + WifiLanService* GetRemoteService(const std::string& ip_address, + int port) override { + return nullptr; + } + + // TODO(b/184975123): replace with real implementation. + std::pair<std::string, int> GetServiceAddress( + const std::string& service_id) override { + return std::pair<std::string, int>{"Un-implemented", 0}; + } +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_WIFI_LAN_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/public/BUILD b/chromium/third_party/nearby/src/cpp/platform/public/BUILD index 459584d54e3..008dae9e94b 100644 --- a/chromium/third_party/nearby/src/cpp/platform/public/BUILD +++ b/chromium/third_party/nearby/src/cpp/platform/public/BUILD @@ -17,6 +17,8 @@ load("//tools/build_defs/cc:cc_fake_binary.bzl", "cc_fake_binary") cc_library( name = "types", srcs = [ + "monitored_runnable.cc", + "pending_job_registry.cc", "pipe.cc", ], hdrs = [ @@ -32,9 +34,11 @@ cc_library( "future.h", "lockable.h", "logging.h", + "monitored_runnable.h", "multi_thread_executor.h", "mutex.h", "mutex_lock.h", + "pending_job_registry.h", "pipe.h", "scheduled_executor.h", "settable_future.h", diff --git a/chromium/third_party/nearby/src/cpp/platform/public/ble_test.cc b/chromium/third_party/nearby/src/cpp/platform/public/ble_test.cc index 9c0e248e4ad..8cb15cc7e3f 100644 --- a/chromium/third_party/nearby/src/cpp/platform/public/ble_test.cc +++ b/chromium/third_party/nearby/src/cpp/platform/public/ble_test.cc @@ -65,6 +65,7 @@ TEST_P(BleMediumTest, CanStartAcceptingConnectionsAndConnect) { std::string fast_advertisement_service_uuid(kFastAdvertisementServiceUuid); CountDownLatch found_latch(1); CountDownLatch accepted_latch(1); + CancellationFlag flag; BlePeripheral* discovered_peripheral = nullptr; ble_a.StartScanning( @@ -102,8 +103,7 @@ TEST_P(BleMediumTest, CanStartAcceptingConnectionsAndConnect) { { SingleThreadExecutor client_executor; client_executor.Execute( - [&ble_a, &socket_a, discovered_peripheral, &service_id]() { - CancellationFlag flag; + [&ble_a, &socket_a, discovered_peripheral, &service_id, &flag]() { socket_a = ble_a.Connect(*discovered_peripheral, service_id, &flag); }); } @@ -127,6 +127,7 @@ TEST_P(BleMediumTest, CanCancelConnect) { std::string fast_advertisement_service_uuid(kFastAdvertisementServiceUuid); CountDownLatch found_latch(1); CountDownLatch accepted_latch(1); + CancellationFlag flag(true); BlePeripheral* discovered_peripheral = nullptr; ble_a.StartScanning( @@ -164,8 +165,7 @@ TEST_P(BleMediumTest, CanCancelConnect) { { SingleThreadExecutor client_executor; client_executor.Execute( - [&ble_a, &socket_a, discovered_peripheral, &service_id]() { - CancellationFlag flag(true); + [&ble_a, &socket_a, discovered_peripheral, &service_id, &flag]() { socket_a = ble_a.Connect(*discovered_peripheral, service_id, &flag); }); } diff --git a/chromium/third_party/nearby/src/cpp/platform/public/bluetooth_classic.h b/chromium/third_party/nearby/src/cpp/platform/public/bluetooth_classic.h index 387437521b1..62a2ec12825 100644 --- a/chromium/third_party/nearby/src/cpp/platform/public/bluetooth_classic.h +++ b/chromium/third_party/nearby/src/cpp/platform/public/bluetooth_classic.h @@ -27,6 +27,7 @@ #include "platform/base/listeners.h" #include "platform/base/output_stream.h" #include "platform/public/bluetooth_adapter.h" +#include "platform/public/logging.h" #include "platform/public/mutex.h" #include "absl/container/flat_hash_map.h" @@ -101,12 +102,21 @@ class BluetoothServerSocket final { // On success, returns connected socket, ready to exchange data. // Returns nullptr on error. // Once error is reported, it is permanent, and ServerSocket has to be closed. - BluetoothSocket Accept() { return BluetoothSocket(impl_->Accept()); } + BluetoothSocket Accept() { + auto socket = impl_->Accept(); + if (!socket) { + NEARBY_LOGS(INFO) << "Accept() failed on server socket: " << this; + } + return BluetoothSocket(std::move(socket)); + } // https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#close() // // Returns Exception::kIo on error, Exception::kSuccess otherwise. - Exception Close() { return impl_->Close(); } + Exception Close() { + NEARBY_LOGS(INFO) << "Closing server socket: " << this; + return impl_->Close(); + } bool IsValid() const { return impl_ != nullptr; } api::BluetoothServerSocket& GetImpl() { return *impl_; } diff --git a/chromium/third_party/nearby/src/cpp/platform/public/bluetooth_classic_test.cc b/chromium/third_party/nearby/src/cpp/platform/public/bluetooth_classic_test.cc index 83f5bad4e7c..2f852052753 100644 --- a/chromium/third_party/nearby/src/cpp/platform/public/bluetooth_classic_test.cc +++ b/chromium/third_party/nearby/src/cpp/platform/public/bluetooth_classic_test.cc @@ -108,15 +108,15 @@ TEST_P(BluetoothClassicMediumTest, CanConnectToService) { EXPECT_FALSE(socket_a.IsValid()); EXPECT_FALSE(socket_b.IsValid()); { + CancellationFlag flag; SingleThreadExecutor server_executor; SingleThreadExecutor client_executor; - client_executor.Execute( - [this, &socket_a, discovered_device, &service_uuid, &server_socket]() { - CancellationFlag flag; - socket_a = - bt_a_->ConnectToService(*discovered_device, service_uuid, &flag); - if (!socket_a.IsValid()) server_socket.Close(); - }); + client_executor.Execute([this, &socket_a, discovered_device, &service_uuid, + &server_socket, &flag]() { + socket_a = + bt_a_->ConnectToService(*discovered_device, service_uuid, &flag); + if (!socket_a.IsValid()) server_socket.Close(); + }); server_executor.Execute([&socket_b, &server_socket]() { socket_b = server_socket.Accept(); if (!socket_b.IsValid()) server_socket.Close(); @@ -157,15 +157,15 @@ TEST_P(BluetoothClassicMediumTest, CanCancelConnect) { EXPECT_FALSE(socket_a.IsValid()); EXPECT_FALSE(socket_b.IsValid()); { + CancellationFlag flag(true); SingleThreadExecutor server_executor; SingleThreadExecutor client_executor; - client_executor.Execute( - [this, &socket_a, discovered_device, &service_uuid, &server_socket]() { - CancellationFlag flag(true); - socket_a = - bt_a_->ConnectToService(*discovered_device, service_uuid, &flag); - if (!socket_a.IsValid()) server_socket.Close(); - }); + client_executor.Execute([this, &socket_a, discovered_device, &service_uuid, + &server_socket, &flag]() { + socket_a = + bt_a_->ConnectToService(*discovered_device, service_uuid, &flag); + if (!socket_a.IsValid()) server_socket.Close(); + }); server_executor.Execute([&socket_b, &server_socket]() { socket_b = server_socket.Accept(); if (!socket_b.IsValid()) server_socket.Close(); diff --git a/chromium/third_party/nearby/src/cpp/platform/public/count_down_latch_test.cc b/chromium/third_party/nearby/src/cpp/platform/public/count_down_latch_test.cc index d8699973547..1485070db58 100644 --- a/chromium/third_party/nearby/src/cpp/platform/public/count_down_latch_test.cc +++ b/chromium/third_party/nearby/src/cpp/platform/public/count_down_latch_test.cc @@ -57,6 +57,14 @@ TEST(CountDownLatch, LatchAwaitWithTimeoutCanExpire) { EXPECT_FALSE(response.result()); } +TEST(CountDownLatch, InitialCountZero_AwaitDoesNotBlock) { + CountDownLatch latch(0); + + auto response = latch.Await(); + + EXPECT_TRUE(response.Ok()); +} + } // namespace } // namespace nearby } // namespace location diff --git a/chromium/third_party/nearby/src/cpp/platform/public/monitored_runnable.cc b/chromium/third_party/nearby/src/cpp/platform/public/monitored_runnable.cc new file mode 100644 index 00000000000..7478f70e8f6 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/public/monitored_runnable.cc @@ -0,0 +1,59 @@ +// 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 "platform/public/monitored_runnable.h" + +#include "platform/public/logging.h" +#include "platform/public/pending_job_registry.h" + +namespace location { +namespace nearby { + +namespace { +absl::Duration kMinReportedStartDelay = absl::Seconds(5); +absl::Duration kMinReportedTaskDuration = absl::Seconds(10); +} // namespace + +MonitoredRunnable::MonitoredRunnable(Runnable&& runnable) + : runnable_{runnable} {} + +MonitoredRunnable::MonitoredRunnable(const std::string& name, + Runnable&& runnable) + : name_{name}, runnable_{runnable} { + PendingJobRegistry::GetInstance().AddPendingJob(name_, post_time_); +} + +MonitoredRunnable::~MonitoredRunnable() = default; + +void MonitoredRunnable::operator()() const { + auto start_time = SystemClock::ElapsedRealtime(); + auto start_delay = start_time - post_time_; + if (start_delay >= kMinReportedStartDelay) { + NEARBY_LOGS(INFO) << "Task: \"" << name_ << "\" started after " + << absl::ToInt64Seconds(start_delay) << " seconds"; + } + PendingJobRegistry::GetInstance().RemovePendingJob(name_, post_time_); + PendingJobRegistry::GetInstance().AddRunningJob(name_, post_time_); + runnable_(); + auto task_duration = SystemClock::ElapsedRealtime() - start_time; + if (task_duration >= kMinReportedTaskDuration) { + NEARBY_LOGS(INFO) << "Task: \"" << name_ << "\" finished after " + << absl::ToInt64Seconds(task_duration) << " seconds"; + } + PendingJobRegistry::GetInstance().RemoveRunningJob(name_, post_time_); + PendingJobRegistry::GetInstance().ListJobs(); +} + +} // namespace nearby +} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/platform/public/monitored_runnable.h b/chromium/third_party/nearby/src/cpp/platform/public/monitored_runnable.h new file mode 100644 index 00000000000..b7630b62585 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/public/monitored_runnable.h @@ -0,0 +1,48 @@ +// 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 PLATFORM_PUBLIC_MONITORED_RUNNABLE_H_ +#define PLATFORM_PUBLIC_MONITORED_RUNNABLE_H_ + +#include <string> + +#include "platform/base/runnable.h" +#include "platform/public/system_clock.h" +#include "absl/time/time.h" + +namespace location { +namespace nearby { + +// A runnable with extra logging +// We log if the task has been waiting long on the executor or if it was running +// for a long time. The latter isn't always an issue - some tasks are expected +// to run for longer periods of time (minutes). +class MonitoredRunnable { + public: + explicit MonitoredRunnable(Runnable&& runnable); + MonitoredRunnable(const std::string& name, Runnable&& runnable); + ~MonitoredRunnable(); + + void operator()() const; + + private: + const std::string name_; + Runnable runnable_; + absl::Time post_time_ = SystemClock::ElapsedRealtime(); +}; + +} // namespace nearby +} // namespace location + +#endif // PLATFORM_PUBLIC_MONITORED_RUNNABLE_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/public/pending_job_registry.cc b/chromium/third_party/nearby/src/cpp/platform/public/pending_job_registry.cc new file mode 100644 index 00000000000..e4858e4fa60 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/public/pending_job_registry.cc @@ -0,0 +1,92 @@ +// 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 "platform/public/pending_job_registry.h" + +#include "platform/public/logging.h" +#include "platform/public/mutex_lock.h" +#include "platform/public/system_clock.h" + +namespace location { +namespace nearby { + +namespace { +absl::Duration kMinReportInterval = absl::Seconds(60); +absl::Duration kReportPendingJobsOlderThan = absl::Seconds(40); +absl::Duration kReportRunningJobsOlderThan = absl::Seconds(60); +} // namespace + +PendingJobRegistry& PendingJobRegistry::GetInstance() { + static PendingJobRegistry* instance = new PendingJobRegistry(); + return *instance; +} + +PendingJobRegistry::PendingJobRegistry() = default; + +PendingJobRegistry::~PendingJobRegistry() = default; + +void PendingJobRegistry::AddPendingJob(const std::string& name, + absl::Time post_time) { + MutexLock lock(&mutex_); + pending_jobs_.emplace(CreateKey(name, post_time), post_time); +} + +void PendingJobRegistry::RemovePendingJob(const std::string& name, + absl::Time post_time) { + MutexLock lock(&mutex_); + pending_jobs_.erase(CreateKey(name, post_time)); +} + +void PendingJobRegistry::AddRunningJob(const std::string& name, + absl::Time post_time) { + MutexLock lock(&mutex_); + running_jobs_.emplace(CreateKey(name, post_time), + SystemClock::ElapsedRealtime()); +} + +void PendingJobRegistry::RemoveRunningJob(const std::string& name, + absl::Time post_time) { + MutexLock lock(&mutex_); + running_jobs_.erase(CreateKey(name, post_time)); +} + +void PendingJobRegistry::ListJobs() { + auto current_time = SystemClock::ElapsedRealtime(); + MutexLock lock(&mutex_); + if (current_time - list_jobs_time_ < kMinReportInterval) + return; + for (auto& job : pending_jobs_) { + auto age = current_time - job.second; + if (age >= kReportPendingJobsOlderThan) { + NEARBY_LOGS(INFO) << "Task \"" << job.first << "\" is waiting for " + << absl::ToInt64Seconds(age) << " s"; + } + } + for (auto& job : running_jobs_) { + auto age = current_time - job.second; + if (age >= kReportRunningJobsOlderThan) { + NEARBY_LOGS(INFO) << "Task \"" << job.first << "\" is running for " + << absl::ToInt64Seconds(age) << " s"; + } + } + list_jobs_time_ = current_time; +} + +std::string PendingJobRegistry::CreateKey(const std::string& name, + absl::Time post_time) { + return name + "." + std::to_string(absl::ToUnixNanos(post_time)); +} + +} // namespace nearby +} // namespace location diff --git a/chromium/third_party/nearby/src/cpp/platform/public/pending_job_registry.h b/chromium/third_party/nearby/src/cpp/platform/public/pending_job_registry.h new file mode 100644 index 00000000000..8b251cb7ff5 --- /dev/null +++ b/chromium/third_party/nearby/src/cpp/platform/public/pending_job_registry.h @@ -0,0 +1,55 @@ +// 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 PLATFORM_PUBLIC_PENDING_JOB_REGISTRY_H_ +#define PLATFORM_PUBLIC_PENDING_JOB_REGISTRY_H_ + +#include "platform/public/mutex.h" +#include "absl/base/thread_annotations.h" +#include "absl/time/time.h" + +namespace location { +namespace nearby { + +// A global registry of running tasks. The goal is to help us monitor +// tasks that are either waiting too long for their turn or they never finish +class PendingJobRegistry { + public: + static PendingJobRegistry& GetInstance(); + + ~PendingJobRegistry(); + + void AddPendingJob(const std::string& name, absl::Time post_time); + void RemovePendingJob(const std::string& name, absl::Time post_time); + void AddRunningJob(const std::string& name, absl::Time post_time); + void RemoveRunningJob(const std::string& name, absl::Time post_time); + void ListJobs(); + + private: + PendingJobRegistry(); + + std::string CreateKey(const std::string& name, absl::Time post_time); + + Mutex mutex_; + absl::flat_hash_map<const std::string, absl::Time> pending_jobs_ + ABSL_GUARDED_BY(mutex_); + absl::flat_hash_map<const std::string, absl::Time> running_jobs_ + ABSL_GUARDED_BY(mutex_); + absl::Time list_jobs_time_ ABSL_GUARDED_BY(mutex_) = absl::UnixEpoch(); +}; + +} // namespace nearby +} // namespace location + +#endif // PLATFORM_PUBLIC_PENDING_JOB_REGISTRY_H_ diff --git a/chromium/third_party/nearby/src/cpp/platform/public/scheduled_executor.h b/chromium/third_party/nearby/src/cpp/platform/public/scheduled_executor.h index bd603887fee..26dc255382b 100644 --- a/chromium/third_party/nearby/src/cpp/platform/public/scheduled_executor.h +++ b/chromium/third_party/nearby/src/cpp/platform/public/scheduled_executor.h @@ -25,6 +25,7 @@ #include "platform/public/cancelable.h" #include "platform/public/cancellable_task.h" #include "platform/public/lockable.h" +#include "platform/public/monitored_runnable.h" #include "platform/public/mutex.h" #include "platform/public/mutex_lock.h" #include "platform/public/thread_check_callable.h" @@ -59,6 +60,14 @@ class ABSL_LOCKABLE ScheduledExecutor final : public Lockable { } return *this; } + void Execute(const std::string& name, Runnable&& runnable) + ABSL_LOCKS_EXCLUDED(mutex_) { + MutexLock lock(&mutex_); + if (impl_) + impl_->Execute(MonitoredRunnable( + name, ThreadCheckRunnable(this, std::move(runnable)))); + } + void Execute(Runnable&& runnable) ABSL_LOCKS_EXCLUDED(mutex_) { MutexLock lock(&mutex_); if (impl_) impl_->Execute(ThreadCheckRunnable(this, std::move(runnable))); diff --git a/chromium/third_party/nearby/src/cpp/platform/public/single_thread_executor_test.cc b/chromium/third_party/nearby/src/cpp/platform/public/single_thread_executor_test.cc index f89773f365d..e2059eded11 100644 --- a/chromium/third_party/nearby/src/cpp/platform/public/single_thread_executor_test.cc +++ b/chromium/third_party/nearby/src/cpp/platform/public/single_thread_executor_test.cc @@ -16,6 +16,7 @@ #include <atomic> #include <functional> +#include <string> #include "platform/base/exception.h" #include "gtest/gtest.h" @@ -47,6 +48,24 @@ TEST(SingleThreadExecutorTest, CanExecute) { EXPECT_TRUE(done); } +TEST(SingleThreadExecutorTest, CanExecuteNamedTask) { + absl::CondVar cond; + std::atomic_bool done = false; + SingleThreadExecutor executor; + executor.Execute("my task", [&done, &cond]() { + done = true; + cond.SignalAll(); + }); + absl::Mutex mutex; + { + absl::MutexLock lock(&mutex); + if (!done) { + cond.WaitWithTimeout(&mutex, absl::Seconds(1)); + } + } + EXPECT_TRUE(done); +} + TEST(SingleThreadExecutorTest, JobsExecuteInOrder) { std::vector<int> results; SingleThreadExecutor executor; diff --git a/chromium/third_party/nearby/src/cpp/platform/public/submittable_executor.h b/chromium/third_party/nearby/src/cpp/platform/public/submittable_executor.h index c5c6f3ab886..8e4e073154f 100644 --- a/chromium/third_party/nearby/src/cpp/platform/public/submittable_executor.h +++ b/chromium/third_party/nearby/src/cpp/platform/public/submittable_executor.h @@ -26,6 +26,7 @@ #include "platform/base/runnable.h" #include "platform/public/future.h" #include "platform/public/lockable.h" +#include "platform/public/monitored_runnable.h" #include "platform/public/mutex.h" #include "platform/public/mutex_lock.h" #include "platform/public/thread_check_callable.h" @@ -57,9 +58,19 @@ class ABSL_LOCKABLE SubmittableExecutor : public api::SubmittableExecutor, } return *this; } + void Execute(const std::string& name, Runnable&& runnable) + ABSL_LOCKS_EXCLUDED(mutex_) { + MutexLock lock(&mutex_); + if (impl_) + impl_->Execute(MonitoredRunnable( + name, ThreadCheckRunnable(this, std::move(runnable)))); + } + void Execute(Runnable&& runnable) ABSL_LOCKS_EXCLUDED(mutex_) override { MutexLock lock(&mutex_); - if (impl_) impl_->Execute(ThreadCheckRunnable(this, std::move(runnable))); + if (impl_) + impl_->Execute( + MonitoredRunnable(ThreadCheckRunnable(this, std::move(runnable)))); } int GetTid(int index) const ABSL_LOCKS_EXCLUDED(mutex_) override { diff --git a/chromium/third_party/nearby/src/cpp/platform/public/wifi_lan_test.cc b/chromium/third_party/nearby/src/cpp/platform/public/wifi_lan_test.cc index f3992771b0b..17985109bcb 100644 --- a/chromium/third_party/nearby/src/cpp/platform/public/wifi_lan_test.cc +++ b/chromium/third_party/nearby/src/cpp/platform/public/wifi_lan_test.cc @@ -64,6 +64,7 @@ TEST_P(WifiLanMediumTest, CanStartAcceptingConnectionsAndConnect) { std::string endpoint_info_name{kEndpointName}; CountDownLatch found_latch(1); CountDownLatch accepted_latch(1); + CancellationFlag flag; WifiLanService* discovered_service = nullptr; wifi_a.StartDiscovery( @@ -102,8 +103,7 @@ TEST_P(WifiLanMediumTest, CanStartAcceptingConnectionsAndConnect) { { SingleThreadExecutor client_executor; client_executor.Execute( - [&wifi_a, &socket_a, discovered_service, &service_id]() { - CancellationFlag flag; + [&wifi_a, &socket_a, discovered_service, &service_id, &flag]() { socket_a = wifi_a.Connect(*discovered_service, service_id, &flag); }); } @@ -126,6 +126,7 @@ TEST_P(WifiLanMediumTest, CanCancelConnect) { std::string endpoint_info_name{kEndpointName}; CountDownLatch found_latch(1); CountDownLatch accepted_latch(1); + CancellationFlag flag(true); WifiLanService* discovered_service = nullptr; wifi_a.StartDiscovery( @@ -164,9 +165,7 @@ TEST_P(WifiLanMediumTest, CanCancelConnect) { { SingleThreadExecutor client_executor; client_executor.Execute( - [&wifi_a, &socket_a, discovered_service, &service_id]() { - // Make it as Cancelled. - CancellationFlag flag(true); + [&wifi_a, &socket_a, discovered_service, &service_id, &flag]() { socket_a = wifi_a.Connect(*discovered_service, service_id, &flag); }); } diff --git a/chromium/third_party/nearby/src/proto/BUILD b/chromium/third_party/nearby/src/proto/BUILD index 880147c8b93..6c7f2ff29b3 100644 --- a/chromium/third_party/nearby/src/proto/BUILD +++ b/chromium/third_party/nearby/src/proto/BUILD @@ -204,3 +204,23 @@ go_proto_library( name = "nearby_event_codes_go_proto", deps = [":nearby_event_codes_proto"], ) + +proto_library( + name = "uwb_enums_proto", + srcs = ["uwb_enums.proto"], + cc_api_version = 2, + compatible_with = ["//buildenv/target:appengine"], + deps = [ + "//logs/proto/logs_annotations", + ], +) + +java_lite_proto_library( + name = "uwb_enums_java_proto_lite", + deps = [":uwb_enums_proto"], +) + +java_proto_library( + name = "uwb_enums_java_proto", + deps = [":uwb_enums_proto"], +) diff --git a/chromium/third_party/nearby/src/proto/connections/offline_wire_formats.proto b/chromium/third_party/nearby/src/proto/connections/offline_wire_formats.proto index 5e582539118..ed7ce124363 100644 --- a/chromium/third_party/nearby/src/proto/connections/offline_wire_formats.proto +++ b/chromium/third_party/nearby/src/proto/connections/offline_wire_formats.proto @@ -84,6 +84,8 @@ message ConnectionRequestFrame { repeated Medium mediums = 5; optional bytes endpoint_info = 6; optional MediumMetadata medium_metadata = 7; + optional int32 keep_alive_interval_millis = 8; + optional int32 keep_alive_timeout_millis = 9; } message ConnectionResponseFrame { diff --git a/chromium/third_party/nearby/src/proto/connections_enums.proto b/chromium/third_party/nearby/src/proto/connections_enums.proto index 4674a4cf20e..b1f8096c8fc 100644 --- a/chromium/third_party/nearby/src/proto/connections_enums.proto +++ b/chromium/third_party/nearby/src/proto/connections_enums.proto @@ -67,9 +67,10 @@ enum SessionRole { DISCOVERER = 2; } +// LINT.IfChange enum Medium { UNKNOWN_MEDIUM = 0; - MDNS = 1; + MDNS = 1 [deprecated = true]; BLUETOOTH = 2; WIFI_HOTSPOT = 3; BLE = 4; @@ -79,6 +80,7 @@ enum Medium { WIFI_DIRECT = 8; WEB_RTC = 9; } +// LINT.ThenChange(//depot/google3/java/com/google/android/gmscore/integ/client/nearby/src/com/google/android/gms/nearby/connection/Medium.java) // The result of a ConnectionRequest. enum ConnectionRequestResponse { diff --git a/chromium/third_party/nearby/src/proto/discovery_enums.proto b/chromium/third_party/nearby/src/proto/discovery_enums.proto index 19901df44d6..40596e6ded3 100644 --- a/chromium/third_party/nearby/src/proto/discovery_enums.proto +++ b/chromium/third_party/nearby/src/proto/discovery_enums.proto @@ -21,7 +21,7 @@ option optimize_for = LITE_RUNTIME; option java_package = "com.google.location.nearby.proto"; option java_outer_classname = "DiscoveryEnums"; -// NEXT ID: 148 +// NEXT ID: 149 enum DiscoveryEvent { UNKNOWN_DISCOVERY_EVENT = 0; @@ -456,6 +456,9 @@ enum DiscoveryEvent { // time HALF_SHEET_CONNECTION_AFTER_BAN = 147; + // User has clicked the companion header slice from device settings. + FAST_PAIR_DEVICE_COMPANION_HEADER_CLICKED = 148; + // Deprecated. reserved 65, 67 to 72; } diff --git a/chromium/third_party/nearby/src/proto/magic_pair_enums.proto b/chromium/third_party/nearby/src/proto/magic_pair_enums.proto index a0633f9be38..b6c35115e07 100644 --- a/chromium/third_party/nearby/src/proto/magic_pair_enums.proto +++ b/chromium/third_party/nearby/src/proto/magic_pair_enums.proto @@ -70,6 +70,8 @@ message MagicPairEvent { UNKNOWN_BOND_ERROR_CODE = 0; BOND_BROKEN = 1; POSSIBLE_MITM = 2; + NO_PERMISSION = 3; + INCORRECT_VARIANT = 4; } enum ConnectErrorCode { diff --git a/chromium/third_party/nearby/src/proto/nearby_event_codes.proto b/chromium/third_party/nearby/src/proto/nearby_event_codes.proto index 7d0939e046b..092fea71cc6 100644 --- a/chromium/third_party/nearby/src/proto/nearby_event_codes.proto +++ b/chromium/third_party/nearby/src/proto/nearby_event_codes.proto @@ -66,5 +66,10 @@ message NearbyEvent { BISTO_PAIR_END = 1340; REMOTE_PAIR_START = 1350; REMOTE_PAIR_END = 1360; + BEFORE_CREATE_BOND = 1370; + BEFORE_CREATE_BOND_BONDING = 1380; + BEFORE_CREATE_BOND_BONDED = 1390; + BEFORE_CONNECT_PROFILE = 1400; + HANDLE_PAIRING_REQUEST = 1410; } } diff --git a/chromium/third_party/nearby/src/proto/sharing_enums.proto b/chromium/third_party/nearby/src/proto/sharing_enums.proto index b43a82bcdc2..f6803167bdd 100644 --- a/chromium/third_party/nearby/src/proto/sharing_enums.proto +++ b/chromium/third_party/nearby/src/proto/sharing_enums.proto @@ -160,6 +160,9 @@ enum EventType { // Receiver verification of APKs status. VERIFY_APK = 41; + + // User starts a consent. + LAUNCH_CONSENT = 42; } // Event category to differentiate whether this comes from sender or receiver, @@ -340,6 +343,12 @@ enum ActivityName { CONSENTS_ACTIVITY = 6; } +enum ConsentType { + CONSENT_TYPE_UNKNOWN = 0; + + CONSENT_TYPE_C11N = 1; +} + enum ApkSource { UNKNOWN_APK_SOURCE = 0; diff --git a/chromium/third_party/nearby/src/proto/uwb_enums.proto b/chromium/third_party/nearby/src/proto/uwb_enums.proto new file mode 100644 index 00000000000..9af4d221d30 --- /dev/null +++ b/chromium/third_party/nearby/src/proto/uwb_enums.proto @@ -0,0 +1,41 @@ +// 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. + +syntax = "proto2"; + +package location.nearby.proto.uwb; + + +option optimize_for = LITE_RUNTIME; +option java_package = "com.google.location.nearby.proto"; +option java_outer_classname = "UwbEnums"; +option objc_class_prefix = "GNUP"; + +// The role which the device takes during UWB ranging. +// LINT.IfChange() +enum RangingRole { + ROLE_UNKNOWN = 0; + ROLE_CONTROLLER = 1; + ROLE_CONTROLLEE = 2; +} +// LINT.ThenChange(//depot/google3/java/com/google/android/gmscore/integ/client/nearby/src/com/google/android/gms/nearby/uwb/UwbOptions.java) + +// The type how a UWB session should be created. +// LINT.IfChange() +enum SessionType { + TYPE_UNKNOWN = 0; + TYPE_UNICAST = 1; + TYPE_MULTICAST = 2; +} +// LINT.ThenChange(//depot/google3/java/com/google/android/gmscore/integ/client/nearby/src/com/google/android/gms/nearby/uwb/UwbOptions.java) |