diff --git a/cpp/core_v2/internal/BUILD b/cpp/core_v2/internal/BUILD index bcb2aa0e..8315217b 100644 --- a/cpp/core_v2/internal/BUILD +++ b/cpp/core_v2/internal/BUILD @@ -141,7 +141,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 ac0da77b..34d95e72 100644 --- a/cpp/core_v2/internal/base_pcp_handler.cc +++ b/cpp/core_v2/internal/base_pcp_handler.cc @@ -288,6 +288,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", @@ -296,9 +297,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", @@ -1054,6 +1077,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 437fbf81..533ec388 100644 --- a/cpp/core_v2/internal/base_pcp_handler.h +++ b/cpp/core_v2/internal/base_pcp_handler.h @@ -10,6 +10,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" @@ -181,6 +182,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; @@ -235,6 +244,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 28894559..e18ff69c 100644 --- a/cpp/core_v2/internal/base_pcp_handler_test.cc +++ b/cpp/core_v2/internal/base_pcp_handler_test.cc @@ -93,11 +93,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 41e10e12..615dd49a 100644 --- a/cpp/core_v2/internal/endpoint_manager.cc +++ b/cpp/core_v2/internal/endpoint_manager.cc @@ -227,7 +227,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 3d761df7..b5ea8194 100644 --- a/cpp/core_v2/internal/endpoint_manager.h +++ b/cpp/core_v2/internal/endpoint_manager.h @@ -81,7 +81,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 3e7587d6..b2b278b8 100644 --- a/cpp/core_v2/internal/mediums/webrtc/BUILD +++ b/cpp/core_v2/internal/mediums/webrtc/BUILD @@ -49,6 +49,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 8087fec5..7a3a859c 100644 --- a/cpp/core_v2/internal/mediums/webrtc/connection_flow_test.cc +++ b/cpp/core_v2/internal/mediums/webrtc/connection_flow_test.cc @@ -5,6 +5,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" @@ -20,6 +21,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(), @@ -29,7 +38,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; @@ -95,7 +104,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( @@ -106,7 +115,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 = @@ -128,7 +137,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( @@ -140,7 +149,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( @@ -155,7 +164,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 9b4f8399..6e450e3d 100644 --- a/cpp/core_v2/internal/mediums/webrtc_test.cc +++ b/cpp/core_v2/internal/mediums/webrtc_test.cc @@ -2,6 +2,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" @@ -13,8 +14,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()); @@ -22,7 +31,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_; @@ -40,7 +49,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"); @@ -54,7 +63,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_; @@ -74,7 +83,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_; @@ -91,7 +100,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"); @@ -135,7 +144,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"); @@ -161,7 +170,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"); @@ -193,7 +202,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 1983137f..019fc0e6 100644 --- a/cpp/core_v2/internal/mediums/wifi_lan.cc +++ b/cpp/core_v2/internal/mediums/wifi_lan.cc @@ -20,10 +20,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."); @@ -36,45 +36,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, @@ -110,7 +110,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; } @@ -138,7 +138,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, @@ -174,7 +174,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; } @@ -188,11 +188,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; } @@ -203,7 +202,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 16884a5d..890b22e8 100644 --- a/cpp/core_v2/internal/mediums/wifi_lan.h +++ b/cpp/core_v2/internal/mediums/wifi_lan.h @@ -9,6 +9,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 { @@ -25,7 +26,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 @@ -33,7 +34,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, @@ -70,31 +71,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 62ab997f..0ca1ee8c 100644 --- a/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc +++ b/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc @@ -233,32 +233,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; } @@ -282,25 +283,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, }, @@ -327,14 +326,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( @@ -344,8 +341,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, }, @@ -597,11 +594,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); }); @@ -618,10 +615,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"); @@ -630,8 +627,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( @@ -639,11 +636,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; } @@ -748,13 +745,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 fc699aae..7b5c4172 100644 --- a/cpp/core_v2/internal/p2p_cluster_pcp_handler.h +++ b/cpp/core_v2/internal/p2p_cluster_pcp_handler.h @@ -83,12 +83,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; @@ -101,7 +95,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; @@ -119,10 +113,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); @@ -146,9 +140,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 6f985fda..52cb6564 100644 --- a/cpp/core_v2/internal/wifi_lan_endpoint_channel.h +++ b/cpp/core_v2/internal/wifi_lan_endpoint_channel.h @@ -13,7 +13,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 d55e41d5..86fe59dc 100644 --- a/cpp/core_v2/options.h +++ b/cpp/core_v2/options.h @@ -7,10 +7,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 49b979a8..10e6cdb2 100644 --- a/cpp/platform_v2/api/wifi_lan.h +++ b/cpp/platform_v2/api/wifi_lan.h @@ -13,7 +13,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; @@ -57,10 +58,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 164af945..8d1cbece 100644 --- a/cpp/platform_v2/base/medium_environment.cc +++ b/cpp/platform_v2/base/medium_environment.cc @@ -22,9 +22,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(); } } @@ -65,6 +66,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) { @@ -74,7 +79,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, @@ -153,19 +159,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( @@ -188,7 +197,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(), @@ -212,7 +223,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(), @@ -271,13 +284,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); }); } @@ -290,18 +300,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); @@ -310,45 +333,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( @@ -356,12 +390,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()); }); } @@ -387,7 +429,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 31fab859..0464a598 100644 --- a/cpp/platform_v2/base/medium_environment.h +++ b/cpp/platform_v2/base/medium_environment.h @@ -15,6 +15,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 @@ -30,6 +39,7 @@ class MediumEnvironment { api::WifiLanMedium::DiscoveredServiceCallback; using WifiLanAcceptedConnectionCallback = api::WifiLanMedium::AcceptedConnectionCallback; + MediumEnvironment(const MediumEnvironment&) = delete; MediumEnvironment& operator=(const MediumEnvironment&) = delete; @@ -42,7 +52,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(); @@ -93,6 +103,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); @@ -107,8 +119,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. @@ -126,16 +137,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); @@ -154,13 +163,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 @@ -185,6 +198,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 9055a604..ae64a943 100644 --- a/cpp/platform_v2/impl/g3/BUILD +++ b/cpp/platform_v2/impl/g3/BUILD @@ -105,6 +105,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 cf5c20f9..31d17c6a 100644 --- a/cpp/platform_v2/impl/g3/platform.cc +++ b/cpp/platform_v2/impl/g3/platform.cc @@ -18,6 +18,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" @@ -133,7 +134,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 1b68f30c..e310c76d 100644 --- a/cpp/platform_v2/impl/g3/wifi_lan.cc +++ b/cpp/platform_v2/impl/g3/wifi_lan.cc @@ -156,7 +156,7 @@ Exception WifiLanServerSocket::DoClose() { WifiLanMedium::WifiLanMedium() { service_.SetMedium(this); auto& env = MediumEnvironment::Instance(); - env.RegisterWifiLanMedium(*this, service_); + env.RegisterWifiLanMedium(*this); } WifiLanMedium::~WifiLanMedium() { @@ -167,7 +167,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()); @@ -181,12 +180,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); @@ -216,8 +214,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(); @@ -227,14 +226,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; } @@ -247,8 +249,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; @@ -262,15 +264,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; } @@ -279,8 +282,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; } @@ -288,7 +290,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; } @@ -301,28 +303,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 45bdfbfd..7bc0e0dd 100644 --- a/cpp/platform_v2/impl/g3/wifi_lan.h +++ b/cpp/platform_v2/impl/g3/wifi_lan.h @@ -20,21 +20,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; }; @@ -151,7 +154,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_); @@ -201,7 +204,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(). @@ -211,8 +214,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 e1894a17..f5882f7e 100644 --- a/cpp/platform_v2/public/wifi_lan.cc +++ b/cpp/platform_v2/public/wifi_lan.cc @@ -8,8 +8,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) { @@ -34,13 +34,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); }, @@ -86,12 +91,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 f2403f04..c94ac1b8 100644 --- a/cpp/platform_v2/public/wifi_lan.h +++ b/cpp/platform_v2/public/wifi_lan.h @@ -12,7 +12,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; @@ -113,7 +114,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 0f463a0b..0464f602 100644 --- a/proto/error_code_enums.proto +++ b/proto/error_code_enums.proto @@ -80,6 +80,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 } @@ -141,8 +144,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 { @@ -199,4 +250,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 32aeee98..962d8e82 100644 --- a/proto/sharing_enums.proto +++ b/proto/sharing_enums.proto @@ -126,6 +126,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,