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