Introduce PacketTransportInternal::NotifyPacketReceived


Plan is to replace SignalReadPacket with this new method and have clients register as listeners.
rtc::ReceivedPacket is ammended with Descryption information so that receivers can know how to treat a received packet.
This will replace the current "flag". Also see https://webrtc-review.googlesource.com/c/src/+/340301/3

Bug: webrtc:15368
Change-Id: I9ea1f34e8b1e923d67c2e92e36a22b3dd10dbd73
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/340181
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41795}
diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn
index 1601b49..657e73d 100644
--- a/p2p/BUILD.gn
+++ b/p2p/BUILD.gn
@@ -628,9 +628,12 @@
   deps = [
     ":connection",
     ":port",
+    "../api:sequence_checker",
     "../rtc_base:async_packet_socket",
+    "../rtc_base:callback_list",
     "../rtc_base:network_route",
     "../rtc_base:socket",
+    "../rtc_base/network:received_packet",
     "../rtc_base/system:rtc_export",
     "../rtc_base/third_party/sigslot",
   ]
@@ -1015,6 +1018,8 @@
       "../api/units:time_delta",
       "../rtc_base:copy_on_write_buffer",
       "../rtc_base:task_queue_for_test",
+      "../rtc_base:timeutils",
+      "../rtc_base/network:received_packet",
     ]
     absl_deps = [
       "//third_party/abseil-cpp/absl/algorithm:container",
@@ -1107,6 +1112,7 @@
       "base/dtls_transport_unittest.cc",
       "base/ice_credentials_iterator_unittest.cc",
       "base/p2p_transport_channel_unittest.cc",
+      "base/packet_transport_internal_unittest.cc",
       "base/port_allocator_unittest.cc",
       "base/port_unittest.cc",
       "base/pseudo_tcp_unittest.cc",
diff --git a/p2p/base/fake_ice_transport.h b/p2p/base/fake_ice_transport.h
index 6172ebb..285bfff 100644
--- a/p2p/base/fake_ice_transport.h
+++ b/p2p/base/fake_ice_transport.h
@@ -24,7 +24,9 @@
 #include "api/units/time_delta.h"
 #include "p2p/base/ice_transport_internal.h"
 #include "rtc_base/copy_on_write_buffer.h"
+#include "rtc_base/network/received_packet.h"
 #include "rtc_base/task_queue_for_test.h"
+#include "rtc_base/time_utils.h"
 
 namespace cricket {
 using ::webrtc::SafeTask;
@@ -391,8 +393,8 @@
       RTC_EXCLUSIVE_LOCKS_REQUIRED(network_thread_) {
     if (dest_) {
       last_sent_packet_ = packet;
-      dest_->SignalReadPacket(dest_, packet.data<char>(), packet.size(),
-                              rtc::TimeMicros(), 0);
+      dest_->NotifyPacketReceived(rtc::ReceivedPacket::CreateFromLegacy(
+          packet.data(), packet.size(), rtc::TimeMicros()));
     }
   }
 
diff --git a/p2p/base/fake_packet_transport.h b/p2p/base/fake_packet_transport.h
index e80af0e..29e9bc7 100644
--- a/p2p/base/fake_packet_transport.h
+++ b/p2p/base/fake_packet_transport.h
@@ -98,6 +98,8 @@
     SignalNetworkRouteChanged(network_route);
   }
 
+  using PacketTransportInternal::NotifyPacketReceived;
+
  private:
   void set_writable(bool writable) {
     if (writable_ == writable) {
@@ -121,8 +123,8 @@
   void SendPacketInternal(const CopyOnWriteBuffer& packet) {
     last_sent_packet_ = packet;
     if (dest_) {
-      dest_->SignalReadPacket(dest_, packet.data<char>(), packet.size(),
-                              TimeMicros(), 0);
+      dest_->NotifyPacketReceived(rtc::ReceivedPacket::CreateFromLegacy(
+          packet.data(), packet.size(), rtc::TimeMicros()));
     }
   }
 
diff --git a/p2p/base/p2p_transport_channel.cc b/p2p/base/p2p_transport_channel.cc
index b0e19f6..e3ac48c 100644
--- a/p2p/base/p2p_transport_channel.cc
+++ b/p2p/base/p2p_transport_channel.cc
@@ -2211,17 +2211,14 @@
     last_data_received_ms_ =
         std::max(last_data_received_ms_, connection->last_data_received());
 
-    SignalReadPacket(
-        this, reinterpret_cast<const char*>(packet.payload().data()),
-        packet.payload().size(),
-        packet.arrival_time() ? packet.arrival_time()->us() : -1, 0);
+    NotifyPacketReceived(packet);
 
-  // May need to switch the sending connection based on the receiving media
-  // path if this is the controlled side.
-  if (ice_role_ == ICEROLE_CONTROLLED && connection != selected_connection_) {
-    ice_controller_->OnImmediateSwitchRequest(IceSwitchReason::DATA_RECEIVED,
-                                              connection);
-  }
+    // May need to switch the sending connection based on the receiving media
+    // path if this is the controlled side.
+    if (ice_role_ == ICEROLE_CONTROLLED && connection != selected_connection_) {
+      ice_controller_->OnImmediateSwitchRequest(IceSwitchReason::DATA_RECEIVED,
+                                                connection);
+    }
 }
 
 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) {
diff --git a/p2p/base/packet_transport_internal.cc b/p2p/base/packet_transport_internal.cc
index 0904cb2..2e8c00a 100644
--- a/p2p/base/packet_transport_internal.cc
+++ b/p2p/base/packet_transport_internal.cc
@@ -10,6 +10,9 @@
 
 #include "p2p/base/packet_transport_internal.h"
 
+#include "api/sequence_checker.h"
+#include "rtc_base/network/received_packet.h"
+
 namespace rtc {
 
 PacketTransportInternal::PacketTransportInternal() = default;
@@ -24,4 +27,23 @@
   return absl::optional<NetworkRoute>();
 }
 
+void PacketTransportInternal::NotifyPacketReceived(
+    const rtc::ReceivedPacket& packet) {
+  RTC_DCHECK_RUN_ON(&network_checker_);
+  if (!SignalReadPacket.is_empty()) {
+    // TODO(bugs.webrtc.org:15368): Replace with
+    // received_packet_callbacklist_.
+    int flags = 0;
+    if (packet.decryption_info() == rtc::ReceivedPacket::kSrtpEncrypted) {
+      flags = 1;
+    }
+    SignalReadPacket(
+        this, reinterpret_cast<const char*>(packet.payload().data()),
+        packet.payload().size(),
+        packet.arrival_time() ? packet.arrival_time()->us() : -1, flags);
+  } else {
+    received_packet_callback_list_.Send(this, packet);
+  }
+}
+
 }  // namespace rtc
diff --git a/p2p/base/packet_transport_internal.h b/p2p/base/packet_transport_internal.h
index 2ca47d5..981554a 100644
--- a/p2p/base/packet_transport_internal.h
+++ b/p2p/base/packet_transport_internal.h
@@ -12,11 +12,14 @@
 #define P2P_BASE_PACKET_TRANSPORT_INTERNAL_H_
 
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "absl/types/optional.h"
 #include "p2p/base/port.h"
 #include "rtc_base/async_packet_socket.h"
+#include "rtc_base/callback_list.h"
+#include "rtc_base/network/received_packet.h"
 #include "rtc_base/network_route.h"
 #include "rtc_base/socket.h"
 #include "rtc_base/system/rtc_export.h"
@@ -78,7 +81,19 @@
   // Emitted when receiving state changes to true.
   sigslot::signal1<PacketTransportInternal*> SignalReceivingState;
 
+  template <typename F>
+  void RegisterReceivedPacketCallback(void* id, F&& callback) {
+    RTC_DCHECK_RUN_ON(&network_checker_);
+    received_packet_callback_list_.AddReceiver(id, std::forward<F>(callback));
+  }
+  void DeregisterReceivedPacketCallback(void* id) {
+    RTC_DCHECK_RUN_ON(&network_checker_);
+    received_packet_callback_list_.RemoveReceivers(id);
+  }
+
   // Signalled each time a packet is received on this channel.
+  // TODO(bugs.webrtc.org:15368): Deprecate and remove. Replace with
+  // RegisterReceivedPacketCallback.
   sigslot::signal5<PacketTransportInternal*,
                    const char*,
                    size_t,
@@ -101,6 +116,14 @@
  protected:
   PacketTransportInternal();
   ~PacketTransportInternal() override;
+
+  void NotifyPacketReceived(const rtc::ReceivedPacket& packet);
+
+  webrtc::SequenceChecker network_checker_{webrtc::SequenceChecker::kDetached};
+
+ private:
+  webrtc::CallbackList<PacketTransportInternal*, const rtc::ReceivedPacket&>
+      received_packet_callback_list_ RTC_GUARDED_BY(&network_checker_);
 };
 
 }  // namespace rtc
diff --git a/p2p/base/packet_transport_internal_unittest.cc b/p2p/base/packet_transport_internal_unittest.cc
new file mode 100644
index 0000000..f17e43f
--- /dev/null
+++ b/p2p/base/packet_transport_internal_unittest.cc
@@ -0,0 +1,101 @@
+/*
+ *  Copyright 2024 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "p2p/base/packet_transport_internal.h"
+
+#include "p2p/base/fake_packet_transport.h"
+#include "rtc_base/gunit.h"
+#include "rtc_base/network/received_packet.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
+#include "test/gmock.h"
+
+namespace {
+
+using ::testing::MockFunction;
+
+class SigslotPacketReceiver : public sigslot::has_slots<> {
+ public:
+  bool packet_received() const { return packet_received_; }
+
+  void OnPacketReceived(rtc::PacketTransportInternal*,
+                        const char*,
+                        size_t,
+                        const int64_t&,
+                        int flags) {
+    packet_received_ = true;
+    flags_ = flags;
+  }
+
+  bool packet_received_ = false;
+  int flags_ = -1;
+};
+
+TEST(PacketTransportInternal,
+     PacketFlagsCorrectWithUnDecryptedPacketUsingSigslot) {
+  rtc::FakePacketTransport packet_transport("test");
+  SigslotPacketReceiver receiver;
+  packet_transport.SignalReadPacket.connect(
+      &receiver, &SigslotPacketReceiver::OnPacketReceived);
+
+  packet_transport.NotifyPacketReceived(
+      rtc::ReceivedPacket({}, rtc::SocketAddress(), absl::nullopt,
+                          rtc::ReceivedPacket::kNotDecrypted));
+  ASSERT_TRUE(receiver.packet_received_);
+  EXPECT_EQ(receiver.flags_, 0);
+}
+
+TEST(PacketTransportInternal, PacketFlagsCorrectWithSrtpPacketUsingSigslot) {
+  rtc::FakePacketTransport packet_transport("test");
+  SigslotPacketReceiver receiver;
+  packet_transport.SignalReadPacket.connect(
+      &receiver, &SigslotPacketReceiver::OnPacketReceived);
+
+  packet_transport.NotifyPacketReceived(
+      rtc::ReceivedPacket({}, rtc::SocketAddress(), absl::nullopt,
+                          rtc::ReceivedPacket::kSrtpEncrypted));
+  ASSERT_TRUE(receiver.packet_received_);
+  EXPECT_EQ(receiver.flags_, 1);
+}
+
+TEST(PacketTransportInternal, PacketFlagsCorrectWithDtlsDecryptedUsingSigslot) {
+  rtc::FakePacketTransport packet_transport("test");
+  SigslotPacketReceiver receiver;
+  packet_transport.SignalReadPacket.connect(
+      &receiver, &SigslotPacketReceiver::OnPacketReceived);
+
+  packet_transport.NotifyPacketReceived(
+      rtc::ReceivedPacket({}, rtc::SocketAddress(), absl::nullopt,
+                          rtc::ReceivedPacket::kDtlsDecrypted));
+  ASSERT_TRUE(receiver.packet_received_);
+  EXPECT_EQ(receiver.flags_, 0);
+}
+
+TEST(PacketTransportInternal,
+     NotifyPacketReceivedPassThrougPacketToRegisterListener) {
+  rtc::FakePacketTransport packet_transport("test");
+  MockFunction<void(rtc::PacketTransportInternal*, const rtc::ReceivedPacket&)>
+      receiver;
+
+  packet_transport.RegisterReceivedPacketCallback(&receiver,
+                                                  receiver.AsStdFunction());
+  EXPECT_CALL(receiver, Call)
+      .WillOnce(
+          [](rtc::PacketTransportInternal*, const rtc::ReceivedPacket& packet) {
+            EXPECT_EQ(packet.decryption_info(),
+                      rtc::ReceivedPacket::kDtlsDecrypted);
+          });
+  packet_transport.NotifyPacketReceived(
+      rtc::ReceivedPacket({}, rtc::SocketAddress(), absl::nullopt,
+                          rtc::ReceivedPacket::kDtlsDecrypted));
+
+  packet_transport.DeregisterReceivedPacketCallback(&receiver);
+}
+
+}  // namespace
diff --git a/rtc_base/network/received_packet.cc b/rtc_base/network/received_packet.cc
index 95f5e22..bf8a07c 100644
--- a/rtc_base/network/received_packet.cc
+++ b/rtc_base/network/received_packet.cc
@@ -13,15 +13,24 @@
 #include <utility>
 
 #include "absl/types/optional.h"
+#include "rtc_base/socket_address.h"
 
 namespace rtc {
 
 ReceivedPacket::ReceivedPacket(rtc::ArrayView<const uint8_t> payload,
                                const SocketAddress& source_address,
-                               absl::optional<webrtc::Timestamp> arrival_time)
+                               absl::optional<webrtc::Timestamp> arrival_time,
+                               DecryptionInfo decryption)
     : payload_(payload),
       arrival_time_(std::move(arrival_time)),
-      source_address_(source_address) {}
+      source_address_(source_address),
+      decryption_info_(decryption) {}
+
+ReceivedPacket ReceivedPacket::CopyAndSet(
+    DecryptionInfo decryption_info) const {
+  return ReceivedPacket(payload_, source_address_, arrival_time_,
+                        decryption_info);
+}
 
 // static
 ReceivedPacket ReceivedPacket::CreateFromLegacy(
diff --git a/rtc_base/network/received_packet.h b/rtc_base/network/received_packet.h
index d898ccb..b5a6092 100644
--- a/rtc_base/network/received_packet.h
+++ b/rtc_base/network/received_packet.h
@@ -26,12 +26,21 @@
 // example it may contains STUN, SCTP, SRTP, RTP, RTCP.... etc.
 class RTC_EXPORT ReceivedPacket {
  public:
+  enum DecryptionInfo {
+    kNotDecrypted,   // Payload has not yet been decrypted or encryption is not
+                     // used.
+    kDtlsDecrypted,  // Payload has been Dtls decrypted
+    kSrtpEncrypted   // Payload is SRTP encrypted.
+  };
+
   // Caller must keep memory pointed to by payload and address valid for the
   // lifetime of this ReceivedPacket.
-  ReceivedPacket(
-      rtc::ArrayView<const uint8_t> payload,
-      const SocketAddress& source_address,
-      absl::optional<webrtc::Timestamp> arrival_time = absl::nullopt);
+  ReceivedPacket(rtc::ArrayView<const uint8_t> payload,
+                 const SocketAddress& source_address,
+                 absl::optional<webrtc::Timestamp> arrival_time = absl::nullopt,
+                 DecryptionInfo decryption = kNotDecrypted);
+
+  ReceivedPacket CopyAndSet(DecryptionInfo decryption_info) const;
 
   // Address/port of the packet sender.
   const SocketAddress& source_address() const { return source_address_; }
@@ -43,6 +52,8 @@
     return arrival_time_;
   }
 
+  const DecryptionInfo& decryption_info() const { return decryption_info_; }
+
   static ReceivedPacket CreateFromLegacy(
       const char* data,
       size_t size,
@@ -62,6 +73,7 @@
   rtc::ArrayView<const uint8_t> payload_;
   absl::optional<webrtc::Timestamp> arrival_time_;
   const SocketAddress& source_address_;
+  DecryptionInfo decryption_info_;
 };
 
 }  // namespace rtc