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