xref: /aosp_15_r20/external/webrtc/call/rtp_demuxer.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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