Ignore internal transport packets in DatagramConnection

Prevent DatagramConnection from forwarding internal and post-handshake
packets (such as BoringSSL session tickets, DTLS handshakes, or STUN
connectivity checks) to the OnSendOutcome observer. These internal
packets are assigned a default packet ID of -1, signaling that they
are not user-initiated data.

This could cause the following error:

[ RUN ]
DatagramConnectionTest.RtpPacketsAreSent
../../pc/datagram_connection_unittest.cc:219: Failure Mock function
called more times than expected - returning directly.
    Function call: OnSendOutcome
         Expected: to be called once
           Actual: called twice - over-saturated and active
[ FAILED ] DatagramConnectionTest.RtpPacketsAreSent (108 ms)

Additionally, update the `Observer::SendOutcome` initialization in
OnSentPacket and DispatchSendOutcome to use structured initialization,
and Add a fallback to Timestamp::MinusInfinity() and avoid setting the
timestamp to -1ms.

Bug: none
Change-Id: I6576110ec5f9aa620b8870d3f6db963d1f5e2bbd
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/477140
Auto-Submit: Tomas Gunnarsson <tommi@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Reviewed-by: Tony Herre <herre@google.com>
Cr-Commit-Position: refs/heads/main@{#47862}
diff --git a/pc/datagram_connection_internal.cc b/pc/datagram_connection_internal.cc
index 38c2e43..f95455e 100644
--- a/pc/datagram_connection_internal.cc
+++ b/pc/datagram_connection_internal.cc
@@ -390,20 +390,25 @@
 }
 
 void DatagramConnectionInternal::OnSentPacket(const SentPacketInfo& sent_info) {
-  Observer::SendOutcome outcome{};
-  outcome.id = sent_info.packet_id;
-  outcome.status = Observer::SendOutcome::Status::kSuccess;
-  outcome.send_time = Timestamp::Millis(sent_info.send_time_ms);
-  outcome.bytes_sent = sent_info.info.packet_size_bytes;
+  // Ignore internal transport packets (e.g. DTLS handshakes, session tickets,
+  // STUN connectivity checks) which are sent with the default packet ID of -1.
+  if (sent_info.packet_id == -1) {
+    return;
+  }
+  Observer::SendOutcome outcome{
+      .id = static_cast<DatagramConnection::PacketId>(sent_info.packet_id),
+      .status = Observer::SendOutcome::Status::kSuccess,
+      .send_time = sent_info.send_time_ms >= 0
+                       ? Timestamp::Millis(sent_info.send_time_ms)
+                       : Timestamp::MinusInfinity(),
+      .bytes_sent = sent_info.info.packet_size_bytes};
   observer_->OnSendOutcome(outcome);
 }
 
 void DatagramConnectionInternal::DispatchSendOutcome(
     PacketId id,
     Observer::SendOutcome::Status status) {
-  Observer::SendOutcome outcome{};
-  outcome.id = id;
-  outcome.status = status;
+  Observer::SendOutcome outcome{.id = id, .status = status};
   observer_->OnSendOutcome(outcome);
 }
 
diff --git a/pc/datagram_connection_unittest.cc b/pc/datagram_connection_unittest.cc
index 0f35f5f..3abb034 100644
--- a/pc/datagram_connection_unittest.cc
+++ b/pc/datagram_connection_unittest.cc
@@ -34,6 +34,7 @@
 #include "pc/datagram_connection_internal.h"
 #include "pc/test/fake_rtc_certificate_generator.h"
 #include "rtc_base/copy_on_write_buffer.h"
+#include "rtc_base/network/sent_packet.h"
 #include "rtc_base/rtc_certificate.h"
 #include "rtc_base/socket_address.h"
 #include "rtc_base/ssl_fingerprint.h"
@@ -543,5 +544,36 @@
   EXPECT_TRUE(callback_called);
 }
 
+TEST_F(DatagramConnectionTest, InternalSentPacketsAreIgnored) {
+  CreateConnections();
+  EXPECT_CALL(*observer1_ptr_, OnSendOutcome(_)).Times(0);
+
+  SentPacketInfo internal_packet;
+  internal_packet.packet_id = -1;
+
+  conn1_->OnSentPacket(internal_packet);
+}
+
+TEST_F(DatagramConnectionTest, UserSentPacketsTriggerOnSendOutcome) {
+  CreateConnections();
+  bool callback_called = false;
+  EXPECT_CALL(*observer1_ptr_, OnSendOutcome(_))
+      .WillOnce([&](const SendOutcome& outcome) {
+        EXPECT_EQ(outcome.id, 123u);
+        EXPECT_EQ(outcome.status, SendOutcome::Status::kSuccess);
+        EXPECT_EQ(outcome.send_time, Timestamp::Millis(456));
+        EXPECT_EQ(outcome.bytes_sent, 100u);
+        callback_called = true;
+      });
+
+  SentPacketInfo user_packet;
+  user_packet.packet_id = 123;
+  user_packet.send_time_ms = 456;
+  user_packet.info.packet_size_bytes = 100;
+
+  conn1_->OnSentPacket(user_packet);
+  EXPECT_TRUE(callback_called);
+}
+
 }  // namespace
 }  // namespace webrtc