diff --git a/Package.swift b/Package.swift index 81150eaa..d96c9aa4 100644 --- a/Package.swift +++ b/Package.swift @@ -345,7 +345,6 @@ let package = Package( "internal/platform/implementation/apple/Mediums/WiFiCommon/BUILD", "internal/platform/implementation/BUILD", "internal/platform/BUILD", - "internal/analytics/BUILD", "internal/flags/BUILD", "internal/network/BUILD", "internal/rpc/BUILD", @@ -369,7 +368,6 @@ let package = Package( "connections/implementation/offline_frames_validator_test.cc", "connections/implementation/service_controller_router_test.cc", "connections/implementation/analytics/analytics_recorder_impl_test.cc", - "connections/implementation/analytics/throughput_recorder_test.cc", "connections/implementation/mediums/advertisements/data_element_test.cc", "connections/implementation/mediums/advertisements/dct_advertisement_test.cc", "connections/implementation/mediums/advertisements/advertisement_util_test.cc", @@ -434,7 +432,6 @@ let package = Package( "internal/encoding/base85_test.cc", "internal/data/leveldb_data_set_test.cc", "internal/flags/nearby_flags_test.cc", - "internal/proto/analytics/connections_log_test.cc", "internal/platform/feature_flags_test.cc", "internal/platform/file_test.cc", "internal/platform/cancelable_alarm_test.cc", @@ -499,7 +496,6 @@ let package = Package( "internal/network/http_client_impl_test.cc", "internal/network/http_status_code_test.cc", "internal/test/fake_clock_test.cc", - "internal/test/fake_webrtc.cc", "internal/test/fake_timer_test.cc", "internal/test/fake_device_info_test.cc", "internal/test/fake_task_runner_test.cc", @@ -521,15 +517,9 @@ let package = Package( "proto", "internal/data/leveldb_data_set_test.proto", // webrtc - "connections/implementation/webrtc_bwu_handler.cc", - "connections/implementation/webrtc_endpoint_channel.cc", - "connections/implementation/mediums/webrtc.cc", - "connections/implementation/mediums/webrtc", - "connections/implementation/mediums/webrtc/tachyon_express_signaling_messenger.cc", - "connections/implementation/mediums/webrtc/tachyon_express_signaling_messenger.h", "internal/platform/implementation/apple/webrtc.h", "internal/platform/implementation/apple/webrtc.mm", - // This breaks the build, but seems to work fine without it? + // Only used in tests "internal/platform/medium_environment.cc", ], sources: [ diff --git a/connections/implementation/mediums/webrtc/BUILD b/connections/implementation/mediums/webrtc/BUILD deleted file mode 100644 index 5b4f0b5b..00000000 --- a/connections/implementation/mediums/webrtc/BUILD +++ /dev/null @@ -1,268 +0,0 @@ -load("@rules_cc//cc:cc_library.bzl", "cc_library") -load("@rules_cc//cc:cc_test.bzl", "cc_test") - -# 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. -licenses(["notice"]) - -cc_library( - name = "webrtc", - hdrs = [ - "data_channel_listener.h", - "local_ice_candidate_listener.h", - "session_description_wrapper.h", - ], - deps = [ - "//connections/implementation/mediums:webrtc_socket", - "//internal/platform:base", - "//third_party/webrtc/files/stable/webrtc/api:jsep", - "@com_google_absl//absl/functional:any_invocable", - ], -) - -cc_library( - name = "connection_flow", - srcs = ["connection_flow.cc"], - hdrs = ["connection_flow.h"], - deps = [ - ":webrtc", - ":webrtc_medium", - ":webrtc_socket_impl", - "//connections/implementation/mediums:webrtc_socket", - "//internal/platform:base", - "//internal/platform:comm", - "//internal/platform:logging", - "//internal/platform:types", - "//third_party/webrtc/files/stable/webrtc/api:data_channel_interface", - "//third_party/webrtc/files/stable/webrtc/api:jsep", - "//third_party/webrtc/files/stable/webrtc/api:libjingle_peerconnection_api", - "//third_party/webrtc/files/stable/webrtc/api:rtc_error", - "//third_party/webrtc/files/stable/webrtc/api:scoped_refptr", - "//third_party/webrtc/files/stable/webrtc/rtc_base:network_constants", - "//third_party/webrtc/files/stable/webrtc/rtc_base:refcount", - "//third_party/webrtc/files/stable/webrtc/rtc_base:threading", - "@com_google_absl//absl/base:core_headers", - "@com_google_absl//absl/functional:any_invocable", - "@com_google_absl//absl/memory", - "@com_google_absl//absl/time", - ], -) - -cc_library( - name = "signaling_frames", - srcs = ["signaling_frames.cc"], - hdrs = ["signaling_frames.h"], - deps = [ - "//connections/implementation/mediums:webrtc_peer_id", - "//internal/platform:base", - "//proto/mediums:web_rtc_signaling_frames_cc_proto", - "//third_party/webrtc/files/stable/webrtc/api:libjingle_peerconnection_api", - ], -) - -cc_library( - name = "webrtc_socket_impl", - srcs = ["webrtc_socket_impl.cc"], - hdrs = ["webrtc_socket_impl.h"], - deps = [ - "//connections/implementation/mediums:webrtc_socket", - "//internal/platform:base", - "//internal/platform:logging", - "//internal/platform:types", - "//third_party/webrtc/files/stable/webrtc/api:data_channel_interface", - "//third_party/webrtc/files/stable/webrtc/api:scoped_refptr", - "@com_google_absl//absl/functional:any_invocable", - "@com_google_absl//absl/strings:string_view", - ], -) - -cc_library( - name = "webrtc_medium", - hdrs = ["webrtc.h"], - deps = [ - "//internal/platform:base", - "//internal/platform/implementation:webrtc_platform", - "//third_party/webrtc/files/stable/webrtc/api:libjingle_peerconnection_api", - "//third_party/webrtc/files/stable/webrtc/rtc_base:network_constants", - "@com_google_absl//absl/strings:string_view", - ], -) - -cc_library( - name = "webrtc_medium_impl", - srcs = ["webrtc_medium_impl.cc"], - hdrs = ["webrtc_medium_impl.h"], - visibility = [ - "//internal/platform/implementation:__subpackages__", - ], - deps = [ - ":tachyon_express_signaling_messenger", - "//internal/platform/implementation:webrtc_platform", - "//third_party/webrtc/files/stable/webrtc/api:create_modular_peer_connection_factory", - "//third_party/webrtc/files/stable/webrtc/api:libjingle_peerconnection_api", - "//third_party/webrtc/files/stable/webrtc/api:rtc_error", - "//third_party/webrtc/files/stable/webrtc/api:scoped_refptr", - "//third_party/webrtc/files/stable/webrtc/rtc_base:threading", - "@com_google_absl//absl/strings:string_view", - ], -) - -cc_library( - name = "webrtc_impl", - srcs = [ - "webrtc_bwu_handler.cc", - "webrtc_endpoint_channel.cc", - "webrtc_impl.cc", - ], - hdrs = [ - "webrtc_bwu_handler.h", - "webrtc_endpoint_channel.h", - "webrtc_impl.h", - ], - visibility = [ - "//connections/implementation/mediums:__pkg__", - ], - deps = [ - ":connection_flow", - ":signaling_frames", - ":webrtc", - ":webrtc_medium", - "//connections:core_types", - "//connections/implementation:bwu_handler", - "//connections/implementation:client_proxy", - "//connections/implementation:endpoint_channel", - "//connections/implementation:offline_frames", - "//connections/implementation/mediums:webrtc", - "//connections/implementation/mediums:webrtc_peer_id", - "//connections/implementation/mediums:webrtc_socket", - "//connections/implementation/proto:offline_wire_formats_cc_proto", - "//internal/platform:base", - "//internal/platform:cancellation_flag", - "//internal/platform:logging", - "//internal/platform:types", - "//internal/platform/implementation:webrtc_platform", - "//proto/mediums:web_rtc_signaling_frames_cc_proto", - "//third_party/webrtc/files/stable/webrtc/api:jsep", - "//third_party/webrtc/files/stable/webrtc/rtc_base:network_constants", - "@com_google_absl//absl/base:core_headers", - "@com_google_absl//absl/base:nullability", - "@com_google_absl//absl/container:flat_hash_map", - "@com_google_absl//absl/container:flat_hash_set", - "@com_google_absl//absl/functional:bind_front", - "@com_google_absl//absl/time", - ], -) - -cc_library( - name = "tachyon_express_signaling_messenger", - srcs = ["tachyon_express_signaling_messenger.cc"], - hdrs = ["tachyon_express_signaling_messenger.h"], - deps = [ - "//internal/account", - "//internal/platform:base", - "//internal/platform:logging", - "//internal/platform:types", - "//internal/platform/implementation:webrtc_platform", - "//internal/proto:messaging_cc_grpc_proto", - "//internal/proto:tachyon_cc_proto", - "//internal/rpc:utils", - "//location/nearby/sharing/lib/account:account_manager", - "//third_party/gloop/util/random:mt_random", - "//third_party/grpc:gpr", - "//third_party/grpc:grpc++", - "//util/random:util", - "@com_google_absl//absl/base:core_headers", - "@com_google_absl//absl/functional:any_invocable", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/synchronization", - "@com_google_absl//absl/time", - ], -) - -cc_library( - name = "fake_webrtc", - testonly = True, - srcs = ["fake_webrtc.cc"], - hdrs = ["fake_webrtc.h"], - deps = [ - ":webrtc_medium", - "//internal/platform:cancellation_flag", - "@com_google_absl//absl/strings:string_view", - ], -) - -cc_test( - name = "webrtc_test", - timeout = "short", - srcs = [ - "connection_flow_test.cc", - "signaling_frames_test.cc", - "webrtc_bwu_handler_test.cc", - "webrtc_impl_test.cc", - "webrtc_socket_impl_test.cc", - ], - shard_count = 16, - tags = [ - "requires-net:external", - ], - deps = [ - ":connection_flow", - ":fake_webrtc", - ":signaling_frames", - ":webrtc", - ":webrtc_impl", - ":webrtc_medium", - ":webrtc_socket_impl", - "//connections/implementation:bwu_handler", - "//connections/implementation:client_proxy", - "//connections/implementation:endpoint_channel", - "//connections/implementation:offline_frames", - "//connections/implementation/mediums:webrtc", - "//connections/implementation/mediums:webrtc_peer_id", - "//connections/implementation/mediums:webrtc_socket", - "//internal/platform:base", - "//internal/platform:cancellation_flag", - "//internal/platform:logging", - "//internal/platform:test_util", - "//internal/platform:types", - "//internal/platform/implementation:platform_impl", - "//third_party/webrtc/files/stable/webrtc/api:data_channel_interface", - "//third_party/webrtc/files/stable/webrtc/api:jsep", - "//third_party/webrtc/files/stable/webrtc/api:scoped_refptr", - "//third_party/webrtc/files/stable/webrtc/rtc_base:network_constants", - "//third_party/webrtc/files/stable/webrtc/rtc_base:refcount", - "@com_github_protobuf_matchers//protobuf-matchers", - "@com_google_absl//absl/strings:string_view", - "@com_google_absl//absl/time", - "@com_google_googletest//:gtest_main", - "@com_google_protobuf//:protobuf", - ], -) - -cc_test( - name = "webrtc_medium_impl_test", - size = "small", - srcs = ["webrtc_medium_impl_test.cc"], - deps = [ - ":webrtc_medium_impl", - "//internal/platform/implementation:platform_impl", - "//internal/platform/implementation:webrtc_platform", - "//third_party/webrtc/files/stable/webrtc/api:data_channel_interface", - "//third_party/webrtc/files/stable/webrtc/api:jsep", - "//third_party/webrtc/files/stable/webrtc/api:peer_connection_interface", - "//third_party/webrtc/files/stable/webrtc/api:scoped_refptr", - "@com_github_protobuf_matchers//protobuf-matchers", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/connections/implementation/mediums/webrtc/README.md b/connections/implementation/mediums/webrtc/README.md deleted file mode 100644 index 27ad4b1b..00000000 --- a/connections/implementation/mediums/webrtc/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# WebRtc support for Nearby Connections - -This directory contains the implementation to support WebRtc in the Nearby -Connection library. - -All dependencies on webrtc MUST be limited to targets in this directory. - -## To Enable WebRtc support - -To enabled WebRtc support undefine the ```NO_WEBRTC``` preprocessor symbol in -the file **connections/implementation/mediums/mediums.cc**. - -When building using bazel, pass the build flag -```--//:enable_webrtc=true``` to set the correct symbol. - -Make sure the binary is linked with an implementation of the -```WebRtcImplementationPlatform```. \ No newline at end of file diff --git a/connections/implementation/mediums/webrtc/connection_flow.cc b/connections/implementation/mediums/webrtc/connection_flow.cc deleted file mode 100644 index d8a2578d..00000000 --- a/connections/implementation/mediums/webrtc/connection_flow.cc +++ /dev/null @@ -1,585 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/connection_flow.h" - -#include -#include -#include -#include - -#include "absl/memory/memory.h" -#include "absl/time/time.h" -#include "connections/implementation/mediums/webrtc/data_channel_listener.h" -#include "connections/implementation/mediums/webrtc/local_ice_candidate_listener.h" -#include "connections/implementation/mediums/webrtc/session_description_wrapper.h" -#include "connections/implementation/mediums/webrtc/webrtc.h" -#include "connections/implementation/mediums/webrtc/webrtc_socket_impl.h" -#include "internal/platform/exception.h" -#include "internal/platform/future.h" -#include "internal/platform/logging.h" -#include "internal/platform/mutex_lock.h" -#include "internal/platform/runnable.h" -#include "webrtc/api/data_channel_interface.h" -#include "webrtc/api/jsep.h" -#include "webrtc/api/peer_connection_interface.h" -#include "webrtc/api/rtc_error.h" -#include "webrtc/api/scoped_refptr.h" -#include "webrtc/api/set_local_description_observer_interface.h" -#include "webrtc/api/set_remote_description_observer_interface.h" -#include "webrtc/rtc_base/ref_counted_object.h" -#include "webrtc/rtc_base/thread.h" - -namespace nearby { -namespace connections { -namespace mediums { - -constexpr absl::Duration ConnectionFlow::kTimeout; -constexpr absl::Duration ConnectionFlow::kPeerConnectionTimeout; - -// This is the same as the nearby data channel name. -constexpr char kDataChannelName[] = "dataChannel"; - -class CreateSessionDescriptionObserverImpl - : public webrtc::CreateSessionDescriptionObserver { - public: - CreateSessionDescriptionObserverImpl( - ConnectionFlow* connection_flow, - Future settable_future, - ConnectionFlow::State expected_entry_state, - ConnectionFlow::State exit_state) - : connection_flow_{connection_flow}, - settable_future_{settable_future}, - expected_entry_state_{expected_entry_state}, - exit_state_{exit_state} {} - - // webrtc::CreateSessionDescriptionObserver - void OnSuccess(webrtc::SessionDescriptionInterface* desc) override { - if (connection_flow_->TransitionState(expected_entry_state_, exit_state_)) { - settable_future_.Set(SessionDescriptionWrapper{desc}); - } else { - settable_future_.SetException({Exception::kFailed}); - } - } - - void OnFailure(webrtc::RTCError error) override { - LOG(ERROR) << "Error when creating session description: " - << error.message(); - settable_future_.SetException({Exception::kFailed}); - } - - private: - ConnectionFlow* connection_flow_; - Future settable_future_; - ConnectionFlow::State expected_entry_state_; - ConnectionFlow::State exit_state_; -}; - -class SetDescriptionObserverBase { - public: - ExceptionOr GetResult(absl::Duration timeout) { - return settable_future_.Get(timeout); - } - - protected: - void OnSetDescriptionComplete(webrtc::RTCError error) { - // On success, |error.ok()| is true. - if (error.ok()) { - settable_future_.Set(true); - return; - } - settable_future_.SetException({Exception::kFailed}); - } - - private: - Future settable_future_; -}; - -class SetLocalDescriptionObserver - : public webrtc::SetLocalDescriptionObserverInterface, - public SetDescriptionObserverBase { - public: - void OnSetLocalDescriptionComplete(webrtc::RTCError error) override { - OnSetDescriptionComplete(error); - } -}; - -class SetRemoteDescriptionObserver - : public webrtc::SetRemoteDescriptionObserverInterface, - public SetDescriptionObserverBase { - public: - void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override { - OnSetDescriptionComplete(error); - } -}; - -using PeerConnectionState = - webrtc::PeerConnectionInterface::PeerConnectionState; - -std::unique_ptr ConnectionFlow::Create( - LocalIceCandidateListener local_ice_candidate_listener, - DataChannelListener data_channel_listener, - AdapterTypeListener adapter_type_listener, WebRtcMedium& webrtc_medium) { - auto connection_flow = absl::WrapUnique(new ConnectionFlow( - std::move(local_ice_candidate_listener), std::move(data_channel_listener), - std::move(adapter_type_listener))); - if (connection_flow->InitPeerConnection(webrtc_medium)) { - return connection_flow; - } - - return nullptr; -} - -ConnectionFlow::ConnectionFlow( - LocalIceCandidateListener local_ice_candidate_listener, - DataChannelListener data_channel_listener, - AdapterTypeListener adapter_type_listener) - : data_channel_listener_(std::move(data_channel_listener)), - local_ice_candidate_listener_(std::move(local_ice_candidate_listener)), - adapter_type_listener_(std::move(adapter_type_listener)) {} - -ConnectionFlow::~ConnectionFlow() { - LOG(INFO) << "~ConnectionFlow"; - RunOnSignalingThread([this] { CloseOnSignalingThread(); }); - shutdown_latch_.Await(); - LOG(INFO) << "~ConnectionFlow done"; -} - -SessionDescriptionWrapper ConnectionFlow::CreateOffer() { - CHECK(!IsRunningOnSignalingThread()); - Future success_future; - if (!RunOnSignalingThread([this, success_future] { - CreateOfferOnSignalingThread(success_future); - })) { - LOG(ERROR) << "Failed to create offer"; - return SessionDescriptionWrapper(); - } - ExceptionOr result = success_future.Get(kTimeout); - if (result.ok()) { - return std::move(result.result()); - } - LOG(ERROR) << "Failed to create offer: " << result.exception(); - return SessionDescriptionWrapper(); -} - -void ConnectionFlow::CreateOfferOnSignalingThread( - Future success_future) { - if (!TransitionState(State::kInitialized, State::kCreatingOffer)) { - success_future.SetException({Exception::kFailed}); - return; - } - webrtc::DataChannelInit data_channel_init; - data_channel_init.reliable = true; - auto pc = GetPeerConnection(); - auto result = - pc->CreateDataChannelOrError(kDataChannelName, &data_channel_init); - if (!result.ok()) { - success_future.SetException({Exception::kFailed}); - return; - } - CreateSocketFromDataChannel(result.MoveValue()); - - webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options; - webrtc::scoped_refptr observer( - new webrtc::RefCountedObject( - this, success_future, State::kCreatingOffer, - State::kWaitingForAnswer)); - pc->CreateOffer(observer.get(), options); -} - -SessionDescriptionWrapper ConnectionFlow::CreateAnswer() { - CHECK(!IsRunningOnSignalingThread()); - Future success_future; - if (!RunOnSignalingThread([this, success_future] { - CreateAnswerOnSignalingThread(success_future); - })) { - LOG(ERROR) << "Failed to create answer"; - return SessionDescriptionWrapper(); - } - ExceptionOr result = success_future.Get(kTimeout); - if (result.ok()) { - return std::move(result.result()); - } - LOG(ERROR) << "Failed to create answer: " << result.exception(); - return SessionDescriptionWrapper(); -} - -void ConnectionFlow::CreateAnswerOnSignalingThread( - Future success_future) { - if (!TransitionState(State::kReceivedOffer, State::kCreatingAnswer)) { - success_future.SetException({Exception::kFailed}); - return; - } - webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options; - webrtc::scoped_refptr observer( - new webrtc::RefCountedObject( - this, success_future, State::kCreatingAnswer, - State::kWaitingToConnect)); - auto pc = GetPeerConnection(); - pc->CreateAnswer(observer.get(), options); -} - -bool ConnectionFlow::SetLocalSessionDescription(SessionDescriptionWrapper sdp) { - CHECK(!IsRunningOnSignalingThread()); - if (!sdp.IsValid()) return false; - - webrtc::scoped_refptr observer( - new webrtc::RefCountedObject()); - - if (!RunOnSignalingThread([this, observer, sdp = std::move(sdp)]() mutable { - if (state_ == State::kEnded) { - observer->OnSetLocalDescriptionComplete( - webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE)); - return; - } - auto pc = GetPeerConnection(); - - pc->SetLocalDescription( - std::unique_ptr(sdp.Release()), - observer); - })) { - return false; - } - - ExceptionOr result = observer->GetResult(kTimeout); - bool success = result.ok() && result.result(); - if (!success) { - LOG(ERROR) << "Failed to set local session description: " - << result.exception(); - } - return success; -} - -bool ConnectionFlow::SetRemoteSessionDescription(SessionDescriptionWrapper sdp, - State expected_entry_state, - State exit_state) { - if (!sdp.IsValid()) return false; - - webrtc::scoped_refptr observer( - new webrtc::RefCountedObject()); - - if (!RunOnSignalingThread([this, observer, sdp = std::move(sdp), - expected_entry_state, exit_state]() mutable { - if (!TransitionState(expected_entry_state, exit_state)) { - observer->OnSetRemoteDescriptionComplete( - webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE)); - return; - } - auto pc = GetPeerConnection(); - - pc->SetRemoteDescription( - std::unique_ptr(sdp.Release()), - observer); - })) { - return false; - } - - ExceptionOr result = observer->GetResult(kTimeout); - bool success = result.ok() && result.result(); - if (!success) { - LOG(ERROR) << "Failed to set remote description: " << result.exception(); - } - return success; -} - -bool ConnectionFlow::OnOfferReceived(SessionDescriptionWrapper offer) { - CHECK(!IsRunningOnSignalingThread()); - return SetRemoteSessionDescription(std::move(offer), State::kInitialized, - State::kReceivedOffer); -} - -bool ConnectionFlow::OnAnswerReceived(SessionDescriptionWrapper answer) { - CHECK(!IsRunningOnSignalingThread()); - return SetRemoteSessionDescription( - std::move(answer), State::kWaitingForAnswer, State::kWaitingToConnect); -} - -bool ConnectionFlow::OnRemoteIceCandidatesReceived( - std::vector> ice_candidates) { - CHECK(!IsRunningOnSignalingThread()); - // We can't call RunOnSignalingThread because C++ wants to copy ice_candidates - // if we try. unique_ptr is not CopyConstructible and compilation fails. - auto pc = GetPeerConnection(); - - if (!pc) { - return false; - } - pc->signaling_thread()->PostTask( - [this, can_run_tasks = std::weak_ptr(can_run_tasks_), - candidates = std::move(ice_candidates)]() mutable { - // Don't run the task if the weak_ptr is no longer valid. - if (!can_run_tasks.lock()) { - return; - } - AddIceCandidatesOnSignalingThread(std::move(candidates)); - }); - return true; -} - -void ConnectionFlow::AddIceCandidatesOnSignalingThread( - std::vector> ice_candidates) { - CHECK(IsRunningOnSignalingThread()); - if (state_ == State::kEnded) { - LOG(WARNING) << "You cannot add ice candidates to a disconnected session."; - return; - } - if (state_ != State::kWaitingToConnect && state_ != State::kConnected) { - cached_remote_ice_candidates_.insert( - cached_remote_ice_candidates_.end(), - std::make_move_iterator(ice_candidates.begin()), - std::make_move_iterator(ice_candidates.end())); - return; - } - auto pc = GetPeerConnection(); - for (auto&& ice_candidate : ice_candidates) { - if (!pc->AddIceCandidate(ice_candidate.get())) { - LOG(WARNING) << "Unable to add remote ice candidate."; - } - } -} - -bool ConnectionFlow::CloseIfNotConnected() { - CHECK(!IsRunningOnSignalingThread()); - Future closed; - if (RunOnSignalingThread([this, closed]() mutable { - if (state_ == State::kConnected) { - closed.Set(false); - } else { - CloseOnSignalingThread(); - closed.Set(true); - } - })) { - auto result = closed.Get(); - return result.ok() && result.result(); - } - return true; -} - -bool ConnectionFlow::InitPeerConnection(WebRtcMedium& webrtc_medium) { - Future success_future; - // CreatePeerConnection callback may be invoked after ConnectionFlow lifetime - // has ended, in case of a timeout. Future is captured by value, and is safe - // to access, but it is not safe to access ConnectionFlow member variables - // unless the Future::Set() returns true. - webrtc_medium.CreatePeerConnection( - this, [this, success_future]( - webrtc::scoped_refptr - peer_connection) mutable { - if (!peer_connection) { - success_future.Set(false); - return; - } - - // If this fails, means we have already assigned something to - // success_future; it is either: - // 1) this is the 2nd call of this callback (and this is a bug), or - // 2) Get(timeout) has set the future value as exception already. - if (success_future.IsSet()) return; - MutexLock lock(&mutex_); - peer_connection_ = peer_connection; - signaling_thread_for_dcheck_only_ = - peer_connection_->signaling_thread(); - success_future.Set(true); - }); - - ExceptionOr result = success_future.Get(kPeerConnectionTimeout); - bool success = result.ok() && result.result(); - if (!success) { - shutdown_latch_.CountDown(); - LOG(ERROR) << "Failed to create peer connection: " << result.exception(); - } - return success; -} - -void ConnectionFlow::OnSignalingStable() { - if (state_ != State::kWaitingToConnect && state_ != State::kConnected) return; - auto pc = GetPeerConnection(); - for (auto&& ice_candidate : cached_remote_ice_candidates_) { - if (!pc->AddIceCandidate(ice_candidate.get())) { - LOG(WARNING) << "Unable to add remote ice candidate."; - } - } - cached_remote_ice_candidates_.clear(); -} - -void ConnectionFlow::CreateSocketFromDataChannel( - webrtc::scoped_refptr data_channel) { - LOG(INFO) << "Creating data channel socket"; - auto socket = std::make_shared("WebRtcSocket", - std::move(data_channel)); - socket_ = socket; - socket->SetSocketListener({ - .socket_ready_cb = {[this](WebRtcSocketImpl* socket) { - CHECK(IsRunningOnSignalingThread()); - if (!TransitionState(State::kWaitingToConnect, State::kConnected)) { - LOG(ERROR) << "Data channel socket is open but connection " - "flow was not in the required state"; - socket->Close(); - return; - } - // Pass socket wrapper by copy on purpose - data_channel_listener_.data_channel_open_cb(socket_); - }}, - .socket_closed_cb = - [this](WebRtcSocketImpl*) { - data_channel_listener_.data_channel_closed_cb(); - }, - }); -} - -void ConnectionFlow::OnIceCandidate(const webrtc::IceCandidate* candidate) { - CHECK(IsRunningOnSignalingThread()); - local_ice_candidate_listener_.local_ice_candidate_found_cb(candidate); -} - -void ConnectionFlow::OnSignalingChange( - webrtc::PeerConnectionInterface::SignalingState new_state) { - LOG(INFO) << "OnSignalingChange: " << new_state; - CHECK(IsRunningOnSignalingThread()); - if (new_state == webrtc::PeerConnectionInterface::SignalingState::kStable) { - OnSignalingStable(); - } -} - -void ConnectionFlow::OnDataChannel( - webrtc::scoped_refptr data_channel) { - LOG(INFO) << "OnDataChannel"; - CHECK(IsRunningOnSignalingThread()); - CreateSocketFromDataChannel(std::move(data_channel)); -} - -void ConnectionFlow::OnIceGatheringChange( - webrtc::PeerConnectionInterface::IceGatheringState new_state) { - LOG(INFO) << "OnIceGatheringChange: " << new_state; - CHECK(IsRunningOnSignalingThread()); -} - -void ConnectionFlow::OnConnectionChange( - webrtc::PeerConnectionInterface::PeerConnectionState new_state) { - LOG(INFO) << "OnConnectionChange: " << static_cast(new_state); - CHECK(IsRunningOnSignalingThread()); - if (new_state == PeerConnectionState::kClosed || - new_state == PeerConnectionState::kFailed || - new_state == PeerConnectionState::kDisconnected) { - LOG(INFO) << "Closing due to peer connection state change: " - << static_cast(new_state); - CloseOnSignalingThread(); - } -} - -void ConnectionFlow::OnRenegotiationNeeded() { - LOG(INFO) << "OnRenegotiationNeeded"; - CHECK(IsRunningOnSignalingThread()); -} - -void ConnectionFlow::OnIceSelectedCandidatePairChanged( - const webrtc::CandidatePairChangeEvent& event) { - LOG(INFO) << "OnIceSelectedCandidatePairChanged"; - CHECK(IsRunningOnSignalingThread()); - // TODO(edwinwu) - Implement the unit test for this. We should be able to get - // the adapter type from the PeerConnection. - adapter_type_listener_.adapter_type_changed_cb( - event.selected_candidate_pair.local_candidate().network_type()); -} - -bool ConnectionFlow::TransitionState(State current_state, State new_state) { - CHECK(IsRunningOnSignalingThread()); - if (current_state != state_) { - LOG(WARNING) << "Invalid state transition to " - << static_cast(new_state) << ": current state is " - << static_cast(state_) << " but expected " - << static_cast(current_state); - return false; - } - LOG(INFO) << "Transition: " << static_cast(state_) << "->" - << static_cast(new_state); - state_ = new_state; - return true; -} - -bool ConnectionFlow::CloseOnSignalingThread() { - if (state_ == State::kEnded) { - return false; - } - state_ = State::kEnded; - // Close the socket wrapper before terminating the PeerConnection - // since the teardown process of the PC may close threads that are - // otherwise depended upon by objects kept alive by the socket_wrapper. - if (socket_ && socket_->IsValid()) socket_->Close(); - - // This prevents other tasks from queuing on the signaling thread for this - // object. - auto pc = GetAndResetPeerConnection(); - - LOG(INFO) << "Closing WebRTC peer connection."; - // NOTE: Closing the peer connection will close the data channel and thus the - // socket implicitly. - if (pc) pc->Close(); - LOG(INFO) << "Closed WebRTC peer connection."; - // Prevent any already queued tasks from running on the signaling thread - can_run_tasks_.reset(); - // If anyone was waiting for shutdown to be done let them know. - shutdown_latch_.CountDown(); - return true; -} - -bool ConnectionFlow::RunOnSignalingThread(Runnable&& runnable) { - CHECK(!IsRunningOnSignalingThread()); - auto pc = GetPeerConnection(); - if (!pc) { - LOG(WARNING) << "Peer connection not available. Cannot schedule tasks."; - return false; - } - // We are off signaling thread, so we can't use peer connection's methods - // but we can access the signaling thread handle. - pc->signaling_thread()->PostTask( - [can_run_tasks = std::weak_ptr(can_run_tasks_), - task = std::move(runnable)]() mutable { - // Don't run the task if the weak_ptr is no longer valid. - // shared_ptr |can_run_tasks_| is destroyed on the same thread - // (signaling thread). This guarantees that if the weak_ptr is valid - // when this task starts, it will stay valid until the task ends. - if (!can_run_tasks.lock()) { - LOG(INFO) << "Peer connection already closed. Cannot run tasks."; - return; - } - task(); - }); - return true; -} - -bool ConnectionFlow::IsRunningOnSignalingThread() { - return signaling_thread_for_dcheck_only_ != nullptr && - signaling_thread_for_dcheck_only_ == webrtc::Thread::Current(); -} - -webrtc::scoped_refptr -ConnectionFlow::GetPeerConnection() { - // We must use a mutex to ensure that peer connection is - // fully initialized. - // We increase the peer_connection_'s refcount to keep it - // alive while we use it. - MutexLock lock(&mutex_); - return peer_connection_; -} - -webrtc::scoped_refptr -ConnectionFlow::GetAndResetPeerConnection() { - MutexLock lock(&mutex_); - return std::move(peer_connection_); -} - -} // namespace mediums -} // namespace connections -} // namespace nearby diff --git a/connections/implementation/mediums/webrtc/connection_flow.h b/connections/implementation/mediums/webrtc/connection_flow.h deleted file mode 100644 index 01c808c1..00000000 --- a/connections/implementation/mediums/webrtc/connection_flow.h +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_CONNECTION_FLOW_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_CONNECTION_FLOW_H_ - -#include -#include - -#include "absl/base/thread_annotations.h" -#include "absl/functional/any_invocable.h" -#include "absl/time/time.h" -#include "connections/implementation/mediums/webrtc/data_channel_listener.h" -#include "connections/implementation/mediums/webrtc/local_ice_candidate_listener.h" -#include "connections/implementation/mediums/webrtc/session_description_wrapper.h" -#include "connections/implementation/mediums/webrtc/webrtc.h" -#include "connections/implementation/mediums/webrtc_socket.h" -#include "internal/platform/count_down_latch.h" -#include "internal/platform/future.h" -#include "internal/platform/listeners.h" -#include "internal/platform/mutex.h" -#include "internal/platform/runnable.h" -#include "webrtc/api/data_channel_interface.h" -#include "webrtc/api/jsep.h" -#include "webrtc/api/peer_connection_interface.h" -#include "webrtc/api/scoped_refptr.h" -#include "webrtc/rtc_base/network_constants.h" - -namespace nearby { -namespace connections { -namespace mediums { - -/** - * Flow for an offerer: - * - *
    - *
  • INITIALIZED: After construction. - *
  • CREATING_OFFER: After CreateOffer(). Local ice candidate collection - * begins. - *
  • WAITING_FOR_ANSWER: Until the remote peer sends their answer. - *
  • WAITING_TO_CONNECT: Until the data channel actually connects. Remote - * ice candidates should be added with OnRemoteIceCandidatesReceived as they are - * gathered. - *
  • CONNECTED: We successfully connected to the remote data - * channel. - *
  • ENDED: The final state that can occur from any of the previous - * states if we disconnect at any point in the flow. - *
- * - *

Flow for an answerer: - * - *

    - *
  • INITIALIZED: After construction. - *
  • RECEIVED_OFFER: After onOfferReceived(). - *
  • CREATING_ANSWER: After CreateAnswer(). Local ice candidate collection - * begins. - *
  • WAITING_TO_CONNECT: Until the data channel actually connects. - * Remote ice candidates should be added with OnRemoteIceCandidatesReceived as - * they are gathered. - *
  • CONNECTED: We successfully connected to the remote - * data channel. - *
  • ENDED: The final state that can occur from any of the - * previous states if we disconnect at any point in the flow. - *
- */ -class ConnectionFlow : public webrtc::PeerConnectionObserver { - public: - enum class State { - kInitialized, - kCreatingOffer, - kWaitingForAnswer, - kReceivedOffer, - kCreatingAnswer, - kWaitingToConnect, - kConnected, - kEnded, - }; - - struct AdapterTypeListener { - absl::AnyInvocable - adapter_type_changed_cb = DefaultCallback(); - }; - - // This method blocks on the creation of the peer connection object. - // Can be called on any thread but never called on signaling thread. - static std::unique_ptr Create( - LocalIceCandidateListener local_ice_candidate_listener, - DataChannelListener data_channel_listener, - AdapterTypeListener adapter_type_listener, WebRtcMedium& webrtc_medium); - ~ConnectionFlow() override; - - // Create the offer that will be sent to the remote. Mirrors the behaviour of - // PeerConnectionInterface::CreateOffer. - // Can be called on any thread but never called on signaling thread. - SessionDescriptionWrapper CreateOffer() ABSL_LOCKS_EXCLUDED(mutex_); - // Create the answer that will be sent to the remote. Mirrors the behaviour of - // PeerConnectionInterface::CreateAnswer. - // Can be called on any thread but never called on signaling thread. - SessionDescriptionWrapper CreateAnswer() ABSL_LOCKS_EXCLUDED(mutex_); - // Set the local session description. |sdp| was created via CreateOffer() - // or CreateAnswer(). - // Can be called on any thread but never called on signaling thread. - bool SetLocalSessionDescription(SessionDescriptionWrapper sdp) - ABSL_LOCKS_EXCLUDED(mutex_); - // Invoked when an offer was received from a remote; this will set the remote - // session description on the peer connection. Returns true if the offer was - // successfully set as remote session description. - // Can be called on any thread but never called on signaling thread. - bool OnOfferReceived(SessionDescriptionWrapper offer) - ABSL_LOCKS_EXCLUDED(mutex_); - // Invoked when an answer was received from a remote; this will set the remote - // session description on the peer connection. Returns true if the offer was - // successfully set as remote session description. - // Can be called on any thread but never called on signaling thread. - bool OnAnswerReceived(SessionDescriptionWrapper answer) - ABSL_LOCKS_EXCLUDED(mutex_); - // Invoked when an ice candidate was received from a remote; this will add the - // ice candidate to the peer connection if ready or cache it otherwise. - // Can be called on any thread but never called on signaling thread. - bool OnRemoteIceCandidatesReceived( - std::vector> ice_candidates) - ABSL_LOCKS_EXCLUDED(mutex_); - // Close the peer connection and data channel if not connected. - // Can be called on any thread but never called on signaling thread. - bool CloseIfNotConnected() ABSL_LOCKS_EXCLUDED(mutex_); - - // webrtc::PeerConnectionObserver: - // All methods called only on signaling thread. - void OnIceCandidate(const webrtc::IceCandidate* candidate) override; - void OnSignalingChange( - webrtc::PeerConnectionInterface::SignalingState new_state) override; - void OnDataChannel(webrtc::scoped_refptr - data_channel) override; - void OnIceGatheringChange( - webrtc::PeerConnectionInterface::IceGatheringState new_state) override; - void OnConnectionChange( - webrtc::PeerConnectionInterface::PeerConnectionState new_state) override; - void OnRenegotiationNeeded() override; - void OnIceSelectedCandidatePairChanged( - const webrtc::CandidatePairChangeEvent& event) override; - - // Public because it's used in tests too. - webrtc::scoped_refptr GetPeerConnection(); - - private: - ConnectionFlow(LocalIceCandidateListener local_ice_candidate_listener, - DataChannelListener data_channel_listener, - AdapterTypeListener adapter_type_listener); - - // Resets peer connection reference. Returns old value. - webrtc::scoped_refptr - GetAndResetPeerConnection(); - void CreateOfferOnSignalingThread( - Future success_future); - void CreateAnswerOnSignalingThread( - Future success_future); - void AddIceCandidatesOnSignalingThread( - std::vector> ice_candidates); - // Invoked when the peer connection indicates that signaling is stable. - void OnSignalingStable() ABSL_LOCKS_EXCLUDED(mutex_); - - void CreateSocketFromDataChannel( - webrtc::scoped_refptr data_channel); - - // TODO(bfranz): Consider whether this needs to be configurable per platform - static constexpr absl::Duration kTimeout = absl::Milliseconds(250); - static constexpr absl::Duration kPeerConnectionTimeout = - absl::Milliseconds(2500); - - bool InitPeerConnection(WebRtcMedium& webrtc_medium); - - bool TransitionState(State current_state, State new_state); - - bool SetRemoteSessionDescription(SessionDescriptionWrapper sdp, - State expected_entry_state, - State exit_state); - - bool CloseOnSignalingThread() ABSL_LOCKS_EXCLUDED(mutex_); - - bool RunOnSignalingThread(Runnable&& runnable); - bool IsRunningOnSignalingThread(); - - Mutex mutex_; - // Used to prevent the destructor from returning while the signaling thread is - // still running CloseOnSignalingThread() - CountDownLatch shutdown_latch_{1}; - - // State is used on signaling thread only. - State state_ = State::kInitialized; - // Used to communicate data channel events back to the caller of Create() - DataChannelListener data_channel_listener_; - - LocalIceCandidateListener local_ice_candidate_listener_; - // Peer connection can be used only on signaling thread. The only exception - // is accessing the signaling thread handle. Tasks posted on the - // signaling thread may outlive both |peer_connection_| and |this| objects. - // A mutex is required to access peer connection reference because peer - // connection object and the reference can be initialized on different - // threads - the reference could be initialized before peer connection's - // constructor has finished. - // |peer_connection_| is actually implemented by PeerConnectionProxy, which - // runs the real PeerConnection's methods on the correct thread (signaling or - // worker). If a proxy method is called on the correct thread, then the real - // method is called directly. Otherwise, a task is posted on the correct - // thread and the current thread is blocked until that task finishes. We - // choose to explicitly use |peer_connection_| on the signaling thread, - // because it allows us to do state management on the signaling thread too, - // simplifies locking, and we don't have to block the current thread for every - // peer connection call. - webrtc::scoped_refptr peer_connection_ - ABSL_GUARDED_BY(mutex_); - - // Used to hold a reference to the WebRtcSocket while the data channel is - // connecting. - std::shared_ptr socket_; - - std::vector> - cached_remote_ice_candidates_; - // This pointer is only for DCHECK() assertions. - // It allows us to check if we are running on signaling thread even - // after destroying |peer_connection_|. - const void* signaling_thread_for_dcheck_only_ = nullptr; - // This shared_ptr is reset on the signaling thread when ConnectionFlow is - // closed. This prevents us from running tasks on the signaling thread when - // peer connection is closed. The value stored in |can_run_tasks_| is not - // used. We are using std::shared_ptr instead of webrtc::WeakPtrFactory - // because the former is thread-safe. - std::shared_ptr can_run_tasks_ = std::make_shared(); - - AdapterTypeListener adapter_type_listener_; - - friend class CreateSessionDescriptionObserverImpl; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_CONNECTION_FLOW_H_ diff --git a/connections/implementation/mediums/webrtc/connection_flow_test.cc b/connections/implementation/mediums/webrtc/connection_flow_test.cc deleted file mode 100644 index 0145fb47..00000000 --- a/connections/implementation/mediums/webrtc/connection_flow_test.cc +++ /dev/null @@ -1,445 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/connection_flow.h" - -#include -#include -#include - -#include "gtest/gtest.h" -#include "absl/strings/string_view.h" -#include "absl/time/time.h" -#include "connections/implementation/mediums/webrtc/data_channel_listener.h" -#include "connections/implementation/mediums/webrtc/local_ice_candidate_listener.h" -#include "connections/implementation/mediums/webrtc/session_description_wrapper.h" -#include "connections/implementation/mediums/webrtc/webrtc.h" -#include "connections/implementation/mediums/webrtc_socket.h" -#include "internal/platform/byte_array.h" -#include "internal/platform/count_down_latch.h" -#include "internal/platform/exception.h" -#include "internal/platform/future.h" -#include "internal/platform/medium_environment.h" -#include "webrtc/api/jsep.h" -#include "webrtc/api/scoped_refptr.h" -#include "webrtc/rtc_base/network_constants.h" - -namespace nearby { -namespace connections { -namespace mediums { -namespace { - -class ConnectionFlowTest : public ::testing::Test { - protected: - ConnectionFlowTest() { - MediumEnvironment::Instance().Start({.webrtc_enabled = true}); - } - ~ConnectionFlowTest() override { MediumEnvironment::Instance().Stop(); } -}; - -std::unique_ptr CopyCandidate( - const webrtc::IceCandidate* candidate) { - return webrtc::CreateIceCandidate(candidate->sdp_mid(), - candidate->sdp_mline_index(), - candidate->candidate()); -} - -// TODO(bfranz) - Add test that deterministically sends answerer_ice_candidates -// before answer is sent. -TEST_F(ConnectionFlowTest, SuccessfulOfferAnswerFlow) { - WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; - - Future message_received_future; - - Future> offerer_socket_future, - answerer_socket_future; - - std::unique_ptr offerer, answerer; - - // Send Ice Candidates immediately when you retrieve them - offerer = ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - [&answerer](const webrtc::IceCandidate* candidate) { - std::vector> vec; - vec.push_back(CopyCandidate(candidate)); - // The callback might be alive while the objects in test are - // destroyed. - if (answerer) - answerer->OnRemoteIceCandidatesReceived(std::move(vec)); - }}, - {.data_channel_open_cb = - [&offerer_socket_future](std::shared_ptr socket) { - offerer_socket_future.Set(std::move(socket)); - }}, - {.adapter_type_changed_cb = - [](webrtc::AdapterType adapter_type) { - // Do nothing - }}, - webrtc_medium_offerer); - ASSERT_NE(offerer, nullptr); - answerer = ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - [&offerer](const webrtc::IceCandidate* candidate) { - std::vector> vec; - vec.push_back(CopyCandidate(candidate)); - // The callback might be alive while the objects in test are - // destroyed. - if (offerer) - offerer->OnRemoteIceCandidatesReceived(std::move(vec)); - }}, - {.data_channel_open_cb = - [&answerer_socket_future](std::shared_ptr socket) { - answerer_socket_future.Set(std::move(socket)); - }}, - {.adapter_type_changed_cb = - [](webrtc::AdapterType adapter_type) { - // Do nothing - }}, - webrtc_medium_answerer); - ASSERT_NE(answerer, nullptr); - - // Create and send offer - SessionDescriptionWrapper offer = offerer->CreateOffer(); - ASSERT_TRUE(offer.IsValid()); - EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - EXPECT_TRUE(answerer->OnOfferReceived(offer)); - EXPECT_TRUE(offerer->SetLocalSessionDescription(std::move(offer))); - - // Create and send answer - SessionDescriptionWrapper answer = answerer->CreateAnswer(); - ASSERT_TRUE(answer.IsValid()); - EXPECT_EQ(answer.GetType(), webrtc::SdpType::kAnswer); - EXPECT_TRUE(offerer->OnAnswerReceived(answer)); - EXPECT_TRUE(answerer->SetLocalSessionDescription(std::move(answer))); - - // Retrieve Data Channels - ExceptionOr> offerer_socket = - offerer_socket_future.Get(absl::Seconds(1)); - EXPECT_TRUE(offerer_socket.ok()); - ExceptionOr> answerer_socket = - answerer_socket_future.Get(absl::Seconds(1)); - EXPECT_TRUE(answerer_socket.ok()); - - // Send message on data channel - absl::string_view message = "Test"; - offerer_socket.result()->GetOutputStream().Write(message); - ExceptionOr received_message = - answerer_socket.result()->GetInputStream().Read(4); - EXPECT_TRUE(received_message.ok()); - EXPECT_EQ(received_message.result(), ByteArray{message.data()}); -} - -TEST_F(ConnectionFlowTest, CreateAnswerBeforeOfferReceived) { - WebRtcMedium webrtc_medium; - - std::unique_ptr answerer = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), - ConnectionFlow::AdapterTypeListener(), webrtc_medium); - ASSERT_NE(answerer, nullptr); - - SessionDescriptionWrapper answer = answerer->CreateAnswer(); - EXPECT_FALSE(answer.IsValid()); -} - -TEST_F(ConnectionFlowTest, SetAnswerBeforeOffer) { - WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; - - std::unique_ptr offerer = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), - ConnectionFlow::AdapterTypeListener(), webrtc_medium_offerer); - ASSERT_NE(offerer, nullptr); - std::unique_ptr answerer = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), - ConnectionFlow::AdapterTypeListener(), webrtc_medium_answerer); - ASSERT_NE(answerer, nullptr); - - SessionDescriptionWrapper offer = offerer->CreateOffer(); - ASSERT_TRUE(offer.IsValid()); - EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - // Did not set offer as local session description - EXPECT_TRUE(answerer->OnOfferReceived(offer)); - - SessionDescriptionWrapper answer = answerer->CreateAnswer(); - ASSERT_TRUE(answer.IsValid()); - EXPECT_EQ(answer.GetType(), webrtc::SdpType::kAnswer); - EXPECT_FALSE(offerer->OnAnswerReceived(answer)); -} - -TEST_F(ConnectionFlowTest, CannotCreateOfferAfterClose) { - WebRtcMedium webrtc_medium; - - std::unique_ptr offerer = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), - ConnectionFlow::AdapterTypeListener(), webrtc_medium); - ASSERT_NE(offerer, nullptr); - - EXPECT_TRUE(offerer->CloseIfNotConnected()); - - EXPECT_FALSE(offerer->CreateOffer().IsValid()); -} - -TEST_F(ConnectionFlowTest, CannotSetSessionDescriptionAfterClose) { - WebRtcMedium webrtc_medium; - - std::unique_ptr offerer = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), - ConnectionFlow::AdapterTypeListener(), webrtc_medium); - ASSERT_NE(offerer, nullptr); - - SessionDescriptionWrapper offer = offerer->CreateOffer(); - ASSERT_TRUE(offer.IsValid()); - EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - - EXPECT_TRUE(offerer->CloseIfNotConnected()); - - EXPECT_FALSE(offerer->SetLocalSessionDescription(offer)); -} - -TEST_F(ConnectionFlowTest, CannotReceiveOfferAfterClose) { - WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; - - std::unique_ptr offerer = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), - ConnectionFlow::AdapterTypeListener(), webrtc_medium_offerer); - ASSERT_NE(offerer, nullptr); - std::unique_ptr answerer = ConnectionFlow::Create( - LocalIceCandidateListener(), DataChannelListener(), - ConnectionFlow::AdapterTypeListener(), webrtc_medium_answerer); - ASSERT_NE(answerer, nullptr); - - EXPECT_TRUE(answerer->CloseIfNotConnected()); - - SessionDescriptionWrapper offer = offerer->CreateOffer(); - ASSERT_TRUE(offer.IsValid()); - EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - - EXPECT_FALSE(answerer->OnOfferReceived(offer)); -} - -TEST_F(ConnectionFlowTest, NullPeerConnection) { - MediumEnvironment::Instance().SetUseValidPeerConnection( - /*use_valid_peer_connection=*/false); - - WebRtcMedium medium; - std::unique_ptr answerer = - ConnectionFlow::Create(LocalIceCandidateListener(), DataChannelListener(), - ConnectionFlow::AdapterTypeListener(), medium); - EXPECT_EQ(answerer, nullptr); -} - -TEST_F(ConnectionFlowTest, PeerConnectionTimeout) { - MediumEnvironment::Instance().SetUseValidPeerConnection( - /*use_valid_peer_connection=*/true); - WebRtcMedium medium1; - std::unique_ptr flow1 = - ConnectionFlow::Create(LocalIceCandidateListener(), DataChannelListener(), - ConnectionFlow::AdapterTypeListener(), medium1); - EXPECT_NE(flow1, nullptr); - - // Attempt to trigger the 2.5s peer connection timeout. - MediumEnvironment::Instance().SetPeerConnectionLatency(absl::Seconds(5)); - WebRtcMedium medium2; - std::unique_ptr flow2 = - ConnectionFlow::Create(LocalIceCandidateListener(), DataChannelListener(), - ConnectionFlow::AdapterTypeListener(), medium2); - EXPECT_EQ(flow2, nullptr); -} - -TEST_F(ConnectionFlowTest, TerminateAnswerer) { - WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; - - Future message_received_future; - - Future> offerer_socket_future, - answerer_socket_future; - - std::unique_ptr offerer, answerer; - - // Send Ice Candidates immediately when you retrieve them - offerer = ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - [&answerer](const webrtc::IceCandidate* candidate) { - std::vector> vec; - vec.push_back(CopyCandidate(candidate)); - // The callback might be alive while the objects in test are - // destroyed. - if (answerer) - answerer->OnRemoteIceCandidatesReceived(std::move(vec)); - }}, - {.data_channel_open_cb = - [&offerer_socket_future](std::shared_ptr socket) { - offerer_socket_future.Set(std::move(socket)); - }}, - {.adapter_type_changed_cb = - [](webrtc::AdapterType adapter_type) { - // Do nothing - }}, - webrtc_medium_offerer); - ASSERT_NE(offerer, nullptr); - answerer = ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - [&offerer](const webrtc::IceCandidate* candidate) { - std::vector> vec; - vec.push_back(CopyCandidate(candidate)); - // The callback might be alive while the objects in test are - // destroyed. - if (offerer) - offerer->OnRemoteIceCandidatesReceived(std::move(vec)); - }}, - {.data_channel_open_cb = - [&answerer_socket_future](std::shared_ptr wrapper) { - answerer_socket_future.Set(std::move(wrapper)); - }}, - {.adapter_type_changed_cb = - [](webrtc::AdapterType adapter_type) { - EXPECT_GE(adapter_type, webrtc::ADAPTER_TYPE_UNKNOWN); - EXPECT_LE(adapter_type, webrtc::ADAPTER_TYPE_CELLULAR_5G); - }}, - webrtc_medium_answerer); - ASSERT_NE(answerer, nullptr); - - // Create and send offer - SessionDescriptionWrapper offer = offerer->CreateOffer(); - ASSERT_TRUE(offer.IsValid()); - EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - EXPECT_TRUE(answerer->OnOfferReceived(offer)); - EXPECT_TRUE(offerer->SetLocalSessionDescription(std::move(offer))); - - // Create and send answer - SessionDescriptionWrapper answer = answerer->CreateAnswer(); - ASSERT_TRUE(answer.IsValid()); - EXPECT_EQ(answer.GetType(), webrtc::SdpType::kAnswer); - EXPECT_TRUE(offerer->OnAnswerReceived(answer)); - EXPECT_TRUE(answerer->SetLocalSessionDescription(std::move(answer))); - - // Retrieve Data Channels - ExceptionOr> offerer_socket = - offerer_socket_future.Get(absl::Seconds(1)); - EXPECT_TRUE(offerer_socket.ok()); - ExceptionOr> answerer_socket = - answerer_socket_future.Get(absl::Seconds(1)); - EXPECT_TRUE(offerer_socket.ok()); - - CountDownLatch latch(1); - auto pc = answerer->GetPeerConnection(); - pc->signaling_thread()->PostTask([pc, latch]() mutable { - pc->Close(); - latch.CountDown(); - }); - latch.Await(); - - // Send message on data channel - absl::string_view message = "Test"; - offerer_socket.result()->GetOutputStream().Write(message); - ExceptionOr received_message = - answerer_socket.result()->GetInputStream().Read(4); - EXPECT_TRUE(received_message.GetResult().Empty()); -} - -TEST_F(ConnectionFlowTest, TerminateOfferer) { - WebRtcMedium webrtc_medium_offerer, webrtc_medium_answerer; - - Future message_received_future; - - Future> offerer_socket_future, - answerer_socket_future; - - std::unique_ptr offerer, answerer; - - // Send Ice Candidates immediately when you retrieve them - offerer = ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - [&answerer](const webrtc::IceCandidate* candidate) { - std::vector> vec; - vec.push_back(CopyCandidate(candidate)); - // The callback might be alive while the objects in test are - // destroyed. - if (answerer) - answerer->OnRemoteIceCandidatesReceived(std::move(vec)); - }}, - {.data_channel_open_cb = - [&offerer_socket_future](std::shared_ptr socket) { - offerer_socket_future.Set(std::move(socket)); - }}, - {.adapter_type_changed_cb = - [](webrtc::AdapterType adapter_type) { - EXPECT_GE(adapter_type, webrtc::ADAPTER_TYPE_UNKNOWN); - EXPECT_LE(adapter_type, webrtc::ADAPTER_TYPE_CELLULAR_5G); - }}, - webrtc_medium_offerer); - ASSERT_NE(offerer, nullptr); - answerer = ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - [&offerer](const webrtc::IceCandidate* candidate) { - std::vector> vec; - vec.push_back(CopyCandidate(candidate)); - // The callback might be alive while the objects in test are - // destroyed. - if (offerer) - offerer->OnRemoteIceCandidatesReceived(std::move(vec)); - }}, - {.data_channel_open_cb = - [&answerer_socket_future](std::shared_ptr wrapper) { - answerer_socket_future.Set(std::move(wrapper)); - }}, - {.adapter_type_changed_cb = - [](webrtc::AdapterType adapter_type) { - EXPECT_GE(adapter_type, webrtc::ADAPTER_TYPE_UNKNOWN); - EXPECT_LE(adapter_type, webrtc::ADAPTER_TYPE_CELLULAR_5G); - }}, - webrtc_medium_answerer); - ASSERT_NE(answerer, nullptr); - - // Create and send offer - SessionDescriptionWrapper offer = offerer->CreateOffer(); - ASSERT_TRUE(offer.IsValid()); - EXPECT_EQ(offer.GetType(), webrtc::SdpType::kOffer); - EXPECT_TRUE(answerer->OnOfferReceived(offer)); - EXPECT_TRUE(offerer->SetLocalSessionDescription(std::move(offer))); - - // Create and send answer - SessionDescriptionWrapper answer = answerer->CreateAnswer(); - ASSERT_TRUE(answer.IsValid()); - EXPECT_EQ(answer.GetType(), webrtc::SdpType::kAnswer); - EXPECT_TRUE(offerer->OnAnswerReceived(answer)); - EXPECT_TRUE(answerer->SetLocalSessionDescription(std::move(answer))); - - // Retrieve Data Channels - ExceptionOr> offerer_socket = - offerer_socket_future.Get(absl::Seconds(1)); - EXPECT_TRUE(offerer_socket.ok()); - ExceptionOr> answerer_socket = - answerer_socket_future.Get(absl::Seconds(1)); - EXPECT_TRUE(offerer_socket.ok()); - - CountDownLatch latch(1); - auto pc = offerer->GetPeerConnection(); - pc->signaling_thread()->PostTask([pc, latch]() mutable { - pc->Close(); - latch.CountDown(); - }); - latch.Await(); - - // Send message on data channel - absl::string_view message = "Test"; - offerer_socket.result()->GetOutputStream().Write(message); - ExceptionOr received_message = - answerer_socket.result()->GetInputStream().Read(4); - EXPECT_TRUE(received_message.GetResult().Empty()); -} - -} // namespace -} // namespace mediums -} // namespace connections -} // namespace nearby diff --git a/connections/implementation/mediums/webrtc/data_channel_listener.h b/connections/implementation/mediums/webrtc/data_channel_listener.h deleted file mode 100644 index cb4e39b3..00000000 --- a/connections/implementation/mediums/webrtc/data_channel_listener.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_DATA_CHANNEL_LISTENER_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_DATA_CHANNEL_LISTENER_H_ - -#include - -#include "absl/functional/any_invocable.h" -#include "connections/implementation/mediums/webrtc_socket.h" - -namespace nearby { -namespace connections { -namespace mediums { - -// Callbacks from the data channel. -struct DataChannelListener { - // Called when the data channel is open and the socket wrapper is ready to - // read and write. - absl::AnyInvocable)> data_channel_open_cb = - [](std::shared_ptr) {}; - - // Called when the data channel is closed. - absl::AnyInvocable data_channel_closed_cb = []() {}; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_DATA_CHANNEL_LISTENER_H_ diff --git a/connections/implementation/mediums/webrtc/fake_webrtc.cc b/connections/implementation/mediums/webrtc/fake_webrtc.cc deleted file mode 100644 index 6f829d94..00000000 --- a/connections/implementation/mediums/webrtc/fake_webrtc.cc +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/fake_webrtc.h" - -#include - -#include "absl/strings/string_view.h" -#include "connections/implementation/mediums/webrtc/webrtc.h" -#include "internal/platform/cancellation_flag.h" - -namespace nearby::connections::mediums { - -FakeWebRtcMedium::FakeWebRtcMedium(CancellationFlag* flag) - : WebRtcMedium(), flag_(flag) {} - -FakeWebRtcMedium::~FakeWebRtcMedium() = default; - -std::unique_ptr -FakeWebRtcMedium::GetSignalingMessenger( - absl::string_view self_id, - const location::nearby::connections::LocationHint& location_hint) { - if (cancel_during_get_signaling_messenger_) { - flag_->Cancel(); - } - - return WebRtcMedium::GetSignalingMessenger(self_id, location_hint); -} - -} // namespace nearby::connections::mediums diff --git a/connections/implementation/mediums/webrtc/fake_webrtc.h b/connections/implementation/mediums/webrtc/fake_webrtc.h deleted file mode 100644 index 65f9e3f5..00000000 --- a/connections/implementation/mediums/webrtc/fake_webrtc.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_FAKE_WEBRTC_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_FAKE_WEBRTC_H_ - -#include - -#include "absl/strings/string_view.h" -#include "connections/implementation/mediums/webrtc/webrtc.h" -#include "internal/platform/cancellation_flag.h" - -namespace nearby::connections::mediums { - -class FakeWebRtcMedium : public WebRtcMedium { - public: - explicit FakeWebRtcMedium(CancellationFlag* flag); - FakeWebRtcMedium(FakeWebRtcMedium&&) = delete; - FakeWebRtcMedium& operator=(FakeWebRtcMedium&&) = delete; - ~FakeWebRtcMedium() override; - - // WebRtcMedium: - bool IsValid() const override { return is_valid_; } - - std::unique_ptr GetSignalingMessenger( - absl::string_view self_id, - const location::nearby::connections::LocationHint& location_hint) - override; - - void TriggerCancellationDuringGetSignalingMessenger() { - cancel_during_get_signaling_messenger_ = true; - } - - void SetIsValid(bool is_valid) { is_valid_ = is_valid; } - - private: - CancellationFlag* flag_ = nullptr; - bool is_valid_ = true; - bool cancel_during_get_signaling_messenger_ = false; -}; - -} // namespace nearby::connections::mediums - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_FAKE_WEBRTC_H_ diff --git a/connections/implementation/mediums/webrtc/local_ice_candidate_listener.h b/connections/implementation/mediums/webrtc/local_ice_candidate_listener.h deleted file mode 100644 index a3b10fd0..00000000 --- a/connections/implementation/mediums/webrtc/local_ice_candidate_listener.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_LOCAL_ICE_CANDIDATE_LISTENER_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_LOCAL_ICE_CANDIDATE_LISTENER_H_ - -#include "absl/functional/any_invocable.h" -#include "internal/platform/listeners.h" -#include "webrtc/api/jsep.h" - -namespace nearby { -namespace connections { -namespace mediums { - -// Callbacks from local ice candidate collection. -struct LocalIceCandidateListener { - // Called when a new local ice candidate has been found. - absl::AnyInvocable - local_ice_candidate_found_cb = - nearby::DefaultCallback(); -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_LOCAL_ICE_CANDIDATE_LISTENER_H_ diff --git a/connections/implementation/mediums/webrtc/session_description_wrapper.h b/connections/implementation/mediums/webrtc/session_description_wrapper.h deleted file mode 100644 index a099b175..00000000 --- a/connections/implementation/mediums/webrtc/session_description_wrapper.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_SESSION_DESCRIPTION_WRAPPER_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_SESSION_DESCRIPTION_WRAPPER_H_ - -#include -#include -#include "webrtc/api/jsep.h" - -// Wrapper object around SessionDescriptionInterface*. -// This object owns the SessionDescriptionInterface* unless Release() has been -// called. -class SessionDescriptionWrapper { - public: - SessionDescriptionWrapper() = default; - explicit SessionDescriptionWrapper(webrtc::SessionDescriptionInterface* sdp) - : impl_(sdp) {} - - // Copy constructor that performs a deep copy, i.e. creates a new - // SessionDescriptionInterface. - SessionDescriptionWrapper(const SessionDescriptionWrapper& sdp) { - if (sdp.IsValid()) { - impl_ = webrtc::CreateSessionDescription(sdp.GetType(), sdp.ToString()); - } - } - - SessionDescriptionWrapper(SessionDescriptionWrapper&&) = default; - SessionDescriptionWrapper& operator=(SessionDescriptionWrapper&&) = default; - - // Release the ownership of the SessionDescriptionInterface*. - webrtc::SessionDescriptionInterface* Release() { return impl_.release(); } - - // Returns a string representation of the sdp. Only call this, if IsValid() is - // true. - std::string ToString() const { - std::string str; - impl_->ToString(&str); - return str; - } - - // Returns the SdpType of the SessionDescriptionInterface. Only call this, if - // IsValid() is true. - webrtc::SdpType GetType() const { return impl_->GetType(); } - - const webrtc::SessionDescriptionInterface& GetSdp() { return *impl_; } - - // Return whether this object currently holds a SessionDescriptionInterface. - bool IsValid() const { return impl_ != nullptr; } - - private: - std::unique_ptr impl_; -}; - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_SESSION_DESCRIPTION_WRAPPER_H_ diff --git a/connections/implementation/mediums/webrtc/signaling_frames.cc b/connections/implementation/mediums/webrtc/signaling_frames.cc deleted file mode 100644 index b59f8c7d..00000000 --- a/connections/implementation/mediums/webrtc/signaling_frames.cc +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include - -#include "connections/implementation/mediums/webrtc/signaling_frames.h" -#include "connections/implementation/mediums/webrtc_peer_id.h" -#include "internal/platform/byte_array.h" -#include "webrtc/api/jsep.h" - -namespace nearby { -namespace connections { -namespace mediums { -namespace webrtc_frames { -using WebRtcSignalingFrame = ::location::nearby::mediums::WebRtcSignalingFrame; - -namespace { - -ByteArray FrameToByteArray(const WebRtcSignalingFrame& signaling_frame) { - std::string message; - signaling_frame.SerializeToString(&message); - return ByteArray(message.c_str(), message.size()); -} - -void SetSenderId(const WebrtcPeerId& sender_id, WebRtcSignalingFrame& frame) { - frame.mutable_sender_id()->set_id(sender_id.GetId()); -} - -std::unique_ptr DecodeIceCandidate( - location::nearby::mediums::IceCandidate ice_candidate_proto) { - webrtc::SdpParseError error; - return std::unique_ptr(webrtc::CreateIceCandidate( - ice_candidate_proto.sdp_mid(), ice_candidate_proto.sdp_m_line_index(), - ice_candidate_proto.sdp(), &error)); -} - -} // namespace - -ByteArray EncodeReadyForSignalingPoke(const WebrtcPeerId& sender_id) { - WebRtcSignalingFrame signaling_frame; - signaling_frame.set_type(WebRtcSignalingFrame::READY_FOR_SIGNALING_POKE_TYPE); - SetSenderId(sender_id, signaling_frame); - signaling_frame.set_allocated_ready_for_signaling_poke( - new location::nearby::mediums::ReadyForSignalingPoke()); - return FrameToByteArray(std::move(signaling_frame)); -} - -ByteArray EncodeOffer(const WebrtcPeerId& sender_id, - const webrtc::SessionDescriptionInterface& offer) { - WebRtcSignalingFrame signaling_frame; - signaling_frame.set_type(WebRtcSignalingFrame::OFFER_TYPE); - SetSenderId(sender_id, signaling_frame); - std::string offer_str; - offer.ToString(&offer_str); - signaling_frame.mutable_offer() - ->mutable_session_description() - ->set_description(offer_str); - return FrameToByteArray(std::move(signaling_frame)); -} - -ByteArray EncodeAnswer(const WebrtcPeerId& sender_id, - const webrtc::SessionDescriptionInterface& answer) { - WebRtcSignalingFrame signaling_frame; - signaling_frame.set_type(WebRtcSignalingFrame::ANSWER_TYPE); - SetSenderId(sender_id, signaling_frame); - std::string answer_str; - answer.ToString(&answer_str); - signaling_frame.mutable_answer() - ->mutable_session_description() - ->set_description(answer_str); - return FrameToByteArray(std::move(signaling_frame)); -} - -ByteArray EncodeIceCandidates( - const WebrtcPeerId& sender_id, - const std::vector& - ice_candidates) { - WebRtcSignalingFrame signaling_frame; - signaling_frame.set_type(WebRtcSignalingFrame::ICE_CANDIDATES_TYPE); - SetSenderId(sender_id, signaling_frame); - for (const auto& ice_candidate : ice_candidates) { - *signaling_frame.mutable_ice_candidates()->add_ice_candidates() = - ice_candidate; - } - return FrameToByteArray(std::move(signaling_frame)); -} - -std::unique_ptr DecodeOffer( - const WebRtcSignalingFrame& frame) { - return webrtc::CreateSessionDescription( - webrtc::SdpType::kOffer, - frame.offer().session_description().description()); -} - -std::unique_ptr DecodeAnswer( - const WebRtcSignalingFrame& frame) { - return webrtc::CreateSessionDescription( - webrtc::SdpType::kAnswer, - frame.answer().session_description().description()); -} - -std::vector> DecodeIceCandidates( - const WebRtcSignalingFrame& frame) { - std::vector> ice_candidates; - for (const auto& candidate : frame.ice_candidates().ice_candidates()) { - ice_candidates.push_back(DecodeIceCandidate(candidate)); - } - return ice_candidates; -} - -location::nearby::mediums::IceCandidate EncodeIceCandidate( - const webrtc::IceCandidate& ice_candidate) { - std::string sdp; - ice_candidate.ToString(&sdp); - location::nearby::mediums::IceCandidate ice_candidate_proto; - ice_candidate_proto.set_sdp(sdp); - ice_candidate_proto.set_sdp_mid(ice_candidate.sdp_mid()); - ice_candidate_proto.set_sdp_m_line_index(ice_candidate.sdp_mline_index()); - return ice_candidate_proto; -} - -} // namespace webrtc_frames -} // namespace mediums -} // namespace connections -} // namespace nearby diff --git a/connections/implementation/mediums/webrtc/signaling_frames.h b/connections/implementation/mediums/webrtc/signaling_frames.h deleted file mode 100644 index c6579463..00000000 --- a/connections/implementation/mediums/webrtc/signaling_frames.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_SIGNALING_FRAMES_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_SIGNALING_FRAMES_H_ - -#include -#include - -#include "connections/implementation/mediums/webrtc_peer_id.h" -#include "internal/platform/byte_array.h" -#include "proto/mediums/web_rtc_signaling_frames.pb.h" -#include "webrtc/api/jsep.h" - -namespace nearby { -namespace connections { -namespace mediums { -namespace webrtc_frames { - -ByteArray EncodeReadyForSignalingPoke(const WebrtcPeerId& sender_id); - -ByteArray EncodeOffer(const WebrtcPeerId& sender_id, - const webrtc::SessionDescriptionInterface& offer); -ByteArray EncodeAnswer(const WebrtcPeerId& sender_id, - const webrtc::SessionDescriptionInterface& answer); - -ByteArray EncodeIceCandidates( - const WebrtcPeerId& sender_id, - const std::vector& ice_candidates); -location::nearby::mediums::IceCandidate EncodeIceCandidate( - const webrtc::IceCandidate& ice_candidate); - -std::unique_ptr DecodeOffer( - const location::nearby::mediums::WebRtcSignalingFrame& frame); -std::unique_ptr DecodeAnswer( - const location::nearby::mediums::WebRtcSignalingFrame& frame); - -std::vector> DecodeIceCandidates( - const location::nearby::mediums::WebRtcSignalingFrame& frame); - -} // namespace webrtc_frames -} // namespace mediums -} // namespace connections -} // namespace nearby - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_SIGNALING_FRAMES_H_ diff --git a/connections/implementation/mediums/webrtc/signaling_frames_test.cc b/connections/implementation/mediums/webrtc/signaling_frames_test.cc deleted file mode 100644 index de5f92bb..00000000 --- a/connections/implementation/mediums/webrtc/signaling_frames_test.cc +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/signaling_frames.h" - -#include - -#include "gmock/gmock.h" -#include "protobuf-matchers/protocol-buffer-matchers.h" -#include "gtest/gtest.h" -#include "connections/implementation/mediums/webrtc_peer_id.h" -#include "google/protobuf/text_format.h" -#include "webrtc/api/jsep.h" - -namespace nearby { -namespace connections { -namespace mediums { -namespace webrtc_frames { - -namespace { - -using ::location::nearby::mediums::IceCandidate; -using ::location::nearby::mediums::WebRtcSignalingFrame; -const char kSampleSdp[] = - "v=0\r\no=- 7859371131 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 " - "0\r\na=msid-semantic: WMS\r\n"; - -const char kIceCandidateSdp1[] = - "a=candidate:1 1 UDP 2130706431 10.0.1.1 8998 typ host"; -const char kIceCandidateSdp2[] = - "a=candidate:2 1 UDP 1694498815 192.0.2.3 45664 typ srflx raddr"; - -const char kIceSdpMid[] = "data"; -const int kIceSdpMLineIndex = 0; - -const char kOfferProto[] = R"( - sender_id { id: "abc" } - type: OFFER_TYPE - offer { - session_description { - description: "v=0\r\no=- 7859371131 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=msid-semantic: WMS\r\n" - } - } - )"; - -const char kAnswerProto[] = R"( - sender_id { id: "abc" } - type: ANSWER_TYPE - answer { - session_description { - description: "v=0\r\no=- 7859371131 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=msid-semantic: WMS\r\n" - } - } - )"; - -const char kIceCandidatesProto[] = R"( - sender_id { id: "abc" } - type: ICE_CANDIDATES_TYPE - ice_candidates { - ice_candidates { - sdp: "candidate:1 1 udp 2130706431 10.0.1.1 8998 typ host generation 0" - sdp_mid: "data" - sdp_m_line_index: 0 - } - ice_candidates { - sdp: "candidate:2 1 udp 1694498815 192.0.2.3 45664 typ srflx generation 0" - sdp_mid: "data" - sdp_m_line_index: 0 - } - } - )"; -} // namespace - -TEST(SignalingFramesTest, SignalingPoke) { - WebrtcPeerId sender_id("abc"); - ByteArray encoded_poke = EncodeReadyForSignalingPoke(sender_id); - - WebRtcSignalingFrame frame; - frame.ParseFromString(std::string(encoded_poke.data(), encoded_poke.size())); - - EXPECT_THAT(frame, protobuf_matchers::EqualsProto(R"pb( - sender_id { id: "abc" } - type: READY_FOR_SIGNALING_POKE_TYPE - ready_for_signaling_poke {} - )pb")); -} - -TEST(SignalingFramesTest, EncodeValidOffer) { - WebrtcPeerId sender_id("abc"); - std::unique_ptr offer = - webrtc::CreateSessionDescription(webrtc::SdpType::kOffer, kSampleSdp); - ByteArray encoded_offer = EncodeOffer(sender_id, *offer); - - WebRtcSignalingFrame frame; - frame.ParseFromString( - std::string(encoded_offer.data(), encoded_offer.size())); - - EXPECT_THAT(frame, protobuf_matchers::EqualsProto(kOfferProto)); -} - -TEST(SignaingFramesTest, DecodeValidOffer) { - WebRtcSignalingFrame frame; - proto2::TextFormat::ParseFromString(kOfferProto, &frame); - std::unique_ptr decoded_offer = - DecodeOffer(frame); - - EXPECT_EQ(webrtc::SdpType::kOffer, decoded_offer->GetType()); - std::string description; - decoded_offer->ToString(&description); - EXPECT_EQ(kSampleSdp, description); -} - -TEST(SignalingFramesTest, EncodeValidAnswer) { - WebrtcPeerId sender_id("abc"); - std::unique_ptr answer( - webrtc::CreateSessionDescription(webrtc::SdpType::kAnswer, kSampleSdp)); - ByteArray encoded_answer = EncodeAnswer(sender_id, *answer); - - WebRtcSignalingFrame frame; - frame.ParseFromString( - std::string(encoded_answer.data(), encoded_answer.size())); - - EXPECT_THAT(frame, protobuf_matchers::EqualsProto(kAnswerProto)); -} - -TEST(SignalingFramesTest, DecodeValidAnswer) { - WebRtcSignalingFrame frame; - proto2::TextFormat::ParseFromString(kAnswerProto, &frame); - std::unique_ptr decoded_answer = - DecodeAnswer(frame); - - EXPECT_EQ(webrtc::SdpType::kAnswer, decoded_answer->GetType()); - std::string description; - decoded_answer->ToString(&description); - EXPECT_EQ(kSampleSdp, description); -} - -TEST(SignalingFramesTest, EncodeValidIceCandidates) { - WebrtcPeerId sender_id("abc"); - webrtc::SdpParseError error; - - std::vector> ice_candidates; - ice_candidates.emplace_back(webrtc::CreateIceCandidate( - kIceSdpMid, kIceSdpMLineIndex, kIceCandidateSdp1, &error)); - ice_candidates.emplace_back(webrtc::CreateIceCandidate( - kIceSdpMid, kIceSdpMLineIndex, kIceCandidateSdp2, &error)); - std::vector encoded_candidates_vec; - for (const auto& ice_candidate : ice_candidates) { - encoded_candidates_vec.push_back(EncodeIceCandidate(*ice_candidate)); - } - ByteArray encoded_candidates = - EncodeIceCandidates(sender_id, encoded_candidates_vec); - - WebRtcSignalingFrame frame; - frame.ParseFromString( - std::string(encoded_candidates.data(), encoded_candidates.size())); - - EXPECT_THAT(frame, protobuf_matchers::EqualsProto(kIceCandidatesProto)); -} - -TEST(SignalingFramesTest, DecodeValidIceCandidates) { - webrtc::SdpParseError error; - std::vector> ice_candidates; - ice_candidates.emplace_back(webrtc::CreateIceCandidate( - kIceSdpMid, kIceSdpMLineIndex, kIceCandidateSdp1, &error)); - ice_candidates.emplace_back(webrtc::CreateIceCandidate( - kIceSdpMid, kIceSdpMLineIndex, kIceCandidateSdp2, &error)); - - WebRtcSignalingFrame frame; - proto2::TextFormat::ParseFromString(kIceCandidatesProto, &frame); - std::vector> decoded_candidates = - DecodeIceCandidates(frame); - - ASSERT_EQ(2u, decoded_candidates.size()); - for (int i = 0; i < static_cast(decoded_candidates.size()); i++) { - EXPECT_TRUE(ice_candidates[i]->candidate().IsEquivalent( - decoded_candidates[i]->candidate())); - EXPECT_EQ(ice_candidates[i]->sdp_mid(), decoded_candidates[i]->sdp_mid()); - EXPECT_EQ(ice_candidates[i]->sdp_mline_index(), - decoded_candidates[i]->sdp_mline_index()); - } -} - -} // namespace webrtc_frames -} // namespace mediums -} // namespace connections -} // namespace nearby diff --git a/connections/implementation/mediums/webrtc/tachyon_express_signaling_messenger.cc b/connections/implementation/mediums/webrtc/tachyon_express_signaling_messenger.cc deleted file mode 100644 index 9e6efa79..00000000 --- a/connections/implementation/mediums/webrtc/tachyon_express_signaling_messenger.cc +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/tachyon_express_signaling_messenger.h" - -#include -#include -#include -#include - -#include "absl/functional/any_invocable.h" -#include "absl/strings/string_view.h" -#include "absl/synchronization/mutex.h" -#include "absl/time/time.h" -#include "third_party/gloop/util/random/mt_random.h" -#include "third_party/grpc/include/grpc/support/time.h" -#include "third_party/grpc/include/grpcpp/channel.h" -#include "third_party/grpc/include/grpcpp/client_context.h" -#include "third_party/grpc/include/grpcpp/create_channel.h" -#include "third_party/grpc/include/grpcpp/security/credentials.h" -#include "third_party/grpc/include/grpcpp/support/client_callback.h" -#include "third_party/grpc/include/grpcpp/support/status.h" -#include "internal/account/account_manager_impl.h" -#include "internal/platform/byte_array.h" -#include "internal/platform/count_down_latch.h" -#include "internal/platform/logging.h" -#include "internal/proto/messaging.grpc.pb.h" -#include "internal/proto/tachyon.proto.h" -#include "internal/proto/tachyon_common.proto.h" -#include "internal/proto/tachyon_enums.proto.h" -#include "internal/rpc/utils.h" -#include "util/random/util.h" - -namespace nearby::connections::mediums { - -namespace { -using ::google::internal::communications::instantmessaging::v1::ClientInfo; -using ::google::internal::communications::instantmessaging::v1::Id; -using ::google::internal::communications::instantmessaging::v1:: - LocationStandard; -using ::google::internal::communications::instantmessaging::v1:: - ReceiveMessagesResponse; -using ::google::internal::communications::instantmessaging::v1::RequestHeader; -using ::google::internal::communications::instantmessaging::v1:: - SendMessageExpressRequest; -using ::google::internal::communications::instantmessaging::v1:: - SendMessageExpressResponse; - -constexpr absl::string_view kApp = "Nearby"; -constexpr absl::string_view kTachyonAddress = - "instantmessaging-pa.googleapis.com:443"; - -// It is unclear to me where these magic numbers are from but they are used -// across both the Android and CrOS implementations. -// See: -// https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/nearby_sharing/tachyon_ice_config_fetcher.cc;l=53 -constexpr int kMajorVersion = 1; -constexpr int kMinorVersion = 24; -constexpr int kPointVersion = 0; - -void InitId(Id& id, absl::string_view id_str, - const location::nearby::connections::LocationHint& location_hint) { - id.set_id(id_str); - id.set_app(kApp); - id.set_type(google::internal::communications::instantmessaging::v1::IdType:: - NEARBY_ID); - auto* request_location_hint = id.mutable_location_hint(); - request_location_hint->set_location(location_hint.location()); - if (location_hint.format() == - location::nearby::connections::LocationStandard::E164_CALLING) { - request_location_hint->set_format(LocationStandard::E164_CALLING); - } else if (location_hint.format() == - location::nearby::connections::LocationStandard:: - ISO_3166_1_ALPHA_2) { - request_location_hint->set_format(LocationStandard::ISO_3166_1_ALPHA_2); - } else { - request_location_hint->set_format(LocationStandard::UNKNOWN); - } -} - -void InitRequestHeader( - RequestHeader& header, absl::string_view self_id, - const location::nearby::connections::LocationHint& location_hint) { - ClientInfo* client_info = header.mutable_client_info(); - client_info->set_platform_type(google::internal::communications:: - instantmessaging::v1::Platform::DESKTOP); - - client_info->set_major(kMajorVersion); - client_info->set_minor(kMinorVersion); - client_info->set_point(kPointVersion); - - client_info->set_api_version( - google::internal::communications::instantmessaging::v1::ApiVersion::V4); - - // Generate a random message identifier. - MTRandom rand; - header.set_request_id(util_random::RandomString(&rand, /*length=*/13, - util::random::kWebsafe64)); - header.set_app(kApp); - - InitId(*header.mutable_requester_id(), self_id, location_hint); -} - -} // namespace - -bool TachyonExpressSignalingMessenger::ReceiveMessagesReader::Start( - google::internal::communications::instantmessaging::v1::grpc::Messaging:: - StubInterface* stub, - absl::string_view self_id, - const location::nearby::connections::LocationHint& location_hint, - absl::string_view access_token, - absl::AnyInvocable on_fast_path_ready_callback, - absl::AnyInvocable on_inbox_message_callback, - absl::AnyInvocable on_complete_callback) { - { - absl::MutexLock lock(mutex_); - if (is_receiving_messages_) { - return false; - } - is_receiving_messages_ = true; - } - - on_fast_path_ready_callback_ = std::move(on_fast_path_ready_callback); - on_inbox_message_callback_ = std::move(on_inbox_message_callback); - on_complete_callback_ = std::move(on_complete_callback); - const std::shared_ptr call_creds = - grpc::AccessTokenCredentials(std::string(access_token)); - context_.set_credentials(call_creds); - gpr_timespec deadline = gpr_now(GPR_CLOCK_MONOTONIC); - timespec timespec = absl::ToTimespec(absl::Seconds(30)); - deadline.tv_sec += timespec.tv_sec; - deadline.tv_nsec += timespec.tv_nsec; - context_.set_deadline(deadline); - - InitRequestHeader(*request_.mutable_header(), self_id, location_hint); - stub->async()->ReceiveMessagesExpress(&context_, &request_, this); - StartRead(&response_); - StartCall(); - return true; -} - -void TachyonExpressSignalingMessenger::ReceiveMessagesReader::OnReadDone( - bool ok) { - { - absl::MutexLock lock(mutex_); - if (!is_receiving_messages_) { - return; - } - } - if (ok) { - switch (response_.body_case()) { - case ReceiveMessagesResponse::kFastPathReady: - on_fast_path_ready_callback_(); - break; - case ReceiveMessagesResponse::kInboxMessage: - on_inbox_message_callback_( - ByteArray(response_.inbox_message().message())); - break; - default: - break; - } - StartRead(&response_); - } -} - -void TachyonExpressSignalingMessenger::ReceiveMessagesReader::OnDone( - const grpc::Status& s) { - { - absl::MutexLock lock(mutex_); - if (!is_receiving_messages_) { - return; - } - } - if (!s.ok()) { - LOG(ERROR) << "ReceiveMessagesExpress failed: " - << rpc::GrpcStatusToAbslStatus(s); - } - on_complete_callback_(s.ok()); -} - -void TachyonExpressSignalingMessenger::ReceiveMessagesReader::TryCancel() { - { - absl::MutexLock lock(mutex_); - if (!is_receiving_messages_) { - return; - } - is_receiving_messages_ = false; - } - context_.TryCancel(); -} - -TachyonExpressSignalingMessenger::TachyonExpressSignalingMessenger( - absl::string_view self_id, - const location::nearby::connections::LocationHint& location_hint) - : self_id_(self_id), - location_hint_(location_hint), - account_manager_(AccountManagerImpl::Factory::instance()) { - std::shared_ptr channel = - grpc::CreateChannel(std::string(kTachyonAddress), - grpc::SslCredentials(grpc::SslCredentialsOptions())); - messaging_stub_ = google::internal::communications::instantmessaging::v1:: - grpc::Messaging::NewStub(channel); -} - -struct StartState { - CountDownLatch latch{1}; - bool success = false; -}; - -bool TachyonExpressSignalingMessenger::StartReceivingMessages( - OnSignalingMessageCallback on_message_callback, - OnSignalingCompleteCallback on_complete_callback) { - auto state = std::make_shared(); - - account_manager_->GetAccessToken( - [this, state, on_message_callback = std::move(on_message_callback), - on_complete_callback = std::move(on_complete_callback)]( - absl::StatusOr token) mutable { - if (!token.ok()) { - state->success = false; - state->latch.CountDown(); - return; - } - auto reader = std::make_shared(); - - reader_ = reader; - - std::weak_ptr weak_state = state; - - bool started = reader->Start( - messaging_stub_.get(), self_id_, location_hint_, token.value(), - /*on_fast_path_ready_callback=*/ - [state] { - LOG(INFO) << "Received fast path ready message from tachyon."; - state->success = true; - state->latch.CountDown(); - }, - std::move(on_message_callback), - [reader, weak_state, - cb = std::move(on_complete_callback)](bool s) mutable { - LOG(INFO) << "Finished receiving messages from tachyon."; - cb(s); - if (auto state = weak_state.lock()) { - state->success = false; - state->latch.CountDown(); - } - }); - - if (!started) { - state->success = false; - state->latch.CountDown(); - } - }); - state->latch.Await(); - if (state->success) { - LOG(INFO) << "Receiving messages from tachyon."; - } else { - LOG(ERROR) << "Failed to start receiving messages from tachyon."; - reader_.reset(); - } - return state->success; -} - -void TachyonExpressSignalingMessenger::StopReceivingMessages() { - if (reader_) { - reader_->TryCancel(); - reader_.reset(); - } -} - -bool TachyonExpressSignalingMessenger::SendMessage(absl::string_view peer_id, - const ByteArray& message) { - auto rpc_state = - std::make_shared>(); - - InitRequestHeader(*rpc_state->request.mutable_header(), self_id_, - location_hint_); - InitId(*rpc_state->request.mutable_dest_id(), peer_id, location_hint_); - - auto* request_message = rpc_state->request.mutable_message(); - request_message->set_message(message.string_data()); - request_message->set_message_type( - google::internal::communications::instantmessaging::v1::InboxMessage:: - BASIC); - request_message->set_message_class( - google::internal::communications::instantmessaging::v1::InboxMessage:: - EPHEMERAL); - MTRandom rand; - request_message->set_message_id(util_random::RandomString( - &rand, /*length=*/13, util::random::kWebsafe64)); - - CountDownLatch latch(1); - bool success = false; - account_manager_->GetAccessToken( - [this, &latch, &success, rpc_state](absl::StatusOr token) { - if (!token.ok()) { - success = false; - latch.CountDown(); - return; - } - - const std::shared_ptr call_creds = - grpc::AccessTokenCredentials(token.value()); - rpc_state->context.set_credentials(call_creds); - gpr_timespec deadline = gpr_now(GPR_CLOCK_MONOTONIC); - timespec timespec = absl::ToTimespec(absl::Seconds(30)); - deadline.tv_sec += timespec.tv_sec; - deadline.tv_nsec += timespec.tv_nsec; - rpc_state->context.set_deadline(deadline); - - // `rpc_state` is captured to ensure its lifetime is valid until the - // callback is executed. - messaging_stub_->async()->SendMessageExpress( - &rpc_state->context, &rpc_state->request, &rpc_state->response, - [&success, &latch, rpc_state](grpc::Status status) { - if (!status.ok()) { - LOG(ERROR) << "SendMessageExpress failed: " - << rpc::GrpcStatusToAbslStatus(status); - } - success = status.ok(); - latch.CountDown(); - }); - }); - latch.Await(); - return success; -} - -} // namespace nearby::connections::mediums diff --git a/connections/implementation/mediums/webrtc/tachyon_express_signaling_messenger.h b/connections/implementation/mediums/webrtc/tachyon_express_signaling_messenger.h deleted file mode 100644 index 47c6f59c..00000000 --- a/connections/implementation/mediums/webrtc/tachyon_express_signaling_messenger.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_TACHYON_MESSAGING_CLIENT_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_TACHYON_MESSAGING_CLIENT_H_ - -#include -#include - -#include "location/nearby/sharing/lib/account/account_manager.h" -#include "absl/base/thread_annotations.h" -#include "absl/functional/any_invocable.h" -#include "absl/strings/string_view.h" -#include "absl/synchronization/mutex.h" -#include "third_party/grpc/include/grpcpp/client_context.h" -#include "third_party/grpc/include/grpcpp/support/client_callback.h" -#include "third_party/grpc/include/grpcpp/support/status.h" -#include "internal/platform/byte_array.h" -#include "internal/platform/implementation/webrtc.h" -#include "internal/proto/messaging.grpc.pb.h" - -namespace nearby::connections::mediums { - -// Interface for the messaging Tachyon service. See -// third_party/nearby/internal/proto/messaging.proto -class TachyonExpressSignalingMessenger : public api::WebRtcSignalingMessenger { - public: - explicit TachyonExpressSignalingMessenger( - absl::string_view self_id, - const location::nearby::connections::LocationHint& location_hint); - - class ReceiveMessagesReader - : public grpc::ClientReadReactor< - google::internal::communications::instantmessaging::v1:: - ReceiveMessagesResponse> { - public: - ReceiveMessagesReader() = default; - - void OnReadDone(bool ok) override; - void OnDone(const grpc::Status& s) override; - - bool Start( - google::internal::communications::instantmessaging::v1::grpc:: - Messaging::StubInterface* stub, - absl::string_view self_id, - const location::nearby::connections::LocationHint& location_hint, - absl::string_view access_token, - absl::AnyInvocable on_fast_path_ready_callback, - absl::AnyInvocable on_inbox_message_callback, - absl::AnyInvocable on_complete_callback); - void TryCancel(); - - private: - grpc::ClientContext context_; - google::internal::communications::instantmessaging::v1:: - ReceiveMessagesExpressRequest request_; - google::internal::communications::instantmessaging::v1:: - ReceiveMessagesResponse response_; - absl::AnyInvocable on_fast_path_ready_callback_; - absl::AnyInvocable on_inbox_message_callback_; - absl::AnyInvocable on_complete_callback_; - - absl::Mutex mutex_; - bool is_receiving_messages_ ABSL_GUARDED_BY(mutex_) = false; - }; - - bool SendMessage(absl::string_view peer_id, - const ByteArray& message) override; - - bool StartReceivingMessages( - OnSignalingMessageCallback on_message_callback, - OnSignalingCompleteCallback on_complete_callback) override; - - void StopReceivingMessages() override; - - private: - std::string self_id_; - location::nearby::connections::LocationHint location_hint_; - std::unique_ptr - messaging_stub_; - nearby::sharing::AccountManager* const account_manager_; - std::shared_ptr reader_ = nullptr; -}; - -} // namespace nearby::connections::mediums - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_TACHYON_MESSAGING_CLIENT_H_ diff --git a/connections/implementation/mediums/webrtc/webrtc.h b/connections/implementation/mediums/webrtc/webrtc.h deleted file mode 100644 index 6490f5de..00000000 --- a/connections/implementation/mediums/webrtc/webrtc.h +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_H_ - -#include -#include -#include - -#include "absl/strings/string_view.h" -#include "internal/platform/byte_array.h" -#include "internal/platform/feature_flags.h" -#include "internal/platform/implementation/webrtc.h" -#include "internal/platform/implementation/webrtc_platform.h" -#include "webrtc/api/peer_connection_interface.h" -#include "webrtc/rtc_base/network_constants.h" - -namespace nearby::connections::mediums { - -class WebRtcSignalingMessenger { - public: - using OnSignalingMessageCallback = - api::WebRtcSignalingMessenger::OnSignalingMessageCallback; - using OnSignalingCompleteCallback = - api::WebRtcSignalingMessenger::OnSignalingCompleteCallback; - - explicit WebRtcSignalingMessenger( - std::unique_ptr messenger) - : impl_(std::move(messenger)) {} - virtual ~WebRtcSignalingMessenger() = default; - WebRtcSignalingMessenger(WebRtcSignalingMessenger&&) = default; - WebRtcSignalingMessenger operator=(WebRtcSignalingMessenger&&) = delete; - - virtual bool SendMessage(absl::string_view peer_id, - const ByteArray& message) { - return impl_->SendMessage(peer_id, message); - } - - virtual bool StartReceivingMessages( - OnSignalingMessageCallback on_message_callback, - OnSignalingCompleteCallback on_complete_callback) { - return impl_->StartReceivingMessages(std::move(on_message_callback), - std::move(on_complete_callback)); - } - - virtual void StopReceivingMessages() { impl_->StopReceivingMessages(); } - - virtual bool IsValid() const { return impl_ != nullptr; } - - private: - std::unique_ptr impl_; -}; - -class WebRtcMedium { - public: - WebRtcMedium() - : impl_(api::WebRtcImplementationPlatform::CreateWebRtcMedium()) {} - virtual ~WebRtcMedium() = default; - WebRtcMedium(WebRtcMedium&&) = default; - WebRtcMedium& operator=(WebRtcMedium&&) = delete; - - void SetNonCellular(bool non_cellular) { non_cellular_ = non_cellular; } - - // Creates and returns a new webrtc::PeerConnectionInterface object via - // |callback|. - void CreatePeerConnection( - webrtc::PeerConnectionObserver* observer, - api::WebRtcMedium::PeerConnectionCallback callback) { - if (FeatureFlags::GetInstance() - .GetFlags() - .support_web_rtc_non_cellular_medium && - non_cellular_) { - std::optional options; - options->network_ignore_mask |= webrtc::ADAPTER_TYPE_CELLULAR; - impl_->CreatePeerConnection(options, observer, std::move(callback)); - } else { - impl_->CreatePeerConnection(observer, std::move(callback)); - } - } - - // Returns a signaling messenger for sending WebRTC signaling messages. - virtual std::unique_ptr GetSignalingMessenger( - absl::string_view self_id, - const location::nearby::connections::LocationHint& location_hint) { - return std::make_unique( - impl_->GetSignalingMessenger(self_id, location_hint)); - } - - virtual bool IsValid() const { return impl_ != nullptr; } - - private: - std::unique_ptr impl_; - bool non_cellular_ = false; -}; - -} // namespace nearby::connections::mediums - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_H_ diff --git a/connections/implementation/mediums/webrtc/webrtc_bwu_handler.cc b/connections/implementation/mediums/webrtc/webrtc_bwu_handler.cc deleted file mode 100644 index 1b2dac5d..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_bwu_handler.cc +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/webrtc_bwu_handler.h" - -#include -#include -#include - -#include "absl/base/nullability.h" -#include "absl/functional/bind_front.h" -#include "connections/implementation/base_bwu_handler.h" -#include "connections/implementation/client_proxy.h" -#include "connections/implementation/endpoint_channel.h" -#include "connections/implementation/mediums/webrtc.h" -#include "connections/implementation/mediums/webrtc/webrtc_endpoint_channel.h" -#include "connections/implementation/mediums/webrtc_peer_id.h" -#include "connections/implementation/mediums/webrtc_socket.h" -#include "connections/implementation/offline_frames.h" -#include "connections/implementation/proto/offline_wire_formats.pb.h" -#include "internal/platform/cancellation_flag.h" -#include "internal/platform/expected.h" -#include "internal/platform/implementation/webrtc_platform.h" -#include "internal/platform/logging.h" - -namespace nearby { -namespace connections { - -namespace { -using ::location::nearby::connections::BandwidthUpgradeNegotiationFrame; -using ::location::nearby::connections::LocationHint; -using ::location::nearby::connections::LocationStandard; -using ::location::nearby::proto::connections::OperationResultCode; - -LocationHint BuildLocationHint(const std::string& location) { - LocationHint location_hint; - location_hint.set_format(LocationStandard::UNKNOWN); - - if (!location.empty()) { - location_hint.set_location(location); - if (location.at(0) == '+') { - location_hint.set_format(LocationStandard::E164_CALLING); - } else { - location_hint.set_format(LocationStandard::ISO_3166_1_ALPHA_2); - } - } - return location_hint; -} - -} // namespace - -WebrtcBwuHandler::WebrtcIncomingSocket::WebrtcIncomingSocket( - const std::string& name, std::shared_ptr socket) - : name_(name), socket_(std::move(socket)) {} - -void WebrtcBwuHandler::WebrtcIncomingSocket::Close() { socket_->Close(); } - -std::string WebrtcBwuHandler::WebrtcIncomingSocket::ToString() { return name_; } - -WebrtcBwuHandler::WebrtcBwuHandler( - mediums::WebRtc* absl_nonnull webrtc_medium, - IncomingConnectionCallback incoming_connection_callback) - : BaseBwuHandler(std::move(incoming_connection_callback)), - webrtc_(*webrtc_medium) {} - -// Called by BWU target. Retrieves a new medium info from incoming message, -// and establishes connection over WebRTC using this info. -ErrorOr> -WebrtcBwuHandler::CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const BandwidthUpgradeNegotiationFrame::UpgradePathInfo& - upgrade_path_info) { - const BandwidthUpgradeNegotiationFrame::UpgradePathInfo::WebRtcCredentials& - web_rtc_credentials = upgrade_path_info.web_rtc_credentials(); - mediums::WebrtcPeerId peer_id(web_rtc_credentials.peer_id()); - - LocationHint location_hint; - location_hint.set_format(LocationStandard::UNKNOWN); - if (web_rtc_credentials.has_location_hint()) { - location_hint = web_rtc_credentials.location_hint(); - } - LOG(INFO) << "WebRtcBwuHandler is attempting to connect to remote peer " - << peer_id.GetId() << ", location hint " - << location_hint.location(); - - std::shared_ptr cancellation_flag = - client->GetCancellationFlag(endpoint_id); - ErrorOr> socket_result = - webrtc_.Connect(service_id, peer_id, location_hint, - cancellation_flag.get(), client->GetWebRtcNonCellular()); - if (socket_result.has_error()) { - LOG(ERROR) << "WebRtcBwuHandler failed to connect to remote peer (" - << peer_id.GetId() << ") on endpoint " << endpoint_id - << ", aborting upgrade."; - return {Error(socket_result.error().operation_result_code().value())}; - } - - LOG(INFO) << "WebRtcBwuHandler successfully connected to remote " - "peer (" - << peer_id.GetId() << ") while upgrading endpoint " << endpoint_id; - - // Create a new WebRtcEndpointChannel. - auto channel = std::make_unique( - service_id, /*channel_name=*/service_id, socket_result.value()); - if (channel == nullptr) { - socket_result.value()->Close(); - LOG(ERROR) << "WebRtcBwuHandler failed to create new EndpointChannel for " - "outgoing socket, aborting upgrade."; - return {Error( - OperationResultCode::NEARBY_WEB_RTC_ENDPOINT_CHANNEL_CREATION_FAILURE)}; - } - - return {std::move(channel)}; -} - -void WebrtcBwuHandler::HandleRevertInitiatorStateForService( - const std::string& upgrade_service_id) { - webrtc_.StopAcceptingConnections(upgrade_service_id); - LOG(INFO) << "WebrtcBwuHandler successfully reverted state for service " - << upgrade_service_id; -} - -// Called by BWU initiator. Set up WebRTC upgraded medium for this endpoint, -// and returns a upgrade path info (PeerId, LocationHint) for remote party to -// perform discovery. -std::string WebrtcBwuHandler::HandleInitializeUpgradedMediumForEndpoint( - ClientProxy* client, const std::string& upgrade_service_id, - const std::string& endpoint_id) { - LocationHint location_hint = BuildLocationHint( - api::WebRtcImplementationPlatform::GetDefaultCountryCode()); - - mediums::WebrtcPeerId self_id{mediums::WebrtcPeerId::FromRandom()}; - if (!webrtc_.IsAcceptingConnections(upgrade_service_id)) { - if (!webrtc_.StartAcceptingConnections( - upgrade_service_id, self_id, location_hint, - absl::bind_front(&WebrtcBwuHandler::OnIncomingWebrtcConnection, - this, client), - client->GetWebRtcNonCellular())) { - LOG(ERROR) << "WebRtcBwuHandler couldn't initiate the WEB_RTC " - "upgrade for endpoint " - << endpoint_id - << " because it failed to start listening for " - "incoming WebRTC connections."; - return {}; - } - LOG(INFO) << "WebRtcBwuHandler successfully started listening for " - "incoming WebRTC connections while upgrading endpoint " - << endpoint_id; - } - - return parser::ForBwuWebrtcPathAvailable(self_id.GetId(), location_hint); -} - -// Accept Connection Callback. -// Notifies that the remote party called WebRtc::Connect() -// for this socket. -void WebrtcBwuHandler::OnIncomingWebrtcConnection( - ClientProxy* client, const std::string& upgrade_service_id, - std::shared_ptr socket) { - auto channel = std::make_unique( - upgrade_service_id, /*channel_name=*/upgrade_service_id, socket); - auto webrtc_socket = std::make_unique( - upgrade_service_id, std::move(socket)); - std::unique_ptr connection( - new IncomingSocketConnection{std::move(webrtc_socket), - std::move(channel)}); - - NotifyOnIncomingConnection(client, std::move(connection)); -} - -} // namespace connections -} // namespace nearby diff --git a/connections/implementation/mediums/webrtc/webrtc_bwu_handler.h b/connections/implementation/mediums/webrtc/webrtc_bwu_handler.h deleted file mode 100644 index f7429a44..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_bwu_handler.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_BWU_HANDLER_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_BWU_HANDLER_H_ - -#include -#include - -#include "absl/base/nullability.h" -#include "connections/implementation/base_bwu_handler.h" -#include "connections/implementation/bwu_handler.h" -#include "connections/implementation/client_proxy.h" -#include "connections/implementation/endpoint_channel.h" -#include "connections/implementation/mediums/webrtc.h" -#include "connections/implementation/mediums/webrtc_socket.h" -#include "connections/medium_selector.h" -#include "internal/platform/expected.h" - -namespace nearby { -namespace connections { - -// Defines the set of methods that need to be implemented to handle the -// per-Medium-specific operations needed to upgrade an EndpointChannel. -class WebrtcBwuHandler : public BaseBwuHandler { - public: - WebrtcBwuHandler( - mediums::WebRtc* absl_nonnull webrtc_medium, - IncomingConnectionCallback incoming_connection_callback); - - private: - class WebrtcIncomingSocket : public BwuHandler::IncomingSocket { - public: - explicit WebrtcIncomingSocket( - const std::string& name, std::shared_ptr socket); - - std::string ToString() override; - void Close() override; - - private: - std::string name_; - std::shared_ptr socket_; - }; - - // BwuHandler implementation: - ErrorOr> CreateUpgradedEndpointChannel( - ClientProxy* client, const std::string& service_id, - const std::string& endpoint_id, - const location::nearby::connections::BandwidthUpgradeNegotiationFrame:: - UpgradePathInfo& upgrade_path_info) final; - location::nearby::proto::connections::Medium GetUpgradeMedium() const final { - return Medium::WEB_RTC; - } - void OnEndpointDisconnect(ClientProxy* client, - const std::string& endpoint_id) final {} - - // BaseBwuHandler implementation: - std::string HandleInitializeUpgradedMediumForEndpoint( - ClientProxy* client, const std::string& upgrade_service_id, - const std::string& endpoint_id) final; - void HandleRevertInitiatorStateForService( - const std::string& upgrade_service_id) final; - - void OnIncomingWebrtcConnection( - ClientProxy* client, const std::string& upgrade_service_id, - std::shared_ptr socket); - - mediums::WebRtc& webrtc_; -}; - -} // namespace connections -} // namespace nearby - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_BWU_HANDLER_H_ diff --git a/connections/implementation/mediums/webrtc/webrtc_bwu_handler_test.cc b/connections/implementation/mediums/webrtc/webrtc_bwu_handler_test.cc deleted file mode 100644 index fc407a65..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_bwu_handler_test.cc +++ /dev/null @@ -1,139 +0,0 @@ - -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include "connections/implementation/mediums/webrtc/webrtc_bwu_handler.h" - -#include -#include -#include - -#include "gtest/gtest.h" -#include "absl/time/time.h" -#include "connections/implementation/bwu_handler.h" -#include "connections/implementation/client_proxy.h" -#include "connections/implementation/endpoint_channel.h" -#include "connections/implementation/mediums/webrtc/webrtc_impl.h" -#include "connections/implementation/offline_frames.h" -#include "internal/platform/count_down_latch.h" -#include "internal/platform/exception.h" -#include "internal/platform/expected.h" -#include "internal/platform/feature_flags.h" -#include "internal/platform/logging.h" -#include "internal/platform/medium_environment.h" -#include "internal/platform/single_thread_executor.h" -namespace nearby { -namespace connections { -namespace { -using ::location::nearby::connections::OfflineFrame; -using ::location::nearby::proto::connections::OperationResultCode; -constexpr absl::Duration kWaitDuration = absl::Milliseconds(5000); -class WebrtcBwuTest : public ::testing::Test { - protected: - WebrtcBwuTest() { - original_flags_ = FeatureFlags::GetInstance().GetFlags(); - env_.Start({.webrtc_enabled = true}); - } - ~WebrtcBwuTest() override { - FeatureFlags::GetMutableInstanceForTesting().SetFlags(original_flags_); - env_.Stop(); - } - void RunCreateEndpointChannelTest(bool enable_cancellation); - MediumEnvironment& env_{MediumEnvironment::Instance()}; - FeatureFlags::Flags original_flags_; -}; -void WebrtcBwuTest::RunCreateEndpointChannelTest(bool enable_cancellation) { - FeatureFlags::Flags flags = original_flags_; - flags.enable_cancellation_flag = enable_cancellation; - FeatureFlags::GetMutableInstanceForTesting().SetFlags(flags); - CountDownLatch start_latch(1); - CountDownLatch accept_latch(1); - CountDownLatch end_latch(1); - ClientProxy client_1, client_2; - auto webrtc_1 = std::make_unique(); - auto webrtc_2 = std::make_unique(); - ExceptionOr upgrade_frame; - std::unique_ptr handler_1 = std::make_unique( - webrtc_1.get(), - [&](ClientProxy* client, - std::unique_ptr connection) { - LOG(INFO) << "Handler 1 callback triggered"; - accept_latch.CountDown(); - }); - std::unique_ptr handler_2 = std::make_unique( - webrtc_2.get(), - [&](ClientProxy* client, - std::unique_ptr connection) { - LOG(INFO) << "Handler 2 callback triggered"; - }); - // Server starts advertising. - SingleThreadExecutor server_executor; - server_executor.Execute([&]() { - std::string upgrade_frame_bytes = - handler_1->InitializeUpgradedMediumForEndpoint( - &client_1, /*upgrade_service_id=*/"A", /*endpoint_id=*/"1"); - EXPECT_FALSE(upgrade_frame_bytes.empty()); - upgrade_frame = parser::FromBytes(upgrade_frame_bytes); - start_latch.CountDown(); - }); - // Client connects. - EXPECT_TRUE(start_latch.Await(kWaitDuration).result()); - if (enable_cancellation) { - client_2.AddCancellationFlag(/*endpoint_id=*/"1"); - client_2.GetCancellationFlag(/*endpoint_id=*/"1")->Cancel(); - } - SingleThreadExecutor client_executor; - client_executor.Execute([&]() { - auto bwu_frame = - upgrade_frame.result().v1().bandwidth_upgrade_negotiation(); - auto result = handler_2->CreateUpgradedEndpointChannel( - &client_2, /*service_id=*/"A", - /*endpoint_id=*/"1", bwu_frame.upgrade_path_info()); - if (!enable_cancellation) { - ASSERT_TRUE(result.has_value()); - std::unique_ptr new_channel = std::move(result.value()); - EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - EXPECT_EQ(new_channel->GetMedium(), - location::nearby::proto::connections::Medium::WEB_RTC); - } else { - EXPECT_FALSE(result.has_value()); - EXPECT_TRUE(result.has_error()); - EXPECT_EQ(result.error().operation_result_code(), - OperationResultCode:: - CLIENT_CANCELLATION_CANCEL_WEB_RTC_OUTGOING_CONNECTION); - accept_latch.CountDown(); - } - handler_1->RevertResponderState(/*service_id=*/"A"); - end_latch.CountDown(); - }); - EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); - EXPECT_TRUE(end_latch.Await(kWaitDuration).result()); -} -TEST_F(WebrtcBwuTest, CanCreateBwuHandler) { - auto webrtc = std::make_unique(); - std::unique_ptr handler = std::make_unique( - webrtc.get(), - [](ClientProxy* client, - std::unique_ptr connection) {}); - EXPECT_EQ(handler->GetUpgradeMedium(), - location::nearby::proto::connections::Medium::WEB_RTC); -} -TEST_F(WebrtcBwuTest, CreateEndpointChannel_WithCancellation) { - RunCreateEndpointChannelTest(true); -} -TEST_F(WebrtcBwuTest, CreateEndpointChannel_NoCancellation) { - RunCreateEndpointChannelTest(false); -} -} // namespace -} // namespace connections -} // namespace nearby diff --git a/connections/implementation/mediums/webrtc/webrtc_endpoint_channel.cc b/connections/implementation/mediums/webrtc/webrtc_endpoint_channel.cc deleted file mode 100644 index bf939ea5..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_endpoint_channel.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/webrtc_endpoint_channel.h" - -#include -#include -#include - -#include "connections/implementation/base_endpoint_channel.h" -#include "connections/implementation/mediums/webrtc_socket.h" - -namespace nearby { -namespace connections { - -WebRtcEndpointChannel::WebRtcEndpointChannel( - const std::string& service_id, const std::string& channel_name, - std::shared_ptr socket) - : BaseEndpointChannel(service_id, channel_name, &socket->GetInputStream(), - &socket->GetOutputStream()), - webrtc_socket_(std::move(socket)) {} - -location::nearby::proto::connections::Medium WebRtcEndpointChannel::GetMedium() - const { - return location::nearby::proto::connections::Medium::WEB_RTC; -} - -void WebRtcEndpointChannel::CloseImpl() { webrtc_socket_->Close(); } - -} // namespace connections -} // namespace nearby diff --git a/connections/implementation/mediums/webrtc/webrtc_endpoint_channel.h b/connections/implementation/mediums/webrtc/webrtc_endpoint_channel.h deleted file mode 100644 index 6ceff1c6..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_endpoint_channel.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_ENDPOINT_CHANNEL_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_ENDPOINT_CHANNEL_H_ - -#include -#include - -#include "connections/implementation/base_endpoint_channel.h" -#include "connections/implementation/mediums/webrtc_socket.h" - -namespace nearby { -namespace connections { - -class WebRtcEndpointChannel final : public BaseEndpointChannel { - public: - WebRtcEndpointChannel(const std::string& service_id, - const std::string& channel_name, - std::shared_ptr socket); - - location::nearby::proto::connections::Medium GetMedium() const override; - - private: - void CloseImpl() override; - - std::shared_ptr webrtc_socket_; -}; - -} // namespace connections -} // namespace nearby - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_ENDPOINT_CHANNEL_H_ diff --git a/connections/implementation/mediums/webrtc/webrtc_impl.cc b/connections/implementation/mediums/webrtc/webrtc_impl.cc deleted file mode 100644 index 9732aac9..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_impl.cc +++ /dev/null @@ -1,793 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/webrtc_impl.h" - -#include -#include -#include -#include -#include - -#include "absl/container/flat_hash_set.h" -#include "absl/functional/bind_front.h" -#include "absl/time/time.h" -#include "connections/implementation/bwu_handler.h" -#include "connections/implementation/mediums/webrtc/connection_flow.h" -#include "connections/implementation/mediums/webrtc/session_description_wrapper.h" -#include "connections/implementation/mediums/webrtc/signaling_frames.h" -#include "connections/implementation/mediums/webrtc/webrtc.h" -#include "connections/implementation/mediums/webrtc/webrtc_bwu_handler.h" -#include "connections/implementation/mediums/webrtc_peer_id.h" -#include "connections/implementation/mediums/webrtc_socket.h" -#include "internal/platform/byte_array.h" -#include "internal/platform/cancelable_alarm.h" -#include "internal/platform/cancellation_flag.h" -#include "internal/platform/cancellation_flag_listener.h" -#include "internal/platform/exception.h" -#include "internal/platform/expected.h" -#include "internal/platform/feature_flags.h" -#include "internal/platform/future.h" -#include "internal/platform/logging.h" -#include "internal/platform/mutex_lock.h" -#include "internal/platform/runnable.h" -#include "webrtc/api/jsep.h" -#include "webrtc/rtc_base/network_constants.h" - -namespace nearby { -namespace connections { -namespace mediums { - -namespace { -using ::location::nearby::connections::LocationHint; -using ::location::nearby::proto::connections::OperationResultCode; - -// The maximum amount of time to wait to connect to a data channel via WebRTC. -constexpr absl::Duration kDataChannelTimeout = absl::Seconds(10); - -// Delay between restarting signaling messenger to receive messages. -constexpr absl::Duration kRestartReceiveMessagesDuration = absl::Seconds(60); - -} // namespace - -WebRtcImpl::WebRtcImpl() : WebRtcImpl(std::make_unique()) {} - -WebRtcImpl::WebRtcImpl(std::unique_ptr medium) - : medium_(std::move(medium)) {} - -WebRtcImpl::~WebRtcImpl() { - // This ensures that all pending callbacks are run before we reset the medium - // and we are not accepting new runnables. - single_thread_executor_.Shutdown(); - - // Stop accepting all connections - absl::flat_hash_set service_ids; - for (auto& item : accepting_connections_info_) { - service_ids.emplace(item.first); - } - for (const auto& service_id : service_ids) { - StopAcceptingConnections(service_id); - } -} - -bool WebRtcImpl::IsAvailable() { return medium_->IsValid(); } - -bool WebRtcImpl::IsAcceptingConnections(const std::string& service_id) { - MutexLock lock(&mutex_); - return IsAcceptingConnectionsLocked(service_id); -} - -bool WebRtcImpl::IsAcceptingConnectionsLocked(const std::string& service_id) { - return accepting_connections_info_.contains(service_id); -} - -bool WebRtcImpl::StartAcceptingConnections(const std::string& service_id, - const WebrtcPeerId& self_peer_id, - const LocationHint& location_hint, - AcceptedConnectionCallback callback, - bool non_cellular) { - MutexLock lock(&mutex_); - if (!IsAvailable()) { - LOG(WARNING) << "Cannot start accepting WebRTC connections because " - "WebRTC is not available."; - return false; - } - - if (IsAcceptingConnectionsLocked(service_id)) { - LOG(WARNING) << "Cannot start accepting WebRTC connections because service " - << service_id << "is already accepting WebRTC connections."; - return false; - } - - // We'll track our state here, so that we're separated from the other services - // who may be also using WebRTC. - AcceptingConnectionsInfo info = AcceptingConnectionsInfo(); - info.self_peer_id = self_peer_id; - info.accepted_connection_callback = std::move(callback); - - medium_->SetNonCellular(non_cellular); - - // Create a new SignalingMessenger so that we can communicate w/ Tachyon. - info.signaling_messenger = - medium_->GetSignalingMessenger(self_peer_id.GetId(), location_hint); - if (!info.signaling_messenger->IsValid()) { - return false; - } - - // This registers ourselves w/ Tachyon, creating a room from the PeerId. - // This allows a remote device to message us over Tachyon. - if (!info.signaling_messenger->StartReceivingMessages( - absl::bind_front(&WebRtcImpl::OnSignalingMessage, this, service_id), - absl::bind_front(&WebRtcImpl::OnSignalingComplete, this, - service_id))) { - info.signaling_messenger.reset(); - return false; - } - - // We'll automatically disconnect from Tachyon after 60sec. When this alarm - // fires, we'll recreate our room so we continue to receive messages. - info.restart_tachyon_receive_messages_alarm = - std::make_unique( - "restart_receiving_messages_webrtc", - std::bind(&WebRtcImpl::ProcessRestartTachyonReceiveMessages, this, - service_id), - kRestartReceiveMessagesDuration, &single_thread_executor_); - - // Now that we're set up to receive messages, we'll save our state and return - // a successful result. - accepting_connections_info_.emplace(service_id, std::move(info)); - LOG(INFO) << "Started listening for WebRTC connections as " - << self_peer_id.GetId() << " on service " << service_id; - return true; -} - -void WebRtcImpl::StopAcceptingConnections(const std::string& service_id) { - MutexLock lock(&mutex_); - if (!IsAcceptingConnectionsLocked(service_id)) { - LOG(WARNING) << "Cannot stop accepting WebRTC connections because service " - << service_id << "is not accepting WebRTC connections."; - return; - } - - // Grab our info from the map. - auto& info = accepting_connections_info_.find(service_id)->second; - - // Stop receiving messages from Tachyon. - info.signaling_messenger->StopReceivingMessages(); - info.signaling_messenger.reset(); - - // Cancel the scheduled alarm. - if (info.restart_tachyon_receive_messages_alarm && - info.restart_tachyon_receive_messages_alarm->IsValid()) { - info.restart_tachyon_receive_messages_alarm->Cancel(); - info.restart_tachyon_receive_messages_alarm.reset(); - } - - // If we had any in-progress connections that haven't materialized into full - // DataChannels yet, it's time to shut them down since they can't reach us - // anymore. - absl::flat_hash_set peer_ids; - for (auto& item : connection_flows_) { - peer_ids.emplace(item.first); - } - for (const auto& peer_id : peer_ids) { - const auto& entry = connection_flows_.find(peer_id); - // Skip outgoing connections in this step. Start/StopAcceptingConnections - // only deals with incoming connections. - if (requesting_connections_info_.contains(peer_id)) { - continue; - } - - // Skip fully connected connections in this step. If the connection was - // formed while we were accepting connections, then it will stay alive until - // it's explicitly closed. - if (!entry->second->CloseIfNotConnected()) { - continue; - } - - connection_flows_.erase(peer_id); - } - - // Clean up our state. We're now no longer listening for connections. - accepting_connections_info_.erase(service_id); - LOG(INFO) << "Stopped listening for WebRTC connections for service " - << service_id; -} - -ErrorOr> WebRtcImpl::Connect( - const std::string& service_id, const WebrtcPeerId& remote_peer_id, - const LocationHint& location_hint, CancellationFlag* cancellation_flag, - bool non_cellular) { - service_id_to_connect_attempts_count_map_[service_id] = 1; - medium_->SetNonCellular(non_cellular); - ErrorOr> wrapper_result = { - Error(OperationResultCode::DETAIL_UNKNOWN)}; - while (service_id_to_connect_attempts_count_map_[service_id] <= - kConnectAttemptsLimit) { - if (cancellation_flag->Cancelled()) { - LOG(WARNING) << "Attempt #" - << service_id_to_connect_attempts_count_map_[service_id] - << ": Cannot Connect with WebRtc due to cancel."; - return { - Error(OperationResultCode:: - CLIENT_CANCELLATION_CANCEL_WEB_RTC_OUTGOING_CONNECTION)}; - } - - LOG(INFO) << "Attempt #" - << service_id_to_connect_attempts_count_map_[service_id] - << ": Beginning connection."; - wrapper_result = AttemptToConnect(service_id, remote_peer_id, location_hint, - cancellation_flag); - if (wrapper_result.has_value()) { - return std::move(wrapper_result.value()); - } - - service_id_to_connect_attempts_count_map_[service_id]++; - } - - LOG(WARNING) << "Giving up after " << kConnectAttemptsLimit << " attempts"; - return {Error(wrapper_result.error().operation_result_code().value())}; -} - -ErrorOr> WebRtcImpl::AttemptToConnect( - const std::string& service_id, const WebrtcPeerId& remote_peer_id, - const LocationHint& location_hint, CancellationFlag* cancellation_flag) { - ConnectionRequestInfo info = ConnectionRequestInfo(); - info.self_peer_id = WebrtcPeerId::FromRandom(); - Future> socket_future = info.socket_future; - - // `listener` will go out of scope at the end of `AttemptToConnect`, and this - // is expected. This `listener` is tied to `socket_future` which we block on - // within this stack call, and will not go out of scope until the attempt - // is complete. - CancellationFlagListener listener( - cancellation_flag, [this, &service_id, &socket_future]() { - LOG(WARNING) << "Attempt # " - << service_id_to_connect_attempts_count_map_[service_id] - << " to connect with WebRtc stopped due to cancel."; - socket_future.SetException({Exception::kFailed}); - }); - - { - MutexLock lock(&mutex_); - if (!IsAvailable()) { - LOG(WARNING) << "Cannot connect to WebRTC peer " << remote_peer_id.GetId() - << " because WebRTC is not available."; - return { - Error(OperationResultCode::MEDIUM_UNAVAILABLE_WEB_RTC_NOT_AVAILABLE)}; - } - - // Create a new ConnectionFlow for this connection attempt. - std::unique_ptr connection_flow = - CreateConnectionFlow(service_id, remote_peer_id); - if (!connection_flow) { - LOG(INFO) << "Cannot connect to WebRTC peer " << remote_peer_id.GetId() - << " because we failed to create a ConnectionFlow."; - return {Error(OperationResultCode::NEARBY_WEB_RTC_CONNECTION_FLOW_NULL)}; - } - - // Create a new SignalingMessenger so that we can communicate over Tachyon. - info.signaling_messenger = medium_->GetSignalingMessenger( - info.self_peer_id.GetId(), location_hint); - if (!info.signaling_messenger->IsValid()) { - LOG(INFO) << "Cannot connect to WebRTC peer " << remote_peer_id.GetId() - << " because we failed to create a SignalingMessenger."; - return { - Error(OperationResultCode:: - MISCELLEANEOUS_WEB_RTC_TACHYON_SIGNALING_MESSENGER_NULL)}; - } - - // This registers ourselves w/ Tachyon, creating a room from the PeerId. - // This allows a remote device to message us over Tachyon. - auto signaling_complete_callback = [socket_future](bool success) mutable { - if (!success) { - socket_future.SetException({Exception::kFailed}); - } - }; - if (!info.signaling_messenger->StartReceivingMessages( - absl::bind_front(&WebRtcImpl::OnSignalingMessage, this, service_id), - signaling_complete_callback)) { - LOG(INFO) - << "Cannot connect to WebRTC peer " << remote_peer_id.GetId() - << " because we failed to start receiving messages over Tachyon."; - info.signaling_messenger.reset(); - return {Error(OperationResultCode:: - MISCELLEANEOUS_WEB_RTC_FAILED_TO_RECEIVE_MESSAGE)}; - } - - // Poke the remote device. This will cause them to send us an Offer. - if (!info.signaling_messenger->SendMessage( - remote_peer_id.GetId(), - webrtc_frames::EncodeReadyForSignalingPoke(info.self_peer_id))) { - LOG(INFO) << "Cannot connect to WebRTC peer " << remote_peer_id.GetId() - << " because we failed to poke the peer over Tachyon."; - info.signaling_messenger.reset(); - return {Error(OperationResultCode:: - CONNECTIVITY_WEB_RTC_CONNECT_TO_TACHYON_FAILURE)}; - } - - // Create a new ConnectionRequest entry. This map will be used later to look - // up state as we negotiate the connection over Tachyon. - requesting_connections_info_.emplace(remote_peer_id.GetId(), - std::move(info)); - connection_flows_.emplace(remote_peer_id.GetId(), - std::move(connection_flow)); - } - - // Wait for the connection to go through. Don't hold the mutex here so that - // we're not blocking necessary operations. - ExceptionOr> socket_result = - socket_future.Get(kDataChannelTimeout); - - { - MutexLock lock(&mutex_); - - // Reclaim our info, since we had released ownership while talking to - // Tachyon. - auto& info = - requesting_connections_info_.find(remote_peer_id.GetId())->second; - - // Verify that the connection went through. - if (!socket_result.ok()) { - LOG(INFO) << "Failed to connect to WebRTC peer " - << remote_peer_id.GetId(); - RemoveConnectionFlow(remote_peer_id); - info.signaling_messenger.reset(); - requesting_connections_info_.erase(remote_peer_id.GetId()); - return {Error(OperationResultCode:: - CONNECTIVITY_WEB_RTC_CLIENT_SOCKET_CREATION_FAILURE)}; - } - - // Clean up our ConnectionRequest. - info.signaling_messenger.reset(); - requesting_connections_info_.erase(remote_peer_id.GetId()); - - // Return the result. - return socket_result.GetResult(); - } -} - -void WebRtcImpl::ProcessLocalIceCandidate( - const std::string& service_id, const WebrtcPeerId& remote_peer_id, - const location::nearby::mediums::IceCandidate ice_candidate) { - MutexLock lock(&mutex_); - - // Check first if we have an outgoing request w/ this peer. As this request is - // tied to a specific peer, it takes precedence. - const auto& connection_request_entry = - requesting_connections_info_.find(remote_peer_id.GetId()); - if (connection_request_entry != requesting_connections_info_.end()) { - // Pass the ice candidate to the remote side. - if (!connection_request_entry->second.signaling_messenger->SendMessage( - remote_peer_id.GetId(), - webrtc_frames::EncodeIceCandidates( - connection_request_entry->second.self_peer_id, - {ice_candidate}))) { - LOG(INFO) << "Failed to send ice candidate to " << remote_peer_id.GetId(); - } - - LOG(INFO) << "Sent ice candidate to " << remote_peer_id.GetId(); - return; - } - - // Check next if we're expecting incoming connection requests. - const auto& accepting_connection_entry = - accepting_connections_info_.find(service_id); - if (accepting_connection_entry != accepting_connections_info_.end()) { - // Pass the ice candidate to the remote side. - // TODO(xlythe) Consider not blocking here, since this can eat into the - // connection time - if (!accepting_connection_entry->second.signaling_messenger->SendMessage( - remote_peer_id.GetId(), - webrtc_frames::EncodeIceCandidates( - accepting_connection_entry->second.self_peer_id, - {ice_candidate}))) { - LOG(INFO) << "Failed to send ice candidate to " << remote_peer_id.GetId(); - } - - LOG(INFO) << "Sent ice candidate to " << remote_peer_id.GetId(); - return; - } - - LOG(INFO) << "Skipping restart listening for tachyon inbox messages " - "since we are not accepting connections for service " - << service_id; -} - -void WebRtcImpl::OnSignalingMessage(const std::string& service_id, - const ByteArray& message) { - OffloadFromThread("rtc-on-signaling-message", [this, service_id, message]() { - ProcessTachyonInboxMessage(service_id, message); - }); -} - -void WebRtcImpl::OnSignalingComplete(const std::string& service_id, - bool success) { - LOG(INFO) << "Signaling completed with status: " << success; - if (success) { - return; - } - - OffloadFromThread("rtc-on-signaling-complete", [this, service_id]() { - MutexLock lock(&mutex_); - const auto& info_entry = accepting_connections_info_.find(service_id); - if (info_entry == accepting_connections_info_.end()) { - return; - } - - if (info_entry->second.restart_accept_connections_count < - kRestartAcceptConnectionsLimit) { - ++info_entry->second.restart_accept_connections_count; - } else { - return; - } - - RestartTachyonReceiveMessages(service_id); - }); -} - -void WebRtcImpl::ProcessTachyonInboxMessage(const std::string& service_id, - const ByteArray& message) { - MutexLock lock(&mutex_); - - // Attempt to parse the incoming message as a WebRtcSignalingFrame. - location::nearby::mediums::WebRtcSignalingFrame frame; - if (!frame.ParseFromString(std::string(message))) { - LOG(WARNING) << "Failed to parse signaling message."; - return; - } - - // Ensure that the frame is valid (no missing fields). - if (!frame.has_sender_id()) { - LOG(WARNING) << "Invalid WebRTC frame: Sender ID is missing."; - return; - } - WebrtcPeerId remote_peer_id = WebrtcPeerId(frame.sender_id().id()); - - // Depending on the message type, we'll respond as appropriate. - if (requesting_connections_info_.contains(remote_peer_id.GetId())) { - // This is from a peer we have an outgoing connection request with, so we'll - // only process the Answer path. - if (frame.has_offer()) { - ReceiveOffer(remote_peer_id, - SessionDescriptionWrapper( - webrtc_frames::DecodeOffer(frame).release())); - SendAnswer(remote_peer_id); - } else if (frame.has_ice_candidates()) { - ReceiveIceCandidates(remote_peer_id, - webrtc_frames::DecodeIceCandidates(frame)); - } else { - LOG(INFO) << "Received unknown WebRTC frame: ignoring."; - } - } else if (IsAcceptingConnectionsLocked(service_id)) { - // We don't have an outgoing connection request with this peer, but we are - // accepting incoming requests so we'll only process the Offer path. - if (frame.has_ready_for_signaling_poke()) { - SendOffer(service_id, remote_peer_id); - } else if (frame.has_answer()) { - ReceiveAnswer(remote_peer_id, - SessionDescriptionWrapper( - webrtc_frames::DecodeAnswer(frame).release())); - } else if (frame.has_ice_candidates()) { - ReceiveIceCandidates(remote_peer_id, - webrtc_frames::DecodeIceCandidates(frame)); - } else { - LOG(INFO) << "Received unknown WebRTC frame: ignoring."; - } - } else { - LOG(INFO) - << "Ignoring Tachyon message since we are not accepting connections."; - } -} - -void WebRtcImpl::SendOffer(const std::string& service_id, - const WebrtcPeerId& remote_peer_id) { - std::unique_ptr connection_flow = - CreateConnectionFlow(service_id, remote_peer_id); - if (!connection_flow) { - LOG(INFO) << "Unable to send offer. Failed to create a ConnectionFlow."; - return; - } - - SessionDescriptionWrapper offer = connection_flow->CreateOffer(); - if (!offer.IsValid()) { - LOG(INFO) << "Unable to send offer. Failed to create our offer locally."; - RemoveConnectionFlow(remote_peer_id); - return; - } - - const webrtc::SessionDescriptionInterface& sdp = offer.GetSdp(); - if (!connection_flow->SetLocalSessionDescription(offer)) { - LOG(INFO) << "Unable to send offer. Failed to register our offer locally."; - RemoveConnectionFlow(remote_peer_id); - return; - } - - // Grab our info from the map. - auto& info = accepting_connections_info_.find(service_id)->second; - - // Pass the offer to the remote side. - if (!info.signaling_messenger->SendMessage( - remote_peer_id.GetId(), - webrtc_frames::EncodeOffer(info.self_peer_id, sdp))) { - LOG(INFO) - << "Unable to send offer. Failed to write the offer to the remote peer " - << remote_peer_id.GetId(); - RemoveConnectionFlow(remote_peer_id); - return; - } - - // Store the ConnectionFlow so that other methods can use it later. - connection_flows_.emplace(remote_peer_id.GetId(), std::move(connection_flow)); - LOG(INFO) << "Sent offer to " << remote_peer_id.GetId(); -} - -void WebRtcImpl::ReceiveOffer(const WebrtcPeerId& remote_peer_id, - SessionDescriptionWrapper offer) { - const auto& entry = connection_flows_.find(remote_peer_id.GetId()); - if (entry == connection_flows_.end()) { - LOG(INFO) << "Unable to receive offer. Failed to create a ConnectionFlow."; - return; - } - - if (!entry->second->OnOfferReceived(offer)) { - LOG(INFO) << "Unable to receive offer. Failed to process the offer."; - RemoveConnectionFlow(remote_peer_id); - } -} - -void WebRtcImpl::SendAnswer(const WebrtcPeerId& remote_peer_id) { - const auto& entry = connection_flows_.find(remote_peer_id.GetId()); - if (entry == connection_flows_.end()) { - LOG(INFO) << "Unable to send answer. Failed to create a ConnectionFlow."; - return; - } - - SessionDescriptionWrapper answer = entry->second->CreateAnswer(); - if (!answer.IsValid()) { - LOG(INFO) << "Unable to send answer. Failed to create our answer locally."; - RemoveConnectionFlow(remote_peer_id); - return; - } - - const webrtc::SessionDescriptionInterface& sdp = answer.GetSdp(); - if (!entry->second->SetLocalSessionDescription(answer)) { - LOG(INFO) - << "Unable to send answer. Failed to register our answer locally."; - RemoveConnectionFlow(remote_peer_id); - return; - } - - // Grab our info from the map. - const auto& connection_request_entry = - requesting_connections_info_.find(remote_peer_id.GetId()); - if (connection_request_entry == requesting_connections_info_.end()) { - LOG(INFO) << "Unable to send answer. Failed to find an outgoing " - "connection request."; - RemoveConnectionFlow(remote_peer_id); - return; - } - - // Pass the answer to the remote side. - if (!connection_request_entry->second.signaling_messenger->SendMessage( - remote_peer_id.GetId(), - webrtc_frames::EncodeAnswer( - connection_request_entry->second.self_peer_id, sdp))) { - LOG(INFO) - << "Unable to send answer. Failed to write the answer to the remote " - "peer " - << remote_peer_id.GetId(); - RemoveConnectionFlow(remote_peer_id); - return; - } - - LOG(INFO) << "Sent answer to " << remote_peer_id.GetId(); -} - -void WebRtcImpl::ReceiveAnswer(const WebrtcPeerId& remote_peer_id, - SessionDescriptionWrapper answer) { - const auto& entry = connection_flows_.find(remote_peer_id.GetId()); - if (entry == connection_flows_.end()) { - LOG(INFO) << "Unable to receive answer. Failed to create a ConnectionFlow."; - return; - } - - if (!entry->second->OnAnswerReceived(answer)) { - LOG(INFO) << "Unable to receive answer. Failed to process the answer."; - RemoveConnectionFlow(remote_peer_id); - } -} - -void WebRtcImpl::ReceiveIceCandidates( - const WebrtcPeerId& remote_peer_id, - std::vector> ice_candidates) { - const auto& entry = connection_flows_.find(remote_peer_id.GetId()); - if (entry == connection_flows_.end()) { - LOG(INFO) << "Unable to receive ice candidates. Failed to create a " - "ConnectionFlow."; - return; - } - - entry->second->OnRemoteIceCandidatesReceived(std::move(ice_candidates)); -} - -void WebRtcImpl::ProcessRestartTachyonReceiveMessages( - const std::string& service_id) { - MutexLock lock(&mutex_); - RestartTachyonReceiveMessages(service_id); -} - -void WebRtcImpl::RestartTachyonReceiveMessages(const std::string& service_id) { - if (!IsAcceptingConnectionsLocked(service_id)) { - LOG(INFO) - << "Skipping restart listening for tachyon inbox messages since we are " - "not accepting connections for service " - << service_id; - return; - } - - // Grab our info from the map. - auto& info = accepting_connections_info_.find(service_id)->second; - - // Ensure we've disconnected from Tachyon. - info.signaling_messenger->StopReceivingMessages(); - - // Attempt to re-register. - if (!info.signaling_messenger->StartReceivingMessages( - absl::bind_front(&WebRtcImpl::OnSignalingMessage, this, service_id), - absl::bind_front(&WebRtcImpl::OnSignalingComplete, this, - service_id))) { - LOG(WARNING) - << "Failed to restart listening for tachyon inbox messages for " - "service " - << service_id << " since we failed to reach Tachyon."; - return; - } - - LOG(INFO) << "Successfully restarted listening for tachyon inbox " - "messages on service " - << service_id; -} - -void WebRtcImpl::ProcessDataChannelOpen( - const std::string& service_id, const WebrtcPeerId& remote_peer_id, - std::shared_ptr socket_wrapper) { - MutexLock lock(&mutex_); - - // Notify the client of the newly formed socket. - const auto& connection_request_entry = - requesting_connections_info_.find(remote_peer_id.GetId()); - if (connection_request_entry != requesting_connections_info_.end()) { - connection_request_entry->second.socket_future.Set(socket_wrapper); - return; - } - - const auto& accepting_connection_entry = - accepting_connections_info_.find(service_id); - if (accepting_connection_entry != accepting_connections_info_.end() && - accepting_connection_entry->second.accepted_connection_callback) { - accepting_connection_entry->second.accepted_connection_callback( - service_id, socket_wrapper); - return; - } - - // No one to handle the newly created DataChannel, so we'll just close it. - socket_wrapper->Close(); - LOG(INFO) << "Ignoring new DataChannel because we are not accepting " - "connections for service " - << service_id; -} - -void WebRtcImpl::ProcessDataChannelClosed(const WebrtcPeerId& remote_peer_id) { - MutexLock lock(&mutex_); - LOG(INFO) << "Data channel has closed, removing connection flow for peer " - << remote_peer_id.GetId(); - - RemoveConnectionFlow(remote_peer_id); -} - -std::unique_ptr WebRtcImpl::CreateConnectionFlow( - const std::string& service_id, const WebrtcPeerId& remote_peer_id) { - RemoveConnectionFlow(remote_peer_id); - - return ConnectionFlow::Create( - {.local_ice_candidate_found_cb = - {[this, service_id, - remote_peer_id](const webrtc::IceCandidate* ice_candidate) { - // Note: We need to encode the ice candidate here, before we jump - // off the thread. Otherwise, it gets destroyed and we can't read - // it later. - location::nearby::mediums::IceCandidate encoded_ice_candidate = - webrtc_frames::EncodeIceCandidate(*ice_candidate); - OffloadFromThread( - "rtc-ice-candidates", - [this, service_id, remote_peer_id, encoded_ice_candidate]() { - ProcessLocalIceCandidate(service_id, remote_peer_id, - encoded_ice_candidate); - }); - }}}, - { - .data_channel_open_cb = {[this, service_id, remote_peer_id]( - std::shared_ptr - socket_wrapper) { - OffloadFromThread( - "rtc-channel-created", - [this, service_id, remote_peer_id, socket_wrapper]() { - ProcessDataChannelOpen(service_id, remote_peer_id, - socket_wrapper); - }); - }}, - .data_channel_closed_cb = {[this, remote_peer_id]() { - OffloadFromThread("rtc-channel-closed", [this, remote_peer_id]() { - ProcessDataChannelClosed(remote_peer_id); - }); - }}, - }, - { - .adapter_type_changed_cb = {[this](webrtc::AdapterType adapter_type) { - OffloadFromThread("rtc-adapter-type-changed", - [this, adapter_type]() { - if (FeatureFlags::GetInstance() - .GetFlags() - .support_web_rtc_non_cellular_medium) { - AdapterTypeChangedHandler(adapter_type); - } - }); - }}, - }, - *medium_); -} - -void WebRtcImpl::AdapterTypeChangedHandler(webrtc::AdapterType adapter_type) { - MutexLock lock(&mutex_); - is_using_cellular_ = adapter_type == webrtc::ADAPTER_TYPE_CELLULAR || - adapter_type == webrtc::ADAPTER_TYPE_CELLULAR_2G || - adapter_type == webrtc::ADAPTER_TYPE_CELLULAR_3G || - adapter_type == webrtc::ADAPTER_TYPE_CELLULAR_4G || - adapter_type == webrtc::ADAPTER_TYPE_CELLULAR_5G; -} - -void WebRtcImpl::RemoveConnectionFlow(const WebrtcPeerId& remote_peer_id) { - if (!connection_flows_.erase(remote_peer_id.GetId())) { - return; - } - - // If we had an outgoing connection request w/ this peer, report the failure - // to the future that's being waited on. - const auto& connection_request_entry = - requesting_connections_info_.find(remote_peer_id.GetId()); - if (connection_request_entry != requesting_connections_info_.end()) { - connection_request_entry->second.socket_future.SetException( - {Exception::kFailed}); - } -} - -void WebRtcImpl::OffloadFromThread(const std::string& name, Runnable runnable) { - single_thread_executor_.Execute(name, std::move(runnable)); -} - -bool WebRtcImpl::IsUsingCellular() { - MutexLock lock(&mutex_); - return is_using_cellular_; -} - -std::unique_ptr WebRtcImpl::CreateBwuHandler( - BwuHandler::IncomingConnectionCallback incoming_connection_callback) { - return std::make_unique( - this, std::move(incoming_connection_callback)); -} - -} // namespace mediums -} // namespace connections -} // namespace nearby diff --git a/connections/implementation/mediums/webrtc/webrtc_impl.h b/connections/implementation/mediums/webrtc/webrtc_impl.h deleted file mode 100644 index 92d9d5b4..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_impl.h +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_IMPL_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_IMPL_H_ - -#include -#include -#include -#include - -#include "absl/base/thread_annotations.h" -#include "absl/container/flat_hash_map.h" -#include "connections/implementation/bwu_handler.h" -#include "connections/implementation/mediums/webrtc.h" -#include "connections/implementation/mediums/webrtc/connection_flow.h" -#include "connections/implementation/mediums/webrtc/session_description_wrapper.h" -#include "connections/implementation/mediums/webrtc/webrtc.h" -#include "connections/implementation/mediums/webrtc_peer_id.h" -#include "connections/implementation/mediums/webrtc_socket.h" -#include "internal/platform/byte_array.h" -#include "internal/platform/cancelable_alarm.h" -#include "internal/platform/cancellation_flag.h" -#include "internal/platform/expected.h" -#include "internal/platform/future.h" -#include "internal/platform/mutex.h" -#include "internal/platform/runnable.h" -#include "internal/platform/scheduled_executor.h" -#include "proto/mediums/web_rtc_signaling_frames.pb.h" -#include "webrtc/api/jsep.h" -#include "webrtc/rtc_base/network_constants.h" - -namespace nearby { -namespace connections { -namespace mediums { - -// Entry point for connecting a data channel between two devices via WebRtc. -class WebRtcImpl : public WebRtc { - public: - WebRtcImpl(); - ~WebRtcImpl() override; - - // Overrides for WebRtc: - bool IsAvailable() override; - bool IsAcceptingConnections(const std::string& service_id) override - ABSL_LOCKS_EXCLUDED(mutex_); - bool StartAcceptingConnections( - const std::string& service_id, const WebrtcPeerId& self_peer_id, - const location::nearby::connections::LocationHint& location_hint, - AcceptedConnectionCallback callback, bool non_cellular) override - ABSL_LOCKS_EXCLUDED(mutex_); - void StopAcceptingConnections(const std::string& service_id) override - ABSL_LOCKS_EXCLUDED(mutex_); - ErrorOr> Connect( - const std::string& service_id, const WebrtcPeerId& peer_id, - const location::nearby::connections::LocationHint& location_hint, - CancellationFlag* cancellation_flag, bool non_cellular) override - ABSL_LOCKS_EXCLUDED(mutex_); - bool IsUsingCellular() override ABSL_LOCKS_EXCLUDED(mutex_); - std::unique_ptr CreateBwuHandler( - BwuHandler::IncomingConnectionCallback incoming_connection_callback) - override; - - protected: - // Use for unit tests only to inject a WebRtcMedium. - explicit WebRtcImpl(std::unique_ptr medium); - - // Used in unit tests to determine how many calls to `AttemptToConnect` - // occured during a call to `Connect`, per service id. - std::map service_id_to_connect_attempts_count_map_; - - private: - static constexpr int kConnectAttemptsLimit = 3; - static constexpr int kRestartAcceptConnectionsLimit = 3; - - enum class Role { - kNone = 0, - kOfferer = 1, - kAnswerer = 2, - }; - - struct AcceptingConnectionsInfo { - // The self_peer_id is generated from the BT/WiFi advertisements and allows - // the scanner to message us over Tachyon. - WebrtcPeerId self_peer_id; - - // The registered callback. When there's an incoming connection, this - // callback is notified. - AcceptedConnectionCallback accepted_connection_callback; - - // Allows us to communicate with the Tachyon web server. - std::unique_ptr signaling_messenger; - - // Restarts the tachyon inbox receives messages streaming rpc if the - // streaming rpc times out. The streaming rpc times out after 60s while - // advertising. Non-null when listening for WebRTC connections as an - // offerer. - std::unique_ptr restart_tachyon_receive_messages_alarm; - - // Tracks the number of times we've restarted receiving messages after a - // failure. We limit the number to prevent endless restarts if we are - // repeatedly unable to communicate with Tachyon. - int restart_accept_connections_count = 0; - }; - - struct ConnectionRequestInfo { - // The self_peer_id is randomly generated and allows the advertiser to - // message us over Tachyon. - WebrtcPeerId self_peer_id; - - // Allows us to communicate with the Tachyon web server. - std::unique_ptr signaling_messenger; - - // The pending DataChannel future. Our client will be blocked on this while - // they wait for us to set up the channel over Tachyon. - Future> socket_future; - }; - - // Attempt to initiates a WebRtc connection with peer device identified by - // |peer_id|. - // Runs on @MainThread. - ErrorOr> AttemptToConnect( - const std::string& service_id, const WebrtcPeerId& peer_id, - const location::nearby::connections::LocationHint& location_hint, - CancellationFlag* cancellation_flag) ABSL_LOCKS_EXCLUDED(mutex_); - - // Returns if the device is accepting connection with specific service id. - // Runs on @MainThread. - bool IsAcceptingConnectionsLocked(const std::string& service_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Receives a message from the signaling messenger. - void OnSignalingMessage(const std::string& service_id, - const ByteArray& message); - - // Decides whether to restart receiving messages. - void OnSignalingComplete(const std::string& service_id, bool success); - - // Runs on |single_thread_executor_|. - void ProcessTachyonInboxMessage(const std::string& service_id, - const ByteArray& message) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Runs on |single_thread_executor_|. - void SendOffer(const std::string& service_id, - const WebrtcPeerId& remote_peer_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void ReceiveOffer(const WebrtcPeerId& remote_peer_id, - SessionDescriptionWrapper offer) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void SendAnswer(const WebrtcPeerId& remote_peer_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void ReceiveAnswer(const WebrtcPeerId& remote_peer_id, - SessionDescriptionWrapper answer) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void ReceiveIceCandidates( - const WebrtcPeerId& remote_peer_id, - std::vector> ice_candidates) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - std::unique_ptr CreateConnectionFlow( - const std::string& service_id, const WebrtcPeerId& remote_peer_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - std::unique_ptr GetConnectionFlow( - const WebrtcPeerId& remote_peer_id) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void RemoveConnectionFlow(const WebrtcPeerId& remote_peer_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void ProcessDataChannelOpen(const std::string& service_id, - const WebrtcPeerId& remote_peer_id, - std::shared_ptr socket_wrapper) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Runs on |single_thread_executor_|. - void ProcessDataChannelClosed(const WebrtcPeerId& remote_peer_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Runs on |single_thread_executor_|. - void ProcessLocalIceCandidate( - const std::string& service_id, const WebrtcPeerId& remote_peer_id, - location::nearby::mediums::IceCandidate ice_candidate) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Runs on |single_thread_executor_|. - void ProcessRestartTachyonReceiveMessages(const std::string& service_id) - ABSL_LOCKS_EXCLUDED(mutex_); - - // Runs on |single_thread_executor_|. - void RestartTachyonReceiveMessages(const std::string& service_id) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Runs on |single_thread_executor_|. - void AdapterTypeChangedHandler(webrtc::AdapterType adapter_type) - ABSL_LOCKS_EXCLUDED(mutex_); - - void OffloadFromThread(const std::string& name, Runnable runnable); - - Mutex mutex_; - - std::unique_ptr medium_; - - // The single thread we throw the potentially blocking work on to. - ScheduledExecutor single_thread_executor_; - - // A map of ServiceID -> State for all services that are listening for - // incoming connections. - absl::flat_hash_map - accepting_connections_info_ ABSL_GUARDED_BY(mutex_); - - // A map of a remote PeerId -> State for pending connection requests. As - // messages from Tachyon come in, this lets us look up the connection request - // info to handle the interaction. - absl::flat_hash_map - requesting_connections_info_ ABSL_GUARDED_BY(mutex_); - - // A map of a remote PeerId -> ConnectionFlow. For each connection, we create - // a unique ConnectionFlow. - absl::flat_hash_map> - connection_flows_ ABSL_GUARDED_BY(mutex_); - - bool is_using_cellular_ ABSL_GUARDED_BY(mutex_) = true; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_IMPL_H_ diff --git a/connections/implementation/mediums/webrtc/webrtc_impl_test.cc b/connections/implementation/mediums/webrtc/webrtc_impl_test.cc deleted file mode 100644 index 6b50243b..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_impl_test.cc +++ /dev/null @@ -1,651 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/webrtc_impl.h" - -#include -#include -#include - -#include "gmock/gmock.h" -#include "protobuf-matchers/protocol-buffer-matchers.h" -#include "gtest/gtest.h" -#include "absl/strings/string_view.h" -#include "connections/implementation/mediums/webrtc.h" -#include "connections/implementation/mediums/webrtc/fake_webrtc.h" -#include "connections/implementation/mediums/webrtc/webrtc.h" -#include "connections/implementation/mediums/webrtc_peer_id.h" -#include "connections/implementation/mediums/webrtc_socket.h" -#include "internal/platform/byte_array.h" -#include "internal/platform/cancellation_flag.h" -#include "internal/platform/exception.h" -#include "internal/platform/expected.h" -#include "internal/platform/feature_flags.h" -#include "internal/platform/future.h" -#include "internal/platform/medium_environment.h" - -namespace nearby { -namespace connections { -namespace mediums { - -namespace { - -using FeatureFlags = FeatureFlags::Flags; -using ::location::nearby::connections::LocationHint; - -struct WebRtcTestParams { - FeatureFlags feature_flags; - bool non_cellular; -}; - -class TestWebRtc : public WebRtcImpl { - public: - explicit TestWebRtc(std::unique_ptr medium) - : WebRtcImpl(std::move(medium)) {} - - int connect_attempts_count(std::string service_id) { - return service_id_to_connect_attempts_count_map_[service_id]; - } -}; - -class WebRtcTest : public ::testing::TestWithParam { - protected: - using MockAcceptedCallback = testing::MockFunction socket)>; - - MediumEnvironment& env_{MediumEnvironment::Instance()}; -}; - -// 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_P(WebRtcTest, ConnectBothDevices_ShutdownSignaling_SendData) { - env_.Start({.webrtc_enabled = true}); - WebRtcTestParams params = GetParam(); - env_.SetFeatureFlags(params.feature_flags); - WebRtcImpl receiver, sender; - std::shared_ptr receiver_socket; - const WebrtcPeerId self_id("self_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - Future connected; - absl::string_view message("message xyz"); - - receiver.StartAcceptingConnections( - service_id, self_id, location_hint, - [&receiver_socket, connected]( - const std::string& service_id, - std::shared_ptr wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket->IsValid()); - }, - params.non_cellular); - - CancellationFlag flag; - ErrorOr> sender_socket_result = sender.Connect( - service_id, self_id, location_hint, &flag, params.non_cellular); - ASSERT_TRUE(sender_socket_result.has_value()); - EXPECT_TRUE(sender_socket_result.value()->IsValid()); - - ExceptionOr devices_connected = connected.Get(); - ASSERT_TRUE(devices_connected.ok()); - EXPECT_TRUE(devices_connected.result()); - - // Only shuts down signaling channel. - receiver.StopAcceptingConnections(service_id); - - sender_socket_result.value()->GetOutputStream().Write(message); - ExceptionOr received_msg = - receiver_socket->GetInputStream().Read(/*size=*/32); - ASSERT_TRUE(received_msg.ok()); - EXPECT_EQ(message, received_msg.result().AsStringView()); - env_.Stop(); -} - -TEST_P(WebRtcTest, CanCancelConnect) { - env_.Start({.webrtc_enabled = true}); - WebRtcTestParams params = GetParam(); - env_.SetFeatureFlags(params.feature_flags); - WebRtcImpl receiver, sender; - std::shared_ptr receiver_socket; - const WebrtcPeerId self_id("self_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - Future connected; - absl::string_view message("message"); - - receiver.StartAcceptingConnections( - service_id, self_id, location_hint, - [&receiver_socket, connected]( - const std::string& service_id, - std::shared_ptr wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket->IsValid()); - }, - params.non_cellular); - - CancellationFlag flag(true); - ErrorOr> sender_socket_result = sender.Connect( - service_id, self_id, location_hint, &flag, params.non_cellular); - // If FeatureFlag is disabled, Cancelled is false as no-op. - if (!params.feature_flags.enable_cancellation_flag) { - ASSERT_TRUE(sender_socket_result.has_value()); - EXPECT_TRUE(sender_socket_result.value()->IsValid()); - - ExceptionOr devices_connected = connected.Get(); - ASSERT_TRUE(devices_connected.ok()); - EXPECT_TRUE(devices_connected.result()); - - sender_socket_result.value()->GetOutputStream().Write(message); - ExceptionOr received_msg = - receiver_socket->GetInputStream().Read(/*size=*/32); - ASSERT_TRUE(received_msg.ok()); - EXPECT_EQ(message, received_msg.result().AsStringView()); - - receiver_socket->Close(); - } else { - EXPECT_TRUE(sender_socket_result.has_error()); - } - env_.Stop(); -} - -// Basic test to check that device is accepting connections when initialized. -TEST_P(WebRtcTest, NotAcceptingConnections) { - env_.Start({.webrtc_enabled = true}); - WebRtcImpl webrtc; - ASSERT_TRUE(webrtc.IsAvailable()); - EXPECT_FALSE(webrtc.IsAcceptingConnections(std::string{})); - env_.Stop(); -} - -// 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_P(WebRtcTest, StartAcceptingConnectionTwice) { - env_.Start({.webrtc_enabled = true}); - WebRtcTestParams params = GetParam(); - testing::StrictMock mock_accepted_callback_; - WebRtcImpl webrtc; - WebrtcPeerId self_id("peer_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint{}; - - ASSERT_TRUE(webrtc.IsAvailable()); - ASSERT_TRUE(webrtc.StartAcceptingConnections( - service_id, self_id, location_hint, - mock_accepted_callback_.AsStdFunction(), params.non_cellular)); - EXPECT_FALSE(webrtc.StartAcceptingConnections( - service_id, self_id, location_hint, - mock_accepted_callback_.AsStdFunction(), params.non_cellular)); - EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); - EXPECT_FALSE(webrtc.IsAcceptingConnections(std::string{})); - env_.Stop(); -} - -// Tests the flow when the device tries to connect but there is no peer -// accepting connections at the given peer ID. -TEST_P(WebRtcTest, Connect_NoPeer) { - env_.Start({.webrtc_enabled = true}); - WebRtcTestParams params = GetParam(); - WebRtcImpl webrtc; - WebrtcPeerId peer_id("peer_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - - ASSERT_TRUE(webrtc.IsAvailable()); - CancellationFlag flag; - ErrorOr> wrapper_1_result = webrtc.Connect( - service_id, peer_id, location_hint, &flag, params.non_cellular); - EXPECT_TRUE(wrapper_1_result.has_error()); - - EXPECT_TRUE(webrtc.StartAcceptingConnections( - service_id, peer_id, location_hint, nullptr, params.non_cellular)); - env_.Stop(); -} - -// Tests the flow when the device calls Connect() after calling -// StartAcceptingConnections() without StopAcceptingConnections(). -TEST_P(WebRtcTest, StartAcceptingConnection_ThenConnect) { - env_.Start({.webrtc_enabled = true}); - testing::StrictMock mock_accepted_callback_; - WebRtcTestParams params = GetParam(); - WebRtcImpl webrtc; - WebrtcPeerId self_id("peer_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - - ASSERT_TRUE(webrtc.IsAvailable()); - ASSERT_TRUE(webrtc.StartAcceptingConnections( - service_id, self_id, location_hint, - mock_accepted_callback_.AsStdFunction(), params.non_cellular)); - CancellationFlag flag; - ErrorOr> wrapper_result = - webrtc.Connect(service_id, WebrtcPeerId("random_peer_id"), location_hint, - &flag, params.non_cellular); - EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); - EXPECT_TRUE(wrapper_result.has_error()); - EXPECT_FALSE(webrtc.StartAcceptingConnections( - service_id, self_id, location_hint, - mock_accepted_callback_.AsStdFunction(), params.non_cellular)); - env_.Stop(); -} - -// Tests the flow when the device calls StartAcceptingConnections but the medium -// is closed before a peer device can connect to it. -TEST_P(WebRtcTest, StartAndStopAcceptingConnections) { - env_.Start({.webrtc_enabled = true}); - testing::StrictMock mock_accepted_callback_; - WebRtcTestParams params = GetParam(); - WebRtcImpl webrtc; - WebrtcPeerId self_id("peer_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - - ASSERT_TRUE(webrtc.IsAvailable()); - ASSERT_TRUE(webrtc.StartAcceptingConnections( - service_id, self_id, location_hint, - mock_accepted_callback_.AsStdFunction(), params.non_cellular)); - EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); - webrtc.StopAcceptingConnections(service_id); - EXPECT_FALSE(webrtc.IsAcceptingConnections(service_id)); - env_.Stop(); -} - -// Tests the flow when the device tries to connect to two different peers -// without disconnecting in between. -TEST_P(WebRtcTest, ConnectTwice) { - env_.Start({.webrtc_enabled = true}); - WebRtcImpl receiver, sender, device_c; - std::shared_ptr receiver_socket; - WebRtcTestParams params = GetParam(); - const WebrtcPeerId self_id("self_id"), other_id("other_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - Future connected; - absl::string_view message("message xyz"); - - receiver.StartAcceptingConnections( - service_id, self_id, location_hint, - [&receiver_socket, connected]( - const std::string& service_id, - std::shared_ptr wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket->IsValid()); - }, - params.non_cellular); - - device_c.StartAcceptingConnections( - service_id, other_id, location_hint, - [](const std::string& service_id, std::shared_ptr wrapper) { - }, - params.non_cellular); - - CancellationFlag flag; - ErrorOr> sender_socket_result = sender.Connect( - service_id, self_id, location_hint, &flag, params.non_cellular); - ASSERT_TRUE(sender_socket_result.has_value()); - EXPECT_TRUE(sender_socket_result.value()->IsValid()); - - ExceptionOr devices_connected = connected.Get(); - ASSERT_TRUE(devices_connected.ok()); - EXPECT_TRUE(devices_connected.result()); - - ErrorOr> socket_result = sender.Connect( - service_id, other_id, location_hint, &flag, params.non_cellular); - EXPECT_TRUE(socket_result.has_value()); - EXPECT_TRUE(socket_result.value()->IsValid()); - socket_result.value()->Close(); - - EXPECT_TRUE(receiver_socket->IsValid()); - ASSERT_TRUE(sender_socket_result.has_value()); - EXPECT_TRUE(sender_socket_result.value()->IsValid()); - - sender_socket_result.value()->GetOutputStream().Write(message); - ExceptionOr received_msg = - receiver_socket->GetInputStream().Read(/*size=*/32); - ASSERT_TRUE(received_msg.ok()); - EXPECT_EQ(message, received_msg.result().AsStringView()); - - receiver_socket->Close(); - env_.Stop(); -} - -// 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_P(WebRtcTest, ConnectBothDevicesAndAbort) { - env_.Start({.webrtc_enabled = true}); - WebRtcImpl receiver, sender; - std::shared_ptr receiver_socket, sender_socket; - WebRtcTestParams params = GetParam(); - const WebrtcPeerId self_id("self_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - Future connected; - - receiver.StartAcceptingConnections( - service_id, self_id, location_hint, - [&receiver_socket, connected]( - const std::string& service_id, - std::shared_ptr wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket->IsValid()); - }, - params.non_cellular); - - CancellationFlag flag; - ErrorOr> sender_socket_result = sender.Connect( - service_id, self_id, location_hint, &flag, params.non_cellular); - ASSERT_TRUE(sender_socket_result.has_value()); - EXPECT_TRUE(sender_socket_result.value()->IsValid()); - - ExceptionOr devices_connected = connected.Get(); - ASSERT_TRUE(devices_connected.ok()); - EXPECT_TRUE(devices_connected.result()); - - receiver_socket->Close(); - env_.Stop(); -} - -// 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_P(WebRtcTest, ConnectBothDevicesAndSendData) { - env_.Start({.webrtc_enabled = true}); - WebRtcImpl receiver, sender; - std::shared_ptr receiver_socket; - WebRtcTestParams params = GetParam(); - const WebrtcPeerId self_id("self_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - Future connected; - absl::string_view message("message"); - - receiver.StartAcceptingConnections( - service_id, self_id, location_hint, - [&receiver_socket, connected]( - const std::string& service_id, - std::shared_ptr wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket->IsValid()); - }, - params.non_cellular); - - CancellationFlag flag; - ErrorOr> sender_socket_result = sender.Connect( - service_id, self_id, location_hint, &flag, params.non_cellular); - ASSERT_TRUE(sender_socket_result.has_value()); - EXPECT_TRUE(sender_socket_result.value()->IsValid()); - - ExceptionOr devices_connected = connected.Get(); - ASSERT_TRUE(devices_connected.ok()); - EXPECT_TRUE(devices_connected.result()); - - sender_socket_result.value()->GetOutputStream().Write(message); - ExceptionOr received_msg = - receiver_socket->GetInputStream().Read(/*size=*/32); - ASSERT_TRUE(received_msg.ok()); - EXPECT_EQ(message, received_msg.result().AsStringView()); - - receiver_socket->Close(); - env_.Stop(); -} - -TEST_P(WebRtcTest, Connect_NullPeerConnection) { - env_.Start({.webrtc_enabled = true}); - WebRtcTestParams params = GetParam(); - testing::StrictMock mock_accepted_callback_; - env_.SetUseValidPeerConnection( - /*use_valid_peer_connection=*/false); - - WebRtcImpl webrtc; - const std::string service_id("NearbySharing"); - WebrtcPeerId self_id("peer_id"); - LocationHint location_hint; - - ASSERT_TRUE(webrtc.IsAvailable()); - CancellationFlag flag; - ErrorOr> wrapper_result = - webrtc.Connect(service_id, WebrtcPeerId("random_peer_id"), location_hint, - &flag, params.non_cellular); - EXPECT_TRUE(wrapper_result.has_error()); - env_.Stop(); -} - -// Tests the flow when the device calls StartAcceptingConnections and the -// receive messages stream fails. -TEST_P(WebRtcTest, ContinueAcceptingConnectionsOnComplete) { - env_.Start({.webrtc_enabled = true}); - testing::StrictMock mock_accepted_callback_; - WebRtcTestParams params = GetParam(); - WebRtcImpl webrtc; - WebrtcPeerId self_id("peer_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - - ASSERT_TRUE(webrtc.IsAvailable()); - ASSERT_TRUE(webrtc.StartAcceptingConnections( - service_id, self_id, location_hint, - mock_accepted_callback_.AsStdFunction(), params.non_cellular)); - EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); - - // Simulate a failure in receiving messages stream, WebRtc should restart - // accepting connections. - env_.SendWebRtcSignalingComplete(self_id.GetId(), - /*success=*/false); - EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); - - // And a "success" message should not cause accepting connections to stop. - env_.SendWebRtcSignalingComplete(self_id.GetId(), - /*success=*/true); - EXPECT_TRUE(webrtc.IsAcceptingConnections(service_id)); - - webrtc.StopAcceptingConnections(service_id); - EXPECT_FALSE(webrtc.IsAcceptingConnections(service_id)); - env_.Stop(); -} - -// Tests when a CancellationFlag is cancelled during an attempt to -// `WebRtc::AttemptToConnect` triggered by `WebRtc::Connect`. -TEST_P(WebRtcTest, CancelDuringConnect) { - env_.Start({.webrtc_enabled = true}); - WebRtcTestParams params = GetParam(); - - // Enable cancellation flags. - env_.SetFeatureFlags(FeatureFlags{ - .enable_cancellation_flag = true, - }); - - std::shared_ptr receiver_socket, sender_socket; - const WebrtcPeerId self_id("self_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - Future connected; - - CancellationFlag receiver_flag; - std::unique_ptr receiver = std::make_unique( - std::make_unique(&receiver_flag)); - - CancellationFlag sender_flag; - std::unique_ptr sender_medium = - std::make_unique(&sender_flag); - FakeWebRtcMedium* fake_sender_medium = - static_cast(sender_medium.get()); - auto sender = std::make_unique(std::move(sender_medium)); - - // Calls `CancellationFlag::Cancel` during a call to `GetSignalingMessenger` - // to simulate the cancellation occuring during an `AttemptToConnect`. - fake_sender_medium->TriggerCancellationDuringGetSignalingMessenger(); - - receiver->StartAcceptingConnections( - service_id, self_id, location_hint, - [&receiver_socket, connected]( - const std::string& service_id, - std::shared_ptr wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket->IsValid()); - }, - params.non_cellular); - - ErrorOr> sender_socket_result = sender->Connect( - service_id, self_id, location_hint, &sender_flag, params.non_cellular); - - // Since the flag was cancelled during the initial `AttemptToConnect`, except - // only one attempt instead of the usual three, because the cancellation flag - // should short-circuit the lengthy connection attempts during shutdown. - // Because of the way the iteration happens, the check for is cancelled - // happens after the counter has already been incremented, but before the - // attempt actually occurs. - EXPECT_TRUE(sender_socket_result.has_error()); - EXPECT_EQ(2, sender->connect_attempts_count(service_id)); - - env_.Stop(); -} - -// Tests when a CancellationFlag is cancelled before `WebRtc::Connect` is -// called. -TEST_P(WebRtcTest, CancelBeforeConnect) { - env_.Start({.webrtc_enabled = true}); - WebRtcTestParams params = GetParam(); - - // Enable cancellation flags. - env_.SetFeatureFlags(FeatureFlags{ - .enable_cancellation_flag = true, - }); - - std::shared_ptr receiver_socket; - const WebrtcPeerId self_id("self_id"); - const std::string service_id("NearbySharing"); - LocationHint location_hint; - Future connected; - - CancellationFlag receiver_flag; - std::unique_ptr receiver = std::make_unique( - std::make_unique(&receiver_flag)); - - CancellationFlag sender_flag(true); - auto sender = std::make_unique( - std::make_unique(&sender_flag)); - - receiver->StartAcceptingConnections( - service_id, self_id, location_hint, - [&receiver_socket, connected]( - const std::string& service_id, - std::shared_ptr wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket->IsValid()); - }, - params.non_cellular); - - ErrorOr> sender_socket_result = sender->Connect( - service_id, self_id, location_hint, &sender_flag, params.non_cellular); - - // Expect an invalid socket from stopping during the first attempt to connect, - // because `Connect` returned immediatley when it checked for cancellation. - EXPECT_TRUE(sender_socket_result.has_error()); - EXPECT_EQ(1, sender->connect_attempts_count(service_id)); - - env_.Stop(); -} - -// Tests when a CancellationFlag is cancelled during an attempt to -// `WebRtc::AttemptToConnect` triggered by `WebRtc::Connect` when multiple -// `WebRTC::Connect` calls are in flight for multiple service ids. -TEST_P(WebRtcTest, CancelDuringConnect_MultipleConnect) { - env_.Start({.webrtc_enabled = true}); - WebRtcTestParams params = GetParam(); - - // Enable cancellation flags. - env_.SetFeatureFlags(FeatureFlags{ - .enable_cancellation_flag = true, - }); - - std::shared_ptr receiver_socket; - const WebrtcPeerId self_id("self_id"); - const std::string ns_service_id("NearbySharing"); - const std::string ph_service_id("PhoneHub"); - LocationHint location_hint; - Future connected; - - CancellationFlag receiver_flag; - std::unique_ptr receiver = std::make_unique( - std::make_unique(&receiver_flag)); - - CancellationFlag flag; - auto sender_medium = std::make_unique(&flag); - FakeWebRtcMedium* fake_sender_medium = sender_medium.get(); - auto sender = std::make_unique(std::move(sender_medium)); - - receiver->StartAcceptingConnections( - ns_service_id, self_id, location_hint, - [&receiver_socket, connected]( - const std::string& ns_service_id, - std::shared_ptr wrapper) mutable { - receiver_socket = wrapper; - connected.Set(receiver_socket->IsValid()); - }, - params.non_cellular); - - // Simulate a successful connect for the endpoint of NearbySharing. - ErrorOr> sender_socket_result = sender->Connect( - ns_service_id, self_id, location_hint, &flag, params.non_cellular); - ASSERT_TRUE(sender_socket_result.has_value()); - EXPECT_TRUE(sender_socket_result.value()->IsValid()); - - // Calls `CancellationFlag::Cancel` during a call to `GetSignalingMessenger` - // to simulate the cancellation occuring during an `AttemptToConnect` for the - // endpoint of Phone Hub. - fake_sender_medium->TriggerCancellationDuringGetSignalingMessenger(); - sender_socket_result = sender->Connect(ph_service_id, self_id, location_hint, - &flag, params.non_cellular); - EXPECT_TRUE(sender_socket_result.has_error()); - - // Since the flag was cancelled during the initial `AttemptToConnect`, except - // only one attempt instead of the usual three, because the cancellation flag - // should short-circuit the lengthy connection attempts during shutdown. - // Because of the way the iteration happens, the check for is cancelled - // happens after the counter has already been incremented, but before the - // attempt actually occurs. For the successful connect, expect only one - // attempt. - EXPECT_EQ(1, sender->connect_attempts_count(ns_service_id)); - EXPECT_EQ(2, sender->connect_attempts_count(ph_service_id)); - - env_.Stop(); -} - -INSTANTIATE_TEST_SUITE_P(ParametrisedWebRtcTest, WebRtcTest, - testing::ValuesIn({ - {.feature_flags = - FeatureFlags{ - .enable_cancellation_flag = true, - }, - .non_cellular = true}, - {.feature_flags = - FeatureFlags{ - .enable_cancellation_flag = true, - }, - .non_cellular = false}, - {.feature_flags = - FeatureFlags{ - .enable_cancellation_flag = false, - }, - .non_cellular = true}, - {.feature_flags = - FeatureFlags{ - .enable_cancellation_flag = false, - }, - .non_cellular = false}, - })); - -} // namespace - -} // namespace mediums -} // namespace connections -} // namespace nearby diff --git a/connections/implementation/mediums/webrtc/webrtc_medium_impl.cc b/connections/implementation/mediums/webrtc/webrtc_medium_impl.cc deleted file mode 100644 index 8c5a2237..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_medium_impl.cc +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/webrtc_medium_impl.h" - -#include -#include -#include - -#include "absl/strings/string_view.h" -#include "connections/implementation/mediums/webrtc/tachyon_express_signaling_messenger.h" -#include "internal/platform/implementation/webrtc.h" -#include "webrtc/api/create_modular_peer_connection_factory.h" -#include "webrtc/api/peer_connection_interface.h" -#include "webrtc/api/rtc_error.h" -#include "webrtc/api/scoped_refptr.h" -#include "webrtc/rtc_base/thread.h" - -namespace nearby::connections::mediums { - -void WebRtcMediumImpl::CreatePeerConnection( - webrtc::PeerConnectionObserver* observer, PeerConnectionCallback callback) { - CreatePeerConnection(std::nullopt, observer, std::move(callback)); -} - -void WebRtcMediumImpl::CreatePeerConnection( - std::optional options, - webrtc::PeerConnectionObserver* observer, PeerConnectionCallback callback) { - webrtc::PeerConnectionInterface::RTCConfiguration rtc_config; - rtc_config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; - // TODO: b/261663238 - Add the TURN servers and go beyond the default servers. - webrtc::PeerConnectionInterface::IceServer ice_server; - ice_server.urls.emplace_back("stun:stun.l.google.com:19302"); - ice_server.urls.emplace_back("stun:stun1.l.google.com:19302"); - ice_server.urls.emplace_back("stun:stun2.l.google.com:19302"); - ice_server.urls.emplace_back("stun:stun3.l.google.com:19302"); - ice_server.urls.emplace_back("stun:stun4.l.google.com:19302"); - rtc_config.servers.push_back(ice_server); - - std::unique_ptr signaling_thread = webrtc::Thread::Create(); - signaling_thread->SetName("signaling_thread", nullptr); - if (!signaling_thread->Start()) { - callback(/*peer_connection=*/nullptr); - return; - } - - webrtc::PeerConnectionDependencies dependencies(observer); - webrtc::PeerConnectionFactoryDependencies factory_dependencies; - factory_dependencies.signaling_thread = signaling_thread.release(); - - webrtc::scoped_refptr - peer_connection_factory = webrtc::CreateModularPeerConnectionFactory( - std::move(factory_dependencies)); - if (options.has_value()) { - peer_connection_factory->SetOptions(options.value()); - } - webrtc::RTCErrorOr> - peer_connection_or_error = - peer_connection_factory->CreatePeerConnectionOrError( - rtc_config, std::move(dependencies)); - if (peer_connection_or_error.ok()) { - callback(peer_connection_or_error.MoveValue()); - } else { - callback(/*peer_connection=*/nullptr); - } -} - -std::unique_ptr -WebRtcMediumImpl::GetSignalingMessenger( - absl::string_view self_id, - const location::nearby::connections::LocationHint& location_hint) { - return std::make_unique(self_id, - location_hint); -} - -} // namespace nearby::connections::mediums diff --git a/connections/implementation/mediums/webrtc/webrtc_medium_impl.h b/connections/implementation/mediums/webrtc/webrtc_medium_impl.h deleted file mode 100644 index 7eb5ff1b..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_medium_impl.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_MEDIUM_IMPL_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_MEDIUM_IMPL_H_ - -#include -#include - -#include "absl/strings/string_view.h" -#include "internal/platform/implementation/webrtc.h" -#include "webrtc/api/peer_connection_interface.h" - -namespace nearby::connections::mediums { - -class WebRtcMediumImpl : public api::WebRtcMedium { - public: - ~WebRtcMediumImpl() override = default; - - // Creates and returns a new webrtc::PeerConnectionInterface object via - // |callback|. - void CreatePeerConnection(webrtc::PeerConnectionObserver* observer, - PeerConnectionCallback callback) override; - - // Creates and returns a new webrtc::PeerConnectionInterface object via - // |callback| with |PeerConnectionFactoryInterface::Options|. - void CreatePeerConnection( - std::optional options, - webrtc::PeerConnectionObserver* observer, - PeerConnectionCallback callback) override; - - // Returns a signaling messenger for sending WebRTC signaling messages. - std::unique_ptr GetSignalingMessenger( - absl::string_view self_id, - const location::nearby::connections::LocationHint& location_hint) - override; -}; - -} // namespace nearby::connections::mediums - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_MEDIUM_IMPL_H_ diff --git a/connections/implementation/mediums/webrtc/webrtc_medium_impl_test.cc b/connections/implementation/mediums/webrtc/webrtc_medium_impl_test.cc deleted file mode 100644 index c52cee0a..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_medium_impl_test.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/webrtc_medium_impl.h" - -#include -#include -#include - -#include "gtest/gtest.h" -#include "internal/platform/implementation/webrtc.h" -#include "webrtc/api/data_channel_interface.h" -#include "webrtc/api/jsep.h" -#include "webrtc/api/peer_connection_interface.h" -#include "webrtc/api/scoped_refptr.h" - -namespace nearby::connections::mediums { - -class MockPeerConnectionObserver : public webrtc::PeerConnectionObserver { - public: - void OnSignalingChange( - webrtc::PeerConnectionInterface::SignalingState new_state) override {} - - void OnDataChannel(webrtc::scoped_refptr - data_channel) override {} - - void OnIceGatheringChange( - webrtc::PeerConnectionInterface::IceGatheringState new_state) override {} - - void OnIceCandidate(const webrtc::IceCandidate* candidate) override {} -}; - -location::nearby::connections::LocationHint GetCountryCodeLocationHint( - const std::string& country_code) { - auto location_hint = location::nearby::connections::LocationHint(); - location_hint.set_location(country_code); - location_hint.set_format( - location::nearby::connections::LocationStandard::ISO_3166_1_ALPHA_2); - return location_hint; -} - -TEST(WebrtcMediumImplTest, CreatePeerConnectionSucceeds) { - auto observer = std::make_unique(); - WebRtcMediumImpl medium; - medium.CreatePeerConnection( - std::nullopt, observer.get(), - [](webrtc::scoped_refptr - peer_connection) mutable { - if (!peer_connection) { - FAIL() << "Peer connection should have been non-null"; - return; - } - }); -} - -TEST(WebrtcMediumImplTest, GetSignalingMessengerSucceeds) { - WebRtcMediumImpl medium; - std::unique_ptr messenger = - medium.GetSignalingMessenger("US", GetCountryCodeLocationHint("US")); - EXPECT_TRUE(messenger); -} - -} // namespace nearby::connections::mediums diff --git a/connections/implementation/mediums/webrtc/webrtc_socket_impl.cc b/connections/implementation/mediums/webrtc/webrtc_socket_impl.cc deleted file mode 100644 index ff8a3a03..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_socket_impl.cc +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/webrtc_socket_impl.h" - -#include -#include -#include -#include - -#include "absl/strings/string_view.h" -#include "internal/platform/byte_array.h" -#include "internal/platform/exception.h" -#include "internal/platform/input_stream.h" -#include "internal/platform/logging.h" -#include "internal/platform/mutex_lock.h" -#include "internal/platform/output_stream.h" -#include "internal/platform/pipe.h" -#include "internal/platform/runnable.h" -#include "webrtc/api/data_channel_interface.h" -#include "webrtc/api/scoped_refptr.h" - -namespace nearby { -namespace connections { -namespace mediums { - -// OutputStreamImpl -Exception WebRtcSocketImpl::OutputStreamImpl::Write(absl::string_view data) { - if (data.size() > kMaxDataSize) { - LOG(WARNING) << "Sending data larger than 1MB"; - return {Exception::kIo}; - } - - socket_->BlockUntilSufficientSpaceInBuffer(data.size()); - - if (socket_->IsClosed()) { - LOG(WARNING) << "Tried sending message while socket is closed"; - return {Exception::kIo}; - } - - if (!socket_->SendMessage(ByteArray::FromStringView(data))) { - LOG(INFO) << "Unable to write data to socket."; - return {Exception::kIo}; - } - return {Exception::kSuccess}; -} - -Exception WebRtcSocketImpl::OutputStreamImpl::Flush() { - // Java implementation is empty. - return {Exception::kSuccess}; -} - -Exception WebRtcSocketImpl::OutputStreamImpl::Close() { - socket_->Close(); - return {Exception::kSuccess}; -} - -// WebRtcSocket -WebRtcSocketImpl::WebRtcSocketImpl( - const std::string& name, - webrtc::scoped_refptr data_channel) - : name_(name), data_channel_(std::move(data_channel)) { - LOG(INFO) << "WebRtcSocket::WebRtcSocket(" << name_ << ") this: " << this; - std::tie(pipe_input_, pipe_output_) = CreatePipe(); - data_channel_->RegisterObserver(this); -} - -WebRtcSocketImpl::~WebRtcSocketImpl() { - LOG(INFO) << "WebRtcSocket::~WebRtcSocket(" << name_ << ") this: " << this; - - if (!IsClosed()) { - data_channel_->UnregisterObserver(); - Close(); - } - - LOG(INFO) << "WebRtcSocket::~WebRtcSocket(" << name_ << ") this: " << this - << " done"; -} - -InputStream& WebRtcSocketImpl::GetInputStream() { return *pipe_input_; } - -OutputStream& WebRtcSocketImpl::GetOutputStream() { return output_stream_; } - -Exception WebRtcSocketImpl::Close() { - LOG(INFO) << "WebRtcSocket::Close(" << name_ << ") this: " << this; - if (closed_.Set(true)) return {Exception::kSuccess}; - - ClosePipe(); - // NOTE: This call blocks and triggers a state change on the signaling thread - // to 'closing' but does not block until 'closed' is sent so the data channel - // is not fully closed when this call is done. - data_channel_->Close(); - LOG(INFO) << "WebRtcSocket::Close(" << name_ << ") this: " << this << " done"; - return {Exception::kSuccess}; -} - -void WebRtcSocketImpl::OnStateChange() { - // Running on the signaling thread right now. - LOG(ERROR) << "WebRtcSocket::OnStateChange() webrtc data channel state: " - << webrtc::DataChannelInterface::DataStateString( - data_channel_->state()); - switch (data_channel_->state()) { - case webrtc::DataChannelInterface::DataState::kConnecting: - break; - case webrtc::DataChannelInterface::DataState::kOpen: - // We implicitly depend on the |socket_listener_| to offload from - // the signaling thread so it does not get blocked. - socket_listener_.socket_ready_cb(this); - break; - case webrtc::DataChannelInterface::DataState::kClosing: - break; - case webrtc::DataChannelInterface::DataState::kClosed: - LOG(ERROR) << "WebRtcSocket::OnStateChange() unregistering data " - "channel observer."; - // This will trigger a destruction of the owning connection flow - // We implicitly depend on the |socket_listener_| to offload from - // the signaling thread so it does not get blocked. - socket_listener_.socket_closed_cb(this); - - if (!closed_.Set(true)) { - OffloadFromSignalingThread([this] { ClosePipe(); }); - } - break; - } -} -void WebRtcSocketImpl::OnMessage(const webrtc::DataBuffer& buffer) { - // This is a data channel callback on the signaling thread, lets off load so - // we don't block signaling. - OffloadFromSignalingThread( - [this, buffer = ByteArray(buffer.data.data(), buffer.size())] { - if (!pipe_output_->Write(buffer.AsStringView()).Ok()) { - Close(); - return; - } - - if (!pipe_output_->Flush().Ok()) { - Close(); - } - }); -} - -void WebRtcSocketImpl::OnBufferedAmountChange(uint64_t sent_data_size) { - // This is a data channel callback on the signaling thread, lets off load so - // we don't block signaling. - OffloadFromSignalingThread([this] { WakeUpWriter(); }); -} - -bool WebRtcSocketImpl::SendMessage(const ByteArray& data) { - return data_channel_->Send( - webrtc::DataBuffer(std::string(data.data(), data.size()))); -} - -bool WebRtcSocketImpl::IsClosed() { return closed_.Get(); } - -void WebRtcSocketImpl::ClosePipe() { - LOG(INFO) << "WebRtcSocket::ClosePipe(" << name_ << ") this: " << this; - // This is thread-safe to close these sockets even if a read or write is in - // process on another thread, Close will wait for the exclusive mutex before - // setting state. - pipe_input_->Close(); - pipe_output_->Close(); - WakeUpWriter(); - LOG(INFO) << "WebRtcSocket::ClosePipe(" << name_ << ") this: " << this - << " done"; -} - -// Must not be called on signalling thread. -void WebRtcSocketImpl::WakeUpWriter() { - MutexLock lock(&backpressure_mutex_); - buffer_variable_.Notify(); -} - -void WebRtcSocketImpl::SetSocketListener(SocketListener&& listener) { - socket_listener_ = std::move(listener); -} - -void WebRtcSocketImpl::BlockUntilSufficientSpaceInBuffer(int length) { - MutexLock lock(&backpressure_mutex_); - while (!IsClosed() && - (data_channel_->buffered_amount() + length > kMaxDataSize)) { - // TODO(himanshujaju): Add wait with timeout. - buffer_variable_.Wait(); - } -} - -void WebRtcSocketImpl::OffloadFromSignalingThread(Runnable runnable) { - single_thread_executor_.Execute(std::move(runnable)); -} - -} // namespace mediums -} // namespace connections -} // namespace nearby diff --git a/connections/implementation/mediums/webrtc/webrtc_socket_impl.h b/connections/implementation/mediums/webrtc/webrtc_socket_impl.h deleted file mode 100644 index b3605462..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_socket_impl.h +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_SOCKET_IMPL_H_ -#define CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_SOCKET_IMPL_H_ - -#include -#include -#include - -#include "absl/functional/any_invocable.h" -#include "absl/strings/string_view.h" -#include "connections/implementation/mediums/webrtc_socket.h" -#include "internal/platform/atomic_boolean.h" -#include "internal/platform/byte_array.h" -#include "internal/platform/condition_variable.h" -#include "internal/platform/exception.h" -#include "internal/platform/input_stream.h" -#include "internal/platform/listeners.h" -#include "internal/platform/mutex.h" -#include "internal/platform/output_stream.h" -#include "internal/platform/runnable.h" -#include "internal/platform/single_thread_executor.h" -#include "webrtc/api/data_channel_interface.h" -#include "webrtc/api/scoped_refptr.h" - -namespace nearby { -namespace connections { -namespace mediums { - -// Maximum data size: 1 MB -constexpr int kMaxDataSize = 1 * 1024 * 1024; - -// Defines the Socket implementation specific to WebRTC, which uses the WebRTC -// data channel to send and receive messages. -// -// Messages are buffered here to prevent the data channel from overflowing, -// which could lead to data loss. -class WebRtcSocketImpl : public WebRtcSocket, - public webrtc::DataChannelObserver { - public: - WebRtcSocketImpl( - const std::string& name, - webrtc::scoped_refptr data_channel); - ~WebRtcSocketImpl() override; - - WebRtcSocketImpl(const WebRtcSocketImpl& other) = delete; - WebRtcSocketImpl& operator=(const WebRtcSocketImpl& other) = delete; - - // Overrides for WebRtcSocket: - InputStream& GetInputStream() override; - OutputStream& GetOutputStream() override; - Exception Close() override; - bool IsValid() const override { return true; } - - // webrtc::DataChannelObserver: - void OnStateChange() override; - void OnMessage(const webrtc::DataBuffer& buffer) override; - void OnBufferedAmountChange(uint64_t sent_data_size) override; - - // Listener class the gets called when the socket is ready or closed - struct SocketListener { - absl::AnyInvocable socket_ready_cb = - DefaultCallback(); - absl::AnyInvocable socket_closed_cb = - DefaultCallback(); - }; - - void SetSocketListener(SocketListener&& listener); - - private: - class OutputStreamImpl : public OutputStream { - public: - explicit OutputStreamImpl(WebRtcSocketImpl* const socket) - : socket_(socket) {} - ~OutputStreamImpl() override = default; - - OutputStreamImpl(const OutputStreamImpl& other) = delete; - OutputStreamImpl& operator=(const OutputStreamImpl& other) = delete; - - // OutputStream: - Exception Write(absl::string_view data) override; - Exception Flush() override; - Exception Close() override; - - private: - // |this| OutputStreamImpl is owned by |socket_|. - WebRtcSocketImpl* const socket_; - }; - - void WakeUpWriter(); - bool IsClosed(); - void ClosePipe(); - bool SendMessage(const ByteArray& data); - void BlockUntilSufficientSpaceInBuffer(int length); - void OffloadFromSignalingThread(Runnable runnable); - - std::string name_; - webrtc::scoped_refptr data_channel_; - - std::unique_ptr pipe_input_; - std::unique_ptr pipe_output_; - OutputStreamImpl output_stream_{this}; - - AtomicBoolean closed_{false}; - - SocketListener socket_listener_; - - mutable Mutex backpressure_mutex_; - ConditionVariable buffer_variable_{&backpressure_mutex_}; - - // This should be destroyed first to ensure any remaining tasks flushed on - // shutdown get run while the other members are still alive. - SingleThreadExecutor single_thread_executor_; -}; - -} // namespace mediums -} // namespace connections -} // namespace nearby - -#endif // CORE_INTERNAL_MEDIUMS_WEBRTC_WEBRTC_SOCKET_IMPL_H_ diff --git a/connections/implementation/mediums/webrtc/webrtc_socket_impl_test.cc b/connections/implementation/mediums/webrtc/webrtc_socket_impl_test.cc deleted file mode 100644 index fdffc732..00000000 --- a/connections/implementation/mediums/webrtc/webrtc_socket_impl_test.cc +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "connections/implementation/mediums/webrtc/webrtc_socket_impl.h" - -#include -#include - -#include "gmock/gmock.h" -#include "protobuf-matchers/protocol-buffer-matchers.h" -#include "gtest/gtest.h" -#include "absl/strings/string_view.h" -#include "internal/platform/byte_array.h" -#include "internal/platform/exception.h" -#include "webrtc/api/data_channel_interface.h" -#include "webrtc/api/scoped_refptr.h" -#include "webrtc/rtc_base/ref_counted_object.h" - -namespace nearby { -namespace connections { -namespace mediums { - -namespace { - -// using TestPlatform = platform::ImplementationPlatform; - -const char kSocketName[] = "TestSocket"; - -class MockDataChannel - : public webrtc::RefCountedObject { - public: - MOCK_METHOD(void, RegisterObserver, (webrtc::DataChannelObserver*)); - MOCK_METHOD(void, UnregisterObserver, ()); - - MOCK_METHOD(std::string, label, (), (const)); - - MOCK_METHOD(bool, reliable, (), (const)); - MOCK_METHOD(int, id, (), (const)); - MOCK_METHOD(DataState, state, (), (const)); - MOCK_METHOD(uint32_t, messages_sent, (), (const)); - MOCK_METHOD(uint64_t, bytes_sent, (), (const)); - MOCK_METHOD(uint32_t, messages_received, (), (const)); - MOCK_METHOD(uint64_t, bytes_received, (), (const)); - - MOCK_METHOD(uint64_t, buffered_amount, (), (const)); - - MOCK_METHOD(void, Close, ()); - - MOCK_METHOD(bool, Send, (const webrtc::DataBuffer&)); -}; - -} // namespace - -TEST(WebRtcSocketTest, ReadFromSocket) { - const char* message = "message"; - webrtc::scoped_refptr mock_data_channel( - new MockDataChannel()); - WebRtcSocketImpl webrtc_socket(kSocketName, mock_data_channel); - - webrtc_socket.OnMessage(webrtc::DataBuffer{message}); - ExceptionOr result = webrtc_socket.GetInputStream().Read(7); - EXPECT_TRUE(result.ok()); - EXPECT_EQ(result.result(), ByteArray{message}); -} - -TEST(WebRtcSocketTest, ReadMultipleMessages) { - webrtc::scoped_refptr mock_data_channel( - new MockDataChannel()); - WebRtcSocketImpl webrtc_socket(kSocketName, mock_data_channel); - - webrtc_socket.OnMessage(webrtc::DataBuffer{"Me"}); - webrtc_socket.OnMessage(webrtc::DataBuffer{"ssa"}); - webrtc_socket.OnMessage(webrtc::DataBuffer{"ge"}); - - ExceptionOr result; - - // This behaviour is different from the Java code - result = webrtc_socket.GetInputStream().Read(7); - EXPECT_TRUE(result.ok()); - EXPECT_EQ(result.result(), ByteArray{"Me"}); - - result = webrtc_socket.GetInputStream().Read(7); - EXPECT_TRUE(result.ok()); - EXPECT_EQ(result.result(), ByteArray{"ssa"}); - - result = webrtc_socket.GetInputStream().Read(7); - EXPECT_TRUE(result.ok()); - EXPECT_EQ(result.result(), ByteArray{"ge"}); -} - -TEST(WebRtcSocketTest, WriteToSocket) { - absl::string_view kMessage{"Message"}; - webrtc::scoped_refptr mock_data_channel( - new MockDataChannel()); - WebRtcSocketImpl webrtc_socket(kSocketName, mock_data_channel); - - EXPECT_CALL(*mock_data_channel, Send(testing::_)) - .WillRepeatedly(testing::Return(true)); - EXPECT_TRUE(webrtc_socket.GetOutputStream().Write(kMessage).Ok()); -} - -TEST(WebRtcSocketTest, SendDataBiggerThanMax) { - std::string kMessage(kMaxDataSize + 1, '0'); - webrtc::scoped_refptr mock_data_channel( - new MockDataChannel()); - WebRtcSocketImpl webrtc_socket(kSocketName, mock_data_channel); - - EXPECT_CALL(*mock_data_channel, Send(testing::_)).Times(0); - EXPECT_EQ(webrtc_socket.GetOutputStream().Write(kMessage), - Exception{Exception::kIo}); -} - -TEST(WebRtcSocketTest, WriteToDataChannelFails) { - absl::string_view kMessage{"Message"}; - webrtc::scoped_refptr mock_data_channel( - new MockDataChannel()); - WebRtcSocketImpl webrtc_socket(kSocketName, mock_data_channel); - - ON_CALL(*mock_data_channel, Send(testing::_)) - .WillByDefault(testing::Return(false)); - EXPECT_EQ(webrtc_socket.GetOutputStream().Write(kMessage), - Exception{Exception::kIo}); -} - -TEST(WebRtcSocketTest, Close) { - webrtc::scoped_refptr mock_data_channel( - new MockDataChannel()); - WebRtcSocketImpl webrtc_socket(kSocketName, mock_data_channel); - - EXPECT_CALL(*mock_data_channel, Close()); - - int socket_closed_cb_called = 0; - - webrtc_socket.SetSocketListener( - {.socket_closed_cb = [&](WebRtcSocketImpl* socket) { - socket_closed_cb_called++; - }}); - webrtc_socket.Close(); - - // We have to fake the close event to get the callback to run. - ON_CALL(*mock_data_channel, state()) - .WillByDefault( - testing::Return(webrtc::DataChannelInterface::DataState::kClosed)); - - webrtc_socket.OnStateChange(); - - EXPECT_EQ(socket_closed_cb_called, 1); -} - -TEST(WebRtcSocketTest, WriteOnClosedChannel) { - absl::string_view kMessage{"Message"}; - webrtc::scoped_refptr mock_data_channel( - new MockDataChannel()); - WebRtcSocketImpl webrtc_socket(kSocketName, mock_data_channel); - webrtc_socket.Close(); - - EXPECT_CALL(*mock_data_channel, Send(testing::_)).Times(0); - EXPECT_EQ(webrtc_socket.GetOutputStream().Write(kMessage), - Exception{Exception::kIo}); -} - -TEST(WebRtcSocketTest, ReadFromClosedChannel) { - absl::string_view kMessage{"Message"}; - webrtc::scoped_refptr mock_data_channel( - new MockDataChannel()); - WebRtcSocketImpl webrtc_socket(kSocketName, mock_data_channel); - ON_CALL(*mock_data_channel, Send(testing::_)) - .WillByDefault(testing::Return(true)); - - webrtc_socket.GetOutputStream().Write(kMessage); - webrtc_socket.Close(); - - EXPECT_TRUE(webrtc_socket.GetInputStream().Read(7).GetResult().Empty()); -} - -TEST(WebRtcSocketTest, DataChannelCloseEventCleansUp) { - webrtc::scoped_refptr mock_data_channel( - new MockDataChannel()); - WebRtcSocketImpl webrtc_socket(kSocketName, mock_data_channel); - - ON_CALL(*mock_data_channel, state()) - .WillByDefault( - testing::Return(webrtc::DataChannelInterface::DataState::kClosed)); - - webrtc_socket.OnStateChange(); - - EXPECT_TRUE(webrtc_socket.GetInputStream().Read(7).GetResult().Empty()); - - // Calling Close again should be safe even if the channel is already shut - // down. - webrtc_socket.Close(); -} - -TEST(WebRtcSocketTest, OpenStateTriggersCallback) { - webrtc::scoped_refptr mock_data_channel( - new MockDataChannel()); - WebRtcSocketImpl webrtc_socket(kSocketName, mock_data_channel); - - int socket_ready_cb_called = 0; - - webrtc_socket.SetSocketListener( - {.socket_ready_cb = [&](WebRtcSocketImpl* socket) { - socket_ready_cb_called++; - }}); - - ON_CALL(*mock_data_channel, state()) - .WillByDefault( - testing::Return(webrtc::DataChannelInterface::DataState::kOpen)); - - webrtc_socket.OnStateChange(); - - EXPECT_EQ(socket_ready_cb_called, 1); -} - -TEST(WebRtcSocketTest, CloseStateTriggersCallback) { - webrtc::scoped_refptr mock_data_channel( - new MockDataChannel()); - WebRtcSocketImpl webrtc_socket(kSocketName, mock_data_channel); - - int socket_closed_cb_called = 0; - - webrtc_socket.SetSocketListener( - {.socket_closed_cb = [&](WebRtcSocketImpl* socket) { - socket_closed_cb_called++; - }}); - - ON_CALL(*mock_data_channel, state()) - .WillByDefault( - testing::Return(webrtc::DataChannelInterface::DataState::kClosed)); - - webrtc_socket.OnStateChange(); - - EXPECT_EQ(socket_closed_cb_called, 1); -} - -} // namespace mediums -} // namespace connections -} // namespace nearby diff --git a/internal/platform/implementation/g3/webrtc.cc b/internal/platform/implementation/g3/webrtc.cc index 9659c50d..da43fa31 100644 --- a/internal/platform/implementation/g3/webrtc.cc +++ b/internal/platform/implementation/g3/webrtc.cc @@ -24,11 +24,11 @@ #include "internal/platform/byte_array.h" #include "internal/platform/implementation/webrtc.h" #include "internal/platform/medium_environment.h" -#include "webrtc/api/create_modular_peer_connection_factory.h" -#include "webrtc/api/peer_connection_interface.h" -#include "webrtc/api/scoped_refptr.h" -#include "webrtc/rtc_base/checks.h" -#include "webrtc/rtc_base/thread.h" +#include "third_party/webrtc/files/stable/webrtc/api/create_modular_peer_connection_factory.h" +#include "third_party/webrtc/files/stable/webrtc/api/peer_connection_interface.h" +#include "third_party/webrtc/files/stable/webrtc/api/scoped_refptr.h" +#include "third_party/webrtc/files/stable/webrtc/rtc_base/checks.h" +#include "third_party/webrtc/files/stable/webrtc/rtc_base/thread.h" namespace nearby { namespace g3 { diff --git a/internal/platform/implementation/g3/webrtc.h b/internal/platform/implementation/g3/webrtc.h index 435fa57e..943e27f6 100644 --- a/internal/platform/implementation/g3/webrtc.h +++ b/internal/platform/implementation/g3/webrtc.h @@ -23,7 +23,7 @@ #include "internal/platform/byte_array.h" #include "internal/platform/implementation/webrtc.h" #include "internal/platform/implementation/g3/single_thread_executor.h" -#include "webrtc/api/peer_connection_interface.h" +#include "third_party/webrtc/files/stable/webrtc/api/peer_connection_interface.h" namespace nearby { namespace g3 { diff --git a/internal/platform/implementation/webrtc.h b/internal/platform/implementation/webrtc.h index 5b64dd50..90938bfa 100644 --- a/internal/platform/implementation/webrtc.h +++ b/internal/platform/implementation/webrtc.h @@ -22,8 +22,8 @@ #include "absl/strings/string_view.h" #include "connections/implementation/proto/offline_wire_formats.pb.h" #include "internal/platform/byte_array.h" -#include "webrtc/api/peer_connection_interface.h" -#include "webrtc/api/scoped_refptr.h" +#include "third_party/webrtc/files/stable/webrtc/api/peer_connection_interface.h" +#include "third_party/webrtc/files/stable/webrtc/api/scoped_refptr.h" namespace nearby { namespace api {