Add feature to set MTU on DTLS handshake

To be used by dtls-in-stun (in follow up, see https://webrtc-review.googlesource.com/c/src/+/385680)

The patch switches from BIO_CTRL_DGRAM_QUERY_MTU to SSL_set_mtu
which is much easier to manage.


BUG=webrtc:367395350

No-Iwyu: ssl_stream_adapter does include correct...#ifdef BORINGSSL
Change-Id: I29bd14287e0cc28f9e58e70299e83e8f2735563c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/385720
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#44347}
diff --git a/rtc_base/openssl_stream_adapter.cc b/rtc_base/openssl_stream_adapter.cc
index 8b256ee..c1d28c0 100644
--- a/rtc_base/openssl_stream_adapter.cc
+++ b/rtc_base/openssl_stream_adapter.cc
@@ -282,6 +282,8 @@
       // The handshake doesn't actually need to send packets above 1k,
       // so this seems like a sensible value that should work in most cases.
       // Webrtc uses the same value for video packets.
+      RTC_DCHECK_NOTREACHED()
+          << "We should be using SSL_set_mtu instead of this!";
       return 1200;
     default:
       return 0;
@@ -578,6 +580,13 @@
 #endif
 }
 
+void OpenSSLStreamAdapter::SetMTU(int mtu) {
+  dtls_mtu_ = mtu;
+  if (ssl_) {
+    RTC_CHECK(SSL_set_mtu(ssl_, dtls_mtu_)) << "Call to SSL_set_mtu failed.";
+  }
+}
+
 //
 // StreamInterface Implementation
 //
@@ -890,6 +899,12 @@
   SSL_set_app_data(ssl_, this);
 
   SSL_set_bio(ssl_, bio, bio);  // the SSL object owns the bio now.
+
+  // Use SSL_set_mtu to configure MTU insted of
+  // BIO_CTRL_DGRAM_QUERY_MTU
+  SSL_set_options(ssl_, SSL_OP_NO_QUERY_MTU);
+  SSL_set_mtu(ssl_, dtls_mtu_);
+
 #ifdef OPENSSL_IS_BORINGSSL
   if (ssl_mode_ == webrtc::SSL_MODE_DTLS) {
     DTLSv1_set_initial_timeout_duration(ssl_, dtls_handshake_timeout_ms_);
@@ -1123,6 +1138,7 @@
 #if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER >= 0x30000000L)
   SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
 #endif
+
   return ctx;
 }
 
diff --git a/rtc_base/openssl_stream_adapter.h b/rtc_base/openssl_stream_adapter.h
index 3c44d52..90f1f55 100644
--- a/rtc_base/openssl_stream_adapter.h
+++ b/rtc_base/openssl_stream_adapter.h
@@ -92,6 +92,7 @@
   [[deprecated]] void SetMode(SSLMode mode) override;
   void SetMaxProtocolVersion(SSLProtocolVersion version) override;
   void SetInitialRetransmissionTimeout(int timeout_ms) override;
+  void SetMTU(int mtu) override;
 
   StreamResult Read(rtc::ArrayView<uint8_t> data,
                     size_t& read,
@@ -252,6 +253,9 @@
   // be too aggressive for low bandwidth links.
   int dtls_handshake_timeout_ms_ = 50;
 
+  // MTU configured for dtls.
+  int dtls_mtu_ = 1200;
+
   // 0 == Disabled
   // 1 == Max
   // 2 == Enabled (both min and max)
diff --git a/rtc_base/ssl_stream_adapter.h b/rtc_base/ssl_stream_adapter.h
index ff051ef..d1c2252 100644
--- a/rtc_base/ssl_stream_adapter.h
+++ b/rtc_base/ssl_stream_adapter.h
@@ -159,6 +159,9 @@
   // This should only be called before StartSSL().
   virtual void SetInitialRetransmissionTimeout(int timeout_ms) = 0;
 
+  // Set MTU to be used for next handshake flight.
+  virtual void SetMTU(int mtu) = 0;
+
   // StartSSL starts negotiation with a peer, whose certificate is verified
   // using the certificate digest. Generally, SetIdentity() and possibly
   // SetServerRole() should have been called before this.
diff --git a/rtc_base/ssl_stream_adapter_unittest.cc b/rtc_base/ssl_stream_adapter_unittest.cc
index db7f5a2..d95ff1d 100644
--- a/rtc_base/ssl_stream_adapter_unittest.cc
+++ b/rtc_base/ssl_stream_adapter_unittest.cc
@@ -770,6 +770,7 @@
       written = data_len;
       return webrtc::SR_SUCCESS;
     }
+    max_seen_mtu_ = std::max(max_seen_mtu_, data_len);
 
     // Optionally damage application data (type 23). Note that we don't damage
     // handshake packets and we damage the last byte to keep the header
@@ -800,6 +801,7 @@
   void SetDamage() { damage_ = true; }
 
   void SetMtu(size_t mtu) { mtu_ = mtu; }
+  size_t GetMaxSeenMtu() const { return max_seen_mtu_; }
 
   void SetHandshakeWait(int wait) {
     handshake_wait_ = webrtc::TimeDelta::Millis(wait);
@@ -895,6 +897,7 @@
   std::unique_ptr<webrtc::SSLStreamAdapter> server_ssl_;
   int delay_;
   size_t mtu_;
+  size_t max_seen_mtu_ = 0;
   int loss_;
   bool lose_first_packet_;
   bool damage_;
@@ -1259,6 +1262,14 @@
   TestTransfer(100);
 }
 
+TEST_F(SSLStreamAdapterTestDTLS, TestSetMTU) {
+  SetMtu(400);
+  client_ssl_->SetMTU(300);
+  server_ssl_->SetMTU(300);
+  TestHandshake();
+  EXPECT_LE(GetMaxSeenMtu(), 300u);
+}
+
 TEST_F(SSLStreamAdapterTestDTLS, TestDTLSTransferWithLoss) {
   TestHandshake();
   SetLoss(10);