From ae277748ce068ef1730d5104002d4324fc4ed89e Mon Sep 17 00:00:00 2001 From: Alexey Polyudov Date: Wed, 15 Jul 2020 11:20:27 -0700 Subject: [PATCH] Roll forward to cl/321106672 Signed-off-by: Alexey Polyudov Change-Id: I6e34e075aa2cbbacba714019f6d0e7506313e53d --- cpp/core_v2/internal/BUILD | 1 - cpp/core_v2/internal/base_pcp_handler.cc | 36 +++- cpp/core_v2/internal/base_pcp_handler.h | 13 ++ cpp/core_v2/internal/base_pcp_handler_test.cc | 8 +- cpp/core_v2/internal/endpoint_manager.cc | 2 +- cpp/core_v2/internal/endpoint_manager.h | 2 +- cpp/core_v2/internal/mediums/webrtc/BUILD | 1 + .../mediums/webrtc/connection_flow_test.cc | 21 ++- cpp/core_v2/internal/mediums/webrtc_test.cc | 27 ++- cpp/core_v2/internal/mediums/wifi_lan.cc | 39 ++--- cpp/core_v2/internal/mediums/wifi_lan.h | 47 +++-- .../internal/p2p_cluster_pcp_handler.cc | 70 ++++---- .../internal/p2p_cluster_pcp_handler.h | 19 +- .../internal/wifi_lan_endpoint_channel.h | 2 +- cpp/core_v2/options.h | 12 ++ cpp/platform_v2/api/wifi_lan.h | 7 +- cpp/platform_v2/base/medium_environment.cc | 162 +++++++++++------- cpp/platform_v2/base/medium_environment.h | 36 ++-- cpp/platform_v2/impl/g3/BUILD | 1 + cpp/platform_v2/impl/g3/platform.cc | 7 +- cpp/platform_v2/impl/g3/wifi_lan.cc | 63 +++---- cpp/platform_v2/impl/g3/wifi_lan.h | 21 +-- cpp/platform_v2/public/wifi_lan.cc | 24 ++- cpp/platform_v2/public/wifi_lan.h | 5 +- proto/error_code_enums.proto | 74 +++++++- proto/sharing_enums.proto | 12 ++ 26 files changed, 477 insertions(+), 235 deletions(-) diff --git a/cpp/core_v2/internal/BUILD b/cpp/core_v2/internal/BUILD index e2e6c2db..b8abaf01 100644 --- a/cpp/core_v2/internal/BUILD +++ b/cpp/core_v2/internal/BUILD @@ -155,7 +155,6 @@ cc_test( "//testing/base/public:gunit", "//testing/base/public:gunit_main", "//absl/container:flat_hash_set", - "//absl/functional:bind_front", "//absl/strings", "//absl/synchronization", "//absl/time", diff --git a/cpp/core_v2/internal/base_pcp_handler.cc b/cpp/core_v2/internal/base_pcp_handler.cc index 30759bec..1677c7d9 100644 --- a/cpp/core_v2/internal/base_pcp_handler.cc +++ b/cpp/core_v2/internal/base_pcp_handler.cc @@ -302,6 +302,7 @@ Status BasePcpHandler::RequestConnection(ClientProxy* client, return; } + std::vector endpoints; auto endpoint = GetDiscoveredEndpoint(endpoint_id); if (endpoint == nullptr) { NEARBY_LOG(INFO, "Discovered endpoint not found: id=%s", @@ -310,9 +311,31 @@ Status BasePcpHandler::RequestConnection(ClientProxy* client, return; } - auto connect_impl_result = ConnectImpl(client, endpoint); - std::unique_ptr channel = - std::move(connect_impl_result.endpoint_channel); + auto webrtc_endpoint = absl::make_unique( + DiscoveredEndpoint{endpoint->endpoint_id, endpoint->endpoint_name, + endpoint->service_id, + proto::connections::Medium::WEB_RTC}, + CreatePeerIdFromAdvertisement(endpoint->service_id, + endpoint->endpoint_id, + endpoint->endpoint_name)); + endpoints.push_back(endpoint); + endpoints.push_back(webrtc_endpoint.get()); + + std::sort(endpoints.begin(), endpoints.end(), + [this](DiscoveredEndpoint* a, DiscoveredEndpoint* b) -> bool { + return IsPreferred(*a, *b); + }); + + std::unique_ptr channel; + ConnectImplResult connect_impl_result; + + for (auto connect_endpoint : endpoints) { + 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", @@ -1068,6 +1091,13 @@ void BasePcpHandler::PendingConnectionInfo::LocalEndpointRejectedConnection( client->LocalEndpointRejectedConnection(endpoint_id); } +mediums::PeerId BasePcpHandler::CreatePeerIdFromAdvertisement( + const std::string& service_id, const std::string& endpoint_id, + const std::string& endpoint_name) { + std::string seed = absl::StrCat(service_id, endpoint_id, endpoint_name); + return mediums::PeerId::FromSeed(ByteArray(std::move(seed))); +} + } // namespace connections } // namespace nearby } // namespace location diff --git a/cpp/core_v2/internal/base_pcp_handler.h b/cpp/core_v2/internal/base_pcp_handler.h index 8f3ec486..ed8d4181 100644 --- a/cpp/core_v2/internal/base_pcp_handler.h +++ b/cpp/core_v2/internal/base_pcp_handler.h @@ -24,6 +24,7 @@ #include "core_v2/internal/encryption_runner.h" #include "core_v2/internal/endpoint_channel_manager.h" #include "core_v2/internal/endpoint_manager.h" +#include "core_v2/internal/mediums/webrtc.h" #include "core_v2/internal/pcp.h" #include "core_v2/internal/pcp_handler.h" #include "core_v2/listeners.h" @@ -195,6 +196,14 @@ class BasePcpHandler : public PcpHandler, proto::connections::Medium medium; }; + struct WebRtcEndpoint : public DiscoveredEndpoint { + WebRtcEndpoint(DiscoveredEndpoint endpoint, mediums::PeerId peer_id) + : DiscoveredEndpoint(std::move(endpoint)), + peer_id(std::move(peer_id)) {} + + mediums::PeerId peer_id; + }; + struct ConnectImplResult { proto::connections::Medium medium = proto::connections::Medium::UNKNOWN_MEDIUM; @@ -249,6 +258,10 @@ class BasePcpHandler : public PcpHandler, GetConnectionMediumsByPriority() = 0; virtual proto::connections::Medium GetDefaultUpgradeMedium() = 0; + mediums::PeerId CreatePeerIdFromAdvertisement(const string& service_id, + const string& endpoint_id, + const string& endpoint_name); + EndpointManager* endpoint_manager_; EndpointChannelManager* channel_manager_; diff --git a/cpp/core_v2/internal/base_pcp_handler_test.cc b/cpp/core_v2/internal/base_pcp_handler_test.cc index 90cd2085..2b90f5fd 100644 --- a/cpp/core_v2/internal/base_pcp_handler_test.cc +++ b/cpp/core_v2/internal/base_pcp_handler_test.cc @@ -107,11 +107,15 @@ class MockPcpHandler : public BasePcpHandler { MOCK_METHOD(Status, StopDiscoveryImpl, (ClientProxy * client), (override)); MOCK_METHOD(ConnectImplResult, ConnectImpl, (ClientProxy * client, DiscoveredEndpoint* endpoint), (override)); - MOCK_METHOD(std::vector, - GetConnectionMediumsByPriority, (), (override)); MOCK_METHOD(proto::connections::Medium, GetDefaultUpgradeMedium, (), (override)); + std::vector GetConnectionMediumsByPriority() + override { + return {proto::connections::Medium::BLE, + proto::connections::Medium::WEB_RTC}; + } + // Mock adapters for protected non-virtual methods of a base class. void OnEndpointFound(ClientProxy* client, std::shared_ptr endpoint) { diff --git a/cpp/core_v2/internal/endpoint_manager.cc b/cpp/core_v2/internal/endpoint_manager.cc index 9ae32550..85855d42 100644 --- a/cpp/core_v2/internal/endpoint_manager.cc +++ b/cpp/core_v2/internal/endpoint_manager.cc @@ -241,7 +241,7 @@ EndpointManager::~EndpointManager() { NEARBY_LOG(INFO, "EndpointManager is down"); } -const EndpointManager::FrameProcessor::Handle +EndpointManager::FrameProcessor::Handle EndpointManager::RegisterFrameProcessor( V1Frame::FrameType frame_type, EndpointManager::FrameProcessor* processor) { const FrameProcessor::Handle handle = processor; diff --git a/cpp/core_v2/internal/endpoint_manager.h b/cpp/core_v2/internal/endpoint_manager.h index 39c2984f..d3afa93b 100644 --- a/cpp/core_v2/internal/endpoint_manager.h +++ b/cpp/core_v2/internal/endpoint_manager.h @@ -95,7 +95,7 @@ class EndpointManager { // FrameProcessor* instances are of dynamic duration and survive all sessions. // returns unique handle to be used for unregistering. // Blocks until registration is complete. - const FrameProcessor::Handle RegisterFrameProcessor( + FrameProcessor::Handle RegisterFrameProcessor( V1Frame::FrameType frame_type, FrameProcessor* processor); void UnregisterFrameProcessor(V1Frame::FrameType frame_type, const void* handle, bool sync = false); diff --git a/cpp/core_v2/internal/mediums/webrtc/BUILD b/cpp/core_v2/internal/mediums/webrtc/BUILD index 699da15f..5aa2c1ae 100644 --- a/cpp/core_v2/internal/mediums/webrtc/BUILD +++ b/cpp/core_v2/internal/mediums/webrtc/BUILD @@ -63,6 +63,7 @@ cc_test( deps = [ ":webrtc", "//platform_v2/base", + "//platform_v2/base:test_util", "//platform_v2/impl/g3", # buildcleaner: keep "//platform_v2/public:comm", "//platform_v2/public:types", diff --git a/cpp/core_v2/internal/mediums/webrtc/connection_flow_test.cc b/cpp/core_v2/internal/mediums/webrtc/connection_flow_test.cc index d6f80326..02aaa468 100644 --- a/cpp/core_v2/internal/mediums/webrtc/connection_flow_test.cc +++ b/cpp/core_v2/internal/mediums/webrtc/connection_flow_test.cc @@ -19,6 +19,7 @@ #include "core_v2/internal/mediums/webrtc/session_description_wrapper.h" #include "platform_v2/base/byte_array.h" +#include "platform_v2/base/medium_environment.h" #include "platform_v2/public/webrtc.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -34,6 +35,14 @@ namespace connections { namespace mediums { namespace { +class ConnectionFlowTest : public ::testing::Test { + protected: + ConnectionFlowTest() { + MediumEnvironment::Instance().Stop(); + MediumEnvironment::Instance().Start({.webrtc_enabled = true}); + } +}; + std::unique_ptr CopyCandidate( const webrtc::IceCandidateInterface* candidate) { return webrtc::CreateIceCandidate(candidate->sdp_mid(), @@ -43,7 +52,7 @@ std::unique_ptr CopyCandidate( // TODO(bfranz) - Add test that deterministically sends answerer_ice_candidates // before answer is sent. -TEST(ConnectionFlowTest, SuccessfulOfferAnswerFlow) { +TEST_F(ConnectionFlowTest, SuccessfulOfferAnswerFlow) { WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; Future message_received_future; @@ -109,7 +118,7 @@ TEST(ConnectionFlowTest, SuccessfulOfferAnswerFlow) { EXPECT_EQ(received_message.result(), ByteArray{message}); } -TEST(ConnectionFlowTest, CreateAnswerBeforeOfferReceived) { +TEST_F(ConnectionFlowTest, CreateAnswerBeforeOfferReceived) { WebRtcMedium webrtc_medium; std::unique_ptr answerer = ConnectionFlow::Create( @@ -120,7 +129,7 @@ TEST(ConnectionFlowTest, CreateAnswerBeforeOfferReceived) { EXPECT_FALSE(answer.IsValid()); } -TEST(ConnectionFlowTest, SetAnswerBeforeOffer) { +TEST_F(ConnectionFlowTest, SetAnswerBeforeOffer) { WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; std::unique_ptr offerer = @@ -142,7 +151,7 @@ TEST(ConnectionFlowTest, SetAnswerBeforeOffer) { EXPECT_FALSE(offerer->OnAnswerReceived(answer)); } -TEST(ConnectionFlowTest, CannotCreateOfferAfterClose) { +TEST_F(ConnectionFlowTest, CannotCreateOfferAfterClose) { WebRtcMedium webrtc_medium; std::unique_ptr offerer = ConnectionFlow::Create( @@ -154,7 +163,7 @@ TEST(ConnectionFlowTest, CannotCreateOfferAfterClose) { EXPECT_FALSE(offerer->CreateOffer().IsValid()); } -TEST(ConnectionFlowTest, CannotSetSessionDescriptionAfterClose) { +TEST_F(ConnectionFlowTest, CannotSetSessionDescriptionAfterClose) { WebRtcMedium webrtc_medium; std::unique_ptr offerer = ConnectionFlow::Create( @@ -169,7 +178,7 @@ TEST(ConnectionFlowTest, CannotSetSessionDescriptionAfterClose) { EXPECT_FALSE(offerer->SetLocalSessionDescription(offer)); } -TEST(ConnectionFlowTest, CannotReceiveOfferAfterClose) { +TEST_F(ConnectionFlowTest, CannotReceiveOfferAfterClose) { WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; std::unique_ptr offerer = diff --git a/cpp/core_v2/internal/mediums/webrtc_test.cc b/cpp/core_v2/internal/mediums/webrtc_test.cc index b66a308f..cd394e59 100644 --- a/cpp/core_v2/internal/mediums/webrtc_test.cc +++ b/cpp/core_v2/internal/mediums/webrtc_test.cc @@ -16,6 +16,7 @@ #include "core_v2/internal/mediums/webrtc/webrtc_socket_wrapper.h" #include "platform_v2/base/listeners.h" +#include "platform_v2/base/medium_environment.h" #include "platform_v2/public/mutex_lock.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -27,8 +28,16 @@ namespace mediums { namespace { +class WebRtcTest : public ::testing::Test { + protected: + WebRtcTest() { + MediumEnvironment::Instance().Stop(); + MediumEnvironment::Instance().Start({.webrtc_enabled = true}); + } +}; + // Basic test to check that device is accepting connections when initialized. -TEST(WebRtcTest, NotAcceptingConnections) { +TEST_F(WebRtcTest, NotAcceptingConnections) { WebRtc webrtc; ASSERT_TRUE(webrtc.IsAvailable()); EXPECT_FALSE(webrtc.IsAcceptingConnections()); @@ -36,7 +45,7 @@ TEST(WebRtcTest, NotAcceptingConnections) { // Tests the flow when the device tries to accept connections twice. In this // case, only the first call is successful and subsequent calls fail. -TEST(WebRtcTest, StartAcceptingConnectionTwice) { +TEST_F(WebRtcTest, StartAcceptingConnectionTwice) { using MockAcceptedCallback = testing::MockFunction; testing::StrictMock mock_accepted_callback_; @@ -54,7 +63,7 @@ TEST(WebRtcTest, StartAcceptingConnectionTwice) { // Tests the flow when the device tries to connect but the data channel times // out. -TEST(WebRtcTest, Connect_DataChannelTimeOut) { +TEST_F(WebRtcTest, Connect_DataChannelTimeOut) { WebRtc webrtc; PeerId peer_id("peer_id"); @@ -68,7 +77,7 @@ TEST(WebRtcTest, Connect_DataChannelTimeOut) { // Tests the flow when the device calls Connect() after calling // StartAcceptingConnections() without StopAcceptingConnections(). -TEST(WebRtcTest, StartAcceptingConnection_ThenConnect) { +TEST_F(WebRtcTest, StartAcceptingConnection_ThenConnect) { using MockAcceptedCallback = testing::MockFunction; testing::StrictMock mock_accepted_callback_; @@ -88,7 +97,7 @@ TEST(WebRtcTest, StartAcceptingConnection_ThenConnect) { // Tests the flow when the device calls StartAcceptingConnections but the medium // is closed before a peer device can connect to it. -TEST(WebRtcTest, StartAndStopAcceptingConnections) { +TEST_F(WebRtcTest, StartAndStopAcceptingConnections) { using MockAcceptedCallback = testing::MockFunction; testing::StrictMock mock_accepted_callback_; @@ -105,7 +114,7 @@ TEST(WebRtcTest, StartAndStopAcceptingConnections) { // Tests the flow when the device tries to connect to two different peers // without disconnecting in between. -TEST(WebRtcTest, ConnectTwice) { +TEST_F(WebRtcTest, ConnectTwice) { WebRtc receiver, sender, device_c; WebRtcSocketWrapper receiver_socket, sender_socket; const PeerId self_id("self_id"), other_id("other_id"); @@ -149,7 +158,7 @@ TEST(WebRtcTest, ConnectTwice) { // Tests the flow when the two devices exchange SDP messages and connect to each // other but disconnect before being able to send/receive the actual data. -TEST(WebRtcTest, ConnectBothDevicesAndAbort) { +TEST_F(WebRtcTest, ConnectBothDevicesAndAbort) { WebRtc receiver, sender; WebRtcSocketWrapper receiver_socket, sender_socket; const PeerId self_id("self_id"); @@ -175,7 +184,7 @@ TEST(WebRtcTest, ConnectBothDevicesAndAbort) { // Tests the flow when the two devices exchange SDP messages and connect to each // other and the actual data is exchanged successfully between the devices. -TEST(WebRtcTest, ConnectBothDevicesAndSendData) { +TEST_F(WebRtcTest, ConnectBothDevicesAndSendData) { WebRtc receiver, sender; WebRtcSocketWrapper receiver_socket, sender_socket; const PeerId self_id("self_id"); @@ -207,7 +216,7 @@ TEST(WebRtcTest, ConnectBothDevicesAndSendData) { // Tests the flow when the two devices exchange SDP messages and connect to each // other but the signaling channel is closed before sending the data. -TEST(WebRtcTest, ConnectBothDevices_ShutdownSignaling_SendData) { +TEST_F(WebRtcTest, ConnectBothDevices_ShutdownSignaling_SendData) { WebRtc receiver, sender; WebRtcSocketWrapper receiver_socket, sender_socket; const PeerId self_id("self_id"); diff --git a/cpp/core_v2/internal/mediums/wifi_lan.cc b/cpp/core_v2/internal/mediums/wifi_lan.cc index b334802d..7b24cdb5 100644 --- a/cpp/core_v2/internal/mediums/wifi_lan.cc +++ b/cpp/core_v2/internal/mediums/wifi_lan.cc @@ -34,10 +34,10 @@ bool WifiLan::IsAvailable() const { bool WifiLan::IsAvailableLocked() const { return medium_.IsValid(); } bool WifiLan::StartAdvertising(const std::string& service_id, - const std::string& wifi_lan_service_info_name) { + const std::string& service_info_name) { MutexLock lock(&mutex_); - if (wifi_lan_service_info_name.empty()) { + if (service_info_name.empty()) { NEARBY_LOG( INFO, "Refusing to turn on WifiLan advertising. Empty service info name."); @@ -50,45 +50,45 @@ bool WifiLan::StartAdvertising(const std::string& service_id, return false; } - if (!medium_.StartAdvertising(service_id, wifi_lan_service_info_name)) { + if (!medium_.StartAdvertising(service_id, service_info_name)) { NEARBY_LOG( INFO, "Failed to turn on WifiLan advertising with service info name=%s", - wifi_lan_service_info_name.c_str()); + service_info_name.c_str()); return false; } NEARBY_LOGS(INFO) << "Turned on WifiLan advertising with service info name=" - << wifi_lan_service_info_name + << service_info_name << ", service id=" << service_id; - advertising_info_.service_id = service_id; + advertising_info_.Add(service_id); return true; } bool WifiLan::StopAdvertising(const std::string& service_id) { MutexLock lock(&mutex_); - if (!IsAdvertisingLocked()) { + if (!IsAdvertisingLocked(service_id)) { NEARBY_LOG(INFO, "Can't turn off WifiLan advertising; it is already off"); return false; } NEARBY_LOG(INFO, "Turned off WifiLan advertising with service id=%s", service_id.c_str()); - bool ret = medium_.StopAdvertising(advertising_info_.service_id); + bool ret = medium_.StopAdvertising(service_id); // Reset our bundle of advertising state to mark that we're no longer // advertising. - advertising_info_.Clear(); + advertising_info_.Remove(service_id); return ret; } -bool WifiLan::IsAdvertising() { +bool WifiLan::IsAdvertising(const std::string& service_id) { MutexLock lock(&mutex_); - return IsAdvertisingLocked(); + return IsAdvertisingLocked(service_id); } -bool WifiLan::IsAdvertisingLocked() { - return !advertising_info_.Empty(); +bool WifiLan::IsAdvertisingLocked(const std::string& service_id) { + return advertising_info_.Existed(service_id); } bool WifiLan::StartDiscovery(const std::string& service_id, @@ -124,7 +124,7 @@ bool WifiLan::StartDiscovery(const std::string& service_id, NEARBY_LOG(INFO, "Turned on WifiLan discovering with service id=%s", service_id.c_str()); // Mark the fact that we're currently performing a WifiLan discovering. - discovering_info_.service_id = service_id; + discovering_info_.Add(service_id); return true; } @@ -152,7 +152,7 @@ bool WifiLan::IsDiscovering(const std::string& service_id) { } bool WifiLan::IsDiscoveringLocked(const std::string& service_id) { - return !discovering_info_.Empty(); + return discovering_info_.Existed(service_id); } bool WifiLan::StartAcceptingConnections(const std::string& service_id, @@ -188,7 +188,7 @@ bool WifiLan::StartAcceptingConnections(const std::string& service_id, return false; } - accepting_connections_info_.service_id = service_id; + accepting_connections_info_.Add(service_id); return true; } @@ -202,11 +202,10 @@ bool WifiLan::StopAcceptingConnections(const std::string& service_id) { return false; } - bool ret = - medium_.StopAcceptingConnections(accepting_connections_info_.service_id); + bool ret = medium_.StopAcceptingConnections(service_id); // Reset our bundle of accepting connections state to mark that we're no // longer accepting connections. - accepting_connections_info_.Clear(); + accepting_connections_info_.Remove(service_id); return ret; } @@ -217,7 +216,7 @@ bool WifiLan::IsAcceptingConnections(const std::string& service_id) { } bool WifiLan::IsAcceptingConnectionsLocked(const std::string& service_id) { - return !accepting_connections_info_.Empty(); + return accepting_connections_info_.Existed(service_id); } WifiLanSocket WifiLan::Connect(WifiLanService& wifi_lan_service, diff --git a/cpp/core_v2/internal/mediums/wifi_lan.h b/cpp/core_v2/internal/mediums/wifi_lan.h index b22a1b9e..72c317f8 100644 --- a/cpp/core_v2/internal/mediums/wifi_lan.h +++ b/cpp/core_v2/internal/mediums/wifi_lan.h @@ -23,6 +23,7 @@ #include "platform_v2/public/mutex.h" #include "platform_v2/public/wifi_lan.h" #include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" namespace location { namespace nearby { @@ -39,7 +40,7 @@ class WifiLan { // Sets custom service info name, and then enables WifiLan advertising. // Returns true, if name is successfully set, and false otherwise. bool StartAdvertising(const std::string& service_id, - const std::string& wifi_lan_service_info_name) + const std::string& service_info_name) ABSL_LOCKS_EXCLUDED(mutex_); // Disables WifiLan advertising, and restores service info name to @@ -47,7 +48,7 @@ class WifiLan { bool StopAdvertising(const std::string& service_id) ABSL_LOCKS_EXCLUDED(mutex_); - bool IsAdvertising() ABSL_LOCKS_EXCLUDED(mutex_); + bool IsAdvertising(const std::string& service_id) ABSL_LOCKS_EXCLUDED(mutex_); // Enables WifiLan discovery mode. Will report any discoverable services in // range through a callback. Returns true, if discovery mode was enabled, @@ -84,31 +85,53 @@ class WifiLan { private: struct AdvertisingInfo { - bool Empty() const { return service_id.empty(); } - void Clear() { service_id.clear(); } + bool Empty() const { return service_ids.empty(); } + void Clear() { service_ids.clear(); } + void Add(const std::string& service_id) { service_ids.emplace(service_id); } + void Remove(const std::string& service_id) { + service_ids.erase(service_id); + } + bool Existed(const std::string& service_id) const { + return service_ids.contains(service_id); + } - std::string service_id; + absl::flat_hash_set service_ids; }; struct DiscoveringInfo { - bool Empty() const { return service_id.empty(); } - void Clear() { service_id.clear(); } + bool Empty() const { return service_ids.empty(); } + void Clear() { service_ids.clear(); } + void Add(const std::string& service_id) { service_ids.emplace(service_id); } + void Remove(const std::string& service_id) { + service_ids.erase(service_id); + } + bool Existed(const std::string& service_id) const { + return service_ids.contains(service_id); + } - std::string service_id; + absl::flat_hash_set service_ids; }; struct AcceptingConnectionsInfo { - bool Empty() const { return service_id.empty(); } - void Clear() { service_id.clear(); } + bool Empty() const { return service_ids.empty(); } + void Clear() { service_ids.clear(); } + void Add(const std::string& service_id) { service_ids.emplace(service_id); } + void Remove(const std::string& service_id) { + service_ids.erase(service_id); + } + bool Existed(const std::string& service_id) const { + return service_ids.contains(service_id); + } - std::string service_id; + absl::flat_hash_set service_ids; }; // Same as IsAvailable(), but must be called with mutex_ held. bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); // Same as IsAdvertising(), but must be called with mutex_ held. - bool IsAdvertisingLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + bool IsAdvertisingLocked(const std::string& service_id) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); // Same as IsDiscovering(), but must be called with mutex_ held. bool IsDiscoveringLocked(const std::string& service_id) diff --git a/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc b/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc index 7a1c9842..9f4a0176 100644 --- a/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc +++ b/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc @@ -247,32 +247,33 @@ P2pClusterPcpHandler::MakeBluetoothDeviceLostHandler( } bool P2pClusterPcpHandler::IsRecognizedWifiLanEndpoint( - const std::string& name_string, const std::string& service_id, - const WifiLanServiceInfo& name) const { - if (!name.IsValid()) { + const std::string& service_id, + const WifiLanServiceInfo& service_info) const { + if (!service_info.IsValid()) { NEARBY_LOG( INFO, "P2pClusterPcpHandler::IsRecognizedWifiLanEndpoint: name is invalid"); return false; } - if (name.GetPcp() != GetPcp()) { + if (service_info.GetPcp() != GetPcp()) { NEARBY_LOG(INFO, "P2pClusterPcpHandler::IsRecognizedWifiLanEndpoint: Pcp is " "not matched; name.Pcp=%d, Pcp=%d", - name.GetPcp(), GetPcp()); + service_info.GetPcp(), GetPcp()); return false; } ByteArray expected_service_id_hash = GenerateHash(service_id, BluetoothDeviceName::kServiceIdHashLength); - if (name.GetServiceIdHash() != expected_service_id_hash) { + if (service_info.GetServiceIdHash() != expected_service_id_hash) { NEARBY_LOG(INFO, "P2pClusterPcpHandler::IsRecognizedWifiLanEndpoint: service " "id hash is " "not matched; name.service_id_hash=%s, expected=%s", - name.GetServiceIdHash().data(), expected_service_id_hash.data()); + service_info.GetServiceIdHash().data(), + expected_service_id_hash.data()); return false; } @@ -296,25 +297,23 @@ P2pClusterPcpHandler::MakeWifiLanServiceDiscoveredHandler( } // Parse the WifiLan service name. - const std::string& service_name_string = service.GetName(); - WifiLanServiceInfo service_name(service_name_string); + const std::string& service_info_name = service.GetName(); + WifiLanServiceInfo service_info(service_info_name); // Make sure the WifiLan service name points to a valid // endpoint we're discovering. - if (!IsRecognizedWifiLanEndpoint(service_name_string, service_id, - service_name)) - return; + if (!IsRecognizedWifiLanEndpoint(service_id, service_info)) return; // Report the discovered endpoint to the client. NEARBY_LOG(INFO, "Invoking BasePcpHandler::OnEndpointFound() for WifiLan " "service=%s; id=%s; name=%s", - service_id.c_str(), service_name.GetEndpointId().c_str(), - service_name.GetEndpointName().c_str()); + service_id.c_str(), service_info.GetEndpointId().c_str(), + service_info.GetEndpointName().c_str()); OnEndpointFound(client, std::make_shared(WifiLanEndpoint{ { - service_name.GetEndpointId(), - service_name.GetEndpointName(), + service_info.GetEndpointId(), + service_info.GetEndpointName(), service_id, proto::connections::Medium::WIFI_LAN, }, @@ -341,14 +340,12 @@ P2pClusterPcpHandler::MakeWifiLanServiceLostHandler( } // Parse the WifiLan service name. - const std::string& service_name_string = service.GetName(); - WifiLanServiceInfo service_name(service_name_string); + const std::string& service_info_name = service.GetName(); + WifiLanServiceInfo service_info(service_info_name); // Make sure the WifiLan service name points to a valid // endpoint we're discovering. - if (!IsRecognizedWifiLanEndpoint(service_name_string, service_id, - service_name)) - return; + if (!IsRecognizedWifiLanEndpoint(service_id, service_info)) return; // Report the discovered endpoint to the client. NEARBY_LOG( @@ -358,8 +355,8 @@ P2pClusterPcpHandler::MakeWifiLanServiceLostHandler( client, service_id.c_str()); OnEndpointLost(client, WifiLanEndpoint{ { - service_name.GetEndpointId(), - service_name.GetEndpointName(), + service_info.GetEndpointId(), + service_info.GetEndpointName(), service_id, proto::connections::Medium::WIFI_LAN, }, @@ -611,11 +608,11 @@ proto::connections::Medium P2pClusterPcpHandler::StartWifiLanAdvertising( } RunOnPcpHandlerThread([this, client, local_endpoint_name, socket = std::move(socket)]() mutable { - std::string remote_service_name = + std::string remote_service_info_name = socket.GetRemoteWifiLanService().GetName(); auto channel = absl::make_unique( - remote_service_name, socket); - OnIncomingConnection(client, remote_service_name, + remote_service_info_name, socket); + OnIncomingConnection(client, remote_service_info_name, std::move(channel), proto::connections::Medium::WIFI_LAN); }); @@ -632,10 +629,10 @@ proto::connections::Medium P2pClusterPcpHandler::StartWifiLanAdvertising( service_id.c_str(), local_endpoint_id.c_str(), std::string(service_id_hash).c_str(), local_endpoint_name.c_str()); // Generate a WifiLanServiceInfo with which to become WifiLan discoverable. - std::string service_name(WifiLanServiceInfo( + std::string service_info_name(WifiLanServiceInfo( WifiLanServiceInfo::Version::kV1, GetPcp(), local_endpoint_id, service_id_hash, local_endpoint_name)); - if (service_name.empty()) { + if (service_info_name.empty()) { NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartWifiLanAdvertising: generate " "WifiLanServiceInfo failed"); @@ -644,8 +641,8 @@ proto::connections::Medium P2pClusterPcpHandler::StartWifiLanAdvertising( } else { NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartWifiLanAdvertising: generate " - "WifiLanServiceInfo succeeded; service_name=%s", - service_name.c_str()); + "WifiLanServiceInfo succeeded; service_info_name=%s", + service_info_name.c_str()); } NEARBY_LOG( @@ -653,11 +650,11 @@ proto::connections::Medium P2pClusterPcpHandler::StartWifiLanAdvertising( "P2pClusterPcpHandler::StartWifiLanAdvertising: service=%s: come up", service_id.c_str()); - if (!wifi_lan_medium_.StartAdvertising(service_id, service_name)) { + if (!wifi_lan_medium_.StartAdvertising(service_id, service_info_name)) { NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartWifiLanAdvertising: failed to " - "start advertising, service_name=%s", - service_name.c_str()); + "start advertising, service_info_name=%s", + service_info_name.c_str()); wifi_lan_medium_.StopAcceptingConnections(service_id); return proto::connections::UNKNOWN_MEDIUM; } @@ -762,13 +759,6 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::WebRtcConnectImpl( .endpoint_channel = std::move(channel)}; } -mediums::PeerId P2pClusterPcpHandler::CreatePeerIdFromAdvertisement( - const std::string& service_id, const std::string& endpoint_id, - const std::string& endpoint_name) { - std::string seed = absl::StrCat(service_id, endpoint_id, endpoint_name); - return mediums::PeerId::FromSeed(ByteArray(seed)); -} - } // namespace connections } // namespace nearby } // namespace location diff --git a/cpp/core_v2/internal/p2p_cluster_pcp_handler.h b/cpp/core_v2/internal/p2p_cluster_pcp_handler.h index 1fdb8663..c4550604 100644 --- a/cpp/core_v2/internal/p2p_cluster_pcp_handler.h +++ b/cpp/core_v2/internal/p2p_cluster_pcp_handler.h @@ -97,12 +97,6 @@ class P2pClusterPcpHandler : public BasePcpHandler { wifi_lan_service(std::move(service)) {} WifiLanService wifi_lan_service; }; - struct WebRtcEndpoint : public BasePcpHandler::DiscoveredEndpoint { - WebRtcEndpoint(DiscoveredEndpoint endpoint, mediums::PeerId peer_id) - : DiscoveredEndpoint(std::move(endpoint)), - peer_id(std::move(peer_id)) {} - mediums::PeerId peer_id; - }; using BluetoothDiscoveredDeviceCallback = BluetoothClassic::DiscoveredDeviceCallback; @@ -115,7 +109,7 @@ class P2pClusterPcpHandler : public BasePcpHandler { static ByteArray GenerateHash(const std::string& source, size_t size); - // Bluetooth. + // Bluetooth bool IsRecognizedBluetoothEndpoint(const std::string& name_string, const std::string& service_id, const BluetoothDeviceName& name) const; @@ -133,10 +127,10 @@ class P2pClusterPcpHandler : public BasePcpHandler { BasePcpHandler::ConnectImplResult BluetoothConnectImpl( ClientProxy* client, BluetoothEndpoint* endpoint); - // WifiLan. - bool IsRecognizedWifiLanEndpoint(const std::string& name_string, - const std::string& service_id, - const WifiLanServiceInfo& name) const; + // WifiLan + bool IsRecognizedWifiLanEndpoint( + const std::string& service_id, + const WifiLanServiceInfo& service_info) const; std::function MakeWifiLanServiceDiscoveredHandler(ClientProxy* client, const std::string& service_id); @@ -160,9 +154,6 @@ class P2pClusterPcpHandler : public BasePcpHandler { const std::string& local_endpoint_name); BasePcpHandler::ConnectImplResult WebRtcConnectImpl( ClientProxy* client, WebRtcEndpoint* webrtc_endpoint); - mediums::PeerId CreatePeerIdFromAdvertisement(const string& service_id, - const string& endpoint_id, - const string& endpoint_name); BluetoothRadio& bluetooth_radio_; BluetoothClassic& bluetooth_medium_; diff --git a/cpp/core_v2/internal/wifi_lan_endpoint_channel.h b/cpp/core_v2/internal/wifi_lan_endpoint_channel.h index 846acf8d..046473e9 100644 --- a/cpp/core_v2/internal/wifi_lan_endpoint_channel.h +++ b/cpp/core_v2/internal/wifi_lan_endpoint_channel.h @@ -27,7 +27,7 @@ class WifiLanEndpointChannel final : public BaseEndpointChannel { public: // Creates both outgoing and incoming WifiLan channels. WifiLanEndpointChannel(const std::string& channel_name, - WifiLanSocket bluetooth_socket); + WifiLanSocket socket); proto::connections::Medium GetMedium() const override; diff --git a/cpp/core_v2/options.h b/cpp/core_v2/options.h index 064ba2b6..6aead821 100644 --- a/cpp/core_v2/options.h +++ b/cpp/core_v2/options.h @@ -21,10 +21,22 @@ namespace location { namespace nearby { namespace connections { +// Generic type: allows definition of a feature T for every Medium. +template +struct MediumSelector { + T bluetooth; + T web_rtc; + T wifi_lan; +}; + +// Feature On/Off switch for mediums. +using BooleanMediumSelector = MediumSelector; + // Connection Options: used for both Advertising and Discovery. // All fields are mutable, to make the type copy-assignable. struct ConnectionOptions { Strategy strategy; + BooleanMediumSelector allowed; bool auto_upgrade_bandwidth; bool enforce_topology_constraints; // Verify if ConnectionOptions is in a not-initialized (Empty) state. diff --git a/cpp/platform_v2/api/wifi_lan.h b/cpp/platform_v2/api/wifi_lan.h index 6977b56a..2b365172 100644 --- a/cpp/platform_v2/api/wifi_lan.h +++ b/cpp/platform_v2/api/wifi_lan.h @@ -27,7 +27,8 @@ namespace location { namespace nearby { namespace api { -// Opaque wrapper over a WifiLan service which contains encoded service name. +// Opaque wrapper over a WifiLan service which contains packed +// |WifiLanServiceInfo| string name. class WifiLanService { public: virtual ~WifiLanService() = default; @@ -71,10 +72,8 @@ class WifiLanMedium { const std::string& wifi_lan_service_info_name) = 0; virtual bool StopAdvertising(const std::string& service_id) = 0; + // Callback that is invoked when a discovered service is found or lost. struct DiscoveredServiceCallback { - // The WifiLanService* is not owned by callbacks. - // It is passed to give access to its non-const methods. - // It is guaranteed to be valid for the duration of call. std::function service_discovered_cb = diff --git a/cpp/platform_v2/base/medium_environment.cc b/cpp/platform_v2/base/medium_environment.cc index 129b4643..b1e1bcd4 100644 --- a/cpp/platform_v2/base/medium_environment.cc +++ b/cpp/platform_v2/base/medium_environment.cc @@ -36,9 +36,10 @@ MediumEnvironment& MediumEnvironment::Instance() { return *env; } -void MediumEnvironment::Start() { +void MediumEnvironment::Start(EnvironmentConfig config) { if (!enabled_.exchange(true)) { NEARBY_LOG(INFO, "MediumEnvironment::Start()"); + config_ = std::move(config); Reset(); } } @@ -79,6 +80,10 @@ void MediumEnvironment::Sync(bool enable_notifications) { NEARBY_LOG(INFO, "MediumEnvironment::Sync(): done [count=%d]", count); } +const EnvironmentConfig& MediumEnvironment::GetEnvironmentConfig() { + return config_; +} + void MediumEnvironment::OnBluetoothAdapterChangedState( api::BluetoothAdapter& adapter, api::BluetoothDevice& adapter_device, std::string name, bool enabled, api::BluetoothAdapter::ScanMode mode) { @@ -88,7 +93,8 @@ void MediumEnvironment::OnBluetoothAdapterChangedState( NEARBY_LOG(INFO, "[adapter=%p, device=%p] update: name=%s, enabled=%d, mode=%d", &adapter, &adapter_device, name.c_str(), enabled, mode); - for (auto& [medium, info] : bluetooth_mediums_) { + for (auto& medium_info : bluetooth_mediums_) { + auto& info = medium_info.second; // Do not send notification to medium that owns this adapter. if (info.adapter == &adapter) continue; NEARBY_LOG(INFO, "[adapter=%p, device=%p] notify: adapter=%p", &adapter, @@ -167,19 +173,22 @@ void MediumEnvironment::OnWifiLanServiceStateChanged( const std::string& service_id, bool enabled) { if (!enabled_) return; NEARBY_LOG(INFO, - "G3 OnWifiLanServiceStateChanged [service impl=%p]; context=%p, " - "notify=%d", - &info, &service, enable_notifications_.load()); + "G3 OnWifiLanServiceStateChanged [service impl=%p]; context=%p; " + "service_id=%s; notify=%d", + &service, &info, service_id.c_str(), enable_notifications_.load()); if (!enable_notifications_) return; - if (enabled) { - RunOnMediumEnvironmentThread([&info, &service, service_id]() { - info.discovery_callback.service_discovered_cb(service, service_id); - }); - } else { - RunOnMediumEnvironmentThread([&info, &service, service_id]() { - info.discovery_callback.service_lost_cb(service, service_id); - }); - } + RunOnMediumEnvironmentThread([&info, enabled, &service, service_id]() { + auto service_id_context = info.services.find(service_id); + if (service_id_context == info.services.end()) return; + + if (enabled) { + service_id_context->second.discovery_callback.service_discovered_cb( + service, service_id); + } else { + service_id_context->second.discovery_callback.service_lost_cb(service, + service_id); + } + }); } void MediumEnvironment::RunOnMediumEnvironmentThread( @@ -202,7 +211,9 @@ void MediumEnvironment::RegisterBluetoothMedium( auto* owned_adapter = context.adapter; NEARBY_LOG(INFO, "Registered: medium=%p; adapter=%p", &medium, owned_adapter); - for (auto& [adapter, device] : bluetooth_adapters_) { + for (auto& adapter_device : bluetooth_adapters_) { + auto& adapter = adapter_device.first; + auto& device = adapter_device.second; if (adapter == nullptr) continue; OnBluetoothDeviceStateChanged(context, *device, adapter->GetName(), adapter->GetScanMode(), @@ -226,7 +237,9 @@ void MediumEnvironment::UpdateBluetoothMedium( "Updated: this=%p; medium=%p; adapter=%p; name=%s; enabled=%d; mode=%d", this, &medium, owned_adapter, owned_adapter->GetName().c_str(), owned_adapter->IsEnabled(), owned_adapter->GetScanMode()); - for (auto& [adapter, device] : bluetooth_adapters_) { + for (auto& adapter_device : bluetooth_adapters_) { + auto& adapter = adapter_device.first; + auto& device = adapter_device.second; if (adapter == nullptr) continue; OnBluetoothDeviceStateChanged(context, *device, adapter->GetName(), adapter->GetScanMode(), @@ -285,13 +298,10 @@ void MediumEnvironment::SendWebRtcSignalingMessage(absl::string_view peer_id, }); } -void MediumEnvironment::RegisterWifiLanMedium(api::WifiLanMedium& medium, - api::WifiLanService& service) { +void MediumEnvironment::RegisterWifiLanMedium(api::WifiLanMedium& medium) { if (!enabled_) return; - RunOnMediumEnvironmentThread([this, &medium, &service]() { - wifi_lan_mediums_.insert({&medium, WifiLanMediumContext{ - .service = &service, - }}); + RunOnMediumEnvironmentThread([this, &medium]() { + wifi_lan_mediums_.insert({&medium, WifiLanMediumContext{}}); NEARBY_LOG(INFO, "Registered: medium=%p", &medium); }); } @@ -304,18 +314,31 @@ void MediumEnvironment::UpdateWifiLanMediumForAdvertising( enabled]() { auto item = wifi_lan_mediums_.find(&medium); if (item == wifi_lan_mediums_.end()) { - NEARBY_LOG( - INFO, "Update WifiLan medium failed. There is no medium registered."); + NEARBY_LOG(INFO, + "UpdateWifiLanMediumForAdvertising failed. There is no medium " + "registered."); return; } auto& context = item->second; - context.advertising = enabled; - NEARBY_LOG( - INFO, - "Update WifiLan medium for advertising: this=%p; medium=%p; name=%s; " - "enabled=%d; advertising=%d", - this, &medium, service.GetName().c_str(), enabled, context.advertising); - for (auto& [local_medium, info] : wifi_lan_mediums_) { + context.wifi_lan_service = &service; + auto service_id_context = context.services.find(service_id); + if (service_id_context == context.services.end()) { + WifiLanServiceIdContext id_context{ + .advertising = enabled, + }; + context.services.emplace(service_id, std::move(id_context)); + } else { + service_id_context->second.advertising = enabled; + } + NEARBY_LOG(INFO, + "Update WifiLan medium for advertising: this=%p; medium=%p; " + "service_id=%s; name=%s; " + "enabled=%d", + this, &medium, service_id.c_str(), service.GetName().c_str(), + enabled); + for (auto& medium_info : wifi_lan_mediums_) { + auto& local_medium = medium_info.first; + auto& info = medium_info.second; // Do not send notification to the same medium. if (local_medium == &medium) continue; OnWifiLanServiceStateChanged(info, service, service_id, enabled); @@ -324,45 +347,56 @@ void MediumEnvironment::UpdateWifiLanMediumForAdvertising( } void MediumEnvironment::UpdateWifiLanMediumForDiscovery( - api::WifiLanMedium& medium, api::WifiLanService& service, - const std::string& service_id, WifiLanDiscoveredServiceCallback callback, - bool enabled) { + api::WifiLanMedium& medium, const std::string& service_id, + WifiLanDiscoveredServiceCallback callback, bool enabled) { if (!enabled_) return; - RunOnMediumEnvironmentThread([this, &medium, &service, service_id, + RunOnMediumEnvironmentThread([this, &medium, service_id, callback = std::move(callback), enabled]() { auto item = wifi_lan_mediums_.find(&medium); if (item == wifi_lan_mediums_.end()) { - NEARBY_LOG( - INFO, "Update WifiLan medium failed. There is no medium registered."); + NEARBY_LOG(INFO, + "UpdateWifiLanMediumForDiscovery failed. There is no medium " + "registered."); return; } auto& context = item->second; - context.discovery_callback = std::move(callback); - NEARBY_LOG( - INFO, - "Update WifiLan medium for discovery: this=%p; medium=%p; name=%s; " - "enabled=%d; advertising=%d", - this, &medium, service.GetName().c_str(), enabled, context.advertising); - for (auto& [local_medium, info] : wifi_lan_mediums_) { + auto service_id_context = context.services.find(service_id); + if (service_id_context == context.services.end()) { + WifiLanServiceIdContext id_context{ + .discovery_callback = std::move(callback), + }; + context.services.emplace(service_id, std::move(id_context)); + } else { + service_id_context->second.discovery_callback = std::move(callback); + } + NEARBY_LOG(INFO, + "Update WifiLan medium for discovery: this=%p; medium=%p; " + "service_id=%s; enabled=%d; ", + this, &medium, service_id.c_str(), enabled); + for (auto& medium_info : wifi_lan_mediums_) { + auto& local_medium = medium_info.first; + auto& info = medium_info.second; // Do not send notification to the same medium. if (local_medium == &medium) continue; // Search advertising mediums and send notification. - if (info.advertising && enabled) { - OnWifiLanServiceStateChanged(context, *(info.service), service_id, - enabled); + for (auto& service_id_context : info.services) { + auto& service_id = service_id_context.first; + auto& id_context = service_id_context.second; + if (id_context.advertising && enabled) { + OnWifiLanServiceStateChanged(context, *(info.wifi_lan_service), + service_id, enabled); + } } } }); } void MediumEnvironment::UpdateWifiLanMediumForAcceptedConnection( - api::WifiLanMedium& medium, api::WifiLanService& service, - const std::string& service_id, - WifiLanAcceptedConnectionCallback accepted_connection_callback) { + api::WifiLanMedium& medium, const std::string& service_id, + WifiLanAcceptedConnectionCallback callback) { if (!enabled_) return; - RunOnMediumEnvironmentThread([this, &medium, &service, service_id, - accepted_connection_callback = - std::move(accepted_connection_callback)]() { + RunOnMediumEnvironmentThread([this, &medium, service_id, + callback = std::move(callback)]() { auto item = wifi_lan_mediums_.find(&medium); if (item == wifi_lan_mediums_.end()) { NEARBY_LOG( @@ -370,12 +404,20 @@ void MediumEnvironment::UpdateWifiLanMediumForAcceptedConnection( return; } auto& context = item->second; - context.accepted_connection_callback = - std::move(accepted_connection_callback); + auto service_id_context = context.services.find(service_id); + if (service_id_context == context.services.end()) { + WifiLanServiceIdContext id_context{ + .accepted_connection_callback = std::move(callback), + }; + context.services.emplace(service_id, std::move(id_context)); + } else { + service_id_context->second.accepted_connection_callback = + std::move(callback); + } NEARBY_LOG(INFO, "Update WifiLan medium for accepted callback: this=%p; " - "medium=%p; name=%s; ", - this, &medium, service.GetName().c_str()); + "medium=%p; service_id=%s; ", + this, &medium, service_id.c_str()); }); } @@ -401,7 +443,11 @@ void MediumEnvironment::CallWifiLanAcceptedConnectionCallback( return; } auto& info = item->second; - info.accepted_connection_callback.accepted_cb(socket, service_id); + auto service_id_context = info.services.find(service_id); + if (service_id_context != info.services.end()) { + service_id_context->second.accepted_connection_callback.accepted_cb( + socket, service_id); + } }); } diff --git a/cpp/platform_v2/base/medium_environment.h b/cpp/platform_v2/base/medium_environment.h index d9999c44..33637062 100644 --- a/cpp/platform_v2/base/medium_environment.h +++ b/cpp/platform_v2/base/medium_environment.h @@ -29,6 +29,15 @@ namespace location { namespace nearby { +// Environment config that can control availability of certain mediums for +// testing. +struct EnvironmentConfig { + // Control whether WEB_RTC medium is enabled in the environment. + // This is currently set to false, due to http://b/139734036 that would lead + // to flaky tests. + bool webrtc_enabled = false; +}; + // MediumEnvironment is a simulated environment which allows multiple instances // of simulated HW devices to "work" together as if they are physical. // For each medium type it provides necessary methods to implement @@ -44,6 +53,7 @@ class MediumEnvironment { api::WifiLanMedium::DiscoveredServiceCallback; using WifiLanAcceptedConnectionCallback = api::WifiLanMedium::AcceptedConnectionCallback; + MediumEnvironment(const MediumEnvironment&) = delete; MediumEnvironment& operator=(const MediumEnvironment&) = delete; @@ -56,7 +66,7 @@ class MediumEnvironment { // tests that are already using it and relying on it being ON. // Enables Medium environment. - void Start(); + void Start(EnvironmentConfig config = EnvironmentConfig()); // Disables Medium environment. void Stop(); @@ -107,6 +117,8 @@ class MediumEnvironment { // Removes medium-related info. This should correspond to device power off. void UnregisterBluetoothMedium(api::BluetoothClassicMedium& medium); + const EnvironmentConfig& GetEnvironmentConfig(); + // Registers |callback| to receive messages sent to device with id |self_id|. void RegisterWebRtcSignalingMessenger(absl::string_view self_id, OnSignalingMessageCallback callback); @@ -121,8 +133,7 @@ class MediumEnvironment { // Adds medium-related info to allow for discovery/advertising to work. // This provides acccess to this medium from other mediums, when protocol // expects they should communicate. - void RegisterWifiLanMedium(api::WifiLanMedium& medium, - api::WifiLanService& service); + void RegisterWifiLanMedium(api::WifiLanMedium& medium); // Updates advertising info to indicate the current medium is exposing // advertising event. @@ -140,16 +151,14 @@ class MediumEnvironment { // with user-specified callback when discovery is enabled, and with default // (empty) callback otherwise. void UpdateWifiLanMediumForDiscovery( - api::WifiLanMedium& medium, api::WifiLanService& service, - const std::string& service_id, - WifiLanDiscoveredServiceCallback discovery_callback, bool enabled); + api::WifiLanMedium& medium, const std::string& service_id, + WifiLanDiscoveredServiceCallback callback, bool enabled); // Updates Accepted connection callback info to allow for dispatch of // advertising events. void UpdateWifiLanMediumForAcceptedConnection( - api::WifiLanMedium& medium, api::WifiLanService& service, - const std::string& service_id, - WifiLanAcceptedConnectionCallback accepted_connection_callback); + api::WifiLanMedium& medium, const std::string& service_id, + WifiLanAcceptedConnectionCallback callback); // Removes medium-related info. This should correspond to device power off. void UnregisterWifiLanMedium(api::WifiLanMedium& medium); @@ -168,13 +177,17 @@ class MediumEnvironment { absl::flat_hash_map devices; }; - struct WifiLanMediumContext { + struct WifiLanServiceIdContext { WifiLanDiscoveredServiceCallback discovery_callback; WifiLanAcceptedConnectionCallback accepted_connection_callback; - api::WifiLanService* service = nullptr; bool advertising = false; }; + struct WifiLanMediumContext { + api::WifiLanService* wifi_lan_service = nullptr; + absl::flat_hash_map services; + }; + // This is a singleton object, for which destructor will never be called. // Constructor will be invoked once from Instance() static method. // Object is create in-place (with a placement new) to guarantee that @@ -199,6 +212,7 @@ class MediumEnvironment { std::atomic_int job_count_ = 0; std::atomic_bool enable_notifications_ = false; SingleThreadExecutor executor_; + EnvironmentConfig config_; // The following data members are accessed in the context of a private // executor_ thread. diff --git a/cpp/platform_v2/impl/g3/BUILD b/cpp/platform_v2/impl/g3/BUILD index 49342b51..1a76321f 100644 --- a/cpp/platform_v2/impl/g3/BUILD +++ b/cpp/platform_v2/impl/g3/BUILD @@ -119,6 +119,7 @@ cc_library( "//platform_v2/api:comm", "//platform_v2/api:platform", "//platform_v2/api:types", + "//platform_v2/base:test_util", "//platform_v2/impl/shared:file", "//absl/base:core_headers", "//absl/memory", diff --git a/cpp/platform_v2/impl/g3/platform.cc b/cpp/platform_v2/impl/g3/platform.cc index afa3f589..91df6849 100644 --- a/cpp/platform_v2/impl/g3/platform.cc +++ b/cpp/platform_v2/impl/g3/platform.cc @@ -32,6 +32,7 @@ #include "platform_v2/api/submittable_executor.h" #include "platform_v2/api/webrtc.h" #include "platform_v2/api/wifi.h" +#include "platform_v2/base/medium_environment.h" #include "platform_v2/impl/g3/atomic_boolean.h" #include "platform_v2/impl/g3/atomic_reference.h" #include "platform_v2/impl/g3/bluetooth_adapter.h" @@ -147,7 +148,11 @@ std::unique_ptr ImplementationPlatform::CreateWifiLanMedium() { } std::unique_ptr ImplementationPlatform::CreateWebRtcMedium() { - return absl::make_unique(); + if (MediumEnvironment::Instance().GetEnvironmentConfig().webrtc_enabled) { + return absl::make_unique(); + } else { + return nullptr; + } } std::unique_ptr ImplementationPlatform::CreateMutex(Mutex::Mode mode) { diff --git a/cpp/platform_v2/impl/g3/wifi_lan.cc b/cpp/platform_v2/impl/g3/wifi_lan.cc index de214b4a..952d4340 100644 --- a/cpp/platform_v2/impl/g3/wifi_lan.cc +++ b/cpp/platform_v2/impl/g3/wifi_lan.cc @@ -170,7 +170,7 @@ Exception WifiLanServerSocket::DoClose() { WifiLanMedium::WifiLanMedium() { service_.SetMedium(this); auto& env = MediumEnvironment::Instance(); - env.RegisterWifiLanMedium(*this, service_); + env.RegisterWifiLanMedium(*this); } WifiLanMedium::~WifiLanMedium() { @@ -181,7 +181,6 @@ WifiLanMedium::~WifiLanMedium() { StopAdvertising(advertising_info_.service_id); StopDiscovery(discovering_info_.service_id); - accept_loops_runner_.Shutdown(); NEARBY_LOG(INFO, "WifiLanMedium dtor advertising_accept_thread_running_ = %d", acceptance_thread_running_.load()); @@ -195,12 +194,11 @@ WifiLanMedium::~WifiLanMedium() { } } -bool WifiLanMedium::StartAdvertising( - const std::string& service_id, - const std::string& wifi_lan_service_info_name) { +bool WifiLanMedium::StartAdvertising(const std::string& service_id, + const std::string& service_info_name) { NEARBY_LOG(INFO, - "G3 WifiLan StartAdvertising: service_id=%s, service_name=%s", - service_id.c_str(), wifi_lan_service_info_name.c_str()); + "G3 WifiLan StartAdvertising: service_id=%s, service_info_name=%s", + service_id.c_str(), service_info_name.c_str()); auto& env = MediumEnvironment::Instance(); env.UpdateWifiLanMediumForAdvertising(*this, service_, service_id, true); @@ -230,8 +228,9 @@ bool WifiLanMedium::StopAdvertising(const std::string& service_id) { { absl::MutexLock lock(&mutex_); if (advertising_info_.Empty()) { - NEARBY_LOG( - INFO, "Can't stop advertising because we never started advertising."); + NEARBY_LOG(INFO, + "G3 WifiLan StopAdvertising: Can't stop advertising because " + "we never started advertising."); return false; } advertising_info_.Clear(); @@ -241,14 +240,17 @@ bool WifiLanMedium::StopAdvertising(const std::string& service_id) { env.UpdateWifiLanMediumForAdvertising(*this, service_, service_id, false); accept_loops_runner_.Shutdown(); if (server_socket_ == nullptr) { - NEARBY_LOG(ERROR, "Failed to find WifiLan Server socket: service_id=%s", - service_id.c_str()); + NEARBY_LOGS(ERROR) << "G3 WifiLan StopAdvertising: failed to find WifiLan " + "Server socket: service_id=" + << service_id; // Fall through for server socket not found. return true; } if (!server_socket_->Close().Ok()) { - NEARBY_LOG(INFO, "Failed to close WifiLan server socket for %s.", + NEARBY_LOG(INFO, + "G3 WifiLan StopAdvertising: Failed to close WifiLan server " + "socket for %s.", service_id.c_str()); return false; } @@ -261,8 +263,8 @@ bool WifiLanMedium::StartDiscovery(const std::string& service_id, NEARBY_LOG(INFO, "G3 WifiLan StartDiscovery: service_id=%s", service_id.c_str()); auto& env = MediumEnvironment::Instance(); - env.UpdateWifiLanMediumForDiscovery(*this, service_, service_id, - std::move(callback), true); + env.UpdateWifiLanMediumForDiscovery(*this, service_id, std::move(callback), + true); { absl::MutexLock lock(&mutex_); discovering_info_.service_id = service_id; @@ -276,15 +278,16 @@ bool WifiLanMedium::StopDiscovery(const std::string& service_id) { { absl::MutexLock lock(&mutex_); if (discovering_info_.Empty()) { - NEARBY_LOG( - INFO, "Can't stop discovering because we never started discovering."); + NEARBY_LOG(INFO, + "G3 WifiLan StopDiscovery: Can't stop discovering because we " + "never started discovering."); return false; } discovering_info_.Clear(); } auto& env = MediumEnvironment::Instance(); - env.UpdateWifiLanMediumForDiscovery(*this, service_, service_id, {}, false); + env.UpdateWifiLanMediumForDiscovery(*this, service_id, {}, false); return true; } @@ -293,8 +296,7 @@ bool WifiLanMedium::StartAcceptingConnections( NEARBY_LOG(INFO, "G3 WifiLan StartAcceptingConnections: service_id=%s", service_id.c_str()); auto& env = MediumEnvironment::Instance(); - env.UpdateWifiLanMediumForAcceptedConnection(*this, service_, service_id, - callback); + env.UpdateWifiLanMediumForAcceptedConnection(*this, service_id, callback); return true; } @@ -302,7 +304,7 @@ bool WifiLanMedium::StopAcceptingConnections(const std::string& service_id) { NEARBY_LOG(INFO, "G3 WifiLan StopAcceptingConnections: service_id=%s", service_id.c_str()); auto& env = MediumEnvironment::Instance(); - env.UpdateWifiLanMediumForAcceptedConnection(*this, service_, service_id, {}); + env.UpdateWifiLanMediumForAcceptedConnection(*this, service_id, {}); return true; } @@ -315,28 +317,31 @@ std::unique_ptr WifiLanMedium::Connect( if (!medium) return {}; // Can't find medium. Bail out. - WifiLanServerSocket* server_socket = nullptr; + WifiLanServerSocket* remote_server_socket = nullptr; NEARBY_LOG(INFO, "G3 WifiLan Connect [peer]: medium=%p, service=%p, service_id=%s", medium, &remote_service, service_id.c_str()); // Then, find our server socket context in this medium. { absl::MutexLock medium_lock(&medium->mutex_); - server_socket = medium->server_socket_.get(); - if (server_socket == nullptr) { - NEARBY_LOG(ERROR, "Failed to find WifiLan Server socket: service_id=%s", + remote_server_socket = medium->server_socket_.get(); + if (remote_server_socket == nullptr) { + NEARBY_LOG(ERROR, + "G3 WifiLan Connect: Failed to find WifiLan Server socket: " + "service_id=%s", service_id.c_str()); + // Fall through for server socket not found. return {}; } } auto socket = std::make_unique(); // Finally, Request to connect to this socket. - if (!server_socket->Connect(*socket)) { - NEARBY_LOG( - ERROR, - "Failed to connect to existing WifiLan Server socket: service_id=%s", - service_id.c_str()); + if (!remote_server_socket->Connect(*socket)) { + NEARBY_LOG(ERROR, + "G3 WifiLan Connect: Failed to connect to existing WifiLan " + "Server socket: service_id=%s", + service_id.c_str()); return {}; } diff --git a/cpp/platform_v2/impl/g3/wifi_lan.h b/cpp/platform_v2/impl/g3/wifi_lan.h index f6163fc8..81cf364c 100644 --- a/cpp/platform_v2/impl/g3/wifi_lan.h +++ b/cpp/platform_v2/impl/g3/wifi_lan.h @@ -34,21 +34,24 @@ namespace g3 { class WifiLanMedium; -// Opaque wrapper over a WifiLan service which contains encoded WifiLan service -// info name. +// Opaque wrapper over a WifiLan service which contains packed +// |WifiLanServiceInfo| string name. class WifiLanService : public api::WifiLanService { public: - explicit WifiLanService(std::string name) : name_(std::move(name)) {} + explicit WifiLanService(std::string service_info_name) + : service_info_name_(std::move(service_info_name)) {} ~WifiLanService() override = default; - void SetName(std::string name) { name_ = std::move(name); } - std::string GetName() const override { return name_; } + void SetName(std::string service_info_name) { + service_info_name_ = std::move(service_info_name); + } + std::string GetName() const override { return service_info_name_; } void SetMedium(WifiLanMedium* medium) { medium_ = medium; } WifiLanMedium* GetMedium() { return medium_; } private: - std::string name_; + std::string service_info_name_; WifiLanMedium* medium_ = nullptr; }; @@ -165,7 +168,7 @@ class WifiLanMedium : public api::WifiLanMedium { ~WifiLanMedium() override; bool StartAdvertising(const std::string& service_id, - const std::string& wifi_lan_service_info_name) override + const std::string& service_info_name) override ABSL_LOCKS_EXCLUDED(mutex_); bool StopAdvertising(const std::string& service_id) override ABSL_LOCKS_EXCLUDED(mutex_); @@ -215,7 +218,7 @@ class WifiLanMedium : public api::WifiLanMedium { }; absl::Mutex mutex_; - WifiLanService service_{"wifi_lan_service_info_name"}; + WifiLanService service_{"unknown G3 WifiLan service"}; // A thread pool dedicated to running all the accept loops from // StartAdvertising(). @@ -225,8 +228,6 @@ class WifiLanMedium : public api::WifiLanMedium { // A thread pool dedicated to wait to complete the accept_loops_runner_. MultiThreadExecutor close_accept_loops_runner_{kMaxConcurrentAcceptLoops}; - // TODO(edwinwu): Extend it to hashmap to accept multiple sockets for multiple - // entrance. // A server socket is established when start advertising. std::unique_ptr server_socket_; AdvertisingInfo advertising_info_ ABSL_GUARDED_BY(mutex_); diff --git a/cpp/platform_v2/public/wifi_lan.cc b/cpp/platform_v2/public/wifi_lan.cc index 6738f8be..896b3a83 100644 --- a/cpp/platform_v2/public/wifi_lan.cc +++ b/cpp/platform_v2/public/wifi_lan.cc @@ -22,8 +22,8 @@ namespace nearby { bool WifiLanMedium::StartAdvertising( const std::string& service_id, - const std::string& wifi_lan_service_info_name) { - return impl_->StartAdvertising(service_id, wifi_lan_service_info_name); + const std::string& service_info_name) { + return impl_->StartAdvertising(service_id, service_info_name); } bool WifiLanMedium::StopAdvertising(const std::string& service_id) { @@ -48,13 +48,18 @@ bool WifiLanMedium::StartDiscovery(const std::string& service_id, &service, absl::make_unique()); auto& context = *pair.first->second; if (!pair.second) { - NEARBY_LOG(INFO, "Adding (again) service=%p, impl=%p", - &context.service, &service); + NEARBY_LOG(INFO, + "Discovering (again) service=%p, impl=%p, " + "service_info_name=%s", + &context.service, &service, + service.GetName().c_str()); return; } context.service = WifiLanService(&service); - NEARBY_LOG(INFO, "Adding service=%p, impl=%p", &context.service, - &service); + NEARBY_LOG( + INFO, + "Discovering service=%p, impl=%p, service_info_name=%s", + &context.service, &service, service.GetName().c_str()); discovered_service_callback_.service_discovered_cb( context.service, service_id); }, @@ -100,12 +105,13 @@ bool WifiLanMedium::StartAcceptingConnections( &socket, absl::make_unique()); auto& context = *pair.first->second; if (!pair.second) { - NEARBY_LOG(INFO, "Adding (again) socket=%p, impl=%p", + NEARBY_LOG(INFO, "Accepting (again) socket=%p, impl=%p", &context.socket, &socket); context.socket = WifiLanSocket(&socket); + } else { + NEARBY_LOG(INFO, "Accepting socket=%p, impl=%p", + &context.socket, &socket); } - NEARBY_LOG(INFO, "Adding socket=%p, impl=%p", &context.socket, - &socket); accepted_connection_callback_.accepted_cb(context.socket, service_id); }, diff --git a/cpp/platform_v2/public/wifi_lan.h b/cpp/platform_v2/public/wifi_lan.h index 058e6937..45c4f375 100644 --- a/cpp/platform_v2/public/wifi_lan.h +++ b/cpp/platform_v2/public/wifi_lan.h @@ -26,7 +26,8 @@ namespace location { namespace nearby { -// Opaque wrapper over a WifiLan service which contains encoded service name. +// Opaque wrapper over a WifiLan service which contains packed +// |WifiLanServiceInfo| string name. class WifiLanService final { public: WifiLanService() = default; @@ -127,7 +128,7 @@ class WifiLanMedium final { ~WifiLanMedium() = default; bool StartAdvertising(const std::string& service_id, - const std::string& wifi_lan_service_info_name); + const std::string& service_info_name); bool StopAdvertising(const std::string& service_id); // Returns true once the WifiLan discovery has been initiated. diff --git a/proto/error_code_enums.proto b/proto/error_code_enums.proto index 2a3c207b..b5e970cd 100644 --- a/proto/error_code_enums.proto +++ b/proto/error_code_enums.proto @@ -94,6 +94,9 @@ enum CommonError { // the Wi-Fi Direct initialized cause Wi-Fi Aware not available, or BLE // connections hit the maximan number, or Wi-Fi Hotstop already created. OUT_OF_RESOURCE = 4; + // Others error, the error happens when user cancel the flow, it's not a + // real failure. + FLOW_CANCELED = 5; // Reserved 5 to 30 } @@ -155,8 +158,56 @@ enum StartDiscoveringError { START_EXTENDED_DISCOVERING_FAILED = 33; // System error, failed to start discovering. START_DISCOVERING_FAILED = 34; + // Network error, invalid remote target info, discover the nearby devices but + // the information not valid. + INVALID_TARGET_INFO = 35; + // Network error, failed to fetch the advertisement from the remote devices. + FETCH_ADVERTISEMENT_FAILED = 36; + // Network error, failed to fetch the advertisement via GATT from the remote + // devices. + GATT_FETCH_ADVERTISEMENT_FAILED = 37; + // Network error, failed to fetch the advertisement via L2CAP from the remote + // devices. + L2CAP_FETCH_ADVERTISEMENT_FAILED = 38; + // System error, the medium not available when trying to fetch advertisements. + // e.g. fetch advertisements but BT disabled unexpectedly. + NOT_AVAILABLE_TO_FETCH_ADVERTISEMENT = 39; + // System error, failed to acquire WifiAwareSession + ACQUIRE_WIFI_AWARE_SESSION_FOR_DISCOVERING_FAILED = 40; - // Next ID :34 + // Next ID :40 +} + +// The error for event CONNECT. The range between 31 and 99. +enum ConnectError { + // Network error, failed to connect to remote device because we lost the + // target without MAC address to connect to. e.g. BLE cache MAC address in + // medium, it may lost when just try to connect. + UNEXPECT_TARGET_LOST = 31; + // System error, failed to establish connection on GATT + ESTABLISH_GATT_CONNECTION_FAILED = 32; + // System error, failed to establish connection on L2CAP + ESTABLISH_L2CAP_CONNECTION_FAILED = 33; + // Developing error, the MAC address not valid for connecting + INVALID_MAC_ADDRESS = 34; + // Others error, unexpected interrupt when sleep before connect GATT for + // waiting GATT server ready. Should not hapepen, it may be the process be + // killed. + SLEEP_BEFORE_CONNECT_GATT_INTERRUPTED = 35; + // Others error, unexpected interrupt when sleep after GATT connect to wait + // GATT connection ready to transfer data. Should not hapepen, it may be + // the process be killed. + SLEEP_AFTER_GATT_CONNECTED_INTERRUPTED = 36; + // Network error, failed to configure the GATT connection priority, it may + // failed when the connection still wait for the status update from network or + // just a RemoteException. + REQUEST_GATT_CONNECTION_PRIORITY_FAILED = 37; + // Network error, failed to change connection for data transferring on L2CAP + // connection. + L2CAP_SWITCH_TO_DATA_TRANSFERRING_FAILED = 38; + // Network error, failed to change connection for data transferring on GATT + // connection. + GATT_SWITCH_TO_DATA_TRANSFERRING_FAILED = 39; } enum Description { @@ -213,4 +264,25 @@ enum Description { SCAN_FAILED_BLUETOOTH_DISABLED = 49; SCAN_FILTERS_NOT_ALLOWED_FOR_LOCATION = 50; BLUETOOTH_SCAN_REJUVENATE_FAILED = 51; + NULL_BLE_PERIPHERAL = 52; + NULL_BLUETOOTH_GATT = 53; + UNEXPECTED_BLUETOOTH_STATE = 54; + REMOTE_EXCEPTION = 55; + INVALID_BLUETOOTH_SOCKET_STATE_BEFORE_CONNECT = 56; + BLUETOOTH_SOCKET_CLOSED_AFTER_CONNECTED = 57; + INVALID_BLUETOOTH_CHANNEL = 58; + NULL_BLUETOOTH_DEVICE = 59; + NULL_BLUETOOTH_PROXY = 60; + INVALID_PACKET_LENGTH = 61; + INVALID_PACKET_BYTES = 62; + UNEXPECTED_EOF_EXCEPTION = 63; + SOCKET_CLOSED_OR_TIMEOUT = 64; + INVALID_IPV4_ADDRESS = 65; + INVALID_IPV6_ADDRESS = 66; + NULL_ADDRESS = 67; + INVALID_VERSION = 68; + SET_CONNECTION_PRIORITY_FAILED = 69; + SET_CONNECTION_PRIORITY_INTERRUPTED = 70; + UNKNOWN_IO_EXCEPTION = 71; + READ_CHARACTERISTIC_FAILED = 72; } diff --git a/proto/sharing_enums.proto b/proto/sharing_enums.proto index 3eae5009..5a0a06ab 100644 --- a/proto/sharing_enums.proto +++ b/proto/sharing_enums.proto @@ -135,6 +135,18 @@ enum EventType { // Receiver taps a privacy notification. TAP_PRIVACY_NOTIFICATION = 33; + + // Receiver taps a help page. + TAP_HELP = 34; + + // Receiver taps a feedback. + TAP_FEEDBACK = 35; + + // Receiver adds quick settings tile. + ADD_QUICK_SETTINGS_TILE = 36; + + // Receiver removes quick settings tile. + REMOVE_QUICK_SETTINGS_TILE = 37; } // Event category to differentiate whether this comes from sender or receiver,