From b0568ecc267de488475e3cb49d22c322d624eae6 Mon Sep 17 00:00:00 2001 From: Anay Wadhera Date: Fri, 2 Jun 2023 21:05:39 -0700 Subject: [PATCH] Update ServiceControllerRouter for v3 API entrypoint PiperOrigin-RevId: 537478014 --- connections/implementation/BUILD | 1 + .../implementation/mock_service_controller.h | 20 + .../mock_service_controller_router.h | 43 ++ .../offline_service_controller.cc | 13 + .../offline_service_controller.h | 21 + .../implementation/service_controller.h | 17 + .../service_controller_router.cc | 303 +++++++++++++ .../service_controller_router.h | 61 +++ .../service_controller_router_test.cc | 422 +++++++++++++++++- connections/v3/BUILD | 1 + connections/v3/listeners.h | 11 +- connections/v3/params.h | 44 ++ 12 files changed, 945 insertions(+), 12 deletions(-) create mode 100644 connections/v3/params.h diff --git a/connections/implementation/BUILD b/connections/implementation/BUILD index 0e93ee0a..07df4e82 100644 --- a/connections/implementation/BUILD +++ b/connections/implementation/BUILD @@ -176,6 +176,7 @@ cc_library( deps = [ ":internal", "//connections:core_types", + "//connections/v3:v3_types", "//internal/platform:base", "//internal/platform:test_util", "//internal/platform:types", diff --git a/connections/implementation/mock_service_controller.h b/connections/implementation/mock_service_controller.h index f036963b..2f84d6ae 100644 --- a/connections/implementation/mock_service_controller.h +++ b/connections/implementation/mock_service_controller.h @@ -17,6 +17,7 @@ #include "gmock/gmock.h" #include "connections/implementation/service_controller.h" +#include "connections/v3/connection_listening_options.h" namespace nearby { namespace connections { @@ -52,6 +53,15 @@ class MockServiceController : public ServiceController { const OutOfBandConnectionMetadata& metadata), (override)); + MOCK_METHOD(Status, StartListeningForIncomingConnections, + (ClientProxy * client, absl::string_view service_id, + v3::ConnectionListener listener, + const v3::ConnectionListeningOptions& options), + (override)); + + MOCK_METHOD(void, StopListeningForIncomingConnections, (ClientProxy * client), + (override)); + MOCK_METHOD(Status, RequestConnection, (ClientProxy * client, const std::string& endpoint_id, const ConnectionRequestInfo& info, @@ -83,6 +93,16 @@ class MockServiceController : public ServiceController { (ClientProxy * client, const std::string& endpoint_id), (override)); + MOCK_METHOD(Status, UpdateAdvertisingOptions, + (ClientProxy * client, absl::string_view service_id, + const AdvertisingOptions& advertising_options), + (override)); + + MOCK_METHOD(Status, UpdateDiscoveryOptions, + (ClientProxy * client, absl::string_view service_id, + const DiscoveryOptions& advertising_options), + (override)); + MOCK_METHOD(void, ShutdownBwuManagerExecutors, (), (override)); MOCK_METHOD(void, SetCustomSavePath, diff --git a/connections/implementation/mock_service_controller_router.h b/connections/implementation/mock_service_controller_router.h index d6ef9958..9133fd1a 100644 --- a/connections/implementation/mock_service_controller_router.h +++ b/connections/implementation/mock_service_controller_router.h @@ -96,6 +96,49 @@ class MockServiceControllerRouter : public ServiceControllerRouter { (ClientProxy * client, absl::string_view path, const ResultCallback& callback), (override)); + + MOCK_METHOD(void, RequestConnectionV3, + (ClientProxy * client, const NearbyDevice&, + v3::ConnectionRequestInfo, const ConnectionOptions&, + const ResultCallback& callback), + (override)); + + MOCK_METHOD(void, AcceptConnectionV3, + (ClientProxy * client, const NearbyDevice&, v3::PayloadListener, + const ResultCallback& callback), + (override)); + + MOCK_METHOD(void, RejectConnectionV3, + (ClientProxy * client, const NearbyDevice&, + const ResultCallback& callback), + (override)); + + MOCK_METHOD(void, InitiateBandwidthUpgradeV3, + (ClientProxy * client, const NearbyDevice&, + const ResultCallback& callback), + (override)); + + MOCK_METHOD(void, SendPayloadV3, + (ClientProxy * client, const NearbyDevice&, Payload, + const ResultCallback& callback), + (override)); + + MOCK_METHOD(void, DisconnectFromDeviceV3, + (ClientProxy * client, const NearbyDevice&, + const ResultCallback& callback), + (override)); + + MOCK_METHOD(void, UpdateAdvertisingOptionsV3, + (ClientProxy * client, absl::string_view service_id, + const AdvertisingOptions& advertising_options, + const ResultCallback& callback), + (override)); + + MOCK_METHOD(void, UpdateDiscoveryOptionsV3, + (ClientProxy * client, absl::string_view service_id, + const DiscoveryOptions& discovery_options, + const ResultCallback& callback), + (override)); }; } // namespace connections diff --git a/connections/implementation/offline_service_controller.cc b/connections/implementation/offline_service_controller.cc index db04282a..53fd55da 100644 --- a/connections/implementation/offline_service_controller.cc +++ b/connections/implementation/offline_service_controller.cc @@ -144,6 +144,19 @@ void OfflineServiceController::DisconnectFromEndpoint( endpoint_manager_.UnregisterEndpoint(client, endpoint_id); } +Status OfflineServiceController::UpdateAdvertisingOptions( + ClientProxy* client, absl::string_view service_id, + const AdvertisingOptions& advertising_options) { + // TODO(b/284048592): Implement. + return {Status::kError}; +} + +Status OfflineServiceController::UpdateDiscoveryOptions( + ClientProxy* client, absl::string_view service_id, + const DiscoveryOptions& discovery_options) { + // TODO(b/284048592): Implement. + return {Status::kError}; +} void OfflineServiceController::SetCustomSavePath(ClientProxy* client, const std::string& path) { if (stop_) return; diff --git a/connections/implementation/offline_service_controller.h b/connections/implementation/offline_service_controller.h index ccd71d62..d245a8b8 100644 --- a/connections/implementation/offline_service_controller.h +++ b/connections/implementation/offline_service_controller.h @@ -31,6 +31,7 @@ #include "connections/listeners.h" #include "connections/payload.h" #include "connections/status.h" +#include "connections/v3/connection_listening_options.h" namespace nearby { namespace connections { @@ -54,6 +55,18 @@ class OfflineServiceController : public ServiceController { void InjectEndpoint(ClientProxy* client, const std::string& service_id, const OutOfBandConnectionMetadata& metadata) override; + Status StartListeningForIncomingConnections( + ClientProxy* client, absl::string_view service_id, + v3::ConnectionListener listener, + const v3::ConnectionListeningOptions& options) override { + // TODO(b/283823898): Implement. + return Status{.value = Status::kError}; + } + + void StopListeningForIncomingConnections(ClientProxy* client) override { + // TODO(b/283823898): Implement. + } + Status RequestConnection( ClientProxy* client, const std::string& endpoint_id, const ConnectionRequestInfo& info, @@ -74,6 +87,14 @@ class OfflineServiceController : public ServiceController { void DisconnectFromEndpoint(ClientProxy* client, const std::string& endpoint_id) override; + Status UpdateAdvertisingOptions( + ClientProxy* client, absl::string_view service_id, + const AdvertisingOptions& advertising_options) override; + + Status UpdateDiscoveryOptions( + ClientProxy* client, absl::string_view service_id, + const DiscoveryOptions& discovery_options) override; + void Stop() override; void SetCustomSavePath(ClientProxy* client, const std::string& path) override; diff --git a/connections/implementation/service_controller.h b/connections/implementation/service_controller.h index e4e56d7e..85ffc8e2 100644 --- a/connections/implementation/service_controller.h +++ b/connections/implementation/service_controller.h @@ -26,6 +26,8 @@ #include "connections/params.h" #include "connections/payload.h" #include "connections/status.h" +#include "connections/v3/connection_listening_options.h" +#include "connections/v3/listeners.h" namespace nearby { namespace connections { @@ -77,6 +79,13 @@ class ServiceController { const std::string& service_id, const OutOfBandConnectionMetadata& metadata) = 0; + virtual Status StartListeningForIncomingConnections( + ClientProxy* client, absl::string_view service_id, + v3::ConnectionListener listener, + const v3::ConnectionListeningOptions& options) = 0; + + virtual void StopListeningForIncomingConnections(ClientProxy* client) = 0; + virtual Status RequestConnection( ClientProxy* client, const std::string& endpoint_id, const ConnectionRequestInfo& info, @@ -99,6 +108,14 @@ class ServiceController { virtual void DisconnectFromEndpoint(ClientProxy* client, const std::string& endpoint_id) = 0; + virtual Status UpdateAdvertisingOptions( + ClientProxy* client, absl::string_view service_id, + const AdvertisingOptions& advertising_options) = 0; + + virtual Status UpdateDiscoveryOptions( + ClientProxy* client, absl::string_view service_id, + const DiscoveryOptions& discovery_options) = 0; + virtual void SetCustomSavePath(ClientProxy* client, const std::string& path) = 0; }; diff --git a/connections/implementation/service_controller_router.cc b/connections/implementation/service_controller_router.cc index c02a6c78..2b6e687a 100644 --- a/connections/implementation/service_controller_router.cc +++ b/connections/implementation/service_controller_router.cc @@ -25,8 +25,12 @@ #include "connections/listeners.h" #include "connections/params.h" #include "connections/payload.h" +#include "connections/v3/bandwidth_info.h" +#include "connections/v3/connection_result.h" +#include "connections/v3/connections_device.h" #include "internal/platform/logging.h" +// TODO(b/285657711): Add tests for uncovered logic, even if trivial. namespace nearby { namespace connections { namespace { @@ -54,6 +58,28 @@ bool ClientHasConnectionToAtLeastOneEndpoint( } } // namespace +v3::Quality ServiceControllerRouter::GetMediumQuality(Medium medium) { + switch (medium) { + case location::nearby::proto::connections::USB: + case location::nearby::proto::connections::UNKNOWN_MEDIUM: + return v3::Quality::kUnknown; + case location::nearby::proto::connections::BLE: + case location::nearby::proto::connections::NFC: + return v3::Quality::kLow; + case location::nearby::proto::connections::BLUETOOTH: + case location::nearby::proto::connections::BLE_L2CAP: + return v3::Quality::kMedium; + case location::nearby::proto::connections::WIFI_HOTSPOT: + case location::nearby::proto::connections::WIFI_LAN: + case location::nearby::proto::connections::WIFI_AWARE: + case location::nearby::proto::connections::WIFI_DIRECT: + case location::nearby::proto::connections::WEB_RTC: + return v3::Quality::kHigh; + default: + return v3::Quality::kUnknown; + } +} + ServiceControllerRouter::ServiceControllerRouter() { NEARBY_LOGS(INFO) << "ServiceControllerRouter going up."; } @@ -326,6 +352,283 @@ void ServiceControllerRouter::DisconnectFromEndpoint( }); } +Status ServiceControllerRouter::StartListeningForIncomingConnectionsV3( + ClientProxy* client, absl::string_view service_id, + v3::ConnectionListener listener, v3::ConnectionListeningOptions& options) { + return GetServiceController()->StartListeningForIncomingConnections( + client, service_id, std::move(listener), options); +} + +void ServiceControllerRouter::StopListeningForIncomingConnectionsV3( + ClientProxy* client) { + GetServiceController()->StopListeningForIncomingConnections(client); +} + +void ServiceControllerRouter::RequestConnectionV3( + ClientProxy* client, const NearbyDevice& remote_device, + v3::ConnectionRequestInfo info, const ConnectionOptions& connection_options, + const ResultCallback& callback) { + // Cancellations can be fired from clients anytime, need to add the + // CancellationListener as soon as possible. + client->AddCancellationFlag(remote_device.GetEndpointId()); + + RouteToServiceController( + "scr-request-connection", + [this, client, endpoint_id = remote_device.GetEndpointId(), + v3_info = std::move(info), connection_options, callback]() mutable { + if (client->HasPendingConnectionToEndpoint(endpoint_id) || + client->IsConnectedToEndpoint(endpoint_id)) { + callback.result_cb({Status::kAlreadyConnectedToEndpoint}); + return; + } + + std::string endpoint_info; + if (v3_info.local_device.GetType() == + NearbyDevice::Type::kConnectionsDevice) { + endpoint_info = + dynamic_cast(v3_info.local_device) + .GetEndpointInfo(); + } + + ConnectionListener listener = { + .initiated_cb = + [&v3_info]( + const std::string& endpoint_id, + const ConnectionResponseInfo& response_info) mutable { + v3::InitialConnectionInfo new_info = { + .authentication_digits = + response_info.authentication_token, + .raw_authentication_token = + response_info.raw_authentication_token.string_data(), + .is_incoming_connection = + response_info.is_incoming_connection, + }; + v3::ConnectionsDevice device( + endpoint_id, + response_info.remote_endpoint_info.AsStringView(), {}); + v3_info.listener.initiated_cb(device, new_info); + }, + .accepted_cb = + [result_cb = v3_info.listener.result_cb]( + const std::string& endpoint_id) { + v3::ConnectionResult result = { + .status = {Status::kSuccess}, + }; + result_cb(v3::ConnectionsDevice(endpoint_id, "", {}), result); + }, + .rejected_cb = + [result_cb = v3_info.listener.result_cb]( + const std::string& endpoint_id, Status status) { + v3::ConnectionResult result = { + .status = status, + }; + result_cb(v3::ConnectionsDevice(endpoint_id, "", {}), result); + }, + .disconnected_cb = + [&v3_info](const std::string& endpoint_id) mutable { + auto device = v3::ConnectionsDevice(endpoint_id, "", {}); + v3_info.listener.disconnected_cb(device); + }, + .bandwidth_changed_cb = + [this, &v3_info](const std::string& endpoint_id, + Medium medium) mutable { + v3::BandwidthInfo bandwidth_info = { + .quality = GetMediumQuality(medium), + .medium = medium, + }; + v3_info.listener.bandwidth_changed_cb( + v3::ConnectionsDevice(endpoint_id, "", {}), + bandwidth_info); + }, + }; + ConnectionRequestInfo old_info = { + .endpoint_info = ByteArray(endpoint_info), + .listener = std::move(listener), + }; + Status status = GetServiceController()->RequestConnection( + client, endpoint_id, std::move(old_info), connection_options); + if (!status.Ok()) { + NEARBY_LOGS(WARNING) << "Unable to request connection to endpoint " + << endpoint_id << ": " << status.ToString(); + client->CancelEndpoint(endpoint_id); + } + callback.result_cb(status); + }); +} + +void ServiceControllerRouter::AcceptConnectionV3( + ClientProxy* client, const NearbyDevice& remote_device, + v3::PayloadListener listener, const ResultCallback& callback) { + RouteToServiceController( + "scr-accept-connection", + [this, client, endpoint_id = remote_device.GetEndpointId(), + v3_listener = std::move(listener), callback]() mutable { + if (client->IsConnectedToEndpoint(endpoint_id)) { + callback.result_cb({Status::kAlreadyConnectedToEndpoint}); + return; + } + + if (client->HasLocalEndpointResponded(endpoint_id)) { + NEARBY_LOGS(WARNING) + << "Client " << client->GetClientId() + << " invoked acceptConnectionRequest() after having already " + "accepted/rejected the connection to endpoint(id=" + << endpoint_id << ")"; + callback.result_cb({Status::kOutOfOrderApiCall}); + return; + } + + PayloadListener old_listener = { + .payload_cb = + [v3_received = std::move(v3_listener.payload_received_cb)]( + absl::string_view endpoint_id, Payload payload) { + v3_received(v3::ConnectionsDevice(endpoint_id, "", {}), + std::move(payload)); + }, + .payload_progress_cb = + [v3_cb = std::move(v3_listener.payload_progress_cb)]( + absl::string_view endpoint_id, + const PayloadProgressInfo& info) mutable { + v3_cb(v3::ConnectionsDevice(endpoint_id, "", {}), info); + }}; + + callback.result_cb(GetServiceController()->AcceptConnection( + client, endpoint_id, std::move(old_listener))); + }); +} + +void ServiceControllerRouter::RejectConnectionV3( + ClientProxy* client, const NearbyDevice& remote_device, + const ResultCallback& callback) { + client->CancelEndpoint(remote_device.GetEndpointId()); + + RouteToServiceController( + "scr-reject-connection", + [this, client, endpoint_id = remote_device.GetEndpointId(), callback]() { + if (client->IsConnectedToEndpoint(endpoint_id)) { + callback.result_cb({Status::kAlreadyConnectedToEndpoint}); + return; + } + + if (client->HasLocalEndpointResponded(endpoint_id)) { + NEARBY_LOGS(WARNING) + << "Client " << client->GetClientId() + << " invoked rejectConnectionRequest() after having already " + "accepted/rejected the connection to endpoint(id=" + << endpoint_id << ")"; + callback.result_cb({Status::kOutOfOrderApiCall}); + return; + } + + callback.result_cb( + GetServiceController()->RejectConnection(client, endpoint_id)); + }); +} + +void ServiceControllerRouter::InitiateBandwidthUpgradeV3( + ClientProxy* client, const NearbyDevice& remote_device, + const ResultCallback& callback) { + RouteToServiceController( + "scr-init-bwu", + [this, client, endpoint_id = remote_device.GetEndpointId(), callback]() { + if (!client->IsConnectedToEndpoint(endpoint_id)) { + callback.result_cb({Status::kOutOfOrderApiCall}); + return; + } + + GetServiceController()->InitiateBandwidthUpgrade(client, endpoint_id); + + // Operation is triggered; the caller can listen to + // ConnectionListener::OnBandwidthChanged() to determine its success. + callback.result_cb({Status::kSuccess}); + }); +} + +void ServiceControllerRouter::SendPayloadV3( + ClientProxy* client, const NearbyDevice& recipient_device, Payload payload, + const ResultCallback& callback) { + // Payload is a move-only type. + // We have to capture it by value inside the lambda, and pass it over to + // the executor as an std::function instance. + // Lambda must be copyable, in order ot satisfy std::function<> requirements. + // To make it so, we need Payload wrapped by a copyable wrapper. + // std::shared_ptr<> is used, because it is copyable. + auto shared_payload = std::make_shared(std::move(payload)); + + RouteToServiceController( + "scr-send-payload", + [this, client, shared_payload, + endpoint_id = recipient_device.GetEndpointId(), callback]() { + if (!client->IsConnectedToEndpoint(endpoint_id)) { + callback.result_cb({Status::kEndpointUnknown}); + return; + } + + GetServiceController()->SendPayload( + client, std::vector{endpoint_id}, + std::move(*shared_payload)); + + // At this point, we've queued up the send Payload request with the + // ServiceController; any further failures (e.g. one of the endpoints is + // unknown, goes away, or otherwise fails) will be returned to the + // client as a PayloadTransferUpdate. + callback.result_cb({Status::kSuccess}); + }); +} + +void ServiceControllerRouter::CancelPayloadV3( + ClientProxy* client, const NearbyDevice& recipient_device, + uint64_t payload_id, const ResultCallback& callback) { + RouteToServiceController( + "scr-cancel-payload", [this, client, payload_id, callback]() { + callback.result_cb( + GetServiceController()->CancelPayload(client, payload_id)); + }); +} + +void ServiceControllerRouter::DisconnectFromDeviceV3( + ClientProxy* client, const NearbyDevice& remote_device, + const ResultCallback& callback) { + // Client can emit the cancellation at anytime, we need to execute the request + // without further posting it. + client->CancelEndpoint(remote_device.GetEndpointId()); + + RouteToServiceController( + "scr-disconnect-endpoint", + [this, client, endpoint_id = remote_device.GetEndpointId(), callback]() { + if (!client->IsConnectedToEndpoint(endpoint_id) && + !client->HasPendingConnectionToEndpoint(endpoint_id)) { + callback.result_cb({Status::kOutOfOrderApiCall}); + return; + } + + GetServiceController()->DisconnectFromEndpoint(client, endpoint_id); + callback.result_cb({Status::kSuccess}); + }); +} + +void ServiceControllerRouter::UpdateAdvertisingOptionsV3( + ClientProxy* client, absl::string_view service_id, + const AdvertisingOptions& options, const ResultCallback& callback) { + RouteToServiceController( + "scr-update-advertising-options", + [this, client, options, callback, service_id]() { + callback.result_cb(GetServiceController()->UpdateAdvertisingOptions( + client, service_id, options)); + }); +} + +void ServiceControllerRouter::UpdateDiscoveryOptionsV3( + ClientProxy* client, absl::string_view service_id, + const DiscoveryOptions& options, const ResultCallback& callback) { + RouteToServiceController( + "scr-update-discovery-options", + [this, client, options, callback, service_id]() { + callback.result_cb(GetServiceController()->UpdateDiscoveryOptions( + client, service_id, options)); + }); +} + void ServiceControllerRouter::StopAllEndpoints(ClientProxy* client, const ResultCallback& callback) { // Client can emit the cancellation at anytime, we need to execute the request diff --git a/connections/implementation/service_controller_router.h b/connections/implementation/service_controller_router.h index f3ed5a51..f04d5b4a 100644 --- a/connections/implementation/service_controller_router.h +++ b/connections/implementation/service_controller_router.h @@ -25,6 +25,10 @@ #include "connections/implementation/client_proxy.h" #include "connections/implementation/service_controller.h" #include "connections/params.h" +#include "connections/v3/connection_listening_options.h" +#include "connections/v3/listeners.h" +#include "connections/v3/params.h" +#include "internal/interop/device.h" #include "internal/platform/runnable.h" #include "internal/platform/single_thread_executor.h" @@ -59,11 +63,13 @@ class ServiceControllerRouter { ServiceControllerRouter(ServiceControllerRouter&&) = delete; ServiceControllerRouter& operator=(ServiceControllerRouter&&) = delete; + virtual v3::Quality GetMediumQuality(Medium medium); virtual void StartAdvertising(ClientProxy* client, absl::string_view service_id, const AdvertisingOptions& advertising_options, const ConnectionRequestInfo& info, const ResultCallback& callback); + virtual void StopAdvertising(ClientProxy* client, const ResultCallback& callback); @@ -71,6 +77,7 @@ class ServiceControllerRouter { const DiscoveryOptions& discovery_options, const DiscoveryListener& listener, const ResultCallback& callback); + virtual void StopDiscovery(ClientProxy* client, const ResultCallback& callback); @@ -83,10 +90,12 @@ class ServiceControllerRouter { const ConnectionRequestInfo& info, const ConnectionOptions& connection_options, const ResultCallback& callback); + virtual void AcceptConnection(ClientProxy* client, absl::string_view endpoint_id, PayloadListener listener, const ResultCallback& callback); + virtual void RejectConnection(ClientProxy* client, absl::string_view endpoint_id, const ResultCallback& callback); @@ -98,12 +107,64 @@ class ServiceControllerRouter { virtual void SendPayload(ClientProxy* client, absl::Span endpoint_ids, Payload payload, const ResultCallback& callback); + virtual void CancelPayload(ClientProxy* client, std::uint64_t payload_id, const ResultCallback& callback); virtual void DisconnectFromEndpoint(ClientProxy* client, absl::string_view endpoint_id, const ResultCallback& callback); + + ////////////////////////////// V3 //////////////////////////////////////////// + virtual Status StartListeningForIncomingConnectionsV3( + ClientProxy* client, absl::string_view service_id, + v3::ConnectionListener listener, v3::ConnectionListeningOptions& options); + + virtual void StopListeningForIncomingConnectionsV3(ClientProxy* client); + + virtual void RequestConnectionV3(ClientProxy* client, + const NearbyDevice& remote_device, + v3::ConnectionRequestInfo info, + const ConnectionOptions& connection_options, + const ResultCallback& callback); + + virtual void AcceptConnectionV3(ClientProxy* client, + const NearbyDevice& remote_device, + v3::PayloadListener listener, + const ResultCallback& callback); + + virtual void RejectConnectionV3(ClientProxy* client, + const NearbyDevice& remote_device, + const ResultCallback& callback); + + virtual void InitiateBandwidthUpgradeV3(ClientProxy* client, + const NearbyDevice& remote_device, + const ResultCallback& callback); + + virtual void SendPayloadV3(ClientProxy* client, + const NearbyDevice& recipient_device, + Payload payload, const ResultCallback& callback); + + virtual void CancelPayloadV3(ClientProxy* client, + const NearbyDevice& recipient_device, + std::uint64_t payload_id, + const ResultCallback& callback); + + virtual void DisconnectFromDeviceV3(ClientProxy* client, + const NearbyDevice& remote_device, + const ResultCallback& callback); + + virtual void UpdateAdvertisingOptionsV3( + ClientProxy* client, absl::string_view service_id, + const AdvertisingOptions& advertising_options, + const ResultCallback& callback); + + virtual void UpdateDiscoveryOptionsV3( + ClientProxy* client, absl::string_view service_id, + const DiscoveryOptions& discovery_options, + const ResultCallback& callback); + /////////////////////////////// END V3 /////////////////////////////////////// + virtual void StopAllEndpoints(ClientProxy* client, const ResultCallback& callback); diff --git a/connections/implementation/service_controller_router_test.cc b/connections/implementation/service_controller_router_test.cc index b0dc0573..4b770ef0 100644 --- a/connections/implementation/service_controller_router_test.cc +++ b/connections/implementation/service_controller_router_test.cc @@ -24,16 +24,18 @@ #include "gmock/gmock.h" #include "protobuf-matchers/protocol-buffer-matchers.h" #include "gtest/gtest.h" -#include "absl/container/flat_hash_set.h" -#include "absl/time/clock.h" #include "absl/types/span.h" #include "connections/implementation/client_proxy.h" #include "connections/implementation/mock_service_controller.h" -#include "connections/implementation/service_controller.h" #include "connections/listeners.h" #include "connections/params.h" +#include "connections/v3/bandwidth_info.h" +#include "connections/v3/connection_result.h" +#include "connections/v3/connections_device.h" +#include "connections/v3/params.h" #include "internal/platform/byte_array.h" #include "internal/platform/condition_variable.h" +#include "internal/platform/count_down_latch.h" #include "internal/platform/mutex.h" #include "internal/platform/mutex_lock.h" @@ -47,6 +49,16 @@ constexpr std::array kFakeInjectedEndpointInfo = {'g', 'h', 'i'}; const char kFakeInejctedEndpointId[] = "abcd"; } // namespace +class FakeNearbyDevice : public NearbyDevice { + public: + NearbyDevice::Type GetType() const override { + return NearbyDevice::Type::kUnknownDevice; + } + MOCK_METHOD(std::string, GetEndpointId, (), (const override)); + MOCK_METHOD(std::vector, GetConnectionInfos, (), + (const override)); +}; + // This class must be in the same namespace as ServiceControllerRouter for // friend class to work. class ServiceControllerRouterTest : public testing::Test { @@ -258,6 +270,159 @@ class ServiceControllerRouterTest : public testing::Test { EXPECT_FALSE(client->IsConnectedToEndpoint(endpoint_id)); } + void RequestConnectionV3(ClientProxy* client, + const NearbyDevice& kRemoteDevice, + v3::ConnectionRequestInfo request_info, + ResultCallback callback, bool call_all_cb, + bool check_result = true, + bool endpoint_info_present = true) { + // If we set check_result to false, we expect that RequestConnection will + // not be called. + if (check_result) { + EXPECT_CALL(*mock_, RequestConnection) + .WillOnce([call_all_cb, endpoint_info_present, this]( + ClientProxy*, const std::string&, + const ConnectionRequestInfo& info, + const ConnectionOptions&) { + EXPECT_EQ(info.endpoint_info.Empty(), !endpoint_info_present); + if (call_all_cb) { + info.listener.initiated_cb(kRemoteEndpointId, {}); + info.listener.accepted_cb(kRemoteEndpointId); + info.listener.rejected_cb(kRemoteEndpointId, + Status{Status::kConnectionRejected}); + info.listener.disconnected_cb(kRemoteEndpointId); + info.listener.bandwidth_changed_cb(kRemoteEndpointId, + Medium::BLUETOOTH); + } + return Status{Status::kSuccess}; + }); + } + ConnectionOptions connection_options; + { + MutexLock lock(&mutex_); + complete_ = false; + router_.RequestConnectionV3(client, kRemoteDevice, + std::move(request_info), connection_options, + callback); + while (!complete_) cond_.Wait(); + if (check_result) { + EXPECT_EQ(result_, Status{Status::kSuccess}); + } + } + ConnectionResponseInfo response_info{ + .remote_endpoint_info = ByteArray{"endpoint_name"}, + .authentication_token = "auth_token", + .raw_authentication_token = ByteArray{"auth_token"}, + .is_incoming_connection = true, + }; + if (client->HasPendingConnectionToEndpoint(kRemoteDevice.GetEndpointId())) { + // we are calling this again, and do not need to rerun the below behavior. + return; + } + client->OnConnectionInitiated(kRemoteDevice.GetEndpointId(), response_info, + connection_options, {}, "conntokn"); + EXPECT_TRUE( + client->HasPendingConnectionToEndpoint(kRemoteDevice.GetEndpointId())); + } + + void AcceptConnectionV3(ClientProxy* client, + const NearbyDevice& kRemoteDevice, + const ResultCallback& callback) { + EXPECT_CALL(*mock_, AcceptConnection) + .WillOnce(Return(Status{Status::kSuccess})); + // Pre-condition for successful Accept is: connection must exist. + EXPECT_TRUE( + client->HasPendingConnectionToEndpoint(kRemoteDevice.GetEndpointId())); + { + MutexLock lock(&mutex_); + complete_ = false; + router_.AcceptConnectionV3(client, kRemoteDevice, {}, callback); + while (!complete_) cond_.Wait(); + EXPECT_EQ(result_, Status{Status::kSuccess}); + } + auto endpoint_id = kRemoteDevice.GetEndpointId(); + client->LocalEndpointAcceptedConnection(endpoint_id, {}); + client->RemoteEndpointAcceptedConnection(endpoint_id); + EXPECT_TRUE(client->IsConnectionAccepted(endpoint_id)); + client->OnConnectionAccepted(endpoint_id); + EXPECT_TRUE(client->IsConnectedToEndpoint(endpoint_id)); + } + + void RejectConnectionV3(ClientProxy* client, const NearbyDevice& device, + ResultCallback callback) { + EXPECT_CALL(*mock_, RejectConnection) + .WillOnce(Return(Status{Status::kSuccess})); + // Pre-condition for successful Accept is: connection must exist. + EXPECT_TRUE(client->HasPendingConnectionToEndpoint(device.GetEndpointId())); + { + MutexLock lock(&mutex_); + complete_ = false; + router_.RejectConnectionV3(client, device, callback); + while (!complete_) cond_.Wait(); + EXPECT_EQ(result_, Status{Status::kSuccess}); + } + client->LocalEndpointRejectedConnection(device.GetEndpointId()); + EXPECT_TRUE(client->IsConnectionRejected(device.GetEndpointId())); + } + + void InitiateBandwidthUpgradeV3(ClientProxy* client, + const NearbyDevice& device, + ResultCallback callback) { + EXPECT_CALL(*mock_, InitiateBandwidthUpgrade).Times(1); + EXPECT_TRUE(client->IsConnectedToEndpoint(device.GetEndpointId())); + { + MutexLock lock(&mutex_); + complete_ = false; + router_.InitiateBandwidthUpgradeV3(client, device, callback); + while (!complete_) cond_.Wait(); + EXPECT_EQ(result_, Status{Status::kSuccess}); + } + } + + void SendPayloadV3(ClientProxy* client, const NearbyDevice& recipient_device, + Payload payload, ResultCallback callback) { + EXPECT_CALL(*mock_, SendPayload).Times(1); + + bool connected = + client->IsConnectedToEndpoint(recipient_device.GetEndpointId()); + EXPECT_TRUE(connected); + { + MutexLock lock(&mutex_); + complete_ = false; + router_.SendPayloadV3(client, recipient_device, std::move(payload), + callback); + while (!complete_) cond_.Wait(); + EXPECT_EQ(result_, Status{Status::kSuccess}); + } + } + + void CancelPayloadV3(ClientProxy* client, + const NearbyDevice& recipient_device, + uint64_t payload_id, const ResultCallback& callback) { + EXPECT_CALL(*mock_, CancelPayload).Times(1); + EXPECT_TRUE( + client->IsConnectedToEndpoint(recipient_device.GetEndpointId())); + { + MutexLock lock(&mutex_); + router_.CancelPayloadV3(client, recipient_device, payload_id, callback); + } + } + + void DisconnectFromDeviceV3(ClientProxy* client, + const NearbyDevice& kRemoteDevice, + ResultCallback callback) { + EXPECT_CALL(*mock_, DisconnectFromEndpoint).Times(1); + EXPECT_TRUE(client->IsConnectedToEndpoint(kRemoteDevice.GetEndpointId())); + { + MutexLock lock(&mutex_); + complete_ = false; + router_.DisconnectFromDeviceV3(client, kRemoteDevice, callback); + while (!complete_) cond_.Wait(); + } + client->OnDisconnected(kRemoteDevice.GetEndpointId(), false); + EXPECT_FALSE(client->IsConnectedToEndpoint(kRemoteDevice.GetEndpointId())); + } + protected: const ResultCallback kCallback{ .result_cb = @@ -271,6 +436,8 @@ class ServiceControllerRouterTest : public testing::Test { const std::string kServiceId = "service id"; const std::string kRequestorName = "requestor name"; const std::string kRemoteEndpointId = "remote endpoint id"; + const v3::ConnectionsDevice kRemoteDevice = + v3::ConnectionsDevice(kRemoteEndpointId, "", {}); const std::int64_t kPayloadId = UINT64_C(0x123456789ABCDEF0); const ConnectionOptions kConnectionOptions{ { @@ -327,6 +494,21 @@ class ServiceControllerRouterTest : public testing::Test { }; namespace { +TEST_F(ServiceControllerRouterTest, QualityConversionWorks) { + EXPECT_EQ(router_.GetMediumQuality(Medium::UNKNOWN_MEDIUM), + v3::Quality::kUnknown); + EXPECT_EQ(router_.GetMediumQuality(Medium::USB), v3::Quality::kUnknown); + EXPECT_EQ(router_.GetMediumQuality(Medium::BLE), v3::Quality::kLow); + EXPECT_EQ(router_.GetMediumQuality(Medium::NFC), v3::Quality::kLow); + EXPECT_EQ(router_.GetMediumQuality(Medium::BLUETOOTH), v3::Quality::kMedium); + EXPECT_EQ(router_.GetMediumQuality(Medium::BLE_L2CAP), v3::Quality::kMedium); + EXPECT_EQ(router_.GetMediumQuality(Medium::WEB_RTC), v3::Quality::kHigh); + EXPECT_EQ(router_.GetMediumQuality(Medium::WIFI_HOTSPOT), v3::Quality::kHigh); + EXPECT_EQ(router_.GetMediumQuality(Medium::WIFI_LAN), v3::Quality::kHigh); + EXPECT_EQ(router_.GetMediumQuality(Medium::WIFI_DIRECT), v3::Quality::kHigh); + EXPECT_EQ(router_.GetMediumQuality(Medium::WIFI_AWARE), v3::Quality::kHigh); +} + TEST_F(ServiceControllerRouterTest, StartAdvertisingCalled) { StartAdvertising(&client_, kServiceId, kAdvertisingOptions, kConnectionRequestInfo, kCallback); @@ -365,7 +547,7 @@ TEST_F(ServiceControllerRouterTest, RequestConnectionCalled) { } TEST_F(ServiceControllerRouterTest, AcceptConnectionCalled) { - // Either Adviertisng, or Discovery should be ongoing. + // Either Advertising, or Discovery should be ongoing. StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, kCallback); // Establish connection. @@ -376,7 +558,7 @@ TEST_F(ServiceControllerRouterTest, AcceptConnectionCalled) { } TEST_F(ServiceControllerRouterTest, RejectConnectionCalled) { - // Either Adviertisng, or Discovery should be ongoing. + // Either Advertising, or Discovery should be ongoing. StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, kCallback); // Establish connection. @@ -387,7 +569,7 @@ TEST_F(ServiceControllerRouterTest, RejectConnectionCalled) { } TEST_F(ServiceControllerRouterTest, InitiateBandwidthUpgradeCalled) { - // Either Adviertisng, or Discovery should be ongoing. + // Either Advertising, or Discovery should be ongoing. StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, kCallback); // Establish connection. @@ -400,7 +582,7 @@ TEST_F(ServiceControllerRouterTest, InitiateBandwidthUpgradeCalled) { } TEST_F(ServiceControllerRouterTest, SendPayloadCalled) { - // Either Adviertisng, or Discovery should be ongoing. + // Either Advertising, or Discovery should be ongoing. StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, kCallback); // Establish connection. @@ -414,7 +596,7 @@ TEST_F(ServiceControllerRouterTest, SendPayloadCalled) { } TEST_F(ServiceControllerRouterTest, CancelPayloadCalled) { - // Either Adviertisng, or Discovery should be ongoing. + // Either Advertising, or Discovery should be ongoing. StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, kCallback); // Establish connection. @@ -429,7 +611,7 @@ TEST_F(ServiceControllerRouterTest, CancelPayloadCalled) { } TEST_F(ServiceControllerRouterTest, DisconnectFromEndpointCalled) { - // Either Adviertisng, or Discovery should be ongoing. + // Either Advertising, or Discovery should be ongoing. StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, kCallback); // Establish connection. @@ -441,6 +623,228 @@ TEST_F(ServiceControllerRouterTest, DisconnectFromEndpointCalled) { DisconnectFromEndpoint(&client_, kRemoteEndpointId, kCallback); } +TEST_F(ServiceControllerRouterTest, RequestConnectionCalledV3) { + // Either Advertising, or Discovery should be ongoing. + StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, + kCallback); + // Establish connection. + auto local_device = + v3::ConnectionsDevice(client_.GetLocalEndpointId(), kRequestorName, {}); + // Testing callback wrapping as well. + CountDownLatch initiated_latch(1); + CountDownLatch result_latch(2); + CountDownLatch disconnected_latch(1); + CountDownLatch bandwidth_changed_latch(1); + RequestConnectionV3( + &client_, kRemoteDevice, + v3::ConnectionRequestInfo{ + .local_device = local_device, + .listener = { + .initiated_cb = + [&initiated_latch](const NearbyDevice&, + const v3::InitialConnectionInfo&) { + initiated_latch.CountDown(); + }, + .result_cb = + [&result_latch](const NearbyDevice&, v3::ConnectionResult) { + result_latch.CountDown(); + }, + .disconnected_cb = + [&disconnected_latch](const NearbyDevice&) { + disconnected_latch.CountDown(); + }, + .bandwidth_changed_cb = + [&bandwidth_changed_latch](const NearbyDevice&, + v3::BandwidthInfo) { + bandwidth_changed_latch.CountDown(); + }}, + }, + kCallback, true); + EXPECT_TRUE(initiated_latch.Await().Ok()); + EXPECT_TRUE(result_latch.Await().Ok()); + EXPECT_TRUE(disconnected_latch.Await().Ok()); + EXPECT_TRUE(bandwidth_changed_latch.Await().Ok()); +} + +TEST_F(ServiceControllerRouterTest, RequestConnectionV3FakeDevice) { + // Either Advertising, or Discovery should be ongoing. + StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, + kCallback); + // Establish connection. + auto local_device = FakeNearbyDevice(); + // Testing callback wrapping as well. + CountDownLatch initiated_latch(1); + CountDownLatch result_latch(2); + CountDownLatch disconnected_latch(1); + CountDownLatch bandwidth_changed_latch(1); + RequestConnectionV3( + &client_, kRemoteDevice, + v3::ConnectionRequestInfo{ + .local_device = local_device, + .listener = { + .initiated_cb = + [&initiated_latch](const NearbyDevice&, + const v3::InitialConnectionInfo&) { + initiated_latch.CountDown(); + }, + .result_cb = + [&result_latch](const NearbyDevice&, v3::ConnectionResult) { + result_latch.CountDown(); + }, + .disconnected_cb = + [&disconnected_latch](const NearbyDevice&) { + disconnected_latch.CountDown(); + }, + .bandwidth_changed_cb = + [&bandwidth_changed_latch](const NearbyDevice&, + v3::BandwidthInfo) { + bandwidth_changed_latch.CountDown(); + }}, + }, + kCallback, true, true, false); + EXPECT_TRUE(initiated_latch.Await().Ok()); + EXPECT_TRUE(result_latch.Await().Ok()); + EXPECT_TRUE(disconnected_latch.Await().Ok()); + EXPECT_TRUE(bandwidth_changed_latch.Await().Ok()); +} + +TEST_F(ServiceControllerRouterTest, RequestConnectionV3TwiceFails) { + // Either Advertising, or Discovery should be ongoing. + StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, + kCallback); + // Establish connection. + auto local_device = + v3::ConnectionsDevice(client_.GetLocalEndpointId(), kRequestorName, {}); + RequestConnectionV3(&client_, kRemoteDevice, + v3::ConnectionRequestInfo{ + .local_device = local_device, + .listener = {}, + }, + kCallback, false); + RequestConnectionV3(&client_, kRemoteDevice, + v3::ConnectionRequestInfo{ + .local_device = local_device, + .listener = {}, + }, + kCallback, false, false); + { + MutexLock lock(&mutex_); + EXPECT_EQ(result_.value, Status::kAlreadyConnectedToEndpoint); + } +} + +TEST_F(ServiceControllerRouterTest, AcceptConnectionCalledV3) { + // Either Advertising, or Discovery should be ongoing. + StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, + kCallback); + // Establish connection. + auto local_device = + v3::ConnectionsDevice(client_.GetLocalEndpointId(), kRequestorName, {}); + RequestConnectionV3(&client_, kRemoteDevice, + v3::ConnectionRequestInfo{ + .local_device = local_device, + .listener = {}, + }, + kCallback, false); + // Now, we can accept connection. + AcceptConnectionV3(&client_, kRemoteDevice, kCallback); +} + +TEST_F(ServiceControllerRouterTest, RejectConnectionCalledV3) { + // Either Advertising, or Discovery should be ongoing. + StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, + kCallback); + // Establish connection. + auto local_device = + v3::ConnectionsDevice(client_.GetLocalEndpointId(), kRequestorName, {}); + RequestConnectionV3(&client_, kRemoteDevice, + v3::ConnectionRequestInfo{ + .local_device = local_device, + .listener = {}, + }, + kCallback, false); + // Now, we can reject connection. + RejectConnectionV3(&client_, kRemoteDevice, kCallback); +} + +TEST_F(ServiceControllerRouterTest, InitiateBandwidthUpgradeCalledV3) { + // Either Advertising, or Discovery should be ongoing. + StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, + kCallback); + // Establish connection. + auto local_device = + v3::ConnectionsDevice(client_.GetLocalEndpointId(), kRequestorName, {}); + RequestConnectionV3(&client_, kRemoteDevice, + v3::ConnectionRequestInfo{ + .local_device = local_device, + .listener = {}, + }, + kCallback, false); + // Now, we can accept connection. + AcceptConnectionV3(&client_, kRemoteDevice, kCallback); + // Now we can change connection bandwidth. + InitiateBandwidthUpgradeV3(&client_, kRemoteDevice, kCallback); +} + +TEST_F(ServiceControllerRouterTest, SendPayloadCalledV3) { + // Either Advertising, or Discovery should be ongoing. + StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, + kCallback); + // Establish connection. + auto local_device = + v3::ConnectionsDevice(client_.GetLocalEndpointId(), kRequestorName, {}); + RequestConnectionV3(&client_, kRemoteDevice, + v3::ConnectionRequestInfo{ + .local_device = local_device, + .listener = {}, + }, + kCallback, false); + // Now, we can accept connection. + AcceptConnectionV3(&client_, kRemoteDevice, kCallback); + // Now we can send payload. + SendPayloadV3(&client_, kRemoteDevice, Payload{ByteArray("data")}, kCallback); +} + +TEST_F(ServiceControllerRouterTest, DisconnectFromDeviceCalledV3) { + // Either Advertising, or Discovery should be ongoing. + StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, + kCallback); + // Establish connection. + auto local_device = + v3::ConnectionsDevice(client_.GetLocalEndpointId(), kRequestorName, {}); + RequestConnectionV3(&client_, kRemoteDevice, + v3::ConnectionRequestInfo{ + .local_device = local_device, + .listener = {}, + }, + kCallback, false); + // Now, we can accept connection. + AcceptConnectionV3(&client_, kRemoteDevice, kCallback); + // We can disconnect at any time after RequestConnection. + DisconnectFromDeviceV3(&client_, kRemoteDevice, kCallback); +} + +TEST_F(ServiceControllerRouterTest, CancelPayloadV3Called) { + // Either Advertising, or Discovery should be ongoing. + StartDiscovery(&client_, kServiceId, kDiscoveryOptions, discovery_listener_, + kCallback); + // Establish connection. + auto local_device = + v3::ConnectionsDevice(client_.GetLocalEndpointId(), kRequestorName, {}); + RequestConnectionV3(&client_, kRemoteDevice, + v3::ConnectionRequestInfo{ + .local_device = local_device, + .listener = {}, + }, + kCallback, false); + // Now, we can accept connection. + AcceptConnectionV3(&client_, kRemoteDevice, kCallback); + // We have to know payload id, before we can cancel payload transfer. + // It is either after a call to SendPayload, or after receiving + // PayloadProgress callback. Let's assume we have it, and proceed. + CancelPayloadV3(&client_, kRemoteDevice, kPayloadId, kCallback); +} + } // namespace } // namespace connections } // namespace nearby diff --git a/connections/v3/BUILD b/connections/v3/BUILD index 554d9d10..d4e5645e 100644 --- a/connections/v3/BUILD +++ b/connections/v3/BUILD @@ -7,6 +7,7 @@ cc_library( "connections_device.h", "connections_device_provider.h", "listeners.h", + "params.h", ], visibility = [ "//connections:__subpackages__", diff --git a/connections/v3/listeners.h b/connections/v3/listeners.h index 01f985e3..ac217b97 100644 --- a/connections/v3/listeners.h +++ b/connections/v3/listeners.h @@ -15,6 +15,8 @@ #ifndef THIRD_PARTY_NEARBY_CONNECTIONS_V3_LISTENERS_H_ #define THIRD_PARTY_NEARBY_CONNECTIONS_V3_LISTENERS_H_ +#include + #include "absl/functional/any_invocable.h" #include "connections/listeners.h" #include "connections/v3/bandwidth_info.h" @@ -53,11 +55,13 @@ struct ConnectionListener { // ConnectionsStatusCodes#SUCCESS}, both sides have accepted the // connection and may now send {@link Payload}s to each other. // Otherwise, the connection was rejected. + // We use std::function here as both rejection and acceptance callbacks call + // this function now. // remote_device - The identifier for the remote endpoint. // resolution - The resolution of the connection (accepted or rejected). - absl::AnyInvocable + std::function result_cb = [](const NearbyDevice&, ConnectionResult) {}; // Called when a remote endpoint is disconnected or has become unreachable. @@ -111,7 +115,8 @@ struct PayloadListener { // remote_device - The identifier for the remote endpoint that sent the // payload. // payload - The Payload object received. - absl::AnyInvocable + absl::AnyInvocable payload_received_cb = [](const NearbyDevice&, Payload) {}; // Called with progress information about an active Payload transfer, either diff --git a/connections/v3/params.h b/connections/v3/params.h new file mode 100644 index 00000000..92676ddd --- /dev/null +++ b/connections/v3/params.h @@ -0,0 +1,44 @@ +// 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 THIRD_PARTY_NEARBY_CONNECTIONS_V3_PARAMS_H_ +#define THIRD_PARTY_NEARBY_CONNECTIONS_V3_PARAMS_H_ + +#include + +#include "connections/v3/listeners.h" +#include "internal/interop/device.h" + +namespace nearby { +namespace connections { +namespace v3 { + +// Used by Discovery in Core::RequestConnection(). +// Used by Advertising in Core::StartAdvertising(). +struct ConnectionRequestInfo { + // local_device - Identifying information about this device (eg. name, + // device type). + // listener - A set of callbacks notified when remote endpoints request a + // connection to this endpoint. + // This variable is a reference since NearbyDevice is a virtual class type, + // and we can only retain the information correctly by taking a reference. + NearbyDevice& local_device; + v3::ConnectionListener listener; +}; + +} // namespace v3 +} // namespace connections +} // namespace nearby + +#endif // THIRD_PARTY_NEARBY_CONNECTIONS_V3_PARAMS_H_