tor-browser

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

rtp_demuxer.h (10123B)


      1 /*
      2 *  Copyright (c) 2017 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 CALL_RTP_DEMUXER_H_
     12 #define CALL_RTP_DEMUXER_H_
     13 
     14 #include <cstdint>
     15 #include <map>
     16 #include <string>
     17 #include <utility>
     18 
     19 #include "absl/strings/string_view.h"
     20 #include "rtc_base/containers/flat_map.h"
     21 #include "rtc_base/containers/flat_set.h"
     22 
     23 namespace webrtc {
     24 
     25 class RtpPacketReceived;
     26 class RtpPacketSinkInterface;
     27 
     28 // This struct describes the criteria that will be used to match packets to a
     29 // specific sink.
     30 class RtpDemuxerCriteria {
     31 public:
     32  explicit RtpDemuxerCriteria(absl::string_view mid,
     33                              absl::string_view rsid = absl::string_view());
     34  RtpDemuxerCriteria();
     35  ~RtpDemuxerCriteria();
     36 
     37  bool operator==(const RtpDemuxerCriteria& other) const;
     38  bool operator!=(const RtpDemuxerCriteria& other) const;
     39 
     40  // If not the empty string, will match packets with this MID.
     41  const std::string& mid() const { return mid_; }
     42 
     43  // Return string representation of demux criteria to facilitate logging
     44  std::string ToString() const;
     45 
     46  // If not the empty string, will match packets with this as their RTP stream
     47  // ID or repaired RTP stream ID.
     48  // Note that if both MID and RSID are specified, this will only match packets
     49  // that have both specified (either through RTP header extensions, SSRC
     50  // latching or RTCP).
     51  const std::string& rsid() const { return rsid_; }
     52 
     53  // The criteria will match packets with any of these SSRCs.
     54  const flat_set<uint32_t>& ssrcs() const { return ssrcs_; }
     55 
     56  // Writable accessor for directly modifying the list of ssrcs.
     57  flat_set<uint32_t>& ssrcs() { return ssrcs_; }
     58 
     59  // The criteria will match packets with any of these payload types.
     60  const flat_set<uint8_t>& payload_types() const { return payload_types_; }
     61 
     62  // Writable accessor for directly modifying the list of payload types.
     63  flat_set<uint8_t>& payload_types() { return payload_types_; }
     64 
     65 private:
     66  // Intentionally private member variables to encourage specifying them via the
     67  // constructor and consider them to be const as much as possible.
     68  const std::string mid_;
     69  const std::string rsid_;
     70  flat_set<uint32_t> ssrcs_;
     71  flat_set<uint8_t> payload_types_;
     72 };
     73 
     74 // This class represents the RTP demuxing, for a single RTP session (i.e., one
     75 // SSRC space, see RFC 7656). It isn't thread aware, leaving responsibility of
     76 // multithreading issues to the user of this class.
     77 // The demuxing algorithm follows the sketch given in the BUNDLE draft:
     78 // https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-38#section-10.2
     79 // with modifications to support RTP stream IDs also.
     80 //
     81 // When a packet is received, the RtpDemuxer will route according to the
     82 // following rules:
     83 // 1. If the packet contains the MID header extension, and no sink has been
     84 //    added with that MID as a criteria, the packet is not routed.
     85 // 2. If the packet has the MID header extension, but no RSID or RRID extension,
     86 //    and the MID is bound to a sink, then bind its SSRC to the same sink and
     87 //    forward the packet to that sink. Note that rebinding to the same sink is
     88 //    not an error. (Later packets with that SSRC would therefore be forwarded
     89 //    to the same sink, whether they have the MID header extension or not.)
     90 // 3. If the packet has the MID header extension and either the RSID or RRID
     91 //    extension, and the MID, RSID (or RRID) pair is bound to a sink, then bind
     92 //    its SSRC to the same sink and forward the packet to that sink. Later
     93 //    packets with that SSRC will be forwarded to the same sink.
     94 // 4. If the packet has the RSID or RRID header extension, but no MID extension,
     95 //    and the RSID or RRID is bound to an RSID sink, then bind its SSRC to the
     96 //    same sink and forward the packet to that sink. Later packets with that
     97 //    SSRC will be forwarded to the same sink.
     98 // 5. If the packet's SSRC is bound to an SSRC through a previous call to
     99 //    AddSink, then forward the packet to that sink. Note that the RtpDemuxer
    100 //    will not verify the payload type even if included in the sink's criteria.
    101 //    The sink is expected to do the check in its handler.
    102 // 6. If the packet's payload type is bound to exactly one payload type sink
    103 //    through an earlier call to AddSink, then forward the packet to that sink.
    104 // 7. Otherwise, the packet is not routed.
    105 //
    106 // In summary, the routing algorithm will always try to first match MID and RSID
    107 // (including through SSRC binding), match SSRC directly as needed, and use
    108 // payload types only if all else fails.
    109 class RtpDemuxer {
    110 public:
    111  // Maximum number of unique SSRC bindings allowed. This limit is to prevent
    112  // memory overuse attacks due to a malicious peer sending many packets with
    113  // different SSRCs.
    114  static constexpr int kMaxSsrcBindings = 1000;
    115 
    116  // Returns a string that contains all the attributes of the given packet
    117  // relevant for demuxing.
    118  static std::string DescribePacket(const RtpPacketReceived& packet);
    119 
    120  explicit RtpDemuxer(bool use_mid = true);
    121  ~RtpDemuxer();
    122 
    123  RtpDemuxer(const RtpDemuxer&) = delete;
    124  void operator=(const RtpDemuxer&) = delete;
    125 
    126  // Registers a sink that will be notified when RTP packets match its given
    127  // criteria according to the algorithm described in the class description.
    128  // Returns true if the sink was successfully added.
    129  // Returns false in the following situations:
    130  // - Only MID is specified and the MID is already registered.
    131  // - Only RSID is specified and the RSID is already registered.
    132  // - Both MID and RSID is specified and the (MID, RSID) pair is already
    133  //   registered.
    134  // - Any of the criteria SSRCs are already registered.
    135  // If false is returned, no changes are made to the demuxer state.
    136  bool AddSink(const RtpDemuxerCriteria& criteria,
    137               RtpPacketSinkInterface* sink);
    138 
    139  // Registers a sink. Multiple SSRCs may be mapped to the same sink, but
    140  // each SSRC may only be mapped to one sink. The return value reports
    141  // whether the association has been recorded or rejected. Rejection may occur
    142  // if the SSRC has already been associated with a sink. The previously added
    143  // sink is *not* forgotten.
    144  bool AddSink(uint32_t ssrc, RtpPacketSinkInterface* sink);
    145 
    146  // Registers a sink's association to an RSID. Only one sink may be associated
    147  // with a given RSID. Null pointer is not allowed.
    148  void AddSink(absl::string_view rsid, RtpPacketSinkInterface* sink);
    149 
    150  // Removes a sink. Return value reports if anything was actually removed.
    151  // Null pointer is not allowed.
    152  bool RemoveSink(const RtpPacketSinkInterface* sink);
    153 
    154  // Returns the set of SSRCs associated with a sink.
    155  flat_set<uint32_t> GetSsrcsForSink(const RtpPacketSinkInterface* sink) const;
    156 
    157  // Demuxes the given packet and forwards it to the chosen sink. Returns true
    158  // if the packet was forwarded and false if the packet was dropped.
    159  bool OnRtpPacket(const RtpPacketReceived& packet);
    160 
    161 private:
    162  // Returns true if adding a sink with the given criteria would cause conflicts
    163  // with the existing criteria and should be rejected.
    164  bool CriteriaWouldConflict(const RtpDemuxerCriteria& criteria) const;
    165 
    166  // Runs the demux algorithm on the given packet and returns the sink that
    167  // should receive the packet.
    168  // Will record any SSRC<->ID associations along the way.
    169  // If the packet should be dropped, this method returns null.
    170  RtpPacketSinkInterface* ResolveSink(const RtpPacketReceived& packet);
    171 
    172  // Used by the ResolveSink algorithm.
    173  RtpPacketSinkInterface* ResolveSinkByMid(absl::string_view mid,
    174                                           uint32_t ssrc);
    175  RtpPacketSinkInterface* ResolveSinkByMidRsid(absl::string_view mid,
    176                                               absl::string_view rsid,
    177                                               uint32_t ssrc);
    178  RtpPacketSinkInterface* ResolveSinkByRsid(absl::string_view rsid,
    179                                            uint32_t ssrc);
    180  RtpPacketSinkInterface* ResolveSinkByPayloadType(uint8_t payload_type,
    181                                                   uint32_t ssrc);
    182 
    183  // Regenerate the known_mids_ set from information in the sink_by_mid_ and
    184  // sink_by_mid_and_rsid_ maps.
    185  void RefreshKnownMids();
    186 
    187  // Map each sink by its component attributes to facilitate quick lookups.
    188  // Payload Type mapping is a multimap because if two sinks register for the
    189  // same payload type, both AddSinks succeed but we must know not to demux on
    190  // that attribute since it is ambiguous.
    191  // Note: Mappings are only modified by AddSink/RemoveSink (except for
    192  // SSRC mapping which receives all MID, payload type, or RSID to SSRC bindings
    193  // discovered when demuxing packets).
    194  flat_map<std::string, RtpPacketSinkInterface*> sink_by_mid_;
    195  flat_map<uint32_t, RtpPacketSinkInterface*> sink_by_ssrc_;
    196  std::multimap<uint8_t, RtpPacketSinkInterface*> sinks_by_pt_;
    197  flat_map<std::pair<std::string, std::string>, RtpPacketSinkInterface*>
    198      sink_by_mid_and_rsid_;
    199  flat_map<std::string, RtpPacketSinkInterface*> sink_by_rsid_;
    200 
    201  // Tracks all the MIDs that have been identified in added criteria. Used to
    202  // determine if a packet should be dropped right away because the MID is
    203  // unknown.
    204  flat_set<std::string> known_mids_;
    205 
    206  // Records learned mappings of MID --> SSRC and RSID --> SSRC as packets are
    207  // received.
    208  // This is stored separately from the sink mappings because if a sink is
    209  // removed we want to still remember these associations.
    210  flat_map<uint32_t, std::string> mid_by_ssrc_;
    211  flat_map<uint32_t, std::string> rsid_by_ssrc_;
    212 
    213  // Adds a binding from the SSRC to the given sink.
    214  void AddSsrcSinkBinding(uint32_t ssrc, RtpPacketSinkInterface* sink);
    215 
    216  const bool use_mid_;
    217 };
    218 
    219 }  // namespace webrtc
    220 
    221 #endif  // CALL_RTP_DEMUXER_H_