blob: c815c47f72443c2a4f8ce9592cf9a11f44a91438 [file] [log] [blame]
nissee4bcd6d2017-05-16 04:47:04 -07001/*
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 */
eladalond0244c22017-06-08 04:19:13 -070010
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef CALL_RTP_DEMUXER_H_
12#define CALL_RTP_DEMUXER_H_
nissee4bcd6d2017-05-16 04:47:04 -070013
14#include <map>
Steve Anton53c7ba62017-08-18 10:05:47 -070015#include <set>
eladalond0244c22017-06-08 04:19:13 -070016#include <string>
Steve Anton53c7ba62017-08-18 10:05:47 -070017#include <utility>
eladalona52722f2017-06-26 11:23:54 -070018#include <vector>
nissee4bcd6d2017-05-16 04:47:04 -070019
20namespace webrtc {
21
22class RtpPacketReceived;
nissed76b7b22017-06-01 04:02:35 -070023class RtpPacketSinkInterface;
Steve Antonb3329172017-08-17 15:23:51 -070024class SsrcBindingObserver;
nissee4bcd6d2017-05-16 04:47:04 -070025
Steve Anton53c7ba62017-08-18 10:05:47 -070026// This struct describes the criteria that will be used to match packets to a
27// specific sink.
28struct RtpDemuxerCriteria {
29 RtpDemuxerCriteria();
30 ~RtpDemuxerCriteria();
31
32 // If not the empty string, will match packets with this MID.
33 std::string mid;
34
35 // If not the empty string, will match packets with this as their RTP stream
36 // ID or repaired RTP stream ID.
37 // Note that if both MID and RSID are specified, this will only match packets
38 // that have both specified (either through RTP header extensions, SSRC
39 // latching or RTCP).
40 std::string rsid;
41
42 // Will match packets with any of these SSRCs.
43 std::set<uint32_t> ssrcs;
44
45 // Will match packets with any of these payload types.
46 std::set<uint8_t> payload_types;
47};
48
nissee4bcd6d2017-05-16 04:47:04 -070049// This class represents the RTP demuxing, for a single RTP session (i.e., one
Steve Anton53c7ba62017-08-18 10:05:47 -070050// SSRC space, see RFC 7656). It isn't thread aware, leaving responsibility of
nissee4bcd6d2017-05-16 04:47:04 -070051// multithreading issues to the user of this class.
Steve Anton53c7ba62017-08-18 10:05:47 -070052// The demuxing algorithm follows the sketch given in the BUNDLE draft:
53// https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-38#section-10.2
54// with modifications to support RTP stream IDs also.
55//
56// When a packet is received, the RtpDemuxer will route according to the
57// following rules:
58// 1. If the packet contains the MID header extension, and no sink has been
59// added with that MID as a criteria, the packet is not routed.
60// 2. If the packet has the MID header extension, but no RSID or RRID extension,
61// and the MID is bound to a sink, then bind its SSRC to the same sink and
62// forward the packet to that sink. Note that rebinding to the same sink is
63// not an error. (Later packets with that SSRC would therefore be forwarded
64// to the same sink, whether they have the MID header extension or not.)
65// 3. If the packet has the MID header extension and either the RSID or RRID
66// extension, and the MID, RSID (or RRID) pair is bound to a sink, then bind
67// its SSRC to the same sink and forward the packet to that sink. Later
68// packets with that SSRC will be forwarded to the same sink.
69// 4. If the packet has the RSID or RRID header extension, but no MID extension,
70// and the RSID or RRID is bound to an RSID sink, then bind its SSRC to the
71// same sink and forward the packet to that sink. Later packets with that
72// SSRC will be forwarded to the same sink.
73// 5. If the packet's SSRC is bound to an SSRC through a previous call to
74// AddSink, then forward the packet to that sink. Note that the RtpDemuxer
75// will not verify the payload type even if included in the sink's criteria.
76// The sink is expected to do the check in its handler.
77// 6. If the packet's payload type is bound to exactly one payload type sink
78// through an earlier call to AddSink, then forward the packet to that sink.
79// 7. Otherwise, the packet is not routed.
80//
81// In summary, the routing algorithm will always try to first match MID and RSID
82// (including through SSRC binding), match SSRC directly as needed, and use
83// payload types only if all else fails.
nissee4bcd6d2017-05-16 04:47:04 -070084class RtpDemuxer {
85 public:
Steve Anton53c7ba62017-08-18 10:05:47 -070086 // Maximum number of unique SSRC bindings allowed. This limit is to prevent
87 // memory overuse attacks due to a malicious peer sending many packets with
88 // different SSRCs.
89 static constexpr int kMaxSsrcBindings = 1000;
90
Steve Anton884adca2019-04-15 16:52:27 -070091 // Returns a string that contains all the attributes of the given packet
92 // relevant for demuxing.
93 static std::string DescribePacket(const RtpPacketReceived& packet);
94
nissee4bcd6d2017-05-16 04:47:04 -070095 RtpDemuxer();
96 ~RtpDemuxer();
97
Steve Anton53c7ba62017-08-18 10:05:47 -070098 RtpDemuxer(const RtpDemuxer&) = delete;
99 void operator=(const RtpDemuxer&) = delete;
100
101 // Registers a sink that will be notified when RTP packets match its given
102 // criteria according to the algorithm described in the class description.
103 // Returns true if the sink was successfully added.
104 // Returns false in the following situations:
105 // - Only MID is specified and the MID is already registered.
106 // - Only RSID is specified and the RSID is already registered.
107 // - Both MID and RSID is specified and the (MID, RSID) pair is already
108 // registered.
109 // - Any of the criteria SSRCs are already registered.
110 // If false is returned, no changes are made to the demuxer state.
111 bool AddSink(const RtpDemuxerCriteria& criteria,
112 RtpPacketSinkInterface* sink);
113
eladalon5daecca2017-08-04 06:34:54 -0700114 // Registers a sink. Multiple SSRCs may be mapped to the same sink, but
115 // each SSRC may only be mapped to one sink. The return value reports
116 // whether the association has been recorded or rejected. Rejection may occur
117 // if the SSRC has already been associated with a sink. The previously added
118 // sink is *not* forgotten.
119 bool AddSink(uint32_t ssrc, RtpPacketSinkInterface* sink);
eladalond0244c22017-06-08 04:19:13 -0700120
eladalon5daecca2017-08-04 06:34:54 -0700121 // Registers a sink's association to an RSID. Only one sink may be associated
122 // with a given RSID. Null pointer is not allowed.
eladalond0244c22017-06-08 04:19:13 -0700123 void AddSink(const std::string& rsid, RtpPacketSinkInterface* sink);
124
125 // Removes a sink. Return value reports if anything was actually removed.
126 // Null pointer is not allowed.
127 bool RemoveSink(const RtpPacketSinkInterface* sink);
nissee4bcd6d2017-05-16 04:47:04 -0700128
Steve Anton53c7ba62017-08-18 10:05:47 -0700129 // Demuxes the given packet and forwards it to the chosen sink. Returns true
130 // if the packet was forwarded and false if the packet was dropped.
nissee4bcd6d2017-05-16 04:47:04 -0700131 bool OnRtpPacket(const RtpPacketReceived& packet);
132
Steve Anton53c7ba62017-08-18 10:05:47 -0700133 // The Observer will be notified when an attribute (e.g., RSID, MID, etc.) is
134 // bound to an SSRC.
Steve Antonb3329172017-08-17 15:23:51 -0700135 void RegisterSsrcBindingObserver(SsrcBindingObserver* observer);
136 // Deprecated: Use the above method.
137 void RegisterRsidResolutionObserver(SsrcBindingObserver* observer);
eladalona52722f2017-06-26 11:23:54 -0700138
Steve Antonb3329172017-08-17 15:23:51 -0700139 // Undo a previous RegisterSsrcBindingObserver().
140 void DeregisterSsrcBindingObserver(const SsrcBindingObserver* observer);
141 // Deprecated: Use the above method.
142 void DeregisterRsidResolutionObserver(const SsrcBindingObserver* observer);
eladalona52722f2017-06-26 11:23:54 -0700143
Steve Antoned09dc62018-03-29 12:59:17 -0700144 // Configure whether to look at the MID header extension when demuxing
145 // incoming RTP packets. By default this is enabled.
146 void set_use_mid(bool use_mid) { use_mid_ = use_mid; }
147
nissee4bcd6d2017-05-16 04:47:04 -0700148 private:
Steve Anton53c7ba62017-08-18 10:05:47 -0700149 // Returns true if adding a sink with the given criteria would cause conflicts
150 // with the existing criteria and should be rejected.
151 bool CriteriaWouldConflict(const RtpDemuxerCriteria& criteria) const;
eladalona52722f2017-06-26 11:23:54 -0700152
Steve Anton53c7ba62017-08-18 10:05:47 -0700153 // Runs the demux algorithm on the given packet and returns the sink that
154 // should receive the packet.
155 // Will record any SSRC<->ID associations along the way.
156 // If the packet should be dropped, this method returns null.
157 RtpPacketSinkInterface* ResolveSink(const RtpPacketReceived& packet);
eladalond0244c22017-06-08 04:19:13 -0700158
Steve Anton53c7ba62017-08-18 10:05:47 -0700159 // Used by the ResolveSink algorithm.
160 RtpPacketSinkInterface* ResolveSinkByMid(const std::string& mid,
161 uint32_t ssrc);
162 RtpPacketSinkInterface* ResolveSinkByMidRsid(const std::string& mid,
163 const std::string& rsid,
164 uint32_t ssrc);
165 RtpPacketSinkInterface* ResolveSinkByRsid(const std::string& rsid,
166 uint32_t ssrc);
167 RtpPacketSinkInterface* ResolveSinkByPayloadType(uint8_t payload_type,
168 uint32_t ssrc);
eladalond0244c22017-06-08 04:19:13 -0700169
Steve Anton53c7ba62017-08-18 10:05:47 -0700170 // Regenerate the known_mids_ set from information in the sink_by_mid_ and
171 // sink_by_mid_and_rsid_ maps.
172 void RefreshKnownMids();
173
174 // Map each sink by its component attributes to facilitate quick lookups.
175 // Payload Type mapping is a multimap because if two sinks register for the
176 // same payload type, both AddSinks succeed but we must know not to demux on
177 // that attribute since it is ambiguous.
178 // Note: Mappings are only modified by AddSink/RemoveSink (except for
179 // SSRC mapping which receives all MID, payload type, or RSID to SSRC bindings
180 // discovered when demuxing packets).
181 std::map<std::string, RtpPacketSinkInterface*> sink_by_mid_;
182 std::map<uint32_t, RtpPacketSinkInterface*> sink_by_ssrc_;
183 std::multimap<uint8_t, RtpPacketSinkInterface*> sinks_by_pt_;
184 std::map<std::pair<std::string, std::string>, RtpPacketSinkInterface*>
185 sink_by_mid_and_rsid_;
186 std::map<std::string, RtpPacketSinkInterface*> sink_by_rsid_;
187
188 // Tracks all the MIDs that have been identified in added criteria. Used to
189 // determine if a packet should be dropped right away because the MID is
190 // unknown.
191 std::set<std::string> known_mids_;
192
193 // Records learned mappings of MID --> SSRC and RSID --> SSRC as packets are
194 // received.
195 // This is stored separately from the sink mappings because if a sink is
196 // removed we want to still remember these associations.
197 std::map<uint32_t, std::string> mid_by_ssrc_;
198 std::map<uint32_t, std::string> rsid_by_ssrc_;
199
200 // Adds a binding from the SSRC to the given sink. Returns true if there was
201 // not already a sink bound to the SSRC or if the sink replaced a different
202 // sink. Returns false if the binding was unchanged.
203 bool AddSsrcSinkBinding(uint32_t ssrc, RtpPacketSinkInterface* sink);
eladalond0244c22017-06-08 04:19:13 -0700204
eladalona52722f2017-06-26 11:23:54 -0700205 // Observers which will be notified when an RSID association to an SSRC is
206 // resolved by this object.
Steve Antonb3329172017-08-17 15:23:51 -0700207 std::vector<SsrcBindingObserver*> ssrc_binding_observers_;
Steve Antoned09dc62018-03-29 12:59:17 -0700208
209 bool use_mid_ = true;
nissee4bcd6d2017-05-16 04:47:04 -0700210};
211
212} // namespace webrtc
213
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200214#endif // CALL_RTP_DEMUXER_H_