blob: 3aa7e9df268172c2e84a6777963ca039ee8bccd8 [file] [log] [blame]
nissee4bcd6d2017-05-16 11:47:041/*
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 11:19:1310
Mirko Bonadei92ea95e2017-09-15 04:47:3111#ifndef CALL_RTP_DEMUXER_H_
12#define CALL_RTP_DEMUXER_H_
nissee4bcd6d2017-05-16 11:47:0413
14#include <map>
Steve Anton53c7ba62017-08-18 17:05:4715#include <set>
eladalond0244c22017-06-08 11:19:1316#include <string>
Steve Anton53c7ba62017-08-18 17:05:4717#include <utility>
eladalona52722f2017-06-26 18:23:5418#include <vector>
nissee4bcd6d2017-05-16 11:47:0419
20namespace webrtc {
21
22class RtpPacketReceived;
nissed76b7b22017-06-01 11:02:3523class RtpPacketSinkInterface;
nissee4bcd6d2017-05-16 11:47:0424
Steve Anton53c7ba62017-08-18 17:05:4725// This struct describes the criteria that will be used to match packets to a
26// specific sink.
27struct 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;
Yura Yaroshevich49a5e3e2020-05-16 11:30:5946
47 // Return string representation of demux criteria to facilitate logging
48 std::string ToString() const;
Steve Anton53c7ba62017-08-18 17:05:4749};
50
nissee4bcd6d2017-05-16 11:47:0451// This class represents the RTP demuxing, for a single RTP session (i.e., one
Steve Anton53c7ba62017-08-18 17:05:4752// SSRC space, see RFC 7656). It isn't thread aware, leaving responsibility of
nissee4bcd6d2017-05-16 11:47:0453// multithreading issues to the user of this class.
Steve Anton53c7ba62017-08-18 17:05:4754// 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.
nissee4bcd6d2017-05-16 11:47:0486class RtpDemuxer {
87 public:
Steve Anton53c7ba62017-08-18 17:05:4788 // 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
Steve Anton884adca2019-04-15 23:52:2793 // 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
nissee4bcd6d2017-05-16 11:47:0497 RtpDemuxer();
98 ~RtpDemuxer();
99
Steve Anton53c7ba62017-08-18 17:05:47100 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
eladalon5daecca2017-08-04 13:34:54116 // 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);
eladalond0244c22017-06-08 11:19:13122
eladalon5daecca2017-08-04 13:34:54123 // Registers a sink's association to an RSID. Only one sink may be associated
124 // with a given RSID. Null pointer is not allowed.
eladalond0244c22017-06-08 11:19:13125 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);
nissee4bcd6d2017-05-16 11:47:04130
Steve Anton53c7ba62017-08-18 17:05:47131 // 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.
nissee4bcd6d2017-05-16 11:47:04133 bool OnRtpPacket(const RtpPacketReceived& packet);
134
Steve Antoned09dc62018-03-29 19:59:17135 // Configure whether to look at the MID header extension when demuxing
136 // incoming RTP packets. By default this is enabled.
137 void set_use_mid(bool use_mid) { use_mid_ = use_mid; }
138
nissee4bcd6d2017-05-16 11:47:04139 private:
Steve Anton53c7ba62017-08-18 17:05:47140 // 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;
eladalona52722f2017-06-26 18:23:54143
Steve Anton53c7ba62017-08-18 17:05:47144 // 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);
eladalond0244c22017-06-08 11:19:13149
Steve Anton53c7ba62017-08-18 17:05:47150 // 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);
eladalond0244c22017-06-08 11:19:13160
Steve Anton53c7ba62017-08-18 17:05:47161 // 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
Danil Chapovalov8fddf1f2020-07-08 16:32:52191 // Adds a binding from the SSRC to the given sink.
192 void AddSsrcSinkBinding(uint32_t ssrc, RtpPacketSinkInterface* sink);
Steve Antoned09dc62018-03-29 19:59:17193
194 bool use_mid_ = true;
nissee4bcd6d2017-05-16 11:47:04195};
196
197} // namespace webrtc
198
Mirko Bonadei92ea95e2017-09-15 04:47:31199#endif // CALL_RTP_DEMUXER_H_