diff --git a/internal/platform/implementation/windows/BUILD b/internal/platform/implementation/windows/BUILD index 321d5dd3..fe8c03f5 100644 --- a/internal/platform/implementation/windows/BUILD +++ b/internal/platform/implementation/windows/BUILD @@ -108,17 +108,20 @@ cc_library( "//internal/platform:base", "//internal/platform:comm", "//internal/platform:types", + "//internal/platform:uuid", "//internal/platform/implementation:comm", "//internal/platform/implementation:types", "//internal/platform/implementation/windows/generated:types", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", + "@com_google_absl//absl/functional:any_invocable", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", "@com_google_absl//absl/synchronization", + "@com_google_absl//absl/time", "@com_google_absl//absl/types:optional", ], ) @@ -167,6 +170,7 @@ cc_library( "system_clock.cc", "thread_pool.cc", "utils.cc", + "webrtc.cc", "wifi_direct_medium.cc", "wifi_direct_server_socket.cc", "wifi_direct_socket.cc", @@ -206,6 +210,8 @@ cc_library( "//internal/platform/implementation/shared:count_down_latch", "//internal/platform/implementation/shared:file", "//internal/platform/implementation/windows/generated:types", + "//third_party/webrtc/files/stable/webrtc/api/task_queue:default_task_queue_factory", + "//third_party/webrtc/files/stable/webrtc/rtc_base:checks", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/functional:any_invocable", @@ -218,7 +224,6 @@ cc_library( "@com_google_absl//absl/synchronization", "@com_google_absl//absl/time", "@com_google_absl//absl/types:optional", - "@com_google_absl//absl/types:span", "@nlohmann_json//:json", ], ) @@ -265,6 +270,7 @@ cc_test( "thread_pool_test.cc", "timer_test.cc", "utils_test.cc", + "webrtc_test.cc", ], copts = ["-Ithird_party/nearby/internal/platform/implementation/windows/generated -DCORE_ADAPTER_DLL"], tags = ["notap"], diff --git a/internal/platform/implementation/windows/platform.cc b/internal/platform/implementation/windows/platform.cc index 4ab4bcb0..ddd8c6e6 100644 --- a/internal/platform/implementation/windows/platform.cc +++ b/internal/platform/implementation/windows/platform.cc @@ -301,7 +301,7 @@ ImplementationPlatform::CreateWifiDirectMedium() { return nullptr; } -// TODO(b/184975123): replace with real implementation. +// TODO(b/261663238) replace with real implementation. std::unique_ptr ImplementationPlatform::CreateWebRtcMedium() { return nullptr; } diff --git a/internal/platform/implementation/windows/webrtc.cc b/internal/platform/implementation/windows/webrtc.cc new file mode 100644 index 00000000..190a87e9 --- /dev/null +++ b/internal/platform/implementation/windows/webrtc.cc @@ -0,0 +1,112 @@ +// 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 "internal/platform/implementation/windows/webrtc.h" + +#include + +#include +#include +#include + +#include "internal/platform/logging.h" +#include "webrtc/api/task_queue/default_task_queue_factory.h" + +namespace nearby { +namespace windows { + +WebRtcSignalingMessenger::WebRtcSignalingMessenger( + absl::string_view self_id, + const location::nearby::connections::LocationHint& location_hint) + : self_id_(self_id), location_hint_(location_hint) {} +// TODO(b/261663238): replace with real implementation. +bool WebRtcSignalingMessenger::SendMessage(absl::string_view peer_id, + const ByteArray& message) { + return false; +} + +// TODO(b/261663238): replace with real implementation. +bool WebRtcSignalingMessenger::StartReceivingMessages( + api::WebRtcSignalingMessenger::OnSignalingMessageCallback + on_message_callback, + api::WebRtcSignalingMessenger::OnSignalingCompleteCallback + on_complete_callback) { + return false; +} +// TODO(b/261663238): replace with real implementation. +void WebRtcSignalingMessenger::StopReceivingMessages() {} + +const std::string WebRtcMedium::GetDefaultCountryCode() { + wchar_t systemGeoName[LOCALE_NAME_MAX_LENGTH]; + + if (!GetUserDefaultGeoName(systemGeoName, LOCALE_NAME_MAX_LENGTH)) { + NEARBY_LOGS(ERROR) << __func__ << ": Failed to GetUserDefaultGeoName: " + << ". Fall back to US."; + return "US"; + } + std::wstring wideGeo(systemGeoName); + std::string systemGeoNameString(wideGeo.begin(), wideGeo.end()); + NEARBY_LOGS(VERBOSE) << "GetUserDefaultGeoName() returns: " + << systemGeoNameString; + return systemGeoNameString; +} + +void WebRtcMedium::CreatePeerConnection( + 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 = rtc::Thread::Create(); + signaling_thread->SetName("signaling_thread", nullptr); + if (!signaling_thread->Start()) { + NEARBY_LOGS(FATAL) << "Failed to start thread"; + } + + webrtc::PeerConnectionDependencies dependencies(observer); + webrtc::PeerConnectionFactoryDependencies factory_dependencies; + factory_dependencies.task_queue_factory = + webrtc::CreateDefaultTaskQueueFactory(); + factory_dependencies.signaling_thread = signaling_thread.release(); + + auto peer_connection_or_error = + webrtc::CreateModularPeerConnectionFactory( + std::move(factory_dependencies)) + ->CreatePeerConnectionOrError(rtc_config, std::move(dependencies)); + + if (peer_connection_or_error.ok()) { + callback(peer_connection_or_error.MoveValue()); + } else { + NEARBY_LOGS(FATAL) << "Failed to create peer connection"; + callback(/*peer_connection=*/nullptr); + } +} + +std::unique_ptr +WebRtcMedium::GetSignalingMessenger( + absl::string_view self_id, + const location::nearby::connections::LocationHint& location_hint) { + return std::make_unique(std::string(self_id), + location_hint); +} + +} // namespace windows +} // namespace nearby diff --git a/internal/platform/implementation/windows/webrtc.h b/internal/platform/implementation/windows/webrtc.h index 0681cd36..70979415 100644 --- a/internal/platform/implementation/windows/webrtc.h +++ b/internal/platform/implementation/windows/webrtc.h @@ -15,6 +15,8 @@ #ifndef PLATFORM_IMPL_WINDOWS_WEBRTC_H_ #define PLATFORM_IMPL_WINDOWS_WEBRTC_H_ +#include + #include "internal/platform/implementation/webrtc.h" namespace nearby { @@ -22,53 +24,49 @@ namespace windows { class WebRtcSignalingMessenger : public api::WebRtcSignalingMessenger { public: - // TODO(b/184975123): replace with real implementation. + using OnSignalingMessageCallback = + api::WebRtcSignalingMessenger::OnSignalingMessageCallback; + using OnSignalingCompleteCallback = + api::WebRtcSignalingMessenger::OnSignalingCompleteCallback; + + explicit WebRtcSignalingMessenger( + absl::string_view self_id, + const location::nearby::connections::LocationHint& location_hint); ~WebRtcSignalingMessenger() override = default; - // TODO(b/184975123): replace with real implementation. bool SendMessage(absl::string_view peer_id, - const ByteArray& message) override { - return false; - } - - // TODO(b/184975123): replace with real implementation. + const ByteArray& message) override; bool StartReceivingMessages( - api::WebRtcSignalingMessenger::OnSignalingMessageCallback - on_message_callback, - api::WebRtcSignalingMessenger::OnSignalingCompleteCallback - on_complete_callback) override { - return false; - } - // TODO(b/184975123): replace with real implementation. - void StopReceivingMessages() override {} + OnSignalingMessageCallback on_message_callback, + OnSignalingCompleteCallback on_complete_callback) override; + void StopReceivingMessages() override; + + private: + std::string self_id_; + location::nearby::connections::LocationHint location_hint_; }; class WebRtcMedium : public api::WebRtcMedium { public: - // TODO(b/184975123): replace with real implementation. + // TODO(b/261663238): replace with real implementation. ~WebRtcMedium() override = default; // Gets the default two-letter country code associated with current locale. // For example, en_US locale resolves to "US". - // TODO(b/184975123): replace with real implementation. - const std::string GetDefaultCountryCode() override { - return "Un-implemented"; - } + // This follows the ISO 3166-1 Alpha-2 standard. + const std::string GetDefaultCountryCode() override; // Creates and returns a new webrtc::PeerConnectionInterface object via // |callback|. - // TODO(b/184975123): replace with real implementation. void CreatePeerConnection(webrtc::PeerConnectionObserver* observer, - PeerConnectionCallback callback) override {} + PeerConnectionCallback callback) override; // Returns a signaling messenger for sending WebRTC signaling messages. - // TODO(b/184975123): replace with real implementation. + // TODO(b/261663238): replace with real implementation. std::unique_ptr GetSignalingMessenger( absl::string_view self_id, const location::nearby::connections::LocationHint& location_hint) - override { - return nullptr; - } + override; }; } // namespace windows diff --git a/internal/platform/implementation/windows/webrtc_test.cc b/internal/platform/implementation/windows/webrtc_test.cc new file mode 100644 index 00000000..81331a14 --- /dev/null +++ b/internal/platform/implementation/windows/webrtc_test.cc @@ -0,0 +1,78 @@ +// 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 "internal/platform/implementation/windows/webrtc.h" + +#include +#include + +#include "gmock/gmock.h" +#include "protobuf-matchers/protocol-buffer-matchers.h" +#include "gtest/gtest.h" + +namespace nearby { +namespace windows { + +class MockPeerConnectionObserver : public webrtc::PeerConnectionObserver { + public: + void OnSignalingChange( + webrtc::PeerConnectionInterface::SignalingState new_state) override {} + + void OnDataChannel( + rtc::scoped_refptr data_channel) override {} + + void OnIceGatheringChange( + webrtc::PeerConnectionInterface::IceGatheringState new_state) override {} + + void OnIceCandidate(const webrtc::IceCandidateInterface* 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(WebrtcTest, CountryCodeDefault) { + WebRtcMedium medium; + std::string result = medium.GetDefaultCountryCode(); + EXPECT_EQ(result, "US"); +} + +TEST(WebrtcTest, CreatePeerConnectionSucceeds) { + auto observer = std::make_unique(); + WebRtcMedium medium; + medium.CreatePeerConnection( + observer.get(), [](rtc::scoped_refptr + peer_connection) mutable { + if (!peer_connection) { + FAIL() << "Peer connection should have been non-null"; + return; + } + }); +} + +TEST(WebrtcTest, GetSignalingMessengerSucceeds) { + WebRtcMedium medium; + std::unique_ptr messenger = + medium.GetSignalingMessenger("US", GetCountryCodeLocationHint("US")); + EXPECT_TRUE(messenger); +} + +} // namespace windows +} // namespace nearby