tor-browser

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

rtc_event_processor.h (6503B)


      1 /*
      2 *  Copyright (c) 2018 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 #ifndef LOGGING_RTC_EVENT_LOG_RTC_EVENT_PROCESSOR_H_
     12 #define LOGGING_RTC_EVENT_LOG_RTC_EVENT_PROCESSOR_H_
     13 
     14 #include <stdint.h>
     15 
     16 #include <functional>
     17 #include <memory>
     18 #include <optional>
     19 #include <type_traits>
     20 #include <vector>
     21 
     22 #include "logging/rtc_event_log/rtc_event_log_parser.h"
     23 #include "logging/rtc_event_log/rtc_event_processor_order.h"
     24 #include "rtc_base/checks.h"
     25 
     26 namespace webrtc {
     27 
     28 // This file contains helper class used to process the elements of two or more
     29 // sorted lists in timestamp order. The effect is the same as doing a merge step
     30 // in the merge-sort algorithm but without copying the elements or modifying the
     31 // lists.
     32 
     33 namespace event_processor_impl {
     34 // Interface to allow "merging" lists of different types. ProcessNext()
     35 // processes the next unprocessed element in the list. IsEmpty() checks if all
     36 // elements have been processed. GetNextTime returns the timestamp of the next
     37 // unprocessed element.
     38 class ProcessableEventListInterface {
     39 public:
     40  virtual ~ProcessableEventListInterface() = default;
     41  virtual void ProcessNext() = 0;
     42  virtual bool IsEmpty() const = 0;
     43  virtual int64_t GetNextTime() const = 0;
     44  virtual int GetTypeOrder() const = 0;
     45  virtual std::optional<uint16_t> GetTransportSeqNum() const = 0;
     46  virtual int GetInsertionOrder() const = 0;
     47 };
     48 
     49 // ProcessableEventList encapsulates a list of events and a function that will
     50 // be applied to each element of the list.
     51 template <typename Iterator, typename T>
     52 class ProcessableEventList : public ProcessableEventListInterface {
     53 public:
     54  ProcessableEventList(Iterator begin,
     55                       Iterator end,
     56                       std::function<void(const T&)> f,
     57                       int type_order,
     58                       std::function<std::optional<uint16_t>(const T&)>
     59                           transport_seq_num_accessor,
     60                       int insertion_order)
     61      : begin_(begin),
     62        end_(end),
     63        f_(f),
     64        type_order_(type_order),
     65        transport_seq_num_accessor_(transport_seq_num_accessor),
     66        insertion_order_(insertion_order) {}
     67 
     68  void ProcessNext() override {
     69    RTC_DCHECK(!IsEmpty());
     70    f_(*begin_);
     71    ++begin_;
     72  }
     73 
     74  bool IsEmpty() const override { return begin_ == end_; }
     75 
     76  int64_t GetNextTime() const override {
     77    RTC_DCHECK(!IsEmpty());
     78    return begin_->log_time_us();
     79  }
     80 
     81  int GetTypeOrder() const override { return type_order_; }
     82 
     83  std::optional<uint16_t> GetTransportSeqNum() const override {
     84    RTC_DCHECK(!IsEmpty());
     85    return transport_seq_num_accessor_(*begin_);
     86  }
     87 
     88  int GetInsertionOrder() const override { return insertion_order_; }
     89 
     90 private:
     91  Iterator begin_;
     92  Iterator end_;
     93  std::function<void(const T&)> f_;
     94  int type_order_;
     95  std::function<std::optional<uint16_t>(const T&)> transport_seq_num_accessor_;
     96  int insertion_order_;
     97 };
     98 
     99 }  // namespace event_processor_impl
    100 
    101 // Helper class used to "merge" two or more lists of ordered RtcEventLog events
    102 // so that they can be treated as a single ordered list. Since the individual
    103 // lists may have different types, we need to access the lists via pointers to
    104 // the common base class.
    105 //
    106 // Usage example:
    107 // ParsedRtcEventLogNew log;
    108 // auto incoming_handler = [] (LoggedRtcpPacketIncoming elem) { ... };
    109 // auto outgoing_handler = [] (LoggedRtcpPacketOutgoing elem) { ... };
    110 //
    111 // RtcEventProcessor processor;
    112 // processor.AddEvents(log.incoming_rtcp_packets(),
    113 //                     incoming_handler);
    114 // processor.AddEvents(log.outgoing_rtcp_packets(),
    115 //                     outgoing_handler);
    116 // processor.ProcessEventsInOrder();
    117 class RtcEventProcessor {
    118 public:
    119  RtcEventProcessor();
    120  ~RtcEventProcessor();
    121  // The elements of each list is processed in the index order. To process all
    122  // elements in all lists in timestamp order, each list needs to be sorted in
    123  // timestamp order prior to insertion.
    124  // N.B. `iterable` is not owned by RtcEventProcessor. The caller must ensure
    125  // that the iterable outlives RtcEventProcessor and it must not be modified
    126  // until processing has finished.
    127  template <typename Iterable>
    128  void AddEvents(
    129      const Iterable& iterable,
    130      std::function<void(const typename Iterable::value_type&)> handler) {
    131    using ValueType =
    132        typename std::remove_const<typename Iterable::value_type>::type;
    133    AddEvents(iterable, handler, TieBreaker<ValueType>::type_order,
    134              TieBreaker<ValueType>::transport_seq_num_accessor,
    135              num_insertions_);
    136  }
    137 
    138  template <typename Iterable>
    139  void AddEvents(
    140      const Iterable& iterable,
    141      std::function<void(const typename Iterable::value_type&)> handler,
    142      PacketDirection direction) {
    143    using ValueType =
    144        typename std::remove_const<typename Iterable::value_type>::type;
    145    AddEvents(iterable, handler, TieBreaker<ValueType>::type_order(direction),
    146              TieBreaker<ValueType>::transport_seq_num_accessor,
    147              num_insertions_);
    148  }
    149 
    150  template <typename Iterable>
    151  void AddEvents(
    152      const Iterable& iterable,
    153      std::function<void(const typename Iterable::value_type&)> handler,
    154      int type_order,
    155      std::function<std::optional<uint16_t>(
    156          const typename Iterable::value_type&)> transport_seq_num_accessor,
    157      int insertion_order) {
    158    if (iterable.begin() == iterable.end())
    159      return;
    160    num_insertions_++;
    161    event_lists_.push_back(
    162        std::make_unique<event_processor_impl::ProcessableEventList<
    163            typename Iterable::const_iterator, typename Iterable::value_type>>(
    164            iterable.begin(), iterable.end(), handler, type_order,
    165            transport_seq_num_accessor, insertion_order));
    166  }
    167 
    168  void ProcessEventsInOrder();
    169 
    170 private:
    171  using ListPtrType =
    172      std::unique_ptr<event_processor_impl::ProcessableEventListInterface>;
    173  // Comparison function to make `event_lists_` into a min heap.
    174  static bool Cmp(const ListPtrType& a, const ListPtrType& b);
    175 
    176  std::vector<ListPtrType> event_lists_;
    177  int num_insertions_ = 0;
    178 };
    179 
    180 }  // namespace webrtc
    181 
    182 #endif  // LOGGING_RTC_EVENT_LOG_RTC_EVENT_PROCESSOR_H_