blob: 80427b82a7f1e072b0d0e2da9d9cf0ff647b7c68 [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>
eladalond0244c22017-06-08 11:19:1315#include <string>
Steve Anton53c7ba62017-08-18 17:05:4716#include <utility>
eladalona52722f2017-06-26 18:23:5417#include <vector>
nissee4bcd6d2017-05-16 11:47:0418
Tomas Gunnarssonc3795ff2022-01-03 13:04:5119#include "absl/strings/string_view.h"
Victor Boivieac5f2e72021-07-01 19:42:0220#include "rtc_base/containers/flat_map.h"
21#include "rtc_base/containers/flat_set.h"
22
nissee4bcd6d2017-05-16 11:47:0423namespace webrtc {
24
25class RtpPacketReceived;
nissed76b7b22017-06-01 11:02:3526class RtpPacketSinkInterface;
nissee4bcd6d2017-05-16 11:47:0427
Steve Anton53c7ba62017-08-18 17:05:4728// This struct describes the criteria that will be used to match packets to a
29// specific sink.
Tomas Gunnarsson8a5ac162022-01-03 14:16:4630class RtpDemuxerCriteria {
31 public:
Tomas Gunnarssonc3795ff2022-01-03 13:04:5132 explicit RtpDemuxerCriteria(absl::string_view mid,
33 absl::string_view rsid = absl::string_view());
Steve Anton53c7ba62017-08-18 17:05:4734 RtpDemuxerCriteria();
35 ~RtpDemuxerCriteria();
36
Henrik Boström15e078c2021-04-16 07:54:1837 bool operator==(const RtpDemuxerCriteria& other) const;
38 bool operator!=(const RtpDemuxerCriteria& other) const;
39
Steve Anton53c7ba62017-08-18 17:05:4740 // If not the empty string, will match packets with this MID.
Tomas Gunnarsson8a5ac162022-01-03 14:16:4641 const std::string& mid() const { return mid_; }
42
43 // Return string representation of demux criteria to facilitate logging
44 std::string ToString() const;
Steve Anton53c7ba62017-08-18 17:05:4745
46 // If not the empty string, will match packets with this as their RTP stream
47 // ID or repaired RTP stream ID.
48 // Note that if both MID and RSID are specified, this will only match packets
49 // that have both specified (either through RTP header extensions, SSRC
50 // latching or RTCP).
Tomas Gunnarsson8a5ac162022-01-03 14:16:4651 const std::string& rsid() const { return rsid_; }
Steve Anton53c7ba62017-08-18 17:05:4752
Tomas Gunnarsson8a5ac162022-01-03 14:16:4653 // The criteria will match packets with any of these SSRCs.
54 const flat_set<uint32_t>& ssrcs() const { return ssrcs_; }
Steve Anton53c7ba62017-08-18 17:05:4755
Tomas Gunnarsson8a5ac162022-01-03 14:16:4656 // Writable accessor for directly modifying the list of ssrcs.
57 flat_set<uint32_t>& ssrcs() { return ssrcs_; }
Yura Yaroshevich49a5e3e2020-05-16 11:30:5958
Tomas Gunnarsson8a5ac162022-01-03 14:16:4659 // The criteria will match packets with any of these payload types.
60 const flat_set<uint8_t>& payload_types() const { return payload_types_; }
61
62 // Writable accessor for directly modifying the list of payload types.
63 flat_set<uint8_t>& payload_types() { return payload_types_; }
64
65 private:
66 // Intentionally private member variables to encourage specifying them via the
67 // constructor and consider them to be const as much as possible.
Tomas Gunnarsson9abd74d2022-01-04 17:21:5468 const std::string mid_;
69 const std::string rsid_;
Tomas Gunnarsson8a5ac162022-01-03 14:16:4670 flat_set<uint32_t> ssrcs_;
71 flat_set<uint8_t> payload_types_;
Steve Anton53c7ba62017-08-18 17:05:4772};
73
nissee4bcd6d2017-05-16 11:47:0474// This class represents the RTP demuxing, for a single RTP session (i.e., one
Steve Anton53c7ba62017-08-18 17:05:4775// SSRC space, see RFC 7656). It isn't thread aware, leaving responsibility of
nissee4bcd6d2017-05-16 11:47:0476// multithreading issues to the user of this class.
Steve Anton53c7ba62017-08-18 17:05:4777// The demuxing algorithm follows the sketch given in the BUNDLE draft:
78// https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-38#section-10.2
79// with modifications to support RTP stream IDs also.
80//
81// When a packet is received, the RtpDemuxer will route according to the
82// following rules:
83// 1. If the packet contains the MID header extension, and no sink has been
84// added with that MID as a criteria, the packet is not routed.
85// 2. If the packet has the MID header extension, but no RSID or RRID extension,
86// and the MID is bound to a sink, then bind its SSRC to the same sink and
87// forward the packet to that sink. Note that rebinding to the same sink is
88// not an error. (Later packets with that SSRC would therefore be forwarded
89// to the same sink, whether they have the MID header extension or not.)
90// 3. If the packet has the MID header extension and either the RSID or RRID
91// extension, and the MID, RSID (or RRID) pair is bound to a sink, then bind
92// its SSRC to the same sink and forward the packet to that sink. Later
93// packets with that SSRC will be forwarded to the same sink.
94// 4. If the packet has the RSID or RRID header extension, but no MID extension,
95// and the RSID or RRID is bound to an RSID sink, then bind its SSRC to the
96// same sink and forward the packet to that sink. Later packets with that
97// SSRC will be forwarded to the same sink.
98// 5. If the packet's SSRC is bound to an SSRC through a previous call to
99// AddSink, then forward the packet to that sink. Note that the RtpDemuxer
100// will not verify the payload type even if included in the sink's criteria.
101// The sink is expected to do the check in its handler.
102// 6. If the packet's payload type is bound to exactly one payload type sink
103// through an earlier call to AddSink, then forward the packet to that sink.
104// 7. Otherwise, the packet is not routed.
105//
106// In summary, the routing algorithm will always try to first match MID and RSID
107// (including through SSRC binding), match SSRC directly as needed, and use
108// payload types only if all else fails.
nissee4bcd6d2017-05-16 11:47:04109class RtpDemuxer {
110 public:
Steve Anton53c7ba62017-08-18 17:05:47111 // Maximum number of unique SSRC bindings allowed. This limit is to prevent
112 // memory overuse attacks due to a malicious peer sending many packets with
113 // different SSRCs.
114 static constexpr int kMaxSsrcBindings = 1000;
115
Steve Anton884adca2019-04-15 23:52:27116 // Returns a string that contains all the attributes of the given packet
117 // relevant for demuxing.
118 static std::string DescribePacket(const RtpPacketReceived& packet);
119
Tomas Gunnarssone091fd22021-01-17 15:14:52120 explicit RtpDemuxer(bool use_mid = true);
nissee4bcd6d2017-05-16 11:47:04121 ~RtpDemuxer();
122
Steve Anton53c7ba62017-08-18 17:05:47123 RtpDemuxer(const RtpDemuxer&) = delete;
124 void operator=(const RtpDemuxer&) = delete;
125
126 // Registers a sink that will be notified when RTP packets match its given
127 // criteria according to the algorithm described in the class description.
128 // Returns true if the sink was successfully added.
129 // Returns false in the following situations:
130 // - Only MID is specified and the MID is already registered.
131 // - Only RSID is specified and the RSID is already registered.
132 // - Both MID and RSID is specified and the (MID, RSID) pair is already
133 // registered.
134 // - Any of the criteria SSRCs are already registered.
135 // If false is returned, no changes are made to the demuxer state.
136 bool AddSink(const RtpDemuxerCriteria& criteria,
137 RtpPacketSinkInterface* sink);
138
eladalon5daecca2017-08-04 13:34:54139 // Registers a sink. Multiple SSRCs may be mapped to the same sink, but
140 // each SSRC may only be mapped to one sink. The return value reports
141 // whether the association has been recorded or rejected. Rejection may occur
142 // if the SSRC has already been associated with a sink. The previously added
143 // sink is *not* forgotten.
144 bool AddSink(uint32_t ssrc, RtpPacketSinkInterface* sink);
eladalond0244c22017-06-08 11:19:13145
eladalon5daecca2017-08-04 13:34:54146 // Registers a sink's association to an RSID. Only one sink may be associated
147 // with a given RSID. Null pointer is not allowed.
Ali Tofigh641a1b12022-05-17 09:48:46148 void AddSink(absl::string_view rsid, RtpPacketSinkInterface* sink);
eladalond0244c22017-06-08 11:19:13149
150 // Removes a sink. Return value reports if anything was actually removed.
151 // Null pointer is not allowed.
152 bool RemoveSink(const RtpPacketSinkInterface* sink);
nissee4bcd6d2017-05-16 11:47:04153
Philipp Hancke977b56c2023-11-08 09:20:51154 // Returns the set of SSRCs associated with a sink.
155 flat_set<uint32_t> GetSsrcsForSink(const RtpPacketSinkInterface* sink) const;
156
Steve Anton53c7ba62017-08-18 17:05:47157 // Demuxes the given packet and forwards it to the chosen sink. Returns true
158 // if the packet was forwarded and false if the packet was dropped.
nissee4bcd6d2017-05-16 11:47:04159 bool OnRtpPacket(const RtpPacketReceived& packet);
160
161 private:
Steve Anton53c7ba62017-08-18 17:05:47162 // Returns true if adding a sink with the given criteria would cause conflicts
163 // with the existing criteria and should be rejected.
164 bool CriteriaWouldConflict(const RtpDemuxerCriteria& criteria) const;
eladalona52722f2017-06-26 18:23:54165
Steve Anton53c7ba62017-08-18 17:05:47166 // Runs the demux algorithm on the given packet and returns the sink that
167 // should receive the packet.
168 // Will record any SSRC<->ID associations along the way.
169 // If the packet should be dropped, this method returns null.
170 RtpPacketSinkInterface* ResolveSink(const RtpPacketReceived& packet);
eladalond0244c22017-06-08 11:19:13171
Steve Anton53c7ba62017-08-18 17:05:47172 // Used by the ResolveSink algorithm.
Ali Tofigh641a1b12022-05-17 09:48:46173 RtpPacketSinkInterface* ResolveSinkByMid(absl::string_view mid,
Steve Anton53c7ba62017-08-18 17:05:47174 uint32_t ssrc);
Ali Tofigh641a1b12022-05-17 09:48:46175 RtpPacketSinkInterface* ResolveSinkByMidRsid(absl::string_view mid,
176 absl::string_view rsid,
Steve Anton53c7ba62017-08-18 17:05:47177 uint32_t ssrc);
Ali Tofigh641a1b12022-05-17 09:48:46178 RtpPacketSinkInterface* ResolveSinkByRsid(absl::string_view rsid,
Steve Anton53c7ba62017-08-18 17:05:47179 uint32_t ssrc);
180 RtpPacketSinkInterface* ResolveSinkByPayloadType(uint8_t payload_type,
181 uint32_t ssrc);
eladalond0244c22017-06-08 11:19:13182
Steve Anton53c7ba62017-08-18 17:05:47183 // Regenerate the known_mids_ set from information in the sink_by_mid_ and
184 // sink_by_mid_and_rsid_ maps.
185 void RefreshKnownMids();
186
187 // Map each sink by its component attributes to facilitate quick lookups.
188 // Payload Type mapping is a multimap because if two sinks register for the
189 // same payload type, both AddSinks succeed but we must know not to demux on
190 // that attribute since it is ambiguous.
191 // Note: Mappings are only modified by AddSink/RemoveSink (except for
192 // SSRC mapping which receives all MID, payload type, or RSID to SSRC bindings
193 // discovered when demuxing packets).
Victor Boivieac5f2e72021-07-01 19:42:02194 flat_map<std::string, RtpPacketSinkInterface*> sink_by_mid_;
195 flat_map<uint32_t, RtpPacketSinkInterface*> sink_by_ssrc_;
Victor Boiviefade9192021-05-25 11:34:07196 std::multimap<uint8_t, RtpPacketSinkInterface*> sinks_by_pt_;
Victor Boivieac5f2e72021-07-01 19:42:02197 flat_map<std::pair<std::string, std::string>, RtpPacketSinkInterface*>
Steve Anton53c7ba62017-08-18 17:05:47198 sink_by_mid_and_rsid_;
Victor Boivieac5f2e72021-07-01 19:42:02199 flat_map<std::string, RtpPacketSinkInterface*> sink_by_rsid_;
Steve Anton53c7ba62017-08-18 17:05:47200
201 // Tracks all the MIDs that have been identified in added criteria. Used to
202 // determine if a packet should be dropped right away because the MID is
203 // unknown.
Victor Boivieac5f2e72021-07-01 19:42:02204 flat_set<std::string> known_mids_;
Steve Anton53c7ba62017-08-18 17:05:47205
206 // Records learned mappings of MID --> SSRC and RSID --> SSRC as packets are
207 // received.
208 // This is stored separately from the sink mappings because if a sink is
209 // removed we want to still remember these associations.
Victor Boivieac5f2e72021-07-01 19:42:02210 flat_map<uint32_t, std::string> mid_by_ssrc_;
211 flat_map<uint32_t, std::string> rsid_by_ssrc_;
Steve Anton53c7ba62017-08-18 17:05:47212
Danil Chapovalov8fddf1f2020-07-08 16:32:52213 // Adds a binding from the SSRC to the given sink.
214 void AddSsrcSinkBinding(uint32_t ssrc, RtpPacketSinkInterface* sink);
Steve Antoned09dc62018-03-29 19:59:17215
Tomas Gunnarssone091fd22021-01-17 15:14:52216 const bool use_mid_;
nissee4bcd6d2017-05-16 11:47:04217};
218
219} // namespace webrtc
220
Mirko Bonadei92ea95e2017-09-15 04:47:31221#endif // CALL_RTP_DEMUXER_H_