From 3e5ca324f18c7e54597ab70aae728d2a60b78e38 Mon Sep 17 00:00:00 2001 From: Alexey Polyudov Date: Wed, 24 Jun 2020 18:23:59 -0700 Subject: [PATCH] Roll forward to cl/318180324 Signed-off-by: Alexey Polyudov Change-Id: I3575487805a067fa397ea01c56e8d26c84054f9d --- cpp/core_v2/internal/base_pcp_handler.h | 9 + cpp/core_v2/internal/base_pcp_handler_test.cc | 12 +- cpp/core_v2/internal/bluetooth_device_name.cc | 4 +- cpp/core_v2/internal/mediums/mediums.cc | 2 + cpp/core_v2/internal/mediums/mediums.h | 6 +- cpp/core_v2/internal/mediums/webrtc.cc | 26 +- cpp/core_v2/internal/mediums/webrtc.h | 4 +- .../mediums/webrtc/connection_flow.cc | 6 +- .../internal/mediums/webrtc/connection_flow.h | 2 +- .../mediums/webrtc/connection_flow_test.cc | 4 +- .../internal/p2p_cluster_pcp_handler.cc | 245 +++++++++++++----- .../internal/p2p_cluster_pcp_handler.h | 27 ++ cpp/core_v2/internal/wifi_lan_service_info.cc | 4 +- cpp/platform_v2/base/types.h | 3 +- cpp/platform_v2/public/atomic_reference.h | 10 +- proto/mediums/BUILD | 109 ++++++++ proto/mediums/ble_frames.proto | 53 ++++ .../ble_frames_portable_proto_config.asciipb | 7 + proto/mediums/nfc_frames.proto | 43 +++ proto/mediums/web_rtc_signaling_frames.proto | 108 ++++++++ proto/mediums/wifi_aware_frames.proto | 62 +++++ 21 files changed, 637 insertions(+), 109 deletions(-) create mode 100644 proto/mediums/BUILD create mode 100644 proto/mediums/ble_frames.proto create mode 100644 proto/mediums/ble_frames_portable_proto_config.asciipb create mode 100644 proto/mediums/nfc_frames.proto create mode 100644 proto/mediums/web_rtc_signaling_frames.proto create mode 100644 proto/mediums/wifi_aware_frames.proto diff --git a/cpp/core_v2/internal/base_pcp_handler.h b/cpp/core_v2/internal/base_pcp_handler.h index 77f44117..804ba8a9 100644 --- a/cpp/core_v2/internal/base_pcp_handler.h +++ b/cpp/core_v2/internal/base_pcp_handler.h @@ -178,6 +178,15 @@ class BasePcpHandler : public PcpHandler, // instance (but it can if implementation desires to do so). // BasePcpHandler will hold on to the shared_ptr. struct DiscoveredEndpoint { + DiscoveredEndpoint(std::string endpoint_id, std::string endpoint_name, + std::string service_id, + proto::connections::Medium medium) + : endpoint_id(std::move(endpoint_id)), + endpoint_name(std::move(endpoint_name)), + service_id(std::move(service_id)), + medium(medium) {} + virtual ~DiscoveredEndpoint() = default; + std::string endpoint_id; std::string endpoint_name; std::string service_id; diff --git a/cpp/core_v2/internal/base_pcp_handler_test.cc b/cpp/core_v2/internal/base_pcp_handler_test.cc index 5aa00d54..ac85e21a 100644 --- a/cpp/core_v2/internal/base_pcp_handler_test.cc +++ b/cpp/core_v2/internal/base_pcp_handler_test.cc @@ -138,6 +138,10 @@ class MockContext { }; struct MockDiscoveredEndpoint : public MockPcpHandler::DiscoveredEndpoint { + MockDiscoveredEndpoint(DiscoveredEndpoint endpoint, MockContext context) + : DiscoveredEndpoint(std::move(endpoint)), + context(std::move(context)) {} + MockContext context; }; @@ -276,10 +280,10 @@ class BasePcpHandlerTest : public ::testing::Test { pcp_handler->OnEndpointFound( client, std::make_shared(MockDiscoveredEndpoint{ { - .endpoint_id = endpoint_id, - .endpoint_name = info.name, - .service_id = "service", - .medium = Medium::BLE, + endpoint_id, + info.name, + "service", + Medium::BLE, }, MockContext{flag}, })); diff --git a/cpp/core_v2/internal/bluetooth_device_name.cc b/cpp/core_v2/internal/bluetooth_device_name.cc index 955c8259..8e9a22bd 100644 --- a/cpp/core_v2/internal/bluetooth_device_name.cc +++ b/cpp/core_v2/internal/bluetooth_device_name.cc @@ -48,9 +48,9 @@ BluetoothDeviceName::BluetoothDeviceName(Version version, Pcp pcp, version_ = version; pcp_ = pcp; - endpoint_id_ = endpoint_id; + endpoint_id_ = std::string(endpoint_id); service_id_hash_ = service_id_hash; - endpoint_name_ = endpoint_name; + endpoint_name_ = std::string(endpoint_name); } BluetoothDeviceName::BluetoothDeviceName( diff --git a/cpp/core_v2/internal/mediums/mediums.cc b/cpp/core_v2/internal/mediums/mediums.cc index 8ea5036e..61f19c5c 100644 --- a/cpp/core_v2/internal/mediums/mediums.cc +++ b/cpp/core_v2/internal/mediums/mediums.cc @@ -30,6 +30,8 @@ WifiLan& Mediums::GetWifiLan() { return wifi_lan_; } +mediums::WebRtc& Mediums::GetWebRtc() { return webrtc_; } + } // namespace connections } // namespace nearby } // namespace location diff --git a/cpp/core_v2/internal/mediums/mediums.h b/cpp/core_v2/internal/mediums/mediums.h index 9018ce02..4636b190 100644 --- a/cpp/core_v2/internal/mediums/mediums.h +++ b/cpp/core_v2/internal/mediums/mediums.h @@ -17,9 +17,9 @@ #include "core_v2/internal/mediums/bluetooth_classic.h" #include "core_v2/internal/mediums/bluetooth_radio.h" +#include "core_v2/internal/mediums/webrtc.h" #include "core_v2/internal/mediums/wifi_lan.h" - namespace location { namespace nearby { namespace connections { @@ -39,6 +39,9 @@ class Mediums { // Returns a handle to the Wifi-Lan medium. WifiLan& GetWifiLan(); + // Returns a handle to the WebRtc medium. + mediums::WebRtc& GetWebRtc(); + private: // The order of declaration is critical for both construction and // destruction. @@ -51,6 +54,7 @@ class Mediums { BluetoothRadio bluetooth_radio_; BluetoothClassic bluetooth_classic_{bluetooth_radio_}; WifiLan wifi_lan_; + mediums::WebRtc webrtc_; }; } // namespace connections diff --git a/cpp/core_v2/internal/mediums/webrtc.cc b/cpp/core_v2/internal/mediums/webrtc.cc index 94eb891d..5ba5308a 100644 --- a/cpp/core_v2/internal/mediums/webrtc.cc +++ b/cpp/core_v2/internal/mediums/webrtc.cc @@ -125,14 +125,13 @@ WebRtcSocketWrapper WebRtc::Connect(const PeerId& peer_id) { NEARBY_LOG(INFO, "Attempting to make a WebRTC connection to %s.", peer_id.GetId().c_str()); - std::shared_ptr> socket_future = - ListenForWebRtcSocketFuture(connection_flow_->GetDataChannel(), - AcceptedConnectionCallback()); + Future socket_future = ListenForWebRtcSocketFuture( + connection_flow_->GetDataChannel(), AcceptedConnectionCallback()); // The two devices have discovered each other, hence we have a timeout for // establishing the transport channel. ExceptionOr result = - socket_future->Get(kDataChannelTimeout); + socket_future.Get(kDataChannelTimeout); if (result.ok()) return result.result(); Disconnect(); @@ -163,18 +162,17 @@ void WebRtc::StopAcceptingConnections() { NEARBY_LOG(INFO, "Stopped accepting WebRTC connections"); } -std::shared_ptr> -WebRtc::ListenForWebRtcSocketFuture( - Future>* +Future WebRtc::ListenForWebRtcSocketFuture( + Future> data_channel_future, AcceptedConnectionCallback callback) { - auto socket_future = std::make_shared>(); + Future socket_future; auto data_channel_runnable = [this, socket_future, data_channel_future, - callback{std::move(callback)}]() { + callback{std::move(callback)}]() mutable { // The overall timeout of creating the socket and data channel is controlled // by the caller of this function. ExceptionOr> res = - data_channel_future->Get(); + data_channel_future.Get(); if (res.ok()) { WebRtcSocketWrapper wrapper = CreateWebRtcSocketWrapper(res.result()); callback.accepted_cb(wrapper); @@ -182,15 +180,15 @@ WebRtc::ListenForWebRtcSocketFuture( MutexLock lock(&mutex_); socket_ = wrapper; } - socket_future->Set(wrapper); + socket_future.Set(wrapper); } else { NEARBY_LOG(WARNING, "Failed to get WebRtcSocket."); - socket_future->Set(WebRtcSocketWrapper()); + socket_future.Set(WebRtcSocketWrapper()); } }; - data_channel_future->AddListener(std::move(data_channel_runnable), - &single_thread_executor_); + data_channel_future.AddListener(std::move(data_channel_runnable), + &single_thread_executor_); return socket_future; } diff --git a/cpp/core_v2/internal/mediums/webrtc.h b/cpp/core_v2/internal/mediums/webrtc.h index 6a4e7d7d..e94bcbf4 100644 --- a/cpp/core_v2/internal/mediums/webrtc.h +++ b/cpp/core_v2/internal/mediums/webrtc.h @@ -88,8 +88,8 @@ class WebRtc { bool InitWebRtcFlow(Role role, const PeerId& self_id) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - std::shared_ptr> ListenForWebRtcSocketFuture( - Future>* + Future ListenForWebRtcSocketFuture( + Future> data_channel_future, AcceptedConnectionCallback callback); diff --git a/cpp/core_v2/internal/mediums/webrtc/connection_flow.cc b/cpp/core_v2/internal/mediums/webrtc/connection_flow.cc index 1712b46d..8488ae0b 100644 --- a/cpp/core_v2/internal/mediums/webrtc/connection_flow.cc +++ b/cpp/core_v2/internal/mediums/webrtc/connection_flow.cc @@ -31,6 +31,8 @@ namespace nearby { namespace connections { namespace mediums { +constexpr absl::Duration ConnectionFlow::kTimeout; + namespace { // This is the same as the nearby data channel name. const char kDataChannelName[] = "dataChannel"; @@ -231,9 +233,9 @@ bool ConnectionFlow::OnRemoteIceCandidatesReceived( return true; } -Future>* +Future> ConnectionFlow::GetDataChannel() { - return &data_channel_future_; + return data_channel_future_; } bool ConnectionFlow::Close() { diff --git a/cpp/core_v2/internal/mediums/webrtc/connection_flow.h b/cpp/core_v2/internal/mediums/webrtc/connection_flow.h index 97cd0efc..ad43eb93 100644 --- a/cpp/core_v2/internal/mediums/webrtc/connection_flow.h +++ b/cpp/core_v2/internal/mediums/webrtc/connection_flow.h @@ -101,7 +101,7 @@ class ConnectionFlow { std::vector> ice_candidates) ABSL_LOCKS_EXCLUDED(mutex_); // Get a future for the data channel. - Future>* GetDataChannel(); + Future> GetDataChannel(); // Close the peer connection and data channel. bool Close() ABSL_LOCKS_EXCLUDED(mutex_); 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 8abaf197..d6f80326 100644 --- a/cpp/core_v2/internal/mediums/webrtc/connection_flow_test.cc +++ b/cpp/core_v2/internal/mediums/webrtc/connection_flow_test.cc @@ -94,10 +94,10 @@ TEST(ConnectionFlowTest, SuccessfulOfferAnswerFlow) { // Retrieve Data Channels ExceptionOr> - offerer_channel = offerer->GetDataChannel()->Get(absl::Seconds(1)); + offerer_channel = offerer->GetDataChannel().Get(absl::Seconds(1)); EXPECT_TRUE(offerer_channel.ok()); ExceptionOr> - answerer_channel = answerer->GetDataChannel()->Get(absl::Seconds(1)); + answerer_channel = answerer->GetDataChannel().Get(absl::Seconds(1)); EXPECT_TRUE(answerer_channel.ok()); // Send message on data channel diff --git a/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc b/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc index 55ce75e1..fb7e6348 100644 --- a/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc +++ b/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc @@ -14,8 +14,12 @@ #include "core_v2/internal/p2p_cluster_pcp_handler.h" +#include "core_v2/internal/base_pcp_handler.h" #include "core_v2/internal/bluetooth_endpoint_channel.h" +#include "core_v2/internal/mediums/webrtc/webrtc_socket_wrapper.h" +#include "core_v2/internal/webrtc_endpoint_channel.h" #include "core_v2/internal/wifi_lan_endpoint_channel.h" +#include "platform_v2/base/types.h" #include "platform_v2/public/crypto.h" #include "proto/connections_enums.pb.h" @@ -37,22 +41,24 @@ P2pClusterPcpHandler::P2pClusterPcpHandler( : BasePcpHandler(endpoint_manager, endpoint_channel_manager, pcp), bluetooth_radio_(mediums.GetBluetoothRadio()), bluetooth_medium_(mediums.GetBluetoothClassic()), - wifi_lan_medium_(mediums.GetWifiLan()) {} + wifi_lan_medium_(mediums.GetWifiLan()), + webrtc_medium_(mediums.GetWebRtc()) {} // Returns a vector or mediums sorted in order or decreasing priority for // all the supported mediums. -// NOTE: currently we only have BT, but eventually it will be more, and items -// will have to be sorted in the order of decreasing traffic bandwidth. -// Example: WiFi_LAN, BT, BLE +// Example: WiFi_LAN, WEB_RTC, BT, BLE std::vector P2pClusterPcpHandler::GetConnectionMediumsByPriority() { std::vector mediums; - if (bluetooth_medium_.IsAvailable()) { - mediums.push_back(proto::connections::BLUETOOTH); - } if (wifi_lan_medium_.IsAvailable()) { mediums.push_back(proto::connections::WIFI_LAN); } + if (webrtc_medium_.IsAvailable()) { + mediums.push_back(proto::connections::WEB_RTC); + } + if (bluetooth_medium_.IsAvailable()) { + mediums.push_back(proto::connections::BLUETOOTH); + } return mediums; } @@ -66,16 +72,6 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartAdvertisingImpl( const std::string& local_endpoint_name, const ConnectionOptions& options) { std::vector mediums_started_successfully; - const ByteArray bluetooth_hash = - GenerateHash(service_id, BluetoothDeviceName::kServiceIdHashLength); - proto::connections::Medium bluetooth_medium = - StartBluetoothAdvertising(client, service_id, bluetooth_hash, - local_endpoint_id, local_endpoint_name); - if (bluetooth_medium != proto::connections::UNKNOWN_MEDIUM) { - NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartAdvertisingImpl: BT added"); - mediums_started_successfully.push_back(bluetooth_medium); - } - const ByteArray wifi_lan_hash = GenerateHash(service_id, WifiLanServiceInfo::kServiceIdHashLength); proto::connections::Medium wifi_lan_medium = @@ -87,6 +83,22 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartAdvertisingImpl( mediums_started_successfully.push_back(wifi_lan_medium); } + proto::connections::Medium webrtc_medium = StartListeningForWebRtcConnections( + client, service_id, local_endpoint_id, local_endpoint_name); + if (webrtc_medium != proto::connections::UNKNOWN_MEDIUM) { + mediums_started_successfully.push_back(webrtc_medium); + } + + const ByteArray bluetooth_hash = + GenerateHash(service_id, BluetoothDeviceName::kServiceIdHashLength); + proto::connections::Medium bluetooth_medium = + StartBluetoothAdvertising(client, service_id, bluetooth_hash, + local_endpoint_id, local_endpoint_name); + if (bluetooth_medium != proto::connections::UNKNOWN_MEDIUM) { + NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartAdvertisingImpl: BT added"); + mediums_started_successfully.push_back(bluetooth_medium); + } + if (mediums_started_successfully.empty()) { NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartAdvertisingImpl: not started"); return { @@ -105,9 +117,13 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartAdvertisingImpl( } Status P2pClusterPcpHandler::StopAdvertisingImpl(ClientProxy* client) { - wifi_lan_medium_.StopAdvertising(client->GetAdvertisingServiceId()); bluetooth_medium_.TurnOffDiscoverability(); bluetooth_medium_.StopAcceptingConnections(client->GetAdvertisingServiceId()); + + webrtc_medium_.StopAcceptingConnections(); + + wifi_lan_medium_.StopAdvertising(client->GetAdvertisingServiceId()); + return {Status::kSuccess}; } @@ -177,10 +193,10 @@ P2pClusterPcpHandler::MakeBluetoothDeviceDiscoveredHandler( OnEndpointFound(client, std::make_shared(BluetoothEndpoint{ { - .endpoint_id = device_name.GetEndpointId(), - .endpoint_name = device_name.GetEndpointName(), - .service_id = service_id, - .medium = proto::connections::Medium::BLUETOOTH, + device_name.GetEndpointId(), + device_name.GetEndpointName(), + service_id, + proto::connections::Medium::BLUETOOTH, }, device, })); @@ -217,16 +233,15 @@ P2pClusterPcpHandler::MakeBluetoothDeviceLostHandler( "BT discovery handler (LOST) [client=%p, service=%s]: report " "to client", client, service_id.c_str()); - OnEndpointLost(client, - BluetoothEndpoint{ - { - .endpoint_id = device_name.GetEndpointId(), - .endpoint_name = device_name.GetEndpointName(), - .service_id = service_id, - .medium = proto::connections::Medium::BLUETOOTH, - }, - device, - }); + OnEndpointLost(client, BluetoothEndpoint{ + { + device_name.GetEndpointId(), + device_name.GetEndpointName(), + service_id, + proto::connections::Medium::BLUETOOTH, + }, + device, + }); }); }; } @@ -296,16 +311,15 @@ P2pClusterPcpHandler::MakeWifiLanServiceDiscoveredHandler( "service=%s; id=%s; name=%s", service_id.c_str(), service_name.GetEndpointId().c_str(), service_name.GetEndpointName().c_str()); - OnEndpointFound(client, - std::make_shared(WifiLanEndpoint{ - { - .endpoint_id = service_name.GetEndpointId(), - .endpoint_name = service_name.GetEndpointName(), - .service_id = service_id, - .medium = proto::connections::Medium::WIFI_LAN, - }, - service, - })); + OnEndpointFound(client, std::make_shared(WifiLanEndpoint{ + { + service_name.GetEndpointId(), + service_name.GetEndpointName(), + service_id, + proto::connections::Medium::WIFI_LAN, + }, + service, + })); }); }; } @@ -342,16 +356,15 @@ P2pClusterPcpHandler::MakeWifiLanServiceLostHandler( "WifiLan discovery handler (LOST) [client=%p, service=%s]: report " "to client", client, service_id.c_str()); - OnEndpointLost(client, - WifiLanEndpoint{ - { - .endpoint_id = service_name.GetEndpointId(), - .endpoint_name = service_name.GetEndpointName(), - .service_id = service_id, - .medium = proto::connections::Medium::WIFI_LAN, - }, - service, - }); + OnEndpointLost(client, WifiLanEndpoint{ + { + service_name.GetEndpointId(), + service_name.GetEndpointName(), + service_id, + proto::connections::Medium::WIFI_LAN, + }, + service, + }); }); }; } @@ -361,18 +374,6 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartDiscoveryImpl( const ConnectionOptions& options) { std::vector mediums_started_successfully; - proto::connections::Medium bluetooth_medium = StartBluetoothDiscovery( - { - .device_discovered_cb = - MakeBluetoothDeviceDiscoveredHandler(client, service_id), - .device_lost_cb = MakeBluetoothDeviceLostHandler(client, service_id), - }, - client, service_id); - if (bluetooth_medium != proto::connections::UNKNOWN_MEDIUM) { - NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartDiscoveryImpl: BT added"); - mediums_started_successfully.push_back(bluetooth_medium); - } - proto::connections::Medium wifi_lan_medium = StartWifiLanDiscovery( { .service_discovered_cb = @@ -385,6 +386,18 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartDiscoveryImpl( mediums_started_successfully.push_back(wifi_lan_medium); } + proto::connections::Medium bluetooth_medium = StartBluetoothDiscovery( + { + .device_discovered_cb = + MakeBluetoothDeviceDiscoveredHandler(client, service_id), + .device_lost_cb = MakeBluetoothDeviceLostHandler(client, service_id), + }, + client, service_id); + if (bluetooth_medium != proto::connections::UNKNOWN_MEDIUM) { + NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartDiscoveryImpl: BT added"); + mediums_started_successfully.push_back(bluetooth_medium); + } + if (mediums_started_successfully.empty()) { NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartDiscoveryImpl: nothing added"); return { @@ -406,15 +419,35 @@ Status P2pClusterPcpHandler::StopDiscoveryImpl(ClientProxy* client) { BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::ConnectImpl( ClientProxy* client, BasePcpHandler::DiscoveredEndpoint* endpoint) { - BluetoothEndpoint* bluetooth_endpoint = - static_cast(endpoint); - if (bluetooth_endpoint) { - return BluetoothConnectImpl(client, bluetooth_endpoint); + if (!endpoint) { + return BasePcpHandler::ConnectImplResult{ + .status = {Status::kError}, + }; } - - WifiLanEndpoint* wifi_lan_endpoint = static_cast(endpoint); - if (wifi_lan_endpoint) { - return WifiLanConnectImpl(client, wifi_lan_endpoint); + switch (endpoint->medium) { + case proto::connections::Medium::BLUETOOTH: { + auto* bluetooth_endpoint = down_cast(endpoint); + if (bluetooth_endpoint) { + return BluetoothConnectImpl(client, bluetooth_endpoint); + } + break; + } + case proto::connections::Medium::WIFI_LAN: { + auto* wifi_lan_endpoint = down_cast(endpoint); + if (wifi_lan_endpoint) { + return WifiLanConnectImpl(client, wifi_lan_endpoint); + } + break; + } + case proto::connections::Medium::WEB_RTC: { + auto* webrtc_endpoint = down_cast(endpoint); + if (webrtc_endpoint) { + return WebRtcConnectImpl(client, webrtc_endpoint); + } + break; + } + default: + break; } return BasePcpHandler::ConnectImplResult{ @@ -668,6 +701,74 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::WifiLanConnectImpl( }; } +proto::connections::Medium +P2pClusterPcpHandler::StartListeningForWebRtcConnections( + ClientProxy* client, const string& service_id, + const string& local_endpoint_id, const string& local_endpoint_name) { + if (!webrtc_medium_.IsAvailable()) { + return proto::connections::UNKNOWN_MEDIUM; + } + + if (!webrtc_medium_.IsAcceptingConnections()) { + mediums::PeerId self_id = CreatePeerIdFromAdvertisement( + service_id, local_endpoint_id, local_endpoint_name); + if (!webrtc_medium_.StartAcceptingConnections( + self_id, {[this, client, local_endpoint_name]( + mediums::WebRtcSocketWrapper socket) { + if (!socket.IsValid()) { + NEARBY_LOG(ERROR, "Invalid socket in accept callback: name=%s", + local_endpoint_name.c_str()); + return; + } + + RunOnPcpHandlerThread( + [this, client, socket = std::move(socket)]() { + string remote_device_name = "WebRtcSocket"; + auto channel = absl::make_unique( + remote_device_name, socket); + + OnIncomingConnection(client, remote_device_name, + std::move(channel), + proto::connections::WEB_RTC); + }); + }})) { + return proto::connections::UNKNOWN_MEDIUM; + } + } + + return proto::connections::WEB_RTC; +} + +BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::WebRtcConnectImpl( + ClientProxy* client, WebRtcEndpoint* webrtc_endpoint) { + mediums::WebRtcSocketWrapper socket_wrapper = + webrtc_medium_.Connect(webrtc_endpoint->peer_id); + + if (!socket_wrapper.IsValid()) { + return BasePcpHandler::ConnectImplResult{.status = {Status::kError}}; + } + + auto channel = absl::make_unique( + webrtc_endpoint->endpoint_id, socket_wrapper); + + if (!channel) { + socket_wrapper.Close(); + return BasePcpHandler::ConnectImplResult{.status = {Status::kError}}; + } + + return BasePcpHandler::ConnectImplResult{ + .medium = proto::connections::Medium::WEB_RTC, + .status = {Status::kSuccess}, + .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 25e4757a..1fdb8663 100644 --- a/cpp/core_v2/internal/p2p_cluster_pcp_handler.h +++ b/cpp/core_v2/internal/p2p_cluster_pcp_handler.h @@ -26,6 +26,8 @@ #include "core_v2/internal/endpoint_manager.h" #include "core_v2/internal/mediums/bluetooth_classic.h" #include "core_v2/internal/mediums/mediums.h" +#include "core_v2/internal/mediums/webrtc.h" +#include "core_v2/internal/mediums/webrtc/peer_id.h" #include "core_v2/internal/pcp.h" #include "core_v2/internal/wifi_lan_service_info.h" #include "core_v2/options.h" @@ -83,11 +85,24 @@ class P2pClusterPcpHandler : public BasePcpHandler { private: struct BluetoothEndpoint : public BasePcpHandler::DiscoveredEndpoint { + BluetoothEndpoint(DiscoveredEndpoint endpoint, BluetoothDevice device) + : DiscoveredEndpoint(std::move(endpoint)), + bluetooth_device(std::move(device)) {} + BluetoothDevice bluetooth_device; }; struct WifiLanEndpoint : public BasePcpHandler::DiscoveredEndpoint { + WifiLanEndpoint(DiscoveredEndpoint endpoint, WifiLanService service) + : DiscoveredEndpoint(std::move(endpoint)), + 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; @@ -138,9 +153,21 @@ class P2pClusterPcpHandler : public BasePcpHandler { BasePcpHandler::ConnectImplResult WifiLanConnectImpl( ClientProxy* client, WifiLanEndpoint* endpoint); + // WebRtc + proto::connections::Medium StartListeningForWebRtcConnections( + ClientProxy* client, const std::string& service_id, + const std::string& local_endpoint_id, + 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_; WifiLan& wifi_lan_medium_; + mediums::WebRtc& webrtc_medium_; }; } // namespace connections diff --git a/cpp/core_v2/internal/wifi_lan_service_info.cc b/cpp/core_v2/internal/wifi_lan_service_info.cc index d7c2ad23..5ccce148 100644 --- a/cpp/core_v2/internal/wifi_lan_service_info.cc +++ b/cpp/core_v2/internal/wifi_lan_service_info.cc @@ -49,8 +49,8 @@ WifiLanServiceInfo::WifiLanServiceInfo(Version version, Pcp pcp, version_ = version; pcp_ = pcp; service_id_hash_ = service_id_hash; - endpoint_id_ = endpoint_id; - endpoint_name_ = endpoint_name; + endpoint_id_ = std::string(endpoint_id); + endpoint_name_ = std::string(endpoint_name); } WifiLanServiceInfo::WifiLanServiceInfo(absl::string_view service_info_string) { diff --git a/cpp/platform_v2/base/types.h b/cpp/platform_v2/base/types.h index 5e9db28c..3ea4ea27 100644 --- a/cpp/platform_v2/base/types.h +++ b/cpp/platform_v2/base/types.h @@ -33,7 +33,8 @@ namespace nearby { template inline Derived down_cast(Base* value) { using DerivedType = typename std::remove_pointer::type; - static_assert(std::is_base_of::value); + static_assert(std::is_base_of::value, + "incompatible casting"); return static_cast(value); } diff --git a/cpp/platform_v2/public/atomic_reference.h b/cpp/platform_v2/public/atomic_reference.h index 23d126df..5742724c 100644 --- a/cpp/platform_v2/public/atomic_reference.h +++ b/cpp/platform_v2/public/atomic_reference.h @@ -22,7 +22,6 @@ #include "platform_v2/api/platform.h" #include "platform_v2/public/mutex.h" #include "platform_v2/public/mutex_lock.h" -#include "absl/types/any.h" namespace location { namespace nearby { @@ -34,8 +33,7 @@ class AtomicReference; // Platform-based atomic type, for something convertible to std::uint32_t. template class AtomicReference, - void>> + std::is_trivially_copyable::value>> final { public: using Platform = api::ImplementationPlatform; @@ -56,9 +54,9 @@ class AtomicReference -class AtomicReference sizeof(std::uint32_t) || - !std::is_trivially_copyable_v), - void>> +class AtomicReference sizeof(std::uint32_t) || + !std::is_trivially_copyable::value)>> final { public: explicit AtomicReference(T value) { diff --git a/proto/mediums/BUILD b/proto/mediums/BUILD new file mode 100644 index 00000000..c3cd9367 --- /dev/null +++ b/proto/mediums/BUILD @@ -0,0 +1,109 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//net/proto2/contrib/portable/cc:portable_proto_build_defs.bzl", "portable_proto_library") +load("//tools/build_defs/proto/cpp:cc_proto_library.bzl", "cc_proto_library") + +package(default_visibility = ["//visibility:public"]) + +proto_library( + name = "nfc_frames_proto", + srcs = [ + "nfc_frames.proto", + ], + cc_api_version = 2, +) + +java_lite_proto_library( + name = "nfc_frames_java_proto_lite", + visibility = ["//java/com/google/android/gmscore/integ/modules/nearby/src/com/google/android/gms/nearby/mediums:__subpackages__"], + deps = [":nfc_frames_proto"], +) + +proto_library( + name = "wifi_aware_frames_proto", + srcs = [ + "wifi_aware_frames.proto", + ], + cc_api_version = 2, +) + +java_lite_proto_library( + name = "wifi_aware_frames_java_proto_lite", + visibility = [ + "//java/com/google/android/gmscore/integ/modules/nearby/src/com/google/android/gms/nearby/mediums:__subpackages__", + "//javatests/com/google/android/gmscore/integ/modules/nearby/src/com/google/android/gms/nearby/mediums:__subpackages__", + ], + deps = [":wifi_aware_frames_proto"], +) + +proto_library( + name = "ble_frames_proto", + srcs = [ + "ble_frames.proto", + ], + cc_api_version = 2, +) + +java_lite_proto_library( + name = "ble_frames_java_proto_lite", + visibility = [ + "//java/com/google/android/gmscore/integ/modules/nearby/src/com/google/android/gms/nearby/mediums:__subpackages__", + "//javatests/com/google/android/gmscore/integ/modules/nearby/src/com/google/android/gms/nearby/mediums:__subpackages__", + ], + deps = [":ble_frames_proto"], +) + +proto_library( + name = "web_rtc_signaling_frames_proto", + srcs = [ + "web_rtc_signaling_frames.proto", + ], + cc_api_version = 2, +) + +cc_proto_library( + name = "web_rtc_signaling_frames_cc_proto", + visibility = ["//location/nearby/connections:__subpackages__"], + deps = [":web_rtc_signaling_frames_proto"], +) + +java_lite_proto_library( + name = "web_rtc_signaling_frames_java_proto_lite", + strict_deps = 0, + visibility = [ + "//java/com/google/android/gmscore/integ/modules/nearby/src/com/google/android/gms/nearby/mediums:__subpackages__", + "//javatests/com/google/android/gmscore/integ/modules/nearby/src/com/google/android/gms/nearby/mediums:__subpackages__", + ], + deps = [":web_rtc_signaling_frames_proto"], +) + +portable_proto_library( + name = "ble_frames_portable_proto", + config = ":ble_frames_portable_proto_config", + copts = [ + "-DGOOGLE_PROTOBUF_NO_RTTI=1", + ], + header_outs = [ + "ble_frames.pb.h", + ], + proto_deps = [ + ":ble_frames_proto", + ], +) + +filegroup( + name = "ble_frames_portable_proto_config", + srcs = ["ble_frames_portable_proto_config.asciipb"], +) diff --git a/proto/mediums/ble_frames.proto b/proto/mediums/ble_frames.proto new file mode 100644 index 00000000..864da316 --- /dev/null +++ b/proto/mediums/ble_frames.proto @@ -0,0 +1,53 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto2"; + +package location.nearby.mediums; + +option optimize_for = LITE_RUNTIME; +option java_outer_classname = "BleFramesProto"; +option java_package = "com.google.location.nearby.mediums.proto"; +option objc_class_prefix = "GNCM"; + +// This should map exactly to BleAdvertisement's socket versions. +// TODO(alexanderkang): Make BleAdvertisement reference this proto. +enum SocketVersion { + UNKNOWN_SOCKET_VERSION = 0; + V1 = 1; + V2 = 2; +} + +message SocketControlFrame { + enum ControlFrameType { + UNKNOWN_CONTROL_FRAME_TYPE = 0; + INTRODUCTION = 1; + DISCONNECTION = 2; + } + + optional ControlFrameType type = 1; + + // Exactly one of the following fields will be set. + optional IntroductionFrame introduction = 2; + optional DisconnectionFrame disconnection = 3; +} + +message IntroductionFrame { + optional bytes service_id_hash = 1; + optional SocketVersion socket_version = 2; +} + +message DisconnectionFrame { + optional bytes service_id_hash = 1; +} diff --git a/proto/mediums/ble_frames_portable_proto_config.asciipb b/proto/mediums/ble_frames_portable_proto_config.asciipb new file mode 100644 index 00000000..73e7564b --- /dev/null +++ b/proto/mediums/ble_frames_portable_proto_config.asciipb @@ -0,0 +1,7 @@ +optimize_mode: LITE_RUNTIME + +allowed_enum: "location.nearby.mediums.proto.SocketVersion" +allowed_message: "location.nearby.mediums.proto.SocketControlFrame" +allowed_enum: "location.nearby.mediums.proto.SocketControlFrame.ControlFrameType" +allowed_message: "location.nearby.mediums.proto.IntroductionFrame" +allowed_message: "location.nearby.mediums.proto.DisconnectionFrame" diff --git a/proto/mediums/nfc_frames.proto b/proto/mediums/nfc_frames.proto new file mode 100644 index 00000000..8dcf0183 --- /dev/null +++ b/proto/mediums/nfc_frames.proto @@ -0,0 +1,43 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto2"; + +package location.nearby.mediums; + +option optimize_for = LITE_RUNTIME; +option java_outer_classname = "NfcFramesProto"; +option java_package = "com.google.location.nearby.mediums.proto"; + +// The data to be sent to scanning devices from advertising devices during +// adveritising. +message AdvertisementData { + // The tag in the advertisement. + optional bytes tag = 1; + + // A public key associated with the advertisement. + optional bytes public_key = 2; +} + +// The data to be sent to advertisers from scanning device during discovery. +message AdvertisementRequest { + // Service id of the scanning device. + optional string service_id = 1; + + // Endpoint id of the scanning device. + optional string endpoint_id = 2; + + // Public key from the scanning device. + optional bytes public_key = 3; +} diff --git a/proto/mediums/web_rtc_signaling_frames.proto b/proto/mediums/web_rtc_signaling_frames.proto new file mode 100644 index 00000000..58f8385f --- /dev/null +++ b/proto/mediums/web_rtc_signaling_frames.proto @@ -0,0 +1,108 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto2"; + +package location.nearby.mediums; + +option optimize_for = LITE_RUNTIME; +option java_outer_classname = "WebRtcSignalingFramesProto"; +option java_package = "com.google.location.nearby.mediums.proto"; + +message WebRtcSignalingFrame { + enum FrameType { + UNKNOWN_FRAME_TYPE = 0; + OFFER_TYPE = 1; + ANSWER_TYPE = 2; + ICE_CANDIDATES_TYPE = 3; + READY_FOR_SIGNALING_POKE_TYPE = 4; + } + + optional PeerId sender_id = 1; + + optional FrameType type = 2; + + oneof Frame { + Offer offer = 3; + Answer answer = 4; + IceCandidates ice_candidates = 5; + ReadyForSignalingPoke ready_for_signaling_poke = 6; + } +} + +// The id of the peer who sent the signaling frame. +message PeerId { + optional string id = 1; +} + +// https://en.wikipedia.org/wiki/Session_Description_Protocol +// SDP (Session Description Protocol) is the standard describing a peer-to-peer +// connection. SDP contains the codec, source address, and timing information of +// audio and video. An example message is: +// v=0 +// t=0 0 +// a=group:BUNDLE data +// a=msid-semantic: WMS +// m=application 9 DTLS/SCTP 5000 +// c=IN IP4 0.0.0.0 +// b=AS:30 +// a=ice-ufrag:zaEf +// a=ice-pwd:w9+RrqMj1RbC++15mNcRoRG5 +// a=ice-options:trickle renomination +// a=fingerprint:sha-256 +// B3:FE:B9:E1:F4:58:F6:05:A7:0D:3C:E6:E5:0A:44:A0:88:F4:50:90:41:D6:2E:A3:84:D8:C5:0C:40:2E:DB:6D +// a=setup:active +// a=mid:data +// a=sctpmap:5000 webrtc-datachannel 1024 +// a=candidate:1 1 UDP 2130706431 10.0.1.1 8998 typ host +// a=candidate:2 1 UDP 1694498815 192.0.2.3 45664 typ srflx raddr +message SessionDescription { + // See the SDP example above. + optional string description = 1; +} + +// https://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment +// https://www.slideshare.net/saghul/ice-4414037 +// An example message contains: +// sdp_mid = data +// sdp_m_line_index = 0 +// sdp = candidate:198238137 1 udp 2122262783 +// 620:0:1000:fd1f:1cc5:76e0:78ba:6c54 41539 typ host generation 0 ufrag kq7J +// network-id 4 network-cost 10: +message IceCandidate { + // See the lines beginning with a=candidate in the SDP example above. + optional string sdp = 1; + // For valid values, see https://tools.ietf.org/html/rfc4566 -> Media Types + // This ID uniquely identifies a given media stream with which the candidate + // is associated. Example: data + optional string sdp_mid = 2; + // A zero-based index of the m-line describing the media associated with the + // candidate. Example: 0 + optional int32 sdp_m_line_index = 3; +} + +message IceCandidates { + repeated IceCandidate ice_candidates = 1; +} + +message Offer { + optional SessionDescription session_description = 1; +} + +message Answer { + optional SessionDescription session_description = 1; +} + +// Sent from answerer->offerer once the answerer is ready to receive the offer. +message ReadyForSignalingPoke {} diff --git a/proto/mediums/wifi_aware_frames.proto b/proto/mediums/wifi_aware_frames.proto new file mode 100644 index 00000000..f4b71235 --- /dev/null +++ b/proto/mediums/wifi_aware_frames.proto @@ -0,0 +1,62 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto2"; + +package location.nearby.mediums; + +option optimize_for = LITE_RUNTIME; +option java_outer_classname = "WifiAwareFramesProto"; +option java_package = "com.google.location.nearby.mediums.proto"; + +message WifiAwareFrame { + enum FrameType { + UNKNOWN_FRAME_TYPE = 0; + HOST_NETWORK = 1; + NETWORK_AVAILABLE = 2; + IP_AVAILABLE = 3; + CANCELLATION = 4; + } + optional FrameType type = 1; + + // Exactly one of the following fields will be set. + optional HostNetworkFrame host_network = 2; + optional NetworkAvailableFrame network_available = 3; + optional IpAvailableFrame ip_available = 4; + optional CancellationFrame cancellation = 7; + + // The id of each frame. + optional int32 frame_id = 5; + + // A byte array of size 2. It is the id and comparable token of a WifiAware + // endpoint session. + optional bytes session_id = 6; +} + +message HostNetworkFrame {} + +message NetworkAvailableFrame {} + +message IpAvailableFrame { + // NOTE: We use string here, rather than int. This is because the WiFi Aware + // ip address has a network interface appended to the end. It looks like + // 'fe80::a321:2935:9b2d:d7e7%aware_data0', where the %aware_data0 at the end + // lets Android know which type of network this address is associated with. + // If this information is lost, we won't be able to connect to the remote + // device's ServerSocket. + optional string ip_address = 1; + optional int32 port = 2; +} + +message CancellationFrame {}