commit 9b5aa1960a37b67b708f8b94072a40b1d38d9e40
parent 9c16af12676f769c7ceb0a2032c2e0840a450772
Author: Michael Froman <mfroman@mozilla.com>
Date: Wed, 8 Oct 2025 16:42:59 -0500
Bug 1993083 - Vendor libwebrtc from a088d50c49
Upstream commit: https://webrtc.googlesource.com/src/+/a088d50c491686097d56b552c23ea3f5c8749646
Do not restart SCTP transport on DTLS restart
since this does not have the updated information (like sctp-port) yet which will be supplied slightly later in the process of applying the local description.
Bug: None
Change-Id: Ia42219d332b06bba20e86128156caa736ffdab76
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/396121
Commit-Queue: Philipp Hancke <phancke@meta.com>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#45015}
Diffstat:
10 files changed, 117 insertions(+), 14 deletions(-)
diff --git a/third_party/libwebrtc/README.mozilla.last-vendor b/third_party/libwebrtc/README.mozilla.last-vendor
@@ -1,4 +1,4 @@
# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
-libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-08T21:11:22.031784+00:00.
+libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-08T21:42:50.165185+00:00.
# base of lastest vendoring
-032f8c223e
+a088d50c49
diff --git a/third_party/libwebrtc/media/BUILD.gn b/third_party/libwebrtc/media/BUILD.gn
@@ -770,6 +770,7 @@ if (rtc_build_dcsctp) {
"../net/dcsctp/timer:task_queue_timeout",
"../p2p:dtls_transport_internal",
"../p2p:packet_transport_internal",
+ "../rtc_base:async_packet_socket",
"../rtc_base:checks",
"../rtc_base:copy_on_write_buffer",
"../rtc_base:event_tracer",
diff --git a/third_party/libwebrtc/media/sctp/dcsctp_transport.cc b/third_party/libwebrtc/media/sctp/dcsctp_transport.cc
@@ -43,6 +43,7 @@
#include "net/dcsctp/public/types.h"
#include "p2p/base/packet_transport_internal.h"
#include "p2p/dtls/dtls_transport_internal.h"
+#include "rtc_base/async_packet_socket.h"
#include "rtc_base/checks.h"
#include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/logging.h"
@@ -710,17 +711,14 @@ void DcSctpTransport::OnDtlsTransportState(DtlsTransportInternal* transport,
if (state == DtlsTransportState::kNew && socket_) {
// IF DTLS restart (DtlsTransportState::kNew)
// THEN
- // restart socket so that we send an SCPT init
+ // reset the socket so that we send an SCTP init
// before any outgoing messages. This is needed
// after DTLS fingerprint changed since peer will discard
// messages with crypto derived from old fingerprint.
+ // The socket will be restarted (with changed parameters)
+ // later.
RTC_DLOG(LS_INFO) << debug_name_ << " DTLS restart";
- dcsctp::DcSctpOptions options = socket_->options();
socket_.reset();
- RTC_DCHECK_LE(options.max_message_size, kSctpSendBufferSize);
- Start({.local_port = options.local_port,
- .remote_port = options.remote_port,
- .max_message_size = static_cast<int>(options.max_message_size)});
}
}
@@ -741,6 +739,12 @@ void DcSctpTransport::OnTransportReadPacket(
}
void DcSctpTransport::MaybeConnectSocket() {
+ RTC_DLOG(LS_VERBOSE)
+ << debug_name_ << "->MaybeConnectSocket(), writable="
+ << (transport_ ? std::to_string(transport_->writable()) : "UNSET")
+ << " socket: "
+ << (socket_ ? std::to_string(static_cast<int>(socket_->state()))
+ : "UNSET");
if (transport_ && transport_->writable() && socket_ &&
socket_->state() == dcsctp::SocketState::kClosed) {
socket_->Connect();
diff --git a/third_party/libwebrtc/moz-patch-stack/s0027.patch b/third_party/libwebrtc/moz-patch-stack/s0027.patch
@@ -544,7 +544,7 @@ index 9cb0f770ca..0031392f8a 100644
#include "rtc_base/memory/aligned_malloc.h"
diff --git a/media/BUILD.gn b/media/BUILD.gn
-index 203a55ba9d..60983d7a96 100644
+index 421e7ba136..309af412f7 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -77,7 +77,7 @@ rtc_library("rtc_media_base") {
diff --git a/third_party/libwebrtc/moz-patch-stack/s0087.patch b/third_party/libwebrtc/moz-patch-stack/s0087.patch
@@ -9,7 +9,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/60304c5d8a86fdecf
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/media/BUILD.gn b/media/BUILD.gn
-index 60983d7a96..4e4d3a31b2 100644
+index 309af412f7..d249da5fd9 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -56,6 +56,11 @@ rtc_library("rtc_media_base") {
diff --git a/third_party/libwebrtc/moz-patch-stack/s0101.patch b/third_party/libwebrtc/moz-patch-stack/s0101.patch
@@ -26,7 +26,7 @@ index 851c745732..cdbd705ec2 100644
# These are the targets to skip header checking by default. The files in targets
# matching these patterns (see "gn help label_pattern" for format) will not have
diff --git a/media/BUILD.gn b/media/BUILD.gn
-index 4e4d3a31b2..d6a16a3205 100644
+index d249da5fd9..a992a032c5 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -7,7 +7,7 @@
diff --git a/third_party/libwebrtc/moz-patch-stack/s0103.patch b/third_party/libwebrtc/moz-patch-stack/s0103.patch
@@ -427,7 +427,7 @@ index 65fe4b69f5..f091ff40cb 100644
group("logging") {
diff --git a/media/BUILD.gn b/media/BUILD.gn
-index d6a16a3205..614bbdb3e7 100644
+index a992a032c5..6f2dc22e00 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -6,7 +6,7 @@
diff --git a/third_party/libwebrtc/moz-patch-stack/s0108.patch b/third_party/libwebrtc/moz-patch-stack/s0108.patch
@@ -38,7 +38,7 @@ index 8964d077bf..123739a1ff 100644
]
# Added when we removed deps in other places to avoid building
diff --git a/media/BUILD.gn b/media/BUILD.gn
-index 614bbdb3e7..02d978446a 100644
+index 6f2dc22e00..e3ee0fe861 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -12,12 +12,10 @@ import("../webrtc.gni")
diff --git a/third_party/libwebrtc/moz-patch-stack/s0110.patch b/third_party/libwebrtc/moz-patch-stack/s0110.patch
@@ -10,7 +10,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b6dd815fc9d2df718
1 file changed, 11 deletions(-)
diff --git a/media/BUILD.gn b/media/BUILD.gn
-index 02d978446a..031388abd7 100644
+index e3ee0fe861..d4f9d62f2f 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -54,11 +54,6 @@ rtc_library("rtc_media_base") {
diff --git a/third_party/libwebrtc/pc/data_channel_integrationtest.cc b/third_party/libwebrtc/pc/data_channel_integrationtest.cc
@@ -75,6 +75,13 @@ using ::testing::ValuesIn;
#define DISABLED_ON_ANDROID(t) t
#endif
+void VerifySctpState(PeerConnectionIntegrationWrapper* pc,
+ SctpTransportState expected_state) {
+ auto sctp_transport = pc->pc()->GetSctpTransport();
+ ASSERT_TRUE(sctp_transport);
+ EXPECT_EQ(sctp_transport->Information().state(), expected_state);
+}
+
class DataChannelIntegrationTest
: public PeerConnectionIntegrationBaseTest,
public ::testing::WithParamInterface<std::tuple<SdpSemantics, bool>> {
@@ -1383,6 +1390,94 @@ TEST_P(DataChannelIntegrationTest,
callee()->data_observer()->received_message_count());
}
+TEST_P(DataChannelIntegrationTest, ChangingSctpPortIsNotAllowed) {
+ ASSERT_TRUE(CreatePeerConnectionWrappers());
+ ConnectFakeSignaling();
+ caller()->CreateDataChannel();
+ caller()->CreateAndSetAndSignalOffer();
+ ASSERT_THAT(WaitUntil([&] { return SignalingStateStable(); }, IsTrue()),
+ IsRtcOk());
+ ASSERT_THAT(WaitUntil([&] { return callee()->data_channel(); }, Ne(nullptr)),
+ IsRtcOk());
+ EXPECT_THAT(
+ WaitUntil([&] { return caller()->data_observer()->IsOpen(); }, IsTrue()),
+ IsRtcOk());
+ EXPECT_THAT(
+ WaitUntil([&] { return callee()->data_observer()->IsOpen(); }, IsTrue()),
+ IsRtcOk());
+
+ std::unique_ptr<SessionDescriptionInterface> answer;
+ caller()->SetReceivedSdpMunger(
+ [&answer](std::unique_ptr<SessionDescriptionInterface>& desc) {
+ // Change the SCTP port.
+ ContentInfo* sctp_content = GetFirstDataContent(desc->description());
+ ASSERT_TRUE(sctp_content);
+ auto sctp_description = sctp_content->media_description()->as_sctp();
+ ASSERT_TRUE(sctp_description);
+ sctp_description->set_port(sctp_description->port() + 1);
+
+ // Capture and suppress the answer.
+ answer.reset(desc.release());
+ });
+ caller()->CreateAndSetAndSignalOffer();
+ ASSERT_TRUE(answer);
+
+ // Currently SRD succeeds.
+ EXPECT_TRUE(caller()->SetRemoteDescription(std::move(answer)));
+ // Check the state of the SCTP transport.
+ VerifySctpState(caller(), SctpTransportState::kClosed);
+}
+
+TEST_P(DataChannelIntegrationTest, ChangingSctpPortIsAllowedWithDtlsRestart) {
+ ASSERT_TRUE(CreatePeerConnectionWrappers());
+ ConnectFakeSignaling();
+ caller()->CreateDataChannel();
+ caller()->CreateAndSetAndSignalOffer();
+ ASSERT_THAT(WaitUntil([&] { return SignalingStateStable(); }, IsTrue()),
+ IsRtcOk());
+ ASSERT_THAT(WaitUntil([&] { return callee()->data_channel(); }, Ne(nullptr)),
+ IsRtcOk());
+ EXPECT_THAT(
+ WaitUntil([&] { return caller()->data_observer()->IsOpen(); }, IsTrue()),
+ IsRtcOk());
+ EXPECT_THAT(
+ WaitUntil([&] { return callee()->data_observer()->IsOpen(); }, IsTrue()),
+ IsRtcOk());
+
+ // Recreate the second peerconnection.
+ PeerConnectionDependencies dependencies(nullptr);
+ std::unique_ptr<FakeRTCCertificateGenerator> cert_generator(
+ new FakeRTCCertificateGenerator());
+ cert_generator->use_alternate_key();
+ dependencies.cert_generator = std::move(cert_generator);
+ SetCalleePcWrapperAndReturnCurrent(CreatePeerConnectionWrapper(
+ "Callee2", nullptr, {}, std::move(dependencies), nullptr,
+ /*reset_encoder_factory=*/false,
+ /*reset_decoder_factory=*/false,
+ /*create_media_engine=*/false));
+ ConnectFakeSignaling();
+
+ std::unique_ptr<SessionDescriptionInterface> answer;
+ caller()->SetReceivedSdpMunger(
+ [&answer](std::unique_ptr<SessionDescriptionInterface>& desc) {
+ // Change the SCTP port.
+ ContentInfo* sctp_content = GetFirstDataContent(desc->description());
+ ASSERT_TRUE(sctp_content);
+ auto sctp_description = sctp_content->media_description()->as_sctp();
+ ASSERT_TRUE(sctp_description);
+ sctp_description->set_port(sctp_description->port() + 1);
+
+ // Capture and suppress the answer.
+ answer.reset(desc.release());
+ });
+ caller()->CreateAndSetAndSignalOffer();
+ ASSERT_TRUE(answer);
+
+ EXPECT_TRUE(caller()->SetRemoteDescription(std::move(answer)));
+ // Check the state of the SCTP transport.
+ VerifySctpState(caller(), SctpTransportState::kConnected);
+}
+
INSTANTIATE_TEST_SUITE_P(DataChannelIntegrationTest,
DataChannelIntegrationTest,
Combine(Values(SdpSemantics::kPlanB_DEPRECATED,
@@ -1716,6 +1811,9 @@ TEST_P(DataChannelIntegrationTestUnifiedPlanFieldTrials,
VerifyReceivedDcMessages(caller(), "KENT", callee2_sent_on_dc);
VerifyReceivedDcMessages(callee2.get(), "KESO", caller_sent_on_dc);
VerifyDtlsRoles(caller(), callee2.get());
+ VerifySctpState(caller(), SctpTransportState::kConnected);
+ VerifySctpState(callee(), SctpTransportState::kClosed);
+ VerifySctpState(callee2.get(), SctpTransportState::kConnected);
ASSERT_FALSE(HasFailure());
}