diff --git a/BUILD.gn b/BUILD.gn index 9c42c12349..373e029de9 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -654,6 +654,7 @@ if (rtc_include_tests && !build_with_chromium) { "p2p:rtc_p2p_unittests", "rtc_base:async_dns_resolver_unittests", "rtc_base:async_packet_socket_unittest", + "rtc_base:async_udp_socket_unittest", "rtc_base:callback_list_unittests", "rtc_base:rtc_base_approved_unittests", "rtc_base:rtc_base_unittests", diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn index 31595b43d8..bddae54a82 100644 --- a/p2p/BUILD.gn +++ b/p2p/BUILD.gn @@ -781,6 +781,7 @@ rtc_library("stun_port") { "../rtc_base:ip_address", "../rtc_base:logging", "../rtc_base:stringutils", + "../rtc_base:timeutils", "../rtc_base/experiments:field_trial_parser", "../rtc_base/network:received_packet", "../rtc_base/system:rtc_export", @@ -826,6 +827,7 @@ rtc_library("tcp_port") { "../rtc_base:net_helper", "../rtc_base:rate_tracker", "../rtc_base:threading", + "../rtc_base:timeutils", "../rtc_base/containers:flat_map", "../rtc_base/network:received_packet", "//third_party/abseil-cpp/absl/algorithm:container", @@ -1218,6 +1220,7 @@ rtc_library("p2p_server_utils") { "../rtc_base:ssl", "../rtc_base:ssl_adapter", "../rtc_base:stringutils", + "../rtc_base:timeutils", "../rtc_base/network:received_packet", "../rtc_base/third_party/sigslot", "//third_party/abseil-cpp/absl/algorithm:container", diff --git a/p2p/base/stun_port.cc b/p2p/base/stun_port.cc index 5a9906dbf9..39d1457c30 100644 --- a/p2p/base/stun_port.cc +++ b/p2p/base/stun_port.cc @@ -26,6 +26,7 @@ #include "rtc_base/logging.h" #include "rtc_base/network/received_packet.h" #include "rtc_base/strings/string_builder.h" +#include "rtc_base/time_utils.h" namespace cricket { diff --git a/p2p/base/tcp_port.cc b/p2p/base/tcp_port.cc index 305db0e73c..cfd3c18b47 100644 --- a/p2p/base/tcp_port.cc +++ b/p2p/base/tcp_port.cc @@ -84,6 +84,7 @@ #include "rtc_base/network/received_packet.h" #include "rtc_base/rate_tracker.h" #include "rtc_base/thread.h" +#include "rtc_base/time_utils.h" namespace cricket { using ::webrtc::IceCandidateType; diff --git a/p2p/base/turn_server.cc b/p2p/base/turn_server.cc index 4fd899ee2d..494939a306 100644 --- a/p2p/base/turn_server.cc +++ b/p2p/base/turn_server.cc @@ -30,6 +30,7 @@ #include "rtc_base/message_digest.h" #include "rtc_base/socket_adapters.h" #include "rtc_base/strings/string_builder.h" +#include "rtc_base/time_utils.h" namespace cricket { namespace { diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index a18e69590d..e772028b9a 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -1302,6 +1302,7 @@ rtc_library("async_udp_socket") { ] deps = [ ":async_packet_socket", + ":buffer", ":checks", ":logging", ":macromagic", @@ -1311,6 +1312,7 @@ rtc_library("async_udp_socket") { ":timeutils", "../api:sequence_checker", "../api/units:time_delta", + "../api/units:timestamp", "../system_wrappers:field_trial", "network:received_packet", "network:sent_packet", @@ -1328,7 +1330,9 @@ rtc_library("async_packet_socket") { ":callback_list", ":checks", ":dscp", + ":macromagic", ":socket", + ":socket_address", ":timeutils", "../api:sequence_checker", "network:received_packet", @@ -1336,6 +1340,7 @@ rtc_library("async_packet_socket") { "system:no_unique_address", "system:rtc_export", "third_party/sigslot", + "//third_party/abseil-cpp/absl/functional:any_invocable", ] } @@ -1353,6 +1358,24 @@ if (rtc_include_tests) { "third_party/sigslot", ] } + + rtc_library("async_udp_socket_unittest") { + testonly = true + visibility = [ "*" ] + sources = [ "async_udp_socket_unittest.cc" ] + deps = [ + ":async_packet_socket", + ":async_udp_socket", + ":gunit_helpers", + ":rtc_base_tests_utils", + ":socket", + ":socket_address", + "../test:test_support", + "network:received_packet", + "third_party/sigslot", + "//third_party/abseil-cpp/absl/memory", + ] + } } rtc_library("mdns_responder_interface") { diff --git a/rtc_base/async_packet_socket.h b/rtc_base/async_packet_socket.h index 78841526e3..4202fccc32 100644 --- a/rtc_base/async_packet_socket.h +++ b/rtc_base/async_packet_socket.h @@ -11,18 +11,24 @@ #ifndef RTC_BASE_ASYNC_PACKET_SOCKET_H_ #define RTC_BASE_ASYNC_PACKET_SOCKET_H_ +#include #include +#include #include +#include "absl/functional/any_invocable.h" #include "api/sequence_checker.h" #include "rtc_base/callback_list.h" +#include "rtc_base/checks.h" #include "rtc_base/dscp.h" #include "rtc_base/network/received_packet.h" #include "rtc_base/network/sent_packet.h" #include "rtc_base/socket.h" +#include "rtc_base/socket_address.h" #include "rtc_base/system/no_unique_address.h" #include "rtc_base/system/rtc_export.h" #include "rtc_base/third_party/sigslot/sigslot.h" +#include "rtc_base/thread_annotations.h" #include "rtc_base/time_utils.h" namespace rtc { @@ -54,8 +60,6 @@ struct RTC_EXPORT PacketOptions { // Packet will be sent with ECN(1), RFC-3168, Section 5. // Intended to be used with L4S // https://www.rfc-editor.org/rfc/rfc9331.html - // TODO(https://bugs.webrtc.org/15368): Actually implement support for sending - // packets with different marking. bool ecn_1 = false; // When used with RTP packets (for example, webrtc::PacketOptions), the value diff --git a/rtc_base/async_udp_socket.cc b/rtc_base/async_udp_socket.cc index 8d8d7c95de..046355cc10 100644 --- a/rtc_base/async_udp_socket.cc +++ b/rtc_base/async_udp_socket.cc @@ -10,15 +10,22 @@ #include "rtc_base/async_udp_socket.h" +#include +#include #include +#include "api/sequence_checker.h" #include "api/units/time_delta.h" +#include "api/units/timestamp.h" +#include "rtc_base/async_packet_socket.h" #include "rtc_base/checks.h" #include "rtc_base/logging.h" #include "rtc_base/network/received_packet.h" #include "rtc_base/network/sent_packet.h" +#include "rtc_base/socket.h" +#include "rtc_base/socket_address.h" +#include "rtc_base/socket_factory.h" #include "rtc_base/time_utils.h" -#include "system_wrappers/include/field_trial.h" namespace rtc { @@ -73,6 +80,15 @@ int AsyncUDPSocket::SendTo(const void* pv, rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis(), options.info_signaled_after_sent); CopySocketInformationToPacketInfo(cb, *this, &sent_packet.info); + if (has_set_ect1_options_ != options.ecn_1) { + // It is unclear what is most efficient, setting options on every sent + // packet or when changed. Potentially, can separate send sockets be used? + // This is the easier implementation. + if (socket_->SetOption(Socket::Option::OPT_SEND_ECN, + options.ecn_1 ? 1 : 0) == 0) { + has_set_ect1_options_ = options.ecn_1; + } + } int ret = socket_->SendTo(pv, cb, addr); SignalSentPacket(this, sent_packet); return ret; diff --git a/rtc_base/async_udp_socket.h b/rtc_base/async_udp_socket.h index 5eb4b4c000..cf68488e68 100644 --- a/rtc_base/async_udp_socket.h +++ b/rtc_base/async_udp_socket.h @@ -13,13 +13,13 @@ #include -#include #include #include #include "api/sequence_checker.h" #include "api/units/time_delta.h" #include "rtc_base/async_packet_socket.h" +#include "rtc_base/buffer.h" #include "rtc_base/socket.h" #include "rtc_base/socket_address.h" #include "rtc_base/socket_factory.h" @@ -69,6 +69,7 @@ class AsyncUDPSocket : public AsyncPacketSocket { RTC_NO_UNIQUE_ADDRESS webrtc::SequenceChecker sequence_checker_; std::unique_ptr socket_; + bool has_set_ect1_options_ = false; rtc::Buffer buffer_ RTC_GUARDED_BY(sequence_checker_); std::optional socket_time_offset_ RTC_GUARDED_BY(sequence_checker_); diff --git a/rtc_base/async_udp_socket_unittest.cc b/rtc_base/async_udp_socket_unittest.cc index 7df1ca0a46..26ab09ea5d 100644 --- a/rtc_base/async_udp_socket_unittest.cc +++ b/rtc_base/async_udp_socket_unittest.cc @@ -10,41 +10,46 @@ #include "rtc_base/async_udp_socket.h" +#include #include -#include -#include "rtc_base/gunit.h" -#include "rtc_base/physical_socket_server.h" +#include "absl/memory/memory.h" +#include "rtc_base/async_packet_socket.h" +#include "rtc_base/socket.h" +#include "rtc_base/socket_address.h" #include "rtc_base/virtual_socket_server.h" +#include "test/gtest.h" namespace rtc { -class AsyncUdpSocketTest : public ::testing::Test, public sigslot::has_slots<> { - public: - AsyncUdpSocketTest() - : pss_(new rtc::PhysicalSocketServer), - vss_(new rtc::VirtualSocketServer(pss_.get())), - socket_(vss_->CreateSocket(SOCK_DGRAM)), - udp_socket_(new AsyncUDPSocket(socket_)), - ready_to_send_(false) { - udp_socket_->SignalReadyToSend.connect(this, - &AsyncUdpSocketTest::OnReadyToSend); - } +static const SocketAddress kAddr("22.22.22.22", 0); - void OnReadyToSend(rtc::AsyncPacketSocket* socket) { ready_to_send_ = true; } +TEST(AsyncUDPSocketTest, SetSocketOptionIfEctChange) { + VirtualSocketServer socket_server; + Socket* socket = socket_server.CreateSocket(kAddr.family(), SOCK_DGRAM); + std::unique_ptr udp__socket = + absl::WrapUnique(AsyncUDPSocket::Create(socket, kAddr)); - protected: - std::unique_ptr pss_; - std::unique_ptr vss_; - Socket* socket_; - std::unique_ptr udp_socket_; - bool ready_to_send_; -}; + int ect = 0; + socket->GetOption(Socket::OPT_SEND_ECN, &ect); + ASSERT_EQ(ect, 0); -TEST_F(AsyncUdpSocketTest, OnWriteEvent) { - EXPECT_FALSE(ready_to_send_); - socket_->SignalWriteEvent(socket_); - EXPECT_TRUE(ready_to_send_); + uint8_t buffer[] = "hello"; + rtc::PacketOptions packet_options; + packet_options.ecn_1 = false; + udp__socket->SendTo(buffer, 5, kAddr, packet_options); + socket->GetOption(Socket::OPT_SEND_ECN, &ect); + EXPECT_EQ(ect, 0); + + packet_options.ecn_1 = true; + udp__socket->SendTo(buffer, 5, kAddr, packet_options); + socket->GetOption(Socket::OPT_SEND_ECN, &ect); + EXPECT_EQ(ect, 1); + + packet_options.ecn_1 = false; + udp__socket->SendTo(buffer, 5, kAddr, packet_options); + socket->GetOption(Socket::OPT_SEND_ECN, &ect); + EXPECT_EQ(ect, 0); } } // namespace rtc