tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

packet_router.cc (14463B)


      1 /*
      2 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "modules/pacing/packet_router.h"
     12 
     13 #include <algorithm>
     14 #include <cstdint>
     15 #include <memory>
     16 #include <optional>
     17 #include <utility>
     18 #include <vector>
     19 
     20 #include "absl/functional/any_invocable.h"
     21 #include "api/array_view.h"
     22 #include "api/rtp_headers.h"
     23 #include "api/sequence_checker.h"
     24 #include "api/transport/network_types.h"
     25 #include "api/units/data_size.h"
     26 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
     27 #include "modules/rtp_rtcp/source/rtcp_packet.h"
     28 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
     29 #include "modules/rtp_rtcp/source/rtp_rtcp_interface.h"
     30 #include "rtc_base/checks.h"
     31 #include "rtc_base/logging.h"
     32 #include "rtc_base/system/unused.h"
     33 #include "rtc_base/trace_event.h"
     34 
     35 namespace webrtc {
     36 
     37 PacketRouter::PacketRouter()
     38    : last_send_module_(nullptr),
     39      active_remb_module_(nullptr),
     40      transport_seq_(1) {}
     41 
     42 PacketRouter::~PacketRouter() {
     43  RTC_DCHECK_RUN_ON(&thread_checker_);
     44  RTC_DCHECK(send_modules_map_.empty());
     45  RTC_DCHECK(send_modules_list_.empty());
     46  RTC_DCHECK(rtcp_feedback_senders_.empty());
     47  RTC_DCHECK(sender_remb_candidates_.empty());
     48  RTC_DCHECK(receiver_remb_candidates_.empty());
     49  RTC_DCHECK(active_remb_module_ == nullptr);
     50 }
     51 
     52 void PacketRouter::AddSendRtpModule(RtpRtcpInterface* rtp_module,
     53                                    bool remb_candidate) {
     54  RTC_DCHECK_RUN_ON(&thread_checker_);
     55 
     56  AddSendRtpModuleToMap(rtp_module, rtp_module->SSRC());
     57  if (std::optional<uint32_t> rtx_ssrc = rtp_module->RtxSsrc()) {
     58    AddSendRtpModuleToMap(rtp_module, *rtx_ssrc);
     59  }
     60  if (std::optional<uint32_t> flexfec_ssrc = rtp_module->FlexfecSsrc()) {
     61    AddSendRtpModuleToMap(rtp_module, *flexfec_ssrc);
     62  }
     63 
     64  if (rtp_module->SupportsRtxPayloadPadding()) {
     65    last_send_module_ = rtp_module;
     66  }
     67 
     68  if (remb_candidate) {
     69    AddRembModuleCandidate(rtp_module, /* media_sender = */ true);
     70  }
     71 }
     72 
     73 bool PacketRouter::SupportsRtxPayloadPadding() const {
     74  RTC_DCHECK_RUN_ON(&thread_checker_);
     75  for (RtpRtcpInterface* rtp_module : send_modules_list_) {
     76    if (rtp_module->SupportsRtxPayloadPadding()) {
     77      return true;
     78    }
     79  }
     80  return false;
     81 }
     82 
     83 void PacketRouter::RegisterNotifyBweCallback(
     84    absl::AnyInvocable<void(const RtpPacketToSend& packet,
     85                            const PacedPacketInfo& pacing_info)> callback) {
     86  RTC_DCHECK_RUN_ON(&thread_checker_);
     87  notify_bwe_callback_ = std::move(callback);
     88 }
     89 
     90 void PacketRouter::ConfigureForRfc8888Feedback(bool send_rtp_packets_as_ect1) {
     91  RTC_DCHECK_RUN_ON(&thread_checker_);
     92  use_cc_feedback_according_to_rfc8888_ = true;
     93  send_rtp_packets_as_ect1_ = send_rtp_packets_as_ect1;
     94 }
     95 
     96 void PacketRouter::AddSendRtpModuleToMap(RtpRtcpInterface* rtp_module,
     97                                         uint32_t ssrc) {
     98  RTC_DCHECK_RUN_ON(&thread_checker_);
     99  RTC_CHECK(send_modules_map_.find(ssrc) == send_modules_map_.end());
    100 
    101  // Signal to module that the pacer thread is attached and can send packets.
    102  rtp_module->OnPacketSendingThreadSwitched();
    103 
    104  // Always keep the audio modules at the back of the list, so that when we
    105  // iterate over the modules in order to find one that can send padding we
    106  // will prioritize video. This is important to make sure they are counted
    107  // into the bandwidth estimate properly.
    108  if (rtp_module->IsAudioConfigured()) {
    109    send_modules_list_.push_back(rtp_module);
    110  } else {
    111    send_modules_list_.push_front(rtp_module);
    112  }
    113  send_modules_map_[ssrc] = rtp_module;
    114 }
    115 
    116 void PacketRouter::RemoveSendRtpModuleFromMap(uint32_t ssrc) {
    117  RTC_DCHECK_RUN_ON(&thread_checker_);
    118  auto it = send_modules_map_.find(ssrc);
    119  if (it == send_modules_map_.end()) {
    120    RTC_LOG(LS_ERROR) << "No send module found for ssrc " << ssrc;
    121    return;
    122  }
    123  send_modules_list_.remove(it->second);
    124  RTC_CHECK(modules_used_in_current_batch_.empty());
    125  send_modules_map_.erase(it);
    126 }
    127 
    128 void PacketRouter::RemoveSendRtpModule(RtpRtcpInterface* rtp_module) {
    129  RTC_DCHECK_RUN_ON(&thread_checker_);
    130  MaybeRemoveRembModuleCandidate(rtp_module, /* media_sender = */ true);
    131 
    132  RemoveSendRtpModuleFromMap(rtp_module->SSRC());
    133  if (std::optional<uint32_t> rtx_ssrc = rtp_module->RtxSsrc()) {
    134    RemoveSendRtpModuleFromMap(*rtx_ssrc);
    135  }
    136  if (std::optional<uint32_t> flexfec_ssrc = rtp_module->FlexfecSsrc()) {
    137    RemoveSendRtpModuleFromMap(*flexfec_ssrc);
    138  }
    139 
    140  if (last_send_module_ == rtp_module) {
    141    last_send_module_ = nullptr;
    142  }
    143  rtp_module->OnPacketSendingThreadSwitched();
    144 }
    145 
    146 void PacketRouter::AddReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender,
    147                                       bool remb_candidate) {
    148  RTC_DCHECK_RUN_ON(&thread_checker_);
    149  RTC_DCHECK(std::find(rtcp_feedback_senders_.begin(),
    150                       rtcp_feedback_senders_.end(),
    151                       rtcp_sender) == rtcp_feedback_senders_.end());
    152 
    153  rtcp_feedback_senders_.push_back(rtcp_sender);
    154 
    155  if (remb_candidate) {
    156    AddRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
    157  }
    158 }
    159 
    160 void PacketRouter::RemoveReceiveRtpModule(
    161    RtcpFeedbackSenderInterface* rtcp_sender) {
    162  RTC_DCHECK_RUN_ON(&thread_checker_);
    163  MaybeRemoveRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
    164  auto it = std::find(rtcp_feedback_senders_.begin(),
    165                      rtcp_feedback_senders_.end(), rtcp_sender);
    166  RTC_DCHECK(it != rtcp_feedback_senders_.end());
    167  rtcp_feedback_senders_.erase(it);
    168 }
    169 
    170 void PacketRouter::SendPacket(std::unique_ptr<RtpPacketToSend> packet,
    171                              const PacedPacketInfo& cluster_info) {
    172  RTC_DCHECK_RUN_ON(&thread_checker_);
    173  TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"), "PacketRouter::SendPacket",
    174               "sequence_number", packet->SequenceNumber(), "rtp_timestamp",
    175               packet->Timestamp());
    176 
    177  uint32_t ssrc = packet->Ssrc();
    178  auto it = send_modules_map_.find(ssrc);
    179  if (it == send_modules_map_.end()) {
    180    RTC_LOG(LS_WARNING)
    181        << "Failed to send packet, matching RTP module not found "
    182           "or transport error. SSRC = "
    183        << packet->Ssrc() << ", sequence number " << packet->SequenceNumber();
    184    return;
    185  }
    186 
    187  RtpRtcpInterface* rtp_module = it->second;
    188  if (!packet || !rtp_module->CanSendPacket(*packet)) {
    189    RTC_LOG(LS_WARNING) << "Failed to send packet, Not sending media";
    190    return;
    191  }
    192 
    193  // Transport sequence numbers are used if send side bandwidth estimation is
    194  // used. Send side BWE relies on RTCP feedback either using format described
    195  // in RFC 8888 or
    196  // https://datatracker.ietf.org/doc/html/draft-holmer-rmcat-transport-wide-cc-extensions-01.
    197  // If RFC 8888 feedback is used, a transport
    198  // sequence number is created for all RTP packets, but not sent in the RTP
    199  // packet. Otherwise, the transport sequence number is only created
    200  // if the TransportSequenceNumber header extension is negotiated for the
    201  // specific media type. Historically, webrtc only used TransportSequenceNumber
    202  // on video packets.
    203  if (use_cc_feedback_according_to_rfc8888_ ||
    204      packet->HasExtension<TransportSequenceNumber>()) {
    205    packet->set_transport_sequence_number(transport_seq_++);
    206  }
    207  if (send_rtp_packets_as_ect1_) {
    208    packet->set_send_as_ect1();
    209  }
    210  rtp_module->AssignSequenceNumber(*packet);
    211  if (notify_bwe_callback_) {
    212    notify_bwe_callback_(*packet, cluster_info);
    213  }
    214 
    215  rtp_module->SendPacket(std::move(packet), cluster_info);
    216  modules_used_in_current_batch_.insert(rtp_module);
    217 
    218  // Sending succeeded.
    219  if (rtp_module->SupportsRtxPayloadPadding()) {
    220    // This is now the last module to send media, and has the desired
    221    // properties needed for payload based padding. Cache it for later use.
    222    last_send_module_ = rtp_module;
    223  }
    224 
    225  for (auto& fec_packet : rtp_module->FetchFecPackets()) {
    226    pending_fec_packets_.push_back(std::move(fec_packet));
    227  }
    228 }
    229 
    230 void PacketRouter::OnBatchComplete() {
    231  RTC_DCHECK_RUN_ON(&thread_checker_);
    232  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("webrtc"),
    233               "PacketRouter::OnBatchComplete");
    234  for (auto& module : modules_used_in_current_batch_) {
    235    module->OnBatchComplete();
    236  }
    237  modules_used_in_current_batch_.clear();
    238 }
    239 
    240 std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::FetchFec() {
    241  RTC_DCHECK_RUN_ON(&thread_checker_);
    242  std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
    243      std::move(pending_fec_packets_);
    244  pending_fec_packets_.clear();
    245  return fec_packets;
    246 }
    247 
    248 std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::GeneratePadding(
    249    DataSize size) {
    250  RTC_DCHECK_RUN_ON(&thread_checker_);
    251  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("webrtc"),
    252               "PacketRouter::GeneratePadding", "bytes", size.bytes());
    253 
    254  // First try on the last rtp module to have sent media. This increases the
    255  // the chance that any payload based padding will be useful as it will be
    256  // somewhat distributed over modules according the packet rate, even if it
    257  // will be more skewed towards the highest bitrate stream. At the very least
    258  // this prevents sending payload padding on a disabled stream where it's
    259  // guaranteed not to be useful.
    260  std::vector<std::unique_ptr<RtpPacketToSend>> padding_packets;
    261  if (last_send_module_ != nullptr &&
    262      last_send_module_->SupportsRtxPayloadPadding()) {
    263    padding_packets = last_send_module_->GeneratePadding(size.bytes());
    264  }
    265 
    266  if (padding_packets.empty()) {
    267    // Iterate over all modules send module. Video modules will be at the front
    268    // and so will be prioritized. This is important since audio packets may not
    269    // be taken into account by the bandwidth estimator, e.g. in FF.
    270    for (RtpRtcpInterface* rtp_module : send_modules_list_) {
    271      if (rtp_module->SupportsPadding()) {
    272        padding_packets = rtp_module->GeneratePadding(size.bytes());
    273        if (!padding_packets.empty()) {
    274          last_send_module_ = rtp_module;
    275          break;
    276        }
    277      }
    278    }
    279  }
    280 
    281  for (auto& packet : padding_packets) {
    282    RTC_UNUSED(packet);
    283    TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"),
    284                 "PacketRouter::GeneratePadding::Loop", "sequence_number",
    285                 packet->SequenceNumber(), "rtp_timestamp",
    286                 packet->Timestamp());
    287  }
    288 
    289  return padding_packets;
    290 }
    291 
    292 void PacketRouter::OnAbortedRetransmissions(
    293    uint32_t ssrc,
    294    ArrayView<const uint16_t> sequence_numbers) {
    295  RTC_DCHECK_RUN_ON(&thread_checker_);
    296  auto it = send_modules_map_.find(ssrc);
    297  if (it != send_modules_map_.end()) {
    298    it->second->OnAbortedRetransmissions(sequence_numbers);
    299  }
    300 }
    301 
    302 std::optional<uint32_t> PacketRouter::GetRtxSsrcForMedia(uint32_t ssrc) const {
    303  RTC_DCHECK_RUN_ON(&thread_checker_);
    304  auto it = send_modules_map_.find(ssrc);
    305  if (it != send_modules_map_.end() && it->second->SSRC() == ssrc) {
    306    // A module is registered with the given SSRC, and that SSRC is the main
    307    // media SSRC for that RTP module.
    308    return it->second->RtxSsrc();
    309  }
    310  return std::nullopt;
    311 }
    312 
    313 void PacketRouter::SendRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs) {
    314  RTC_DCHECK_RUN_ON(&thread_checker_);
    315 
    316  if (!active_remb_module_) {
    317    return;
    318  }
    319 
    320  // The Add* and Remove* methods above ensure that REMB is disabled on all
    321  // other modules, because otherwise, they will send REMB with stale info.
    322  active_remb_module_->SetRemb(bitrate_bps, std::move(ssrcs));
    323 }
    324 
    325 void PacketRouter::SendCombinedRtcpPacket(
    326    std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets) {
    327  RTC_DCHECK_RUN_ON(&thread_checker_);
    328 
    329  // Prefer send modules.
    330  for (RtpRtcpInterface* rtp_module : send_modules_list_) {
    331    if (rtp_module->RTCP() == RtcpMode::kOff) {
    332      continue;
    333    }
    334    rtp_module->SendCombinedRtcpPacket(std::move(packets));
    335    return;
    336  }
    337 
    338  if (rtcp_feedback_senders_.empty()) {
    339    return;
    340  }
    341  auto* rtcp_sender = rtcp_feedback_senders_[0];
    342  rtcp_sender->SendCombinedRtcpPacket(std::move(packets));
    343 }
    344 
    345 void PacketRouter::AddRembModuleCandidate(
    346    RtcpFeedbackSenderInterface* candidate_module,
    347    bool media_sender) {
    348  RTC_DCHECK(candidate_module);
    349  std::vector<RtcpFeedbackSenderInterface*>& candidates =
    350      media_sender ? sender_remb_candidates_ : receiver_remb_candidates_;
    351  RTC_DCHECK(std::find(candidates.cbegin(), candidates.cend(),
    352                       candidate_module) == candidates.cend());
    353  candidates.push_back(candidate_module);
    354  DetermineActiveRembModule();
    355 }
    356 
    357 void PacketRouter::MaybeRemoveRembModuleCandidate(
    358    RtcpFeedbackSenderInterface* candidate_module,
    359    bool media_sender) {
    360  RTC_DCHECK_RUN_ON(&thread_checker_);
    361  RTC_DCHECK(candidate_module);
    362  std::vector<RtcpFeedbackSenderInterface*>& candidates =
    363      media_sender ? sender_remb_candidates_ : receiver_remb_candidates_;
    364  auto it = std::find(candidates.begin(), candidates.end(), candidate_module);
    365 
    366  if (it == candidates.end()) {
    367    return;  // Function called due to removal of non-REMB-candidate module.
    368  }
    369 
    370  if (*it == active_remb_module_) {
    371    UnsetActiveRembModule();
    372  }
    373  candidates.erase(it);
    374  DetermineActiveRembModule();
    375 }
    376 
    377 void PacketRouter::UnsetActiveRembModule() {
    378  RTC_DCHECK_RUN_ON(&thread_checker_);
    379  RTC_CHECK(active_remb_module_);
    380  active_remb_module_->UnsetRemb();
    381  active_remb_module_ = nullptr;
    382 }
    383 
    384 void PacketRouter::DetermineActiveRembModule() {
    385  RTC_DCHECK_RUN_ON(&thread_checker_);
    386  // Sender modules take precedence over receiver modules, because SRs (sender
    387  // reports) are sent more frequently than RR (receiver reports).
    388  // When adding the first sender module, we should change the active REMB
    389  // module to be that. Otherwise, we remain with the current active module.
    390 
    391  RtcpFeedbackSenderInterface* new_active_remb_module;
    392 
    393  if (!sender_remb_candidates_.empty()) {
    394    new_active_remb_module = sender_remb_candidates_.front();
    395  } else if (!receiver_remb_candidates_.empty()) {
    396    new_active_remb_module = receiver_remb_candidates_.front();
    397  } else {
    398    new_active_remb_module = nullptr;
    399  }
    400 
    401  if (new_active_remb_module != active_remb_module_ && active_remb_module_) {
    402    UnsetActiveRembModule();
    403  }
    404 
    405  active_remb_module_ = new_active_remb_module;
    406 }
    407 
    408 }  // namespace webrtc